From 0c58f09e59fcd2b9d5262ebca7f9c0214412e2d9 Mon Sep 17 00:00:00 2001 From: Matt Irvine Date: Tue, 5 Jun 2018 11:24:51 -0700 Subject: [PATCH] Merge VS Code 1.23.1 (#1520) --- .gitattributes | 9 + .gitignore | 1 + .travis.yml | 2 - .vscode/extensions.json | 4 +- LICENSE.txt | 10 +- OSSREADME.json | 384 + appveyor.yml | 1 - build/builtInExtensions.json | 6 +- build/gulpfile.editor.js | 111 +- build/gulpfile.extensions.js | 8 + build/gulpfile.hygiene.js | 30 +- build/gulpfile.vscode.js | 86 +- build/gulpfile.vscode.linux.js | 30 - build/lib/compilation.js | 3 +- build/lib/compilation.ts | 1 + build/lib/i18n.js | 8 +- build/lib/i18n.resources.json | 16 + build/lib/i18n.ts | 5 +- build/lib/nls.js | 3 + build/lib/reporter.js | 18 +- build/lib/reporter.ts | 30 +- build/lib/standalone.js | 265 + build/lib/standalone.ts | 305 + build/lib/test/util.test.js | 56 + build/lib/test/util.test.ts | 79 + build/lib/tslint/translationRemindRule.js | 2 +- build/lib/tslint/translationRemindRule.ts | 2 +- build/lib/util.js | 66 + build/lib/util.ts | 73 +- build/monaco/LICENSE | 2 +- build/monaco/ThirdPartyNotices.txt | 4 +- build/monaco/api.js | 15 +- build/monaco/api.ts | 56 +- build/monaco/monaco.d.ts.recipe | 20 +- build/monaco/package.json | 6 +- build/npm/postinstall.js | 24 +- build/package.json | 7 +- build/tfs/common/symbols.ts | 219 + build/tfs/continuous-build.yml | 100 + build/tfs/darwin/build.yml | 51 + build/tfs/linux/build.yml | 103 + build/tfs/linux/release2.sh | 67 + build/tfs/product-build.yml | 413 ++ build/tfs/win32/build.yml | 212 + build/tsconfig.json | 1 - build/win32/OSSREADME.json | 814 +-- build/win32/inno_updater.exe | Bin 394240 -> 371200 bytes build/yarn.lock | 145 +- .../bat/syntaxes/batchfile.tmLanguage.json | 111 +- .../bat/test/colorize-results/test_bat.json | 21 +- extensions/configuration-editing/package.json | 4 - .../configuration-editing/src/extension.ts | 7 +- extensions/docker/OSSREADME.json | 2 +- extensions/extension-editing/package.json | 4 - extensions/git/package.json | 30 +- extensions/git/package.nls.json | 1 + extensions/git/src/api.ts | 58 +- extensions/git/src/commands.ts | 91 +- extensions/git/src/encoding.ts | 81 + extensions/git/src/git.ts | 68 +- extensions/git/src/main.ts | 4 +- extensions/git/src/model.ts | 14 +- extensions/git/src/protocolHandler.ts | 39 + extensions/git/src/repository.ts | 92 +- extensions/git/src/typings/jschardet.d.ts | 11 + extensions/git/src/util.ts | 10 + extensions/git/yarn.lock | 10 +- .../.vscode/launch.json | 0 .../.vscode/tasks.json | 0 .../json-language-features/.vscodeignore | 7 + .../client/src/jsonMain.ts | 79 +- .../client/src/typings/ref.d.ts | 0 .../client/src/utils/hash.ts | 0 .../client/tsconfig.json | 0 .../icons/json.png | Bin .../json-language-features/package.json | 111 + .../json-language-features/package.nls.json | 13 + .../json-language-features/server/.npmignore | 7 + .../server/.vscode/launch.json | 6 +- .../server/.vscode/tasks.json | 20 + .../json-language-features/server/README.md | 173 + .../server/bin/vscode-json-languageserver | 6 +- .../server/package.json | 38 + .../server/src/jsonServerMain.ts | 177 +- .../server/src/languageModelCache.ts | 0 .../server/src/utils/runner.ts | 69 + .../server/src/utils/strings.ts | 0 .../server/test/mocha.opts | 3 + .../server/tsconfig.json | 0 .../server/yarn.lock | 79 +- .../yarn.lock | 49 +- extensions/json/.vscodeignore | 7 +- extensions/json/OSSREADME.json | 2 +- .../src/protocol/foldingProvider.proposed.ts | 89 - extensions/json/language-configuration.json | 1 + extensions/json/package.json | 102 +- extensions/json/package.nls.json | 14 +- extensions/json/server/.vscode/tasks.json | 9 - extensions/json/server/package.json | 29 - .../src/protocol/foldingProvider.proposed.ts | 89 - extensions/json/server/src/utils/errors.ts | 33 - extensions/markdown-basics/package.json | 3 - .../syntaxes/markdown.tmLanguage.json | 103 +- .../test/colorize-results/test-33886_md.json | 18 +- .../test/colorize-results/test_md.json | 108 +- extensions/markdown/.vscodeignore | 3 - extensions/markdown/OSSREADME.json | 38 - extensions/markdown/icon.png | Bin 1218 -> 0 bytes extensions/markdown/media/Preview.svg | 1 - .../markdown/media/PreviewOnRightPane_16x.svg | 19 - .../media/PreviewOnRightPane_16x_dark.svg | 19 - extensions/markdown/media/Preview_inverse.svg | 1 - extensions/markdown/media/ViewSource.svg | 3 - extensions/markdown/media/csp.js | 49 - extensions/markdown/media/loading.js | 40 - extensions/markdown/media/main.js | 344 - extensions/markdown/media/markdown.css | 266 - extensions/markdown/media/tomorrow.css | 73 - extensions/markdown/package.json | 288 - extensions/markdown/package.nls.json | 25 - .../markdown/schemas/package.schema.json | 32 - extensions/markdown/src/commandManager.ts | 36 - extensions/markdown/src/commands/index.ts | 13 - .../src/commands/moveCursorToPosition.ts | 22 - .../src/commands/onPreviewStyleLoadError.ts | 18 - .../markdown/src/commands/openDocumentLink.ts | 74 - .../markdown/src/commands/refreshPreview.ts | 19 - .../markdown/src/commands/showPreview.ts | 123 - .../commands/showPreviewSecuritySelector.ts | 30 - .../markdown/src/commands/showSource.ts | 30 - .../markdown/src/commands/toggleLock.ts | 20 - extensions/markdown/src/extension.ts | 59 - .../src/features/documentLinkProvider.ts | 158 - .../src/features/documentSymbolProvider.ts | 23 - extensions/markdown/src/features/preview.ts | 299 - .../markdown/src/features/previewConfig.ts | 104 - .../src/features/previewContentProvider.ts | 187 - .../markdown/src/features/previewManager.ts | 141 - extensions/markdown/src/logger.ts | 76 - extensions/markdown/src/markdownEngine.ts | 171 - extensions/markdown/src/markdownExtensions.ts | 81 - extensions/markdown/src/security.ts | 154 - .../markdown/src/tableOfContentsProvider.ts | 95 - extensions/markdown/src/telemetryReporter.ts | 60 - extensions/markdown/src/test/index.ts | 28 - .../src/test/tableOfContentsProvider.test.ts | 131 - .../typings/markdown-it-named-headers.d.ts | 5 - extensions/markdown/src/typings/ref.d.ts | 8 - extensions/markdown/src/util/file.ts | 10 - .../markdown/src/util/topmostLineMonitor.ts | 75 - extensions/markdown/tsconfig.json | 22 - extensions/markdown/yarn.lock | 1798 ----- extensions/package.json | 4 +- .../powershell/language-configuration.json | 1 - extensions/powershell/package.json | 3 +- extensions/python/language-configuration.json | 4 +- extensions/r/syntaxes/r.tmLanguage.json | 8 +- extensions/shellscript/.vscodeignore | 1 - extensions/shellscript/OSSREADME.json | 9 - .../shellscript/language-configuration.json | 26 - extensions/shellscript/package.json | 27 - extensions/shellscript/package.nls.json | 4 - .../syntaxes/Shell-Unix-Bash.tmLanguage.json | 1283 ---- .../test/colorize-fixtures/test.sh | 30 - .../test/colorize-results/test_sh.json | 1960 ----- .../theme-abyss/themes/abyss-color-theme.json | 7 +- .../theme-carbon/themes/dark_carbon.json | 3 +- .../theme-carbon/themes/light_carbon.json | 1 + .../theme-defaults/themes/dark_defaults.json | 15 + .../theme-defaults/themes/dark_plus.json | 163 + extensions/theme-defaults/themes/dark_vs.json | 356 + .../themes/hc_black_defaults.json | 1 + .../theme-defaults/themes/light_defaults.json | 17 + .../theme-defaults/themes/light_plus.json | 164 + .../theme-defaults/themes/light_vs.json | 375 + .../themes/kimbie-dark-color-theme.json | 3 +- .../themes/dimmed-monokai-color-theme.json | 4 +- .../themes/monokai-color-theme.json | 5 +- .../themes/quietlight-color-theme.json | 3 +- .../theme-red/themes/Red-color-theme.json | 3 +- ...partynotices.txt => ThirdPartyNotices.txt} | 0 .../themes/solarized-dark-color-theme.json | 9 +- .../themes/solarized-light-color-theme.json | 9 +- .../themes/tomorrow-night-blue-theme.json | 2 +- extensions/yaml/language-configuration.json | 6 +- extensions/yaml/package.json | 4 +- extensions/yarn.lock | 6 +- gulpfile.js | 6 +- .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/chs/extensions/css/package.i18n.json | 74 +- i18n/chs/extensions/emmet/package.i18n.json | 6 +- .../chs/extensions/git/out/commands.i18n.json | 6 +- i18n/chs/extensions/git/out/main.i18n.json | 4 +- i18n/chs/extensions/git/package.i18n.json | 7 +- .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/chs/extensions/html/package.i18n.json | 27 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/chs/extensions/json/package.i18n.json | 14 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/chs/extensions/npm/out/npmView.i18n.json | 11 + i18n/chs/extensions/npm/out/tasks.i18n.json | 10 + i18n/chs/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/chs/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/chs/src/vs/base/node/processes.i18n.json | 2 +- i18n/chs/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 17 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 8 +- .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 22 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../editor/contrib/find/findWidget.i18n.json | 2 +- .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 12 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 5 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 6 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 2 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 1 + .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 15 +- .../electron-browser/accessibility.i18n.json | 6 +- .../inspectKeybindings.i18n.json | 2 +- .../electron-browser/toggleWordWrap.i18n.json | 4 +- .../debug/browser/breakpointsView.i18n.json | 6 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../debug/browser/linkDetector.i18n.json | 4 +- .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 5 +- .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 4 +- .../extensionsUtils.i18n.json | 6 +- .../extensionsViewlet.i18n.json | 4 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../fileActions.contribution.i18n.json | 2 +- .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 6 +- .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 6 +- .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../startupProfiler.i18n.json | 2 +- .../browser/keybindingsEditor.i18n.json | 29 +- .../keybindingsEditorContribution.i18n.json | 2 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../preferences.contribution.i18n.json | 2 +- .../browser/gotoLineHandler.i18n.json | 4 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../parts/search/browser/searchView.i18n.json | 4 +- .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 11 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 8 +- .../terminalInstance.i18n.json | 3 +- .../electron-browser/terminalPanel.i18n.json | 4 +- .../terminalService.i18n.json | 2 +- .../themes.contribution.i18n.json | 2 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../electron-browser/welcomePage.i18n.json | 4 +- .../menusExtensionPoint.i18n.json | 8 +- .../configurationExtensionPoint.i18n.json | 5 +- .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 21 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 17 +- .../remoteFileService.i18n.json | 5 +- .../services/files/node/fileService.i18n.json | 2 +- .../common/keybindingEditing.i18n.json | 8 +- .../keybindingService.i18n.json | 10 +- .../common/workbenchModeService.i18n.json | 2 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 3 +- .../electron-browser/TMSyntax.i18n.json | 5 +- .../colorThemeStore.i18n.json | 2 +- .../fileIconThemeStore.i18n.json | 2 +- .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/cht/extensions/css/package.i18n.json | 74 +- i18n/cht/extensions/emmet/package.i18n.json | 4 +- .../cht/extensions/git/out/commands.i18n.json | 6 +- i18n/cht/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/cht/extensions/html/package.i18n.json | 29 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/cht/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/cht/extensions/npm/out/npmView.i18n.json | 11 + i18n/cht/extensions/npm/out/tasks.i18n.json | 10 + i18n/cht/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/cht/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/cht/src/vs/base/node/processes.i18n.json | 2 +- i18n/cht/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 4 +- .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 8 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 2 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 1 + .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 6 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../emmet.contribution.i18n.json | 4 +- .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 4 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 6 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 13 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 8 +- .../terminalInstance.i18n.json | 3 +- .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../services/files/node/fileService.i18n.json | 1 - .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/deu/extensions/css/package.i18n.json | 76 +- i18n/deu/extensions/emmet/package.i18n.json | 8 +- .../deu/extensions/git/out/commands.i18n.json | 6 +- i18n/deu/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/deu/extensions/html/package.i18n.json | 29 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/deu/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/deu/extensions/npm/out/npmView.i18n.json | 11 + i18n/deu/extensions/npm/out/tasks.i18n.json | 10 + i18n/deu/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/deu/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/deu/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 4 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../electron-main/windowsService.i18n.json | 2 +- .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 11 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 5 +- .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 13 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 12 +- .../terminalInstance.i18n.json | 5 +- .../electron-browser/terminalPanel.i18n.json | 1 + ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/esn/extensions/css/package.i18n.json | 74 +- i18n/esn/extensions/emmet/package.i18n.json | 6 +- .../esn/extensions/git/out/commands.i18n.json | 6 +- i18n/esn/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/esn/extensions/html/package.i18n.json | 27 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/esn/extensions/json/package.i18n.json | 14 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/esn/extensions/npm/out/npmView.i18n.json | 11 + i18n/esn/extensions/npm/out/tasks.i18n.json | 10 + i18n/esn/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/esn/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/esn/src/vs/base/node/processes.i18n.json | 2 +- i18n/esn/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 10 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 11 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 13 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 10 +- .../terminalInstance.i18n.json | 5 +- .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 11 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/fra/extensions/css/package.i18n.json | 74 +- i18n/fra/extensions/emmet/package.i18n.json | 6 +- .../fra/extensions/git/out/commands.i18n.json | 6 +- i18n/fra/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/fra/extensions/html/package.i18n.json | 27 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/fra/extensions/json/package.i18n.json | 14 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/fra/extensions/npm/out/npmView.i18n.json | 11 + i18n/fra/extensions/npm/out/tasks.i18n.json | 10 + i18n/fra/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/fra/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/fra/src/vs/base/node/processes.i18n.json | 2 +- i18n/fra/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 2 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 1 + .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 6 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 6 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 11 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 8 +- .../terminalInstance.i18n.json | 3 +- .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 21 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../services/files/node/fileService.i18n.json | 1 - .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/hun/extensions/css/package.i18n.json | 74 +- i18n/hun/extensions/emmet/package.i18n.json | 4 +- .../hun/extensions/git/out/commands.i18n.json | 6 +- i18n/hun/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/hun/extensions/html/package.i18n.json | 27 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/hun/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/hun/extensions/npm/out/npmView.i18n.json | 11 + i18n/hun/extensions/npm/out/tasks.i18n.json | 10 + i18n/hun/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/hun/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + .../findinput/findInputCheckboxes.i18n.json | 2 +- .../src/vs/base/common/errorMessage.i18n.json | 2 +- .../base/common/jsonErrorMessages.i18n.json | 6 +- i18n/hun/src/vs/base/node/processes.i18n.json | 2 +- i18n/hun/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 26 +- .../editor/common/controller/cursor.i18n.json | 2 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 4 +- .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../abstractKeybindingService.i18n.json | 2 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 4 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../electron-main/windowsService.i18n.json | 2 +- .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 11 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 2 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 1 + .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 6 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 4 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 4 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 6 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 24 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../browser/gotoLineHandler.i18n.json | 4 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 13 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 11 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminal.contribution.i18n.json | 2 +- .../terminalActions.i18n.json | 8 +- .../terminalInstance.i18n.json | 3 +- .../terminalLinkHandler.i18n.json | 2 +- .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 11 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 17 +- .../remoteFileService.i18n.json | 5 +- .../services/files/node/fileService.i18n.json | 2 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 3 +- .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/ita/extensions/css/package.i18n.json | 76 +- i18n/ita/extensions/emmet/package.i18n.json | 6 +- .../ita/extensions/git/out/commands.i18n.json | 6 +- i18n/ita/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/ita/extensions/html/package.i18n.json | 29 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/ita/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/ita/extensions/npm/out/npmView.i18n.json | 11 + i18n/ita/extensions/npm/out/tasks.i18n.json | 10 + i18n/ita/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/ita/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/ita/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 8 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 6 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 6 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 13 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 10 +- .../terminalInstance.i18n.json | 5 +- .../electron-browser/terminalPanel.i18n.json | 1 + ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/jpn/extensions/css/package.i18n.json | 74 +- i18n/jpn/extensions/emmet/package.i18n.json | 6 +- .../jpn/extensions/git/out/commands.i18n.json | 6 +- i18n/jpn/extensions/git/package.i18n.json | 3 +- .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/jpn/extensions/html/package.i18n.json | 27 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/jpn/extensions/json/package.i18n.json | 14 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/jpn/extensions/npm/out/npmView.i18n.json | 11 + i18n/jpn/extensions/npm/out/tasks.i18n.json | 10 + i18n/jpn/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/jpn/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/jpn/src/vs/base/node/processes.i18n.json | 2 +- i18n/jpn/src/vs/base/node/zip.i18n.json | 1 + .../browser/quickOpenModel.i18n.json | 2 +- .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 4 +- .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 4 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 4 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 2 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 1 + .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 6 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 4 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 25 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 6 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../snippetsService.i18n.json | 2 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 11 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 10 +- .../terminalInstance.i18n.json | 3 +- .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 21 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 17 +- .../remoteFileService.i18n.json | 5 +- .../services/files/node/fileService.i18n.json | 2 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/kor/extensions/css/package.i18n.json | 76 +- i18n/kor/extensions/emmet/package.i18n.json | 8 +- .../kor/extensions/git/out/commands.i18n.json | 6 +- i18n/kor/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/kor/extensions/html/package.i18n.json | 29 +- i18n/kor/extensions/jake/package.i18n.json | 3 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/kor/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/kor/extensions/npm/out/npmView.i18n.json | 11 + i18n/kor/extensions/npm/out/tasks.i18n.json | 10 + i18n/kor/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/kor/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/kor/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 10 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 4 +- .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 12 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 4 +- .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 14 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 10 +- .../terminalInstance.i18n.json | 5 +- .../electron-browser/terminalPanel.i18n.json | 1 + ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + i18n/ptb/extensions/clojure/package.i18n.json | 5 +- .../extensions/coffeescript/package.i18n.json | 5 +- .../out/settingsDocumentHelper.i18n.json | 2 +- .../configuration-editing/package.i18n.json | 5 +- i18n/ptb/extensions/cpp/package.i18n.json | 5 +- .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/ptb/extensions/css/package.i18n.json | 74 +- i18n/ptb/extensions/emmet/package.i18n.json | 6 +- .../extension-editing/package.i18n.json | 5 +- i18n/ptb/extensions/fsharp/package.i18n.json | 5 +- .../ptb/extensions/git/out/commands.i18n.json | 5 +- i18n/ptb/extensions/git/package.i18n.json | 1 + i18n/ptb/extensions/go/package.i18n.json | 5 +- i18n/ptb/extensions/groovy/package.i18n.json | 5 +- .../extensions/handlebars/package.i18n.json | 5 +- i18n/ptb/extensions/hlsl/package.i18n.json | 5 +- .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/ptb/extensions/html/package.i18n.json | 27 +- i18n/ptb/extensions/ini/package.i18n.json | 5 +- i18n/ptb/extensions/java/package.i18n.json | 5 +- .../extensions/javascript/package.i18n.json | 5 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/ptb/extensions/json/package.i18n.json | 14 +- i18n/ptb/extensions/less/package.i18n.json | 5 +- i18n/ptb/extensions/log/package.i18n.json | 5 +- i18n/ptb/extensions/lua/package.i18n.json | 5 +- i18n/ptb/extensions/make/package.i18n.json | 5 +- .../markdown-basics/package.i18n.json | 6 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- .../merge-conflict/package.i18n.json | 3 +- i18n/ptb/extensions/npm/out/npmView.i18n.json | 9 + i18n/ptb/extensions/npm/out/tasks.i18n.json | 9 + i18n/ptb/extensions/npm/package.i18n.json | 8 +- .../extensions/objective-c/package.i18n.json | 5 +- i18n/ptb/extensions/perl/package.i18n.json | 5 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/ptb/extensions/php/package.i18n.json | 12 +- .../extensions/powershell/package.i18n.json | 5 +- i18n/ptb/extensions/pug/package.i18n.json | 5 +- i18n/ptb/extensions/python/package.i18n.json | 5 +- i18n/ptb/extensions/r/package.i18n.json | 5 +- i18n/ptb/extensions/razor/package.i18n.json | 5 +- i18n/ptb/extensions/ruby/package.i18n.json | 5 +- i18n/ptb/extensions/rust/package.i18n.json | 5 +- i18n/ptb/extensions/scss/package.i18n.json | 5 +- .../extensions/shaderlab/package.i18n.json | 5 +- .../extensions/shellscript/package.i18n.json | 5 +- i18n/ptb/extensions/sql/package.i18n.json | 5 +- i18n/ptb/extensions/swift/package.i18n.json | 5 +- .../typescript-basics/package.i18n.json | 3 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/ptb/extensions/vb/package.i18n.json | 5 +- i18n/ptb/extensions/xml/package.i18n.json | 5 +- i18n/ptb/extensions/yaml/package.i18n.json | 5 +- i18n/ptb/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 5 +- .../issue/issueReporterPage.i18n.json | 9 +- .../processExplorerMain.i18n.json | 15 + .../code/electron-main/logUploader.i18n.json | 1 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../vs/code/electron-main/windows.i18n.json | 2 +- .../browser/widget/diffReview.i18n.json | 3 +- .../editor/common/commonCodeEditor.i18n.json | 9 + .../config/commonEditorConfig.i18n.json | 10 +- .../common/view/editorColorRegistry.i18n.json | 5 +- .../codeAction/codeActionCommands.i18n.json | 11 + .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../message/messageController.i18n.json | 9 + .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../platform/environment/node/argv.i18n.json | 5 +- .../node/extensionManagementService.i18n.json | 8 +- .../node/extensionValidator.i18n.json | 1 - .../node/integrityServiceImpl.i18n.json | 4 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 8 +- .../inactiveExtensionUrlHandler.i18n.json | 9 + .../viewsContainersExtensionPoint.i18n.json | 17 + .../api/browser/viewsExtensionPoint.i18n.json | 3 - .../mainThreadMessageService.i18n.json | 1 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 3 +- .../api/node/extHostProgress.i18n.json | 10 + .../editor/editor.contribution.i18n.json | 2 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 1 - .../parts/editor/resourceViewer.i18n.json | 2 - .../parts/editor/titleControl.i18n.json | 1 - .../notificationsActions.i18n.json | 4 +- .../notificationsCenter.i18n.json | 2 + .../notificationsStatus.i18n.json | 6 +- .../parts/quickinput/quickInput.i18n.json | 12 + .../parts/quickinput/quickInputBox.i18n.json | 9 + .../vs/workbench/browser/viewlet.i18n.json | 1 + .../electron-browser/actions.i18n.json | 4 +- .../main.contribution.i18n.json | 7 +- .../debug/browser/breakpointsView.i18n.json | 10 +- .../debug/browser/debugActions.i18n.json | 5 +- .../debug/browser/debugCommands.i18n.json | 1 + .../browser/debugContentProvider.i18n.json | 3 +- .../breakpointWidget.i18n.json | 14 + .../debug.contribution.i18n.json | 3 +- .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 11 + .../electron-browser/debugService.i18n.json | 6 +- .../electronDebugActions.i18n.json | 1 + .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 8 +- .../extensionEditor.i18n.json | 57 + .../extensionTipsService.i18n.json | 4 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 3 +- .../electron-browser/fileActions.i18n.json | 11 +- .../views/explorerViewer.i18n.json | 1 - .../views/openEditorsView.i18n.json | 2 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 10 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 23 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 12 + .../electron-browser/markersPanel.i18n.json | 9 + .../markersPanelActions.i18n.json | 9 + .../electron-browser/messages.i18n.json | 33 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 1 - .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 1 - .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 5 +- .../search/browser/searchActions.i18n.json | 1 - .../parts/search/browser/searchView.i18n.json | 1 + .../search.contribution.i18n.json | 10 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../common/taskDefinitionRegistry.i18n.json | 1 - .../electron-browser/jsonSchema_v2.i18n.json | 2 + .../task.contribution.i18n.json | 9 +- .../terminalTaskSystem.i18n.json | 1 - .../tasks/node/taskConfiguration.i18n.json | 1 - .../common/terminalColorRegistry.i18n.json | 12 + .../terminal.contribution.i18n.json | 1 + .../terminalActions.i18n.json | 1 + .../electron-browser/terminalPanel.i18n.json | 4 +- ...edWorkspaceSettings.contribution.i18n.json | 4 +- .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../vs_code_welcome_page.i18n.json | 2 - .../configurationEditingService.i18n.json | 5 + .../node/configurationService.i18n.json | 10 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 9 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 1 + .../extensionService.i18n.json | 1 - .../electron-browser/fileService.i18n.json | 15 +- .../remoteFileService.i18n.json | 4 +- .../services/files/node/fileService.i18n.json | 1 - .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../themes/common/colorThemeSchema.i18n.json | 2 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/rus/extensions/css/package.i18n.json | 76 +- i18n/rus/extensions/emmet/package.i18n.json | 6 +- .../rus/extensions/git/out/commands.i18n.json | 6 +- i18n/rus/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/rus/extensions/html/package.i18n.json | 29 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/rus/extensions/json/package.i18n.json | 16 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/rus/extensions/npm/out/npmView.i18n.json | 11 + i18n/rus/extensions/npm/out/tasks.i18n.json | 10 + i18n/rus/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/rus/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/rus/src/vs/base/node/processes.i18n.json | 2 +- i18n/rus/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 15 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 6 +- .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 8 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 2 + .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 6 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../node/extensionManagementService.i18n.json | 10 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 8 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 21 + .../api/browser/viewsExtensionPoint.i18n.json | 9 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 2 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 13 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 15 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 14 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 24 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 3 + .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 23 +- .../files.contribution.i18n.json | 2 + .../views/explorerViewer.i18n.json | 8 +- .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 4 + .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 11 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 1 + .../common/taskDefinitionRegistry.i18n.json | 2 +- .../electron-browser/jsonSchema_v2.i18n.json | 9 + .../task.contribution.i18n.json | 13 +- .../terminalTaskSystem.i18n.json | 2 +- .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 10 +- .../terminalInstance.i18n.json | 5 +- .../electron-browser/terminalPanel.i18n.json | 1 + ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../configurationExtensionPoint.i18n.json | 1 + .../configurationEditingService.i18n.json | 1 + .../node/configurationService.i18n.json | 11 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 20 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 5 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 1 + .../electron-browser/TMSyntax.i18n.json | 1 + .../client/out/cssMain.i18n.json | 12 + .../css-language-features/package.i18n.json | 81 + i18n/trk/extensions/css/package.i18n.json | 76 +- i18n/trk/extensions/emmet/package.i18n.json | 10 +- .../trk/extensions/git/out/commands.i18n.json | 6 +- i18n/trk/extensions/git/package.i18n.json | 1 + .../client/out/htmlMain.i18n.json | 12 + .../html-language-features/package.i18n.json | 33 + i18n/trk/extensions/html/package.i18n.json | 29 +- .../client/out/jsonMain.i18n.json | 10 + .../json-language-features/package.i18n.json | 20 + i18n/trk/extensions/json/package.i18n.json | 14 +- .../markdown-basics/package.i18n.json | 2 +- .../onPreviewStyleLoadError.i18n.json | 10 + .../out/features/preview.i18n.json | 11 + .../features/previewContentProvider.i18n.json | 12 + .../out/security.i18n.json | 22 + .../package.i18n.json | 32 + .../markdown/out/features/preview.i18n.json | 2 +- i18n/trk/extensions/npm/out/npmView.i18n.json | 11 + i18n/trk/extensions/npm/out/tasks.i18n.json | 10 + i18n/trk/extensions/npm/package.i18n.json | 12 +- .../out/features/validationProvider.i18n.json | 15 + .../php-language-features/package.i18n.json | 18 + i18n/trk/extensions/php/package.i18n.json | 13 +- .../out/commands.i18n.json | 16 + .../features/completionItemProvider.i18n.json | 13 + ...rectiveCommentCompletionProvider.i18n.json | 12 + .../implementationsCodeLensProvider.i18n.json | 12 + .../jsDocCompletionProvider.i18n.json | 10 + .../out/features/organizeImports.i18n.json | 10 + .../out/features/quickFixProvider.i18n.json | 10 + .../referencesCodeLensProvider.i18n.json | 12 + .../out/features/taskProvider.i18n.json | 11 + .../out/typescriptServiceClient.i18n.json | 19 + .../out/utils/api.i18n.json | 10 + .../out/utils/logger.i18n.json | 10 + .../out/utils/projectStatus.i18n.json | 13 + .../out/utils/typingsStatus.i18n.json | 12 + .../out/utils/versionPicker.i18n.json | 13 + .../out/utils/versionProvider.i18n.json | 11 + .../package.i18n.json | 65 + i18n/trk/src/vs/base/node/zip.i18n.json | 1 + .../issue/issueReporterMain.i18n.json | 7 +- .../issue/issueReporterPage.i18n.json | 13 +- .../processExplorerMain.i18n.json | 15 + .../src/vs/code/electron-main/menus.i18n.json | 2 + .../browser/widget/diffReview.i18n.json | 5 +- .../editor/common/commonCodeEditor.i18n.json | 10 + .../config/commonEditorConfig.i18n.json | 18 +- .../common/view/editorColorRegistry.i18n.json | 6 +- .../codeAction/codeActionCommands.i18n.json | 19 + .../contrib/find/findController.i18n.json | 1 + .../contrib/format/formatActions.i18n.json | 4 +- .../contrib/gotoError/gotoError.i18n.json | 7 +- .../gotoError/gotoErrorWidget.i18n.json | 14 + .../vs/editor/contrib/links/links.i18n.json | 8 +- .../message/messageController.i18n.json | 10 + .../referencesWidget.i18n.json | 3 +- .../snippet/snippetVariables.i18n.json | 47 + .../wordHighlighter/wordHighlighter.i18n.json | 4 +- .../platform/dialogs/common/dialogs.i18n.json | 11 + .../dialogs/node/dialogService.i18n.json | 10 + .../node/extensionManagementService.i18n.json | 8 +- .../node/extensionValidator.i18n.json | 2 +- .../node/integrityServiceImpl.i18n.json | 4 +- .../electron-main/issueService.i18n.json | 3 +- .../list/browser/listService.i18n.json | 3 +- .../platform/markers/common/markers.i18n.json | 12 + .../theme/common/colorRegistry.i18n.json | 6 +- .../inactiveExtensionUrlHandler.i18n.json | 10 + .../viewsContainersExtensionPoint.i18n.json | 18 + .../api/browser/viewsExtensionPoint.i18n.json | 12 +- .../mainThreadSaveParticipant.i18n.json | 3 + .../electron-browser/mainThreadTask.i18n.json | 10 + .../mainThreadWebview.i18n.json | 4 +- .../api/node/extHostProgress.i18n.json | 10 + .../api/node/extHostTreeViews.i18n.json | 2 +- .../parts/editor/editorActions.i18n.json | 1 + .../parts/editor/editorStatus.i18n.json | 8 +- .../parts/editor/resourceViewer.i18n.json | 6 +- .../parts/editor/titleControl.i18n.json | 1 - .../notificationsCenter.i18n.json | 3 +- .../parts/quickinput/quickInput.i18n.json | 13 + .../parts/quickinput/quickInputBox.i18n.json | 10 + .../src/vs/workbench/common/views.i18n.json | 4 +- .../electron-browser/actions.i18n.json | 1 + .../main.contribution.i18n.json | 17 +- .../debug/browser/breakpointsView.i18n.json | 8 +- .../debug/browser/debugActions.i18n.json | 5 +- .../browser/debugEditorActions.i18n.json | 1 + .../breakpointWidget.i18n.json | 14 + .../debugConfigurationManager.i18n.json | 2 +- .../debugEditorContribution.i18n.json | 13 + .../electron-browser/debugService.i18n.json | 4 +- .../rawDebugSession.i18n.json | 3 - .../parts/debug/node/debugAdapter.i18n.json | 16 +- .../parts/debug/node/debugger.i18n.json | 23 + .../parts/debug/node/terminals.i18n.json | 14 + .../browser/extensionsActions.i18n.json | 5 +- .../extensionEditor.i18n.json | 61 + .../extensionTipsService.i18n.json | 2 +- .../extensions.contribution.i18n.json | 6 +- .../extensionsUtils.i18n.json | 4 +- .../extensionsViewlet.i18n.json | 6 +- .../browser/editors/textFileEditor.i18n.json | 2 + .../electron-browser/fileActions.i18n.json | 21 +- .../files.contribution.i18n.json | 1 + .../views/explorerViewer.i18n.json | 2 + .../html.contribution.i18n.json | 10 + .../htmlPreviewPart.i18n.json | 10 + .../webview.contribution.i18n.json | 10 + .../webviewCommands.i18n.json | 11 + .../localizations.contribution.i18n.json | 10 +- .../localizations.contribution.i18n.json | 25 + .../localizationsActions.i18n.json | 14 + .../markers.contribution.i18n.json | 11 + .../electron-browser/markers.i18n.json | 10 + .../markersFileDecorations.i18n.json | 13 + .../electron-browser/markersPanel.i18n.json | 11 + .../markersPanelActions.i18n.json | 10 + .../electron-browser/messages.i18n.json | 48 + .../output/browser/outputActions.i18n.json | 3 +- .../output.contribution.i18n.json | 3 +- .../browser/keybindingsEditor.i18n.json | 3 +- .../browser/preferencesActions.i18n.json | 1 + .../browser/preferencesEditor.i18n.json | 3 +- .../browser/preferencesRenderers.i18n.json | 6 +- .../scm/electron-browser/scmViewlet.i18n.json | 3 +- .../search/browser/searchActions.i18n.json | 1 - .../search.contribution.i18n.json | 12 +- .../languageSurveys.contribution.i18n.json | 4 +- .../nps.contribution.i18n.json | 4 +- .../tasks/common/problemMatcher.i18n.json | 5 +- .../common/taskDefinitionRegistry.i18n.json | 1 - .../electron-browser/jsonSchema_v2.i18n.json | 11 +- .../task.contribution.i18n.json | 11 +- .../terminalTaskSystem.i18n.json | 1 - .../tasks/node/taskConfiguration.i18n.json | 2 +- .../common/terminalColorRegistry.i18n.json | 16 + .../terminalActions.i18n.json | 7 +- .../electron-browser/terminalPanel.i18n.json | 1 + ...edWorkspaceSettings.contribution.i18n.json | 1 + .../releaseNotesEditor.i18n.json | 11 + .../update/electron-browser/update.i18n.json | 11 +- .../url.contribution.i18n.json | 11 + .../webview.contribution.i18n.json | 11 + .../webviewCommands.i18n.json | 11 + .../telemetryOptOut.i18n.json | 12 + .../overlay/browser/welcomeOverlay.i18n.json | 1 + .../vs_code_welcome_page.i18n.json | 4 +- .../menusExtensionPoint.i18n.json | 2 +- .../configurationExtensionPoint.i18n.json | 1 + .../node/configurationService.i18n.json | 10 + .../configurationResolverService.i18n.json | 9 + .../node/variableResolver.i18n.json | 16 + .../electron-browser/dialogService.i18n.json | 11 + .../common/extensionsRegistry.i18n.json | 2 + .../extensionService.i18n.json | 3 +- .../electron-browser/fileService.i18n.json | 19 +- .../remoteFileService.i18n.json | 5 +- .../browser/progressService2.i18n.json | 3 +- .../electron-browser/TMGrammars.i18n.json | 3 +- .../electron-browser/TMSyntax.i18n.json | 1 + .../common/fileIconThemeSchema.i18n.json | 6 +- package.json | 24 +- resources/linux/code.desktop | 2 +- scripts/env.ps1 | 4 +- scripts/env.sh | 4 +- scripts/test-integration.bat | 10 +- scripts/test-integration.sh | 8 +- scripts/test.sh | 1 + src/bootstrap-amd.js | 15 +- src/bootstrap.js | 6 +- src/cli.js | 6 +- src/main.js | 200 +- src/sql/base/browser/ui/checkbox/checkbox.ts | 2 +- .../browser/ui/dropdownList/dropdownList.ts | 21 +- .../ui/dropdownList/media/dropdownList.css | 12 +- .../browser/ui/editableDropdown/dropdown.ts | 37 +- .../ui/editableDropdown/dropdownTree.ts | 2 +- .../editableDropdown/media/dropdownList.css | 6 +- src/sql/base/browser/ui/inputBox/inputBox.ts | 2 +- src/sql/base/browser/ui/listBox/listBox.ts | 2 - src/sql/base/browser/ui/modal/media/modal.css | 3 +- src/sql/base/browser/ui/modal/modal.ts | 4 +- .../base/browser/ui/modal/optionsDialog.ts | 2 +- .../browser/ui/modal/optionsDialogHelper.ts | 18 +- .../base/browser/ui/modal/webViewDialog.ts | 10 +- src/sql/base/browser/ui/panel/panel.ts | 7 +- .../browser/ui/radioButton/radioButton.ts | 2 +- .../base/browser/ui/splitview/splitview.ts | 2 +- src/sql/base/browser/ui/table/table.ts | 11 +- .../base/browser/ui/table/tableDataView.ts | 2 +- .../base/browser/ui/views/browser/views.ts | 2 +- src/sql/base/browser/ui/views/common/views.ts | 2 +- .../accountDialog/accountDialog.ts | 2 +- .../accountDialog/accountViewModel.ts | 2 +- .../accountPicker/accountPicker.ts | 2 +- .../accountPicker/accountPickerService.ts | 2 +- .../accountPicker/accountPickerViewModel.ts | 2 +- .../autoOAuthDialog/autoOAuthDialog.ts | 2 +- .../common/accountActions.ts | 8 +- .../accountManagement/common/interfaces.ts | 2 +- .../firewallRuleDialog/firewallRuleDialog.ts | 2 +- .../parts/admin/security/createLoginEditor.ts | 12 +- .../connection/common/connectionActions.ts | 14 +- .../connection/common/connectionManagement.ts | 2 +- .../common/connectionManagementService.ts | 2 +- .../connectionDialogService.ts | 3 +- .../connectionDialogWidget.ts | 5 +- .../recentConnectionTreeController.ts | 4 +- src/sql/parts/dashboard/common/actions.ts | 2 +- .../common/dashboardPage.component.ts | 2 +- src/sql/parts/dashboard/common/interfaces.ts | 2 +- ...dashboardControlHostContainer.component.ts | 2 +- .../dashboardErrorContainer.component.ts | 2 +- .../dashboardGridContainer.component.ts | 2 +- .../dashboardModelViewContainer.component.ts | 2 +- .../dashboardNavSection.component.ts | 2 +- .../dashboardWebviewContainer.component.ts | 2 +- .../dashboardWidgetContainer.component.ts | 2 +- .../contents/controlHostContent.component.ts | 2 +- .../contents/webviewContent.component.ts | 10 +- .../contents/widgetContent.component.ts | 2 +- src/sql/parts/dashboard/dashboardEditor.ts | 10 +- .../newDashboardTabDialog.ts | 2 +- .../newDashboardTabViewModel.ts | 2 +- .../dashboardServiceInterface.service.ts | 2 +- .../insights/views/tableInsight.component.ts | 3 +- .../webview/webviewWidget.component.ts | 10 +- .../backup/common/backupService.ts | 2 +- .../backup/common/backupServiceImp.ts | 2 +- .../disasterRecovery/backup/constants.ts | 2 +- .../disasterRecovery/restore/restoreDialog.ts | 2 +- .../restore/restoreViewModel.ts | 2 +- .../parts/editData/common/editDataInput.ts | 2 +- .../parts/editData/editor/editDataEditor.ts | 36 +- .../editData/editor/editDataResultsEditor.ts | 12 +- .../parts/extensions/sqlExtensionsHelper.ts | 2 +- .../fileBrowser/common/fileBrowserService.ts | 2 +- .../parts/fileBrowser/common/interfaces.ts | 4 +- .../fileBrowser/fileBrowserController.ts | 2 +- .../parts/fileBrowser/fileBrowserDialog.ts | 2 +- .../parts/fileBrowser/fileBrowserRenderer.ts | 4 +- .../parts/fileBrowser/fileBrowserTreeView.ts | 4 +- .../insights/common/insightsDialogModel.ts | 2 +- src/sql/parts/insights/common/interfaces.ts | 2 +- .../jobManagement/views/jobHistoryTree.ts | 2 +- .../jobManagement/views/jobStepsViewTree.ts | 1 - .../parts/modelComponents/button.component.ts | 2 +- .../modelComponents/checkbox.component.ts | 2 +- .../parts/modelComponents/componentBase.ts | 2 +- .../modelComponents/dropdown.component.ts | 2 +- .../modelComponents/inputbox.component.ts | 2 +- src/sql/parts/modelComponents/interfaces.ts | 2 +- .../modelEditor/modelViewEditor.ts | 9 +- .../modelViewContent.component.ts | 2 +- .../modelComponents/radioButton.component.ts | 2 +- .../parts/modelComponents/table.component.ts | 14 +- .../parts/modelComponents/text.component.ts | 2 +- src/sql/parts/modelComponents/viewBase.ts | 2 +- .../modelComponents/webview.component.ts | 10 +- .../common/objectExplorerService.ts | 2 +- .../serverGroupDialog/serverGroupDialog.ts | 2 +- .../viewlet/connectionViewlet.ts | 15 +- .../viewlet/serverTreeController.ts | 2 +- .../objectExplorer/viewlet/serverTreeView.ts | 2 +- .../objectExplorer/viewlet/treeUpdateUtils.ts | 2 +- .../dialog/profilerColumnEditorDialog.ts | 2 +- .../editor/controller/profilerTableEditor.ts | 11 +- .../parts/profiler/editor/profilerEditor.ts | 16 +- .../parts/profiler/editor/profilerInput.ts | 2 +- .../profiler/editor/profilerResourceEditor.ts | 8 +- src/sql/parts/query/common/queryInput.ts | 2 +- src/sql/parts/query/editor/queryEditor.ts | 43 +- .../parts/query/editor/queryResultsEditor.ts | 12 +- src/sql/parts/query/execution/queryModel.ts | 2 +- .../query/execution/queryModelService.ts | 2 +- .../query/services/queryEditorService.ts | 2 +- src/sql/parts/query/views/flexibleSash.ts | 4 +- src/sql/parts/queryPlan/planXmlParser.ts | 74 +- src/sql/parts/queryPlan/queryPlanEditor.ts | 15 +- .../parts/taskHistory/common/taskService.ts | 8 +- .../viewlet/taskHistoryController.ts | 2 +- .../taskHistory/viewlet/taskHistoryView.ts | 2 +- .../taskHistory/viewlet/taskHistoryViewlet.ts | 9 +- .../parts/tasks/dialog/taskDialogEditor.ts | 10 +- .../dialog/dialogContainer.component.ts | 2 +- src/sql/platform/dialog/dialogModal.ts | 2 +- src/sql/platform/dialog/dialogPane.ts | 6 +- src/sql/platform/dialog/dialogTypes.ts | 4 +- src/sql/platform/tasks/common/tasks.ts | 2 +- .../accountManagementService.ts | 2 +- .../services/accountManagement/interfaces.ts | 2 +- .../capabilities/capabilitiesService.ts | 2 +- .../dashboard/common/dashboardService.ts | 2 +- .../dashboard/common/dashboardServiceImpl.ts | 2 +- .../dashboard/common/dashboardViewService.ts | 2 +- .../common/dashboardViewServiceImpl.ts | 2 +- src/sql/services/model/modelViewService.ts | 2 +- .../modelComponents/modelViewService.ts | 2 +- .../modelComponents/modelViewServiceImpl.ts | 2 +- .../workbench/api/node/extHostDashboard.ts | 2 +- .../workbench/api/node/extHostDataProtocol.ts | 2 +- .../api/node/extHostModelViewDialog.ts | 2 +- .../workbench/api/node/sqlExtHost.protocol.ts | 2 +- .../errorMessageDialog/errorMessageDialog.ts | 2 +- .../common/connectionProviderExtension.ts | 2 +- src/sql/workbench/update/releaseNotes.ts | 6 +- .../connection/objectExplorerService.test.ts | 2 +- .../parts/query/editor/queryEditor.test.ts | 4 +- src/sqltest/stubs/accountManagementStubs.ts | 2 +- src/sqltest/stubs/capabilitiesTestService.ts | 2 +- .../stubs/connectionManagementService.test.ts | 2 +- src/sqltest/stubs/contextKeyServiceStub.ts | 2 +- src/sqltest/stubs/editorGroupService.ts | 2 +- .../workspaceConfigurationTestService.ts | 2 +- src/tsconfig.json | 3 + src/typings/electron.d.ts | 2 +- src/typings/gc-signals.d.ts | 2 +- src/typings/globals/core-js/index.d.ts | 2 +- src/typings/keytar.d.ts | 72 +- src/typings/mocha.d.ts | 300 +- src/typings/node-pty.d.ts | 100 +- src/typings/node.d.ts | 6386 ++++++++--------- src/typings/{nsfw.d.ts => vscode-nsfw.d.ts} | 2 +- src/typings/vscode-textmate.d.ts | 17 +- src/typings/vscode-xterm.d.ts | 122 +- .../{windows-mutex.ts => windows-mutex.d.ts} | 2 +- src/typings/windows-process-tree.d.ts | 63 +- src/typings/yauzl.d.ts | 1 + src/vs/base/browser/browser.ts | 15 +- src/vs/base/browser/builder.css | 10 +- src/vs/base/browser/builder.ts | 240 +- src/vs/base/browser/dnd.ts | 16 +- src/vs/base/browser/dom.ts | 136 +- src/vs/base/browser/event.ts | 3 +- src/vs/base/browser/keyboardEvent.ts | 255 +- src/vs/base/browser/touch.ts | 4 +- src/vs/base/browser/ui/actionbar/actionbar.ts | 27 +- src/vs/base/browser/ui/aria/aria.css | 2 +- src/vs/base/browser/ui/aria/aria.ts | 2 +- src/vs/base/browser/ui/button/button.ts | 23 +- src/vs/base/browser/ui/checkbox/checkbox.ts | 16 +- .../browser/ui/contextview/contextview.ts | 3 +- .../base/browser/ui/countBadge/countBadge.ts | 10 +- src/vs/base/browser/ui/dropdown/dropdown.css | 15 +- src/vs/base/browser/ui/dropdown/dropdown.ts | 55 +- .../base/browser/ui/findinput/findInput.css | 8 - src/vs/base/browser/ui/findinput/findInput.ts | 40 +- .../ui/findinput/findInputCheckboxes.ts | 10 +- .../ui/highlightedlabel/highlightedLabel.ts | 2 +- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 4 +- src/vs/base/browser/ui/inputbox/inputBox.ts | 25 +- src/vs/base/browser/ui/list/listPaging.ts | 18 +- src/vs/base/browser/ui/list/listView.ts | 11 +- src/vs/base/browser/ui/list/listWidget.ts | 172 +- src/vs/base/browser/ui/menu/menu.ts | 12 +- .../ui/octiconLabel/octiconLabel.mock.ts | 14 +- .../browser/ui/octiconLabel/octiconLabel.ts | 6 +- .../browser/ui/progressbar/progressbar.css | 32 +- .../browser/ui/progressbar/progressbar.ts | 35 +- src/vs/base/browser/ui/sash/sash.css | 14 +- src/vs/base/browser/ui/sash/sash.ts | 76 +- .../browser/ui/scrollbar/scrollableElement.ts | 14 +- .../base/browser/ui/selectBox/selectBox.css | 5 +- src/vs/base/browser/ui/selectBox/selectBox.ts | 15 +- .../browser/ui/selectBox/selectBoxCustom.css | 18 +- .../browser/ui/selectBox/selectBoxCustom.ts | 63 +- .../browser/ui/selectBox/selectBoxNative.ts | 10 +- src/vs/base/browser/ui/splitview/grid.ts | 2 +- src/vs/base/browser/ui/splitview/panelview.ts | 46 +- .../base/browser/ui/splitview/splitview.css | 11 +- src/vs/base/browser/ui/splitview/splitview.ts | 21 +- src/vs/base/browser/ui/toolbar/toolbar.ts | 15 +- src/vs/base/common/actions.ts | 2 +- src/vs/base/common/arrays.ts | 4 +- src/vs/base/common/async.ts | 76 +- src/vs/base/common/cancellation.ts | 20 +- src/vs/base/common/decorators.ts | 22 +- src/vs/base/common/errorMessage.ts | 6 +- src/vs/base/common/event.ts | 27 +- src/vs/base/common/filters.ts | 4 +- src/vs/base/common/glob.ts | 6 +- src/vs/base/common/history.ts | 5 + src/vs/base/common/jsonFormatter.ts | 2 +- src/vs/base/common/keybindingLabels.ts | 24 +- src/vs/base/common/labels.ts | 38 +- src/vs/base/common/map.ts | 34 +- src/vs/base/common/marked/OSSREADME.json | 2 +- src/vs/base/common/marked/marked.d.ts | 2 +- src/vs/base/common/marked/marked.js | 1414 +++- src/vs/base/common/marked/raw.marked.js | 1388 ---- src/vs/base/common/marshalling.ts | 2 +- src/vs/base/common/mime.ts | 4 +- src/vs/base/common/paths.ts | 8 +- src/vs/base/common/platform.ts | 16 +- src/vs/base/common/resources.ts | 10 +- src/vs/base/common/scrollable.ts | 4 +- src/vs/base/common/sequence.ts | 2 +- src/vs/base/common/severity.ts | 15 +- src/vs/base/common/strings.ts | 6 +- src/vs/base/common/winjs.base.js | 2099 +++++- src/vs/base/common/winjs.base.raw.js | 2078 ------ src/vs/base/common/winjs.polyfill.promise.ts | 11 +- src/vs/base/common/worker/simpleWorker.ts | 25 +- src/vs/base/node/config.ts | 19 +- src/vs/base/node/decoder.ts | 2 +- src/vs/base/node/encoding.ts | 176 +- src/vs/base/node/flow.ts | 2 +- src/vs/base/node/mime.ts | 106 - src/vs/base/node/pfs.ts | 10 +- src/vs/base/node/ports.ts | 2 +- src/vs/base/node/processes.ts | 8 +- src/vs/base/node/ps-win.ps1 | 183 - src/vs/base/node/ps.ts | 131 +- src/vs/base/node/request.ts | 6 +- src/vs/base/node/stdFork.ts | 8 +- src/vs/base/node/stream.ts | 2 +- src/vs/base/node/zip.ts | 76 +- src/vs/base/parts/ipc/common/ipc.electron.ts | 2 +- src/vs/base/parts/ipc/common/ipc.ts | 4 +- .../ipc/electron-main/ipc.electron-main.ts | 2 +- src/vs/base/parts/ipc/node/ipc.net.ts | 2 +- src/vs/base/parts/ipc/test/node/ipc.perf.ts | 8 +- .../base/parts/ipc/test/node/testService.ts | 2 +- .../parts/quickopen/browser/quickOpenModel.ts | 6 +- .../quickopen/browser/quickOpenWidget.ts | 61 +- .../parts/quickopen/browser/quickopen.css | 46 +- .../parts/quickopen/common/quickOpenScorer.ts | 10 +- src/vs/base/parts/tree/browser/tree.ts | 25 +- .../base/parts/tree/browser/treeDefaults.ts | 99 +- src/vs/base/parts/tree/browser/treeDnd.ts | 4 +- src/vs/base/parts/tree/browser/treeImpl.ts | 51 +- src/vs/base/parts/tree/browser/treeModel.ts | 10 +- src/vs/base/parts/tree/browser/treeView.ts | 236 +- .../base/parts/tree/browser/treeViewModel.ts | 3 +- .../parts/tree/test/browser/treeModel.test.ts | 493 +- .../tree/test/browser/treeViewModel.test.ts | 5 +- src/vs/base/test/browser/builder.test.ts | 17 +- src/vs/base/test/browser/progressBar.test.ts | 6 +- .../test/browser/ui/list/rangeMap.test.ts | 2 +- src/vs/base/test/common/arrays.test.ts | 34 +- src/vs/base/test/common/async.test.ts | 155 +- src/vs/base/test/common/cache.test.ts | 8 +- src/vs/base/test/common/cancellation.test.ts | 14 + src/vs/base/test/common/collections.test.ts | 2 +- src/vs/base/test/common/event.test.ts | 51 +- src/vs/base/test/common/history.test.ts | 55 +- src/vs/base/test/common/jsonEdit.test.ts | 2 +- src/vs/base/test/common/jsonFormatter.test.ts | 4 +- src/vs/base/test/common/labels.test.ts | 25 +- src/vs/base/test/common/map.test.ts | 65 +- src/vs/base/test/common/objects.test.ts | 2 +- src/vs/base/test/common/paths.test.ts | 7 +- src/vs/base/test/common/resources.test.ts | 3 +- src/vs/base/test/common/strings.test.ts | 42 +- src/vs/base/test/common/types.test.ts | 2 +- src/vs/base/test/common/utils.ts | 6 - src/vs/base/test/common/uuid.test.ts | 2 +- src/vs/base/test/node/config.test.ts | 125 +- src/vs/base/test/node/decoder.test.ts | 2 +- .../base/test/node/encoding/encoding.test.ts | 260 +- .../fixtures/some.cp1252.txt | 0 .../fixtures/some.css.qwoff | 0 .../{mime => encoding}/fixtures/some.json.png | 0 .../node/{mime => encoding}/fixtures/some.pdf | Bin .../{mime => encoding}/fixtures/some.png.txt | Bin .../fixtures/some.qwoff.txt | Bin .../fixtures/some.shiftjis.txt | 0 .../{mime => encoding}/fixtures/some.xml.png | 0 .../node/encoding/fixtures/utf16_be_nobom.txt | Bin 0 -> 60 bytes .../node/encoding/fixtures/utf16_le_nobom.txt | Bin 0 -> 60 bytes src/vs/base/test/node/extfs/extfs.test.ts | 107 +- src/vs/base/test/node/flow.test.ts | 2 +- src/vs/base/test/node/glob.test.ts | 2 +- src/vs/base/test/node/mime/mime.test.ts | 91 - src/vs/base/test/node/pfs.test.ts | 109 +- src/vs/base/test/node/port.test.ts | 8 +- .../base/test/node/processes/fixtures/fork.ts | 4 +- .../node/processes/fixtures/fork_large.ts | 4 +- .../test/node/processes/processes.test.ts | 2 +- src/vs/base/test/node/stream/stream.test.ts | 33 +- src/vs/base/test/node/utils.ts | 31 + src/vs/base/test/node/zip/zip.test.ts | 3 +- src/vs/base/worker/defaultWorkerFactory.ts | 30 +- src/vs/code/buildfile.js | 17 +- .../electron-browser/issue/issueReporter.js | 67 +- .../issue/issueReporterMain.ts | 296 +- .../issue/issueReporterModel.ts | 31 +- .../issue/issueReporterPage.ts | 206 +- .../issue/issueReporterUtil.ts | 30 + .../issue/media/issueReporter.css | 93 +- .../issue/test/testReporterModel.test.ts | 76 +- .../processExplorer/media/processExplorer.css | 69 + .../processExplorer/processExplorer.html | 17 + .../processExplorer/processExplorer.js | 175 + .../processExplorer/processExplorerMain.ts | 184 + .../sharedProcess/sharedProcess.js | 6 +- .../sharedProcess/sharedProcessMain.ts | 35 +- src/vs/code/electron-main/app.ts | 110 +- src/vs/code/electron-main/diagnostics.ts | 14 +- src/vs/code/electron-main/keyboard.ts | 4 +- src/vs/code/electron-main/launch.ts | 106 +- src/vs/code/electron-main/main.ts | 10 +- src/vs/code/electron-main/menus.ts | 12 +- src/vs/code/electron-main/sharedProcess.ts | 34 +- src/vs/code/electron-main/window.ts | 117 +- src/vs/code/electron-main/windows.ts | 174 +- src/vs/code/node/cliProcessMain.ts | 24 +- src/vs/code/node/windowsFinder.ts | 52 +- src/vs/code/test/node/argv.test.ts | 2 +- .../_vscode/{keepfolder.txt => settings.json} | 0 .../_vscode/{keepfolder.txt => settings.json} | 0 src/vs/code/test/node/windowsFinder.test.ts | 54 +- src/vs/editor/browser/codeEditor.ts | 6 +- src/vs/editor/browser/config/configuration.ts | 23 +- .../editor/browser/controller/coreCommands.ts | 84 +- .../editor/browser/controller/mouseHandler.ts | 76 +- .../editor/browser/controller/mouseTarget.ts | 49 +- .../browser/controller/pointerHandler.ts | 2 +- .../browser/controller/textAreaHandler.ts | 49 +- .../browser/controller/textAreaInput.ts | 110 +- .../browser/controller/textAreaState.ts | 18 +- src/vs/editor/browser/core/editorState.ts | 30 + src/vs/editor/browser/editorBrowser.ts | 16 +- .../services/abstractCodeEditorService.ts | 10 +- .../browser/services/codeEditorService.ts | 2 +- .../browser/services/codeEditorServiceImpl.ts | 31 +- src/vs/editor/browser/view/viewController.ts | 49 +- src/vs/editor/browser/view/viewImpl.ts | 10 +- .../contentWidgets/contentWidgets.ts | 3 +- .../viewParts/decorations/decorations.ts | 91 +- .../viewParts/indentGuides/indentGuides.css | 3 + .../viewParts/indentGuides/indentGuides.ts | 44 +- .../browser/viewParts/lines/viewLine.ts | 40 +- .../editor/browser/viewParts/margin/margin.ts | 3 +- .../browser/viewParts/minimap/minimap.ts | 26 +- .../overviewRuler/decorationsOverviewRuler.ts | 7 +- .../editor/browser/viewParts/rulers/rulers.ts | 5 +- .../scrollDecoration/scrollDecoration.ts | 7 +- .../viewParts/selections/selections.ts | 38 +- .../viewParts/viewCursors/viewCursor.ts | 20 +- .../browser/viewParts/viewZones/viewZones.ts | 6 +- .../editor/browser/widget/codeEditorWidget.ts | 111 +- .../editor/browser/widget/diffEditorWidget.ts | 67 +- src/vs/editor/browser/widget/diffNavigator.ts | 2 +- src/vs/editor/browser/widget/diffReview.ts | 35 +- .../widget/embeddedCodeEditorWidget.ts | 5 +- src/vs/editor/common/commonCodeEditor.ts | 103 +- .../common/config/commonEditorConfig.ts | 59 +- src/vs/editor/common/config/editorOptions.ts | 174 +- src/vs/editor/common/config/editorZoom.ts | 6 +- src/vs/editor/common/controller/cursor.ts | 28 +- .../common/controller/cursorCollection.ts | 18 + .../editor/common/controller/cursorCommon.ts | 3 + .../common/controller/cursorTypeOperations.ts | 10 + .../common/controller/cursorWordOperations.ts | 51 +- src/vs/editor/common/controller/oneCursor.ts | 31 +- src/vs/editor/common/core/lineTokens.ts | 5 + src/vs/editor/common/diff/diffComputer.ts | 2 +- src/vs/editor/common/editorCommon.ts | 9 +- src/vs/editor/common/editorContextKeys.ts | 7 +- src/vs/editor/common/model.ts | 64 +- .../model/chunksTextBuffer/bufferPiece.ts | 323 - .../chunksTextBuffer/chunksTextBuffer.ts | 1526 ---- .../chunksTextBufferBuilder.ts | 186 - src/vs/editor/common/model/intervalTree.ts | 10 +- .../model/linesTextBuffer/linesTextBuffer.ts | 660 -- .../linesTextBuffer/linesTextBufferBuilder.ts | 139 - .../model/linesTextBuffer/textSource.ts | 66 - .../pieceTreeTextBuffer/pieceTreeBase.ts | 284 +- .../pieceTreeTextBuffer.ts | 50 +- src/vs/editor/common/model/textModel.ts | 607 +- src/vs/editor/common/model/textModelEvents.ts | 4 + src/vs/editor/common/model/textModelSearch.ts | 16 +- src/vs/editor/common/model/textModelTokens.ts | 37 +- src/vs/editor/common/modes.ts | 107 +- .../modes/languageConfigurationRegistry.ts | 6 +- .../common/modes/languageFeatureRegistry.ts | 31 +- .../editor/common/modes/languageSelector.ts | 24 +- src/vs/editor/common/modes/modesRegistry.ts | 6 +- .../common/modes/supports/richEditBrackets.ts | 19 +- .../common/modes/tokenizationRegistry.ts | 6 +- .../common/services/editorSimpleWorker.ts | 134 +- .../services/editorWorkerServiceImpl.ts | 4 +- .../common/services/languagesRegistry.ts | 10 +- src/vs/editor/common/services/modeService.ts | 2 +- .../editor/common/services/modeServiceImpl.ts | 2 +- src/vs/editor/common/services/modelService.ts | 12 +- .../common/services/modelServiceImpl.ts | 105 +- .../common/services/resourceConfiguration.ts | 2 +- .../services/resourceConfigurationImpl.ts | 5 +- .../common/standalone/standaloneBase.ts | 8 + .../editor/common/view/editorColorRegistry.ts | 34 +- .../editor/common/view/minimapCharRenderer.ts | 4 +- .../common/viewLayout/lineDecorations.ts | 2 +- src/vs/editor/common/viewLayout/viewLayout.ts | 18 +- .../common/viewLayout/viewLineRenderer.ts | 63 +- .../common/viewModel/splitLinesCollection.ts | 71 +- src/vs/editor/common/viewModel/viewModel.ts | 45 +- .../common/viewModel/viewModelDecorations.ts | 2 +- .../editor/common/viewModel/viewModelImpl.ts | 132 +- .../bracketMatching/bracketMatching.ts | 62 +- .../test/bracketMatching.test.ts | 53 + .../contrib/caretOperations/transpose.ts | 76 +- src/vs/editor/contrib/clipboard/clipboard.ts | 8 +- .../quickFix.ts => codeAction/codeAction.ts} | 63 +- .../codeActionCommands.ts} | 221 +- .../codeAction/codeActionContributions.ts | 15 + .../codeActionModel.ts} | 81 +- .../codeActionTrigger.ts | 13 +- .../codeActionWidget.ts} | 23 +- .../lightBulbWidget.css | 0 .../lightBulbWidget.ts | 25 +- .../lightbulb-dark.svg | 0 .../{quickFix => codeAction}/lightbulb.svg | 0 .../test/codeAction.test.ts} | 45 +- .../test/codeActionModel.test.ts} | 22 +- src/vs/editor/contrib/codelens/codelens.ts | 22 +- .../contrib/codelens/codelensController.ts | 12 +- src/vs/editor/contrib/colorPicker/color.ts | 61 + .../contrib/colorPicker/colorDetector.ts | 3 +- .../contrib/colorPicker/colorPicker.css | 2 +- .../contrib/colorPicker/colorPickerModel.ts | 2 +- .../contrib/colorPicker/colorPickerWidget.ts | 11 +- .../contrib/comment/blockCommentCommand.ts | 18 +- src/vs/editor/contrib/comment/comment.ts | 8 +- .../contrib/comment/lineCommentCommand.ts | 8 +- .../comment/test/lineCommentCommand.test.ts | 66 +- .../editor/contrib/contextmenu/contextmenu.ts | 2 +- .../editor/contrib/cursorUndo/cursorUndo.ts | 2 +- src/vs/editor/contrib/dnd/dnd.ts | 17 +- src/vs/editor/contrib/find/findController.ts | 14 +- src/vs/editor/contrib/find/findDecorations.ts | 45 + src/vs/editor/contrib/find/findModel.ts | 140 +- src/vs/editor/contrib/find/findState.ts | 4 +- src/vs/editor/contrib/find/findWidget.css | 8 - src/vs/editor/contrib/find/findWidget.ts | 150 +- .../editor/contrib/find/simpleFindWidget.ts | 57 +- .../contrib/find/test/findController.test.ts | 4 +- .../contrib/find/test/findModel.test.ts | 18 +- src/vs/editor/contrib/folding/folding.ts | 88 +- .../contrib/folding/foldingDecorations.ts | 12 +- src/vs/editor/contrib/folding/foldingModel.ts | 2 +- .../contrib/folding/hiddenRangeModel.ts | 6 +- .../contrib/folding/indentRangeProvider.ts | 3 +- .../contrib/folding/syntaxRangeProvider.ts | 73 +- src/vs/editor/contrib/format/format.ts | 32 +- src/vs/editor/contrib/format/formatActions.ts | 23 +- src/vs/editor/contrib/format/formatCommand.ts | 65 +- .../contrib/format/test/formatCommand.test.ts | 49 + .../goToDeclaration/clickLinkGesture.ts | 2 +- .../goToDeclarationCommands.ts | 14 +- src/vs/editor/contrib/gotoError/gotoError.ts | 490 +- .../{gotoError.css => gotoErrorWidget.css} | 5 + .../contrib/gotoError/gotoErrorWidget.ts | 275 + src/vs/editor/contrib/hover/hover.ts | 31 +- .../editor/contrib/hover/modesContentHover.ts | 15 +- .../editor/contrib/hover/modesGlyphHover.ts | 8 +- .../contrib/inPlaceReplace/inPlaceReplace.ts | 9 +- .../editor/contrib/indentation/indentation.ts | 29 +- .../indentation/test/indentation.test.ts | 20 +- .../linesOperations/linesOperations.ts | 26 +- .../test/linesOperations.test.ts | 10 +- src/vs/editor/contrib/links/links.ts | 55 +- .../contrib/markdown/markdownRenderer.ts | 36 +- .../contrib/message/messageController.ts | 18 +- .../editor/contrib/multicursor/multicursor.ts | 32 +- .../contrib/parameterHints/parameterHints.ts | 8 +- .../parameterHints/parameterHintsWidget.ts | 38 +- .../test/parameterHintsModel.test.ts | 103 + .../contrib/referenceSearch/peekViewWidget.ts | 4 +- .../referenceSearch/referenceSearch.ts | 50 +- .../referenceSearch/referencesController.ts | 50 +- .../referenceSearch/referencesModel.ts | 34 +- .../referenceSearch/referencesWidget.ts | 87 +- src/vs/editor/contrib/rename/rename.ts | 191 +- .../editor/contrib/rename/renameInputField.ts | 31 +- .../editor/contrib/smartSelect/smartSelect.ts | 4 +- .../smartSelect/tokenSelectionSupport.ts | 2 +- .../contrib/snippet/snippetController2.ts | 14 +- .../editor/contrib/snippet/snippetParser.ts | 2 +- .../editor/contrib/snippet/snippetSession.ts | 37 +- .../contrib/snippet/snippetVariables.ts | 18 + .../snippet/test/snippetVariables.test.ts | 6 +- .../editor/contrib/suggest/completionModel.ts | 7 +- src/vs/editor/contrib/suggest/suggest.ts | 17 +- .../contrib/suggest/suggestController.ts | 22 +- .../editor/contrib/suggest/suggestMemory.ts | 30 +- src/vs/editor/contrib/suggest/suggestModel.ts | 28 +- .../editor/contrib/suggest/suggestWidget.ts | 32 +- .../suggest/test/suggestMemory.test.ts | 18 +- .../contrib/suggest/test/suggestModel.test.ts | 129 +- .../wordHighlighter/wordHighlighter.ts | 40 +- .../test/wordOperations.test.ts | 31 +- .../contrib/wordOperations/wordOperations.ts | 12 +- .../editor/contrib/zoneWidget/zoneWidget.ts | 11 +- src/vs/editor/editor.all.ts | 2 +- src/vs/editor/editor.api.ts | 61 + src/vs/editor/editor.main.ts | 47 +- src/vs/editor/editor.worker.ts | 34 + src/vs/editor/standalone/browser/colorizer.ts | 20 +- .../browser/quickOpen/editorQuickOpen.ts | 36 +- .../standalone/browser/quickOpen/gotoLine.css | 2 +- .../quickOpen/quickOpenEditorWidget.ts | 4 +- .../browser/quickOpen/quickOutline.css | 84 +- .../browser/quickOpen/quickOutline.ts | 10 +- .../standaloneReferenceSearch.ts | 53 + .../standalone/browser/simpleServices.ts | 32 +- .../standalone/browser/standalone-tokens.css | 16 +- .../browser/standaloneCodeEditor.ts | 10 +- .../standalone/browser/standaloneEditor.ts | 3 +- .../standalone/browser/standaloneLanguages.ts | 28 +- .../standalone/browser/standaloneServices.ts | 9 +- .../browser/standaloneThemeServiceImpl.ts | 6 +- src/vs/editor/standalone/common/themes.ts | 5 +- .../test/browser/standaloneLanguages.test.ts | 4 +- .../test/browser/controller/cursor.test.ts | 633 +- .../browser/controller/textAreaState.test.ts | 88 +- src/vs/editor/test/browser/testCodeEditor.ts | 8 +- .../common/config/commonEditorConfig.test.ts | 8 +- .../editor/test/common/core/viewLineToken.ts | 4 + .../test/common/diff/diffComputer.test.ts | 19 + src/vs/editor/test/common/editorTestUtils.ts | 26 + .../common/model/benchmark/benchmarkUtils.ts | 4 +- .../model/benchmark/modelbuilder.benchmark.ts | 4 +- .../chunksTextBuffer/bufferPiece.test.ts | 61 - .../common/model/editableTextModel.test.ts | 46 +- .../model/editableTextModelTestUtils.ts | 11 +- .../linesTextBuffer/linesTextBuffer.test.ts | 18 +- .../linesTextBufferBuilder.test.ts | 133 +- .../linesTextBufferBuilderAuto.test.ts | 97 - src/vs/editor/test/common/model/model.test.ts | 99 +- .../common/model/modelEditOperation.test.ts | 11 +- .../pieceTreeTextBuffer.test.ts | 224 + .../test/common/model/textModel.test.ts | 26 +- .../common/model/textModelWithTokens.test.ts | 58 +- .../common/modes/languageSelector.test.ts | 87 +- .../services/editorSimpleWorker.test.ts | 23 +- .../test/common/services/modelService.test.ts | 6 +- .../viewLayout/editorLayoutProvider.test.ts | 93 +- .../viewLayout/viewLineRenderer.test.ts | 117 +- .../viewModel/splitLinesCollection.test.ts | 3 + .../common/viewModel/viewModelImpl.test.ts | 11 +- src/vs/monaco.d.ts | 179 +- src/vs/nls.mock.ts | 26 + .../actions/browser/menuItemActionItem.ts | 13 +- src/vs/platform/actions/common/actions.ts | 3 +- src/vs/platform/actions/common/menu.ts | 2 +- .../electron-main/backupMainService.test.ts | 100 +- .../electron-browser/broadcastService.ts | 4 +- src/vs/platform/commands/common/commands.ts | 2 +- .../configuration/common/configuration.ts | 7 +- .../common/configurationModels.ts | 45 +- .../common/configurationRegistry.ts | 51 +- .../configuration/node/configuration.ts | 4 +- .../node/configurationService.ts | 4 +- .../test/common/configurationModels.test.ts | 29 +- .../test/node/configurationService.test.ts | 108 +- .../contextkey/browser/contextKeyService.ts | 8 +- .../platform/contextkey/common/contextkey.ts | 13 +- .../contextkey/test/common/contextkey.test.ts | 3 +- .../contextview/browser/contextMenuService.ts | 2 +- .../contextview/browser/contextView.ts | 2 +- src/vs/platform/dialogs/common/choiceIpc.ts | 40 - src/vs/platform/dialogs/common/dialogIpc.ts | 46 + src/vs/platform/dialogs/common/dialogs.ts | 88 +- .../node/{choiceCli.ts => dialogService.ts} | 15 +- src/vs/platform/driver/common/driver.ts | 287 + .../driver/electron-browser/driver.ts | 204 + .../platform/driver/electron-main/driver.ts | 218 + src/vs/platform/driver/node/driver.ts | 17 + src/vs/platform/editor/common/editor.ts | 14 +- .../environment/common/environment.ts | 3 + src/vs/platform/environment/node/argv.ts | 9 +- .../environment/node/environmentService.ts | 2 + .../common/extensionEnablementService.ts | 75 +- .../common/extensionManagement.ts | 30 +- .../common/extensionManagementIpc.ts | 17 +- .../common/extensionManagementUtil.ts | 8 +- .../node/extensionGalleryService.ts | 19 +- .../node/extensionManagementService.ts | 344 +- .../common/extensionEnablementService.test.ts | 73 +- .../test/node/extensionGalleryService.test.ts | 8 +- .../extensions/node/extensionValidator.ts | 8 +- src/vs/platform/files/common/files.ts | 166 +- src/vs/platform/files/test/files.test.ts | 14 +- src/vs/platform/history/common/history.ts | 2 +- .../electron-main/historyMainService.ts | 2 +- .../test/common/instantiationService.test.ts | 20 +- .../integrity/node/integrityServiceImpl.ts | 38 +- src/vs/platform/issue/common/issue.ts | 27 +- src/vs/platform/issue/common/issueIpc.ts | 8 +- .../issue/electron-main/issueService.ts | 74 +- .../common/jsonContributionRegistry.ts | 4 +- .../common/abstractKeybindingService.ts | 2 +- .../platform/keybinding/common/keybinding.ts | 2 +- .../common/usLayoutResolvedKeybinding.ts | 3 +- .../common/abstractKeybindingService.test.ts | 2 +- .../test/common/mockKeybindingService.ts | 6 +- src/vs/platform/lifecycle/common/lifecycle.ts | 2 +- .../electron-browser/lifecycleService.ts | 2 +- .../lifecycle/electron-main/lifecycleMain.ts | 97 +- src/vs/platform/list/browser/listService.ts | 142 +- .../localizations/common/localizations.ts | 9 +- .../localizations/common/localizationsIpc.ts | 10 +- .../localizations/node/localizations.ts | 13 +- src/vs/platform/log/common/log.ts | 3 +- src/vs/platform/log/common/logIpc.ts | 2 +- src/vs/platform/log/node/spdlogService.ts | 10 +- .../platform/markers/common/markerService.ts | 62 +- src/vs/platform/markers/common/markers.ts | 59 +- .../markers/test/common/markerService.test.ts | 20 +- .../notification/common/notification.ts | 18 +- .../test/common/testNotificationService.ts | 34 + src/vs/platform/progress/common/progress.ts | 11 +- src/vs/platform/quickOpen/common/quickOpen.ts | 8 +- .../platform/quickinput/common/quickInput.ts | 23 + src/vs/platform/registry/common/platform.ts | 5 +- .../registry/test/common/platform.test.ts | 10 +- .../platform/request/node/requestService.ts | 2 +- src/vs/platform/search/common/search.ts | 9 +- src/vs/platform/state/node/stateService.ts | 2 +- src/vs/platform/state/test/node/state.test.ts | 15 +- .../platform/storage/common/storageService.ts | 6 +- .../telemetry/browser/errorTelemetry.ts | 64 +- .../platform/telemetry/common/experiments.ts | 1 - src/vs/platform/telemetry/common/telemetry.ts | 2 +- .../telemetry/common/telemetryService.ts | 59 +- .../telemetry/common/telemetryUtils.ts | 4 +- .../telemetry/node/commonProperties.ts | 10 +- .../node/workbenchCommonProperties.ts | 4 +- .../electron-browser/commonProperties.test.ts | 4 +- .../electron-browser/telemetryService.test.ts | 280 +- src/vs/platform/theme/common/colorRegistry.ts | 29 +- src/vs/platform/theme/common/styler.ts | 78 +- src/vs/platform/theme/common/themeService.ts | 6 +- .../theme/test/common/testThemeService.ts | 2 +- src/vs/platform/update/common/update.ts | 2 +- src/vs/platform/update/common/updateIpc.ts | 2 +- .../electron-main/abstractUpdateService.ts | 2 +- .../electron-main/updateService.darwin.ts | 4 +- .../electron-main/updateService.linux.ts | 4 +- .../electron-main/updateService.win32.ts | 4 +- .../update/node/update.config.contribution.ts | 9 +- src/vs/platform/url/common/url.ts | 12 +- src/vs/platform/url/common/urlIpc.ts | 78 +- src/vs/platform/url/common/urlService.ts | 54 + .../inactiveExtensionUrlHandler.ts | 149 + .../url/electron-main/electronUrlListener.ts | 70 + .../platform/url/electron-main/urlService.ts | 61 - src/vs/platform/windows/common/windows.ts | 30 +- src/vs/platform/windows/common/windowsIpc.ts | 2 +- .../windows/electron-browser/windowService.ts | 2 +- .../platform/windows/electron-main/windows.ts | 36 +- .../windows/electron-main/windowsService.ts | 58 +- src/vs/platform/workspace/common/workspace.ts | 2 +- .../platform/workspaces/common/workspaces.ts | 2 +- .../electron-main/workspacesMainService.ts | 6 +- .../workspacesMainService.test.ts | 82 +- src/vs/vscode.d.ts | 958 ++- src/vs/vscode.proposed.d.ts | 631 +- src/vs/workbench/api/browser/media/test.svg | 10 + .../browser/viewsContainersExtensionPoint.ts | 206 + .../api/browser/viewsExtensionPoint.ts | 51 +- .../extensionHost.contribution.ts | 3 + .../mainThreadDebugService.ts | 100 +- .../electron-browser/mainThreadDecorations.ts | 17 +- .../electron-browser/mainThreadDiagnostics.ts | 9 + .../api/electron-browser/mainThreadDialogs.ts | 2 + .../electron-browser/mainThreadDocuments.ts | 6 +- .../mainThreadDocumentsAndEditors.ts | 13 +- .../api/electron-browser/mainThreadEditor.ts | 6 +- .../api/electron-browser/mainThreadErrors.ts | 2 +- .../electron-browser/mainThreadFileSystem.ts | 213 +- .../electron-browser/mainThreadHeapService.ts | 4 +- .../mainThreadLanguageFeatures.ts | 53 +- .../mainThreadMessageService.ts | 25 +- .../electron-browser/mainThreadProgress.ts | 7 +- .../electron-browser/mainThreadQuickOpen.ts | 43 +- .../api/electron-browser/mainThreadSCM.ts | 2 +- .../mainThreadSaveParticipant.ts | 90 +- .../api/electron-browser/mainThreadSearch.ts | 148 + .../api/electron-browser/mainThreadTask.ts | 400 +- .../electron-browser/mainThreadTelemetry.ts | 2 +- .../mainThreadTerminalService.ts | 76 +- .../electron-browser/mainThreadTreeViews.ts | 30 +- .../api/electron-browser/mainThreadUrls.ts | 75 + .../api/electron-browser/mainThreadWebview.ts | 674 +- .../api/electron-browser/mainThreadWindow.ts | 4 +- src/vs/workbench/api/node/apiCommands.ts | 99 + src/vs/workbench/api/node/extHost.api.impl.ts | 201 +- src/vs/workbench/api/node/extHost.protocol.ts | 192 +- .../workbench/api/node/extHostApiCommands.ts | 340 +- src/vs/workbench/api/node/extHostCommands.ts | 20 +- .../api/node/extHostConfiguration.ts | 91 +- .../workbench/api/node/extHostDebugService.ts | 141 +- .../workbench/api/node/extHostDecorations.ts | 4 + .../workbench/api/node/extHostDiagnostics.ts | 118 +- .../node/extHostDocumentContentProviders.ts | 13 +- .../workbench/api/node/extHostDocumentData.ts | 5 +- .../node/extHostDocumentSaveParticipant.ts | 2 +- src/vs/workbench/api/node/extHostDocuments.ts | 3 +- .../api/node/extHostDocumentsAndEditors.ts | 25 +- .../api/node/extHostExtensionActivator.ts | 22 +- .../api/node/extHostExtensionService.ts | 23 +- .../workbench/api/node/extHostFileSystem.ts | 281 +- .../api/node/extHostFileSystemEventService.ts | 2 +- .../api/node/extHostLanguageFeatures.ts | 175 +- .../workbench/api/node/extHostLogService.ts | 42 +- .../api/node/extHostMessageService.ts | 2 +- src/vs/workbench/api/node/extHostProgress.ts | 68 +- src/vs/workbench/api/node/extHostQuickOpen.ts | 15 +- src/vs/workbench/api/node/extHostSCM.ts | 2 +- src/vs/workbench/api/node/extHostSearch.ts | 64 + src/vs/workbench/api/node/extHostTask.ts | 402 +- .../api/node/extHostTerminalService.ts | 205 +- .../workbench/api/node/extHostTextEditor.ts | 2 - .../workbench/api/node/extHostTextEditors.ts | 2 +- src/vs/workbench/api/node/extHostTreeViews.ts | 24 +- .../api/node/extHostTypeConverters.ts | 118 +- src/vs/workbench/api/node/extHostTypes.ts | 300 +- src/vs/workbench/api/node/extHostUrls.ts | 53 + src/vs/workbench/api/node/extHostWebview.ts | 302 +- src/vs/workbench/api/node/extHostWindow.ts | 2 +- src/vs/workbench/api/node/extHostWorkspace.ts | 19 +- src/vs/workbench/api/shared/tasks.ts | 94 + src/vs/workbench/browser/actions.ts | 2 +- .../actions/toggleActivityBarVisibility.ts | 2 +- .../browser/actions/toggleCenteredLayout.ts | 6 +- .../browser/actions/toggleEditorLayout.ts | 2 +- .../browser/actions/toggleSidebarPosition.ts | 2 +- .../actions/toggleSidebarVisibility.ts | 2 +- .../actions/toggleStatusbarVisibility.ts | 2 +- .../browser/actions/toggleTabsVisibility.ts | 2 +- .../browser/actions/toggleZenMode.ts | 2 +- .../browser/actions/workspaceActions.ts | 2 +- .../browser/actions/workspaceCommands.ts | 2 +- src/vs/workbench/browser/composite.ts | 24 +- src/vs/workbench/browser/dnd.ts | 6 +- src/vs/workbench/browser/labels.ts | 26 +- src/vs/workbench/browser/layout.ts | 100 +- src/vs/workbench/browser/media/part.css | 4 +- src/vs/workbench/browser/panel.ts | 2 +- src/vs/workbench/browser/part.ts | 25 +- .../parts/activitybar/activitybarActions.ts | 18 +- .../parts/activitybar/activitybarPart.ts | 54 +- .../activitybar/media/activitybarpart.css | 2 +- .../workbench/browser/parts/compositePart.ts | 78 +- .../parts/compositebar/compositeBar.ts | 110 +- .../parts/compositebar/compositeBarActions.ts | 10 +- .../browser/parts/editor/baseEditor.ts | 20 +- .../browser/parts/editor/binaryDiffEditor.ts | 2 +- .../browser/parts/editor/binaryEditor.ts | 59 +- .../parts/editor/editor.contribution.ts | 4 +- .../browser/parts/editor/editorActions.ts | 46 +- .../browser/parts/editor/editorCommands.ts | 10 +- .../parts/editor/editorGroupsControl.ts | 128 +- .../browser/parts/editor/editorPart.ts | 117 +- .../browser/parts/editor/editorPicker.ts | 4 +- .../browser/parts/editor/editorStatus.ts | 209 +- .../parts/editor/media/editorpicker.css | 2 +- .../parts/editor/media/editorstatus.css | 21 +- .../parts/editor/media/resourceviewer.css | 5 +- .../browser/parts/editor/media/tabstitle.css | 15 +- .../parts/editor/noTabsTitleControl.ts | 8 +- .../browser/parts/editor/rangeDecorations.ts | 6 +- .../browser/parts/editor/resourceViewer.ts | 119 +- .../browser/parts/editor/sideBySideEditor.ts | 30 +- .../browser/parts/editor/tabsTitleControl.ts | 26 +- .../browser/parts/editor/textDiffEditor.ts | 169 +- .../browser/parts/editor/textEditor.ts | 92 +- .../parts/editor/textResourceEditor.ts | 16 +- .../browser/parts/editor/titleControl.ts | 55 +- .../browser/parts/editor/webviewEditor.ts | 66 - .../media/notificationsActions.css | 8 +- .../notifications/notificationsCenter.ts | 35 +- .../parts/notifications/notificationsList.ts | 2 +- .../notifications/notificationsStatus.ts | 2 +- .../notifications/notificationsToasts.ts | 31 +- .../notifications/notificationsViewer.ts | 18 +- .../browser/parts/panel/media/panelpart.css | 6 +- .../browser/parts/panel/panelActions.ts | 2 +- .../browser/parts/panel/panelPart.ts | 33 +- .../browser/parts/quickinput/quickInput.css | 120 + .../browser/parts/quickinput/quickInput.ts | 526 ++ .../browser/parts/quickinput/quickInputBox.ts | 107 + .../quickinput/quickInputCheckboxList.ts | 389 + .../parts/quickopen/media/quickopen.css | 12 +- .../parts/quickopen/quickOpenController.ts | 46 +- .../parts/quickopen/quickopen.contribution.ts | 9 +- .../browser/parts/quickopen/quickopen.ts | 2 +- .../browser/parts/sidebar/sidebarPart.ts | 34 +- .../parts/statusbar/media/statusbarpart.css | 6 +- .../browser/parts/statusbar/statusbarPart.ts | 24 +- .../parts/titlebar/media/titlebarpart.css | 2 +- .../browser/parts/titlebar/titlebarPart.ts | 35 +- .../browser/parts/views/contributableViews.ts | 446 ++ .../browser/parts/views/customView.ts | 122 +- .../browser/parts/views/customViewPanel.ts | 8 +- .../browser/parts/views/media/views.css | 7 +- .../browser/parts/views/panelViewlet.ts | 99 +- .../browser/parts/views/viewsViewlet.ts | 58 +- src/vs/workbench/browser/quickopen.ts | 10 +- src/vs/workbench/browser/viewlet.ts | 8 +- src/vs/workbench/common/actions.ts | 25 +- src/vs/workbench/common/editor.ts | 119 +- .../common/editor/editorStacksModel.ts | 50 +- .../common/editor/untitledEditorInput.ts | 12 +- .../common/editor/untitledEditorModel.ts | 8 +- src/vs/workbench/common/memento.ts | 2 +- src/vs/workbench/common/notifications.ts | 2 +- src/vs/workbench/common/resources.ts | 5 +- src/vs/workbench/common/theme.ts | 4 +- src/vs/workbench/common/views.ts | 40 +- src/vs/workbench/electron-browser/actions.ts | 24 +- .../electron-browser/bootstrap/index.js | 12 +- src/vs/workbench/electron-browser/commands.ts | 34 +- .../electron-browser/main.contribution.ts | 69 +- src/vs/workbench/electron-browser/main.ts | 32 +- .../electron-browser/media/shell.css | 63 +- .../electron-browser/media/workbench.css | 10 +- .../workbench/electron-browser/resources.ts | 6 +- src/vs/workbench/electron-browser/shell.ts | 121 +- src/vs/workbench/electron-browser/window.ts | 26 +- .../workbench/electron-browser/workbench.ts | 130 +- src/vs/workbench/node/extensionHostMain.ts | 28 +- src/vs/workbench/node/extensionHostProcess.ts | 2 +- .../parts/backup/common/backupModelTracker.ts | 2 +- .../parts/backup/common/backupRestorer.ts | 2 +- .../parts/cache/node/nodeCachedDataManager.ts | 12 +- .../cli/electron-browser/cli.contribution.ts | 10 +- .../codeEditor/codeEditor.contribution.ts | 8 +- .../languageConfigurationExtensionPoint.ts | 2 +- .../textMate/inspectTMScopes.css | 5 - .../workbenchReferenceSearch.ts | 53 + .../parts/debug/browser/baseDebugView.ts | 7 +- .../parts/debug/browser/breakpointWidget.ts | 165 - .../parts/debug/browser/breakpointsView.ts | 33 +- .../parts/debug/browser/debugActionItems.ts | 24 +- .../parts/debug/browser/debugActions.ts | 149 +- .../parts/debug/browser/debugActionsWidget.ts | 47 +- .../parts/debug/browser/debugCommands.ts | 28 +- .../debug/browser/debugContentProvider.ts | 4 +- .../parts/debug/browser/debugEditorActions.ts | 68 +- .../parts/debug/browser/debugQuickOpen.ts | 15 +- .../parts/debug/browser/debugStatus.ts | 12 +- .../parts/debug/browser/debugViewlet.ts | 50 +- .../parts/debug/browser/media/add-focus.svg | 2 +- .../parts/debug/browser/media/add-inverse.svg | 2 +- .../parts/debug/browser/media/add.svg | 2 +- .../media/breakpoint-conditional-dark.svg | 10 - .../media/breakpoint-conditional-disabled.svg | 1 + .../breakpoint-conditional-unverified.svg | 1 + .../browser/media/breakpoint-conditional.svg | 11 +- .../debug/browser/media/breakpoint-dark.svg | 1 - .../media/breakpoint-disabled-dark.svg | 1 - .../browser/media/breakpoint-disabled.svg | 2 +- .../media/breakpoint-function-dark.svg | 1 - .../breakpoint-function-disabled-dark.svg | 1 - .../media/breakpoint-function-disabled.svg | 2 +- .../breakpoint-function-unverified-dark.svg | 1 - .../media/breakpoint-function-unverified.svg | 2 +- .../browser/media/breakpoint-function.svg | 2 +- .../debug/browser/media/breakpoint-hint.svg | 2 +- .../browser/media/breakpoint-log-disabled.svg | 1 + .../media/breakpoint-log-unverified.svg | 1 + .../debug/browser/media/breakpoint-log.svg | 1 + .../media/breakpoint-unsupported-dark.svg | 17 - .../browser/media/breakpoint-unsupported.svg | 18 +- .../media/breakpoint-unverified-dark.svg | 1 - .../browser/media/breakpoint-unverified.svg | 2 +- .../parts/debug/browser/media/breakpoint.svg | 2 +- .../debug/browser/media/breakpointWidget.css | 25 +- .../media/breakpoints-activate-inverse.svg | 2 +- .../browser/media/breakpoints-activate.svg | 2 +- .../browser/media/clear-repl-inverse.svg | 2 +- .../parts/debug/browser/media/clear-repl.svg | 2 +- .../debug/browser/media/configure-inverse.svg | 2 +- .../parts/debug/browser/media/configure.svg | 2 +- .../debug/browser/media/continue-inverse.svg | 4 +- .../parts/debug/browser/media/continue.svg | 2 +- .../browser/media/current-and-breakpoint.svg | 2 +- .../debug/browser/media/current-arrow.svg | 2 +- .../parts/debug/browser/media/debug-dark.svg | 2 +- .../browser/media/debug.contribution.css | 88 +- .../browser/media/debugActionsWidget.css | 5 +- .../parts/debug/browser/media/debugHover.css | 4 +- .../debug/browser/media/debugViewlet.css | 14 +- .../browser/media/disconnect-inverse.svg | 2 +- .../parts/debug/browser/media/disconnect.svg | 2 +- .../parts/debug/browser/media/drag.svg | 9 +- .../debug/browser/media/exceptionWidget.css | 5 - .../debug/browser/media/pause-inverse.svg | 2 +- .../parts/debug/browser/media/pause.svg | 2 +- .../browser/media/remove-all-inverse.svg | 2 +- .../parts/debug/browser/media/remove-all.svg | 2 +- .../debug/browser/media/remove-focus.svg | 2 +- .../debug/browser/media/remove-inverse.svg | 2 +- .../parts/debug/browser/media/remove.svg | 2 +- .../debug/browser/media/repl-inverse.svg | 2 +- .../parts/debug/browser/media/repl.css | 3 +- .../parts/debug/browser/media/repl.svg | 2 +- .../debug/browser/media/restart-inverse.svg | 2 +- .../parts/debug/browser/media/restart.svg | 2 +- .../media/stackframe-and-breakpoint-dark.svg | 1 - .../media/stackframe-and-breakpoint.svg | 2 +- .../browser/media/stackframe-arrow-dark.svg | 1 - .../debug/browser/media/stackframe-arrow.svg | 2 +- .../debug/browser/media/step-into-inverse.svg | 2 +- .../parts/debug/browser/media/step-into.svg | 2 +- .../debug/browser/media/step-out-inverse.svg | 2 +- .../parts/debug/browser/media/step-out.svg | 2 +- .../debug/browser/media/step-over-inverse.svg | 2 +- .../parts/debug/browser/media/step-over.svg | 2 +- .../debug/browser/media/stop-inverse.svg | 2 +- .../parts/debug/browser/media/stop.svg | 2 +- .../debug/browser/statusbarColorProvider.ts | 30 +- src/vs/workbench/parts/debug/common/debug.ts | 160 +- .../parts/debug/common/debugModel.ts | 164 +- .../parts/debug/common/debugProtocol.d.ts | 107 +- .../parts/debug/common/debugSource.ts | 17 +- .../parts/debug/common/debugViewModel.ts | 8 +- .../electron-browser/breakpointWidget.ts | 336 + .../debug/electron-browser/callStackView.ts | 8 +- .../electron-browser/debug.contribution.ts | 12 +- .../debugConfigurationManager.ts | 276 +- .../debugEditorContribution.ts | 144 +- .../debug/electron-browser/debugHover.ts | 17 +- .../debug/electron-browser/debugService.ts | 197 +- .../electron-browser/electronDebugActions.ts | 19 +- .../debug/electron-browser/rawDebugSession.ts | 295 +- .../parts/debug/electron-browser/repl.ts | 53 +- .../debug/electron-browser/replViewer.ts | 23 +- .../{replEditor.ts => simpleDebugEditor.ts} | 33 +- .../debug/electron-browser/terminalSupport.ts | 58 +- .../debug/electron-browser/variablesView.ts | 4 +- .../parts/debug/node/debugAdapter.ts | 699 +- src/vs/workbench/parts/debug/node/debugger.ts | 239 + .../workbench/parts/debug/node/terminals.ts | 260 + .../workbench/parts/debug/node/v8Protocol.ts | 155 - .../debug/test/common/debugUtils.test.ts | 4 +- .../parts/debug/test/common/mockDebug.ts | 13 +- .../debug/test/node/debugAdapter.test.ts | 141 - .../parts/debug/test/node/debugger.test.ts | 182 + .../browser/actions/showEmmetCommands.ts | 2 +- .../actions/expandAbbreviation.ts | 4 +- .../test/electron-browser/emmetAction.test.ts | 2 +- .../execution.contribution.ts | 23 +- .../execution/electron-browser/terminal.ts | 7 +- .../electron-browser/terminalService.ts | 10 +- .../extensions/browser/dependenciesViewer.ts | 4 +- .../extensions/browser/extensionsActions.ts | 229 +- .../extensions/browser/extensionsList.ts | 8 +- .../extensions/browser/extensionsQuickOpen.ts | 2 +- .../browser/media/extensionActions.css | 3 + .../parts/extensions/common/extensions.ts | 2 +- .../extensionEditor.ts | 43 +- .../extensionProfileService.ts | 12 +- .../electron-browser/extensionTipsService.ts | 291 +- .../extensions.contribution.ts | 17 +- .../electron-browser/extensionsActions.ts | 47 +- .../electron-browser/extensionsUtils.ts | 100 +- .../electron-browser/extensionsViewlet.ts | 183 +- .../electron-browser/extensionsViews.ts | 99 +- .../media/extensionEditor.css | 3 +- .../media/extensionsViewlet.css | 12 +- .../media/markdown.css | 0 .../media/runtimeExtensionsEditor.css | 8 - .../runtimeExtensionsEditor.ts | 36 +- .../node/extensionsWorkbenchService.ts | 208 +- .../extensionsActions.test.ts | 3 +- .../extensionsTipsService.test.ts | 15 +- .../extensionsWorkbenchService.test.ts | 26 +- .../feedback/electron-browser/feedback.ts | 107 +- .../electron-browser/feedbackStatusbarItem.ts | 19 +- .../electron-browser/media/feedback.css | 49 +- .../files/browser/editors/binaryFileEditor.ts | 41 +- .../browser/editors/fileEditorTracker.ts | 52 +- .../files/browser/editors/textFileEditor.ts | 40 +- src/vs/workbench/parts/files/browser/files.ts | 51 +- .../parts/files/common/dirtyFilesTracker.ts | 6 +- .../files/common/editors/fileEditorInput.ts | 40 +- .../parts/files/common/explorerModel.ts | 193 +- src/vs/workbench/parts/files/common/files.ts | 20 +- .../files/electron-browser/explorerViewlet.ts | 18 +- .../fileActions.contribution.ts | 12 +- .../files/electron-browser/fileActions.ts | 375 +- .../files/electron-browser/fileCommands.ts | 74 +- .../electron-browser/files.contribution.ts | 18 +- .../media/explorerviewlet.css | 1 - .../electron-browser/saveErrorHandler.ts | 12 +- .../files/electron-browser/views/emptyView.ts | 8 +- .../views/explorerDecorationsProvider.ts | 4 +- .../electron-browser/views/explorerView.ts | 125 +- .../electron-browser/views/explorerViewer.ts | 290 +- .../electron-browser/views/openEditorsView.ts | 4 +- .../test/browser/fileEditorInput.test.ts | 42 +- .../test/browser/fileEditorTracker.test.ts | 8 +- .../electron-browser/explorerModel.test.ts | 88 +- .../workbench/parts/html/common/htmlInput.ts | 8 +- .../html.contribution.ts | 7 +- .../htmlPreviewPart.ts | 109 +- .../browser/localizations.contribution.ts | 110 - .../localizations.contribution.ts | 217 + .../localizationsActions.ts | 0 .../electron-browser/logs.contribution.ts | 2 +- .../markers/browser/markersPanelActions.ts | 151 - .../markers/browser/markersTreeViewer.ts | 230 - .../browser/markersWorkbenchContributions.ts | 82 - .../workbench/parts/markers/common/markers.ts | 65 - .../parts/markers/common/markersModel.ts | 351 - .../{common => electron-browser}/constants.ts | 4 +- .../electron-browser/markers.contribution.ts | 214 + .../parts/markers/electron-browser/markers.ts | 133 + .../markersElectronContributions.ts | 128 - .../markersFileDecorations.ts | 12 +- .../markers/electron-browser/markersModel.ts | 376 + .../markersPanel.ts | 201 +- .../electron-browser/markersPanelActions.ts | 294 + .../markersTreeController.ts | 9 +- .../electron-browser/markersTreeViewer.ts | 269 + .../media/excludeSettings-dark.svg | 1 + .../media/excludeSettings.svg | 1 + .../media/markers.css | 66 +- .../media/status-error-inverse.svg | 0 .../media/status-error.svg | 0 .../media/status-info-inverse.svg | 0 .../media/status-info.svg | 0 .../media/status-warning-inverse.svg | 0 .../media/status-warning.svg | 0 .../{common => electron-browser}/messages.ts | 46 +- .../parts/markers/markers.contribution.ts | 11 - .../markersModel.test.ts | 119 +- .../output/browser/media/open_log_file.svg | 1 + .../browser/media/open_log_file_inverse.svg | 0 .../parts/output/browser/media/output.css | 9 + .../parts/output/browser/outputActions.ts | 94 +- .../parts/output/browser/outputPanel.ts | 12 +- .../workbench/parts/output/common/output.ts | 8 +- .../parts/output/common/outputLinkComputer.ts | 19 +- .../electron-browser/output.contribution.ts | 18 +- .../output/electron-browser/outputServices.ts | 46 +- .../output/test/outputLinkProvider.test.ts | 20 +- .../electron-browser/startupProfiler.ts | 12 +- .../preferences/browser/keybindingWidgets.ts | 13 +- .../preferences/browser/keybindingsEditor.ts | 90 +- .../browser/keybindingsEditorContribution.ts | 2 +- .../preferences/browser/media/preferences.css | 7 +- .../preferences/browser/preferencesActions.ts | 20 +- .../preferences/browser/preferencesEditor.ts | 139 +- .../browser/preferencesRenderers.ts | 198 +- .../preferences/browser/preferencesWidgets.ts | 30 +- .../parts/preferences/common/preferences.ts | 189 +- .../common/preferencesContribution.ts | 4 +- .../preferences.contribution.ts | 16 +- .../electron-browser/preferencesSearch.ts | 7 +- .../quickopen/browser/commandsHandler.ts | 6 +- .../quickopen/browser/gotoLineHandler.ts | 2 +- .../quickopen/browser/gotoSymbolHandler.ts | 10 +- .../parts/quickopen/browser/helpHandler.ts | 8 +- .../browser/media/gotoSymbolHandler.css | 204 +- .../browser/quickopen.contribution.ts | 6 +- .../quickopen/browser/viewPickerHandler.ts | 21 +- .../relauncher.contribution.ts | 66 +- .../electron-browser/dirtydiffDecorator.ts | 37 +- .../scm/electron-browser/scm.contribution.ts | 6 +- .../parts/scm/electron-browser/scmMenus.ts | 2 +- .../parts/scm/electron-browser/scmViewlet.ts | 252 +- .../parts/search/browser/media/searchview.css | 52 +- .../search/browser/openAnythingHandler.ts | 4 +- .../parts/search/browser/openFileHandler.ts | 8 +- .../parts/search/browser/openSymbolHandler.ts | 10 +- .../search/browser/patternInputWidget.ts | 17 +- .../parts/search/browser/replaceService.ts | 13 +- .../parts/search/browser/searchActions.ts | 206 +- .../parts/search/browser/searchResultsView.ts | 52 +- .../parts/search/browser/searchView.ts | 135 +- .../browser/searchViewLocationUpdater.ts | 1 - .../parts/search/browser/searchWidget.ts | 40 +- .../parts/search/common/constants.ts | 10 +- .../parts/search/common/queryBuilder.ts | 24 +- .../parts/search/common/searchModel.ts | 41 +- .../electron-browser/search.contribution.ts | 177 +- .../search/test/browser/searchActions.test.ts | 4 +- .../search/test/common/queryBuilder.test.ts | 45 + .../search/test/common/searchModel.test.ts | 47 +- .../electron-browser/tabCompletion.ts | 2 +- .../parts/stats/node/workspaceStats.ts | 230 +- .../languageSurveys.contribution.ts | 59 +- .../electron-browser/nps.contribution.ts | 36 +- .../parts/tasks/browser/quickOpen.ts | 2 +- .../parts/tasks/browser/taskQuickOpen.ts | 6 +- .../parts/tasks/common/problemCollectors.ts | 25 +- .../parts/tasks/common/problemMatcher.ts | 65 +- .../tasks/common/taskDefinitionRegistry.ts | 4 +- .../parts/tasks/common/taskService.ts | 13 +- .../parts/tasks/common/taskSystem.ts | 6 +- src/vs/workbench/parts/tasks/common/tasks.ts | 138 +- .../tasks/electron-browser/jsonSchema_v2.ts | 71 + .../electron-browser/task.contribution.ts | 233 +- .../electron-browser/terminalTaskSystem.ts | 270 +- .../parts/tasks/node/processRunnerDetector.ts | 15 +- .../parts/tasks/node/processTaskSystem.ts | 18 +- .../parts/tasks/node/taskConfiguration.ts | 163 +- .../tasks/test/common/problemMatcher.test.ts | 3 +- .../terminalFindWidget.ts | 0 .../terminal/browser/terminalQuickOpen.ts | 3 +- .../terminalTab.ts | 60 +- .../parts/terminal/common/terminal.ts | 120 +- .../terminalColorRegistry.ts | 1 - .../terminalCommands.ts | 0 .../parts/terminal/common/terminalService.ts | 46 +- .../electron-browser/media/terminal.css | 17 +- .../terminal/electron-browser/media/xterm.css | 10 +- .../electron-browser/terminal.contribution.ts | 72 +- .../electron-browser/terminalActions.ts | 165 +- .../electron-browser/terminalConfigHelper.ts | 28 +- .../electron-browser/terminalInstance.ts | 525 +- .../electron-browser/terminalPanel.ts | 107 +- .../terminalProcessManager.ts | 207 + .../electron-browser/terminalService.ts | 84 +- .../{electron-browser => node}/terminal.ts | 28 +- .../terminal/node/terminalCommandTracker.ts | 156 + .../terminal/node/terminalEnvironment.ts | 182 + .../parts/terminal/node/terminalProcess.ts | 7 +- .../node/terminalProcessExtHostProxy.ts | 78 + .../windowsShellHelper.ts | 59 +- .../terminalColorRegistry.test.ts | 6 +- .../terminalConfigHelper.test.ts | 4 +- .../electron-browser/terminalInstance.test.ts | 215 - .../terminalLinkHandler.test.ts | 2 - .../electron-browser/terminalPanel.test.ts | 22 - .../test/node/terminalCommandTracker.test.ts | 114 + .../test/node/terminalEnvironment.test.ts | 178 + .../electron-browser/themes.contribution.ts | 14 +- .../themes.test.contribution.ts | 4 +- ...supportedWorkspaceSettings.contribution.ts | 80 - .../update/electron-browser/media/update.svg | 2 +- .../electron-browser/releaseNotesEditor.ts | 218 +- .../electron-browser/releaseNotesInput.ts | 52 - .../electron-browser/update.contribution.ts | 14 - .../parts/update/electron-browser/update.ts | 248 +- .../url/electron-browser/url.contribution.ts | 39 + .../watermark/electron-browser/watermark.ts | 4 +- .../electron-browser/baseWebviewEditor.ts} | 25 +- .../electron-browser}/webview-pre.js | 68 +- .../electron-browser}/webview.contribution.ts | 54 +- .../electron-browser}/webview.html | 0 .../electron-browser}/webviewCommands.ts | 75 +- .../webview/electron-browser/webviewEditor.ts | 242 + .../electron-browser/webviewEditorInput.ts | 230 + .../webviewEditorInputFactory.ts | 57 + .../electron-browser/webviewEditorService.ts | 178 + .../electron-browser/webviewElement.ts} | 62 +- .../electron-browser}/webviewFindWidget.ts | 4 +- .../gettingStarted.contribution.ts | 4 + .../electron-browser/gettingStarted.ts | 17 +- .../overlay/browser/welcomeOverlay.css | 10 +- .../welcome/overlay/browser/welcomeOverlay.ts | 7 + .../electron-browser/vs_code_welcome_page.ts | 4 +- .../page/electron-browser/welcomePage.css | 43 +- .../page/electron-browser/welcomePage.ts | 33 +- .../editor/vs_code_editor_walkthrough.md | 2 +- .../walkThrough.contribution.ts | 14 +- .../electron-browser/walkThroughPart.css | 1 - .../electron-browser/walkThroughPart.ts | 98 +- .../actions/test/common/menuService.test.ts | 2 +- .../backupFileService.test.ts | 139 +- .../commands/common/commandService.ts | 4 +- .../test/common/commandService.test.ts | 2 +- .../configuration/common/configuration.ts | 8 +- .../common/configurationExtensionPoint.ts | 18 +- .../common/configurationModels.ts | 67 +- .../configuration/node/configuration.ts | 462 +- .../node/configurationEditingService.ts | 97 +- .../node/configurationService.ts | 132 +- .../test/common/configurationModels.test.ts | 34 +- .../configurationEditingService.test.ts | 46 +- .../configurationService.test.ts | 16 +- .../common/configurationResolver.ts | 4 +- .../configurationResolverService.ts | 298 +- .../node/variableResolver.ts | 218 + .../configurationResolverService.test.ts | 49 +- .../electron-browser/contextmenuService.ts | 4 +- .../electron-browser/crashReporterService.ts | 6 +- .../decorations/browser/decorations.ts | 5 +- .../decorations/browser/decorationsService.ts | 31 +- .../test/browser/decorationsService.test.ts | 48 +- .../dialogs/electron-browser/dialogService.ts | 144 + .../dialogs/electron-browser/dialogs.ts | 241 - .../services/editor/common/editorService.ts | 2 +- .../editor/test/browser/editorService.test.ts | 2 +- .../services/extensions/common/extensions.ts | 2 +- .../extensions/common/extensionsRegistry.ts | 41 +- .../electron-browser/extensionHost.ts | 29 +- .../electron-browser/extensionService.ts | 402 +- .../node/extensionDescriptionRegistry.ts | 6 + .../extensions/node/extensionPoints.ts | 14 +- .../services/extensions/node/rpcProtocol.ts | 96 +- .../files/electron-browser/encoding.ts | 146 + .../files/electron-browser/fileService.ts | 1294 +++- .../electron-browser/remoteFileService.ts | 525 +- .../files/electron-browser/streams.ts | 168 + .../services/files/node/fileService.ts | 1296 ---- .../node/watcher/nsfw/nsfwWatcherService.ts | 4 +- .../nsfw/test/nsfwWatcherService.test.ts | 4 +- .../watcher/unix/chokidarWatcherService.ts | 25 +- .../watcher/win32/csharpWatcherService.ts | 6 +- .../fileService.test.ts | 621 +- .../fixtures/resolver/examples/company.js | 0 .../fixtures/resolver/examples/conway.js | 0 .../fixtures/resolver/examples/employee.js | 0 .../fixtures/resolver/examples/small.js | 0 .../fixtures/resolver/index.html | 0 .../fixtures/resolver/other/deep/company.js | 0 .../fixtures/resolver/other/deep/conway.js | 0 .../fixtures/resolver/other/deep/employee.js | 0 .../fixtures/resolver/other/deep/small.js | 0 .../fixtures/resolver/site.css | 0 .../fixtures/service/binary.txt | Bin .../fixtures/service/deep/company.js | 0 .../fixtures/service/deep/conway.js | 0 .../fixtures/service/deep/employee.js | 0 .../fixtures/service/deep/small.js | 0 .../fixtures/service/index.html | 0 .../fixtures/service/lorem.txt | 0 .../fixtures/service/small.txt | 0 .../fixtures/service/small_umlaut.txt | 0 .../fixtures/service/some_utf16le.css | Bin .../fixtures/service/some_utf8_bom.txt | 0 .../resolver.test.ts | 52 +- .../test/{node => electron-browser}/utils.ts | 0 .../watcher.test.ts | 8 +- .../services/group/common/groupService.ts | 2 +- .../history/electron-browser/history.ts | 2 +- .../workbench/services/issue/common/issue.ts | 1 + .../electron-browser/workbenchIssueService.ts | 20 +- .../common/jsonValidationExtensionPoint.ts | 6 +- .../common/macLinuxKeyboardMapper.ts | 3 + .../common/windowsKeyboardMapper.ts | 3 + .../electron-browser/keybindingService.ts | 12 +- .../keybindingEditing.test.ts | 36 +- .../test/keyboardMapperTestUtils.ts | 14 +- .../test/macLinuxKeyboardMapper.test.ts | 77 +- .../test/windowsKeyboardMapper.test.ts | 44 +- .../mode/common/workbenchModeService.ts | 2 +- .../common/notificationService.ts | 2 + .../services/panel/common/panelService.ts | 2 +- .../services/part/common/partService.ts | 12 +- .../preferences/browser/preferencesService.ts | 173 +- .../common/keybindingsEditorModel.ts | 40 +- .../preferences/common/preferences.ts | 164 + .../common/preferencesEditorInput.ts | 83 + .../preferences/common/preferencesModels.ts | 24 +- .../common/keybindingsEditorModel.test.ts | 24 +- .../progress/browser/media/progress.svg | 31 - .../browser/media/progressService2.css | 10 +- .../progress/browser/progressService.ts | 34 +- .../progress/browser/progressService2.ts | 124 +- .../progress/test/progressService.test.ts | 17 +- src/vs/workbench/services/scm/common/scm.ts | 2 +- .../services/scm/common/scmService.ts | 4 +- .../services/search/node/fileSearch.ts | 20 +- .../services/search/node/rawSearchService.ts | 18 +- .../services/search/node/ripgrepFileSearch.ts | 21 +- .../services/search/node/ripgrepTextSearch.ts | 14 +- .../services/search/node/searchService.ts | 4 +- .../search/node/worker/searchWorker.ts | 12 +- .../test/node/ripgrepTextSearch.test.ts | 36 +- .../services/search/test/node/search.test.ts | 24 +- .../search/test/node/searchService.test.ts | 37 +- .../test/node/textSearch.integrationTest.ts | 94 +- .../textMate/electron-browser/TMGrammars.ts | 12 + .../textMate/electron-browser/TMSyntax.ts | 49 +- .../electron-browser/textMateService.ts | 2 +- .../textfile/common/textFileEditorModel.ts | 153 +- .../common/textFileEditorModelManager.ts | 33 +- .../textfile/common/textFileService.ts | 18 +- .../services/textfile/common/textfiles.ts | 31 +- .../electron-browser/textFileService.ts | 63 +- .../textfile/test/textFileEditorModel.test.ts | 151 +- .../test/textFileEditorModelManager.test.ts | 45 +- .../textfile/test/textFileService.test.ts | 206 +- .../common/textModelResolverService.ts | 13 +- .../test/textModelResolverService.test.ts | 5 +- .../themes/common/colorExtensionPoint.ts | 2 +- .../themes/common/colorThemeSchema.ts | 6 +- .../themes/common/fileIconThemeSchema.ts | 4 +- .../themes/common/workbenchThemeService.ts | 2 +- .../themes/electron-browser/colorThemeData.ts | 10 +- .../electron-browser/colorThemeStore.ts | 8 +- .../electron-browser/fileIconThemeData.ts | 6 +- .../electron-browser/fileIconThemeStore.ts | 8 +- .../electron-browser/themeCompatibility.ts | 1 + .../electron-browser/workbenchThemeService.ts | 34 +- .../services/timer/common/timerService.ts | 46 +- .../untitled/common/untitledEditorService.ts | 12 +- .../services/viewlet/browser/viewlet.ts | 3 +- .../viewlet/browser/viewletService.ts | 3 +- .../workspace/node/workspaceEditingService.ts | 30 +- src/vs/workbench/test/browser/part.test.ts | 55 +- .../browser/parts/editor/baseEditor.test.ts | 10 +- .../parts/editor/editorStacksModel.test.ts | 12 +- .../parts/editor/rangeDecorations.test.ts | 2 +- .../parts/views/contributableViews.test.ts | 242 + .../workbench/test/browser/quickopen.test.ts | 4 +- src/vs/workbench/test/browser/viewlet.test.ts | 16 +- .../test/common/editor/editor.test.ts | 131 +- .../common/editor/editorDiffModel.test.ts | 6 +- .../test/common/editor/editorModel.test.ts | 13 +- .../test/common/editor/untitledEditor.test.ts | 48 +- .../api/extHostApiCommands.test.ts | 220 +- .../api/extHostCommands.test.ts | 4 +- .../api/extHostConfiguration.test.ts | 164 +- .../api/extHostDiagnostics.test.ts | 94 +- .../api/extHostDocumentData.test.ts | 6 + .../extHostDocumentSaveParticipant.test.ts | 17 +- .../api/extHostLanguageFeatures.test.ts | 45 +- .../api/extHostMessagerService.test.ts | 36 +- .../api/extHostTreeViews.test.ts | 29 +- .../electron-browser/api/extHostTypes.test.ts | 6 + .../api/extHostWebview.test.ts | 62 + .../api/mainThreadDocuments.test.ts | 4 +- .../api/mainThreadDocumentsAndEditors.test.ts | 19 +- .../api/mainThreadEditors.test.ts | 2 +- .../api/mainThreadSaveParticipant.test.ts | 46 +- .../textsearch.perf.integrationTest.ts | 6 +- .../workbench/test/workbenchTestServices.ts | 103 +- src/vs/workbench/workbench.main.ts | 13 +- test/README.md | 2 +- test/electron/index.js | 71 +- test/electron/renderer.html | 5 +- test/electron/renderer.js | 3 + test/smoke/.gitignore | 3 +- test/smoke/README.md | 37 +- test/smoke/package.json | 17 +- test/smoke/src/application.ts | 146 + .../src/areas/activitybar/activityBar.ts | 11 +- test/smoke/src/areas/css/css.test.ts | 37 +- test/smoke/src/areas/debug/debug.test.ts | 45 +- test/smoke/src/areas/debug/debug.ts | 145 +- test/smoke/src/areas/editor/editor.test.ts | 27 +- test/smoke/src/areas/editor/editor.ts | 191 +- test/smoke/src/areas/editor/editors.ts | 44 + test/smoke/src/areas/editor/peek.ts | 41 +- test/smoke/src/areas/editor/quickoutline.ts | 28 - .../smoke/src/areas/explorer/explorer.test.ts | 14 +- test/smoke/src/areas/explorer/explorer.ts | 25 +- .../src/areas/extensions/extensions.test.ts | 21 +- test/smoke/src/areas/extensions/extensions.ts | 32 +- test/smoke/src/areas/git/git.test.ts | 29 +- test/smoke/src/areas/git/scm.ts | 89 +- .../src/areas/multiroot/multiroot.test.ts | 15 +- .../src/areas/preferences/keybindings.ts | 26 +- .../src/areas/preferences/preferences.test.ts | 33 +- test/smoke/src/areas/preferences/settings.ts | 32 +- test/smoke/src/areas/problems/problems.ts | 30 +- test/smoke/src/areas/quickopen/quickopen.ts | 100 +- test/smoke/src/areas/search/search.test.ts | 16 +- test/smoke/src/areas/search/search.ts | 68 +- .../src/areas/statusbar/statusbar.test.ts | 24 +- test/smoke/src/areas/statusbar/statusbar.ts | 25 +- .../smoke/src/areas/terminal/terminal.test.ts | 41 +- test/smoke/src/areas/terminal/terminal.ts | 52 +- .../src/areas/workbench/data-loss.test.ts | 21 +- .../areas/workbench/data-migration.test.ts | 147 +- .../src/areas/workbench/localization.test.ts | 29 +- test/smoke/src/areas/workbench/viewlet.ts | 13 +- test/smoke/src/areas/workbench/workbench.ts | 78 +- test/smoke/src/helpers/screenshot.ts | 37 - test/smoke/src/helpers/utilities.ts | 53 - test/smoke/src/logger.ts | 42 + test/smoke/src/main.ts | 228 +- test/smoke/src/spectron/application.ts | 351 - test/smoke/src/spectron/client.ts | 204 - test/smoke/src/vscode/code.ts | 324 + .../smoke/src/vscode/driver.js | 16 +- test/smoke/test/mocha.opts | 2 +- test/smoke/tools/copy-driver-definition.js | 33 + test/smoke/yarn.lock | 1167 +-- tsfmt.json | 3 +- yarn.lock | 457 +- 3651 files changed, 74249 insertions(+), 48599 deletions(-) create mode 100644 .gitattributes create mode 100644 build/lib/standalone.js create mode 100644 build/lib/standalone.ts create mode 100644 build/lib/test/util.test.js create mode 100644 build/lib/test/util.test.ts create mode 100644 build/tfs/common/symbols.ts create mode 100644 build/tfs/continuous-build.yml create mode 100644 build/tfs/darwin/build.yml create mode 100644 build/tfs/linux/build.yml create mode 100755 build/tfs/linux/release2.sh create mode 100644 build/tfs/product-build.yml create mode 100644 build/tfs/win32/build.yml mode change 100644 => 100755 build/win32/OSSREADME.json create mode 100644 extensions/git/src/encoding.ts create mode 100644 extensions/git/src/protocolHandler.ts create mode 100644 extensions/git/src/typings/jschardet.d.ts rename extensions/{json => json-language-features}/.vscode/launch.json (100%) rename extensions/{json => json-language-features}/.vscode/tasks.json (100%) create mode 100644 extensions/json-language-features/.vscodeignore rename extensions/{json => json-language-features}/client/src/jsonMain.ts (81%) rename extensions/{json => json-language-features}/client/src/typings/ref.d.ts (100%) rename extensions/{json => json-language-features}/client/src/utils/hash.ts (100%) rename extensions/{json => json-language-features}/client/tsconfig.json (100%) rename extensions/{json => json-language-features}/icons/json.png (100%) create mode 100644 extensions/json-language-features/package.json create mode 100644 extensions/json-language-features/package.nls.json create mode 100644 extensions/json-language-features/server/.npmignore rename extensions/{json => json-language-features}/server/.vscode/launch.json (77%) create mode 100644 extensions/json-language-features/server/.vscode/tasks.json create mode 100644 extensions/json-language-features/server/README.md rename src/vs/workbench/parts/html/browser/media/htmlPreviewPart.css => extensions/json-language-features/server/bin/vscode-json-languageserver (86%) create mode 100644 extensions/json-language-features/server/package.json rename extensions/{json => json-language-features}/server/src/jsonServerMain.ts (68%) rename extensions/{json => json-language-features}/server/src/languageModelCache.ts (100%) create mode 100644 extensions/json-language-features/server/src/utils/runner.ts rename extensions/{json => json-language-features}/server/src/utils/strings.ts (100%) create mode 100644 extensions/json-language-features/server/test/mocha.opts rename extensions/{json => json-language-features}/server/tsconfig.json (100%) rename extensions/{json => json-language-features}/server/yarn.lock (56%) rename extensions/{json => json-language-features}/yarn.lock (57%) delete mode 100644 extensions/json/client/src/protocol/foldingProvider.proposed.ts delete mode 100644 extensions/json/server/.vscode/tasks.json delete mode 100644 extensions/json/server/package.json delete mode 100644 extensions/json/server/src/protocol/foldingProvider.proposed.ts delete mode 100644 extensions/json/server/src/utils/errors.ts delete mode 100644 extensions/markdown/.vscodeignore delete mode 100644 extensions/markdown/OSSREADME.json delete mode 100644 extensions/markdown/icon.png delete mode 100644 extensions/markdown/media/Preview.svg delete mode 100644 extensions/markdown/media/PreviewOnRightPane_16x.svg delete mode 100644 extensions/markdown/media/PreviewOnRightPane_16x_dark.svg delete mode 100644 extensions/markdown/media/Preview_inverse.svg delete mode 100644 extensions/markdown/media/ViewSource.svg delete mode 100644 extensions/markdown/media/csp.js delete mode 100644 extensions/markdown/media/loading.js delete mode 100644 extensions/markdown/media/main.js delete mode 100644 extensions/markdown/media/markdown.css delete mode 100644 extensions/markdown/media/tomorrow.css delete mode 100644 extensions/markdown/package.json delete mode 100644 extensions/markdown/package.nls.json delete mode 100644 extensions/markdown/schemas/package.schema.json delete mode 100644 extensions/markdown/src/commandManager.ts delete mode 100644 extensions/markdown/src/commands/index.ts delete mode 100644 extensions/markdown/src/commands/moveCursorToPosition.ts delete mode 100644 extensions/markdown/src/commands/onPreviewStyleLoadError.ts delete mode 100644 extensions/markdown/src/commands/openDocumentLink.ts delete mode 100644 extensions/markdown/src/commands/refreshPreview.ts delete mode 100644 extensions/markdown/src/commands/showPreview.ts delete mode 100644 extensions/markdown/src/commands/showPreviewSecuritySelector.ts delete mode 100644 extensions/markdown/src/commands/showSource.ts delete mode 100644 extensions/markdown/src/commands/toggleLock.ts delete mode 100644 extensions/markdown/src/extension.ts delete mode 100644 extensions/markdown/src/features/documentLinkProvider.ts delete mode 100644 extensions/markdown/src/features/documentSymbolProvider.ts delete mode 100644 extensions/markdown/src/features/preview.ts delete mode 100644 extensions/markdown/src/features/previewConfig.ts delete mode 100644 extensions/markdown/src/features/previewContentProvider.ts delete mode 100644 extensions/markdown/src/features/previewManager.ts delete mode 100644 extensions/markdown/src/logger.ts delete mode 100644 extensions/markdown/src/markdownEngine.ts delete mode 100644 extensions/markdown/src/markdownExtensions.ts delete mode 100644 extensions/markdown/src/security.ts delete mode 100644 extensions/markdown/src/tableOfContentsProvider.ts delete mode 100644 extensions/markdown/src/telemetryReporter.ts delete mode 100644 extensions/markdown/src/test/index.ts delete mode 100644 extensions/markdown/src/test/tableOfContentsProvider.test.ts delete mode 100644 extensions/markdown/src/typings/markdown-it-named-headers.d.ts delete mode 100644 extensions/markdown/src/typings/ref.d.ts delete mode 100644 extensions/markdown/src/util/file.ts delete mode 100644 extensions/markdown/src/util/topmostLineMonitor.ts delete mode 100644 extensions/markdown/tsconfig.json delete mode 100644 extensions/markdown/yarn.lock delete mode 100644 extensions/shellscript/.vscodeignore delete mode 100644 extensions/shellscript/OSSREADME.json delete mode 100644 extensions/shellscript/language-configuration.json delete mode 100644 extensions/shellscript/package.json delete mode 100644 extensions/shellscript/package.nls.json delete mode 100644 extensions/shellscript/syntaxes/Shell-Unix-Bash.tmLanguage.json delete mode 100644 extensions/shellscript/test/colorize-fixtures/test.sh delete mode 100644 extensions/shellscript/test/colorize-results/test_sh.json create mode 100644 extensions/theme-defaults/themes/dark_defaults.json create mode 100644 extensions/theme-defaults/themes/dark_plus.json create mode 100644 extensions/theme-defaults/themes/dark_vs.json create mode 100644 extensions/theme-defaults/themes/light_defaults.json create mode 100644 extensions/theme-defaults/themes/light_plus.json create mode 100644 extensions/theme-defaults/themes/light_vs.json rename extensions/theme-seti/{thirdpartynotices.txt => ThirdPartyNotices.txt} (100%) create mode 100644 i18n/chs/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/chs/extensions/css-language-features/package.i18n.json create mode 100644 i18n/chs/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/chs/extensions/html-language-features/package.i18n.json create mode 100644 i18n/chs/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/chs/extensions/json-language-features/package.i18n.json create mode 100644 i18n/chs/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/chs/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/chs/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/chs/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/chs/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/chs/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/chs/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/chs/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/chs/extensions/php-language-features/package.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/chs/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/chs/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/chs/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/chs/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/chs/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/chs/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/chs/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/chs/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/chs/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/chs/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/chs/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/chs/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/chs/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/chs/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/chs/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/chs/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/cht/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/cht/extensions/css-language-features/package.i18n.json create mode 100644 i18n/cht/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/cht/extensions/html-language-features/package.i18n.json create mode 100644 i18n/cht/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/cht/extensions/json-language-features/package.i18n.json create mode 100644 i18n/cht/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/cht/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/cht/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/cht/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/cht/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/cht/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/cht/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/cht/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/cht/extensions/php-language-features/package.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/cht/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/cht/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/cht/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/cht/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/cht/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/cht/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/cht/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/cht/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/cht/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/cht/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/cht/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/cht/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/cht/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/cht/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/cht/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/cht/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/deu/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/deu/extensions/css-language-features/package.i18n.json create mode 100644 i18n/deu/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/deu/extensions/html-language-features/package.i18n.json create mode 100644 i18n/deu/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/deu/extensions/json-language-features/package.i18n.json create mode 100644 i18n/deu/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/deu/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/deu/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/deu/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/deu/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/deu/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/deu/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/deu/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/deu/extensions/php-language-features/package.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/deu/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/deu/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/deu/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/deu/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/deu/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/deu/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/deu/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/deu/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/deu/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/deu/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/deu/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/deu/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/deu/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/deu/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/deu/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/deu/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/esn/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/esn/extensions/css-language-features/package.i18n.json create mode 100644 i18n/esn/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/esn/extensions/html-language-features/package.i18n.json create mode 100644 i18n/esn/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/esn/extensions/json-language-features/package.i18n.json create mode 100644 i18n/esn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/esn/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/esn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/esn/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/esn/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/esn/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/esn/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/esn/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/esn/extensions/php-language-features/package.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/esn/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/esn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/esn/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/esn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/esn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/esn/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/esn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/esn/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/esn/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/esn/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/esn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/esn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/esn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/esn/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/esn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/esn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/fra/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/fra/extensions/css-language-features/package.i18n.json create mode 100644 i18n/fra/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/fra/extensions/html-language-features/package.i18n.json create mode 100644 i18n/fra/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/fra/extensions/json-language-features/package.i18n.json create mode 100644 i18n/fra/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/fra/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/fra/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/fra/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/fra/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/fra/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/fra/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/fra/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/fra/extensions/php-language-features/package.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/fra/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/fra/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/fra/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/fra/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/fra/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/fra/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/fra/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/fra/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/fra/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/fra/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/fra/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/fra/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/fra/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/fra/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/fra/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/fra/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/hun/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/hun/extensions/css-language-features/package.i18n.json create mode 100644 i18n/hun/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/hun/extensions/html-language-features/package.i18n.json create mode 100644 i18n/hun/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/hun/extensions/json-language-features/package.i18n.json create mode 100644 i18n/hun/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/hun/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/hun/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/hun/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/hun/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/hun/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/hun/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/hun/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/hun/extensions/php-language-features/package.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/hun/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/hun/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/hun/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/hun/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/hun/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/hun/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/hun/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/hun/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/hun/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/hun/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/hun/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/hun/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/hun/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/hun/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/hun/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/hun/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/ita/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/ita/extensions/css-language-features/package.i18n.json create mode 100644 i18n/ita/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/ita/extensions/html-language-features/package.i18n.json create mode 100644 i18n/ita/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/ita/extensions/json-language-features/package.i18n.json create mode 100644 i18n/ita/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/ita/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/ita/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/ita/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/ita/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/ita/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/ita/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/ita/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/ita/extensions/php-language-features/package.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/ita/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/ita/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/ita/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/ita/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/ita/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/ita/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/ita/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/ita/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/ita/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/ita/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/ita/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/ita/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/ita/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/ita/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/ita/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/ita/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/jpn/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/jpn/extensions/css-language-features/package.i18n.json create mode 100644 i18n/jpn/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/jpn/extensions/html-language-features/package.i18n.json create mode 100644 i18n/jpn/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/jpn/extensions/json-language-features/package.i18n.json create mode 100644 i18n/jpn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/jpn/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/jpn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/jpn/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/jpn/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/jpn/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/jpn/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/jpn/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/jpn/extensions/php-language-features/package.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/jpn/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/jpn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/jpn/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/jpn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/jpn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/jpn/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/jpn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/jpn/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/jpn/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/jpn/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/jpn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/jpn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/kor/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/kor/extensions/css-language-features/package.i18n.json create mode 100644 i18n/kor/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/kor/extensions/html-language-features/package.i18n.json create mode 100644 i18n/kor/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/kor/extensions/json-language-features/package.i18n.json create mode 100644 i18n/kor/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/kor/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/kor/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/kor/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/kor/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/kor/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/kor/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/kor/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/kor/extensions/php-language-features/package.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/kor/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/kor/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/kor/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/kor/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/kor/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/kor/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/kor/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/kor/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/kor/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/kor/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/kor/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/kor/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/kor/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/kor/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/kor/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/kor/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/ptb/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/ptb/extensions/css-language-features/package.i18n.json create mode 100644 i18n/ptb/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/ptb/extensions/html-language-features/package.i18n.json create mode 100644 i18n/ptb/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/ptb/extensions/json-language-features/package.i18n.json create mode 100644 i18n/ptb/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/ptb/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/ptb/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/ptb/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/ptb/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/ptb/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/ptb/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/ptb/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/ptb/extensions/php-language-features/package.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/ptb/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/ptb/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/ptb/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/ptb/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/ptb/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/ptb/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/ptb/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/ptb/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/ptb/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/ptb/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/ptb/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/ptb/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/rus/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/rus/extensions/css-language-features/package.i18n.json create mode 100644 i18n/rus/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/rus/extensions/html-language-features/package.i18n.json create mode 100644 i18n/rus/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/rus/extensions/json-language-features/package.i18n.json create mode 100644 i18n/rus/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/rus/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/rus/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/rus/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/rus/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/rus/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/rus/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/rus/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/rus/extensions/php-language-features/package.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/rus/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/rus/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/rus/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/rus/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/rus/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/rus/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/rus/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/rus/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/rus/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/rus/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/rus/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/rus/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/rus/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/rus/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/rus/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/rus/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json create mode 100644 i18n/trk/extensions/css-language-features/client/out/cssMain.i18n.json create mode 100644 i18n/trk/extensions/css-language-features/package.i18n.json create mode 100644 i18n/trk/extensions/html-language-features/client/out/htmlMain.i18n.json create mode 100644 i18n/trk/extensions/html-language-features/package.i18n.json create mode 100644 i18n/trk/extensions/json-language-features/client/out/jsonMain.i18n.json create mode 100644 i18n/trk/extensions/json-language-features/package.i18n.json create mode 100644 i18n/trk/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json create mode 100644 i18n/trk/extensions/markdown-language-features/out/features/preview.i18n.json create mode 100644 i18n/trk/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json create mode 100644 i18n/trk/extensions/markdown-language-features/out/security.i18n.json create mode 100644 i18n/trk/extensions/markdown-language-features/package.i18n.json create mode 100644 i18n/trk/extensions/npm/out/npmView.i18n.json create mode 100644 i18n/trk/extensions/npm/out/tasks.i18n.json create mode 100644 i18n/trk/extensions/php-language-features/out/features/validationProvider.i18n.json create mode 100644 i18n/trk/extensions/php-language-features/package.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/commands.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/organizeImports.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/features/taskProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/api.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/logger.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/projectStatus.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/versionPicker.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/out/utils/versionProvider.i18n.json create mode 100644 i18n/trk/extensions/typescript-language-features/package.i18n.json create mode 100644 i18n/trk/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json create mode 100644 i18n/trk/src/vs/editor/common/commonCodeEditor.i18n.json create mode 100644 i18n/trk/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json create mode 100644 i18n/trk/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json create mode 100644 i18n/trk/src/vs/editor/contrib/message/messageController.i18n.json create mode 100644 i18n/trk/src/vs/editor/contrib/snippet/snippetVariables.i18n.json create mode 100644 i18n/trk/src/vs/platform/dialogs/common/dialogs.i18n.json create mode 100644 i18n/trk/src/vs/platform/dialogs/node/dialogService.i18n.json create mode 100644 i18n/trk/src/vs/platform/markers/common/markers.i18n.json create mode 100644 i18n/trk/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json create mode 100644 i18n/trk/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json create mode 100644 i18n/trk/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json create mode 100644 i18n/trk/src/vs/workbench/api/node/extHostProgress.i18n.json create mode 100644 i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json create mode 100644 i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/debug/node/debugger.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/debug/node/terminals.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json create mode 100644 i18n/trk/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/configuration/node/configurationService.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json create mode 100644 i18n/trk/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json rename src/typings/{nsfw.d.ts => vscode-nsfw.d.ts} (96%) rename src/typings/{windows-mutex.ts => windows-mutex.d.ts} (99%) delete mode 100644 src/vs/base/common/marked/raw.marked.js delete mode 100644 src/vs/base/common/winjs.base.raw.js delete mode 100644 src/vs/base/node/mime.ts delete mode 100644 src/vs/base/node/ps-win.ps1 rename src/vs/base/test/node/{mime => encoding}/fixtures/some.cp1252.txt (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.css.qwoff (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.json.png (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.pdf (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.png.txt (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.qwoff.txt (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.shiftjis.txt (100%) rename src/vs/base/test/node/{mime => encoding}/fixtures/some.xml.png (100%) create mode 100644 src/vs/base/test/node/encoding/fixtures/utf16_be_nobom.txt create mode 100644 src/vs/base/test/node/encoding/fixtures/utf16_le_nobom.txt delete mode 100644 src/vs/base/test/node/mime/mime.test.ts create mode 100644 src/vs/base/test/node/utils.ts create mode 100644 src/vs/code/electron-browser/issue/issueReporterUtil.ts create mode 100644 src/vs/code/electron-browser/processExplorer/media/processExplorer.css create mode 100644 src/vs/code/electron-browser/processExplorer/processExplorer.html create mode 100644 src/vs/code/electron-browser/processExplorer/processExplorer.js create mode 100644 src/vs/code/electron-browser/processExplorer/processExplorerMain.ts rename src/vs/code/test/node/fixtures/vscode_folder/_vscode/{keepfolder.txt => settings.json} (100%) rename src/vs/code/test/node/fixtures/vscode_folder/nested_vscode_folder/_vscode/{keepfolder.txt => settings.json} (100%) delete mode 100644 src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts delete mode 100644 src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts delete mode 100644 src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts delete mode 100644 src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts delete mode 100644 src/vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder.ts delete mode 100644 src/vs/editor/common/model/linesTextBuffer/textSource.ts rename src/vs/editor/contrib/{quickFix/quickFix.ts => codeAction/codeAction.ts} (59%) rename src/vs/editor/contrib/{quickFix/quickFixCommands.ts => codeAction/codeActionCommands.ts} (51%) create mode 100644 src/vs/editor/contrib/codeAction/codeActionContributions.ts rename src/vs/editor/contrib/{quickFix/quickFixModel.ts => codeAction/codeActionModel.ts} (66%) rename src/vs/editor/contrib/{quickFix => codeAction}/codeActionTrigger.ts (69%) rename src/vs/editor/contrib/{quickFix/quickFixWidget.ts => codeAction/codeActionWidget.ts} (88%) rename src/vs/editor/contrib/{quickFix => codeAction}/lightBulbWidget.css (100%) rename src/vs/editor/contrib/{quickFix => codeAction}/lightBulbWidget.ts (89%) rename src/vs/editor/contrib/{quickFix => codeAction}/lightbulb-dark.svg (100%) rename src/vs/editor/contrib/{quickFix => codeAction}/lightbulb.svg (100%) rename src/vs/editor/contrib/{quickFix/test/quickFix.test.ts => codeAction/test/codeAction.test.ts} (77%) rename src/vs/editor/contrib/{quickFix/test/quickFixModel.test.ts => codeAction/test/codeActionModel.test.ts} (91%) rename src/vs/editor/contrib/gotoError/{gotoError.css => gotoErrorWidget.css} (89%) create mode 100644 src/vs/editor/contrib/gotoError/gotoErrorWidget.ts create mode 100644 src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts create mode 100644 src/vs/editor/editor.api.ts create mode 100644 src/vs/editor/editor.worker.ts create mode 100644 src/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.ts delete mode 100644 src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts delete mode 100644 src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts create mode 100644 src/vs/nls.mock.ts delete mode 100644 src/vs/platform/dialogs/common/choiceIpc.ts create mode 100644 src/vs/platform/dialogs/common/dialogIpc.ts rename src/vs/platform/dialogs/node/{choiceCli.ts => dialogService.ts} (72%) create mode 100644 src/vs/platform/driver/common/driver.ts create mode 100644 src/vs/platform/driver/electron-browser/driver.ts create mode 100644 src/vs/platform/driver/electron-main/driver.ts create mode 100644 src/vs/platform/driver/node/driver.ts create mode 100644 src/vs/platform/notification/test/common/testNotificationService.ts create mode 100644 src/vs/platform/quickinput/common/quickInput.ts create mode 100644 src/vs/platform/url/common/urlService.ts create mode 100644 src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts create mode 100644 src/vs/platform/url/electron-main/electronUrlListener.ts delete mode 100644 src/vs/platform/url/electron-main/urlService.ts create mode 100644 src/vs/workbench/api/browser/media/test.svg create mode 100644 src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts create mode 100644 src/vs/workbench/api/electron-browser/mainThreadSearch.ts create mode 100644 src/vs/workbench/api/electron-browser/mainThreadUrls.ts create mode 100644 src/vs/workbench/api/node/apiCommands.ts create mode 100644 src/vs/workbench/api/node/extHostSearch.ts create mode 100644 src/vs/workbench/api/node/extHostUrls.ts create mode 100644 src/vs/workbench/api/shared/tasks.ts delete mode 100644 src/vs/workbench/browser/parts/editor/webviewEditor.ts create mode 100644 src/vs/workbench/browser/parts/quickinput/quickInput.css create mode 100644 src/vs/workbench/browser/parts/quickinput/quickInput.ts create mode 100644 src/vs/workbench/browser/parts/quickinput/quickInputBox.ts create mode 100644 src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts create mode 100644 src/vs/workbench/browser/parts/views/contributableViews.ts create mode 100644 src/vs/workbench/parts/codeEditor/electron-browser/workbenchReferenceSearch.ts delete mode 100644 src/vs/workbench/parts/debug/browser/breakpointWidget.ts delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-dark.svg create mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-disabled.svg create mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-unverified.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-disabled-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-function-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified-dark.svg create mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-log-disabled.svg create mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-log-unverified.svg create mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-log.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/breakpoint-unverified-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint-dark.svg delete mode 100644 src/vs/workbench/parts/debug/browser/media/stackframe-arrow-dark.svg create mode 100644 src/vs/workbench/parts/debug/electron-browser/breakpointWidget.ts rename src/vs/workbench/parts/debug/electron-browser/{replEditor.ts => simpleDebugEditor.ts} (70%) create mode 100644 src/vs/workbench/parts/debug/node/debugger.ts create mode 100644 src/vs/workbench/parts/debug/node/terminals.ts delete mode 100644 src/vs/workbench/parts/debug/node/v8Protocol.ts delete mode 100644 src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts create mode 100644 src/vs/workbench/parts/debug/test/node/debugger.test.ts rename src/vs/workbench/parts/extensions/{browser => electron-browser}/extensionEditor.ts (95%) rename src/vs/workbench/parts/extensions/{browser => electron-browser}/media/extensionEditor.css (99%) rename src/vs/workbench/parts/extensions/{browser => electron-browser}/media/markdown.css (100%) rename src/vs/workbench/parts/html/{browser => electron-browser}/html.contribution.ts (94%) rename src/vs/workbench/parts/html/{browser => electron-browser}/htmlPreviewPart.ts (66%) delete mode 100644 src/vs/workbench/parts/localizations/browser/localizations.contribution.ts create mode 100644 src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts rename src/vs/workbench/parts/localizations/{browser => electron-browser}/localizationsActions.ts (100%) delete mode 100644 src/vs/workbench/parts/markers/browser/markersPanelActions.ts delete mode 100644 src/vs/workbench/parts/markers/browser/markersTreeViewer.ts delete mode 100644 src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts delete mode 100644 src/vs/workbench/parts/markers/common/markers.ts delete mode 100644 src/vs/workbench/parts/markers/common/markersModel.ts rename src/vs/workbench/parts/markers/{common => electron-browser}/constants.ts (79%) create mode 100644 src/vs/workbench/parts/markers/electron-browser/markers.contribution.ts create mode 100644 src/vs/workbench/parts/markers/electron-browser/markers.ts delete mode 100644 src/vs/workbench/parts/markers/electron-browser/markersElectronContributions.ts rename src/vs/workbench/parts/markers/{browser => electron-browser}/markersFileDecorations.ts (91%) create mode 100644 src/vs/workbench/parts/markers/electron-browser/markersModel.ts rename src/vs/workbench/parts/markers/{browser => electron-browser}/markersPanel.ts (60%) create mode 100644 src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts rename src/vs/workbench/parts/markers/{browser => electron-browser}/markersTreeController.ts (92%) create mode 100644 src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts create mode 100755 src/vs/workbench/parts/markers/electron-browser/media/excludeSettings-dark.svg create mode 100755 src/vs/workbench/parts/markers/electron-browser/media/excludeSettings.svg rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/markers.css (64%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-error-inverse.svg (100%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-error.svg (100%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-info-inverse.svg (100%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-info.svg (100%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-warning-inverse.svg (100%) rename src/vs/workbench/parts/markers/{browser => electron-browser}/media/status-warning.svg (100%) rename src/vs/workbench/parts/markers/{common => electron-browser}/messages.ts (55%) delete mode 100644 src/vs/workbench/parts/markers/markers.contribution.ts rename src/vs/workbench/parts/markers/test/{common => electron-browser}/markersModel.test.ts (52%) create mode 100644 src/vs/workbench/parts/output/browser/media/open_log_file.svg rename extensions/markdown/media/ViewSource_inverse.svg => src/vs/workbench/parts/output/browser/media/open_log_file_inverse.svg (100%) rename src/vs/workbench/parts/terminal/{electron-browser => browser}/terminalFindWidget.ts (100%) rename src/vs/workbench/parts/terminal/{electron-browser => browser}/terminalTab.ts (89%) rename src/vs/workbench/parts/terminal/{electron-browser => common}/terminalColorRegistry.ts (99%) rename src/vs/workbench/parts/terminal/{electron-browser => common}/terminalCommands.ts (100%) create mode 100644 src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts rename src/vs/workbench/parts/terminal/{electron-browser => node}/terminal.ts (74%) create mode 100644 src/vs/workbench/parts/terminal/node/terminalCommandTracker.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminalEnvironment.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts rename src/vs/workbench/parts/terminal/{electron-browser => node}/windowsShellHelper.ts (68%) delete mode 100644 src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts delete mode 100644 src/vs/workbench/parts/terminal/test/electron-browser/terminalPanel.test.ts create mode 100644 src/vs/workbench/parts/terminal/test/node/terminalCommandTracker.test.ts create mode 100644 src/vs/workbench/parts/terminal/test/node/terminalEnvironment.test.ts delete mode 100644 src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts delete mode 100644 src/vs/workbench/parts/update/electron-browser/releaseNotesInput.ts create mode 100644 src/vs/workbench/parts/url/electron-browser/url.contribution.ts rename src/vs/workbench/parts/{html/browser/webviewEditor.ts => webview/electron-browser/baseWebviewEditor.ts} (78%) rename src/vs/workbench/parts/{html/browser => webview/electron-browser}/webview-pre.js (86%) rename src/vs/workbench/parts/{html/browser => webview/electron-browser}/webview.contribution.ts (50%) rename src/vs/workbench/parts/{html/browser => webview/electron-browser}/webview.html (100%) rename src/vs/workbench/parts/{html/browser => webview/electron-browser}/webviewCommands.ts (61%) create mode 100644 src/vs/workbench/parts/webview/electron-browser/webviewEditor.ts create mode 100644 src/vs/workbench/parts/webview/electron-browser/webviewEditorInput.ts create mode 100644 src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts create mode 100644 src/vs/workbench/parts/webview/electron-browser/webviewEditorService.ts rename src/vs/workbench/parts/{html/browser/webview.ts => webview/electron-browser/webviewElement.ts} (91%) rename src/vs/workbench/parts/{html/browser => webview/electron-browser}/webviewFindWidget.ts (93%) rename src/vs/workbench/services/backup/test/{node => electron-browser}/backupFileService.test.ts (72%) rename src/vs/workbench/services/configuration/test/{node => electron-browser}/configurationEditingService.test.ts (87%) rename src/vs/workbench/services/configuration/test/{node => electron-browser}/configurationService.test.ts (87%) create mode 100644 src/vs/workbench/services/configurationResolver/node/variableResolver.ts create mode 100644 src/vs/workbench/services/dialogs/electron-browser/dialogService.ts delete mode 100644 src/vs/workbench/services/dialogs/electron-browser/dialogs.ts create mode 100644 src/vs/workbench/services/files/electron-browser/encoding.ts create mode 100644 src/vs/workbench/services/files/electron-browser/streams.ts delete mode 100644 src/vs/workbench/services/files/node/fileService.ts rename src/vs/workbench/services/files/test/{node => electron-browser}/fileService.test.ts (63%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/examples/company.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/examples/conway.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/examples/employee.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/examples/small.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/index.html (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/other/deep/company.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/other/deep/conway.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/other/deep/employee.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/other/deep/small.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/resolver/site.css (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/binary.txt (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/deep/company.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/deep/conway.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/deep/employee.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/deep/small.js (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/index.html (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/lorem.txt (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/small.txt (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/small_umlaut.txt (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/some_utf16le.css (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/fixtures/service/some_utf8_bom.txt (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/resolver.test.ts (82%) rename src/vs/workbench/services/files/test/{node => electron-browser}/utils.ts (100%) rename src/vs/workbench/services/files/test/{node => electron-browser}/watcher.test.ts (97%) rename src/vs/workbench/services/keybinding/test/{node => electron-browser}/keybindingEditing.test.ts (88%) rename src/vs/workbench/{parts => services}/preferences/browser/preferencesService.ts (72%) rename src/vs/workbench/{parts => services}/preferences/common/keybindingsEditorModel.ts (94%) create mode 100644 src/vs/workbench/services/preferences/common/preferences.ts create mode 100644 src/vs/workbench/services/preferences/common/preferencesEditorInput.ts rename src/vs/workbench/{parts => services}/preferences/common/preferencesModels.ts (97%) rename src/vs/workbench/{parts => services}/preferences/test/common/keybindingsEditorModel.test.ts (97%) delete mode 100644 src/vs/workbench/services/progress/browser/media/progress.svg create mode 100644 src/vs/workbench/test/browser/parts/views/contributableViews.test.ts create mode 100644 src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts create mode 100644 test/smoke/src/application.ts create mode 100644 test/smoke/src/areas/editor/editors.ts delete mode 100644 test/smoke/src/areas/editor/quickoutline.ts delete mode 100644 test/smoke/src/helpers/screenshot.ts delete mode 100644 test/smoke/src/helpers/utilities.ts create mode 100644 test/smoke/src/logger.ts delete mode 100644 test/smoke/src/spectron/application.ts delete mode 100644 test/smoke/src/spectron/client.ts create mode 100644 test/smoke/src/vscode/code.ts rename extensions/markdown/src/util/dispose.ts => test/smoke/src/vscode/driver.js (53%) create mode 100644 test/smoke/tools/copy-driver-definition.js diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0a56ba75f9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +* text=auto + +LICENSE.txt eol=crlf +ThirdPartyNotices.txt eol=crlf + +*.bat eol=crlf +*.cmd eol=crlf +*.ps1 eol=lf +*.sh eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3506c9929f..ccf4cca05f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules/ out/ out-build/ out-editor/ +out-editor-esm/ out-editor-min/ out-monaco-editor-core/ out-vscode/ diff --git a/.travis.yml b/.travis.yml index 4eb8148574..9f90d272ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,6 @@ addons: before_install: - git submodule update --init --recursive - - git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm - - source ./.nvm/nvm.sh - nvm install 8.9.1 - nvm use 8.9.1 - npm i -g yarn diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 6cb9439d5c..8ad783bcbe 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,9 +1,9 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 + // See https://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format "recommendations": [ "eg2.tslint", "dbaeumer.vscode-eslint", "msjsdiag.debugger-for-chrome" ] -} \ No newline at end of file +} diff --git a/LICENSE.txt b/LICENSE.txt index 9039ca3692..45c3fa304a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,11 +4,11 @@ MICROSOFT SQL OPERATIONS STUDIO Microsoft Corporation ("Microsoft") grants you a nonexclusive, perpetual, royalty-free right to use, copy, and modify the software code provided by us -("Software Code"). You may not sublicense the Software Code or any use of it -(except to your affiliates and to vendors to perform work on your behalf) -through distribution, network access, service agreement, lease, rental, or -otherwise. Unless applicable law gives you more rights, Microsoft reserves all -other rights not expressly granted herein, whether by implication, estoppel or +("Software Code"). You may not sublicense the Software Code or any use of it +(except to your affiliates and to vendors to perform work on your behalf) +through distribution, network access, service agreement, lease, rental, or +otherwise. Unless applicable law gives you more rights, Microsoft reserves all +other rights not expressly granted herein, whether by implication, estoppel or otherwise. THE SOFTWARE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY diff --git a/OSSREADME.json b/OSSREADME.json index ccc6ceb8c2..518965880e 100644 --- a/OSSREADME.json +++ b/OSSREADME.json @@ -808,5 +808,389 @@ "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", "SOFTWARE" ] +}, +{ + "name": "mdn-data", + "version": "1.1.12", + "repositoryURL": "https://github.com/mdn/data", + "license": "MPL", + "licenseDetail": [ + "Mozilla Public License Version 2.0", + "", + "Copyright (c) 2018 Mozilla Corporation", + "", + "==================================", + "", + "1. Definitions", + "--------------", + "", + "1.1. \"Contributor\"", + " means each individual or legal entity that creates, contributes to", + " the creation of, or owns Covered Software.", + "", + "1.2. \"Contributor Version\"", + " means the combination of the Contributions of others (if any) used", + " by a Contributor and that particular Contributor's Contribution.", + "", + "1.3. \"Contribution\"", + " means Covered Software of a particular Contributor.", + "", + "1.4. \"Covered Software\"", + " means Source Code Form to which the initial Contributor has attached", + " the notice in Exhibit A, the Executable Form of such Source Code", + " Form, and Modifications of such Source Code Form, in each case", + " including portions thereof.", + "", + "1.5. \"Incompatible With Secondary Licenses\"", + " means", + "", + " (a) that the initial Contributor has attached the notice described", + " in Exhibit B to the Covered Software; or", + "", + " (b) that the Covered Software was made available under the terms of", + " version 1.1 or earlier of the License, but not also under the", + " terms of a Secondary License.", + "", + "1.6. \"Executable Form\"", + " means any form of the work other than Source Code Form.", + "", + "1.7. \"Larger Work\"", + " means a work that combines Covered Software with other material, in", + " a separate file or files, that is not Covered Software.", + "", + "1.8. \"License\"", + " means this document.", + "", + "1.9. \"Licensable\"", + " means having the right to grant, to the maximum extent possible,", + " whether at the time of the initial grant or subsequently, any and", + " all of the rights conveyed by this License.", + "", + "1.10. \"Modifications\"", + " means any of the following:", + "", + " (a) any file in Source Code Form that results from an addition to,", + " deletion from, or modification of the contents of Covered", + " Software; or", + "", + " (b) any new file in Source Code Form that contains any Covered", + " Software.", + "", + "1.11. \"Patent Claims\" of a Contributor", + " means any patent claim(s), including without limitation, method,", + " process, and apparatus claims, in any patent Licensable by such", + " Contributor that would be infringed, but for the grant of the", + " License, by the making, using, selling, offering for sale, having", + " made, import, or transfer of either its Contributions or its", + " Contributor Version.", + "", + "1.12. \"Secondary License\"", + " means either the GNU General Public License, Version 2.0, the GNU", + " Lesser General Public License, Version 2.1, the GNU Affero General", + " Public License, Version 3.0, or any later versions of those", + " licenses.", + "", + "1.13. \"Source Code Form\"", + " means the form of the work preferred for making modifications.", + "", + "1.14. \"You\" (or \"Your\")", + " means an individual or a legal entity exercising rights under this", + " License. For legal entities, \"You\" includes any entity that", + " controls, is controlled by, or is under common control with You. For", + " purposes of this definition, \"control\" means (a) the power, direct", + " or indirect, to cause the direction or management of such entity,", + " whether by contract or otherwise, or (b) ownership of more than", + " fifty percent (50%) of the outstanding shares or beneficial", + " ownership of such entity.", + "", + "2. License Grants and Conditions", + "--------------------------------", + "", + "2.1. Grants", + "", + "Each Contributor hereby grants You a world-wide, royalty-free,", + "non-exclusive license:", + "", + "(a) under intellectual property rights (other than patent or trademark)", + " Licensable by such Contributor to use, reproduce, make available,", + " modify, display, perform, distribute, and otherwise exploit its", + " Contributions, either on an unmodified basis, with Modifications, or", + " as part of a Larger Work; and", + "", + "(b) under Patent Claims of such Contributor to make, use, sell, offer", + " for sale, have made, import, and otherwise transfer either its", + " Contributions or its Contributor Version.", + "", + "2.2. Effective Date", + "", + "The licenses granted in Section 2.1 with respect to any Contribution", + "become effective for each Contribution on the date the Contributor first", + "distributes such Contribution.", + "", + "2.3. Limitations on Grant Scope", + "", + "The licenses granted in this Section 2 are the only rights granted under", + "this License. No additional rights or licenses will be implied from the", + "distribution or licensing of Covered Software under this License.", + "Notwithstanding Section 2.1(b) above, no patent license is granted by a", + "Contributor:", + "", + "(a) for any code that a Contributor has removed from Covered Software;", + " or", + "", + "(b) for infringements caused by: (i) Your and any other third party's", + " modifications of Covered Software, or (ii) the combination of its", + " Contributions with other software (except as part of its Contributor", + " Version); or", + "", + "(c) under Patent Claims infringed by Covered Software in the absence of", + " its Contributions.", + "", + "This License does not grant any rights in the trademarks, service marks,", + "or logos of any Contributor (except as may be necessary to comply with", + "the notice requirements in Section 3.4).", + "", + "2.4. Subsequent Licenses", + "", + "No Contributor makes additional grants as a result of Your choice to", + "distribute the Covered Software under a subsequent version of this", + "License (see Section 10.2) or under the terms of a Secondary License (if", + "permitted under the terms of Section 3.3).", + "", + "2.5. Representation", + "", + "Each Contributor represents that the Contributor believes its", + "Contributions are its original creation(s) or it has sufficient rights", + "to grant the rights to its Contributions conveyed by this License.", + "", + "2.6. Fair Use", + "", + "This License is not intended to limit any rights You have under", + "applicable copyright doctrines of fair use, fair dealing, or other", + "equivalents.", + "", + "2.7. Conditions", + "", + "Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted", + "in Section 2.1.", + "", + "3. Responsibilities", + "-------------------", + "", + "3.1. Distribution of Source Form", + "", + "All distribution of Covered Software in Source Code Form, including any", + "Modifications that You create or to which You contribute, must be under", + "the terms of this License. You must inform recipients that the Source", + "Code Form of the Covered Software is governed by the terms of this", + "License, and how they can obtain a copy of this License. You may not", + "attempt to alter or restrict the recipients' rights in the Source Code", + "Form.", + "", + "3.2. Distribution of Executable Form", + "", + "If You distribute Covered Software in Executable Form then:", + "", + "(a) such Covered Software must also be made available in Source Code", + " Form, as described in Section 3.1, and You must inform recipients of", + " the Executable Form how they can obtain a copy of such Source Code", + " Form by reasonable means in a timely manner, at a charge no more", + " than the cost of distribution to the recipient; and", + "", + "(b) You may distribute such Executable Form under the terms of this", + " License, or sublicense it under different terms, provided that the", + " license for the Executable Form does not attempt to limit or alter", + " the recipients' rights in the Source Code Form under this License.", + "", + "3.3. Distribution of a Larger Work", + "", + "You may create and distribute a Larger Work under terms of Your choice,", + "provided that You also comply with the requirements of this License for", + "the Covered Software. If the Larger Work is a combination of Covered", + "Software with a work governed by one or more Secondary Licenses, and the", + "Covered Software is not Incompatible With Secondary Licenses, this", + "License permits You to additionally distribute such Covered Software", + "under the terms of such Secondary License(s), so that the recipient of", + "the Larger Work may, at their option, further distribute the Covered", + "Software under the terms of either this License or such Secondary", + "License(s).", + "", + "3.4. Notices", + "", + "You may not remove or alter the substance of any license notices", + "(including copyright notices, patent notices, disclaimers of warranty,", + "or limitations of liability) contained within the Source Code Form of", + "the Covered Software, except that You may alter any license notices to", + "the extent required to remedy known factual inaccuracies.", + "", + "3.5. Application of Additional Terms", + "", + "You may choose to offer, and to charge a fee for, warranty, support,", + "indemnity or liability obligations to one or more recipients of Covered", + "Software. However, You may do so only on Your own behalf, and not on", + "behalf of any Contributor. You must make it absolutely clear that any", + "such warranty, support, indemnity, or liability obligation is offered by", + "You alone, and You hereby agree to indemnify every Contributor for any", + "liability incurred by such Contributor as a result of warranty, support,", + "indemnity or liability terms You offer. You may include additional", + "disclaimers of warranty and limitations of liability specific to any", + "jurisdiction.", + "", + "4. Inability to Comply Due to Statute or Regulation", + "---------------------------------------------------", + "", + "If it is impossible for You to comply with any of the terms of this", + "License with respect to some or all of the Covered Software due to", + "statute, judicial order, or regulation then You must: (a) comply with", + "the terms of this License to the maximum extent possible; and (b)", + "describe the limitations and the code they affect. Such description must", + "be placed in a text file included with all distributions of the Covered", + "Software under this License. Except to the extent prohibited by statute", + "or regulation, such description must be sufficiently detailed for a", + "recipient of ordinary skill to be able to understand it.", + "", + "5. Termination", + "--------------", + "", + "5.1. The rights granted under this License will terminate automatically", + "if You fail to comply with any of its terms. However, if You become", + "compliant, then the rights granted under this License from a particular", + "Contributor are reinstated (a) provisionally, unless and until such", + "Contributor explicitly and finally terminates Your grants, and (b) on an", + "ongoing basis, if such Contributor fails to notify You of the", + "non-compliance by some reasonable means prior to 60 days after You have", + "come back into compliance. Moreover, Your grants from a particular", + "Contributor are reinstated on an ongoing basis if such Contributor", + "notifies You of the non-compliance by some reasonable means, this is the", + "first time You have received notice of non-compliance with this License", + "from such Contributor, and You become compliant prior to 30 days after", + "Your receipt of the notice.", + "", + "5.2. If You initiate litigation against any entity by asserting a patent", + "infringement claim (excluding declaratory judgment actions,", + "counter-claims, and cross-claims) alleging that a Contributor Version", + "directly or indirectly infringes any patent, then the rights granted to", + "You by any and all Contributors for the Covered Software under Section", + "2.1 of this License shall terminate.", + "", + "5.3. In the event of termination under Sections 5.1 or 5.2 above, all", + "end user license agreements (excluding distributors and resellers) which", + "have been validly granted by You or Your distributors under this License", + "prior to termination shall survive termination.", + "", + "************************************************************************", + "* *", + "* 6. Disclaimer of Warranty *", + "* ------------------------- *", + "* *", + "* Covered Software is provided under this License on an \"as is\" *", + "* basis, without warranty of any kind, either expressed, implied, or *", + "* statutory, including, without limitation, warranties that the *", + "* Covered Software is free of defects, merchantable, fit for a *", + "* particular purpose or non-infringing. The entire risk as to the *", + "* quality and performance of the Covered Software is with You. *", + "* Should any Covered Software prove defective in any respect, You *", + "* (not any Contributor) assume the cost of any necessary servicing, *", + "* repair, or correction. This disclaimer of warranty constitutes an *", + "* essential part of this License. No use of any Covered Software is *", + "* authorized under this License except under this disclaimer. *", + "* *", + "************************************************************************", + "", + "************************************************************************", + "* *", + "* 7. Limitation of Liability *", + "* -------------------------- *", + "* *", + "* Under no circumstances and under no legal theory, whether tort *", + "* (including negligence), contract, or otherwise, shall any *", + "* Contributor, or anyone who distributes Covered Software as *", + "* permitted above, be liable to You for any direct, indirect, *", + "* special, incidental, or consequential damages of any character *", + "* including, without limitation, damages for lost profits, loss of *", + "* goodwill, work stoppage, computer failure or malfunction, or any *", + "* and all other commercial damages or losses, even if such party *", + "* shall have been informed of the possibility of such damages. This *", + "* limitation of liability shall not apply to liability for death or *", + "* personal injury resulting from such party's negligence to the *", + "* extent applicable law prohibits such limitation. Some *", + "* jurisdictions do not allow the exclusion or limitation of *", + "* incidental or consequential damages, so this exclusion and *", + "* limitation may not apply to You. *", + "* *", + "************************************************************************", + "", + "8. Litigation", + "-------------", + "", + "Any litigation relating to this License may be brought only in the", + "courts of a jurisdiction where the defendant maintains its principal", + "place of business and such litigation shall be governed by laws of that", + "jurisdiction, without reference to its conflict-of-law provisions.", + "Nothing in this Section shall prevent a party's ability to bring", + "cross-claims or counter-claims.", + "", + "9. Miscellaneous", + "----------------", + "", + "This License represents the complete agreement concerning the subject", + "matter hereof. If any provision of this License is held to be", + "unenforceable, such provision shall be reformed only to the extent", + "necessary to make it enforceable. Any law or regulation which provides", + "that the language of a contract shall be construed against the drafter", + "shall not be used to construe this License against a Contributor.", + "", + "10. Versions of the License", + "---------------------------", + "", + "10.1. New Versions", + "", + "Mozilla Foundation is the license steward. Except as provided in Section", + "10.3, no one other than the license steward has the right to modify or", + "publish new versions of this License. Each version will be given a", + "distinguishing version number.", + "", + "10.2. Effect of New Versions", + "", + "You may distribute the Covered Software under the terms of the version", + "of the License under which You originally received the Covered Software,", + "or under the terms of any subsequent version published by the license", + "steward.", + "", + "10.3. Modified Versions", + "", + "If you create software not governed by this License, and you want to", + "create a new license for such software, you may create and use a", + "modified version of this License if you rename the license and remove", + "any references to the name of the license steward (except to note that", + "such modified license differs from this License).", + "", + "10.4. Distributing Source Code Form that is Incompatible With Secondary", + "Licenses", + "", + "If You choose to distribute Source Code Form that is Incompatible With", + "Secondary Licenses under the terms of this version of the License, the", + "notice described in Exhibit B of this License must be attached.", + "", + "Exhibit A - Source Code Form License Notice", + "-------------------------------------------", + "", + " This Source Code Form is subject to the terms of the Mozilla Public", + " License, v. 2.0. If a copy of the MPL was not distributed with this", + " file, You can obtain one at http://mozilla.org/MPL/2.0/.", + "", + "If it is not possible or desirable to put the notice in a particular", + "file, then You may include the notice in a location (such as a LICENSE", + "file in a relevant directory) where a recipient would be likely to look", + "for such a notice.", + "", + "You may add additional accurate notices of copyright ownership.", + "", + "Exhibit B - \"Incompatible With Secondary Licenses\" Notice", + "---------------------------------------------------------", + "", + " This Source Code Form is \"Incompatible With Secondary Licenses\", as", + " defined by the Mozilla Public License, v. 2.0." + ] } ] diff --git a/appveyor.yml b/appveyor.yml index 3ece36f7a3..d9471f2a8f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,6 @@ install: build_script: - yarn - .\node_modules\.bin\gulp electron - - .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit - npm run compile test_script: diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json index edf3e072a5..0c7ae4ea8a 100644 --- a/build/builtInExtensions.json +++ b/build/builtInExtensions.json @@ -1,12 +1,12 @@ [ { "name": "ms-vscode.node-debug", - "version": "1.21.8", + "version": "1.23.3", "repo": "https://github.com/Microsoft/vscode-node-debug" }, { "name": "ms-vscode.node-debug2", - "version": "1.21.2", + "version": "1.23.5", "repo": "https://github.com/Microsoft/vscode-node-debug2" } -] \ No newline at end of file +] diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 59e5638d62..e6f95e5a91 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -3,12 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -var gulp = require('gulp'); -var path = require('path'); -var util = require('./lib/util'); -var common = require('./lib/optimize'); -var es = require('event-stream'); -var File = require('vinyl'); +const gulp = require('gulp'); +const path = require('path'); +const util = require('./lib/util'); +const common = require('./lib/optimize'); +const es = require('event-stream'); +const File = require('vinyl'); +const i18n = require('./lib/i18n'); +const standalone = require('./lib/standalone'); +const cp = require('child_process'); var root = path.dirname(__dirname); var sha1 = util.getVersion(root); @@ -71,6 +74,8 @@ function editorLoaderConfig() { return result; } +const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []); + gulp.task('clean-optimized-editor', util.rimraf('out-editor')); gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'], common.optimizeTask({ entryPoints: editorEntryPoints, @@ -81,14 +86,36 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'], header: BUNDLED_FILE_HEADER, bundleInfo: true, out: 'out-editor', - languages: undefined + languages: languages })); 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('clean-editor-esm', util.rimraf('out-editor-esm')); +gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro'], function () { + standalone.createESMSourcesAndResources({ + entryPoints: [ + 'vs/editor/editor.main', + 'vs/editor/editor.worker' + ], + outFolder: './out-editor-esm/src', + outResourcesFolder: './out-monaco-editor-core/esm', + redirects: { + 'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock', + 'vs/nls': 'vs/nls.mock', + } + }); +}); +gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () { + const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], { + cwd: path.join(__dirname, '../out-editor-esm') + }); + console.log(result.stdout.toString()); +}); + gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core')); -gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function () { +gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify-editor', 'optimize-editor'], function () { return es.merge( // other assets es.merge( @@ -97,6 +124,17 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed gulp.src('src/vs/monaco.d.ts') ).pipe(gulp.dest('out-monaco-editor-core')), + // place the .d.ts in the esm folder + gulp.src('src/vs/monaco.d.ts') + .pipe(es.through(function (data) { + this.emit('data', new File({ + path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'), + base: data.base, + contents: data.contents + })); + })) + .pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')), + // package.json gulp.src('build/monaco/package.json') .pipe(es.through(function (data) { @@ -208,3 +246,60 @@ function filterStream(testFunc) { this.emit('data', data); }); } + + +//#region monaco type checking + +function createTscCompileTask(watch) { + return () => { + const createReporter = require('./lib/reporter').createReporter; + + return new Promise((resolve, reject) => { + const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit']; + if (watch) { + args.push('-w'); + } + const child = cp.spawn(`node`, args, { + cwd: path.join(__dirname, '..'), + // stdio: [null, 'pipe', 'inherit'] + }); + let errors = []; + let reporter = createReporter(); + let report; + let magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings + + child.stdout.on('data', data => { + let str = String(data); + str = str.replace(magic, '').trim(); + if (str.indexOf('Starting compilation') >= 0 || str.indexOf('File change detected') >= 0) { + errors.length = 0; + report = reporter.end(false); + + } else if (str.indexOf('Compilation complete') >= 0) { + report.end(); + + } else if (str) { + let match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(str); + if (match) { + // trying to massage the message so that it matches the gulp-tsb error messages + // e.g. src/vs/base/common/strings.ts(663,5): error TS2322: Type '1234' is not assignable to type 'string'. + let fullpath = path.join(root, match[1]); + let message = match[3]; + // @ts-ignore + reporter(fullpath + message); + } else { + // @ts-ignore + reporter(str); + } + } + }); + child.on('exit', resolve); + child.on('error', reject); + }); + }; +} + +gulp.task('monaco-typecheck-watch', createTscCompileTask(true)); +gulp.task('monaco-typecheck', createTscCompileTask(false)); + +//#endregion diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index c8ba60b608..5ac30c8197 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -21,6 +21,7 @@ const nlsDev = require('vscode-nls-dev'); const root = path.dirname(__dirname); const commit = util.getVersion(root); const i18n = require('./lib/i18n'); +const plumber = require('gulp-plumber'); const extensionsPath = path.join(path.dirname(__dirname), 'extensions'); @@ -82,6 +83,13 @@ const tasks = compilations.map(function (tsconfigFile) { const input = es.through(); const tsFilter = filter(['**/*.ts', '!**/lib/lib*.d.ts', '!**/node_modules/**'], { restore: true }); const output = input + .pipe(plumber({ + errorHandler: function (err) { + if (err && !err.__reporter__) { + reporter(err); + } + } + })) .pipe(tsFilter) .pipe(util.loadSourcemaps()) .pipe(compilation()) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 5b9fab8643..2e74c0a1c9 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -46,10 +46,9 @@ const indentationFilter = [ '!src/vs/nls.js', '!src/vs/css.js', '!src/vs/loader.js', - '!src/vs/base/common/marked/raw.marked.js', - '!src/vs/base/common/winjs.base.raw.js', + '!src/vs/base/common/marked/marked.js', + '!src/vs/base/common/winjs.base.js', '!src/vs/base/node/terminateProcess.sh', - '!src/vs/base/node/ps-win.ps1', '!test/assert.js', // except specific folders @@ -62,6 +61,7 @@ const indentationFilter = [ // except multiple specific files '!**/package.json', '!**/yarn.lock', + '!**/yarn-error.log', // except multiple specific folders '!**/octicons/**', @@ -104,8 +104,9 @@ const copyrightFilter = [ '!build/**/*.init', '!resources/linux/snap/snapcraft.yaml', '!resources/win32/bin/code.js', - '!extensions/markdown/media/tomorrow.css', - '!extensions/html/server/src/modes/typescript/*' + '!extensions/markdown-language-features/media/tomorrow.css', + '!extensions/html-language-features/server/src/modes/typescript/*', + '!extensions/*/server/bin/*' ]; const eslintFilter = [ @@ -116,8 +117,8 @@ const eslintFilter = [ '!src/vs/nls.js', '!src/vs/css.build.js', '!src/vs/nls.build.js', - '!src/**/winjs.base.raw.js', - '!src/**/raw.marked.js', + '!src/**/winjs.base.js', + '!src/**/marked.js', '!**/test/**' ]; @@ -132,15 +133,15 @@ const tslintFilter = [ '!extensions/vscode-api-tests/testWorkspace/**', '!extensions/vscode-api-tests/testWorkspace2/**', '!extensions/**/*.test.ts', - '!extensions/html/server/lib/jquery.d.ts' + '!extensions/html-language-features/server/lib/jquery.d.ts' ]; -const copyrightHeader = [ +const copyrightHeaderLines = [ '/*---------------------------------------------------------------------------------------------', ' * Copyright (c) Microsoft Corporation. All rights reserved.', ' * Licensed under the Source EULA. See License.txt in the project root for license information.', ' *--------------------------------------------------------------------------------------------*/' -].join('\n'); +]; gulp.task('eslint', () => { return vfs.src(all, { base: '.', follow: true, allowEmpty: true }) @@ -202,12 +203,17 @@ function hygiene(some) { tsfmt.processString(file.path, file.contents.toString('utf8'), { verify: false, tsfmt: true, - // verbose: true + // verbose: true, // keep checkJS happy editorconfig: undefined, replace: undefined, tsconfig: undefined, - tslint: undefined + tsconfigFile: undefined, + tslint: undefined, + tslintFile: undefined, + tsfmtFile: undefined, + vscode: undefined, + vscodeFile: undefined }).then(result => { let original = result.src.replace(/\r\n/gm, '\n'); let formatted = result.dest.replace(/\r\n/gm, '\n'); diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index a23b5cf977..89ffadd309 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -91,18 +91,19 @@ const vscodeEntryPoints = _.flatten([ const vscodeResources = [ 'out-build/main.js', 'out-build/cli.js', + 'out-build/driver.js', 'out-build/bootstrap.js', 'out-build/bootstrap-amd.js', 'out-build/paths.js', 'out-build/vs/**/*.{svg,png,cur,html}', 'out-build/vs/base/common/performance.js', - 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,ps-win.ps1}', + 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh}', 'out-build/vs/base/browser/ui/octiconLabel/octicons/**', '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/execution/**/*.scpt', - 'out-build/vs/workbench/parts/html/browser/webview-pre.js', + 'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js', 'out-build/vs/**/markdown.css', 'out-build/vs/workbench/parts/tasks/**/*.json', 'out-build/vs/workbench/parts/terminal/electron-browser/terminalProcess.js', @@ -111,6 +112,7 @@ const vscodeResources = [ 'out-build/vs/workbench/services/files/**/*.md', 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', 'out-build/vs/code/electron-browser/issue/issueReporter.js', + 'out-build/vs/code/electron-browser/processExplorer/processExplorer.js', // {{SQL CARBON EDIT}} 'out-build/sql/workbench/electron-browser/splashscreen/*', 'out-build/sql/**/*.{svg,png,cur,html}', @@ -348,7 +350,7 @@ function packageTask(platform, arch, opts) { const packageJsonStream = gulp.src(['package.json'], { base: '.' }) .pipe(json({ name, version })); - const settingsSearchBuildId = getBuildNumber(); + const settingsSearchBuildId = getSettingsSearchBuildId(packageJson); const date = new Date().toISOString(); const productJsonStream = gulp.src(['product.json'], { base: '.' }) .pipe(json({ commit, date, checksums, settingsSearchBuildId })); @@ -390,6 +392,7 @@ function packageTask(platform, arch, opts) { .pipe(util.cleanNodeModule('core-js', ['**/**'], undefined)) .pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined)) .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('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')); @@ -579,14 +582,12 @@ gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () = } if (!fs.existsSync(allConfigDetailsPath)) { - console.error(`configuration file at ${allConfigDetailsPath} does not exist`); - return; + throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`); } - const settingsSearchBuildId = getBuildNumber(); + const settingsSearchBuildId = getSettingsSearchBuildId(packageJson); if (!settingsSearchBuildId) { - console.error('Failed to compute build number'); - return; + throw new Error('Failed to compute build number'); } return gulp.src(allConfigDetailsPath) @@ -598,76 +599,18 @@ gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () = })); }); -function getBuildNumber() { - const previous = getPreviousVersion(packageJson.version); - if (!previous) { - return 0; - } +function getSettingsSearchBuildId(packageJson) { + const previous = util.getPreviousVersion(packageJson.version); try { const out = cp.execSync(`git rev-list ${previous}..HEAD --count`); const count = parseInt(out.toString()); - return versionStringToNumber(packageJson.version) * 1e4 + count; + return util.versionStringToNumber(packageJson.version) * 1e4 + count; } catch (e) { - console.error('Could not determine build number: ' + e.toString()); - return 0; + throw new Error('Could not determine build number: ' + e.toString()); } } -/** - * Given 1.17.2, return 1.17.1 - * 1.18.0 => 1.17.2. - * 2.0.0 => 1.18.0 (or the highest 1.x) - */ -function getPreviousVersion(versionStr) { - function tagExists(tagName) { - try { - cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } - } - - function getLastTagFromBase(semverArr, componentToTest) { - const baseVersion = semverArr.join('.'); - if (!tagExists(baseVersion)) { - console.error('Failed to find tag for base version, ' + baseVersion); - return null; - } - - let goodTag; - do { - goodTag = semverArr.join('.'); - semverArr[componentToTest]++; - } while (tagExists(semverArr.join('.'))); - - return goodTag; - } - - const semverArr = versionStr.split('.'); - if (semverArr[2] > 0) { - semverArr[2]--; - return semverArr.join('.'); - } else if (semverArr[1] > 0) { - semverArr[1]--; - return getLastTagFromBase(semverArr, 2); - } else { - semverArr[0]--; - return getLastTagFromBase(semverArr, 1); - } -} - -function versionStringToNumber(versionStr) { - const semverRegex = /(\d+)\.(\d+)\.(\d+)/; - const match = versionStr.match(semverRegex); - if (!match) { - return 0; - } - - return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); -} - // This task is only run for the MacOS build gulp.task('generate-vscode-configuration', () => { return new Promise((resolve, reject) => { @@ -699,9 +642,6 @@ gulp.task('generate-vscode-configuration', () => { clearTimeout(timer); reject(err); }); - }).catch(e => { - // Don't fail the build - console.error(e.toString()); }); }); diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index 2c06afb10d..c96f9deed0 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -21,29 +21,6 @@ const rpmDependencies = require('../resources/linux/rpm/dependencies.json'); const linuxPackageRevision = Math.floor(new Date().getTime() / 1000); -const flatpakManifest = { - appId: product.darwinBundleIdentifier, // We need a reverse-url style identifier. - sdk: 'org.freedesktop.Sdk', - runtime: 'org.freedesktop.Sdk', - runtimeVersion: '1.4', - base: 'io.atom.electron.BaseApp', - baseFlatpakref: 'https://s3-us-west-2.amazonaws.com/electron-flatpak.endlessm.com/electron-base-app-master.flatpakref', - command: product.applicationName, - symlinks: [ - ['/share/' + product.applicationName + '/bin/' + product.applicationName, '/bin/' + product.applicationName], - ], - finishArgs: [ - '--share=ipc', '--socket=x11', // Allow showing X11 windows. - '--share=network', // Network access (e.g. for installing extension). - '--filesystem=host', // Allow access to the whole file system. - '--device=dri', // Allow OpenGL rendering. - '--filesystem=/tmp', // Needed for Chromium's single instance check. - '--socket=pulseaudio', // Some extensions may want to play sounds... - '--talk-name=org.freedesktop.Notifications', // ...or pop up notifications. - ], -}; - - function getDebPackageArch(arch) { return { x64: 'amd64', ia32: 'i386', arm: 'armhf' }[arch]; } @@ -336,10 +313,3 @@ gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prep 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-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm')); - -gulp.task('vscode-linux-ia32-prepare-flatpak', ['clean-vscode-linux-ia32-flatpak'], prepareFlatpak('ia32')); -gulp.task('vscode-linux-x64-prepare-flatpak', ['clean-vscode-linux-x64-flatpak'], prepareFlatpak('x64')); -gulp.task('vscode-linux-arm-prepare-flatpak', ['clean-vscode-linux-arm-flatpak'], prepareFlatpak('arm')); -gulp.task('vscode-linux-ia32-flatpak', ['vscode-linux-ia32-prepare-flatpak'], buildFlatpak('ia32')); -gulp.task('vscode-linux-x64-flatpak', ['vscode-linux-x64-prepare-flatpak'], buildFlatpak('x64')); -gulp.task('vscode-linux-arm-flatpak', ['vscode-linux-arm-prepare-flatpak'], buildFlatpak('arm')); diff --git a/build/lib/compilation.js b/build/lib/compilation.js index 7ce9c33d34..6788e40961 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -22,11 +22,12 @@ var rootDir = path.join(__dirname, '../../src'); var options = require('../../src/tsconfig.json').compilerOptions; options.verbose = false; options.sourceMap = true; -if (process.env['VSCODE_NO_SOURCEMAP']) { +if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry options.sourceMap = false; } options.rootDir = rootDir; options.sourceRoot = util.toFileUri(rootDir); +options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF'; function createCompile(build, emitError) { var opts = _.clone(options); opts.inlineSources = !!build; diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index f7f25001db..dec7cf28ab 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -30,6 +30,7 @@ if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry } options.rootDir = rootDir; options.sourceRoot = util.toFileUri(rootDir); +options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF'; function createCompile(build: boolean, emitError?: boolean): (token?: util.ICancellationToken) => NodeJS.ReadWriteStream { const opts = _.clone(options); diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 10cafc2703..fc50027fd2 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -527,6 +527,7 @@ function getResource(sourceFile) { else if (/^vs\/workbench/.test(sourceFile)) { return { name: 'vs/workbench', project: workbenchProject }; } + // {{SQL CARBON EDIT}} else if (/^sql/.test(sourceFile)) { return { name: 'sql', project: sqlopsProject }; } @@ -1051,7 +1052,10 @@ function createI18nFile(originalFilePath, messages) { var key = _a[_i]; result[key] = messages[key]; } - var content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n'); + var content = JSON.stringify(result, null, '\t'); + if (process.platform === 'win32') { + content = content.replace(/\n/g, '\r\n'); + } return new File({ path: path.join(originalFilePath + '.i18n.json'), contents: Buffer.from(content, 'utf8') @@ -1085,7 +1089,7 @@ function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pse extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} }; } var externalId = externalExtensions[resource]; - if (!externalId) { + if (!externalId) { // internal extension: remove 'extensions/extensionId/' segnent var secondSlash = path.indexOf('/', firstSlash + 1); extPack.contents[path.substr(secondSlash + 1)] = file.messages; } diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 56fab72bd5..4cf0bc4cf6 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -130,10 +130,18 @@ "name": "vs/workbench/parts/update", "project": "vscode-workbench" }, + { + "name": "vs/workbench/parts/url", + "project": "vscode-workbench" + }, { "name": "vs/workbench/parts/watermark", "project": "vscode-workbench" }, + { + "name": "vs/workbench/parts/webview", + "project": "vscode-workbench" + }, { "name": "vs/workbench/parts/welcome", "project": "vscode-workbench" @@ -146,6 +154,10 @@ "name": "vs/workbench/services/configuration", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/configurationResolver", + "project": "vscode-workbench" + }, { "name": "vs/workbench/services/crashReporter", "project": "vscode-workbench" @@ -201,6 +213,10 @@ { "name": "vs/workbench/services/decorations", "project": "vscode-workbench" + }, + { + "name": "vs/workbench/services/preferences", + "project": "vscode-preferences" } ] } \ No newline at end of file diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index e9a62ecfe9..7afac93d6d 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -1179,7 +1179,10 @@ function createI18nFile(originalFilePath: string, messages: any): File { result[key] = messages[key]; } - let content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n'); + let content = JSON.stringify(result, null, '\t'); + if (process.platform === 'win32') { + content = content.replace(/\n/g, '\r\n'); + } return new File({ path: path.join(originalFilePath + '.i18n.json'), contents: Buffer.from(content, 'utf8') diff --git a/build/lib/nls.js b/build/lib/nls.js index 67ef0476b2..9004518f30 100644 --- a/build/lib/nls.js +++ b/build/lib/nls.js @@ -150,13 +150,16 @@ function isImportNode(node) { .filter(function (d) { return d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport; }) .map(function (d) { return d.importClause.namedBindings.name; }) .concat(importEqualsDeclarations.map(function (d) { return d.name; })) + // find read-only references to `nls` .map(function (n) { return service.getReferencesAtPosition(filename, n.pos + 1); }) .flatten() .filter(function (r) { return !r.isWriteAccess; }) + // 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(function (a) { return lazy(a).last(); }) .filter(function (n) { return !!n; }) .map(function (n) { return n; }) + // only `localize` calls .filter(function (n) { return n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize'; }); // `localize` named imports var allLocalizeImportDeclarations = importDeclarations diff --git a/build/lib/reporter.js b/build/lib/reporter.js index adb4ff268d..9fe9b5c2ca 100644 --- a/build/lib/reporter.js +++ b/build/lib/reporter.js @@ -34,7 +34,13 @@ catch (err) { } function log() { var errors = _.flatten(allErrors); - errors.map(function (err) { return util.log(util.colors.red('Error') + ": " + err); }); + var seen = new Set(); + errors.map(function (err) { + if (!seen.has(err)) { + seen.add(err); + util.log(util.colors.red('Error') + ": " + err); + } + }); var regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/; var messages = errors .map(function (err) { return regex.exec(err); }) @@ -67,8 +73,13 @@ function createReporter() { return es.through(null, function () { onEnd(); if (emitError && errors.length > 0) { - log(); - this.emit('error'); + errors.__logged__ = true; + if (!errors.__logged__) { + log(); + } + var err = new Error("Found " + errors.length + " errors"); + err.__reporter__ = true; + this.emit('error', err); } else { this.emit('end'); @@ -80,4 +91,3 @@ function createReporter() { return ReportFunc; } exports.createReporter = createReporter; -; diff --git a/build/lib/reporter.ts b/build/lib/reporter.ts index 6be780fcc2..c358395582 100644 --- a/build/lib/reporter.ts +++ b/build/lib/reporter.ts @@ -11,7 +11,7 @@ import * as util from 'gulp-util'; import * as fs from 'fs'; import * as path from 'path'; -const allErrors: Error[][] = []; +const allErrors: string[][] = []; let startTime: number = null; let count = 0; @@ -42,7 +42,14 @@ try { function log(): void { const errors = _.flatten(allErrors); - errors.map(err => util.log(`${util.colors.red('Error')}: ${err}`)); + const seen = new Set(); + + errors.map(err => { + if (!seen.has(err)) { + seen.add(err); + util.log(`${util.colors.red('Error')}: ${err}`); + } + }); const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/; const messages = errors @@ -61,17 +68,17 @@ function log(): void { } export interface IReporter { - (err: Error): void; + (err: string): void; hasErrors(): boolean; end(emitError: boolean): NodeJS.ReadWriteStream; } export function createReporter(): IReporter { - const errors: Error[] = []; + const errors: string[] = []; allErrors.push(errors); class ReportFunc { - constructor(err: Error) { + constructor(err: string) { errors.push(err); } @@ -87,8 +94,15 @@ export function createReporter(): IReporter { onEnd(); if (emitError && errors.length > 0) { - log(); - this.emit('error'); + (errors as any).__logged__ = true; + + 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'); } @@ -97,4 +111,4 @@ export function createReporter(): IReporter { } return ReportFunc; -}; +} diff --git a/build/lib/standalone.js b/build/lib/standalone.js new file mode 100644 index 0000000000..4ae887e007 --- /dev/null +++ b/build/lib/standalone.js @@ -0,0 +1,265 @@ +"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 }); +var ts = require("typescript"); +var fs = require("fs"); +var path = require("path"); +var REPO_ROOT = path.join(__dirname, '../../'); +var SRC_DIR = path.join(REPO_ROOT, 'src'); +var OUT_EDITOR = path.join(REPO_ROOT, 'out-editor'); +function createESMSourcesAndResources(options) { + var OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); + var OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); + var in_queue = Object.create(null); + var queue = []; + var enqueue = function (module) { + if (in_queue[module]) { + return; + } + in_queue[module] = true; + queue.push(module); + }; + var seenDir = {}; + var createDirectoryRecursive = function (dir) { + if (seenDir[dir]) { + return; + } + var lastSlash = dir.lastIndexOf('/'); + 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; + var toggleComments = function (fileContents) { + var lines = fileContents.split(/\r\n|\r|\n/); + var mode = 0; + for (var i = 0; i < lines.length; i++) { + var 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'); + }; + var write = function (filePath, contents) { + 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()); + } + fs.writeFileSync(absoluteFilePath, contents); + }; + options.entryPoints.forEach(function (entryPoint) { return enqueue(entryPoint); }); + while (queue.length > 0) { + var module_1 = queue.shift(); + if (transportCSS(options, module_1, enqueue, write)) { + continue; + } + 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; +function transportCSS(options, module, enqueue, write) { + if (!/\.css/.test(module)) { + return false; + } + var filename = path.join(SRC_DIR, module); + var fileContents = fs.readFileSync(filename).toString(); + var inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148 + var inlineResourcesLimit = 300000; //3000; // see https://github.com/Microsoft/monaco-editor/issues/336 + var newContents = _rewriteOrInlineUrls(filename, fileContents, inlineResources === 'base64', inlineResourcesLimit); + write(module, newContents); + return true; + function _rewriteOrInlineUrls(originalFileFSPath, contents, forceBase64, inlineByteLimit) { + return _replaceURL(contents, function (url) { + var imagePath = path.join(path.dirname(module), url); + var fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath)); + if (fileContents.length < inlineByteLimit) { + var MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png'; + var DATA = ';base64,' + fileContents.toString('base64'); + if (!forceBase64 && /\.svg$/.test(url)) { + // .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris + var newText = fileContents.toString() + .replace(/"/g, '\'') + .replace(//g, '%3E') + .replace(/&/g, '%26') + .replace(/#/g, '%23') + .replace(/\s+/g, ' '); + var encodedData = ',' + newText; + if (encodedData.length < DATA.length) { + DATA = encodedData; + } + } + return '"data:' + MIME + DATA + '"'; + } + enqueue(imagePath); + return url; + }); + } + function _replaceURL(contents, replacer) { + // Use ")" as the terminator as quotes are oftentimes not used at all + return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, function (_) { + var matches = []; + 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) + if (url.charAt(0) === '"' || url.charAt(0) === '\'') { + url = url.substring(1); + } + // The ending whitespace is captured + while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) { + url = url.substring(0, url.length - 1); + } + // Eliminate ending quotes + if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') { + url = url.substring(0, url.length - 1); + } + if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) { + url = replacer(url); + } + return 'url(' + url + ')'; + }); + } + function _startsWith(haystack, 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; +} diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts new file mode 100644 index 0000000000..ee76c1e2b9 --- /dev/null +++ b/build/lib/standalone.ts @@ -0,0 +1,305 @@ +/*--------------------------------------------------------------------------------------------- + * 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 fs from 'fs'; +import * as path from 'path'; + +const REPO_ROOT = path.join(__dirname, '../../'); +const SRC_DIR = path.join(REPO_ROOT, 'src'); +const OUT_EDITOR = path.join(REPO_ROOT, 'out-editor'); + +export interface IOptions { + entryPoints: string[]; + outFolder: string; + outResourcesFolder: string; + redirects: { [module: string]: string; }; +} + +export function createESMSourcesAndResources(options: IOptions): void { + const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); + const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); + + let in_queue: { [module: string]: boolean; } = Object.create(null); + let queue: string[] = []; + + const enqueue = (module: string) => { + if (in_queue[module]) { + return; + } + in_queue[module] = true; + queue.push(module); + }; + + const seenDir: { [key: string]: boolean; } = {}; + const createDirectoryRecursive = (dir: string) => { + if (seenDir[dir]) { + return; + } + + let lastSlash = dir.lastIndexOf('/'); + 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(options, module, enqueue, write)) { + continue; + } + if (transportResource(options, module, enqueue, write)) { + continue; + } + if (transportDTS(options, module, enqueue, write)) { + continue; + } + + let filename: string; + if (options.redirects[module]) { + filename = path.join(SRC_DIR, options.redirects[module] + '.ts'); + } else { + filename = path.join(SRC_DIR, module + '.ts'); + } + 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) { + return `import * as ${m1} from ${m2};`; + }); + fileContents = fileContents.replace(/Thenable/g, 'PromiseLike'); + + write(module + '.ts', fileContents); + } + + const 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')); + + const monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString(); + fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts); + +} + +function transportCSS(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean { + + if (!/\.css/.test(module)) { + return false; + } + + const filename = path.join(SRC_DIR, module); + const fileContents = fs.readFileSync(filename).toString(); + const inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148 + const inlineResourcesLimit = 300000;//3000; // see https://github.com/Microsoft/monaco-editor/issues/336 + + const newContents = _rewriteOrInlineUrls(filename, fileContents, inlineResources === 'base64', inlineResourcesLimit); + write(module, newContents); + return true; + + function _rewriteOrInlineUrls(originalFileFSPath: string, contents: string, forceBase64: boolean, inlineByteLimit: number): string { + return _replaceURL(contents, (url) => { + let imagePath = path.join(path.dirname(module), url); + let fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath)); + + if (fileContents.length < inlineByteLimit) { + const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png'; + let DATA = ';base64,' + fileContents.toString('base64'); + + if (!forceBase64 && /\.svg$/.test(url)) { + // .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris + let newText = fileContents.toString() + .replace(/"/g, '\'') + .replace(//g, '%3E') + .replace(/&/g, '%26') + .replace(/#/g, '%23') + .replace(/\s+/g, ' '); + let encodedData = ',' + newText; + if (encodedData.length < DATA.length) { + DATA = encodedData; + } + } + return '"data:' + MIME + DATA + '"'; + } + + enqueue(imagePath); + return url; + }); + } + + function _replaceURL(contents: string, replacer: (url: string) => string): string { + // Use ")" as the terminator as quotes are oftentimes not used at all + return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_: string, ...matches: string[]) => { + var url = matches[0]; + // Eliminate starting quotes (the initial whitespace is not captured) + if (url.charAt(0) === '"' || url.charAt(0) === '\'') { + url = url.substring(1); + } + // The ending whitespace is captured + while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) { + url = url.substring(0, url.length - 1); + } + // Eliminate ending quotes + if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') { + url = url.substring(0, url.length - 1); + } + + if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) { + url = replacer(url); + } + + return 'url(' + url + ')'; + }); + } + + function _startsWith(haystack: string, needle: string): boolean { + 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; +} diff --git a/build/lib/test/util.test.js b/build/lib/test/util.test.js new file mode 100644 index 0000000000..78ee9ceb9d --- /dev/null +++ b/build/lib/test/util.test.js @@ -0,0 +1,56 @@ +"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 }); +var assert = require("assert"); +var util = require("../util"); +function getMockTagExists(tags) { + return function (tag) { return tags.indexOf(tag) >= 0; }; +} +suite('util tests', function () { + test('getPreviousVersion - patch', function () { + assert.equal(util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])), '1.2.2'); + }); + test('getPreviousVersion - patch invalid', function () { + try { + util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0'])); + } + catch (e) { + // expected + return; + } + throw new Error('Expected an exception'); + }); + test('getPreviousVersion - minor', function () { + assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])), '1.1.3'); + assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])), '1.1.0'); + }); + test('getPreviousVersion - minor gap', function () { + assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])), '1.1.1'); + }); + test('getPreviousVersion - minor invalid', function () { + try { + util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0'])); + } + catch (e) { + // expected + return; + } + throw new Error('Expected an exception'); + }); + test('getPreviousVersion - major', function () { + assert.equal(util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])), '1.2.2'); + }); + test('getPreviousVersion - major invalid', function () { + try { + util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0'])); + } + catch (e) { + // expected + return; + } + throw new Error('Expected an exception'); + }); +}); diff --git a/build/lib/test/util.test.ts b/build/lib/test/util.test.ts new file mode 100644 index 0000000000..ff11188555 --- /dev/null +++ b/build/lib/test/util.test.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); +import util = require('../util'); + +function getMockTagExists(tags: string[]) { + return (tag: string) => tags.indexOf(tag) >= 0; +} + +suite('util tests', () => { + test('getPreviousVersion - patch', () => { + assert.equal( + util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])), + '1.2.2' + ); + }); + + test('getPreviousVersion - patch invalid', () => { + try { + util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0'])); + } catch (e) { + // expected + return; + } + + throw new Error('Expected an exception'); + }); + + test('getPreviousVersion - minor', () => { + assert.equal( + util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])), + '1.1.3' + ); + + assert.equal( + util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])), + '1.1.0' + ); + }); + + test('getPreviousVersion - minor gap', () => { + assert.equal( + util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])), + '1.1.1' + ); + }); + + test('getPreviousVersion - minor invalid', () => { + try { + util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0'])); + } catch (e) { + // expected + return; + } + + throw new Error('Expected an exception'); + }); + + test('getPreviousVersion - major', () => { + assert.equal( + util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])), + '1.2.2' + ); + }); + + test('getPreviousVersion - major invalid', () => { + try { + util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0'])); + } catch (e) { + // expected + return; + } + + throw new Error('Expected an exception'); + }); +}); diff --git a/build/lib/tslint/translationRemindRule.js b/build/lib/tslint/translationRemindRule.js index 43b26b2d35..3dc26b378e 100644 --- a/build/lib/tslint/translationRemindRule.js +++ b/build/lib/tslint/translationRemindRule.js @@ -71,7 +71,7 @@ var TranslationRemindRuleWalker = /** @class */ (function (_super) { } }); if (!resourceDefined) { - this.addFailureAtNode(node, "Please add '" + resource + "' to ./builds/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'; diff --git a/build/lib/tslint/translationRemindRule.ts b/build/lib/tslint/translationRemindRule.ts index 48b01c5bef..e8847d17be 100644 --- a/build/lib/tslint/translationRemindRule.ts +++ b/build/lib/tslint/translationRemindRule.ts @@ -67,7 +67,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker { }); if (!resourceDefined) { - this.addFailureAtNode(node, `Please add '${resource}' to ./builds/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.`); } } } diff --git a/build/lib/util.js b/build/lib/util.js index a81408fadb..35341b5703 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -14,6 +14,7 @@ var fs = require("fs"); var _rimraf = require("rimraf"); var git = require("./git"); var VinylFile = require("vinyl"); +var cp = require("child_process"); var NoCancellationToken = { isCancellationRequested: function () { return false; } }; function incremental(streamProvider, initial, supportsCancellation) { var input = es.through(); @@ -210,3 +211,68 @@ function filter(fn) { return result; } exports.filter = filter; +function tagExists(tagName) { + try { + cp.execSync("git rev-parse " + tagName, { stdio: 'ignore' }); + return true; + } + catch (e) { + return false; + } +} +/** + * Returns the version previous to the given version. Throws if a git tag for that version doesn't exist. + * Given 1.17.2, return 1.17.1 + * 1.18.0 => 1.17.2. (or the highest 1.17.x) + * 2.0.0 => 1.18.0 (or the highest 1.x) + */ +function getPreviousVersion(versionStr, _tagExists) { + if (_tagExists === void 0) { _tagExists = tagExists; } + function getLatestTagFromBase(semverArr, componentToTest) { + var baseVersion = semverArr.join('.'); + if (!_tagExists(baseVersion)) { + throw new Error('Failed to find git tag for base version, ' + baseVersion); + } + var goodTag; + do { + goodTag = semverArr.join('.'); + semverArr[componentToTest]++; + } while (_tagExists(semverArr.join('.'))); + return goodTag; + } + var semverArr = versionStringToNumberArray(versionStr); + if (semverArr[2] > 0) { + semverArr[2]--; + var previous = semverArr.join('.'); + if (!_tagExists(previous)) { + throw new Error('Failed to find git tag for previous version, ' + previous); + } + return previous; + } + else if (semverArr[1] > 0) { + semverArr[1]--; + return getLatestTagFromBase(semverArr, 2); + } + else { + semverArr[0]--; + // Find 1.x.0 for latest x + var latestMinorVersion = getLatestTagFromBase(semverArr, 1); + // Find 1.x.y for latest y + return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2); + } +} +exports.getPreviousVersion = getPreviousVersion; +function versionStringToNumberArray(versionStr) { + return versionStr + .split('.') + .map(function (s) { return parseInt(s); }); +} +function versionStringToNumber(versionStr) { + var semverRegex = /(\d+)\.(\d+)\.(\d+)/; + var match = versionStr.match(semverRegex); + if (!match) { + throw new Error('Version string is not properly formatted: ' + versionStr); + } + return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); +} +exports.versionStringToNumber = versionStringToNumber; diff --git a/build/lib/util.ts b/build/lib/util.ts index 9fe54ac0f1..75c84685b7 100644 --- a/build/lib/util.ts +++ b/build/lib/util.ts @@ -17,6 +17,7 @@ import * as git from './git'; import * as VinylFile from 'vinyl'; import { ThroughStream } from 'through'; import * as sm from 'source-map'; +import * as cp from 'child_process'; export interface ICancellationToken { isCancellationRequested(): boolean; @@ -268,4 +269,74 @@ export function filter(fn: (data: any) => boolean): FilterStream { result.restore = es.through(); return result; -} \ No newline at end of file +} + +function tagExists(tagName: string): boolean { + try { + cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' }); + return true; + } catch (e) { + return false; + } +} + +/** + * Returns the version previous to the given version. Throws if a git tag for that version doesn't exist. + * Given 1.17.2, return 1.17.1 + * 1.18.0 => 1.17.2. (or the highest 1.17.x) + * 2.0.0 => 1.18.0 (or the highest 1.x) + */ +export function getPreviousVersion(versionStr: string, _tagExists = tagExists) { + function getLatestTagFromBase(semverArr: number[], componentToTest: number): string { + const baseVersion = semverArr.join('.'); + if (!_tagExists(baseVersion)) { + throw new Error('Failed to find git tag for base version, ' + baseVersion); + } + + let goodTag; + do { + goodTag = semverArr.join('.'); + semverArr[componentToTest]++; + } while (_tagExists(semverArr.join('.'))); + + return goodTag; + } + + const semverArr = versionStringToNumberArray(versionStr); + if (semverArr[2] > 0) { + semverArr[2]--; + const previous = semverArr.join('.'); + if (!_tagExists(previous)) { + throw new Error('Failed to find git tag for previous version, ' + previous); + } + + return previous; + } else if (semverArr[1] > 0) { + semverArr[1]--; + return getLatestTagFromBase(semverArr, 2); + } else { + semverArr[0]--; + + // Find 1.x.0 for latest x + const latestMinorVersion = getLatestTagFromBase(semverArr, 1); + + // Find 1.x.y for latest y + return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2); + } +} + +function versionStringToNumberArray(versionStr: string): number[] { + return versionStr + .split('.') + .map(s => parseInt(s)); +} + +export function versionStringToNumber(versionStr: string) { + const semverRegex = /(\d+)\.(\d+)\.(\d+)/; + const match = versionStr.match(semverRegex); + if (!match) { + throw new Error('Version string is not properly formatted: ' + versionStr); + } + + return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); +} diff --git a/build/monaco/LICENSE b/build/monaco/LICENSE index 0b52fb74a7..35c624d284 100644 --- a/build/monaco/LICENSE +++ b/build/monaco/LICENSE @@ -1,6 +1,6 @@ The Source EULA -Copyright (c) 2016 Microsoft Corporation +Copyright (c) 2016 - present Microsoft Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/build/monaco/ThirdPartyNotices.txt b/build/monaco/ThirdPartyNotices.txt index bf7dd4a715..45eeffb9f3 100644 --- a/build/monaco/ThirdPartyNotices.txt +++ b/build/monaco/ThirdPartyNotices.txt @@ -32,7 +32,7 @@ END OF winjs NOTICES AND INFORMATION %% string_scorer version 0.1.20 (https://github.com/joshaven/string_score) ========================================= -This software is released under the Source EULA: +This software is released under the MIT license: Copyright (c) Joshaven Potter @@ -60,7 +60,7 @@ END OF string_scorer NOTICES AND INFORMATION %% chjj-marked NOTICES AND INFORMATION BEGIN HERE ========================================= -The Source EULA +The MIT License (MIT) Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) diff --git a/build/monaco/api.js b/build/monaco/api.js index b50f4cc027..6ea2b5be09 100644 --- a/build/monaco/api.js +++ b/build/monaco/api.js @@ -171,9 +171,7 @@ function format(text) { function getRuleProvider(options) { // Share this between multiple formatters using the same options. // This represents the bulk of the space the formatter uses. - var ruleProvider = new ts.formatting.RulesProvider(); - ruleProvider.ensureUpToDate(options); - return ruleProvider; + return ts.formatting.getFormatContext(options); } function applyEdits(text, edits) { // Apply edits in reverse on the existing text @@ -210,7 +208,8 @@ function createReplacer(data) { }; } function generateDeclarationFile(out, inputFiles, recipe) { - var lines = recipe.split(/\r\n|\n|\r/); + var endl = /\r\n/.test(recipe) ? '\r\n' : '\n'; + var lines = recipe.split(endl); var result = []; lines.forEach(function (line) { var m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/); @@ -278,12 +277,11 @@ function generateDeclarationFile(out, inputFiles, recipe) { } result.push(line); }); - var resultTxt = result.join('\n'); + var resultTxt = result.join(endl); resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri'); resultTxt = resultTxt.replace(/\bEventboolean): void { +function visitTopLevelDeclarations(sourceFile: ts.SourceFile, visitor: (node: TSTopLevelDeclare) => boolean): void { let stop = false; let visit = (node: ts.Node): void => { @@ -100,8 +100,8 @@ function visitTopLevelDeclarations(sourceFile:ts.SourceFile, visitor:(node:TSTop } -function getAllTopLevelDeclarations(sourceFile:ts.SourceFile): TSTopLevelDeclare[] { - let all:TSTopLevelDeclare[] = []; +function getAllTopLevelDeclarations(sourceFile: ts.SourceFile): TSTopLevelDeclare[] { + let all: TSTopLevelDeclare[] = []; visitTopLevelDeclarations(sourceFile, (node) => { if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) { let interfaceDeclaration = node; @@ -128,8 +128,8 @@ function getAllTopLevelDeclarations(sourceFile:ts.SourceFile): TSTopLevelDeclare } -function getTopLevelDeclaration(sourceFile:ts.SourceFile, typeName:string): TSTopLevelDeclare { - let result:TSTopLevelDeclare = null; +function getTopLevelDeclaration(sourceFile: ts.SourceFile, typeName: string): TSTopLevelDeclare { + let result: TSTopLevelDeclare = null; visitTopLevelDeclarations(sourceFile, (node) => { if (isDeclaration(node)) { if (node.name.text === typeName) { @@ -149,12 +149,12 @@ function getTopLevelDeclaration(sourceFile:ts.SourceFile, typeName:string): TSTo } -function getNodeText(sourceFile:ts.SourceFile, node:{pos:number; end:number;}): string { +function getNodeText(sourceFile: ts.SourceFile, node: { pos: number; end: number; }): string { return sourceFile.getFullText().substring(node.pos, node.end); } -function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaration: TSTopLevelDeclare): string { +function getMassagedTopLevelDeclarationText(sourceFile: ts.SourceFile, declaration: TSTopLevelDeclare): string { let result = getNodeText(sourceFile, declaration); // if (result.indexOf('MonacoWorker') >= 0) { // console.log('here!'); @@ -163,7 +163,7 @@ function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaratio if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) { let interfaceDeclaration = declaration; - let members:ts.NodeArray = interfaceDeclaration.members; + let members: ts.NodeArray = interfaceDeclaration.members; members.forEach((member) => { try { let memberText = getNodeText(sourceFile, member); @@ -182,7 +182,7 @@ function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaratio return result; } -function format(text:string): string { +function format(text: string): string { // Parse the source text let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true); @@ -196,9 +196,7 @@ function format(text:string): string { function getRuleProvider(options: ts.FormatCodeSettings) { // Share this between multiple formatters using the same options. // This represents the bulk of the space the formatter uses. - let ruleProvider = new (ts).formatting.RulesProvider(); - ruleProvider.ensureUpToDate(options); - return ruleProvider; + return (ts as any).formatting.getFormatContext(options); } function applyEdits(text: string, edits: ts.TextChange[]): string { @@ -214,10 +212,10 @@ function format(text:string): string { } } -function createReplacer(data:string): (str:string)=>string { +function createReplacer(data: string): (str: string) => string { data = data || ''; let rawDirectives = data.split(';'); - let directives: [RegExp,string][] = []; + let directives: [RegExp, string][] = []; rawDirectives.forEach((rawDirective) => { if (rawDirective.length === 0) { return; @@ -231,7 +229,7 @@ function createReplacer(data:string): (str:string)=>string { directives.push([new RegExp(findStr, 'g'), replaceStr]); }); - return (str:string)=> { + return (str: string) => { for (let i = 0; i < directives.length; i++) { str = str.replace(directives[i][0], directives[i][1]); } @@ -239,10 +237,11 @@ function createReplacer(data:string): (str:string)=>string { }; } -function generateDeclarationFile(out: string, inputFiles: { [file: string]: string; }, recipe:string): string { - let lines = recipe.split(/\r\n|\n|\r/); - let result = []; +function generateDeclarationFile(out: string, inputFiles: { [file: string]: string; }, recipe: string): string { + const endl = /\r\n/.test(recipe) ? '\r\n' : '\n'; + let lines = recipe.split(endl); + let result = []; lines.forEach(line => { @@ -285,7 +284,7 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri let replacer = createReplacer(m2[2]); let typeNames = m2[3].split(/,/); - let typesToExcludeMap: {[typeName:string]:boolean;} = {}; + let typesToExcludeMap: { [typeName: string]: boolean; } = {}; let typesToExcludeArr: string[] = []; typeNames.forEach((typeName) => { typeName = typeName.trim(); @@ -318,18 +317,17 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri result.push(line); }); - let resultTxt = result.join('\n'); + let resultTxt = result.join(endl); resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri'); resultTxt = resultTxt.replace(/\bEvent = PromiseLike; + export type Thenable = PromiseLike; export interface IDisposable { dispose(): void; @@ -32,6 +32,14 @@ declare module monaco { Error = 3, } + export enum MarkerSeverity { + Hint = 1, + Info = 2, + Warning = 4, + Error = 8, + } + + #include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, Promise #include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken #include(vs/base/common/uri): URI, UriComponents @@ -46,7 +54,7 @@ declare module monaco { #include(vs/editor/common/core/token): Token } -declare module monaco.editor { +declare namespace monaco.editor { #includeAll(vs/editor/standalone/browser/standaloneEditor;modes.=>languages.;editorCommon.=>): #include(vs/editor/standalone/common/standaloneThemeService): BuiltinTheme, IStandaloneThemeData, IColors @@ -58,7 +66,7 @@ export interface ICommandHandler { } #include(vs/platform/contextkey/common/contextkey): IContextKey #include(vs/editor/standalone/browser/standaloneServices): IEditorOverrideServices -#include(vs/platform/markers/common/markers): IMarker, IMarkerData +#include(vs/platform/markers/common/markers): IMarker, IMarkerData, IRelatedInformation #include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions #include(vs/base/common/scrollable): ScrollbarVisibility #include(vs/platform/theme/common/themeService): ThemeColor @@ -75,7 +83,7 @@ export type IReadOnlyModel = ITextModel; export type IModel = ITextModel; } -declare module monaco.languages { +declare namespace monaco.languages { #includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData): #includeAll(vs/editor/common/modes/languageConfiguration): @@ -85,7 +93,7 @@ declare module monaco.languages { } -declare module monaco.worker { +declare namespace monaco.worker { #includeAll(vs/editor/common/services/editorSimpleWorker;): diff --git a/build/monaco/package.json b/build/monaco/package.json index 40cd4f1e27..256ca1ff53 100644 --- a/build/monaco/package.json +++ b/build/monaco/package.json @@ -1,15 +1,17 @@ { "name": "monaco-editor-core", "private": true, - "version": "0.9.0", + "version": "0.12.0", "description": "A browser based code editor", "author": "Microsoft Corporation", "license": "MIT", + "typings": "./esm/vs/editor/editor.api.d.ts", + "module": "./esm/vs/editor/editor.main.js", "repository": { "type": "git", "url": "https://github.com/Microsoft/vscode" }, - "bugs": { + "bugs": { "url": "https://github.com/Microsoft/vscode/issues" } } diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 1d759280af..6b8a3bde0b 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -23,21 +23,15 @@ function yarnInstall(location, opts) { // {{SQL CARBON EDIT}} yarnInstall('extensions'); // node modules shared by all extensions -const extensions = [ - 'vscode-colorize-tests', - 'json', - 'mssql', - 'configuration-editing', - 'extension-editing', - 'markdown', - 'markdown-basics', - 'git', - 'merge-conflict', - 'insights-default', - 'account-provider-azure', - 'agent', - 'profiler' -]; +const allExtensionFolders = fs.readdirSync('extensions'); +const extensions = allExtensionFolders.filter(e => { + try { + let packageJSON = JSON.parse(fs.readFileSync(path.join('extensions', e, 'package.json')).toString()); + return packageJSON && (packageJSON.dependencies || packageJSON.devDependencies); + } catch (e) { + return false; + } +}); extensions.forEach(extension => yarnInstall(`extensions/${extension}`)); diff --git a/build/package.json b/build/package.json index 0415c4e1be..56886c4836 100644 --- a/build/package.json +++ b/build/package.json @@ -9,6 +9,7 @@ "@types/mime": "0.0.29", "@types/node": "8.0.33", "@types/xml2js": "0.0.33", + "@types/request": "^2.47.0", "azure-storage": "^2.1.0", "decompress": "^4.2.0", "documentdb": "1.13.0", @@ -16,9 +17,11 @@ "fs-extra-promise": "^1.0.1", "mime": "^1.3.4", "minimist": "^1.2.0", - "typescript": "2.6.1", + "typescript": "2.8.1", "vscode": "^1.0.1", - "xml2js": "^0.4.17" + "xml2js": "^0.4.17", + "github-releases": "^0.4.1", + "request": "^2.85.0" }, "scripts": { "compile": "tsc -p tsconfig.build.json", diff --git a/build/tfs/common/symbols.ts b/build/tfs/common/symbols.ts new file mode 100644 index 0000000000..0ca98f18fe --- /dev/null +++ b/build/tfs/common/symbols.ts @@ -0,0 +1,219 @@ +/*--------------------------------------------------------------------------------------------- + * 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 request from 'request'; +import { createReadStream, createWriteStream, unlink, mkdir } from 'fs'; +import * as github from 'github-releases'; +import { join } from 'path'; +import { tmpdir } from 'os'; +import { promisify } from 'util'; + +const BASE_URL = 'https://rink.hockeyapp.net/api/2/'; +const HOCKEY_APP_TOKEN_HEADER = 'X-HockeyAppToken'; + +export interface IVersions { + app_versions: IVersion[]; +} + +export interface IVersion { + id: number; + version: string; +} + +export interface IApplicationAccessor { + accessToken: string; + appId: string; +} + +export interface IVersionAccessor extends IApplicationAccessor { + id: string; +} + +enum Platform { + WIN_32 = 'win32-ia32', + WIN_64 = 'win32-x64', + LINUX_32 = 'linux-ia32', + LINUX_64 = 'linux-x64', + MAC_OS = 'darwin-x64' +} + +function symbolsZipName(platform: Platform, electronVersion: string, insiders: boolean): string { + return `${insiders ? 'insiders' : 'stable'}-symbols-v${electronVersion}-${platform}.zip`; +} + +const SEED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +async function tmpFile(name: string): Promise { + let res = ''; + for (let i = 0; i < 8; i++) { + res += SEED.charAt(Math.floor(Math.random() * SEED.length)); + } + + const tmpParent = join(tmpdir(), res); + + await promisify(mkdir)(tmpParent); + + return join(tmpParent, name); +} + +function getVersions(accessor: IApplicationAccessor): Promise { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions`, + method: 'GET', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + } + }); +} + +function createVersion(accessor: IApplicationAccessor, version: string): Promise { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions/new`, + method: 'POST', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + }, + formData: { + bundle_version: version + } + }); +} + +function updateVersion(accessor: IVersionAccessor, symbolsPath: string) { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions/${accessor.id}`, + method: 'PUT', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + }, + formData: { + dsym: createReadStream(symbolsPath) + } + }); +} + +function asyncRequest(options: request.UrlOptions & request.CoreOptions): Promise { + return new Promise((resolve, reject) => { + request(options, (error, response, body) => { + if (error) { + reject(error); + } else { + resolve(JSON.parse(body)); + } + }); + }); +} + +function downloadAsset(repository, assetName: string, targetPath: string, electronVersion: string) { + return new Promise((resolve, reject) => { + repository.getReleases({ tag_name: `v${electronVersion}` }, (err, releases) => { + if (err) { + reject(err); + } else { + const asset = releases[0].assets.filter(asset => asset.name === assetName)[0]; + if (!asset) { + reject(new Error(`Asset with name ${assetName} not found`)); + } else { + repository.downloadAsset(asset, (err, reader) => { + if (err) { + reject(err); + } else { + const writer = createWriteStream(targetPath); + writer.on('error', reject); + writer.on('close', resolve); + reader.on('error', reject); + + reader.pipe(writer); + } + }); + } + } + }); + }); +} + +interface IOptions { + repository: string; + platform: Platform; + versions: { code: string; insiders: boolean; electron: string; }; + access: { hockeyAppToken: string; hockeyAppId: string; githubToken: string }; +} + +async function ensureVersionAndSymbols(options: IOptions) { + + // Check version does not exist + console.log(`HockeyApp: checking for existing version ${options.versions.code} (${options.platform})`); + const versions = await getVersions({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }); + if (versions.app_versions.some(v => v.version === options.versions.code)) { + console.log(`HockeyApp: Returning without uploading symbols because version ${options.versions.code} (${options.platform}) was already found`); + return; + } + + // Download symbols for platform and electron version + const symbolsName = symbolsZipName(options.platform, options.versions.electron, options.versions.insiders); + const symbolsPath = await tmpFile('symbols.zip'); + 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); + + // Create version + console.log(`HockeyApp: creating new version ${options.versions.code} (${options.platform})`); + const version = await createVersion({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, options.versions.code); + + // Upload symbols + console.log(`HockeyApp: uploading symbols for version ${options.versions.code} (${options.platform})`); + await updateVersion({ id: String(version.id), accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, symbolsPath); + + // Cleanup + await promisify(unlink)(symbolsPath); +} + +// Environment +const pakage = require('../../../package.json'); +const product = require('../../../product.json'); +const repository = product.electronRepository; +const electronVersion = require('../../lib/electron').getElectronVersion(); +const insiders = product.quality !== 'stable'; +let codeVersion = pakage.version; +if (insiders) { + codeVersion = `${codeVersion}-insider`; +} +const githubToken = process.argv[2]; +const hockeyAppToken = process.argv[3]; +const is64 = process.argv[4] === 'x64'; +const hockeyAppId = process.argv[5]; + +let platform: Platform; +if (process.platform === 'darwin') { + platform = Platform.MAC_OS; +} else if (process.platform === 'win32') { + platform = is64 ? Platform.WIN_64 : Platform.WIN_32; +} else { + platform = is64 ? Platform.LINUX_64 : Platform.LINUX_32; +} + +// Create version and upload symbols in HockeyApp +if (repository && codeVersion && electronVersion && (product.quality === 'stable' || product.quality === 'insider')) { + ensureVersionAndSymbols({ + repository, + platform, + versions: { + code: codeVersion, + insiders, + electron: electronVersion + }, + access: { + githubToken, + hockeyAppToken, + hockeyAppId + } + }).then(() => { + console.log('HockeyApp: done'); + }).catch(error => { + console.error(`HockeyApp: error (${error})`); + }); +} else { + console.log(`HockeyApp: skipping due to unexpected context (repository: ${repository}, codeVersion: ${codeVersion}, electronVersion: ${electronVersion}, quality: ${product.quality})`); +} \ No newline at end of file diff --git a/build/tfs/continuous-build.yml b/build/tfs/continuous-build.yml new file mode 100644 index 0000000000..107c7ff9cd --- /dev/null +++ b/build/tfs/continuous-build.yml @@ -0,0 +1,100 @@ +phases: +- phase: Windows + queue: Hosted VS2017 + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + - powershell: | + $ErrorActionPreference = "Stop" + yarn + .\node_modules\.bin\gulp electron + npm run gulp -- hygiene + .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit + npm run compile + node build/lib/builtInExtensions.js + name: build + - powershell: | + $ErrorActionPreference = "Stop" + .\scripts\test.bat --tfs + .\scripts\test-integration.bat + yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)\artifacts" --log "$(Build.ArtifactStagingDirectory)\artifacts\smoketest.log" + name: test + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: build-artifacts-win32 + publishLocation: Container + condition: succeededOrFailed() + +- phase: Linux + queue: Hosted Linux Preview + steps: + - script: | + set -e + apt-get update + apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0 + cp build/tfs/linux/x64/xvfb.init /etc/init.d/xvfb + chmod +x /etc/init.d/xvfb + update-rc.d xvfb defaults + ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon + service xvfb start + service dbus start + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + - script: | + set -e + yarn + npm run gulp -- electron-x64 + - script: | + set -e + npm run gulp -- hygiene + ./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit + npm run compile + node build/lib/builtInExtensions.js + name: build + - script: | + set -e + DISPLAY=:10 ./scripts/test.sh --tfs + # DISPLAY=:10 ./scripts/test-integration.sh + name: test + +- phase: macOS + queue: Hosted macOS Preview + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + - script: | + set -e + yarn + npm run gulp -- electron-x64 + - script: | + set -e + npm run gulp -- hygiene + ./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit + npm run compile + node build/lib/builtInExtensions.js + name: build + - script: | + set -e + ./scripts/test.sh --tfs + ./scripts/test-integration.sh + yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)/artifacts" --log "$(Build.ArtifactStagingDirectory)/artifacts/smoketest.log" + name: test + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: build-artifacts-darwin + publishLocation: Container + condition: succeededOrFailed() \ No newline at end of file diff --git a/build/tfs/darwin/build.yml b/build/tfs/darwin/build.yml new file mode 100644 index 0000000000..008314830a --- /dev/null +++ b/build/tfs/darwin/build.yml @@ -0,0 +1,51 @@ +steps: + +- task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + +- script: | + echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin electron + node build/tfs/common/installDistro.js + +- script: | + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-darwin-min + name: build + +- script: | + ./scripts/test.sh --build --tfs + name: test + +- script: | + # archive the unsigned build + pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin-unsigned.zip * && popd + + # publish the unsigned 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/tfs/common/publish.js \ + "$(VSCODE_QUALITY)" \ + darwin \ + archive-unsigned \ + "VSCode-darwin-$(VSCODE_QUALITY)-unsigned.zip" \ + $VERSION \ + false \ + ../VSCode-darwin-unsigned.zip + + # enqueue the unsigned build + AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ + node build/tfs/common/enqueue.js "$(VSCODE_QUALITY)" + + npm run gulp -- upload-vscode-configuration \ No newline at end of file diff --git a/build/tfs/linux/build.yml b/build/tfs/linux/build.yml new file mode 100644 index 0000000000..1234e2d411 --- /dev/null +++ b/build/tfs/linux/build.yml @@ -0,0 +1,103 @@ +steps: + +- script: | + # dependencies + dpkg --add-architecture i386 + apt-get update + + DEPS=" \ + gcc-multilib g++-multilib \ + pkg-config \ + dbus \ + xvfb \ + fakeroot \ + bc \ + bsdmainutils \ + rpm \ + " + + if [[ "$(VSCODE_ARCH)" == "x64" ]]; then + DEPS="$DEPS \ + dpkg-dev \ + libgconf-2-4 \ + libnss3 \ + libasound2 \ + libxtst6 \ + libx11-dev \ + libxkbfile-dev \ + libxss1 \ + libx11-xcb-dev \ + libsecret-1-dev \ + " + else + DEPS="$DEPS \ + dpkg-dev:i386 \ + libgconf-2-4:i386 \ + libnss3:i386 \ + libasound2:i386 \ + libxtst6:i386 \ + libnotify4:i386 \ + libx11-dev:i386 \ + libxkbfile-dev:i386 \ + libxss1:i386 \ + libx11-xcb-dev:i386 \ + libgl1-mesa-glx:i386 libgl1-mesa-dri:i386 \ + libgirepository-1.0-1:i386 \ + gir1.2-glib-2.0:i386 \ + gir1.2-secret-1:i386 \ + libsecret-1-dev:i386 \ + libgtk2.0-0:i386 \ + " + fi + + apt-get install -y $DEPS + + # setup xvfb + cp build/tfs/linux/$(VSCODE_ARCH)/xvfb.init /etc/init.d/xvfb + chmod +x /etc/init.d/xvfb + update-rc.d xvfb defaults + service xvfb start + + # setup dbus + ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon + service dbus start + +- task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + +- script: | + 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 + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin + node build/tfs/common/installDistro.js + +- script: | + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min + name: build + +- script: | + npm run gulp -- "electron-$(VSCODE_ARCH)" + DISPLAY=:10 ./scripts/test.sh --build --tfs + name: test + +- script: | + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb" + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm" + #npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap" + + AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ + MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ + ./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)" \ No newline at end of file diff --git a/build/tfs/linux/release2.sh b/build/tfs/linux/release2.sh new file mode 100755 index 0000000000..ad74ce0a38 --- /dev/null +++ b/build/tfs/linux/release2.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -e + +# Arguments +ARCH="$1" +LINUX_REPO_PASSWORD="$2" + +# Variables +PLATFORM_LINUX="linux-$ARCH" +PLATFORM_DEB="linux-deb-$ARCH" +PLATFORM_RPM="linux-rpm-$ARCH" +[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64" +[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64" +REPO="`pwd`" +ROOT="$REPO/.." +BUILDNAME="VSCode-$PLATFORM_LINUX" +BUILD="$ROOT/$BUILDNAME" +BUILD_VERSION="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/ | sed -e 's/code-[a-z]*_//g' -e 's/\.deb$//g')" +[ -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) + +node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_LINUX archive-unsigned $TARBALL_FILENAME $VERSION true $TARBALL_PATH + +DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)" +DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME" + +node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_DEB package $DEB_FILENAME $VERSION true $DEB_PATH + +RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)" +RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME" + +node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_RPM package $RPM_FILENAME $VERSION true $RPM_PATH + +# SNAP_FILENAME="$(ls $REPO/.build/linux/snap/$ARCH/ | grep .snap)" +# SNAP_PATH="$REPO/.build/linux/snap/$ARCH/$SNAP_FILENAME" + +IS_FROZEN="$(node build/tfs/linux/frozen-check.js $VSCODE_QUALITY)" + +if [ -z "$VSCODE_QUALITY" ]; then + echo "VSCODE_QUALITY is not set, skipping repo package publish" +elif [ "$IS_FROZEN" = "true" ]; then + echo "$VSCODE_QUALITY is frozen, skipping repo package publish" +else + if [ "$BUILD_SOURCEBRANCH" = "master" ] || [ "$BUILD_SOURCEBRANCH" = "refs/heads/master" ]; then + if [[ $BUILD_QUEUEDBY = *"Project Collection Service Accounts"* || $BUILD_QUEUEDBY = *"Microsoft.VisualStudio.Services.TFS"* ]]; then + # Write config files needed by API, use eval to force environment variable expansion + pushd build/tfs/linux + # Submit to apt repo + if [ "$DEB_ARCH" = "amd64" ]; then + eval echo '{ \"server\": \"azure-apt-cat.cloudapp.net\", \"protocol\": \"https\", \"port\": \"443\", \"repositoryId\": \"58a4adf642421134a1a48d1a\", \"username\": \"vscode\", \"password\": \"$LINUX_REPO_PASSWORD\" }' > apt-config.json + + ./repoapi_client.sh -config apt-config.json -addfile $DEB_PATH + fi + # Submit to yum repo (disabled as it's manual until signing is automated) + # eval echo '{ \"server\": \"azure-apt-cat.cloudapp.net\", \"protocol\": \"https\", \"port\": \"443\", \"repositoryId\": \"58a4ae3542421134a1a48d1b\", \"username\": \"vscode\", \"password\": \"$LINUX_REPO_PASSWORD\" }' > yum-config.json + + # ./repoapi_client.sh -config yum-config.json -addfile $RPM_PATH + popd + echo "To check repo publish status run ./repoapi_client.sh -config config.json -check " + fi + fi +fi diff --git a/build/tfs/product-build.yml b/build/tfs/product-build.yml new file mode 100644 index 0000000000..29fc43598e --- /dev/null +++ b/build/tfs/product-build.yml @@ -0,0 +1,413 @@ +phases: +- phase: Windows + condition: eq(variables['VSCODE_BUILD_WIN32'], 'true') + queue: + name: Hosted VS2017 + parallel: 2 + matrix: + x64: + VSCODE_ARCH: x64 + ia32: + VSCODE_ARCH: ia32 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + + - powershell: | + $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" + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" + npm run gulp -- mixin + node build/tfs/common/installDistro.js + node build/lib/builtInExtensions.js + + - powershell: | + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-copy-inno-updater" + name: build + + - powershell: | + $ErrorActionPreference = "Stop" + npm run gulp -- "electron-$(VSCODE_ARCH)" + .\scripts\test.bat --build --tfs + # 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-229803", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "VS Code" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "https://code.visualstudio.com/" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\"" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "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 + + - powershell: | + $ErrorActionPreference = "Stop" + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-setup" + + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: 'ESRP CodeSign' + FolderPath: '$(agent.builddirectory)' + Pattern: VSCodeSetup.exe + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-229803", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "VS Code" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "https://code.visualstudio.com/" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\"" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "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 + + - powershell: | + $ErrorActionPreference = "Stop" + $Repo = "$(pwd)" + $Root = "$Repo\.." + $Exe = "$Repo\.build\win32-$(VSCODE_ARCH)\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" } + + node build/tfs/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip + node build/tfs/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $Exe + + # publish hockeyapp symbols + $hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" } + node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId + +- phase: Linux + condition: eq(variables['VSCODE_BUILD_LINUX'], 'true') + queue: linux-x64 + variables: + VSCODE_ARCH: x64 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + + - 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 + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin + node build/tfs/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)" + DISPLAY=:10 ./scripts/test.sh --build --tfs + # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)" + name: test + + - script: | + set -e + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb" + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm" + #npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap" + + AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ + MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ + ./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)" + + # publish hockeyapp symbols + node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)" + +- phase: Linux32 + condition: eq(variables['VSCODE_BUILD_LINUX'], 'true') + queue: linux-ia32 + variables: + VSCODE_ARCH: ia32 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + + - 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 + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin + node build/tfs/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)" + DISPLAY=:10 ./scripts/test.sh --build --tfs + # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)" + name: test + + - script: | + set -e + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb" + npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm" + #npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap" + + AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ + MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ + ./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)" + + # publish hockeyapp symbols + node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX32)" + +- phase: macOS + condition: eq(variables['VSCODE_BUILD_MACOS'], 'true') + queue: Hosted macOS Preview + steps: + - task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + + - script: | + set -e + echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin + node build/tfs/common/installDistro.js + node build/lib/builtInExtensions.js + + - script: | + set -e + VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \ + AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ + npm run gulp -- vscode-darwin-min upload-vscode-sourcemaps + name: build + + - script: | + set -e + ./scripts/test.sh --build --tfs + APP_NAME="`ls $(agent.builddirectory)/VSCode-darwin | head -n 1`" + # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME" + name: test + + - script: | + set -e + # archive the unsigned build + pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin-unsigned.zip * && popd + + # publish the unsigned 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/tfs/common/publish.js \ + "$(VSCODE_QUALITY)" \ + darwin \ + archive-unsigned \ + "VSCode-darwin-$(VSCODE_QUALITY)-unsigned.zip" \ + $VERSION \ + false \ + ../VSCode-darwin-unsigned.zip + + # publish hockeyapp symbols + node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)" + + # enqueue the unsigned build + AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ + node build/tfs/common/enqueue.js "$(VSCODE_QUALITY)" + + AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ + npm run gulp -- upload-vscode-configuration \ No newline at end of file diff --git a/build/tfs/win32/build.yml b/build/tfs/win32/build.yml new file mode 100644 index 0000000000..d55b6f1bde --- /dev/null +++ b/build/tfs/win32/build.yml @@ -0,0 +1,212 @@ +steps: + +- task: NodeTool@0 + inputs: + versionSpec: "8.9.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.3.2" + +- powershell: | + "machine monacotools.visualstudio.com password $(VSO_PAT)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII + $env:npm_config_arch="$(VSCODE_ARCH)" + $env:CHILD_CONCURRENCY="1" + yarn + npm run gulp -- hygiene + npm run monaco-compile-check + $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" + npm run gulp -- mixin + node build/tfs/common/installDistro.js + +- powershell: | + $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-copy-inno-updater" + name: build + +- powershell: | + npm run gulp -- "electron-$(VSCODE_ARCH)" + .\scripts\test.bat --build --tfs + 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-229803", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\"" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.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 + +- powershell: | + npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-setup" + +- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + inputs: + ConnectedServiceName: 'ESRP CodeSign' + FolderPath: '$(agent.builddirectory)' + Pattern: VSCodeSetup.exe + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-229803", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\"" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.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 + +- powershell: | + $Repo = "$(pwd)" + $Root = "$Repo\.." + $Exe = "$Repo\.build\win32-$(VSCODE_ARCH)\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" } + + node build/tfs/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip + node build/tfs/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $Exe \ No newline at end of file diff --git a/build/tsconfig.json b/build/tsconfig.json index b68c9b6daf..d60805e7f7 100644 --- a/build/tsconfig.json +++ b/build/tsconfig.json @@ -7,7 +7,6 @@ "preserveConstEnums": true, "sourceMap": false, "experimentalDecorators": true, - "newLine": "LF", // enable JavaScript type checking for the language service // use the tsconfig.build.json for compiling wich disable JavaScript // type checking so that JavaScript file are not transpiled diff --git a/build/win32/OSSREADME.json b/build/win32/OSSREADME.json old mode 100644 new mode 100755 index e1dbed4b2c..c7f63b03a6 --- a/build/win32/OSSREADME.json +++ b/build/win32/OSSREADME.json @@ -1,198 +1,10 @@ [ { - "name": "dtolnay/isatty", - "version": "0.1.6", - "repositoryUrl": "https://github.com/dtolnay/isatty", + "name": "Amanieu/thread_local-rs", + "version": "0.3.5", + "repositoryUrl": "https://github.com/Amanieu/thread_local-rs", "licenseDetail": [ - "Copyright (c) 2016", - "", - "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." - ], - "isProd": true - }, - { - "name": "rust-num/num-integer", - "version": "0.1.35", - "repositoryUrl": "https://github.com/rust-num/num-integer", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "rust-lang-nursery/lazy-static.rs", - "version": "1.0.0", - "repositoryUrl": "https://github.com/rust-lang-nursery/lazy-static.rs", - "licenseDetail": [ - "Copyright (c) 2010 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "rust-lang/libc", - "version": "0.2.36", - "repositoryUrl": "https://github.com/rust-lang/libc", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "retep998/winapi-rs", - "version": "0.2.2", - "repositoryUrl": "https://github.com/retep998/winapi-rs", - "licenseDetail": [ - "Copyright (c) 2015 The winapi-rs Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "mrhooray/crc-rs", - "version": "1.7.0", - "repositoryUrl": "https://github.com/mrhooray/crc-rs.git", - "licenseDetail": [ - "MIT License", - "", - "Copyright (c) 2017 crc-rs Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "rust-num/num", - "version": "0.1.41", - "repositoryUrl": "https://github.com/rust-num/num", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", + "Copyright (c) 2016 The Rust Project Developers", "", "Permission is hereby granted, free of charge, to any", "person obtaining a copy of this software and associated", @@ -250,141 +62,13 @@ "isProd": true }, { - "name": "rust-num/num-traits", - "version": "0.1.42", - "repositoryUrl": "https://github.com/rust-num/num-traits", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "slog-rs/slog", - "version": "2.1.1", - "repositoryUrl": "https://github.com/slog-rs/slog", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "rust-num/num-iter", - "version": "0.1.34", - "repositoryUrl": "https://github.com/rust-num/num-iter", - "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "vitiral/build_const", + "name": "Sgeo/take_mut", "version": "0.2.0", - "repositoryUrl": "https://github.com/vitiral/build_const", + "repositoryUrl": "https://github.com/Sgeo/take_mut", "licenseDetail": [ "The Source EULA", "", - "Copyright (c) 2017 Garrett Berg, vitiral@gmail.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." - ], - "isProd": true - }, - { - "name": "redox-os/termios", - "version": "0.1.1", - "repositoryUrl": "https://github.com/redox-os/termios", - "licenseDetail": [ - "MIT License", - "", - "Copyright (c) 2017 Redox OS", + "Copyright (c) 2016 Sgeo", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and associated documentation files (the \"Software\"), to deal", @@ -406,36 +90,6 @@ ], "isProd": true }, - { - "name": "redox-os/syscall", - "version": "0.1.37", - "repositoryUrl": "https://github.com/redox-os/syscall", - "licenseDetail": [ - "Copyright (c) 2017 Redox OS Developers", - "", - "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." - ], - "isProd": true - }, { "name": "Stebalien/term", "version": "0.4.6", @@ -717,11 +371,11 @@ "isProd": true }, { - "name": "Amanieu/thread_local-rs", - "version": "0.3.5", - "repositoryUrl": "https://github.com/Amanieu/thread_local-rs", + "name": "dtolnay/isatty", + "version": "0.1.6", + "repositoryUrl": "https://github.com/dtolnay/isatty", "licenseDetail": [ - "Copyright (c) 2016 The Rust Project Developers", + "Copyright (c) 2016", "", "Permission is hereby granted, free of charge, to any", "person obtaining a copy of this software and associated", @@ -750,13 +404,13 @@ "isProd": true }, { - "name": "Sgeo/take_mut", - "version": "0.2.0", - "repositoryUrl": "https://github.com/Sgeo/take_mut", + "name": "mrhooray/crc-rs", + "version": "1.7.0", + "repositoryUrl": "https://github.com/mrhooray/crc-rs.git", "licenseDetail": [ - "The Source EULA", + "MIT License", "", - "Copyright (c) 2016 Sgeo", + "Copyright (c) 2017 crc-rs Developers", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and associated documentation files (the \"Software\"), to deal", @@ -779,11 +433,43 @@ "isProd": true }, { - "name": "reem/rust-void", - "version": "1.0.2", - "repositoryUrl": "https://github.com/reem/rust-void.git", + "name": "redox-os/syscall", + "version": "0.1.37", + "repositoryUrl": "https://github.com/redox-os/syscall", "licenseDetail": [ - "Copyright (c) 2015 The rust-void Developers", + "Copyright (c) 2017 Redox OS Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "redox-os/termios", + "version": "0.1.1", + "repositoryUrl": "https://github.com/redox-os/termios", + "licenseDetail": [ + "MIT License", + "", + "Copyright (c) 2017 Redox OS", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and associated documentation files (the \"Software\"), to deal", @@ -833,46 +519,11 @@ "isProd": true }, { - "name": "rust-lang/time", - "version": "0.1.39", - "repositoryUrl": "https://github.com/rust-lang/time", + "name": "reem/rust-void", + "version": "1.0.2", + "repositoryUrl": "https://github.com/reem/rust-void.git", "licenseDetail": [ - "Copyright (c) 2014 The Rust Project Developers", - "", - "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." - ], - "isProd": true - }, - { - "name": "ticki/termion", - "version": "1.5.1", - "repositoryUrl": "https://github.com/ticki/termion", - "licenseDetail": [ - "The Source EULA", - "", - "Copyright (c) 2016 Ticki", + "Copyright (c) 2015 The rust-void Developers", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and associated documentation files (the \"Software\"), to deal", @@ -896,7 +547,7 @@ }, { "name": "retep998/winapi-rs", - "version": "0.2.8", + "version": "0.3.4", "repositoryUrl": "https://github.com/retep998/winapi-rs", "licenseDetail": [ "Copyright (c) 2015 The winapi-rs Developers", @@ -923,7 +574,7 @@ }, { "name": "retep998/winapi-rs", - "version": "0.3.4", + "version": "0.2.8", "repositoryUrl": "https://github.com/retep998/winapi-rs", "licenseDetail": [ "Copyright (c) 2015 The winapi-rs Developers", @@ -1029,6 +680,264 @@ ], "isProd": true }, + { + "name": "retep998/winapi-rs", + "version": "0.2.2", + "repositoryUrl": "https://github.com/retep998/winapi-rs", + "licenseDetail": [ + "Copyright (c) 2015 The winapi-rs Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-lang-nursery/lazy-static.rs", + "version": "1.0.0", + "repositoryUrl": "https://github.com/rust-lang-nursery/lazy-static.rs", + "licenseDetail": [ + "Copyright (c) 2010 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-lang/libc", + "version": "0.2.36", + "repositoryUrl": "https://github.com/rust-lang/libc", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-lang/time", + "version": "0.1.39", + "repositoryUrl": "https://github.com/rust-lang/time", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-num/num", + "version": "0.1.41", + "repositoryUrl": "https://github.com/rust-num/num", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-num/num-integer", + "version": "0.1.35", + "repositoryUrl": "https://github.com/rust-num/num-integer", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-num/num-iter", + "version": "0.1.34", + "repositoryUrl": "https://github.com/rust-num/num-iter", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, + { + "name": "rust-num/num-traits", + "version": "0.1.42", + "repositoryUrl": "https://github.com/rust-num/num-traits", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, { "name": "slog-rs/async", "version": "2.2.0", @@ -1410,6 +1319,39 @@ ], "isProd": true }, + { + "name": "slog-rs/slog", + "version": "2.1.1", + "repositoryUrl": "https://github.com/slog-rs/slog", + "licenseDetail": [ + "Copyright (c) 2014 The Rust Project Developers", + "", + "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." + ], + "isProd": true + }, { "name": "slog-rs/term", "version": "2.3.0", @@ -1790,5 +1732,63 @@ " defined by the Mozilla Public License, v. 2.0." ], "isProd": true + }, + { + "name": "ticki/termion", + "version": "1.5.1", + "repositoryUrl": "https://github.com/ticki/termion", + "licenseDetail": [ + "The MIT License (MIT)", + "", + "Copyright (c) 2016 Ticki", + "", + "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." + ], + "isProd": true + }, + { + "name": "vitiral/build_const", + "version": "0.2.0", + "repositoryUrl": "https://github.com/vitiral/build_const", + "licenseDetail": [ + "The MIT License (MIT)", + "", + "Copyright (c) 2017 Garrett Berg, vitiral@gmail.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." + ], + "isProd": true } ] diff --git a/build/win32/inno_updater.exe b/build/win32/inno_updater.exe index a896061751d4bcc3a187c924fc3c184e923d0916..6d83b2b748b3eafcf10d92e52f84fd1b96e87906 100644 GIT binary patch literal 371200 zcmeEv3w#vS_5W-#BokPe1y@-#%Brg-iZm%v6A2Q?k^~75AUw1PSP=nH5q2eN#ErWP z8HQC;&sQ_szU>V9%c2Z93?y z8|NLo_sN)5;s3h=PpS9K`G$C*huUy!IITgr%+SNoOAyT9!cztoJ>&v}O$eqC zXR>%WMiAmyYTHvVAqH9U|K3fA5wc2HMk+^z*)#HBC2c!J!9pmk-2}^PEUNuaLpP!M zGC^3iMHC9#r?9t~TTvb%3D2zPbkLau`cCyX&~ayx1BuQ)dcCNwRJEu-t02r6xM1e( zj@t!c*(xMZ-T#iKrG3UMFk~RlCd{OyM*I-&jh*sU4!mpDoS6$zT_g)aH=b{Er+irh z9rKWjCkrM$A9xV`mn8_50~ah@a0en8@4!Q$3@_U{<;xnl;LdsXAtUip08a%Qo=fnI z`pXi8;Zd*uUj|jXO$?b*E2}s2zfhq~YIdJq!x%FhfUJ9JZuo$>%^!` zEM1@+63g*wha4T#6K{=a2VuhGN$$f&^;SvQ;@w*`S-sJ5kv7F33KQlE1=>Ueyp_&g z%6@I;F+q@ftR+oSM4K|zCf3?*5;dW+Uum77t$cz}26WPK*@PT9c=nESuQN`Y{ zeIg`#N>J2ix8=_!Z6u<{n?%&mh`2nEm^T2?1rxMqQNrD9a5@o3swm(|dM)@0ZSxRL zWZ`_9b+(8)Y9pq_5}VXwn-x{Esrj}fcgUdR+l&fo=$wTTB0)*r8>m2jU%oA`f~?Qn zOJ~1`3Tgj%hRPEwKtj+qK}!UFthI5(Tre$1^xgS6xOQ7LP!9mB z(-em-1sKygMo^HMS{dvu_qPiI%Yq0zEo!072uh`lYNgO-$6Emi&O%s}J?j7)X<3N1 zs}5VbQlIT_5WOL#FiupAaY)KUlBndzNr*B6Yoa6HRcw=D7K}iCqnaazt`C`rCpn_K zNE94a^(J?bBrTG(q)@CdIVfpXJVT4VqDB~mpk~6)Bzn670cwu|v~jw2G2W;t#t=V< z{hZ}Hrk;-FvbRqt6bjl=#;m=*C6+2~RzW4Wksi1VX@H%k{o^E3@@*-M@n+;ntR=1z zTZf6tFk|4iCqp4t6f8wi5n%}hjNZMR|H>Fi$q^mbqvb{aLD5|+&Z578a(@rO5!^!s zM{jk}SK1(8VwKB7z+G!{S2sEjxQiiFvL_Qrv_6OjO(HSChH&6Y#BPQ#uQjzo!m?u^ z!draBHq&eY?{kI8+H*abzol_PsZ*9MvsAW{XcInaZ(oX@; zeb@pLk{~lSkYRfOSR_X*EG& zj_YAFG8I7J)j{gRpkq=&XtEXcRYhB7tnB?1rVwgqQTEr0Ht|L~H6>ZQNR#5-^uj+` zycyBLI08UqqsA6M@U$QjO`aI|13>Z40M=iDxkuAR1S9Wb2nNK#XH16yl43>MF$;F(|o$Qqg{2jjE_vS-y6 zaIEP-U}w5LK+UE$u-j~dvyHOH0+Q8H+$1OY%vo8Kww>AymBTNL5n}SUQ;Uh)m28tb zLaGtE1?t26^ks`clvR^$Hh{HC4R~V%b6uG>@YYSaieX=4p^^48)vM5EK{g9&k;rNV zB@WjJ@hPf2sbD-87?|J`fKMdw@u5MJLIndNIAw~ARb^l^o<(a;DnR2~3nFkWfO}pW zT-bKKF0WH7bGY>#TL(#?w4Ic61@{dC!RbxX;X3ain0mD>tWi(j`dx8{;Yx3-19;;p zgk9y09_)rEq-zAVp%A>3^=N*%tPwHttJ@|2AxVCDqvYQ&C2Ua&L?tEM(fUS7TFeZP zoNWr!f31VF1k1`_E=D(97uV*uoV&huZ`SoS9sylnFVKES`uf~~uJqLu{|)u^)w9#r zDvtF>eTAH}4)tvG>OZEhtWkeZ`Z|8nwv|B!GQ{HK0KdG~YX_X?~EyC2_#sV6dTq;G4 ztarJrYoo>nKr*Hly~|}okmxSgN?opjFcjKsf%0&dOW@Gy0w9Pth5>0iK44mG;=QgZ z7U|UOj*JbfF(T0KnqYzB0iuv7(mUTaig@SCx>k%E3enwKkT)G=s0LH!&mB$_Q*Xq( zUMt8*(waDG^r+}d(-D;x?s^BXuJ`h&t~aGa*NaXUU2jsCUGKpNcUjk)M_n&tbX(_( z5ehiHj55MmV!dzvS=5Zi9aiMC>D@2uim6tJPjBD-rUU+E1V5_#%5ZMIxj0A)7+E}nRUP%as^6H!XUZVq?C>A^TA22yk{Y*fy+7cQOxs?iI-6Yhnr;a+%nh=v4b+5g_(<}WX6 z)D?Lt0($@ZY(tw0kEIsq(q9fjY$0yn!e4HtHXwib<*@S7Y)MCd*|N8*{&xiplh+x! zM*|7-O(a!3qsv@q%MUxr%zZ9syr1c8M|U}!BRysJ+c!#Q&&6Hd9cJfg-Q~w9*Z-Zn zd{LWLwYkf^DDvC6%YEA5wzy(IQd56V`f3|@Dt$fF^zHQZ>VU4VS0SM5 z>-BqnNcy^VXIJ`~g5mggp|1tAyVTc%9O;kx`d_54)YRXTzB)#qN?&jM{M+g4Lm%n- zx(ESXUzfc5L(*4iTUYw(!Z`f9&{yjdUFz!~j`T-;{V&p2YU=MvU)PO1mA)=({C4`f zalfvwwFv0?x(kbc;q{*X{P=as=C1U08;0B8g}!cE(WSn+Inp2X^}k48sj0sweKqHt zN?+eQ{O$Dh!Vh$P?Tdh}uUBsQA?fQYbzSMJ_0#W0Un{%rUw3k(KkDm$k-kz>e^2^4 zbNH$B_3FU4)7QE0>H2yX0=m9Fu#8Ta>|ZZm&yfD8um45* zN=^Me>FaAZol0LH`smx~YsD^IUtdQ+*VmewACkW2`Mc8BN({HZ3w@pM?NVPCa-=`% z>wl5HQd56V`YH}SmA-D=e+qro_fx1N64lY|wp7@$bCEV4V{1jH-HTuC(6zS(0bP5g z>Nf5D&+lGb_Rp@gH|9VG?Jcxrv0W76>31;lO%!a;B3q7~()e_j>iZhUdP?>Ej&?6* zo_6u&}E zy8h<9{X^2Qa9{=U9K#-*f4H{}a0z&qaT!t-mMz^$a?d z{@(oF>Gc;IggWhL#BMt5RPWUJKDtR)-eLrFj z|NLgHuEOOA=qg-?0~U{pW9UHma-rjNg&}EDku83UAyIt-?|Id%E*_QTva(uhTU)9sylr zFLE(x6l1=R~l>D*+FB!;r`^7GxeEI@m_5{JlNv$>F_ zzRBWo1l#rObHe0F+M7_~yX$5ubtNsr#$OG_Sr?=1ek@K9N@@g`|LT(6myY@Q$+qmH z*T)LV_6jPDtPXi{B~E~uqJ{&p5+5F;3I0393f14*ff&}?>+!Y|dj{6Ga*QeSpi>h8!)c{ze zj8~V`u51p4M$JM*9z|S9p?nG@QOK?{sbG?}5;)4KW-8}U>~hAJ^P{R+Fix8VuApux zDz)*~27c2Y2(Y#Vlk}jR?6H{;rl+7k8B6%>JNg#8 z6#zBFF$wwg&*axb?&iz|7vlhiaZV+*7W@X9=M;P^O~Qf+*$`D@N$tFNL8$2O4USVb zDb4V?@|zC$55>=^S^=Vz*3?jPmD1>MNTBOx1oz1va&9f%3((SE&fO=MRlGIIE+p(r zs4WSF`hobRb`hnT{aUR2)^q#D*aiQ=*ph?I{SjH;RPVFLHx8-40QuaB$X9~nTcM|~ zTf~mDQ`0Q{0>@U|&4cBo*!qqp#Ytj!YhQUO<}UDtJ0{#MnX-Eu-mY=j9FPNcLfp6H z(QyW0Na%Ms_2&MN@PDS@fPB+lXM|Uk>>$ERS{UW;5#`jPXsH>f=1er=Y;a

^={*(UB;} z3#bCqb9e6GA8VJ+EBT$o%t7?iRBtZ@{b^~RN%+$V9Hn&v6oWe7Z+5B zS#~lR+z?;->@@c!(!x9y;-#q;OWT<6(?Z`td_%D8R5JogV`T zG9X&m4Fha0!-VR(5DPG36fq1Gr4j3pX4JWYpatbPZxHtaPo9V1iwOESFaUZPZlcT}6}S~ezv-p?xrw+2$A}zS_jo$JT5ifg1RV+0TG;XPa@R0KTtN|< z9x*f=v71F`Ga&AA53L#qaEy`0Oa-Wn3q|TDol^Wb@2CznkS?m187ftvEN9}SOGJe@ zncd1zSg>SRw8&}iTtS_!R?r!xnM!mm@n?rJ@f0X;Whl#M5IbOY1Z__@#;~k##Oyk# zj`o?IlvM;LSKyW9oSjGs4_%}uXpIOVz2PRrepti3hOmDRf1we;(Zs16d@F6+2oe5; z>F#ucZ;I%fZ^XqPHhIJz+<{}DK8te5BaZp<%xad|Td513Y_9_+Nkh>Z7H!(qf`A(x zEb-3x)XG3AdJG5#38$crHo}?}$}6k9d*zjt-Y?~q>!fwkfzp?4zoXK_EN*{d=}OxZ z^n%m4XeT2LjF|?|jU;q=g~wKjWT39Y11bC+hMT`5orE0eB-L^me?3{3*=;`m}zic4wh2=1X!lm7;)OtGN>GS*(r2w%5!+3#t66S#w5K>h^?~sFX$cu z)A1vhEw}v%V2DqD##4EdX#^}HX>zH@hB2I=)Riu`y@UX`*hgMEyf@{qELTcPOTo@! zotPYB(>ZSvCx4e-2o?&+^&qHMO zZh8w{jo=UUH=O9bHSo9dI9Ws<5X+0k^XAKp!uK5Ei)B6YrFBC-!JEAF2!0j6KM*UI zDgDRW1)sUje<KhX^)&==hyoC z?7}r5X+Ah{$gok_=5OtRSVNUk2R2DfN0nWMEu=i%D7FT&aMW;|apELENAu`im5@3Gxfp+lu)tKf0x-g!aZt6Ao8E@q zT$=;_m)r3Z*aSff8*bS%5Lr}RwzG^hQk&e9s>awr9MI4_cy`Hwv#UQ-m!?C+1ZG>> zaU#%x6A?Z*bUqY?`2cY#L@kRMFSuYbcJOYRafFKuTv@X5@y4#9uP6JHn zcYt9=I}8rAK=2xB&k}&w+jBUzXBK|sTtB!%Vog^J3RGddlO{|(yUr_+1eqb|mlN@0 zL}sz5^>SM-Sku5mpsLLTFKtUiA4Ymj7EPURY}0bf@*$jFVgu2e zvYEZx=$%*u;>f%d6~GZ7LDEIWg=FD@Eb7K1B7@{4WVawYUBL)r;XfKN7AG)lRF0js zf^6|0fq}T53&&q%pKnlGca#Ks;a;zR>1izFI*5t+NrPjMxp@E&)mUY zGIzQV!hp&H85f3p+YG7}-kBgI*U&rzt0ZP#0;D}{YIkiL(V&+)fJx}LqdEZU0>2AG z58|cH#Low5M0}ehpN@Dlbpogs@A%Lf)Czd-vUfs@wsnaMKM#dSD6YdWbuGC)<$w9} zpa0x+rLxl>>;bQ9e>sg`w;w7w@Kq@Es81YEj7_eV?Rx^Bl0%82tq^c%P@&q3DXcnQ zq;4b1&4YIZdk9Yt6SXMq55^ld1^%YHqb9&V*RDaS!@wXOw<1zmqp!}9C8UPlAcOQ4 z8D&C(DNWL<(Ec~b+X{?_`$iqn^F(V8_#YcFF}T%zAl?@5Khe{-0OJff`?&w8$a=w& zPng%)q%=1jaEIdLr7O`>jw+}5#JAG`4txnHd&pBkUkQJP&nqVTeNWQ-qIZKla(hWD z1?9&)C>b~etb~1A_Xzf_$`+12)YEq>!~PyTQjYy&hW!KLnENEK-wGIG8TPjr_GVyj zIV$%teUMfAGjjFaCs6H76!*9E zWYf4KsfRe5D!Ug0pIo+#rf}bggN*GAx(^!Mo6-VwA2t#4IuUYFY6ug{fFBe~7~Vh% z=G#e{2OxPZIrCfxx{(fWS>}=-_>!6!aAFBgEJj|<{Xr!S`Y>m{;8hIzs+HYrWaqA) z>E11PcgQ1K<&pJ)jXD7vA&Y8{wKO~d6(qHn`b%2aU~b7npcvN=zocjV4a=(MQZ|+x zph6|BJntNyccGqlAtwGSqu-ULtp zc#a;a=uIpWaJ#UU{u3Z!m%LgrzO=oqPmsUYHbK7iZ8kx^TYl_Xf`@|2ae#Xna5xn0 zWsHX1nA67~7FQ3)BUj0r3>__Syg}wrUK+#8CZ>jzjsDi2B`pNhw;&`xu?!Vslf8i$ zgh-MuhK{L&-vavtjPFDJVR{2=srpefNe%kAikbvHm=zCtCh7O-4WM_LSqhYY8Vb4g z%gMXflA3Qnx>HNtVA$<$F!+zgxa-m~Y8h_%7k)Xn*|5ofu)F^gk)cl5rz7tkxBspEYT95l8n*gB>F)nnOgO2}_jGSR-*dyCPBY)rVXo(G)b5+()hC$Z zUg^@-)Wh5ars)WF@`?p_YS_w(iIkmGw;-!qwVb=heQ;=4sA*abE!Z|ilDM6VeL~=T zB(+O`)pQ^1A84Vb=%L0@)9buwF9B|3U>sz!lDw@c7&hTPdyHYuHtHhhG>={Xb;z(Q zI1Te<=r3Nu&l@Bmf&ZZpjGGWxNg>FNzy_2US&_dBq3Gz8TFF6r)fuh)`=2tHK-*$kDNFby-; zsHHs3xJ`>|JfeR%f@c$WY(hBpEh-F<^8rdIe*tqN%5i`RJQW6G0l&3Bze+1d9aouX ze^xtgHQ+ly%A-XvQ<0wLip1JpCW{vaS6D|o;q#02i%ZEC0&^>R?NiWoZ_FL z*;nZN3|}m$Kk4Ho!{}0X18&wt>thv6v}ve3pima=Fa2qCFjC5WI1Q>NDhFV@$Oigg8HAvl0VlD-!+}_YXPAvjAz<3= zEBTUQ1UCgHG6vXT`=-3XR*7)iEXJ7cG#ylSu^A8lk#2X_WG1g?j(DT8z3Cu^6#hUD zOmPE!T5?TlC2Uo?I#$Hi*>yKF;zSa5BJzFyZlrg(R~z6}{!+O9&UJFm9vHc)@-He4 znr|L>I~B+CFwqZIq$%_GrUEL1xJ1OI1D2Kb1@|Ya57PDeHpFHkHi^v=p+`^}@Rq{f zTCm$f`w-WOvh_Jf{3=7>dPpsH8$8N-Up_1fPjgi}=Cj#O9vhzGs+K)}1%6_NMH@}VvY4xDpKDCOzQu;g4whmL|8Cr z23&XrZJ^QE@OlfhR-DH`O@kA=1WPl#X9gSB8SG0Otb3iEeflLVG!PUKO(&^>Y6{I4 zwc^bTd*m}0?!)xym#owc$bfY#wvq+UiY@qoVrh}wZo$u3hurp(R_ey(rAvu98{zDL zV%q?0IKY#pvgtX%&fin$-Mzm*778JMBE(%%%r>_*f?sb{frzB(5|2-K=ZDi>BX;ikTi}7_F#}(Mi z)gby3v+!}Go792Ykms;#W+E*kFGUEuU#>HRf)?#cyv&_J(Uwm1iqdqs7c040k+9*LovP;bsm8#_9850UZ&Qb2>+jm+GFFy~w$iCKL-6(zh=U+3 zO7d$)Y|=!!Y-~WHQjY>uY?I42)aWX;+YHDb6HN7MeOR*^8(A(C3#WH35`!YK>Lf`y zHd)KSd;km{Xr`;>@qMKIv2l~fVZY_eY=d}eB@*e|J<2idUfc$Ze1Rl5PFxDyhZ7lV z>C;!VrAozftrLXZ9%1D<0fD$?pH7ARi^r~3WoO!HIp2Tkkm(L+m!?`m#Ep| z8W(axfY8t&O#Mm zMZ(@5XiMk@{>`mi{>`l<3>!stsQ%rpRZm09@!hRg@YKJ%^#+32-Y04+DUGz{PZR@S zs|@tHr7=?2f9B1znLhuP2M!dn^?KHcv|p2lK-FQfoh`{n7TcAYrVo6MRP0NTM;`OH z^fzpWPtsLJOmq*+q*-o1a*^r*)fB^a@0ZkVnB{p>7 ziO;#Q4$0iW-!05q;u}E3Xr%Mq3-pnKeAc&Q>fKQm?|x{+WoJ>`w_)88fhf>YcIw?v z-n8k})Sc->nA(U)dW9n$p!bR?`tF4^dPfoJ^N0wGjx@T@(~;7y3L+wt_jzw%7!AR4 zuOp=G&VxaI@ck!Ax70&iz_73q5@By7w;g*c<~2HBVN2gF{k1MsXQNlNXom4(Z<$^ zl%v?agw?BnvXkc2*(z1_oN5}A(u%9^HJO6RwerZOl9Nv&D7#1CmyS4K)(hKxljvWY zxe_ysehf$jmwN{$uKQ5VvS-JP#uoTb#W^+i;JxG{wrsQBH}C3@;T<-IB)ftrQvT1l zyE7CGG;GHzbBj!qZT>m_)i=h#rEPl8_uBasOkQ7c`)B>`l1F~Q76`W~$CInJA2MLC zmQ-@`&A}MvE%gJ~oGQYVTqBn~M%ZC=M5XZ>{4TuY=8{%k1InkTmoU<>zT2p;!?`ii zq@8yDulr{i_9-=(%>7uzeDTpaA>zc4d-3D*+(=(@m2;0l-QtBs$pFSq0@V0&8i(x0 zxOmY8D*U)sHkC@--*;g!8;pUQ4tpxWOJGiZc`0`ND#vFNQQA}ZCISotT$is3F)6^} z7DwVrv4qSg3g$-Qicp&8n-q@I+c!&HU{p3~sE9BfqW}}OAdgk&O7J(0%SH<)H@I55 z$xCUjRxaDHDlRtDm-(wKA@qrQn}oUd(rYn}mpzPt(LVUQBv>~ifR$~p3xxt~8R2U6 zW>Lws`J4vt28>{vh|#kBYuQteEHLxpvWYZUOCzK{tnbNX8$COaiMlqkT>3}QMyDvA zP$@h5M&Ga|cXKz{O(Sv74!P8i3=m~=;6+H4TsFe6Y;=sf(X?!Z6+5$6iGc(vH$nu> zifCIE!>5>e1?HKl0%ZW8EnluzKtX^i@O#9RxghilY{P+@4 zF%Lvu^m-WxZYDrGwiG!{if zEQ-`2ANm2%hWKW1o=Us7P-(>a_s1pFDgMCUQHr^|6GBertQKfXo@ZXis@Ndk5#N?F zPfsy`fhPBQ;~3>WNm*pXo3S*$bh4pzY>W!iKUP$xOM$;(RwQ+Ua#W|=od+ikbf@_n z;u8GS6puUM=}}X-TdcCDh}^!GD;zmE=_K@qO4DeuCN@5B7vK=ve9jnm!%(!SS!vX3 z^Vm-TGoxAd%tdD>mnCH>HSUjw24>(5brc~E1E{k^%h4A=Q8WeriH-!fJOmtsnZ za?#YGdwmQt`0_%^Pi6ZN zZ#ceknHaCsx|`!<_dfsx>v_0EPb{Z?*yM%2qA{Ff(w{XR-wE`D8)2h}~H zUI`LcWbY!lfQpv-sZtyD{Z9}m`KBA_V@v`nYTt)J;zb$Fj=pkPyr;70a(rwqP>;0m z_d*rTwLjL?f;svI#0D0U&|+9#x{fBCT_5((*y%`-%LXa$4Oe!$KOU;2+2pd%GaD8p zvq>H-6l5HCz`FcYPj=WcgErkmU>O(gRz;it_nH1Jg@R zvZk7>p3j=<7<>`A%-G%C(hWTkjyRbB`&ep-zNSk}CjWjn3+_D7)?lsji0u&P%QN3$ zZDxLl+AN_}eg?}_sT%i91!Lvleam}&)6w1c^5OJJl`gS zd})0Zr=W~rXY8yvP%ujwW>_}Uc3J7|vC4y@GENFy15HTXs~lx|2aVt3YHeK5YcS-_ z@qk=5)cwiO;Cv8hq_*KYxgSI7z+IR&PcEybJlro_L=Zn!no%XQ|C6`` z2AZJu1<_`bXh`Q^xy(emcwlJorzFAt{l|_2By5MQh-5Hes&u>Hp|5nM?ofj4d&IEfN}^5qjG6K$(3ZZ1hKzl( z{WDtB{S$KH#q(P{<+51Ad(fCm$?4C%^|KrN!^xI)zTd&#tsNN^J(Kh_WUxEYa`_C#2{ zj++u@NYdhHSB-lwCbc1xsg;c7^6#73bLS^tMr=u~Jfh`t@e3xGnO`uutR>#VY>_I^ z(pbdwf6eLU_7|)T%K}&$VT9~mgL1)#Q79c{1?6kKeR~w!(xK6oNaKF(7zkr5j8Kk{ zVzV!+a)5dZM}eF{Ad@g&-yhGj^hxkj+v@EZmGgS!q?RVRz@`+>RbT*ek^#47Y=h0V zIeN=WTCpzRDn4I;njA$C3dJnELKCHR=;c%JPpZ;4W4pZM&uy81gP;%PP{1U=juWjl zu`x=9GE7{SZ@X-kvd~aEDpt8$R3^Yt%3_X^@}BEJ|BSC4S*)t4s9d(gb)sQGCgO(3 zWsjiEKN(8ZXm*`wT#zvsy)lt4d-9p2Jt81EFdSh_o`d~VcHuhzfw*9ApA$tL0?osyLh4Q~D<7kzdx9jw|dmr>%vgCq;+A%Y_T6}?15 z9CZ|}3ERL9cm|$3K}lc(WCn(4H_MBr(5NZSC({;IO)_sxCH)^86B^Ho#i&f7&S0>X z$!r3V3na=l{X=Oz|OP82WS-wh2jDBDjw_>NTdMOqBm+0VHFlk zg@6%BNH8G*K=+0dJ)cwJ{rK?>H=qx;SCK(^A5I)~$p6CAXZ$G%r((1%>+abgm*T!j z*zp!zh=_uJMFaRAVg*~NAlvSSg3qJivKZe0Rur2kN>8#|^wIU$BMO3>ELHcSjz&^)@)UMXyx`Rxoe@WsC_t$)o!OXsK#- zw>8}&=v;&jjx&`qf*<5$kz6_F1`Z;2bG zV(GXTiouyEOh=X)9GAFGV65Us@2?d+ikXHq8x8;NKrnDGMGkI@97B<}AQCm{85Hpw zw<^qV=VPd_vGl^yn++(v@SehvdjtluVyIn1f@?(Drr;Y*BIYqHU|!tqEr#6-C$ocb|K?Exn<@NWd$ zKn58N?LY<)#XwH%3gm<^NHW!O83TD9f^8tzbp}}#2AR?o$bn&y9)d_p_@qqV6@B|WPtP$b@gK@e;O@vnH{BSoy%1A@_%vedQi->W{z!10sKkf4N zC7tM$mzpww`L6bPZ|XAd2Fkln&--bF@9t7Yg|Pz_WOf3-!4FXpmHV$<=Khd!w|36G zqs!bwi4tls3{*eCI6Kb&NuPwR39Ti7Kq|HgrIex+l zuvoJhfNh)f#a*(nR#;dYm`%%6R!wW5Ek!Iy%8D7=my5Bq|Jx;O;n@lYsNxdTd3F{; z+TCb022wTK7$TtgBV?GxmA7Rspv*UgGjoz!k@w+n-dQUK0O-H*|0(`!@ZTTE$#C3* zUfU8zaP8gayPUbSS$;&qHuik&m9~ zc>W6i!x8R-{4XKA8)16C2=5Jeo{F|xk#_*n_uxr~k#55O?Ff&=lj5ly?Qi=8&sPyY z7vbf4{9L?K`mgZ+5B!fu85iPS$A2;2sXlMv|5?1#ddVa;RoSMF6P07MQ~u=tQo~76 z`^orvN+L#$DHx%r)3_P~r(L9&Sj)$@{snW(g_YMW3LgoDI%9ESPv^sQ8Hd(VQorWn z^RZsazBr!ouF{O2US3W!^~vul8`ly*3_P3OORmGIs}ubV|L(mHx$RXsN}4Sgj~~oZ zN%)febAHTq|E9{i5wq@wcd!{*IaE@`uG2YLvg`SER-6oB*Xew~F9LcB2$UM%3WARd z3Y5>1H@QEc>GF}=;H5uT>D}S`JKIP08^0A_^7b3*(GA;= *ZhR^iHpve=pUq6WT zC!;NSeZSoXnp=I_+9^dGE}mj-auopUpLA* z(!1foe zhGrAaxxxf(9SBqC5T6;u5*DmlS@3Vt4i(X6d|Jfbavqi&U{1x1FO-x0wiNe8wHZsm zhKzYOv0qDZhIhx}>vRYN_F|l|Rs0}h7i-`SCwr?6@APg`>H~Mfroy5aK`F!yOV2t4 zFl_k(n%g&HiNGj0uLA1~^{Jm?zibcmXXRPg&c|;q*-X~KilW?X%s_&cicT;}5=mM& zZ`SwQ(EiFN7l!v&`Vi9hS8m=#J6|BK`u@t7X$1=VD?gm2!{%TjziVgyV%7YLJu6MU z`F;oNx75-jfYaIlFJypgg%rAKCQJM&Xswuuu;QQn8gOXtt`S7hyC1BW%PtT4H$pnS zi5=*jfm>mS-n6d4MebK^C^=jS64VDJWf%0pL#s;aEhcrCF?ENbKD((23&A-_Y-0~v zWd`J5P;)HGEqvEc0j1K7DwxD#c_2;2s^RX9X>6f5kCN$vp?ups7Li2}yeM60hz z&O*>B(uC{CAisqy(xE3)$6d%SZNUjs#9@-mG@fK|4>ZN@$UtgsA3IS~oe%NC65d^SunTXQ- zvMT~yqm?6?Z3Nqb0Eoj%zcqRCOL;F&xhOwN0~m1wKMv zs=#=H?YM>D1}CsgnDjI`=W4&xGt%NPWgNvaj%OM3+tm-}(KPXPjQ{k@uR0}uG6S<5 z2KNa70f*{?<2vP7j~uHFsg;fLslU4fXsopc+=*fBDmme2eG`$U4yP)`vVPpdXx)O zAQMTb-)#G>kclifuN`HA`vXaUpZWGx$cY_QDJ3WAOppB7ukg+y|4HZJX0i1WrLp{$ zzOQd@+OHg=bJRWOR8wBM6Qb!Oc9wLe{QAm1jum#qm7EMUe9=w$Kz@CB0>#Wy3Nyc+ zrQ~OZe2;#$=pXJAGm9_hdpg1gQD@@#_3NICD6_J2mSWEgxob~iNRZ_|k??3=S9OYS za>yrUmL_HfFUFe9iJ6bQ9c%zXR>Ftugd*gdeDW=-OY$zZBsYn=ugoXGfVb}?cPO28 z#kyXg;(Wg{+pWCiH_XwE+Q7GV$eZKpD&D+m=0`ko?IV&FsCZ&wa36m!FZdaF+z;5$ zIZN6->pK8gYo+vLr1Si!j8s8!bCb0hov>}*>^_{r_F7x!ArCA)jf&~n?rMvQVoJnU zPi|v*#EX#!){ZuI85>^CqK#f`TOZ!dDFOCQBZ0`>7TNRsnU^437F5LQP92H2ny43_Tx+SUH)fgZ1}WREIRGi`IHa z7&kS+H^o1n-?k>6JN}2-;iqf1BsE72UC%cz=I9$2)$7@&MU!>{TLYN&Hr*X7Osm#{ zc-L+5Nd%`w$qLm6+cR;;QD=Y`s5dcyN!p)Ligg!nBj8?a7973R2Ta=2cw=~8A*j=< zwa4((_f0*c=XCB0end#3{K(u9Z1d(3nGu1br@Ui;laeRY2;H$|p z38$>ArwbZxZb!qJ@Nb?S#$SgJ>N}9|!~IE*;<-{_id1`L7btgcid6ed_@+kiP2u>? zwS8ai0{`T*$N&Ca;riAi^bO?ewJz}Q-gx%)kKmue@uv{K=_=Z2hR=%T__{7I-WkSt zCVn5D6|S#_5bAqoeE;eK-xnM78lDMXaRgrx$9E=q`mhUZOT*a0`zcSYuf_;I>Fn@* z-UYtCUE@PH0i%+JIfr!hCfqKdV5=9|sORns^K>Oby3V9PXVP${Zi=YnNlJlHncb!{ zBKp0KHtD50#?dqJa{%G8kUdJ`xUOS*386`c6Q0SC0$-6)nPO53%n>y;cY!j6ql~h~ zXXfv#GsE~_K?rp{OZ>Jj@UNORB5a%V* zRVTh2Xi`U**>M0XWY;E_9)wThxLEtw&-LzmI|7&sApc9$J{V7aI9no9A7R_|*#SUW z2xHC~$_mh8B+}P@TZKELQb5w&SbMKMre(M2BLujX^csYM;5dCsE8Lj zu0o{HovLO$2jFSKGf5i;O6De#s1IQ@IdTCbQ6Wec>i!|-^GVEcl`E408kA?56$4!p zJWQO)`4S%U@G0Ya=acWosy1jn*SBc?jIgLqs-=;pq5(7N+zeoYCj4ST8ox-_?&tM3 zGh0Aj6Q~v$^*9mhxjjt03n9o&I#?ez2kK}uJQroYPP%A29p#|MqIuWp5;S=dZYNrd z5ur)FN$U^L%oR&RKwWIqdW9n{M?m+@7MrvtYzSrfjFc}Ykp}P>za?tZenQhQNudX9 zy7!pG29bT$2W-sS>#e_7wgma|x}J5S9q&h{W`+@#P05)L?E&e4qFZeBOp>rWsmMPx2TadPtY zwn39nGYR<5Lmb)$(?5umw0B2ACgYan8C6QmvXtiA;#m?Jk2UM5i*B5bma~%B)gYu) z)5OXoP=JCYsl~Qp0Lmu3414cv;6#vU;`m1qDY0stI$y$MZs`?7eUa$stIY>I#>;yU zfR1$!yf5jSkI~2yQ!U!yMDv!|1_{-=_hzPACa4uO#)P}#rAasz_0hd(#);q%X_k&2 z!dIZiusULbMvxyb2W*vJwFS~VjCZ(0rV?=BKN2_iZKI6(JY1{$AyS}Q1-Pwn9fB-F z9RessTm5j2$iFDZaN5>X#0d7->M4ddEm}FxU1dbJ_j#m;7iz!*ld*XP+6pUXD%P=0 zZkT_?HO^kzQLqeEz!{e!ZQL|4KA9Ll8X-2*6_29e3>$xU6sk-j1R7W10mA9g#vQPbGf-Q98)z{SEq;WQ8rnNUA1(lx z0wssq8Z|=RIPLjJ&Rb{rCQIp~X6E(aGPRFi8m1bS1{qv?X|F+d`4ouzv}a(AZ3H`d0DDHwjvL}@V^ zwi@Ins*9|(xqOx<*NQf!tc@dHVAg{O2)jO~Y$Q8OYF419h5xSB%<(3U3FsNhGI?A;8E+WX_UJYNW`Y&!i8-5j(R-n`JIOt@w(1bpxg*E^(T4)y=lg_{ztWdNUOGwzSM@Ht!$B?_5 z#plU$&?ScF$+NU6S2CHGQui|6e1Xj&Y%M^w(f01D{1?$U}&=#JcipjkW}yx@B^!z&Cjm@4v3RoTZ7!XW%JX{tH+SQsKg?Q z?7as%87V`TBC|4&q6`r_iU@rgrKt1Pewjmq2s9wNOp0JqEonP&-4gS~^Rz#fQ;@sp zo7mJY4vLYRE@>~IX1Fn7L;*cm%tI`5c)6g~sI+K{4zco$w1kv~2AXZ7<$~S^_2q)7 zb%ZoZXg<(6p`I3<_JtGLT-vZdi}lSchz0JcfZO~F)JVH*ESKCbvBXU4FWuqfDSo$K z44T`C1$9Ot7{v^4$Tul*S&mhHrW)PWcx9J1ePY-P_!&anch~}O$_;OMrenY8bX3V$|OHiiH#lJzk+?fQD*XB zaZ237dLq}uS#Th!~8m*6iCx%W{pdkQcX0*RH{!1eVCUEDMQ_MhX(e)F)cCBQ^{V0O8}|p#6TG zf)P3eW;NVIm$aQ%YDbA1s@t)#Jhx(ViM!e;mu*w_XkVin!S)W$t!3PY0Mq&r31$pB zO*(6|nN~LJGNHM#u54tj>-jTS1MOTHcC`6u7|?V#n~zT*^+wX#mEq6IguQRLFi!AG!-t!`neG ztKSom`q8pKtDk}ZD+7>L*?T3Go2Zvd4ws9Klp~jlmHQgF+VO=X>(yZpKUkd9F9X%F z$Y{68AT1O8UIkD-yeiq5FlDR`m~=9Rbw}asqbd8CuCiw!J32Zm zHwPvy84`a=3qZ3_)J`AXgj(O1%WIw8jn%r{=8$YYmK;F5%@R@dPMbq02L>+4z{ipn zFjR&NPJw`^3kRqVr-VkO(L})sfcNDZQg<|cnQ>B?kRmVn0x@bf?VPg`6GxX|n(mX<>L55^d^%3kh{v86FyN6C`_| z0Y>cOsr-m(StF1_L#h1R_(#g(8YFo10f|2Ti;OSWU>B(xvNGL;LgQ5*l3+UnR5Fhx zq$2@KRruwLBZ!4r$YK=L@zPP&iono@sWVzDaMmI?uMZ}ql9P_$HQJgHyzQ1k%OJ5% z-hZ4&k{ayUuEnUi&qs6PYz+A~T%eqB=sJ1@FX6)-Y)aX{T8|n#3ZdRUQw=C&6Dum5w(a8Sg|tDNAG-OL1Ga&AbZAxD$2=Teufv4V|e1E zXeRCTn_-05l;|3S$iDs!g{gW!3uI%E$~bt6xy2Wpm=C(K(+eD(T47%TDz3E zV8MM0@U+ai*Lo+O<^|Td_u*-}Z^7O4ZoGY_brGJDWA*}i7w6o2m$g=u^6$IrE%xI9}Tk$+?Ac zvU%T2i35Xcv-w0`Hk-)1tTdZVDqOs9Q7v@zQJ)=W6Mwee^oTngzNt`!YOpwdx5YI8XmdCKUx8br;j$+8;M z1nuJ+ks}1F@fiftO3CdtDnVPP=U9jw;fV$9Zvf0jWmfHT5R4&Q!AuOnrV-t1o}r}{ zeH>@i*8PPK@h~&1X_F{PQ}eJDkk2jpxC05{vA*^&+n58#jmdbsZ&cRs=BD}E*Qm-X zncE4sneL{tR=i0?xo^(Cn~1eqf}%Z#%sQDp(;1o1WA{x347o7-WrVa({uLe&R#L*% zlyI05wnP%zwxT6rQ=0aVa6)(-T5W_kcyuqTWN_XJ`849D((9l% zrqoLMLMrUCeL|ZGr85<}Ov}#E_oz-m0COh}TQGUVDnp|ImDuat7&K{@A|bSp?J7;< zd7SaMwQ-plMv-p&!hUs-X4XdjiCRS;(zE@~CSbQh<81Ds=)d1Wovy}45-x4RnhjP zAUZBm^AhJ8W$r zcs*J++VP>tEr`@MpiqQ=;rS4(C!4S&jP*VBHnXyyuFi8>a8ZsabOY|+LmkboOj|eS zd7(wd&?0HVBy|MXng^f0Oo?url!(+TY|pY)1Qk zMt)1@_D?$l-mnCmEC1A7!tZ+2BsltxD+udp@cf99275-L^P#>Sb@m+bK_18+gcg}0 z6*{)`?@%5(wHLk%eHv?U&h6EOy}@0hr@?TJ{OJOI;&%zZ6Mx83pU$qFBmJG=o4#B4 zUCB@8>Es99pNKO7dHSWnp>bem^p(L;^`njCCS})eg+@C%NoV(R3TT*y#f0_wH*sIv zajQFoxr_iD0(Y(G9%{fK5!c>iz}JSGFu;WpzxCk9-HaPe79rPfDN3a)^R(LsqBA{= z9+d`AFA@aw!gEz@5Tx@dL5Ef_Bs^BhM~J)jOOUTNo+zQ^P5fcPmL46bd>03Clol*L zOjfoQX!oFam^SZBtj+|UBNs8ccXwlIb1%-kT&S9D%Z6j+2@_!ejG1suPg>NQ&E5@; z>B^Qd$^x@G+^FW4e&txGT9l3MlLidsM8!lWSe#Cp9)(LMX6#b>$xB`VVXAS37x#wz z6+z|1tQEer6*q4`q-L(jXn8>L?oe)Weu`s(`vOl;*5MNMac<2ZKeisjdS$r8M*En{ zLu#Oyvd~g8{7XHa20FpJ;Deb{H?WC}6~4)ajN=P?sEKO_PhBf6icxket-z*amimhO z7?kZ9O$*+qF`Cb~B0}fVDPT#taJwBt7t{of?mi1z=1k@i{tgr7~GW9oWqgjy`Zn6SY6c zfH)L`@G5}DJ~;LI)D72+k<<&Y%?T2fG^eTj!5jVu^%Qp=!IXMpmF%fO)qP;tKHS-f zF`iEL@X&u6b{#$g-}@`1lNZ{-NcW(gVFWY66QyQ`!z&f`Ie(r7+H zz0r5Ggv*UY$K9!4dht~w=X#*0&tQ^fCuy%ynROzX%Nqn(x*9q~?WKK+v7A;kh_~Ya z%7b!BrjdGg(q#HNc=|*l-uhU z5;NX$^ihHUiN#>bml*gRkfR2o3KVGBV-(HTCRQk|sUhzU5>w2$k@(-*9-c41u~~Vq zOcW#lkpCIRH)Lg4}pyFW>S(0{Vgaz{bfR;>#{RGabk zN@MqgNp!GKy$UUTK?;{++Nwr!9KA_PKXusxY3-y$(Wfr!k-@uRS)naoeg-4q9HVE4 zL(EcgjJW(72M*N<*jzl`ABf4Qlb5Ul;l9j1w8fDYoJHKHykA)_yZ%TpK9x&pSJ7Kk zP4B0U9Ig4fSb=>*;tK>w-CjYmvL39aZR4VUzv%Wik0XXG8Ns#;Do1MVUpJ#TI`yx= zqG!;wmcad!!3;U;uvl@or2Pi)_+-rUI^=9Xre+wSq|g@S+1QCrUkx;1sS#J54W0u7 z%Pc!+zGjr<6L&+DEjy3+#**Y#K})&34vVDWihLQT+u2N@BtA*UFw$0E0O+ z>i9ESsK1zMv&eQ$wr`W|&8*MR2$W+`>X(DjfwS!1@g&{%a(I;A^9cw**9+$X(7#5v zOxWK+W(j(dr^KocV|xQ6SO)Ey4I7-*c$$rm$A*pvAV=y#QM)Nk-!VG@0bEf?S9xMy zft1bUOvS{fpY#MxHn33=8*|~wlZu&mxG!Phg(Oo zlLzIiFkQpHpi$~#hVw&2Xq#~z60^05+LOXhMeZ`PHUR1=~ffht;1O0t7*5jhe+Qq zknrJ-9246ALO3ODyUd^bslLnn4+yA>6Mws$Il>0VXe>cG1}gh2taswvXkTp#X2j9K zsJOjrLj@Sl)-YE3lQ&{5W9j)+3X@?&Asgn&+ADyi-4KSH&mn79h9d^E2%C0(IO1vq z8bf15XD`iwAlq(z0Rk{{?EZh8Z%oDJ83E^>a*U`#vN{IyN4<%h921k2zSv05Hosq? zy`8Gp=wArvQ2&A;gIb9IZHWIBp87e*zv|f>dm`r?fp3@yeidPg)HgQ1>Ag!g8jg== zyX_gkYuzD{nHD*>R;j`T%q7(6xV+n)$?j%pQEzQ<7+-;o?`p!w57Q6fQRO1eFlkQ> zCCQ=l0XUG53m-&s-~*72p*+!X9_WOL(T37u1B-HgsvSttE7ybo;|<9bx9{o7R>+;G z-T=>rI#URs(Ts1?!8(26CMhzMz)>w(4CW=BJ zKzLb#NFclf&`U(Cq!Hi4EwVzsxn*S1t`c#+lwC<%xVgbE5u z#8l6Au?DaR0m=9C%sHC`g!cCS@%y3KGiT1cJoC&m&ph+YGtUgS$gv-|GGDpb#@rtW z$gztb#v@)OP%}OaI|Z@j^G3#}%gE%YMY?&v;C}odLDaj#81Kn=$Q&HnoUYh;=lma9 z((KT}&q|6VEn@w(M8?Mw(}CNDtavp(sdq`M**_jJm_TUBNjZwUUc3P5MY!?7&{YWL_Ws58arXhYae7cA7nQHKF7Quigmh% zjlvA?jJvI!31$LWTBq9Qx0PWCB$*B&O1eSKFXf2{AUiIcYeg%7EB(nSf$p|%2Af19?glCqf(%@@ehoWX=Iw06h?v{4JG6z0%rzTq zE)P83*7juE4Z@QcKCTavU;_qNj?y)39f{`2k+ zeAvp9E@`Fy^Y0JLvc9`>q)`{UKkz9lQR<2>RK?40=8%x^R#_XdMfK zLxGs?Ss?;aV6gcJgaKJC6zKY?=`LM1fMQp$foCVuV(*^=AgkyG8i(%J+EN1(j5Re@ z!LQn-=(@5z{ddJqqle*l22(^&;X30}q9b7u=F?Pf4MqK^EFXWuN5++?V)VA@X8YB) zGNzLVnLkB@91=-Fc#(Ix=jK49NDg ziR_r>Ix1N2U^(2y{{=ptm<&2)9+7v%Gfx^y#Gy7@fGbymcXM?n!%`jMSw%?pV*QJ3 z+xrIDTo!}YBz6!Jw6!3uL`Mhsh-6X6cON7~PfXLZw&uCyL{>uegznl}PX^u#x?!gQ zx-c(SzLFa_^3T79Ja#teZcTTp&e*&@OP2CK8Y1I`E^(Q2m)jDf%bcNtJ9cQb!dLlN zIMvJ&E`5&nbH@&v=He)FM}zJCQ7q$Xl3ZtV6U!1W2^e-=U*+uT?U+Hi0^uqml|M43csa=)fj0)BN z1LVHgn%k>e;}k&8hd%~6TsB>G1I)78pOI+3`0e$^@-u9|^-g z(IGKpUf^sJIFe&BE@P^fiQChF)sJlzvmvp4mY@p?2n4StRSEms3+~OnU>gov?FR`SA%Or2@ zo)`%bbh}|zPDX#f7f^mZ5beD5sF)m#ste|oF`ZV zSTcvTAH>aY?BMv_LL1`OH8P@_$zQ~Av6s$1&?&FCm%Gf9)S$S3-}yl1GXEwuDvOra zosnm74;gs>#AbGlz7Xtnl=Lxg*#{*3y7Th?<|6rjdrtlrJMu3&FaM(#%+LOfUAO;1 z?&h)e?^6HJ^YY(x;rzG8^9Pb+*Q<8<(~Q+d-14(dMAo8GTSJM^L>M!}8^PpPb}t@m(? zwy#<8m}&jGO5Yv(<43Y0oL@p;dY3Emgxe_ClKt+?S>{hmW#)E=Dz-q~V%lv`NyS0E zxLFUhnE$~!3v{3Rz;ROc3Av+S{R-*JyZSH;E`6S0q}M8b^`>hYmC@?&8C!ajUa(g$ z+P}5iNlHin;wH33{=u@Ge~@b9tNAmcfo3)DJ9x3hd|=p% zbreSj4v>6Vpa`AR7As$<;-GU~-G7dD1QH{@X1#t{FG*V}aJM&cRnS!u!v5@D^QHdK zo|5E#O332Obu@r^$#;ZlM!5y>9pts3g;&cdz;yE?5{nzX->H)H2LEOFN+r&m&X2nJ ztyGFTJ>A?Ou_O4gM9dtCRz|6JQ;V&{Z;;io!@OKlsa>W^B$YaYE~bw!y1xtFx|?5J z&G#&s(2f(5nOaN+BLzDmMf*FB4iV!>KB^bGBSm|A2AafW&Ew)lr6Etq$Dz;0CNy1z z7P0Ngnq3f`rPc&?XLTr9hRT_PuqdFr^vrjlkAKoL4_v5cMBX6ZKkS+43)B_yHLhP# zf;2DN8oKYG;e!~VL{l$rDKy8jS3ohW`fpQxcp^|@9=a;thX)7=3lH=FV)J?^RGnB< zJ*j+(cJ`#YnK)^tnF1%6l3cAs0ryOQs~*4W-HJ2bpqKCAS*pd$n+x? zDR4SgB31x?^Dm6=rznc?t;DU1k8khX&hedl>4nF)Y-XW0?9l2yqx`zf^_p*{*>u@N zATqa8t2JdyVF$@Qh41MFO-8p-a5+LW*A&my zwtpO6*?9D|=*4E7^{?URP{em6Qqf{~Qk^IDf+N#s;FX69k%FeGx(y^|5v)8#vH=X-eYSQN zZDE2Wlreuf0Y;A~=K}l9*cCQ)IwX3_AcZ{8V@`vYfQ#r!meSTy+`LSom56W0`aH0< zVW8l`*J9Ad3czaBi;onVM*yuW9mnyXuB{#8j@%Mi>?&cl^Gb5x5xrnP=cJNBy4)}( zTedY<8#A3;snkQOJ)pm*E`rhbXY|i$^WUJ=&UA*hCUCa{vz2~KZc*gkq;Kc6(S7z6 zeMPOIPq~9jf6vA^XH-?H1s_C;kH{@kn_~}AbM^@~pL{B!RW3>LQv8+bjz6n_K9M5& zqLs_2lAH9++{AQ(2z@hGjM!K79ph{A9{h`QbwHqBgLqYN;9`hh9mc8Mm74`u@sK+Cgr;*`xAp$3cgqmt#Me{D`@+_y{6HL!y3Kuh>ho z1{Sw+wVv_Rl?jNN)fmt_%-nuo#*X`^W0Xwb}*F(B=fv&?naQlx4#y zlCL@3JvUZ9G>?*-6SvB3dAANPHvMC@+Dp_2?#as`0Ufp3%DUiB+;b7@qi@cxi)UHz z4!7t5Me!N0}9L6#2% z2OE5pLRbB+dt6BC!qem9!3%$VTJ3ilX|jqEjqlh~6 z-8qhu^O1i}r2AG^mScR*aSj-l6;o&r>bn-&Z-@=fKA}jM2_aM8Y)+4tQ%WFqx!z!o zCNNWRum~X~-H+2x>c`?uXP@|woJX*l5&Qo7CYY4DTq$wa7s_nQEY5iuI4def)n$*V zkI2A$aKKm_e67+Dqrf!3q$I(h^@(xmYnA8^RrI<2iHlpzi}Zq%M!`wF=nS&AC4%o& zY{9qR62TA3o072g0+XU(QA+YIXf_I(=qdS3B?#$j&g41FmwO4Ao$@x@wVp@?o?X-C zyG#F@mUW&>2$)8|td^{5g~6!b>O1N%o^dh5=|@Y~2pax$m(r=>5rE03sHL<{BG*`v zk%A*NzEMub^FUX zN;SCL{%Xd)tv-&^-{WGTRfK!4$i&phw6w@jyk!}_aDy-W>d!=`sg{mu@Ga+;$4Ye$ z#rM3t6`JM@)i|hWnx!OsTsRhmCA{Ja+{tZJp;Py3&+a4b266n1Yv;qZYvns z)T-@o3IUerzQcy^Fm?g4%P;i7C%4=Yrk+!YxkO4V2B+4eHg7?TeXh%M6h6bc^DmI^P?8xpwR%#wjhUNcLpl=N)ir_jRd0&TI;TU7 zg2ND@^cU(AOW3QoCJoCq_{&ID3afODfbVApiw!%c2)naYW;(XBPfN*5pOW3mJCwZH z+fF37);hJ7b+~UI<8IXVZ4ejae-!q>9kEAI&Z8-3vetaZaM>5%2cSzY6%D$x^jFf^ z@#yM?YE&bScNNsnlh-?TLlBGDMh=0&$Hg8oJ_|g^E>l@H^T`EA zlq9#mxTTAd#5Uadsg+MH#hbe-NhIw|6eN#EMxyPUZ9dyOzOY_ONKM^K;);=cuac?a zijgTIT6Ldg{)vQYIXzO}?7wW5`CH!2k^CqLV7e4@XqLH_XAmzq0gr53#tj#d1X5Nw z9P95zmt)=E5+r1zlDF0-vZj}N+Q1e4EBeJ$eJ2GtIy4qaj|7UE=v0C}!L@KS zn$E!hg4z;+i@roE*vl`EgO+g6EN|wkY`lu*lx+`{$RWQn6S0h6^Wy3bn%=P?ozmu~ zm~VffIyzLb!?`Z#u@rwz(qWRe^ksh9n@qXb5$tp~|3E z8&ugofb9Mrm7_`m4?p}`Vj$tQ1b9_Sby15M?O{{QSpqdhEx|UIR=Y{zNb@x=>m|Uj zzSN7KuP!=A z>b@q!_q^`gYxrK(eftgHD@tuhqnlrJg9RB7>m^_Y*uE?@H4r8`SpThDaH56(hV_De zNX`K*aj`MFjA}wl+z!@|&>PE($O2DfiPsqGQ6~t@Cz2U#%C-L^gruCnHO#~2dNop% zF_LiyhwxDva964My|0DT8WN>`TivT4QeaVICu9duK}|0-7gMAHBm5+jg6$nfbe`a2 ztmp@M&;}rsV<%5q00NpQ<{KoQ?<#fnHlyfEy<(jnc%#O597%QDZZr!;8}SwvIHJVu z@T255iZ(*grFlZ61IP$H1S?F37DkkEMCbAoiFZU)WDyeUfks^1R&1GNe$`!NP>rF~ z&c^hnG3d73Hk$h>G%o``9ccC!M&a}hGlMi1GSltUIHjPTe~PdF>7np7kz9hWfKR$C zFciZ$V~GbGfIZ03|77IOxLxR2%P#c07%DGvv+iptzr*}_cQzpdEwPE_oyzyzKSnqn z$2!W6^|wsQK2eHTa}EVX3R>EqQ0LemmN#Exq+kmx=qavvmmCn(2G}y{jV)n8otaOa z5#JktIRsPYTUnaeCak`7%BJUwD9l#t?+``li}d;}{N2u9e8REk zThEJWR)sy*OTZMT$av@lD8?}Rd6QASPd2CUZf)V;DPLqi&)3jhGMsz(jcq-NjBo3y z68Aua=taxOc;RimY253s^;GlK|9bzdsZ8nDl`YxD_3O%t%-%mcs77tP^=du8eueOK zkw8n|pgi+Q{F5r4E~(=4aUS#MXpxNi@OKAGVbl*T8&2XsSgBlhZ1tImGO@Cu)TdxC zKSetV%|kx55N42u<;)gT!l^?!Y!VBuhV@S<^2t_ z(iQK`3PRGGTA0-%1isPoyyAOHf3mU!Q;{Sy-k0aV!0g8z=kLMH|Yj()PW%l&v85l zl{&~jpCgf#eFZ?zA0222D8ns^0-kF2;Au@Jt_)%&T1;#lu^w@I0_Ta!v!Wj_`?h`z zD+~9)lnnC~mJM=*N9VdsKUU=&2$Un7F%7;!2`;I~05C56{4hauei$gFoBIi>Nm4WK zBba>vDz1uB85+bM=47HmCl~ww9o6DT3nFq1ilc%{BSPhvw}>^N^KR8-+Lw-HP6o$6 z({RM;l6z%c;K9R&i20$DUh>N&m4)UPgyn3Zzc7-Uq5MHtw!ck%fw3nxCk969`?C*V z2etGUM7<~~()Qcrt0FG-u2}Elh>BGtc8~cqMb3=fLwQsVo-=22=?Y?bg^z-x+n6*|rrE8R5vYdV@CUNh>7 z#>kBUa=+IAF)=4@ki_wxM|hl6K>Va>GYe_QjP~77zTzzv966Yj;9nTYPpN^!xU{P6 zB+cH23mR=rFE7)Nu-#lCU8`94466+uNKo2fjS~Q~edweS?I@f{>Y;`0Tu&LVs3#R= z!Ml#inDl21j{bsxew<+8H~GxKNN**CKrQ7x&Hn8PLcOk-$4nt8G-L}B*YavQ_)#q9 zQUdx%9W4pp4)v^GC-d+-tbVjwv4_gij}^8D+~xteKxm75YqyPj?_3}cQ(O8vO&~2d zz@bmZYT`M|VJ^hwzUVS}c6^yUQ027kEoN9bp=r0hP?i%Ip7=_+RG@2b!kRNnaFUy- zEfcX%EKs-cjE4A$+$M<_K=+%MolUTfG5Qj+rjTEfgb9fbV3tvP_&`YnltV;(7k@J8 ztzCR6%-Y2tOq{tH1+YTiegd+Ke*>{y;CWU~bAGdfIwyjqF4$=kV>YV^ z;~%Jdw5sdL67Q(4b}_G7c`sspArQ4UMRy44&UKjsX_3ftO!V&%#X@O>x#SF8qs%hP z3F-AL)YRpidO!UMm%V%XVm0O1_cM-mV;s{?mI29CHv6_We(iL`39&`zN(MM8flHn@XJ7+-BGI zcLGvdKC$eo+$iR7){$V*ob`j^(4F2ZOX-_vT|}MC@DE_!EGGP0saBcr4~yh`Sj^lSnG#=f;SFaIw*A*c=2~a*+~%z$p3ZO@ z$kX=vHIkrtB|nz_i$I6b|DRYh$}D(4k>_Zgm`h z+|Us#vkOzfU>;Ipmfl!`o`s3V8|!J&dx@U=_;?uiVBBY$Y+r;3BK?Se?!$0*kE+~33U&o24g}ZXQV@QiR)lbqqH%Na8+-fwzkQ+ z-B_+5HT&UsJz_x}3j)={+3zYvR0-pCO#LTbTsrJYZXn;oR(1aGN1+RQd`hA_v$t8v z-VW_@+8~9+BYboZ>1a%rah1T6^S*zIR@=vTQfvtPTI~l&eOcPtJqT)5D`;!>yRjAL zq{imMO088lNz>yw-ln8TRD_G{1KD*^ao?fP^1B2uZO^nIm22}9dcq&02#DsBy!t); z{otqla}ME@l>((Qt@bWws6K(@S)orx>ASSrox!$dZRr=%MdI9TgaTa-o$#lHhe_wc zo!JJ;7x)Q_Pf>U1fsB+h-Zo#&` zKlrhN=yidJF4JmfJ41B|LLUNA1NXfvh(ypNQf%cPHhQUocWL1diH*Y&`dA=Hep}W5 z9v?dEXBn#Mm%6_q%*km1KHl6=A8?3?Me^HLe}o?gWtC{2MAc%Ot9)Ubt5oh%1`;3W zr=uS+a_y4hV219JlEl`=q8R#03m+g|bT!q|J1IOI7FN5UE3}&mG3e+3;0wvJn6mU; zLSA;OLN^ctx;=JMReA+UV?N99;}gs9qobHtq!`(|qxZ71-&I*ZNs_jUnaIa|lXpu} zRm|-qwVV8b-Q>T@s4wRf<543Z}vqY9FHp2K8{-gPJ2ClM3G=!h^$NbJxgzs@?WsZw~LEcLgK+4umxmgHCS3V%e-ARJF-%7Qhkg|zalQ+ znAgast!BDBp!Cum4A1$(e}(Jm4YSN1EdJrOv&=-25MND;OGT|A`21Wgnmxd=QdrFL zjOXRCGUH_)@Y-sU$!-t9FxliE>^#VWnB_d+m*OsTjTQ3-5BbMO*@jmi!x^isn3s9T zKR&+7Lq5)TG9i35vwaV{X@NP$s*DuojO-I~-fn)!e}McYAQbWxJB307^GUNxClQ6T zKSy$A0Dh29fWMsR@e}m1C-t#s^q!&3p3vC`%3hBpKmv3GRO=0$orj}+VUx@-E9F6> zd1#?$u4kI4@FY-?`iw7T40=I?;rczLJ2w2!uYPqy_5s6_r#BkQJu<(2^;f-VcU!&L z-?_;kd8o}rp+VAWOP!QS;*Dw^q)3^}jFsvmi}k^&k(l1HgF#I+q=l9pd2=^sfNhvlf`d5>}@UL^5PNeuG5q+2f-$UON~ zw6oP#!$NI|SQ0K9XfYM9EGLBkn_YoQSiE17_@;v>Ss2bI6`?F-?+ ze*=}~FaiQQ_2c?inTPN?)!$m92nwx;-m!qxXT2?W5Z*A)E*?q~tgn{!qcv`Mlb{R@ z`A4vopjt>;R3@=>R*=V32raFU?X~tooZWdC6cQV3OZ0b-ex5<+w%fgGSM$ohT8%Z3 zgr3u;UZ5H_KBy)0ECj2CJ|QS;6P>4^a=9Wa*iIHO0dX9&53iF&c!~CC-MTHnL!fb; ztlSAStt*7{lxW{+Bw;eDAy)g86A-8VEq(d zz4KE_*HE%~!0NF$>#`XtSQ7pywrUP-+}6Mq47tHbfkVlf3+_1Ra~0zL8`r{vWP4-2 zV;1+de3x}JC2hZYukG(;w+l~8L-!4JyLirKE%ZZP1saBUB28qVigX5L<0<}WC-6O0qP>SBWFi9((kux$wD3kL zMJ}JRsA2#)sKOJht3P+S&6oxl0<(7PsQi@m?PLOz|ox-NE*i))#k~RwU zpf3@&$g{B7dY>Vc*gSC1dgb?dg2N!GImvugT%v+ks+|EzEF zA?tHxo7g66;dH@+mGoL1C564bQkJ<;9qi$(&v{!5%|JMsX+FxrUN(-z@qGVl z0KnoHD3r`!=cyeE+$CAJ2|}+yN=60UPvokNia?{i2ydlF6Mg2ehFXA8h(0=2gqjcRMwO4zs)UrHl8s6- zB5(+%*C4MrCA7u~eZ5KgdTF}!_2u;SB0_cv3;!5=Cb90RDV6OH0|e&dYrBt_i-I}e z&aMkSlQ7xeO-3n8!@wZQ&ZrsJy*>A>r_+roiD2+?Fo@1oYp*=@5V>W;x7|NG*XN%> z);eu@J)@_x{V^%Hw-kK$WO}XYe~9fYOMC9eyc<(w<#K*`ps(HU&h_DPk~E1_hDi1} z2}=!6Paa+@8gWHG98nZEE#Lv;^qKnUY_$S7C98+f27s?`_9WLEPd0_xdn}k1JxmPL zc{Dvr)2kQIIbc-y@6=uOyhH5?nG?Rz2eg<74KuRltI`WQ}6CP78_hPQfoYFsgsrsIroyHwd{wpMwY6G8G$Cd>4HvhF+?R3@T!=rMW%S0BTMgGgRTGia# z*0StaU+IqA<^`X`u9MCq?kczd?MvP#V8g`3CER6pmRKJFT-6y^0i$WhnIS5F=}!9c zqO98eKU(Dw|-(~4h|=8FK@ae^n>hc}?Nn0Gi;YT>^SU6Vlj z?q*9=q;$tjfqa+ z@G>@Q%bcN232;+T^zX4A((3FJghK+1pJNI=#y~RCv|Lu?^Q94eRibV2xS7OpT0oF? zRApje-xqR0^nMrAD6E`M?NxHpK&E4E5``it@bUOua}pf!b`zSscgKYXyNZb*xVZ9&v-n$ z{T1hW!C~NL443`%un?=hxr4Uh@v`$5r)~Xxkw*U5m+oqmtxmjtl*7B>zez@6J2vp* zDMe=2+LVznM~3xwV|0^|GE(7LP#l$wJG}`nfjGy24YC&Dj&A@r{5c6)?W7!MCo>$# zP)`$5%{l8Ipw*5X--RKTU56)EkMzl9Le{rZoEO#?>!+XXkX!B?;gj(EI4BFU zV)^lLV0}J+EQDt>D|e(X>t`|bvdKuteb7MZ$D~j;-$!7&LxYu61w9TBQWxpUe+ef{ z!rN1!*{4Q2nPcA~n13hDE!C<%620A5L{4GC%}#N7hyJ zik>C8NPr(mks}A{t@^3JCCW*2qg9aCn9`2?BPe@oAsy*F3S92Y251iqf+k~e6RLq% zWRSEcYs(%Y8?G2jDG9MFa`tG?zHzx4 zvl0<}>hdO#^D|%s5dW()8^Jfeti}cgw z0?N3d&dKl$cdVD_z`u_LiPCqoTPdLJmp&f{@%0EUmMk9vU1i%M5o>zXB;?)%`xMYg zVJuddh*tyOBi|(chWe9(qsaQp%M{Da2;U~9zn7#B4h4>DfI|RQxU4&? z4q#Vlu$k!d>>lX5W7okxJWjux7T4*!pSrBF?Md3Jg_lx%Zic>F3ojxhMX(M}OQ7eO z#hk_yA`&p=@8^Wh{_EP?`(w;-6IZbUQ|M%dkJkSTJ4ui zdlO+bix_Yj40*4Ax>nnJJWPUSWavjNU26tH!Zh{uyIO71c>O4BI(82pYRSMtf~=~f z1+{X@?sykassc1JRxIg276gKLsFdB5xZpRmXOVCY&h~TwUnLTEY#{D}0E)DsPdS#? zH+gIFaqHlu|AwxKFC(#ipz;clqB8gC+nu{uQ&fEj6Og{rcg4hCt)f#LKEKUTgv`@6 z`J)R91CflZdbwp$x+jn#RINSxISS`s?l3y<6GF45bzLy%?}@9&IMWvD=-JEa9X8>) zTGX%fvI9DZvA+~71mir*H@A=v?5nCb^F;KA9&*~BVN$KyvtM2!H4EANl@JGhh3f1q z2ax%r4@j0dG;KFq0LI|d?7GnD1pT{eIZ zIu_Z7plGf#;OaePNXzEKD3VB0ae9jgF7og12?}v4r@y#8qOi)g#fmr+Aj!&M8Pf}) zv=hSjB$%gi{Gy71Q>3srRYG z|Dh6pMFMGY<$~X`65IbYOWGv#nqlxEdlntHA zwii{#g{W%cHA-7bc)w`IT9xsaWb}Jz{4_FD{fs!I)-^;%*_d?5@}p6DUk%%Zc+uvo zaJsJ4c0R5Bl=*}_vY{g)wVD&z&Vx)Q#MzI{{(i;L#XCfv*WXqoX5l1VXzzR2Tt=^y zlHe(!likY3DLfhJ44dF$mZ*=*hxji@Py8 z$_bs@M&haXN0chamDc*lLpFgS^OSC2v8xNNZj}4BanYzc&o1V5r!C-Aw*5h&iqnmb zsF-Vls*S|_Ba)f~I0{vem4zb4l7%9BLIXvoXu)h|!Qdi+bh6BcT`(J}>t>YpU2fISCp8NxASIv6F_lU)gUAa>_+Yl4!hE`+al05))M^cNruI@-Zo z^cJXt@beNrVvm71(^g`^6wq31vGN?y-UoII zv|WTQ1lqBlanPhp|BQG?54i{i)!?wV)-KxFf1xPrL~~S}M}WN+0dX`S5`KknR~|-{ z-xw%iz!f^{%1GcEqI?zAz0FH(CbHa~M{On&-Dh)!b5OC9$}LoEA#@>Bd`2-=FA4me zy)@+i+Do5P480^;6PkTQP%!dB1SF2KEzmMA0@|bw(4@>x&~Cj*FUfHHhXnL@3$#}( z(7qJVgqY}xb2)|Vp;@4bbax@F{f^1m!kU!nzbj5aw_F6Yp~78-4M;*^Z0Bvp}NzY`Cox$ z{Wnlj1uTM+r=GbGI(|ke*$2*Pga1awId8e(SO)_gBCb>w$fTVPHaxqIkn=fvnyjoI zC_HB=LuN)1<0XqCx$~}bQ4<)(W{W5#obT#84cGTbgB~jNs{@&vv0p9E-0j@sJe7Gm zv^fjq1Pf9WFUi>KMIVq;Mb?a`Z$d$;y}I39A9ZUl?{?Q87Bg_Q5rm5zmg$t)p{T8T zPUf8K$dhivHXvE4EEVQoS?U!VlDnXo5MJVJqZafAlHS_rF44ZIBbU8jxCNl)pQuhd zgRj~_bsM&wQXZ&c98>Mg+}^!1S1dfCC##vSFx9nq&F!VjR7L0Z**VT7mjW7Ewg z$ZTvTqS2PEMn|AejfF(lX*qncrX$_-j&xE<5>&+}(Y%}M(Nr{%d?C5 zgvgus4RdW4tMX~2*wkywZX#^Hy$gHN=s<~nBO?q1(Jv)TL6ArucppcbgT(8ilgp4f zNWk8LU<=rBd~m<4-UbNFteI7`)-~G3b$9vO_!Qnq$I3W5t zP0rb@f5nAjM!7SmK^ym#sQTT;WM|G+&3BZB3ei!@4?$E0Bqp!n&H>T-1YYPY(yq2* z1-s1q5?jq9<-gS6ku6$@73(MKqZlKo7|X1JQL&n$;l?k^!y*sEGJTLS=EaW09$F*~ zT4l)a65E2#v4m9?cL9oeNk)=ZHIx+iYo$Ng#P!6kw75FEF@4On@2GPY>0*htjWDzA z4ax)QOvLhQKbdz#imbw@8p= zw@8rG*&@M{ZCoMLK@D*hBD-*DWG|F+CSBU7=9=Z58*el0?=p)_V0=sxj&eoxEee*m zxH4E_=T{QR4qZETD4}`}`*9CzRf`WYZT!Se4jH?}ka_~6dXj&;zRwI|<0q_C(DpsT zdYe?RK6W32yOCTDHaM(JGNzp^yvM{GrjCI9o>Q-dZ|3@F?)~0ItTVGd(YgT~5?3k{ z0B1i;tGb#*(OW-d{<6j_#fU98w-i3^Vw=!<+v-SUc344tyEQ@aCi0GgGdg`Axh<<8 z3K5>khIc82#-{S9W z=BTdk8)V3sgU*TSCQ z0d4Yj#!d7u1mjj$=JEIAHdpJ2RyJ2`4$UUqVA~e+R4N_1!8=RFH>XYD*Qv8Oqp2)5 z(;$G=WXNeK>jPy;$6&(J8xxjYWwqPG>Ahw;H; zaq9t2|28OZ5bU)cObyUa%}*<>hm2JiZCcDMa%rdI9XD;he`UvW6pYee7Fi z$u>rYb#m`Xg8E113?7POJSgvNW56r@pgZ-c9e4W0>E_8l2o;>$e@F0l$-U}Y^{0YV z{D2iS`!6@!8*OvsGX&(6ee@4}R$y=<16Lp7u@d*F;!p?B9OhYU(j&gs2rkC(Sc$8v z*6Ez7UdZe$oU#~KmK;mooBi&rndVDgX(qmZ_abMVA~RlA&F83R{xve*YgCO`WKba$ zZMa5K_{0mEgyQu*XVqs+xQ40{edhdYN}C@Rk4%YHm2$Gh1R&->aX-<7>kEk@DCeMk zd(Eq)LUp>RA0f3pW4YP(9khJD%OPc4zW==;p6)0i>!419fYcvP(dvwGzPo3rqQz0; z`)hT+oH8~`^!#MpXue5$)iF&3BEIGhf4PcPFLKAm3LXQ3MZKccT(t(XBb**j$9*6^ z_MHk1{_7(J%{b@8B}KdL+?puvIq#=9Wh%aiK*;vPX_iYRlGbhemsFi)=i=7;_ryQT zgtfwhEFYb#{;XI6v1ME_qt3U>d9fDGx2&dp;zbTeYm>P|FEUdGv**NSm;S!LpZ6+Em3+j^8;65KSadZkMQ<_X-T(-P}bvLd)Wt4q{woP0!sm8U96vLMIU z=#m-#tNqGFm438v7TbFt|BNNXRxE)<31r;vDbtv-Z#d$?U&ImV-{+>FqLa|>Kt`1ay*7DKXnj8&d3 zqSRn+5^B#o31JGrMSgRui;vf&CE@aPo>u#IP4RKcsQL=<D0N%l6aRz5EH1Ph_q^|8ca$Mv&GN)_N-`5K1H*` z$s_{n4Pt^WmzP5Iv1B~Y$iS5T9*PMQo#KR`3(Y;(NYo_j*u1aN5QnBs_!`iQ>hyvw zM!`mt?Tt>p*roruLZ%Ok)5sI9NJ3;9H^1T$;CAyR5Dow8V5FV=lpEsorpQzm1jvc> zCFiD#)6)Ph8r~Uv<_?Fyr{%dlnoBS1vx{E5!&rEB zc;JXXpSS8qj#n38A~gBy>K(XOvD4ko7p=D7Sj{8HjfG!J+H4iG@Qm77PNK}%x3dq# ze4$VJ$41zW(PGzz=Cx>cw%BF1E1*bmOHlUA5A?*Ja&b$fct<24G0G6^K=ScOpeaL6 zQi)aAe&7Zl;a2v38hm>N4Y;FckjPBu_ifF;!x_oXi%c1pSs(KW0ccgHWjnaLm7e4{ zTi)voycg@o8An|7HB;bpGvz8Fw-oj1O-|xc0M6Gl>-AaVoSXHl^~rd2m8&VlY1dwJ zAthRr3B84m46ZI{S1$i?qk{{$f9Uc*5B&u$!8x~slckHh{10@x1kZ$LbPR(yeP`hQ zOGGlqTsR=R)C;a$lf=P5+(I?!ZCq$uWNKAELXeF9f}hH^W)?QqCgGep$n~QzhZv?+ z$)+#1VF)9bdRG61H@&{{<3oa?`nN)-`f1B{6IT=5wv40K6;0K?gKN4)Uq>-xj6G|V zB@iW+A- za5U~~)sIG93V&xnx-k(c)>W2TdCF7``z=kW%qf~Y7D$A_(4RYvlq;~a^BoC&c7~>K z86_+HDx@+bha)-raO)hNPs+~wPPE$odSmvs;ORNq_v@YY@(h1X^8B2(z$g0gXfCM{ zU;s);C0b5zPz|t@aeeO<#@I7bQ2`#}F|q2XZ;xam{hpi#a26f_zlqOh7pgCb@A)}r zsZWlQhQ!@S^Z}^|BvG8v~G2jKT}=lG{;wfRnbc@VK#MdT4dS9V5V zyPTicHR5U`-=*)#+#F(E^K0C1#gS9>Iio&yr`Qj@9TW`>6g>d0BP+0xIh;$ z`<&Yax1Zky*PY)5DbfYUJG&tIHat>)Tb#a>g10q^fXNt%`k@9ejy3qQAo0eXPQ5L2 zJ4+%4E$_~HECj#Gem4`97=weCz}~V7{V1l@XHk1eeW>M6Xn$us;@g`)}1YN6U- z#SuQ$JGZMqIAncG_~tkNLt5>G#0$hvHzqK~GIxdA6U(0q)e*-17xqJE#TsYyyY#}? zm>WxauDRKqNF)gvjaVBly9GoEcA7wiZ@;$mcHXg#Y-3nr8d-5Lb34ho`#|>Kwlk!) zr6Qa|+QzulM3}NA?^7Q9FG2CYHGEfu@C!*uMGaUo##x}KiG(&H>Yg@XT;1~exoqiV8whZb|l{lrN#~;AX{Ni>^j+<@{mF8EzWcW`&MG1pZ-FH(WJwQfDE*ntnom3NJH zv`a4>>Vf5Lpp`x=XjU^GR-e0S+-sbIjGiDvKjly28u$d1>|A%?j&R?=R2Sa#tEaka ziVjv!P1c|AAQb7_^}D?K;uO6swR%iiNyC_{90{Q<8A>pT{)T;4Jo=n^RUz(uVEvm4 znrq*anDwp9GHU5I)4c81BJOb8ivB)IkOnJ9oB5ndI1!QIC;XN37vk?b{Mq8S?GLT; z$N+dCIsv0<2lQ>brYbZ)RcmF>o1!Oeh~IK_5cKiZY&{f*M9m;bjU}#d9;iGm69oRK zKH!#%f%w1d_X^G6ilSn18qJj$cxsGY8lP`OVkEiod#M-kf6_XZ|I^I?578O~dYXIJ z;!Z<6R^Fd;2uD7?HGW zG2FM&MOJVtz8z85=0;bATv7cjEPNDUr8m2T)A$N}Q-k^2JlmDww)SyJEQL&PR|kGlq6bz{MfH2+DOkx5j?as^a?E5mV!T52li@fXQfq-?pp$pk@^nY@$^CcIpu2nd7DPjj_QKH8U@SE>SP&HZo_yO z@dnS9YG1^7iWey|%+L4b3z;ViIELSP886^pCb7tU%OeG^VjbsyCUmNs7B;{}PGjH^ zJXe3*-G68B6z-gkDdR2zQ34U)%Hh5@0+S*ID( zpLy|R0r1Zk0S_&Y(c6uiujZxwicmA&1yxI0B(QM{wNs0kmhHB+x5xlcN*;N_Ypu4X`# z=)R9@e7})QyCwVk!M23zqNCNmPmm$fs&RGiGpk#xi~dsW`!q0-;c&n|-UzI!_8nK~ z=^}p}HHsR|A3*h?iq+i$H$)0nVdT4X9ud%#voZ5+{0EAxSiB>!C)P_pl$+qcKAOd6 z{Sf{~dFvPb7H{$K32_}4Ma!;gA1lU!quF&Lt~kQn9bShxa>{9-hSkPx&ST{u3S&ok zDyv2-)SKIO%$^7VY8_b@tT@W5qfSh#3yxJ69FJ7gIa{6k+1h$mW-_B-m4JSL^a8q8 zC3YS9sev?LmlhJ5i^^PfUVDL|;#iVV)P!%_ByHRt|1X)5&TfO^%5TB0_f44*BDscV z?r3Jbf@6slTd0}2VWK-S&1>B4WH)2n2gaO!?q~@$MDAwpc18b5L*r=~NM?+`9InxjkBq;BhzdI`r6atQ# zyU^(B9|Sj@<_=J8*?$uSvzh7&)w_eIq3lNgzt!|R`!=5O$}`cdtg}R&7aZSFq7Fy% z@9^UIN2Hxo92;@xY+7)0>_N`6Bk~fyHdf4x3RB*+AT>5kPV%3VJRxUOSuWbjoF>s; zYU6fk;dykV^SzqOgKal)5`asHBoyddlWfU2$s#qY6PybB_8YyFmJIPq!X4l+bR@2*J2svnm;0bRj)TJ2%=CN=6 zKBU(EapY-lWHR@c8MB<6Z5p@Fc&d*(b`yRHDKT(MYz_AkK;W^f?PvN0(kB2#aciub zQXd;0uc&#aBc(PwPgx>A3!<|yfXJ<)+(w(~>aD+Tq+JH{*FVa{i5qs+Y*0FC9&`u4 zW}MUqzfStSkmftVuNm+4=}~olw&tPs@HT%=P)2zx$%9K|lt)!a;zS$^Z9NlQa%N88 z{-`Kj&YeGlUo-yKN^(h!Nbab4=&XulC|QxKROHtx^84{f8S^y{ospuYgrF7gUlQ7U zM*l!9T(xEQLNYn~{oG*Fda+g{Rvet19!;!h&OCHyV#Se?6*U9H+Zg{}-|Wuh~!RkHi*L+uIvT+XNkCXcXLz|fllV`}bT;R&WU1y3dY4opLi@1Cd^E`T#I zRiniQw#U*$Q{Wh(xPVt%>$SN+xAnpWlroX4;e-d&2@h!0$Gi2XJ^ExB{*z_+k7xJ~ zw&cq*+hvrLtdQ}+($cYvKjFN;;;-xYn2o-hyHSaC%&wVo6?6owf!?&QL3ufg`T)tu zXOb|bgFEyuEaR`vP4w>@T3^1$@@-)rCoHdIuKQqhaVyABuy^L59@vWw{6Oo#{3AC}GQQo|fY0_Xp zL?5;biuOllx%BrkcWO&D*pE{~MAXY&{s*HzUPV5p&V=AIX%4MQG-N=JR29fV%-+Mf z3(hr;ijJ3*wOj`4(v}GYL_Ae3rK25*1+%Nf|oXAWst9gz-i$t)UY1Ww3BO#W0kuThu{yV4O%m1^O zOP&#pmS%Kkx9Myn$INnFdhtQZL(VS0F_QAaNg%dXr$x=}hp8)ak2_wMF{!6Jr@&m0 z5`9OSr<%mOwp6487Po_$U?Rl_Esme^g6BavzA9q8+bC1u9y7*ev9WH7%4|WZ+KGyc z7tU|TX-kE~SZ=ZaWtX`-f*$vUv9{x%Ugpv#x~s={YVxnF9@Af2o8PZQA0q;4z6iBb z@Q>YR;-&nI=@pd&CwO=k+59tt?cFDE)3hQ z#MS9j(|EbVTKi$_BB1-T0GmueZe1)G7vZ{G1yRRzZ;n|Ncep5x!+vD6f)=^%N+K%w zdyzj0-_M`i$|Uwc;_11Ww*H#GOZgkl-);QisnfyA#+LuY6K{NMyN6A7YgNK@Su0r+ zRWY+vqRTL)r`f;q4j=CgJdOL^$V^YpZoekWq}d=88v&NZ^CJ1F!^fuviX&4}A~RE7 zcamhfB)P34$(Y!fn*8Kp}qGD)A?y`P{EK z*z3;N-@(DP!22M7GS|n$UHKQQ0F-OECaT^`tJxXhO3&tB*jxJ_5&&{_rDyDivh||2 z-Ho(z(T%sT(-gmJP3~FT7I-vvYkWPzh75X;A5bQAXLzz;l8L^SnMOhD)IxKF1urUT zGUenP@?WE^)le>}((6C=CfCE?16M__C%etxsPIsBo%*1Kg-3;sI&lbNdi70}haD#o z{@TPfomTaqG!(avyrTao8;T=D%Z5WX;4jM<^+&j>qyDdH!H-9Ig2C<0!EM26uAVAj z33p6+53uV)Yw?j5MlC~OLjX-bUipdR4Aq>LaJq}J=%wTmW^`QuU2KC5x_&&dy+ zd=+Zzfa$t8OtJB{zHseF__7SW?d(jnkP|}!qqb}fMOoPVCY*MA?EVM53-$l+6}^g3 zCv>A#-9mxUFHv0ANBhcAO&MarZFCE5p?Mwc_(sc)v9gY?AS1OzYy}S6c+*PY} z#o==HZaTF=o${^RuhsQFt9yHWu7C2wSgHdM6^@obT=oLrUxG!I+~?6kGIvHMy5tsFkK6%^;l)I*d)bSf4Fi|~t=3{S9&Q)cetuTH z?D_0OeYz}PaDDid<~wz5VE?rhdy~J?!r;YG^9XF9Ro@r>JkT>zp3Wi-4-w;!;k+>$ zebZ#L)hpP42@R%RBR6Y!1u%$L&q#&0#xrD?=N7F>Wd6yav+V)OP}ltilHlEusp&aI zIMLa~*GK`{rxvO)IK19p_H#nVB)XzSZ!&U+s6vlRM3EQ8`7OgzvIE1%>zi`kE882D zSy73{o%CN*kgAVKMZ})oftRIfCYoWq;Yf)B(XS+wxa(Tb28`9f|00fMe0Wp=^E;6 zG(6mKkcZIHiXwUN$l(Eq<6!|VKtHC99F~^DaX(7S*Z1V*94eE294Xgla+7>v8nTYn zUl1III}ni&2KPgYau)+5MHXDc$Ez2EEv?p*J@o`l|r)Y<0jnmEwCVN4oT%D0XTqTY-lcbF>W9({BQ$wphr)EH&Y zr%UpeC3!y~Ha?C4O`Rp_if%lRg+3<5Qg6owBo?Fbw#uF@CFj`yG}Bzmf{shQ^x2S( zrG{Als!c3s*b}mdWn%}im>qGeR4O5$z417i8h4~_*gBzcEfKsc{^X5Rus^~T1ZneomS%{p zXZ&tMG5@RRav!T)#;OO@t*cq2Gl#JRrbP^-|Nm}X?L-jmQSFY$SncN;RyVh?31S~Y zYX`XTM0}q~yEl9(67tdZKuUYSYkrs65!)%f6@K1w5Xf75Ql!@v>LYC?2M(UJn)$*Caz3RT4?&h?PbdzmZ zMZK&KZOF3>RP)^4nu5dC6EIFKXfDwwBsYj1ghL;XSt)nn^r6`af#O*5)+Fotn=i!d z?i<(N479Jmxx_rYiupWti2%S#rB71q8gmy>_Gt$BN&)6ZNhJu}O+fs@=iW2dx>zt_ zh0NgwR}8LO9-qxSc>=7AB9&u7(c3*Qn_P;blueYF*aX`r{x2c?53nr zxyI!@v2;>KH*zE?)opAjlAkT~sid7!AIZL%Gl`ttm2wv|bT@|#T!m&7$`)*L-oirX zqk>LB90#%#Eu4c-??1xlhd;9L`DdOsK23sx&rR}4@VQSSaI$hSe1?uNAHe_J8@!K> zb3jk$3|!0&&KLz}WGsBikF1XS6txtZ*B+2oq@T|~y7Z4sgo=bBSwci2MRg^j`TsWx ziv5?>;!k+mEj~d|THGX`q{V-chznB?@BtQ#665YQ$m6iVbDF^SbMf&_RwfuZ4;>(= z(CqWU1u$acf_46WHX7J7J7^Sq znCtZS$V~_=Vx|@)evTG+BsZZ9GpxN4j1<3drPVO|su}LPOEZ7}JlMj5`zjV6oSm4c z@6T*p5Q^pqll?EgVWME)Jo8K5%xC#gM)NAW{PoDywe^#ZL{)4hfeQ0mGP@hVfg&ICpAE$-FY2Df805 z6X5ABFMaG`o}LH&^YHfMc0ZP0F5g}A9!U4g1!ng>_%K3@fMi~jbJzVa&bc=dl3Qgs zFAvuq-@&z$%vBv}o+rez=oUSzlVkU;Dfp|!u{llv$L_8;cD^fm7NJT1zSZ4ItxuPyeLB zmBAMWbg|w7@)1spAlR;Rq=RS9x3JnLq>b5JXrBJ78fKhX8Q>&IK+g6Ia%kb96wdjc zL5z#6oc-|WG@Yw;v}L0D&_6CTH{1DgGw|89oJbOj>mhgS7Q1@!e$2QDxM!I|6&RNI z%`ncc%YN5VHrf^Ft_)`*b;!L^srq4Ra+ScU-B8<)m#|EkqptLl3!Vl`!#Mdf81k7; zj;yJ(%w}MsCq@9lUmrT`sY;gt!Wck{$YG%sz?$5_X(}L(;t1z&(oD&e%}IU+&^!TpXLd%a_JcdH5hwz8Bv71gow*iaYM~NuZ)xW zZbFujA}eMR=UGw;hrUVM-Ta@9l)oS(O^J}MtC-@cnUs;BsNR!d$ti*jFet1T_I$v1%=ioK_KL z1Qm2(CX$z7EVXDa$5w4^>uK#*XsM7$B@<{8E^0t3pi~2*zT-qsxHN=|%=cS+zcWdI zYEMs}=l}hA$h`Z0S$plh*Is+=wLp$xY#RarVOa?TYzt%_HCfnrXy-`6OJ>a(D-R4y zfm^B0QYJw}WlK^^Ztamc+GBlNO(7ADv?fB)8U0m%U5vl)^%eA;>&J+C+9Yy3 zS;7#?s)Q1L{Y^D_!`?2+;*7@A0*u*8EN`W<$bVAp$@+7+fhC92e9M%qS>6t7{gX+I zScgj;r7L>^w)8^i|Xq~Cogpnq$`3UIyH17@ex`hml8S70{3$sO za1Dc^zoXWD?evqC*)!6d#B-32^o*&ni3dGzcNN&_J#oKB`@|DKRmyeZD^s=Lo_Mp6E|0>~EAgm)AgyUZoDcE<+quk<) z-r6mqK~+?wtG3@X2K{BmxLxMEPA)921R1TO@7WYpAr4t}FC`S7!VHru*WHLS za@k)e>%|NNQ_J`H%9HmAoukUz`~}n@46?%r{Fm<@zB5vh9{o6NEVT$jv(y;dYNbCW z2YmB{Vl3^(EY*ZD=3!l!zdp?Pyk~@jZ@J{G$Q*e|hZbA(R~|*eVf7ouM~s?Z5{LDY z@^wRr_x`lR2M4yL@2jq;Br~`fv zorbfo9ObuUpa!Xky`$roiqdNmB{R=i&y%uvp80O!JIPFQHlxKYK0xabLvOIy`vEY0 z-_VT=i6GTNm_2m$$ij~jfG`^Chkc{nEEF5nfSfSj(0wp!y4bm6>-m8xD2p7AX?Dum z*eVzONHk_UB1K~m8`*jk5$V}pY%9SZG>^^*UgKbYm!SwgoaXR7%!f%dhfjvX_nioW zRQrb?F*ir!L!Fzq9+M{pn}Ut*;sgG(;zP_$s7{8MP0{yKn(u0G7)j=Xg7u+(Y@nqx zgk}jN2S-z+Ra`jsmMm5J8mto#Vlzj`d_0Pai*>=AG|)tB=Z&C=;7+r*OoQ4rVpHH~ma+J3f_Pw= z?s{r|t=y=tX_$pk0NI{nw-AMpRm8uAxmdZ=8X!xY7ZK&P&EAHNFako}4b9$`72h9A z@Y?X?obc3K`qfSWjHB#YjH9MhELk-boj}h!#8YAYpUs-MU(m{1X(M!{)aKt}?O0;N zu^mTjD4}a+Vc@lHkTj`*pEb{k_iXX56z?~s!2`tmbMdxFtVg^*5brwi_7!hPyo*R2 zU$ADDO(fl}zLu!rw*w?Z~WG(D`#R13<3x7M)H>5iA0h;)2Q%$+dg>ZTunXfoFc%Y$S!9J8939Y0Ht5EK# zh`xVZt2dk`T5_$E1V(Ts*c2&W6?sakt+3qlG}SqMmAsD-snYO*wPEiXb|UYK=7N`u z&<%t|ibnAymRFvM$arMNjN0#0J=;KJ3Kz6z7>mT%LhwkQwpo(274b2F3y+L0Am!qB zrQj=D9*6GS6#baTn%RReUSb3#4SP0y#eqa`hw;mImGjN_J5!f|2MzD83yc1`o7@-X z{&goGo_*4s8bM&C%f-H*Nm7ckW8HBgGX4ZIkb5yf5%6C%%G>Vap;Fank@26^{x$GH zL*TQ3f4GDq0Xbe|(Ufroq_J1X)29{jY@VlHD9=-eVCv8a?lt253OfUPd5O9WTQKZ( zV!h#=z6eI?*QXo%a#P%{UxNFF+JFgu#1_OGs;1%Z88sp>WRtSt%9r3^ASii0>!&td z@^}ZG36zK;)DLkLHyYQoS#dk~BBrIeZ>i9#F08D@Xr)28sFIaoLq0gclA_m+EwXl~ zO+gV|CWBnQs@c0n796uu79r&--)_IYh+h?9uaLEM!>zg;P=n&OIMgI+RU^XADH+-% zEBPc0CVQlEgLT<#hIfM?v!;6&aNDJOWdtu~uZ~^EPrahxqt?QQ!GivEEekL`oMF9* zPffJC5<%+a%Oz6L$FhENm5`a3<+lC|eM72K*Y6T|rskV$_TzJt3fLaZNmO{4G%KCl zB-F^u)JXPFWMHSG*Z~R2-B73@;j2YFeMBgvnaeojiZHG-!Kv;XdDEX|w(v&YdAPXM z|6%Owq+J#`_TJp{P%&P-RgtqsSu~m8FR^P#5IFXUzgWeyAeZgpVOHousbd^sGfLXQ zH-M*hfuqmPty1!q$=r)$#{nZ5!S~{=<_?t>(f+cn7;-2+YLqp~OZ@?n3TJVbk~Bbk z80{T)cB4kDqbNCF43q@+4uyXQK)_2-5)IUSTNQcAD}cRb*YFl&(O+fE1P~q2fs0$k z$F=1C3QM+B0L&XJ0orfyMaTm+;@w{Hgltl+;Ym5+s$6iW2r{DCyH+DegGP`I^c8$- ziFnt5G~%hS`u;@~$(_a>>i%_iFq&Sx3o}WNKP)rhZEFH^mP4q#_u~`@{k(7ZdUO9R zR)ua$s9~kkfA(nx7KT8Jy1?L-wYf9CX{9s%DTlHn&#U5)!Fby`pQWr9MUdR@bM#KH zUcSq_>Pl{@EweS<3;De--WN34p~eTvdH!4 zH(6|CZ=~K)P^UKIIOf1 zd+Qbu#4>YtlHS%QAFQn=t;y&k%k;qrDi`#By0b#5|3CV0scdU(QSy z^W_|MLM+WlWpjSOu_>OZ4@`SAz$YF9Tr-x9%rZh>CTz@2{zGxsjAe5@kuxO5Ji~-d8C4RVk1s z%|ipkJ5JZXpO9){Lh#85{t~zD-@s>+{kxH{p8b=U?*6@i@6`TXV)t*}*vPe>=gS6S*Z}jOD50JBIgd7U(~sgXk8r#isF7_lT5}7MqAW zvMBS!{=~JJC(<0Vt0If`p7B}Y+PxY59kXwUEE<}PXDDPVPYo8`QTQ3Ez6Z`m^~Xgg zFvoE1kTsm$E{rT1ew#!LpPds~vU$R136PY2L3Ra?^fML@r0r(wE3$VI(&9A!+z{-@ zjaq5J4)%z4v>CL+RFZd>E1XF=EmoYxKLs@X>kB9e=GTACQ9gCsd&K%r<*Tds37guw zh{P;=lH%{Bj$iUOoxjiUe~G_`$^T>f?>k^u(*5uHoEgEmii3@3YVz6MAq9i_xy0htomKcGqW_mux=SD>+0pSP(5J| zP$@=QSMB_gi}XF>Uy}H9PKuvm-A^@kCCT+X+jec37XPE_Y; zE`{8M&^}C3Gm4pPfDB8w9SikSa%@HJ{`T;sT&o66JXYphUE(}Sq%e#-LUT0+(c{o> z$@n~G;l;6gh~j!kO4T(X6s>e2=oCiHI1v2}o_&jHPK(8(fy!^lmQAW*CbMFrMn((?MN zXh`)0T-FWu+v8ohO&;Vl2AgtuYBf$E)W5Fc9@5@{+Zwx30<80BgVDcmTg}G!n{{pA zL;YYWsY@^;L9Hpw(KrV_1lvdQ)~B}e5M2LAB~0@+$YIU<-y#Fffl;5R?VEtEo@{^K z&LA`A-KRMJJYp?xu`dVOR{(5|=2C*yq$YI|Ujx#=3#3&qNdNBb*($;3Hi?&sCLD-& z*wScoa*ibN7xO4;w+tH!MQ+RC+UjbsMu3}xE%sEnwh5V{H+aBg)W|cN@YRy^wf_Kb zr}3CkW`Zyu{sG>~@wL|=o{YCH64Y#5!>__yu;vbChzP`Sb?}V<_+iw@dmJkc?^r66 z1Bz63mf(pI5_(i{B{m92ubN`R2?5i5U$1lc0Zc9#t8;N#1@u!5r^3T$2$y>Nms*SM zIu_Y=d_FG5fB|H`!o6^x@Vxxzx5zYVkZEMqmr~Qrv#l4VtGa>-+tz)77Ws?YQDd@z?HHBBryn7IC4FYo>x` z;b|^}@pw{)t=AQRDJ73*`gccAWPpk`uhry@IU);o*9S;o?yp|MXX;Fswc~Y}Qy!kg z)VJuERuyxG^=BOuSP*k8;q`0i2Bz-{XNa42P8sz-|9P3?)fe~)yE~(>`Erf212faA z60>p=Q{?1W+f1FYv&plh)QL_Pkrs4SzeL&Ht&?`4Z&4j5n!KOb=kV$fi7aESn(J5= z8}C~3D0*m(PzzoCqcq_5@W4)|%Xe;gj2u{>h6GDIU>{gHDP2bnrnY}*;L*Mg-#Ot7 z8b>l^X(ib@k_}Eq{7~{IBh2-+cercciwSQkTLKguIv{dv@#=p=E^?tfh$q|?Fgsm!Lpqh~mlJnHgYrf}fGaE3yG zb-hvG=*+aKDOiF6jKl)V;mbni*IMAWIjc|NsO<`F$W_bCjAd7XB!j=;Z!_cZMQKis zKkp05JUPAihw^vfN%`bS%B4NRzS_fW;J$)CSt3{;WTrYGb(Bz4VhRd}dx%8ocok*A z=3(0Ph_v%px{)7K6XLcdXDS}~-1CG#?s;m<&p?_zg3FoJ7K0OuQ-pZk)otS4ZF{q- z9S`CK30167oh4p*uO^AJs`JGAd)w=&E)?%`wzqHfwc-_Sq^@YZco*5;e$`cY;}1&I zfa*KNJyYEMs=q7lJH+j&o-6K~#ofO;DDLs%c2_?k?rX%|xB6*uU#8PMEAB6e`;6+} zh#OK-%KyE%`-$7AUW+@0R@2wRPZoB35r0DZ+|1uy{IP;M9^>x`{(i#WulV}|f6{j$ z3*X{zFMpr%ca%So5we$d^|8kDI*eSylPawNJ%EV1)jet zhKjZye3RG@9)xbEV<;)VySKa>SBQb5qO$ymaLbPQ--wS19R0+9w(a*_F%CtSUk(&M z``|_Ks^TN&PB?CnX)wV=P zY#B)MpeB{pJK`UACx@|F*~T>)J+;1xavb(f;Hlu1X>OJwaHzK^_Up0mBW|=l&8`Ti zcSi;0kNoTt|Fugdjy$0Pc?uNR(-AoGoXY6WUsBHVa^J`Vx2VAn#WI{I;(T45527Dt zE@ZoM>V$!`*A&=IBS6 z+ zx;Lk9E3Cl2&De*1qazRqm?iz>k%EX@BtSldD7dPNOmu(7z#?zK6IwXGqP%F2#Ew%! zCpWp%)2kBx4)hj3CKo4ql~%8;t+&-7JUM4hnlHbLDfI3&U(i;{V=KjkMhb}jLV_H^ zI>nTVo2{E>sk;~6O&>~0oy7~R!2Q(P^<7_|Yh@Yq8#>MwIzwyBNs@h#jmcAU65sOW zX1^8TI%~r}?7JV<`m{_;N`yKEBc`|c&I@hBH0ybRc|$oNtPjk~b1bR2fSK?AQv4x_ zV%8Gn`$k~i1yDS`%eqteZVPSmPY)bKRnW1>{LyLgDoN@0ND6<3q{nLV#w3v3Qvsn3 zIwK^f0_*U1MS9hWEyja_mhP&5O@~4Y302b|Jk1lHkli1%j6%aVMBB3a@^*StbkEs+ zqkVVHbWE9w2rLRcK@NYaJk)w1tq0q_5{5Iw!?w>r8=hMTC%=_mVnd{_;Z)C2nmCx`O@=GOu=C>z^yF$CG z#a*D>zvco(CCk*_7j18z_U^R39UzsF`Rf+j>(H@XwzpNs3T{iuZQ7e7AG|BHSCmkT zw?TVH+TLZ_JIwYzr@hl`?=0<|V0#1FJJ0r3Xm7Rcy;FOCWP1y=x7PNSYVR7`o2k7o z+TJ|v-D!I}q$~8-_BwQIm+fuUv6k&^)7~5biu6}|-L|(udq>*dW!gJTd2i33g*}*C z^Y08Vo@U2CN4yAg&M+S3!Aa(`6A0(~YZ*FD00^kulb^${7@DmSh7}^5^GR@PzK>sY z_49jAekR2()u@AxZ$T-_oTf!Xvu@3=P{v2@QN>J9*`&yOP<4;+{o;sxbhny(Nz>uK59B(_z@Zm?t9l=o>_+a-2|j@@U+ zHt5)F`4GEI#|nc)TJfBYEwW>0>DYWbHlSl~wPP!EY?&Quu}GXFVw^M+M=n3Df8Ro=+Swow3U6l~svSf3t5Kb&?ADg!V8+WR8AI}ycmY~>KMBrYOZ;(gZTUb`S z8>*7`#lZz@A&9nwMF(Og&pY(9dN%5YZ`mdq{)!`caZICQ6~IHkZ$IBB9Z3?0e3SH8 zk!*I3X(-mHgdRp|2HYIqpzz?rjZ1D%L!;DJeFM;)>~nJm?FtWGi5(_UqL#NgQr=Ku z&3!>Ndx^KDa2p(DwDx<^NO+I}mwbutW#FjYqg8X1a3tWeH2e2S4Ky6eW>hwwm34e5M43;K{0g{<5e{&Z*W2HgqBlkU|*jTTLQ;jbMG)--a@g% zx{J+>Oi|jrwo*=HBI>9rX^BiFL^(#4Z}3ftSIL3!3+hgz?w`a*P=@HqIWv6YNyVZo z9GX-L^!Gu1&QlF}>qYfVd4o{4cm6_wB_O&l`vM#>2{!w@?)cJVd`pH=^Q<&2mGz>Y zQL^-RNA*ia^(=Kxc(7DD*KNgrt|~1=UEtpwk?Ac)&2wZIFSV2*5+aO)CH-whDX7L_ zKy1}GkrKd%YMh%g<(OfEFH)B2F23G9_wM*NgO9l#zUj@^yD7mDzZJcC74?G3aHYJ= zg79Q_xDVOT?cd~b-yXk$QeeAF=8NJNpHga?L?HYsd%gqrgXuinpqu6qf!#g(r5pOm zm0T>#W+fmJzQEu3<U)_>4+{Sb5vioPb{eA)V%vdMEHdE`ZKjE=<0i4&bn#v-{{ z2eCriBv=?+_HrTZ@T0@6o%2C)Mjf#ZG*Oke`>>CYrDZUXMc$_MH)cQeqd$oJMF)dB zMX9d4P0fv6k=xI8W5xz0k|?bo5(`sG_%>1Dn7V&S#y&VZQvL!*)cG_sQjW~i3rLKx z{)kT0OrheG0H*HyMk51t>*@)nu1Za|LbzlF}q4 zk}~nTUZH=EWQ}v5pa#Gt3RiWaN=a05N)OVKIgG{ASm@#{GL#~e#DdQ9l_ty4CjXff zmEN3j1~mjXR4A?{kgDCz5+V!8IqA7iy#$aF?}u*?ome#+CB6T;_!jxbuR5vLiRZF1 zs1&*J-<%T1iY0NrWlF1+O*8Vgx5`~RUg?P%Z|jK~-&;@AB+(N!et^=S3C7hlL?$GB z^MRJ$z+>a+o|zH$w#mZ3lb=f9oQa;W@wt*Qo1aMtJZDw8VmTzWa}B_mD(x~=n!q{s zcfi?09CQo(J1cUtT0OV~T7Qe|6sT>gSB?|pxD1#M<*$Li|Kv{y)SLMeB39g2@yC3t zf`6fR6D4On_w2ylbdfh6BJ#!)!Z)~392d{la>pWe%uR%ghxtoxaKbdI&!i$*oRB;2 z#L4P}CZ`wv#K>s5;;u|69jxh2gv2#>Vh3{;5`9?@~d(F=`Y7(Sb**ErWz^BBE>xG|5%}Tgf z-S3M>M2qVO*fAnlT#tl?N+x2(^&(a*$wa7Fz9Lmzf2JKMV#TR~M6S4gpdBNE#j2{F z$wjm{l|p2TQ+Y+WxW2!gSEP&U``I25FHR*B`C@gwOwolKV-XO*zN|3p%Zh<32gDvE zc%?gbzkD)d)$-{VyGuS9v9HOePwW=?xMCCKlOFTR=Zx5O@=1$b&8G)iDJkQtpg`2! z;j%*7)d-M3?@#u-&x=1@+{P~`^K^My$+P36d?K{_L65NZ9&R~{9OSQp_KoG+pTD#C zlf7v&U%8LEm%ku?dHgNoZ$EK@Y!Bkz!S^eCg*|zcuaIGCzVI5|?^c(F2<0D1^JjCb zB^MM0Rf#Dgxu&#F*vrUCIxLd=8~T#!T06KE+F||IMCSYXJMo~l)puLXJN_%IU$P(S zM-I>9(oe93-fm8J$?rJ%<)e0XQ{`pz9yQM8n-=bG7DdhZQCDJ|Th(CQTaFPAXZ$Md z`#Qd=#9&5Oy}cR&k>G|5DWaMx6d#P>Yg>*RjkB;Jd2@|ocA4r_6Mu$#YwMenPU1(u z9)8rt^Q(*CvA*w`H!hq3o7Vc<*C27>XNfS*MU)4TdZjZF&#^WTF*8qs8*mZ))pgP* zTjx`z7St%3!4h}wy|S<&0wG;SqdLrPNhz-dpS@AFp$B=a=wlu{dg}6lr#0!OMB@1o zxTqit?uGAxa6v~RYxt@s_UTa`h2Olle3i^=H!`3yOqO` zB#Hbaeq?fD8IqXeR&~MHw|;P&eLi^+N8pj%w8$fwzTChg=R5p^L`m3DYb7Ns^$gbp z7VJy&6$Ky377Li8t!c@u-^CHm=txX(`3G8K@hC-HQ*mJYOv@)g9;45+s{fP8%pKl{jIKP6kFbIKhSp*Zhb(IJ?s)IO)+X7U}cW+ zexWA=GTGk(OgPFJ2Ba}UMNBr)z*UZH=Sk=Brt1elU|jEk&bOh|4>LxO|RcF(u(HF^n2H(U={a5lX^iU5U%hw=~GOpB2%hNhVqkl<~>A z1=e4u%JeEg4vJ3MO$@z2e&<0^S1z*X@vF>^+O`tI_fq^i>zAarr{Nl$C{VDTlp+LI ze=Py!9g^=;5OhU4E5`Y;tLW;A^w{MBx(?%|x7^W>l{twa1VHHz-(@T+!)c!ejF7PW z0d}~LbN!TCDiBpi(aI5yzH;sIHn=PLmL|Jn@6kqUFg0qki)Y~y9-KTS0ftJ-2r3&Q z_W}~y_fXd0vDC>6VllfY>I!FGP@Okd-gqsg0?HP0Xdek6eY~wbo|q+%&epH0lFQ%E zaY=;&YxN$jgGa%Ve*>8v)`C>Rhj1ws3g49;9H94R23&e&dvUyb;1chLwd2L^;=UQ? z_`cB(b5^9mY^d1_08u$%yl}uB{Sf)|hQ1xxtuPU$EYM4kvY7hAdt|z@0$!$$<8@_p z##*ETWf_`wgUnxX4IJM+ll7{k@f+nD;ZYnKUL`&}*KHnQ7=WO|dhL1wn2~OOAFibm z2ycmx*H;=ZXj|drpPNSuOvg+gAsayWK*r@@h|ayDyr|foFj3Eo#~J&qSG2ES%*p1ez;gv zZ%fHDN_Wh8?&eY=N`^Xkd3QlmX+9yH zwG%EOgv&=m#gf9Zd zuq(eL-G2iSP`AZ99~^;UlDDl%zb8iCf#;}q;OtE93hVGU6;j&!^&PJGH<_T$CD(gc zP6lHj;CAF|%TShJQ}tZN#INIR#vZkh@RGc4ty)84fDZ=WFIuL*UwMu%He=mzx68r~CHq$MRmcQH-dJN2kqS2jkW&- z+B6O(FR?LeJ%A9nR{C=dA$fs^F|HFjhrFL(TN4WX;uDhc>eTxMt&_4DnhcdMle1sV zxh&nO{3!m2xXwYWbuVPUTv=l(I#;k50h-}kjqz_3?>83T0~jLN{mrJ~Z=pzh_QUig zhjMe##Nmp}KkK-Od3JM0q-5wR`$u5@&_q8YB%~zH6FB9L1?OitMIZ*}aXSGej>LW$ zD!(tKe6dv(b-w3(SJX-om1A}xGf~{=%bnDNpBk7a#ml}kVN!7;FOHA6XOHU<&(c-a zzsqQ9*lrAKF{Z9Jrf!;HY~L`$cqhu=U$}K?m|@Inn1rLTZ=;{1ZCCI}pSdj<#LmUy z6s)=65!dY7g3%ND{Xt-Ue7*RZB4zzg1f$1?@8q6+ zZZp2LU^K0GJLQ08M^CP+Al|*?^!7&1m z$|X_()1jz&tg1_v&s27 zFX(Ou)#f=Vvl@jVZq<GZviRMEDCr= z-~@~FJ!t~!&#zN3NCrT@vT6Q5omykBJO)aM^+oTUXOCtsv|QTtaRZQ;bX&ts#un0ZjDdGH`t580@gFxLQrtOv;A$ zp34rD+59i+38P5WFu~ml8djD+fl_hN*a?K)slujN%Wg_i#Y=H%`mTnykoZomG)!M| zXIL{*DeuMwopx6*tzpc?5|k+Qs}*IB^ir!pU^+U?v98z$(8SjEuL!|K!d$CZ9l#+F z?i?*tiVCY#PEEW#bejYVw5&7x|ImOS5;p-1<1x$mf?LDqQ4IRUeXKZ}q) zB8mDXOFX-mY(Cc!`t=IpPBj}balGWQe6F#uKiywMXx8(DWp_Nib~+k}dT9kL-yZSq z#+XUv_WGsJ>SlQhDR(w`x1@931vJ&sqa3XpS(V5Tb}^4R>k2ntcA3C}Ef6JBa9Klc z1ma4+=ef9~#V-nCAfapsu#|EOaoOAnYsi(122Wklhd0IGX6~QT?@2S1@((%DpmRY^ zHt6g$y=%n3!ukn7(yXATacOd0Zc%suZ|nD5LBc-P>{Pn@a7kMaNE>_W_w1$gB14V1 zt>5!Hx}D}5iIz`J>d%rBwR+ai#_Dl;9>0uJg(4_J0lZD)bDi;rlgdCFx!yf>-6^%t zzr(D*B1TdbA0|DM+tCcE#$OWu&t9XAVAJnNXPk`+f0JOA&i5DlLh@j-vn zv5G3|ii2uH*9Qt@1mfQ*YzVVuu+?}%4a{dhl67chEf3FfpNctoHs-jk{~Rxv1OJP! zjTyhfDe{lJzh5A+0@5dSm^n|hKCf^lmv%W%b?eJ~fwkbIm4b)%r`I3)KJ3=u7wQiM ze+p6etHh48K)nf6vnV*3y&s ztv^iV`+?3U{8p)^PGzgTswcly1^Ef8Yo%<>Z+-mxvPC8NtuJ2Py(Z}S1|Q)%*_?ht z@!@Z{t&908uFEJ1NODXw@hIqDgu~{===@3k&bvh{Og;HKp8$|<{?7MUx2#RbuPKy$ z4~MmuA63&<9H-~+DE7{BqBYZI87{@>da%msz%86DZ>Q#Lc@Od3596i_lQ*^Aqt^6P zw%c$4@iDy_HnWlpo2JrC&4)S5=EGz)!M|BjezbN1cHqjpAQ8?M&Wtc-_E|FkZ!dmD zdjX6XShga-Qy`lYODm!Z=!?HbSyZaIjJ>8A#moE)h*-j4a~EFr5p?IF>h+$O67L$C z)G=!zC3V+t^^t%lasG?2hs>Ps@J|eOW%#kA+m_6|OXbgxZI@b+LP^Dl%t?b?zOm>} zM04m{FHFB`8W9uP9nPiLyGUgb^PN~qa{A7aTb()VEtOGM)iU=3)1>ANi}u)6fW7=MMUZ!tFQerM<)2gFt7hj>T9{V)>_GA`-WdDJGgg) z<&<`Lq%)tD+9>&Te zzV!SL=u7`~LM41LeOXRAn~Jy-r_h(zNLIn($v94?FP|bTMPKGAT2iRW8HE}TcU!ra zX*^64nBXJ&3jEl%9 z&oYwL_2d_yM9IV%5KdiFeO6?*n8zIMwl#wpZ@L!tz7XG_58sF7a$?Ein$vu9xl z5C+x%nx5S}N-))Jt>+e@54(qQaqKNK(T4`ds)akpvrqh4Dl_+NE%$D{a!=+SFUf0}5G9;;!6RMnG z6S85+qLxt9)Cy}jWySjxc8Y0F%#{R1L4Xif?N(pKda-A?T2G`sWy$u4!}6;3yeGBx zXwUtr_WVbW_DF{A_J}Xp9#zy)&dRjs$K*JDdmb9mV~Nx4k?Xf zZ{?PPbC&S2_=S7QFIOoRTee#5h4g}(VAL$cVVz5;=4FXZ!Qgd-ZU)S5V%}i|kbFimF=mr$3Zp+4e}bQnKX-EDB-BE0{JD|P z|4;GfNXNg3Kcz^b^ccHg*8ThcRs8XPUK>6Sf7a?33`rc$v*MKW{|Nq+KCkfSzj~5b z;E#I$JQD4-JV{;fZg@ysvHX58n8ZWX3z8O)54Feo8Wx#4BQ%D2j!xCKbfw8>&*4OE0Xp2giIH7y_Xq> zgooBoquzG(xDU2A|A{g8?nBn#PJ?X(CJa*WwrIcu+Z)C*3oBKd_c%F;5(EQ`t zq|1_7Uh+2wyNDb`=NjOkg=3B*yo7MGQU)Dq~6=9yNB z_^L!W9wMUaqGUw3_9Rz8&T#s|V8R%6p7XXwDz`++QTn-CS!g(|eqkQHdPOa$vdvJr zL0Iqk)PV*iWtu@N9<~NOo7|!_ek^RC2h@ZKAy%cuDl6O%$14oALp|p44YI~vZc|#N zIAoY)%`$7|f5uqE2L{^qoTnk;}FR?dGjCJ z#Sd@A%oE^H@`)U>s(;~h4XJVq8cU~I9nw2q@FPF;Cz4wo2$pMds2!KUR7!yr(VOQq zfd})JIROc?E#?HQvbEcq#UFCmNbI(zD;`DaG?tXd+SjpWRw)pB(l@NC;JG(?)YAA;>}g)JhNFw5z`mUD>@ zQGuOAbLTzp6pp$P`n^OcQ2}G|4{%#!(77@-woHP_Y)oxH3Zj6j?j(eV#L#o{Qz}0N z6;mxYfP#TDsk1D<(B-?f+EFU+CabJJs3Wq7Xdo&ClJjL$R5U{|(^37Rqc5^$Z%`XV z@EO)2Sb&=@Uf2wQJmJ#_)+8eM;wI>Ha*n?+;aY{;-Qde z?_&*{#3w09t5ZF{Tj<@cbiY$fMFiV1^_OV!CY+JVt~!Z=Ra(7F7Oh{X^PQ(#(}K=V zrYY7rwB0UNuP+efa$s`=Mmn0PF(mJKFcLeo)S-o}-x|WgaIJ`RBS3wkuL?AlH~d0E ztX)H8W%W%*^@VR{xDT2&L=KY&ORyr+jm_n}&k)5~PH)jyN2YmRxl_3j9J zZ8?ZT@h-?Oz#HQZXYsPctUP3vcSXt%ncm~p7zVNT;4uVAcxQ*NYy)_h$jX=$yG<5T zR1ju9Oh3Mc{x(tg0=rjaenrGqE_GzpSK1i>Zp2l{oKx_`07v9&qAhoj`L@VsoudDx zk*AWP{{?NyZ<0Xtza06*pJV%dSBynG>dS#q=zme#fr{6on78a$WU3Rpu4Ow!->nBj z_o&9^NhSC|5$Jzu4~)Fjf8iwGeW;3wpN~{qomRHVdlo&@mc12=eunA z{pd)ty`zH7t-(aUIbS}!XVwsB*X(o06~F7Z3g2n+wrK`7$|59pe*AJ(Tv~jf`a0to zsp7#eNdwwUyj0MpUC`tkI79EK#u#OXBjcTm&kzvHSyU@Z45IB$Mf>(z+1>dr!5MG0 zC!xXzY%wwipLc7DY9o!8%i`f&7PB=(#XAp{|5xhr7_a(^@mEifk!wBQ#=zA6KopXS zY8^5CmNi+G=(~^7BFL|M!N6I^Dw)v3l@8`c1NrlG; zAW!`z(m2%enJn?p$$3zdV)o%$K@&tu2!8r{p@lJ?V_Bt?VqKaq>%O&*rttZ*M?QAn zDwHMc_pD5D2FS_Hc>?h~oxEkx_Bj|erio&Ai@PObHNxAYo;ZZx)_a|b0c za#}-1L4vK1*|O{|c3IQukG%01amVyVm!pTa%Ud6m$;flE|2V(btfap)=UGn=m*rTp z;GdGXS(Ycga%y;Zo}Va_6}|Bl)-|NXHKec;5kbS-5uaKok=CM1g{6|KV*PuqKMsR< zP!B?Wk4s%}UDZ53N0QoyWG$d;mkc*Wl~O_}$nn1;c@z^xcqkp#U(U0~iS}syv2$}$ z+F{+~ndz*senlp06hDgmslbs+@&RI8GDm_0s&y+lU!hg%_dX1*Jw)twyQs(Ff&ZQHeZA_-75zLrrM{1!w(HyJ^sD+1j-kG}VQ-sIjFqhIyku_|lb7ps zQcfKhkQZBy>_z@eC88|53`?p1^7wT#oh+dc07G>{uhI?8w45}_-hr~EsX7Neur9WD z?ay!oZDmK+aXdYHurB_ZoWTGTI5xqGnPlMm2@l8(Lk^f>0eU1-Y3Uvts1W?)l=EoXn=<+)S85UXpCF&1k$GOz*c4S10(@kLwp!hS2Yrg4k}y9r-JW~D9CK8vM$gyspu-s zA0w-*fjUT3u7�C`R68KBEdWbv<@!yEN->9F1u$mA*jfo$E6(SXLvVrk%|$U%ndV z6gr@Qo(SPEUcgsm>9WX!zJ~BvRFKrW@vL)jtqW{ikyZIG;ivf?gy>gaXKwCRKC(+I zACV2sSp8@k0{luV$$F<9@rsUcof3gPKgp4CN`y&7u*uDmvWfu-Hg*j^XucOk{m6St z{YYe<+gR)e3A6?h6n4#!l7@z4Hd5kRmt-?HbvF_HCn!n@arzYl8UEcdW-u87Dt-O? z{fyusKydPGIK!R|M$Hbu@P&Y}%lk+0@ky1ZgU{D>#HsK>ZQ|+S!w&pEfse1?B>ge} z2tH!rM8Ssz#}yMD4I&TnMF?@yd%u6w|7^?!mNzmk%^ z2tRy&>3dsze((2(T2GA;oOuQ~^*Y@2e5SihhAM02T(!8cM7xAzRYD3Nm(MI6!Q`h- z>w81(g=;Ae_$xJX84|mcgd7$$z9!4>cWU`ldY8W&tnMzqFYvU!nk;{WU4EC8znO%o z@?|WOb^J=^Meja*@}TMiVlB1vrF^y--G0#>ZoM(Y7IxZ#L)w2ap|SrUq2kK1n98#zWJ8yDlGEadlTouxq&-nR**35e;ne898rt9T@0O$#uku*Z>hvli(++zJ=sVbIq z1y26}8dX%1?kkLOYbm2z1Rk)XoTrU-I)7cA&ML2t{Vc zaIm4sMyHtKedu+plbhzmD!uJ(ASVe%vOx(i+QSYhZc8***c-3xTy7&I`Yi%$)iw+3 zD-R#UfkNw3Uwj+_nn~{0cHGuDX;5sd1Vg%ndESSm%V{pO>0%67wVJRZGtIowMf1;2 zHvh}Lny*?XU9nbCd$I@8_tW)Y8EKL|FhZ?V-QD^|X~;ip{nHYwcy|aXn&;7SBnTGr zwV7qhamIbt{oNspa0-;Huj5dIJ4-^i@B^Mna%SBUJ;q6L#^_1T^obYJAfaI(LIkQ+ z)`fH)TI&LVn4-0S%&~Lr@-rzvNkCeLR3_ACH}U1)9&aOPByDhU+TCot^twA5cgL@^ z_ELlyjke`PV?0?_Q~?AiWj~uNdle4J2j+ReygW_X8ZR77z1pqWX5PlTUF7!JT$S1j z&8poEQH?1S7ofMELt6*ZV@!VQTm8Dvhnzozp%r}0<1o8?XDRtl>eKR{QgKTD6OY2- zi*WRk|AeI_#=fji&*2a&>`&`sT>4g0jU7kEa`!@veWI@9eWwF5Xdq`HA@8fITf4?c zW!6?o1-kv4!FCqb>s|3GtC?b&MGFdkw|$9!3UAk!m%@$jl3sA*TYPQYn1|D<J+}y+P+w$ z`htB9|JU`=+d4!8!UHUt%}6P$CcEpOqwbm6*4fEU?snGAI;yRjw24&{Ni7yl)KNV# z*hYwKO5%X;@ZE?Gfwb9WC_?+ZQEHZajM6&3_9$(`Y5krbHA)+B1Z~Z&SiOo`A8-~? zpkRF9zYLsof4dwsDe&>;a9M>~q?9u-v{+Ke*CB6N`{=b;;6vD-rR z^|=(Rs^_O%p8HqstFTNI=%(au$S?A8p74UqnTISN{gz3Aieu##>)gFL@}#e-fCFRO zE0;$R18TipuS(-$kMm^LUT5s;K zXw0Lm+6DF)fsJiMn$i5xP60cyps7_Lx8~vld3VRS$%HfJ!umWb{Go-Q&DS{mu zAK+61T#PY#F}0|WqrzHODJ_6^*xe)Q7hb5gkLa>~dcB&F-3f?S{4w<3Fhh_5Go!rLxn<5?u_S425sY%SMU?t2A53!!fW~!*A_(NPQEaxcVEM8(Qk{DTPA5#&& zFWb6f?Awk8`k-`AS>|1WvUM*IV7>MwakKE*YT1N!?Cr3sU?ppuPPT7^+#Gj=C%eLZ z4o4wQhWf@vDqN8wF#&*%=M+7her~YQ9c=3IcLpCr-O5FB4Y8Ue!DGhUKB!Ki8!qQN za|U2CBz^_Amn8DPBjoWfNkky)NUpW|EPK0Ig@Zn3@k-5VOqVvP-WI;Yyt-Z{*kJx9 zi%CG4V@el}v`6kjT$rsiy%^AFkqNg`CS0pbxRwel=T- zVK81uIY8+UP%7NUZuBOT2y9IPZutcgt@z!+_99t4Dvz_YB5-gk6?fZE*OrWS>ZRmR zo{Hkb zbEB>FI24$Z-RXU*ctBkECAG21ia~dh)4{$!V#UCcqbFRj@K}Jh%n>+@8t*bfjrhU? zYjd56@ouFRcHuE)4K!(`b!d^ZLj#)wo`za)NA2|e@jDhCQ|rjZQOmPV zR@Z#P(?*=RQ!KBNYjYrfv?oyO-CsNXK)fJoow-g{k^DZM4wZ^*cKj(h4%ALRs1(e< zj%*W6jd(_i%82p~^vko9jK9F{s;nl`TW&t@k&e)ZulC|*+2e(=8@0X&j{NiM%bqEM z0eL-u2~?BwL*}p2_cX$pm^YP)dN4CNQLlyZ0}@}_J;m(JBYu(f8maUPppCeg92zLS zrmm1Be}P0wqTV?}d!R(J{%l56DXjqs3%A*K8+MJh8k$JaI4i;!#S44L+mM_W1rHL; zt(@oqQ3`5q0k#146OO$QN9M8OgXUqytCfpgZd;Aj=@^EnQ%m4`(YDOKQ7jA^p;7|O z^%x;A-(I-a!C@JbkvnN@jnI6>hqVE0WA$cEcAVdh#d6#=RvYFfQXf~TAzq9cQKkdJ zEQ~txQHlxgltddZQl<-{1Uj6UD0VoqU^%@(x!4$OPJ2aA36x4=Q%etQY7uk4;NM0Y z{|;cMCMI`f>O8jJDTM_bb1nh^qr4U>vC8)`0ZPqdZ1b@+()Hx;NMeWEHVHiE{HQeu z?Cv!YUXiI0dqG%xQ5_wP<>rqD{n=H)e@vgLDe#KSk=T6FF$UHunZe%n_#!TAkzzq2 z1kFpJfzrAd&+E2u^PdB4nrH{7`x(8&)fwO*I!45NIWw7u_xHr!T2#2bLJW^ zFX~#vdMb9Hu?K-+i@uEuj|!uG?)}6)M;5BN^KnYqGrFE&M`42d|6lHSb8lxf&+r~K zyl-7N&vjvDUz7$Y8m6u*Smvmf23QXPFuk(6DQD&Yt2z~sLqN4O!MZgSHcY}ABn%N4 zoiVk#^_-7y!mHkifoNX)4-6g|ZUn2zgN)Z*VOLGt6LbcXmnecp`wX^`OE5YiA`52p zWPV%A;R~G|=3BwH9Aj)hj_s6-X;^I9QGZ?|6ml%tM(JM-pe9JhvMEensuv=BD*hIpQl4z)^*9yQs0XD0v+1N8m2=- z?>zKu{X`u&&=N(0lueEPC*nV?m%AHlG(Q|R#my#FsC;#9a?BiN1@YOVE=3$AXjU?) z_jm@|u|#^@tn7+-q0fjT0c=G zJ|rQmjFQTF0nAJ7-y_Tx1U$^ja@?C&!B8&Ka~S8H;=RvNw{ zcmkAqg9=&sBR9FYLn|q6GJ>NR2NCu7E-`3xiMVPg0b}rgR9as|50D5yw=h39!dDz& zif#zc@Fsk4M3XbwTWdEn+uo11Meg^TvCTKmn)@nf+TQZfPD-)WX1(g z9QW^t9iZYF%V?Vic1Sj*6%@+lMxJPbh?KdV)WB6<@YpaT_;-?$r~np*FedX4=l3J7 zsIVcuWT5e6L;8FeO(g@(=ByoPvK=R>ijh3`uNSHXek)l-#SRVe4L3JQ;Kcmwh|6tm zjbyvkjQlkfM9M;?lGQA!rLK{v8xcmR+u1_uVF;&;?SiY7C++YUHKI#4RwB6`1!Rk8 zEA`O&9QrXVQX=Af!Z|I#n@_hWc6e*#)}^I@$761;6Hu{uP&`#+hD%lhqqE1OTqxM+ z8V885g(6&a`2Ez0wioH3fJV!rXZz+Bc2Xr4t))3d3Py?(2aD(MJ(s(v88f8mo~s2o zblmh@ZAP=U2Af>tiUFU06SZ())3buuVex?~ zy@sgfA$bI1&X!AW%^!j0a;LK+38-wvhc#-P^c3q^QV;p!!hLdyPfQv`z{~3AsH1}G z)G~E?7wTb@xiiTJtLu=t{x)+x1jzLCcQD}yn3D|9%LVec1Q`99Kf!$+!S+%kGYvBR z1|j;-;cp5ihQL?&cM$a;2fwtO-`nAY4lm2kv(EI{`PKP~_qbS4$__8^)Ic3UW@NEa zY%!;AFc-A=vcp-OjZS~Q+0@zSYVyV%{t@xJN%a+h*DR;R>fp2EH{mDdQex~tAEMXo zn4v_BF7EVQc+&o1yxe~r%FFjO1dardcyl&R_P3||J;UE(dq*cnc>0!bc_#MTBi^{_ zMN7v9)c*w^aXbB^!jE`3jSWBiU}0yY+dpl|Ed?u`0Sx%1p^w_%j$UphNhEsgm1P1B z47ACiY|M-7Ln~z6V=P1nQo9f=L?wD|!k=B0m}46;4BF3W&36^E2$_-svNw${a9Xl{ zaX8wzWKzKjC+e-KvPCX1E14gn=0|wP!WU7W4*76&h4Wx67UBqEp4FG6gyvxLlxyZ1 zAB$1!Nm;8nVz-RhYHf|Fb-F!10HVjHPdTlb@7k1=E^zKSsxT#|BjOZBjch%!@%$v& z8p9P^!(P?985=@l=^ULjBqq0Gipyav{tbTE7383o@Gvy5qvI5=#eTH@=@M2+3ETKF zyRP5*-&-wg9w15O?b-3i<e|g}r_WT9b_EM`#?8rT#FY;M3-bZzDSdcmxC zwOFbr&6lHbPvCtcu(^#`^G%XVCX&A|2M>;_Tb4g~O)1c$t)Ag6bz{pj%bl%< zV`gjNHhcc4eR(MtG3M>d3&!%m^4Z~K?LFIVk3K7jU=NqaiY4kTWsJ&{%UBS1OYF^rFHN0qhNNVX#fvdaDM zX-m)ZwrbCJq&*X*Jq>15@gZo>Gx@E$JzG-kxy2f#+k;$Mh=q#(V!^G}b^^|&IIEu_ zcqWWex7~OIzGlE;9UWP!V2sApK@12!=_x+9_DMbXj?x(5o`<2Mc^4b&T1h8$#mf%A zXFH8`JFM;9sUCX!@J_pEV_g>|Oham_yYw5i&n~?LANPxGG!X))2uiU)!J4*Pgds9D zjdQ;YeJEdLf!-|c0$JR~*ydmtM}k7GBqE*~ne1rFoP7&!oN^%F7Cn*{_AM_;U$tC7 zXFS>LJYhV!-Xv(O`xy2uUS>VymB^XFE{>S;JhQn>>7I6!+R(O?nH}(&i^=!e1kf~KLS6rM$Rf8BXo_l;oaofeIsp@*`gNglz!_qq<3(H zx6jkbBfLc!2Q@!RC|)R7kKH$gaOaAs+tTGy+}N;<2YLdkMsy-mCXDSJ#3!qNhXo;X z#xh;s#pu+0Gx(-`eurgX(E&LdcwlvhJ|>&gs;c@u4K$xwK7s)mYeShj>}h5M!**4R zrK+L`zYYYidhiQQ)4wL_lji+g*Q1X_*GoN1)xeL9EtO)no!T>{csn+jI;FjZ+j_KQ z5t1y4*m3wuus0@4SELI`gg6C8i+0P2>NS$9WO}mpEbbC1?sq!gO?L&EDNW`o!gsSk zUr^r1N1;FWUw8Ibc+bRB#~;*w2FIWTB9?q z?UAXoU$Q2NRNJQIl1xkUCBUAZ7`x^8W{iC!cx0Hd_@P%tosf8pC1b2&|V zd}R@r8b3kMR6O(J_V9978`;9ETvB}T0sl2JNj`{#T+*t@@_hLexBAbH7cPs0mi7wt z4WU+`2-J?meKVF7ADI1V&+@4gXmRn}XZ8(t{e|1q?O?PkP0pKZmrHqvcciaX=q`)G zVObQkSJs6_`O;buT9m1* zv9LI5jBQa%!ut?2oVrWxIhwi;gHOo#775B0FF&cjg58X+e0ubEX|G`V8;vdaoc^9> zeC__~@m;=3%KNlU9Wq42>1(Slk}4%0x$1@>Zaf;B;ybF_@P5Bz*1qkF)PXQQ@v}}IACj@T

)ZbzzKcQcKEofnO2ua~sYlopNoqO|GafHQC{y2S zeETC|Esktia39$10XZVFBSrL{s40`}0&Afd)JkY?6LT75i(o0}h93c5)&rHwUJtH- zZ!GJjM=gv?^?KRjpA^rP+T!CO0eZ(2#nWaN(5ZYS-%({*3=?PX7oEOygC|(1Hp@5= zEu?krJ?A*Nx;5Vg5P4=tk}<29u2C!Uq4caS_esT*eGi{v(k8EP?$gos6;4Akx~_!u z)HCg9aEADaHyl9rO%#eJ!EyQGGp z+I^1{cYqp3CyVQ5xTN^SVJ8;W(8z-dC)uzg{0V)=un3)&$w$69&-|I|9u`aSo34Bg z>Mmg_YZmfjSex%De9_InXwOC-re$G5uBVOQXc=rbhMwYQFrHkmcaLvmNyV zzD*tTBeN42bX3K?CdK70GmjkJC26?-diTvw&8<)#dge6{&l6mAJt@{cJH`}m#YX&` z;c9)HeS$*fepggQ&R=%?&G*I5&51WZ?fWkG-$l!AEUw%)`yGj_?0EB@Wf%{!;xM31 zchJ6Yt}FY2LX}nflKlKz31D=FS{G(=12@jUdPp6Ko8;FByGDDmtW# z;0d9|$mEFY`!$3wxW8*ez7`{J5ED1mdn zcAmgFPhd2E(1~E<@!^ND!HYeJ`GeAejcLUv{QcvDBHTu8Dn8*GaAV-HM6thO@{NQa zn!yD)V{xfyc6gBjX1wAkK+8x|M&ayx)ha;!#f@{m-Q*fnFt&Kp?1S-}Nm3Y}IJUTP zc4oZ#Mm~MxcLf_ykm_qET!SRh;P~*K_+#gtlTF%#b!))<3TwjqHV_KmDNGovoBQrm zY___cD)!6CShLZ3b+3Zwiz*^38By1QUkNpxAYM)IBshECSKi5{o8-^sX#QMHe}dr8 zP0{?hR;Ej~5qd;Ir(}j75dIuIySezCZ)cq_7CnSZ^W|g?p2roOvFHK9;NBg5RWZ+| zHo#XC?v-p7@_o+!F0;P@^*!|hRB`3hG*w)=242z%*(&_G&Y{APYl0z%C0=7)X^z>X zxNu1hTn8LDwgH)OdcJ*|!yWv$yk7h_j-*u0qTVVWmQHo1gaNbTxKkJ~FqUS4Yy1}; zlh1ZWLizJ>rg%&*=)^N>I_LGLEGg1F5ceE@7ms8&*1e_e^9Yr_z%5KAk7g=KED42m zB)JH*hQ0@LXqC!Gs8mV2^5rH`wGD}#QMx+b$IpHsc!G23PdUq*$GX=eR)vYt57P=a zCi(aCi}H9=>Dcs>QB$T`mvM=EZ;RuqZ*4Hkit?OC%T zCQzuIpI6K(YR(6&3&+%*^p}NY(dio%&i!frQ)LdRtszAZg;jmG@I16}ztdsvl6s8a zw+w%Ss!*=e#u(-a@0dfj^ct$s%@yQ0&Dv_`?AhahH!XF*Lne5Bel{n(WzeJfLXQf> zl1EvBy6I79QMoF0D_ZnAnhGtN47$zbd;vw6HF%)PXSL)+54SGM7Lv5Cx%-_=5 zI>Sp{GGN6MU3o^0uJ{eumZB!pr1*sI>(Y^wTu5ZC z!oD8+iKg!^N%FJ${9o$c20p6lPWYcm2AIIW9W<6iVu?Doq{fB&O9Ih?1|fth zDD7IBQfo2H2q=LGlV~o(v^-nd+O6HPE$;es?G`H=AyUaCm;_KsfW`1q2#9*)pbamQ zgkbV~f9KxG3)0>0v-|l!|FtD^?s-4IbI$Ml-p=oYS6lWWbRArjD&1EWB440Becg5e z#PsOMl3z@XYFLVht~L>>Qmv@hX1egWPC*9hUc~!p>yC1q>ASTZb=r>IX^r}!v}PQx zdz-W!5p8O%pt;v2!xrVwj1`F0wJB){Z&0gVKR9<5btM^Fy3`gS3%011tfm(72_{LP zq?dcP63<@Q9;*QX&+5KHl4#0m!UGD$w%}YAeR_dWU}fiOgeju=rsOq;7CX@uWM6`# zwOGTj2@pgd!A=Lw3v~3_lKcAihu##-w)t0xUw{8nans=cesHk}3oR>C5uR=$blqJ%}# zKUrlg0GV8%WC@Fs$-x-1En(4m!B5DCRHp4&Qp|r_Og}y|Z6U;g@}CEVCBLHlN936b7n;k`pDPPenX! zURaY9{m_I$r?y56N81+DREc5oXKZA?2FrUuX_>pk7}3VYR@_BZeOp0ha??!BYBbnbs1op$`m(j0MTgh_V^yUA`(~h z{eOVJ$M@lHo^R~O-y{0YPh1utlZXlrD{_)Vx{zYw^GV(a{p3}&p;+_A_BJQ7bfzS+ z?Z<#2bC>mPNfa)KfWv(4Fr1={oX~ljhn0oTwz5BM9oO3}`Gq}vuX)}u^^dA!R2Z65 zRIP8{B7mM2ogrK*-Ah4`x+X#tM~LL~9@L&ol#K1XOH^J*wajypeRsj)j0cTUG(MC| zg054xYRvT&@OTfq?URY;;%27zUHXATVlj8SB(D z9`M$f-}9~WIB1NA=2-yORF2VAA4tjszjNsc3l#DepKDsBXLNLLjI}O**P^^*=1x}= z(Qhj`WWZO%=s4JyW<*tZ+shkZmo$`xuuD579B+n?O1J}`mBgQyu=uYe?1BMiz+F+-J7wrZGF7`ANr!^TNP}K#q@C( zmi_$|>^UE&%wKKKxl&~wWY2lvkPNfm-V%QmvW`M`g-RTHr*I|9h41iTtv1CODsiz> zoV;zylGDl;lM;Fe#|(-3u>@XyTO>Jqc-WBKqwBRb-{O11N=QS#$4ZGc^NF!{vw3E) zx!hOhdK~|o##*(C2T0IfyDv#U4zYk$Vz9myvMIMy%dK0a!U(6rjg> z$F;o1@U(Uk>nU+u+jPts`Ow)Bp*m8#DHG1`B(;&1M$t|Ok4bmbliE&+@ROIQL9dmn z!#Tes)~0Pb94CFL3E$tNXV_&e{Zr@EukaFz*AaG_JFmUNT z&7UAMh_DwD_kT!ChK!Z52|jY`k((L4jC@gAGstE=^|L8OMz@G#@Of#r@|*Bb7=KgN zNx2m5#h(2iUWj1(-H};pBndgu` z?{?}*xCj+9kCXzf;=TmtiT|o00Yk7xNee*r@GNrwO%tj7683}uSJwFL80t2RQPT$Zf_CZQ--H4EI+mCn6eCB58 z(C5RBK%~_%Wb-Cuj2&2<7u&nHsp9q?|6^a^NF2AEY*-BqCzs~IUVn1*4TFo zxXe~2UDk?6Z&V${gqTeE`hGQxNmPVu8_^_sfla&633CyPh#O0blS^NZR?fmUHlzD_!U9#pH7)^@y zyISqVbNm0i{{!Y*8HoUI*55HxGT_#7FH&!Iu)Y^Z33v^V6^Q7dtXKQ8LJaBDmZQBE zz>9)_)3Iz!u=la0w@J6Sr`DUG{j4tRJ7SOKl=V)Uq9OHr6%wzkcjL2m+cq~y^u;+a6C1{7mKx9U+#l}yf`QzaS(6~m6EtKa*Y<2+&S`+G%s-y;?50c=H*_D~S z9T)V2j*M#hWz$~lATCM4O3MRNoMj%|SJTo2cB+1HENyY*RXVOM`6>dOTrF53Ms-@2|cPa-a>Ek6W`7pVtxZ5NOJpd`Ar%``5ZBOz+Km{*rkVE_pw>{CN7l)mZSadxI*Jv?s5GPicfF7-XsH*l|dOtvV8Hdg|pHn zWANzjmQ2$dtED&7sVA2fGCEEMd&MPK5(PYAM^)G{g^*K5qCGpGVM-O-T3J$v_~*Z4 zktigqO9(fExW=wj2+Re>d5nqweV6@R$`Ckczo<7L8<7prG`c-aRLL@y^yITLK6)t) zi;%>T)}Guo0R+qxWP$3)l%lN>4;pNMR367}XU2lp@(p(Eq(D}n?p79u>oWd=^^=YC z8Sso2D=ZPlIlb>BHC;B{zT;+kv^8 zE;+3AGfrBguVuZxt)C8Ac0*Zj;HS^q-Vl8Dx`ebT$Mj>b4r_Z54nj6bG!GRAqQN)h zR?_PdGIJ!fWk`+)GQTr=XWLG5v5l9-rq-(z9j@=EDcOH=U<=ICk?o=zrx%3|B z@$oi)HpB?98C~Z+tG6U~YHQ>+mFlH6PLy8oQ{i`IB@CXqmn*C+qq0{`h0O-{ov;G?QclDFu*BGyTue zYrThvG=-iD?CnjXyXbGWw?%JccG62qO-odUn4KnzKRx+k+A(^a?rl%r z&9`&u!?c%6dWOEgI*}Fy`ElVWtE%HL=>1V4&EJHU^+{e*cHL1_<4sZxG;AexMi z2XeSzHOI4r3YJ%IHB0*>lG5v}B1R7T7sjCzirrX<@`kWm4vRTvc)W!3&F~}%=a}Jn z63#HgOC;`GYe2Cs&Tdc(enJ1b{Q+=*|z*Vd_=#MFh0dKT$3Cf2DT;49!= zMK2WLC8Job#2K!)1saq3?5<<*m;^ky!KODSM6~i&#EQZsz_6Sk7%WY+Y31(`5*8L4 zTRix}vDE4p!%wyfZ^4y=lWyT#C?rfvqn7t>c$F|MJwohho0`P$OpIxXKuv^;glTyf zPE|Ln zbOWU=elVJ*F zzQ71oE8@J+NT}00p^CYF(y2Fhe7l{u4R|b0FFY06s>pVg_!f!#ag;(jRCwWALLL_$ zg%Itd!Q=563R%106o2h?TWi?DgcilWCKS28;ArN)w02JN9gTX6^1QG6aSO5&`c?Z~ zyU3D4POXDLTll=TRPUz%0c(?_jVOGum2{K}B%HDx`01Z%Z~Bs!jg z)Pnn`(xYWP>a-YB)+1-cHmR%HJT01E879T$VAv){M74QDG{2HS@xUR--DcTM#?6JT zdST;~Mc&;!%AoyFTwUH+x>fvAFKE$r9M*Q6N!y)v4yA*RN7mBB8}qh%yF&|VaFC!) z-K!*fsI}2tFIpd7h8?rs(s5>jKan=Hpxh|YTZr4!aVAvg#?rX7wKDfE%xlDoWrE+( zf*;Fi(V_^~=_c9QJ)B*tH!poo^I2Kc$G!VQ3l8XqlFw+t;~+-#;oSah=M8|guH+W)-sC!sE9syfRFVq}QajQj z$;Z9uQ}YqS?zfC|hLyHG!@1`H;EIe76Hky&>{iis-x`a{!WP&)G(hfnH@6o%H_iMpA;^ZPbpspqUEb-96OK;Q9 zgcHZgU>RoGe!W&-aEjU?+#!h%^Z|i5PEaklQEK6FlRVxJG4w9)VF7!ws`^yg{^Xvt zmgF3 zFmtC+czyaBolB=j717LU(-&-kbZ*95SBoNPJ5Ek0P2?Gp;4{)FPDr4n9h3DlH?l8r z?-99i=5`D%fVTF#`u&CgaVBhNy(6R2;pJWHup=86(5#ZMD-ce+&v(`I39R|1u?(}N zbkc0;^uQhETo>0EN>(x+Hs$LK~{3$_`4BYD5KKKby{g_36h80(Y{<&j)V)~2N% z$qk{rEgdJl^N6g$hr356Kj@P>lPLyrgmk}xSF4_vp+tfNRAc>pD@Gi68<+cY>^P+ z(IzOqUHasQcno?H4=K*jWH&R&3upcWTzHIZ)N(6yg}=&P>@dL+kyATd7FH9YE@H} zxz>WC!Pa}^K?Dw-sy72&ttGc}U6iFcA+Ozcn^u)Hi9;*+-aX(`y)OFI*p13My$}!A zR*|J|15k0@5Q*L^KHl+;F0hruPNGNTwTQR=Bxwc2HS?%9;+w!_buO^7ccQm}g(4?h z3607{Lf`%%>ooISfwXt^!}jCe7Of(QX^N(1?qVh3e<9L(RYIe*e1ewAE>0*$+x)wD z?G*rIsA2&lYLlI&H;W;WYNY6|BWl9Ctwu&(*FnRL|FaZqVC4E4F^4z; zK+?s(DB&1bBwoOBj^E3{B54D`BIWEcSSX;r_m|-zJqDJSgT#9VpzQVC%vkL8`nhnH zQ$N&yo@iCclQU}q@6`mlfl!UT!TS#WMDkAET-v@iKf}Ciy*s}2booACR^Vcs?|N%1 zM{hP4bWyLrwf9N$GH+JfZGf`xR`O}RAvy$p1{I-lEG4kT`pSy0{R+;zF=Uu{)Z@?wxw$GLNs4_3gcyP8pIVp5+ito#rM=W{VTwZbLzpd+k zfLvVDHM5nR#JxV_@4Kw)&rmm=za$rRE&Z?wrMa_XFmlPWv+A<*`4wdV@dG2?T2YkkhAcyQESvocO^hcnAtua*CnK2TO&?+TaLr91uW z%iFYcDEW7+c88buLS6WVBBJYr(CI|wzG7R!-*Nc09FRlN%X4EJ!ZSCab-P5bI1Uu& zpLaCz=kg`4d7y${ZphngdN|nz`P-^(S-I})w#crYMaz&%;SvIY8>1ypqAtL zb3NNgr`x_s_rkb|k;g7%!q=-QZV~v>zs=@^%a@+lH{pd_=#x41+s&!B=2tJ=Y0dj2 zH89mZeBVfUV}|NUzrr`RpP=eoa^%_O!E10~eDRmnRdF|44-XZ?Wna45?ql7s&y)wP zkUKo3BiQ-HWn=Nzv~$)J+YTS4vJixXnpo*t^6mX zO#Zt6d^B#ED?CKv^)ucE{}%1F-LF6U%Us^+T6<&o8GHGu+f@IS$6L^|FO1@`y#~g+27HOR<+a~IJFwnY%6 zNk}WXD!gV-z66IqHB7N_(d+akTqVeYSH9DNjdtyi+`UhUw8aI_3}bGN+36Y9)5trw&k4~BA;+Sc#4c0osqEYBh_!mRmXZ{`VKDr*&X?u@ zfGw)-6M@h>acWW^t9O>Qdc$oK#dAhp`%O|!u+afGpvp!6tv@nOBA=0ZYWgGNCDJdE z{|phXU(_QtC*lGpQucooJgMnT;rlXzHAR7o!?Biwg2tXK;a*0l_#mi{vJnqQ1niimzX)FY{Q4C{ZnY<`EXuRMNj;{kw*e zvG9M_?}G#CkJTx0BJxNA4Sd3HJilUU)sIaq`;qZj`*S`sZ2UvCNkue1V0+d3d!vEguDjEUMtn^ab)Lp7Iwo2|U!0C)^nYYf|~C z$9YLZ-cB<{OyfZ22Y7Wgw8R~nml#^^4B-#ebxijk#RjYp0YEEPLJ;vG0h+l*D?b4c zq5Xw&%)yl=aOPG5wc}FvA%2qf8 zMCdXSLJ8c7S|2L9gjj_;zQKdiL7Yd{l&x$wGhH2WHIr-HK>C9FR*3_@Ll0b166gfP zd>jjn^rT&Sa;Mpoh0>Gn#d@Od%U{-$yH!uV9<$dB6`i;GGwuJfKj-`U^OiodDY&}T z?!PuvB*G&ZrCb1Flwn76ct*1$I!3Y307=fKFz>#K*oH+FF5LcLZ$|HEbv$VmFUvgT zwTolhV1p-EcT}sGEyTc+nfq}0BD+um(Y0`}4~KKiX|2apC!U!dj8C8s7hQR7{r83Q zwu4tL^?pIM$}Mndv7uA=k-AR*n^CC^2~KF{*07_|3*(=1<(ibkC*^;|)B|kW$u1}` zM!ymhmnbT5A9@qCF$YxIr<<*`*!myO`Zx6_8D%}99MRVN13)k}Cj;nBy?xs^#=O>y zSnLeyEm4|8q9easCneG%{pt>sBT7k<7BPj%`mvZ&L)0X@M5VC@UCFY|!ESUV+oT?Z zyeBMONgcY9u}W96UvwpVL{~D?73@w}os9XV=t^=YzEwGY;#(XM=cu9djp%V&R7FVI zBW>(KbMgkgvLOs(4cO)u#8f7SUX`(Dn<|so_;dAlUbP2S@l2n)@)2k6H03lgSLKnH z*taTb{&^0_Z7=Z8* z%F``TkAn!T~Dm^7%N_ZNciSM=3MF>V_8}%fz=!2y@d9k3495hzW4{hfm zJ3=_#8eZwNW5iT?Ann-FyAU6Sc(tuD4SjJ9x$s@GMpP#8rO3MGT=yPz0}C+{NwZz#HzV zSp|Awjd8LOGu6Tx#tSdDz%U;=l?~o653{-zlvl2!UnWzmqroDHF|T(I$e)K~`+%Hh zrKjsBJFz?DO=3HDFg8T!=Y~4xp3r>`|447gQ%@ro4CLIlW7U&$nYn%*_&#p5B*VZ^ zhy7eyhgR_o!AuzzKW!#Zd}bi$_8qIHn_2FVEF;ZUr_roEs>itFEVag~9gJH)WR&u> zi-ta-o#$a-mXBc}3Pj=Rcwf0_uJKOnyYGmO?Vm&uo|bY%pTaL9j!?Op$cr)`Q0rEy zT1n(V~W+L)o=vZ)&yj$0DwrhzS_u1XF@HSOZ+Hfu=xZcza=%f*8Jh>&~v+1f9il%)T)g~ z%y;0VR@8=Y4)NO&gj1_p$$bi;+^UlawfjKb0K2Gk2<8K_+>8!8yqy<&BFF}`#ES&>F(&P%w67Y-?{$vuT@P9*V*LGnS+0GHkpSzl zK)mk@H78<5?uN<>2{SJ#4&HRMhF@gM(b`8tbu3YG=<2HgSOp)%EHeoXZCD^ZWTvsA6*qVIV`XnZ*Annp>kiI zE0pW0oY}igb_RarXFbSk5BPNp?sN}!Hg1k5csj-MU%nLt%mSI@=8yc#?|*6nPndb< z`P28x#EqXyg_n6RSMZTT0DpgeS8s;#nR;_+z^l&+etAv-p@7Z;;{OB)-lm3fIRqKc zVEFwf{J$&H|H~jqeKHxme>$T0ker80;0xtIv}Ue9eN^$OE2r~3g?jWE1;M3o9$ZXI z>aRu4b5vG1T#NbMgxs;PRgWh{{8h`7rSLb_L$;?S&1nAZ<%{23FN&Xmoq=dkk zyA(r@ybx*}ek)i?w__17;x zeaA?Tl()dX9z8W?V2@5m?}*V0{rx%p@ApTw73&X|yX#9fh_0H4KpMQw+H`-rHocj4 zpUV(PEa0LCz6Lp)()r}jdhS+!!zr0K$SXYR``UxEXBqW1&<1Q1j6#Gw@TH>gXhKdq zr8d~h;fCVlDtI@{3Ge{jrmPkql{j>!_nIKsr}sb}2`mAY`J-qiIMsphI39M~*72^r z6ESgc2?!%ztSe4=&uYN}zUTmwDXq%Ezr@kmO-skcm$FV&efmW*MrRI&Z+4SE9q-|& z!nR49(=egsX2BUqSOnLsjpNajLGxkNWn$w6rzRAhMqP_$3m>}JKy>T1VaKqJ!*p)V zgOEGc$Yc@oU*EV|tR=p zf($6y7kuv$+9U1A$R<*xzgkrR`mPKLp_zN)B%h-5y1>7W2-~?>iY+AiJ1B)CkO@zm zB#a{P2apQqAQ_f?45@Gg4b?f+V@p1{pF@M(k~+7+tn=Ill4!=yeb@gZQkuN9wWOAk z(OL)%(RtNS*D8376o$r%Z!6-L@`DGmCp`Vi0~xTMwW=lPGu2=|AS{FVgkN-%eM2A~ zF_<|n8R>t+coqPjD-Fmu)!sdLe<=UWy=uAhoPmB=t>}Sf?Of40gtLtO37y^rZ($Bl z$ZlYc)kcm!WFiFnp0LXc+D5h}^_d1us2q-HFLtXBWr?E}thy1@#VwQt?Fl{J1&03} zcuOkn6*tKSTM9qHm_H)xD{aCEiTd?N#kaNoXqNs!Hi8ztD93srZJAS_4mxVrA8;c) z)Qb`^_0S(k0?Rc_Pm%qoKboo+dGrUy$8=)bvN>MlA?yz}3bBAe#I|`>%z?g`d^v(@ z=Nh$_#S|HvV=Tr{Te1*32VHx$E^r~&h!i$=PNHEvQredkjF*3IBW#9*tsf<42u zX`Lbm`!S0O*8zj@k5-iuhbD=u|8W;0@xH4kdD}~(ZQoVPPx()&ae6zKUK^Sb=NRF_ zsxZKRzK@~_vGalaOGgB9;%qBERp%4MUvB#f#VvY!ZD?0zt}W2z@MR)N)5`w|IEjz# z3h@yT&bPDUl?-WZ%5Y1GTYiEpZDNsZC5z;Lt!p^SCI4^?Io@0n`0UoFZV7blST?Hi zPk}eJz-MvG9Ob)~UmNK9k@lQO5(C}mwTe0dc=cAc58?bcY3MgrO{Vwoir@1Y&X1QA zq0jre;QLnFFI5t~TUw%;ZdFac-x~OAqwlu9rpE<78=;yW7wG!cvV=hQ$A0O^Xvr`= z@Lo@#`xE~?<-1l)Q0*`Ma$gJnJ16Ung49c496|IAG{^cWaOg{%(dn>mGQY6;6E?l>F!21uK6f>H#lB zgJS4{c&8-8G^TBd8PjsBCavy!wP`V#50AfSueB`F3olgPL_ed$t3~h==uTLch`i{H z@qC1HuW72Be@#=`L9ws3L`8WQ-k`HwYNH_CA0Q+8*ME==k^RWPr<7Q|{qmCeP|?EY zzQai$KtSZXdb7Q9nxlT&5W76LF<)`j$V68Su~k3I4%#NNB4jMs0BE_pCy6imyr$3> zF2p(f-w)^U(Gr$dERHH&AFsURostkD>(G5kp$AhM@}94xmWI3+04qNmP0{uy>As%# zQaJDVhP;>MqrmtIPK*GpNQ6Wt(R+tb`bCha&bEgIk35|edME`+4Hl~Pd97T8bcF8W z`8otn_oeC!4y=7BLoaE?#KEtdRgYXJ^K{`j#p zrldi<7}zg?7gwg03=RNF8*Q$!_n1y2D$_qMTOn4DBlvr|o$$MBo?)!>Xb?p?&V#F1_ zf!`R>cG%3d^e|h;G~SwlY~&)k?8t{h6ON0?*60a^Exv2Cs^O|Uwpt@1t*(Ry+&Wy3 zHLzuYrHm_;4VG!8q?Lc2A*~Nj?ojGhaIYv^Q_+jff3i>6+89%|Ud?t;_%hfv9|OM9 z_BJt$023(Z?%H!AIqMe<}Lc)u=p@{WI|*z{QtOg* zCFVFw58E$K%WKb;=h<1ys4&l1>eyz~u`fnPbDj>;(Ecs9gzZ#XZE9(SURrxY_#x5M zjzQV`LjKbD7o!vOmRN%_Wdfimua)9-XXYFh|GRLaJl~|YaI89D+ zb_Q0vAPs*WPyMYqPX%SYre0S(F$79+M1QTR*;Vidd&s+n+^Xo9iw=p4T6t3*OV zvvy4_u$X}j-HJtbnq1>1*Vq1Xp+Ylg}n0gW(2@~rhPnJi>ZrO@&R;EBbo9$7l< z_jbK>r-+m%vf5D8jPbtfyIKq0$`?daAjgYwpy=Q5IWWe1P?E%rhf2yMN!BPRCBD?) zQJVWw3X1f1dzV?#0KvWy+SLyQPQ;6TtVk({p)7n8h0drr&v>BHc;=vI7t{w1g^2*0 zgk0ek_GA3a#@-WU-#%>v_nCU?FPZp7!6%yBx1L34c7!D;_9`2t&Iiy{OD`;(R{k_K zwA~>fn0Y#;Kz2kQLvm+nuVpcsifYX9Vv#7SPn(MBe+h9;K}i04n(8Jr)kD!#H$?*j zT0u>Hy6thAAGjZwa76)64A9w<3}9pofDl2O<}Dnta2%kIKP9Lc=BBYNwA{X`eR zaKUy5h|9*=VQ<9f3BE+8Tjght)9TUk+3US^TE$GnYRoKjxxwTnFU3~MyJPj}2aAk& zbx0uECJ75VzccNky$glTj#GOUk$EsVr>>&fhUc- zLy#n32-3_4 zM8+!#YE1H4%hR+U$*b|-D)V}kJ_4z0fnnPxbb@n` z%vI=xe)==Smi&K2f!_Wz>D=ci&=@__udlU*`ZTt`0v@KuwjUq<&)3(c{nUhnde@Zk z&*g!rveWAsD>OJ{pgclxK|BL4kv|LNPl5cIB!4pGk834! zFS$BUTU0qGYxVt@{(mUcMlJ{P?u=N}0SJ2|FtLn=m);aE&k7LeI2L0Z;)+jzj*OM; zW90bZZ(oA^td=aiUfoeG8(Pt@|Hb~V{e1sxKHq=z%a`|`sK2WJ+c#XH|91}Re~~

0@XH~PP<$Ol`%VcNqyIDyS1Bd_85#X0<$y*R=6t(g)iJp(-2`{8l=uYyOr1&OdYiKd12jQ%T=KcX0!ri}ZR=#28bCyWrJe@W!y?jxc9Yz_y4n zFW=zmxd=K}p=^cu%}< z!rGb6oH+k{*1cAKjEY2ZRlZ9FpfOtsRP=6b$J+b#^ZZeSmzLks_6`Y)XxtemU2x3- zy8OE3I8_ICX7B4_@6uLF1a-gBSA+JmS}t)&n)dvgT7Hj~f6V!B(&&`qP})_W`H}}z zJ8wX>QGb~6iBo2-pcl+F@~YIr;&ntP)Z4SP!$oz3I5-aoc3!2eSxZdYWMI?Z@#xst zSXBG@Es;Nuiw;vA&Fme}?0l@ zS1!rt7`cMS=}B-qS;UA>!2+Kx8QQaTL@h!{uw(bCdvV5O0+RW2rR{#oAI^2<(1Kf{ zVHfzD)ClbP71_B0dup8AsrNA3;}r?h_7JP3@-WbWr?YZSR=SJkf0RC?E@89 zg|DM9rdQ0Ll~Ykwl3hJ!tbBxX2K{EOoI%?*P_xmnNrhjQ@arn9_LBUu@Q3WD03@H< zPr0(6fSz-}o~jAE`t}qOt!8UaU5_ZZJ9r|tr@k<7PelT|*i^4Lq7#RxJ=GgcxAs($ z_F4^VPDZOX)GPKOYCj>Vt6@L&4w3B?IAijlcve_RXJ!DteBd#MLIT|aYa`8D`+_Gx z6j|nDJmy)*e)(1)BK@DlsUXu-DGpcoUCS@uf5Z28O5$FLhgI{<0%@)-b+V@YPXv0| zRdVd%6*cXQNcQ(J7S)U5ps9HLs&p086ou6{Ub#eq!)_u?S`5 zkB&=hp3CZ`Y^VhQKzeJfbz!X)tdi&$n?;#nDA`{>g!{njoA#GV`eG%QQ@ylqPLe>G zi<#a}J8SolI*6`GTx1V(CJGLQ7<{b6(;h+!oI&!0Qnc#~ZN>ku2>53dKN z6YT=G;2J8D@rloVT%N21VaOe2g)sK5TCLYp#Yzhfc$WoLXwNEXzyeozM&e4Ab)ux= z#go4&7Vb!u-bu8F?T=R>mTkH+JMrScMGFQ=O{FJ+N>8^MrgP&h0HntNzyK*_w%2weBQh6C zvV<0b`i+l%CCIH>7BOh=<%)i^*Q8RmDYUm!h5PXxPtF$T?*v!z66-DJv>yx)-S1kY zt)AgQ^SUJR{@Q67p;e9xLote6RVT0f;f&xSze!O)M)fT$-L^ORBa>;p@_5?C;K@!E z=@i0?jqdQo9;NgR+iY*!Ap1)W3hf7Y=*g_9W@Iwu8M0RS&EnHG;F;EXnzN@J(xx2hU< zV3t^>|0M%VJM`3~wRGNtEN%mdtdbNiYvgeAleaKgD#Qu8PFj{%i6bLo+%nmaY84{( zY#YlLt0)6VKS8iShLtCaF!};L%+8onW0e(S$U#JK(v;6(DLP zwU4UU<)0XREMiC^Q?-n}KqEYQrR4G8Z{_Foca={NP4zhdcx>E7e=eyLoMWRg0nUEO#Pi4yCIMF@Klc04DJJ;nv- zp>6Fj?&@3%(K?rr^)7SvE_1YRC} zF=LjwCYMt!l^gE|1dW;WnX)l(uC?20JaJ0=h8C)(_sPTpWB(J0Mg|F1fb$jlyRG|Rwqc4(+iBl-$aYzlN(MJYjwe7t>n%~jI~nKo~j1^ z%A)nIz+HXnQwOqDvqj{on%mY;8-!Y}APMlnydvY&OR^M%a&$wJ{hV}YGU#bs?I{N9 zm&C+agUVI1xcbKt9S3!65>BeKFvM_MpY(BCipaIPVNp*>0`3^MCGHAW;xINq9KBhI zAF*a7h=jgNWTz|s?lGAJpSs|fvA))@2;9#DM z4luWg7SEN-^eX-+MFBq5A{)etL(Ru{#dC?z&kU32nnN2V&t;9oqJp5i%n~W;JWrL$ zl)~c9j>Fk3Jch!G=Q5jQ=u(ODzzqLHjSzxBr|n8nypk!J0FgZ0)~*>_6Br-Y!RWAdpqOm~c_^ zJu_l_*Ok~Zcrga2yhc`XKH;-25#}q2xOoG4G~s7f_VZ)Z?hu}AE`S#ipT(E`K=EaZ zXkYPVUs3_K<*Nj+&x|OFe}^zn)~@W-8!KvL9^o;x3VE%)?Oy&^F~lcX+cZVCsmYjK zP@7UI&S=iO{uATJToo4-m!>$fdYCdeGMD1WxRi$&n9UiV zYS{iDdtUgkME1N0F4*(%*3dR>HGK8Mqz@dvsWN

9ciAsHC!%b3Go@68;W7QgOkA zsVR5?oFId~D*S(xDl9ypWE={D^e~ahe4LSfo(Fgq9yGT76`(UO^wnpYtwet-m;=<1 zKexyzQo0bQenwUVi^qlkAnk``^w#3J9+IgCVF=c@c&=~C42zIv->Q;+o{KqAJXezT zY$L_thAf^-p;lxojKyQ&j`7r>7D>9|xiU-^2-eCA$5lpJT3z&8Ow53u|DMg?_A!43 zv02taxB`?Fo8^&(IH(PXf7q<+6`M6y#%!`$*(^?0gz)V-Z7)bGB(?pR0JD{%_$Y~y z>Qc!y$K#3dQq)dlhBdIP*ubcek~ylB8gS-JS=mWz+mdc!Nf#>L04y(LC$<`qd|xbK+zwLRf!J(>H; zcZpq;SifmMuT86;i^mhwPvohmrJL5JM{}yw-&p_B>7P;^YCCNBJIibDIHt{Lk6i`* zDHW>J_5UsRKi`!5pACQY{m+KW?td6|7^VS{m+K*GMr}4nb?rIZ&9$c-R!x* zqob(r66k>y0*{=2MS=yB7(8UYM7Q`_QdzfLZY{~LmV2*UQa!03H1EBBGV;6i>fS55 zia}GSZoV!8hOs%)&+&D3>y1D$diz$H9kFVR&HbRVeb-*eFKdFiUp7kS-ZzAaAM#fI z0P{uP5V`3(WKVcfkD45%icD+hcMkezHtc1S9vffZe213Xcx6}?3@|5rGdy>3Ua zF6LbJD*dpymwgELve(p9&bX##pnKWtcCZnp888QW9W}a$Y?R~uYv`Y!63Cf1q1hv` z^^+097oYRC`=qKT#(#4Wu@64@+x=tkf4INh7yJT_LH>3j0Zc9O`yyqy>^_(=q9Aq@ zC=3Hd#v*I)P4Eu~as>|K7pN8MEaYRt7ybIF&fsaK)JDaQd&ODK@YCF~x&GbwY`wMD zpM>K>toD(<%gwXIK#pgKe@Ok%A<+b`aX38O0vswYy>^P0T$J_VkQ|rvMtfEdUcL?e zOFg}zyZ>QbdoIr^*?lvEopHRveWE(`+xS-=V_dtihY>nL4o~JT^(dPdSZ#=;?dJEn zYorwF+$ z&Ba5l4v+D5#J-_b?!VZb(4&8ScaG4Yu{hTJYH5Cz+xSK-;t3Uz@)w&*{ZBNtgu0C0 zr>&7Enl&4r#3JH}SUb&w>f42=^OoMH#v31z7MhlBK_T7P_h*4ZhJ23<-JgLr;gLt% zKI;VKODMJ^to zNkZ5rF$~3!7#H3bOFY?STf@HB)2qLJL*A<4Dx_+uu?YeNe$nFo#U zP1MFGdbIIy+1luDBx<91VUuS>%eLu6Ce+hQx#>LDyNiZ`S3SIkcz2pNM|M%s!Se3 zE~u!SsSQ}pt1$8QXTHWUopA}(&P_bKI z>&u;bzAJjloDcRJC_r9G@vvK+t;`p{SKQe$=KQ2kL5f0pj@C`) zCI?5!OW$gv7Z~Zvu*4HXpKon-{3A=lO<(%<_rUfNN&PRixBXv*9vIMG*5&QZqrLgS zZXx?R*KE!qsF`M+9Ib?hw}wS>DFgPIDb5!S)2dY z6v><&&QIqvNBPD=(i+as;4@b~!;`YekZ;{2;suE%K8nb55N3OGtZ%mhY@&3gz<6(q z3~YWMAkFD|OV%F(tRx1N8v33iG{XC){)sl_&9wS(4xVoiL(MY&5h9OOG~sa`R+*qL zbu5*K>=Ua;QLlbxaY}LPKeH+SCP6Yeqr)VverUYju6VJ&`sLY{rH;_exVD(mlh#ut zRTtVnGwwAjr~O3zW-2!qn!en+OJ;5lWJK~VPpa4_x{GBA^w}qJ$mDp?1IU^YVT!Fj z*OMTc0v7@&SMeq3+lQ~o*yY_22Z~F1XZHzZ^!6>*u^7FLy|U5UR4E`bwkS)0Cs37L`Pg;oiMFOEmP8q9X5gP~uSDhBb{D@%`$D&Im-?Z~4 zV!r=;Xl|#GE>zc0@w%n(@=%4AuMItNNulL&MtZF5WCG~JgY{X#hPSke$B?Nm%uuYNbW+@5<~ZM$c|p;si71B-q=+Ea$14Dq;;NvnTH2oLfJSP0)ODl zNe%_pze}(KueV4SU0(wemU}V?%IQl`8dKK{ksP+(i8U)`9u&%c{1ufmJC+lqlR{yt z9uGoU&ad0T$%zV8m3wl?N`;fG5~z_wxGtGBtmDx2&EX^=Ah?6br2A{cLZa81G3Q}ywmw#ZlEq2P$dm|yU)u*X|?XQ1P z@J4zyw6Qg{(?rR(62*cs48_8y{26%Pg$X~j)^&oJnDM7WvuK8o|h$TB+`r7ZQ`LZwA~|9 z55~-(Svgt8Gi@2+b?RYAYc=KfuO{-wR+FOB%T;lSmBq-+KQF;`YLP%&&eIQ5hv?^J z@mQ-yjZV|gD54lTc0ZQEV;-V zZ`{|HbDHFA5U*$QWVk-AVY1gFYr}DYvO79)RL1R**&|pxP z0`cz=GJZ{|xoyP+1x}135s=RV-19Av&jaKxlBw0{6L|k6x@m*TMyVuglJtwf)lE?a zVvBa7m4(J?KP4s^~LH3T(z1TXG+!7(% z>@cNeUi3qtFxhd&u-}?8j5$2MXKoXynej&Z|5niov%eIB_+~R;ZVUE9hJF};ViT^i zZB(hO_$5Rt#*d_hM%5pwi8VLG>bO>ZD;*H~EJ{HP@;BF$&tKW7;6pa7Fna4eEoN(w zk9?MUTFvS=cpA;XI!_Y;qsXk@IYcY}1`A!)$q7WAsj5yVOQx?xrz&dkedQh-9ii?G z9wSy|JAn!1>RYQwpgujqHAr6`*C721@mc17nChfmGD%*o;uLj&GZn?K!E>58Z?o@f z1rN?LCa+NFABN>iZKCa6kJ=^$7)w^ry<|03)b#XX^P}GIST7JILFUH@Y`37MRs0(& zuNYvAVl$rMRxr6D1X(V7>?LcDfdgf)xvjGi?VkFcmz}K+!HjUZI=IM^rOrS022}_( zZW8AZ-F(aWs}!#6J26~YsE$<(SmZ1nctY-uAHzCYCj(;d&w9{29p$Kd`MV5W&JdW* zzFuCkdTI6QbGwb=Gv-b$|8isjriWosXj561FQ^kiI zXfC;-O}z1o0i}LNSe5awZWDkgzD{Oz@fV6~7`HL%GdbAhVZ{u#VwUj;1x$SM5Fzs* ze}#hjBM$v;fIjdbSB?6A6ur(EFHM^0V1g8jp##}Zs(FRrmm4+`6#}}3K*a@r7RUPr zsr?XMm}iTtM2pO`2t2Lgs~BjpxGTxjz(3SMZtF9|2@ZRl?}!P;s)eG#fHlhH0BwY< zO`~)cuuWyN__evv3i3XrTR#Kr6OHXJ;$nLz-c27dIlEXo zHcjK;+*ZIi3KpyqB3#z42c@=R}W# zQ+Ih_1Re4E36K@TjDs&Kh7gu69rFT5ynlgOdT_H^@mA_Heu5OAg_l`_ z3FcLjCC*C`r={0*};fOS}u2iN=%_dk7gx4QkD(I;8%3TYR5bKvoB&NhmvbkInxO z02aBhdgHcX*nm}`pImHvuwWL}p2iEb!MYgEeq)X?c1$!*{0*a+=2Z4$SUk&O(T6rb zyz*<#bDgo2+d%Yy+MOY1(2F41>PiFq1nG|Ppvs`utG*{RA@l=B#mBx!Lw82rkJnQ? z!FnWMxf~;36yw;?2;&?lWGG%(!(q_q72KW*ebM+T9Z{mcsRYCi^P8Riw>y})-rjK> z_6WW2G=`I;fHh9?h{$j_)|*i0W#kIoZhZ7DE4`OM@NyqF(!b#89DR@eLG@j~=fF6_ z6~OOcYemjbx(D=vm~fQwB4rB&QC1Vc5$n~or8gAYRtwi-e99NwErW3j60;5@=fYRu z=2*)D4}RV9iwRC5;UpDiW(cQ3P)WK+#XasBPdHt|bB$k9vDlfF&l2QwqIx+!Ts+KZ z;8u?GFULdUm8wT5()r&*#Yto=rfeYgrzWnbP{MJ>!vY@}k6zD+_G6HvkflLD*tlVo zA&ErJ$A#zvC&}w@mn!)h6F+sqmX^eP>y}ldRty>o?!}Wz(sr zRyWXuUccBr*Ql0GxQuQ5Fz;I>{zUa=nTV^6`CHA2NcV6YISUtSi?zANFUW%Ocpg9I z2Jso?k6Ih#=LDjUF_+SJ*G_8TSMfIdCR%++u~cBG@@*_1uZTTYb(6ID1;cpFY!j{; z6@DkvNh@yIhF_#|wbySakXd6vtJZB>FEvl(-vj^2e-B&v(GMzr3R}lkY^OpVneNi*B~ynJzFv1Ivc<%=81 zYrOVrbv&|2|DVfC1-lB8bG85L6cCd!S@7kL9x=Ct1DMF_uoZyqN1kfuPS`I0cotvH z(=3EB#yBkB*pSex_HFGH^(zsu-uT=Q$qUi$F6eEB!x&}U%I&pa=W?xLKaey!=Chz3 zg09aIk`4GO(bNkbu<0m6ayC~bJN3@s&J<{Ydf5YdmPbFi zO;U^3uON5Lm(?^y4{r-F-s&6aN%1B^#`Fi&xFMoW7+;?uWaYM2$st?2IPn>B+!V_Z zlW*dIK_pqo5jK)Z{!=gsuT$T%3XG3|P{{mZ*efLmT&LKA2PBB8G`8U71dT33v0>GApNcCI#JYID-)krc2m~Yd{n@LyZvDGqw z=+)~fvw@IM5Qne;zo^$s%ZdQZ_nrYnFOf>CCY=2_qwyDsqWdp2YbGAdjj9q#OmvLr<9>rXrpN%1N5a=u=r%p44BWYb#gxRVda< zPPV{C`PrblM!oAioB5_&re=MElHxNn+**<8AV=Rahza(|x`f*ETLB-xGc0buz_Nsx z0}w@CKaZBhP@mZ~Wjf?#)vFa{$#!lY*V}7MyA>N^C0w5b*&iA@VwyuMzX3WCBZO(r zwtPZC?h4+;L=N$b$Tusd2hMpJAQHM8Cc=?u5XAUk>b-&h8%1s(=diQvo&J{u zSPlj*z~V=KIRqFMP5~Ih-L%%mH4m|xmKEwSZln%VfH{s35_B-CR{l#)PHJ{DB!`{^ zyH3Ex)3-82V7*alE?4s^P$noFPJ;HXVApwaIkoby@J$^#X#DfG;F5knhf zRM$28^*()K{DA&k zL)ZdW7?e!?shzShO<>tfeVO1P7FcXiSh^5FQnEfM<53n34RPdUl7`yQBVAXEb z=vvwI7ZdL0rdd_DZ6ne+Zd~B#s2rcn6MN^>Uh1 zYHjZws{QZ;MqWllN-34i9|;Mvc!y{fj_j=Ej_`KRM)K=R(0mooua{%uM_wUdMA|G} zLAoXxu%FsQIr^7MGxR@&AO3ISoc8d`IW0Fi3XJd4N_+1JTpFxX2}VI9&6TTE$%b6r_;kz*y!T%H|ADLNU>Af@)c2rfrjj$=~nr1!+6;G)(FOviQsVlK$)P0JQ)Bd`i1ih^QoqU;LtT zxt>3}?$^6V_i*=Zq_*keND!OcS94^Z!{_gO3?}QO;>^Q#g`Wx6jBeCk?s99Jdfenq zxgCU=Suco^rvx}HMxWC*HD04_I&+QQli5PNn9w*fBX$m)(XgA^rh}ttXY}nHg>rY+ z7Dp}a+eyvrDeK_&ij4;e1pl{7O-&=|gHzjdb|e$(qP}kFAGsa&J>*K!JEiB1)Y>I3 zPF$IXGTX`NpeIhfVRXH=X)k?=T$9-$W0E@PuhYIC7)+AhQ@h)&qe=Bj?@;BPnTOdX z4(Yx9;OIJS6Xt$Er*@>w0A(DRm&IM0G_VfDXXBcS9(Kj?$Isu zc%B_vJ6L+w+hYH*>b;OJy-I=*JJmYzXG@JQu z=DxDM%tPS%ZYp*LbDo!T&;!O7t?YOjOy}tw2#8doGqiG9T--oW|MlHRqBSvv8_&L5 zM>;FKk{@EziOnGPk{R16vFpslEgtptf=UbJydoeCjn&)JI4KM5-?y85g(YE;xzR|Q3zXjGz614N(}H53F|5z}5vQ_5Au zji5yh?56U#tfjs5=jB%Kt+&^Hj$_h~mC-GRcxwEt<#$}N+{Pq7CwiK>*gAPS z%l1Xt8KtaN+#NAKU)%ZCp8`||$?Rx)8GAruog(s^?DA9ps{ERGrMMGiV{70BtrK8H zL*-_!6Sy#c=ML?8rzy%J^jUHL2E*Xs4R^ z&d#$w=ZI(dYBvx|P)!oo0a_eJdWFR+`!8)vuv|@)#A5l9`ED29qGS z0KlOKNk)QH1IlBG2b5@ah;p?(}m~skCZ$+$mSj(nM%AW@FC8&-*(s;^MQF~Y2Ln6sWCzR4zICY9364>u#u)LNDP zqm~~K?&+2W)bm5Ub#@);uVmS2n>ms-I{1Pq9c}8Tnl{V-U{#<#T2hYDi!!}cp z`DdH5Su_$BEC}UD`VtWtS#`Uc3@CQ*`%DJ3r!BTR9LXE97HHWCWIJ+cjXrf_Ae}Lw|syy1}vC z-~>Re@`3Qx?$CyAaAG$&IRGihjezoGjIamI-^5zb_>G#sj3VADRB_YgK|h#r^Im5B z2u2##t!NC8n)RQV=I{sOjqWUS79u-_N9EO*n*l+7Rf5K$p49Z`gT|tAr$>$nzJ5es z)4;NiCFY{{A>~FmX3=;~oMN z>(exeMCBI}(?^Jo7?>TKh)$_BFa4_(K!z(~B_&l{anp2)SPw*j#a9(=2;XL^Sg-fe z|A96#Umi}o$$bYf$ftx@Z%&iYmfO_!TbcIKG_j)0Mb7{4EMQYgD&ulzDtKPc94ULL zNJLfD2NX9pQ*LwGfe9Y8FTo-dnkSI12>u1!G{3k)1pfe#tW+vSN-85+jYN5-Nj=C3 zTWeI1dEDjt>z^EmO)78;2Wb@To4InH8RWcEIe*UP{DyL_N>~rc2Gs5W*mH@31NO*? z$NU|8a$N3sfo}r_-Xk9al9G9ar|q%c0a#Y_5Jz#I0yVimxH8(p$z{bEVYTX^gQ9CP zbzY(wwg?6X5;Qcw}#KvZlGRMEFGDkxx@>({7juh4KD9Sh3a@5Ow=z^{Yl<(^MhztTg9VNk~7D z`nY$G7HP7sTokLkS3&xR1zECjpMo?^g16;-T4b;N2x(Z>8dj?}=lhO=xII3^Y#Le+ zh<5-b5bZpzKx_tBR<19PSAq{yj6#B26#Q9&y*bp1?I&_?@cPMREBEfXoiDn}CYLx> zpOu}kTw7n+w_Hie)t~hDsnHPmv3-%fG*ey$QoT8gB*_QWCTYb6V)iv)(~goFm-{MU zp|tT|P+Da_{mT@vKeH7yg9yIr+&CPk>m@LfsdbJsXJ&|!a>`WBh??7#SUzfQ;TbeM zDM9ghl7g__WHw9##+J~G^)b+HhPpUwZ;W+uqgdrAA}*&{2lH7WI5)5=K&5viPg`%N z0W7Ok1)T)RnsMaQKLO@){Dd_WwQXnWer<=bjW_29xE!Vs)2XSB1qBRR7Pkj_sa>RU zpgKEegRQg5u7GbGsrL@3%j(6w6M#Z~dZ~9m;w+NGu?Wos23SEsz6q#;T*1>8HgMn=U2|v<>+o`^CVDs_iVb8h?ND6gs6iu!9yPiGkvrAY} zro%LEfJI`B^5IS5((nh~t@Zcwon%wnt^6?b324e4Z$x zz`UGPVP}7CW*+C}W9B>foJH=*w9d^t_;`#$}pzTA$-M9${-CwsT?y!oVh8*v-& zH#0}H`H))szWHU~3m$NBz&D@MYT>`F0wz)2%qyIm&spzq^nQAS!`Z@=6j$;I=WiRp zfq>f-|9Adv1?GA4InykzZtA=Fhzj>zNCWBa<@UbYcy4CuaPu+EE)T(n1ayEqeFK;8 z{f*oF{Oj50J_9e)-)u}nlyD{}9aZ^i2A^DW7>t*v1#njHzk{70S_V-%u zrBY_IXgH0~G1l_WuO1tb(s>M;y?Q<9Msw zF20wMM(I@6z;-Qvg5g}+njwu*dN4JNCD^`Lbd)~61iQb8W#|sC`9s#qFlFX`Y@f-` znOAFqJYNB@>qrBdK1;GPRrNK*JPt@Bj){goe`!%K%116cw3%}_UtEMn8mIvgj-e26W9(Vr_W`!U8OYaZv)dv%q+}uO*Y;w@mFRZm(XqH@} zfnAh+t^kyKtYy-mC(yw~UfpWCfw6>6@amocoX~WH?KhxvkPw1m`@3}nR)smKcdp-b zWL7b0BNxz#Oq^@;si}8aUvHpHFFmx?u7)OBV63DC3ze6-vDTw zm5qFFD0EJ|gt;x%KepCjKXwmMgZxqVM0n2RiOGEr7xv=TI(O7Pac}WFn;!6IG_|IB z<#3OCj$))IL6Hn)U2q^G-ki5+CHd173W9l`$rFYbf-$)D4YUr(eVrbJde-7$z4Oe4 zl_Ra+fECB#5f&_n9OX}n`QzeznpUx{)(5rzIBhAe^RL#rO0&Ypl@n0oU#$tkxIa#l zY32Uan*8kVkE`G<>0ez1vdw?oVAeo}gI#AkkB6#haOym~mZz99%00`^GMNkrL!|W& zb?W?7?vh(;>~&=d-a_!Q(+DiYm0Kf9aq%aKJGDogH)kzx*fI0;=xr`18=Va^qu%s| zl5zQZB~q(IL`3epJyP;tpWeV=!=}@FcU5w5=6vh-TW+2ltaQrFVxB<{y#~mxbS;zdAtD+eg6{cdp(hiAq@891qw?5^dS*cct@N4C6XQn1 zS11+w?CWVs)Ih|K_8Jk#7!e0D;YT!8I+z)pvof)SCUN>VXK#<<_RFl?jE~F*7X>|e zltfb0$J?B zWw|}R1I0eq#aYYkCk}2f8HXg{_z#eBzvU*P|#FCem*D+Jy z*bEoV7f=i-&Gb;(2{2`B4^@o{R*j;9=kp+SNt^kGOQd^#sVr^hlDa`S&LOUgh6*{=LAz z-TYg}zYY9*n|~$9$ZI_N@(iZl>_eBw#}Zj4sJ)=DIglPM02%eTSUC7(4fa2}5_ZIWT^fUbTp(}FsSVjeJorX^VYmoeF(A=9A z0Wkyf@yYYGs|0i=70W0RzMLmkp&G}Tbv&$3pJ#q{KEAn|Wg7mF^>}jDzeD%V$9%6WtJeds8vPH%6608`Wp{X?dOT4JV`O|qAUjwN6B@H-oSvRQ4?es9*2F|GFrnQs3 zudepmpC9541V;;~h4oYG@59Jb?sD@iFNa&NAGR~%@<-PrXGyo6(fLuP?T%~b8Dw$9 zbo*LsUsXx=wSu{L{s=_z6H?1THGpy|s^#DsKzZWTy3IL!dsM9sv0>=Lugh>`Oreof zYt`(%%_QZ`xmv^TO|aDUw=V;^O|8o-sjgw_8rj>bU;63u=B5+h2K2BND<;#|$dJ0Q-CkbadLHb{`oOGgH7 zM-l6GbT3JpX14G+x1(7=lB=H*+~FEptz$r~RZEB#2Y`C_jS)o{#o*!a7nBX*73|5f*=g`8B)Fovi!R{2ac zRO!Ja#(YC*#8r;30Xcb_s#L6?g;F=n>FZ%uU7HIE-&E=w>k3*WqE5zx$tw8aR+2h~ zJN!e0Z&y@`fkfxq=k8DEG)p5=7l<@+XP!AH{IUZ`UoJYpmjgmkPbZl1>d^|))+N_U zays#H*yOBO5ivN3p38&k4sV+w!ChC2x% zO2h=hV~SN0YlMD`rgVJXeh!v271Ys(id75O1Ml&6_-vUm%nNui>&`?(A3JPtc{7_W~a$nr6F4@e+O->-fyF|-3*hqu6$XiK*@?CSr1IUjS@PKL}jl8 z8?WPf){h=z{6%V{@)9&)&>=rG5I6MY_Kh)JCxM}I!jL$7itU#fUSg3j8+HUzBK;NF zQ&Td%ya!@Q0a4L?u_BaE9h<>na@M&DP@J-WC$qYFqI3z>XMxvf0?>wP#$Ja-xuOPT zRE#7&Q_buc7>xZs1R%whKNA`h-R$NJK-R=RCd%)qT(eBn zSwo8@x$O+pe#Oth*^vG}vSH9M2Vui7=y7bg+!C$Ad+7(xa;(6mJM7$#(rW8F5Y5Q) zR}i0jiXYq7!peOg_S?S7sr9g`_`)24!e;=js>{aY-X*AyL+9Lf^R2=0v3Fs!Qj=A}>9KE@JlJjldO- zGV3Xp3qNy^`goMJWmg}+1(H~n4m@yOEQh$FH>WllzE*|jKOhm( z03@*!3}%Pv1HAMcU|MNuwlvC?DEXUti%-tpRh-^D^H_gx^@gU-{8#t&M@+SsH1BzR z#^Kekcy&8KcrHJrdC$8|Wx;#${Ndc2eOB}3_uqDU?z#aCuU_#xy}FLCD>pGkF zbWV?DhZk3G@Hp=Jl-eSam}e>Aq>(^^27fBvjYaUB5`-W9tt&iL!1%LDG6_$`T1i$9 zzM8A?hhpd!A-uwWpK(&moOqX=zhO|P0hCz2v=#!`#atZ3EVQBcYcqZ_ry>ssj2$d7 ztUBlPV1jKZKseSa1GZx=#kw)#k){u@6*|RI4XScRL=s82Ug?4!Ew=uS_L#BLGs|tf zo&1ZMHsoeJ>y}G+1{?gJ1thIBiQp3CwY-zCZC~#wV+o7-=6~2)ms|)Xy$KWw@DcCw zq*`v}!F)|=%LKebDYCDK2EL#*x-t_gkrA!%d~=U<96znKOc~ zx^A(D;#|P1P84?cwYd9Z~OL#B_rZF@V$9*Ni2~W|r1k5g+>GrC1f#U7R$goYEM-kg2%}yGdJjXEd~I&(iaIX`E^_v#V+@ znLY}Ypo+{4k91w=DuKhfX0nx|Jaclu^iii#!7#m!XK<3wctBIdkFCzn11N1BTH>WO zrwh--!7S&qazEPQDUCCf)hqmUTy~tjy12UCt6Qg5#rbH()otDtYefuL-_FbYX@H)vXSMEW zQ_g6t5N}Emyc8}_YzQw(4hvc0&G{#c{)4f_OP{Y;%Np;V0>8}>M2*}yzpFI`*J>ZZ|mV5Ux(>vTw8qU&<+1)gE!fyr_cQXm~Ff_ra zha@Ka&5b0?(hq218feRUqtJm?R`h{~+TZB<7%yBV;23H%ia&+a%`qa+PSPJG^6bG} zl|<|_&gmEyRjPJ?o-4Ow|DW)VreFokZIg9l|Bh3_)K&sXnBEXN1LnbYSP|hXjW`JrHhgdA0<>SRp47w(}d?4W@VIgjg3 z#`rkXK&G8tp7pqlnJX8N7i+k(imV?d%!-@jzahgDxkL9xeErO^d=Y4ifqC^l~0OeKr3qzdXoW=^GMFmk+K~Fmv*d9;CvRA*EdZU-t{22Ekkx~_xL$Y_+oXjxY--R^I(nK!n10?D=tp6SatcM4A zlMYzLtK^YM(cMV&7J})F9xAb&ose*O`w4HH+~~j3`|L)0U(_Y)@4S0PgJdR%jNH|L zT;r^bs;`(U2yz4cAwc5Dl_wD`za2`SwA~0SD}`l)v;z-HIkeeJpMy-QwAQFmIbe5D z=1O}v{A0lLGebXAEyDRyKAM&px|37fR9UJgTt$X{gg88=kAgZ|og9VHk*pu>KWA<| zJE*F1@*QleDtRunOk=M&(eqCX*!iCTA$9m#w5ZZ^Kcjr`ADR%tzmfx8Y0FCG+?HZ@ z*_`?Psq$Dq4$L0fwnSzHgv9u8$5yX4ZMP>m@r~CACb%*(ZNQcl#pp5;e!KiPVebgL|DmxdZwAt18i)7*bjRAnNkZ znnM8ti}eIRNviqa_@D(v3GsJpJ7AMiT5dH>4b|NYb;wRb)*a91r8OCYJVprUp#aM` zYBo@S#D@y7*Te_R)p!62tQb%Y{sC+Rx;%mlBP)BXUXQypcK3;AYoj^>yQ=<+?qc4? z4@uJ8p>k4_ZEr@hGb38xJ|=U+N9HpsALQSt_L<XD@vQ8&}LW3W0Fg8RR}7 zr!zjvzhUiz>=5;#YUtFS%($TTrhTebv9Qo8 zCeSLde!A;tpBi-sHtz^jF%RVwNR295{M6ad!R0eOYm?IuCnl<}q;>aT33qk2{X)$ft&ZM22-ve+n8Ros8Sq;F2 z%$#YioLL%pil;jR#%lJliT>5QycU^b{!X?QqhW1#we=WvSC_l)N_I8a)6`ed9eB+z z5oV|hv)k(nl28RCqSNmgE zM}|;U(m&s#IW#1pKLEu}24uW|0>_*pXU$Hk$mWkn2bpgJ5Nf~+ zEPtKUCI5`%jyBB6Q~Wmn1)puYPm3rSwU|-aD!p+gNMZe(nrbG5Dk-B8XfjOM%3NCM6r2NG=<(1+kV6^OV2C{a4Z?hCC_Z&c;@A`&xE_ z_7M%>hMesZpyWSc&mm0N()0Y%#OT6N+1P{}lRcx<+CXmG;UgZkhv{I-Hq$l*wbWg(l+1z!^?yqYbG;pw2ZvlHT|pBUWe4_4Dpo z%bO39>kw!o4NG6V>Z@_@w`;z+<~(z!Fc{w4IJ|zTfE|DS#-`e#+!5T4H}A&c zbxTsOoj5G@3Z`t^+ecTneq*g7tDjjyC3LZWySS6M)XuKd>$YF=_j<$H>dp6{UX=MA z^|ZuD*Jo192YxFO_Duc67c6@e62Nfj*9Pu3oy!yVrxi9X6_ z0UwZ0%lUkO$W+0N!KuIWP3?)G1sC!GJ+ZnIuchJ;URI~J^i6d}+`&jzk5!qgn3B|n zbCIikV@h@nPu(%E{!B^QncVkyLGukZo4*AgwkXP#2nMJHXD8MAubOo?S&LZ#9P9iR zc?TLL;&H`#s?1u%F175B>G92lR2hz9i zGWaQcAtvG0&|Vv3N(2vyN~(#{e@HORdbJ)%ZsxxE!dsAN=7DxmZ&k_;X9gMbERxsq zpQP%y-D43mSJ!t8uLq~dU%TUlPOt3;^MGgX=BJtKeaREH6*b>;pMrDW^Nt0_*bM(63+@LM7ECxIWWiVk*WEH+ZwvJ{}kApoUG`>tH&eZTSM>T!ELlI^HpyazKT1tgwRoCrQVo(#-I(j^Sl4 zvJ?SSmt}?8-;~Lc{`+f<2 zl!MNj0!QtMID*aI=AxoS+FILyta9?axpXQbD95fQc^Oox1#m#SJQG+>#w4mxMRDG7 z169ZBa#>Steq4{puvS^k6wkV@u0K#k_xL_p27-hyBulXQI%GLHXgLGnMqTyq-Ig0r zi)zb{P<6EB{t!`q;I@1tgmkxMEg;yo+~3UpJz&t5tqMZy+R0vR`Awcm(pD-H;A+d| z#+!*yigC08l~30?%5OlhdE{>UNtylR8n%`&b@o$*1tKs~yG?ddMfBsEoE;q0-JBZ~ zF@c|e6}<%RC-V+2aNW6&{nK8Z7SsUUMY+#mUj@`R=}5V9^L;4KUmu2zwPB<0AnfyD zSgpeH7w{?t)>O&sU^7Xdoe_qeWW!F-XGe!&+QmNDTsVtzF0=~WHt8RUeFc4|H^jv$ ze5Nw3stwK?{OC~>!(aNaH8gp4^B!v8B|4e(=BAo``wOo{&j04V+bG=%px&{+QEc<= z#6Ea{*!hb6o)q!7filZ&*Agn?8Tfda)6ogRA__Jq5aW4G!L{?CT4dx=KGm~rENF=| zCjQ^)P|})@q5&@{T7_rh0KRJcD-b7xBE#0NJm|@;j+x)?`nbznT(Z}y^!6ACgNvJv z)z-%qsTC3buzQEc@w+%9cQbyi1s^aGl4^}quJKm{7+%ZOAfVO0PlIf}tG1}=u+&{u zPWb&{q|H?nc`c1J8}mf5qoB@F;I&*qsJjPdBvAYCcyaD> z0Dq%f%XCWMPL-S?Rm&iva=YoHE7v?B;;gjhW$tkNL}fFsA8PCTRmmcAe5SuIs!eo|8yYrYf^~Q8yc& zp!Ajva|1T4;~6wgwt1llYy-Xa)^46oC7s;G$OLOh6)e^?m{S9?{T0*d&+t6mOfyKX1!ORQQx5p_iu$HBW! zPt({3Q-eXH4%>W>#@*DX>l)p$OM5D1Rt`kfsMYEb?GZsaPit&t<5u|y;qNo+CqBU5hn5ojOS|^C&un~MAjQYA7!KFQ;D#EB)(x|5@%9XQM=X27xKTYTJ$_6?g z9QXOlec$yx&I-Q3Wi!|u194%Seg}-4ZW=C#>5(DYlRd=rX`%f~PqepSvz6wKrtZ{! zDzvE%tv|{oP*V3O_*#PZtCB1Kjs!2ay8PY|&ZfJl<Md16)WGino)24(K580inUSN!S*tL%v4$`^Kg zP`!u!ao)F|we2R6DczZwxRZIhopd!6Dza0L)b3)8i3YFb39!_fE4!8{oMm8cjbrQ9 z0B)RadBGo7%Iy$=X<2I%$dq*mkqw#n!0~Z< z=a9b5y}?I?ZPUv8-3XsrTGK@)vB&Xq5qe3zVwv^hI7Ka9JpVpC=RoHZ^IzDnKJTzm z$@6eaRa^R9ab;_#x9AHo><_)WE2xh_j&V4EU#&y% z)abKm>j)E?5YAt#-h2*D(B}urM7$jh1rVarg8UHdF=u@hHg2C2(%r z!|>(Ds3$vr^&9Ca7Rh(|uQM!sN623K!cDZ*$87e#u)i5%H+N%qd%Cq83p&(_6Y7O` zc6&f{9@qndOc?NKv8DG;6~+T7iMc|+NDRDaKfMQA<#sN!PAAfQFJ+o8-E5W4yx_g% zOuah?xQsjM$lQD<{0w}Zyp}i!xpIE&xtvEc=`z)Pi6LFc*ykIN!&dM^wlYYS7T`Ll zu6?8?wXZdm{xa&P@&(ybD^l%TjAOq38k|0SNu7>d&m0kK=o1UgRbSQ4!r-JQ8*+&a zfn|ErUmz4_sEr8UO6^;ZL#h7q1*N-WtPZ6*)8?^c6qn(e6CG?f6MFmP{rp#gU5z&1 zmG&)Yk3lX7vu#&DL~gyq?SQRH^Wsa&scSo6t1u`2NoC96sjvevDu-w_$tZGWrp>ZC z*?C2vXd~ui>0>9pK|^7ZK-t@~s?2kLR9ayXD=kG!7I8A#Qt^VFD(_p@FN$dc(Z&Q$ zDFl||r)SQNi4TmG-rpvoD_fC)Eg&KT5Ar~tYtA$#a+tx4ntX$}u;js6eET41D=a*sro&0pUS8-hSZx6^tl#;TpVew2 zb#PGTr4>qpnNx)$1EE)jY5Il=v!s^jrDY`EI04AKUT^gS5#57@mo!*t4A;S-unnA~mJsId>Rb9yX4L7Kym=Uf%54U&R{5zHp>GY`1Yi=POCnMCV>T#dy zEZS_ve$m6>KxQM5IV+^C2hpoU^ig4i*+G{|p|;?kvvh(=i+4$p*>+7>T8=K~{FTFO zWsL;ZhP;333}s`2ViPX5J8z@Be^W?e5p`_3`q?BNP(ET)<6M2}he+r-Tg79UX6#YT z&;H-5d8X1hKsDd@bz9Bd1g(ZNv-9e(;Pd&;)&E04=Jhb5dxvLX|K$@6u+zM|mpZv3 ziYQHpvxNJoC4C~G+76)&fPsYG*d00*b9uePeHgr_9JmOODpsHUfF2y4g%Gs@!YJX9 z-YOpT@!G<;#l;ixED_dKD4l2|BfbzpL`)5`C8=p-%N6$oCV^~+kWS1DKsgoNq8neg zWv55`9EPBYN|q=`jtg&mt(NgFE~Z*H*!haiv$ar(}-Q#5X#pe8!dLh+WKLC7Brc0w3se+L*pGA7X$xQ@s;N*4*7ghz(e6E%st& z8fCNRZpY*@D?!VUXs}N40i-E< zCJYl9aNj-_T56~P35NbS#betT(~h|#L&SyK!yAMShvtK`wC`iI!N5V!+u(NXa6!-f z?}c9pi?aNPhpL>4OX!owT$LviqX<=krGx^0qJSPiKFI$u<>EvU8GXX#xrhhab|w<1 zc0O5qdDeygqZ8^=TerW^TvlEkC4} zM1GY}Cy|qY+^l#0GN4NT_6WvJ%Sz-YH}!Z*brA@GKhKqbtUOkk(*Ue24ps={Fhw)> ze!g$no-8+qgs~+6NaSaN#%5w~O7&aO3}w<40N#f(8Q}W6x#KGxikKn`f|(ghg>&Et z6+eL^Kx3Vy<0cJeFHGh{?JZOeIMo$w0bBf7+-#&%yw6gFwJpfQ-+C+T0zQ z?gk|SYE>XeMD+)#)cGs%ca5tzd2A^v46{-K&y)lcmXcblJsz`Vv@85Hj%R7-Fkv+h z6wZ;`oJBInMYYnjTEU~Fojmk6*}L00 z23TNy7}5$*PYX?HvdAT+}0kJ zY5!w>X8$ElY-$fDUup1*uxK-ZDhvEFvl;W>sX`S$tVW2I08(4DN2ghnr$C-M)yAZRJ~bUVvE7rkgG__IM||qu}T=@&3`%+s&6p$+)AK%>HV;t*8{nFzWx%+H09_Q zht=)19HEk&%nxMiTi1b=H`bzD%^=2GZlXw0$da-&w-r*KUP!&`VvnUv`1wG+_g--j8x=U`FVZwMSiGTOJ>l`xF$`3#WY)Z_Okt!u^06VTSOWi zym*d-(2r^3fr!xE$5Y%qo^GH?k*0`;f8~H;E}(|e&jL2;N*ggCEWS& zh4=XKh|vAD-6TCP5|YQHT1%R?KZu)2MVm`RYORX5pH}d_NieRXe<4oHK*Anqx zg-uhf_fo`5-$em3jPA0L>I3b!>Ain#zx_7B{j=nN zMUigcp+9rQCTr&Cor1RV$o3yx+{ql9g5+nGs5ig)*wPZT>(rh@nofVTc=p}~_?8?n z`?98+zHt*bM6n(fxwWwE6!-ZfQhWMx1JPZFJazYao#TR!*U#S#II;{t+|cUUQgWhv zID;Q$S_mgod$8vZh2xqVvMk!{q#_-hTA(>$D!kYgs3Q|=rXUV0)rBHbPjX;I6l#X` zB-pKp)_!Em=oAsY0_kOYy1GJCHFKd3kTNm%JJibUxgUZ&&*We4c zL9rIae%+gIo@#kBvj=ayH1j>015>(uwSdR=ws_M?j}~u#IuevMdEuq8qM`@9@2@P{ z+`O_Rf2Ox|>tR9Mt!0-olkvc#eY^#27Ax7Wc}>KBCXd>nDK@|q%c94np?S}6;~0xa z%puoM`42)QZ5OSxl0HAmc(K%+#MS7!;l{2kwlV}RM|o)|-2XhDb2s9RnOc1qdb}>Y zUxL8_9BCGoldgxHubLz*m}Zd(1%p_rew(6G+!5xEkVYwIz7|`9QRN^&yP1VF(MIGT zYQb5>+m^T4UyJa%2*nfeEDyP~5}_I;Z)EStPg`5=n1p(?a&~23dmo<5?1=l=L4PK zPiKyvre03{lVo;e*Co2m=N?st_gfv5r~YMZqSpF}9n?c?m-P@^>2L6N7C+-W#5VNu z5PNP3@?|~5Hl{XM53$#ZtZ&$Dc?jh$jd5lkH|7J)_D0)|X}W83w&~i#L;eUHHt9!PxNXv_fP*G&=Z3XB zmAi-^*m9%v0o-bdo-Ab+sN{}tsKxImr=DCU?C-wNcTpF$X* z(QgJe_XP8G)}8maxe?>R@XgxY?7y>JQBtQ5bQ|5{&6jsreOuWoo#HIb>|+UO?Q!NZ z7f12wU@kPbK!U6Ge+F_U_U_L?jq({wr5F37Lu2?C@58I5{3sHYAW{M2fT|ap(Ktxa zTvxq$nGRRxplj{fz_Q(Bp1QqfXVNrPoCvx8F*H!R{c1e(HCy9S{jWt)9aKJ3P%i@R z$9l$h3J$9MK46o5Q`MePu(O^qtXHe4p%Nfh>eF^c-5u8Pj`py_I+*4BKDvn_VmZ@x zo#O1aoX49NU3C8Ru&Zp+vl0@pGJiE*mvl%ly1%=h z#BSA^7P_j>Y+vYunw zt$tb1pOe_a{3Qplq6_=gMPnghujQNcF!{qEF=ns%>~D=~e-rlfBH7auahtI7UksgS z)CGHb%t7txGYfn9oB!hM>6ttOdpZLcWNy9!Y`d)607RAegxhy;ql$AsOP*?~L%a)x z$8>?~R1oZ@V{+FIa$(L;c5MUUY=xcle5-h1Nl2Xa=WiNkuDd1FbqcjJTCD)V@|CPE zDz4E^YBiuM9wN@1d8hlP&hGSUtlW-46_Y^)s%D-`^GAj9O&1$GkHVCbt15>EX4n+UL$=s9;3G%6iPGfDe8{;-sPF}S5tn0~S}*k|BIDcTY;V=L-J z+fn8Lc#EC6DbMjd_^G`(+5Z^;10aTbQzUS&#~k z&UU((yqFvc`U)p8cnW(u89HJ;#ak|7u#bGFMbv(0Rh${j>qgB3TPPO&?T>f{)3d(< z3^cTv4Q%E62LL%-wlvGqTx88rtfLZ&Zp|)q1!mV6kl>;@ZYy-Mv!kZ)*0juvg*=Pd*M&_Z>z} zaHtHUn!z!d*9*qSPXTEPaWezJa$+7p!5(`0ZTk2P{Fw0sJIi1UkPO210ahN$^*N2K zmK~ISH2+V%%)wI%-<=qI_r#fGpw%3GNPChNuC=U$f1R%d{5u5f1M%-W*F$??5&p^H z>}MZ*6C7vJTwra31Db>Rqsbt!3!VWsO=LYTw_3q$gX4P{gsXBe;AMUSSu@vw<@oRg zAdxR#{PhgVROU~M1ZBBV18kj?7mCY;LZ-a7oL&n@T6N`4;>UFTsZbY32RJ5An5~N< z7cwf#>^<5*A~O|@52!LTmJul9FW9Cet1k#`B`^stN=BLrm7@pf*6R3=A&S_46;dA) z(L*N(gGE_I0%>c#2YTU&AQZ12evA#QR(qDv1are;tCuyqb)-2uEZCU8b?b1h!s#jzlf1VF$#$U&yzVuRrAf$R-1w>)nU*>?w>;vLLaM5KE^B2&8BAr;#38AQ`0+W*92c zY}vNB6kSP3v6Y0^OU4%VmKa-b13Fj*(V56jQaXA}6cW`#kvxLy-6f6ma|Ei6B#D-5 zoutx3A{yuUH8r=R}=j6g#ePqUP^Oa3jg+=ls_&`ji(b|SOk_gvO>wu&JU;HfP&|VgM z06xZ!U8he{zve_x(5aDNo&GFd&7u5Q9oJvqvrc~x-?L8tHyV&#r+){)uG7Eq=dP}O z7DM-2pfB)ij48)^1P;P8wP4$DEZJij+p)!l-MZbDqmDZ3qyrW{LI8#R>6fj1Mw)4o z4w_BswvL>z$_{j*`w|cRnTf2CVRWwt&Ndxcx#lTFRBq0Fj0{7F!fDc>jtHB)Q@^%d z1hNhxr`pJEnU%QR>$4EueM(faYr5L@Xm#bnH*L*D{BM{MD!}4shnUkUyTn z>obJ|LzE5dkJ(FJYS}>UH9rGJs*A%y)&Z~}F!u#LHz$Xiw>Dr1guUmvVnka@E7erB zRNVFIR*;f*8v}e)pd)pQJ z_W+<;OCw&}vkwSlhsaRJAHblX5>~;1P{C`R=({DZ(!^h?temo_aHSL;Q%kG+4d(X@ zx~xW73!uoBHOcefLjSg{T(se5r$vMDcZ&N`kILNjkx7AQrQ=5c)MCosx54$@;^$<- z;HN!LY^LHFE728cXe?IP%U#tonoEha`F_!1sV8>P8oim5!|3x}^dAe+>Yz>6i^12W zL_@VEgv;fZa2L%}RTU_rptdStJ)m^38Zn@hhyDQ7ECUbYRze1=n)d6OF*4NYg03pi zA7G)6o|PEct479W_pOd>q3;$Of!pqK7$roa6eMn zdl&`B_9l`htwLe|N{NSuNh-+tz@JWUrU>i&6E)v@fjVH2cq`9fQuf<`B=UgR!#`X7 z3-n}9@}IEXckzR4&CCYQb{fXuaF?kK{S1Xm(ZrYl6gL7;6@@h}gz4R(w{?Tly1}rP zxIv(aP8aOzG5Pj!B?Ul5%emeq8cW=zNtPvZwTjm#w9g042Nn zgF)-{Y>a@S942m|+U(_GDqQ+3$`vTr$}U>5?cQU}*}CR;P$zYiN>khs<`^!HdylW4 zy(>#%!9Mv>7e_Kx7o*6_K#gZcT`av_#WOa!TWBr$E2Ns3n=8SzlL8!XvP~jGcZ(`V zE(#mchhhfCXE+luB{JUJxG$prn%8nYs8pzq+P0~0W5eP?+eq}m`TKqlAbBk}DT5XM zM$UNLR*w!T9cQBZqIxag1qba}r6FvY=6{|G^w2zjR7YtwD*|3io}MhnN&ZD=qsRqXf26FC)TPf)@jc(QA$))((ZEuI->k>&>~uIyrOqSI>xY`;oObq>qo0KK@`G z{DK}k!4d&K(8;>LI;Is;Yg0n(S|O^6Uk9LowlC1pG`AjNOI2e}E#!_2W;@2izj)zf z2F?Z{EcGqUzKEKXlA+yyi)S!7bRS^uKS1$!=KE&rF6N*&lyZ4C=4Y$EQ{Bn-oS9sv zUXJ1@%Ffhf>JuWShHtFNIvSvQufMbDRZFm1BgCFWs3rD10Q7~GJ2(HszKHv&7#fWN znQd!%49@Z@&IYp_JrVTL`}c%qV{63hhvHiIhxo@7F-XxSoe1Ix`7MP=O|oE?4;2|qYqADp8Pw(vpz z%jWI1h2%d5w8?J(u*v5Eo*X3X_)}mHGRwQMp9`@c3bFqn>@$U33$~fhs}sI?Kq~MN zrM7%kn!nTFby@`D?;AwI0DFzYw}8 zxgZ_bDowHfD8Aca>i#uuf#-)jg9V;n0-AgHvFuz35YS;eReN`nQeLHcYY-aIF_C-= zFIJa-Ro}?MX3KdNcL54nqeNoK^Tu}_D@HM+VC~bhA(pV`=pP|O0ccs-3TCt2jd}YzyF*th_&|n6N(S)_in>I zO{mT6$1b{;;r_KS`VJRu4RT663Se_7(Ls^w0nIt#cSGHG{08Fz%h4ml z=+gk0!_-8ZM!ub@NUTX-nFcZRoK{TU0I<^_7t!9`3Yt^n*40e1z>I{1fUY?l3Yb?P zvC~F+&&CD^Rv1?%2z@*b*drNF%Q9M?c!}%^BV0NcebT}ez)WeXA3>YTW5}EPMZ%?E z9d%cR)Qt$K`!QwwwA9sn0(HM+tnR1_CLA5%`%cCh z0D3ysKZ^fu;8-6tuz$qF@Bi)}GqH~&(@yP(u>pOUz9I^yIur8)?`94ogff|`MCcDt z^y`ml6lXH4HFHxuW zbYd)zDaBdWDI(@m)Ec-w+VaF521F(zgT!p#y^paTl%^mX0eMz3TFDyOS;d2r=%GKr zRtu0l*O)7N8SIK?xDaGNImo_Kz1Ke)E4;;bg|WgGUZkrpJ`#b}SYciw1_(`Y9%L*h ziK21~mI>sK;Xr?Zc96nw#azVz8?nMNX(c!yTqBr$mF<+;F^#3aq^r1~zr_zUE_T+B zgzFY`_x+@?nFQgX@ln?@!T+{h;?^gzJeRDd_<1=5B)lG#4Fzw=@qTxppZ zs1Zfz?-ND9aT3c^b!;vm5!ba=0;#&B%L-%6{H5knWwR2_hdD5oQJ!Y^ity9zK>D;r zpR%AxkKEyi!NdsdLR7hiR#+smS990%6ZVVF9Na4E57IY!>EA0hFbBU6Y`#UN<8$8w z+&7u^@aEvjJgC?pnY6fAWs{i=7$)P*d8W@lO5%RS21%rV&9*jC(k$>zz@S^%1!!%c z7XWOJ^%j7=lK074L^XFS9|Xd+R5H&U;ah%%2oD`EIndD4RyL!)Vp4MTHQAenbiG02 zZ{-Ue*!G&l3yx2HLbB!!U70N{9@s9q(hPMS6WA;$4>5SD|FYg@E`eTXX-3P~j4vr< z{1vkZiUO{!1hiaR2w=JPJAh?p7GV%h6W1;+IWX5^y(yibYI2!5uDumBY5< zY*q2Vl_AluX%vg21&FS-1QT-8uPP8dwOd;LMHwAbZojVBKw7>4Y*s!cX&DK4AckLY zZ7+tuM0w43_-4vfT@{`IvZor9bMj9=o3Yp#sFfvCfm3^JJ*><2j}ClpH2nwT_*hUP zqV}zZFNP(;&EPI*>MmA}j1OL{KPWaR*1wCycb-(SehPS?V%;>>7OQf5L8{a79=Sa^ zAHnzLe5^#BcHw~c-p9K?uh`&t_unha+ijMQ2)qd}kf7OsW)eSEdTs?+Hc-;@0McV6 zYbZfZJl3=I4=fad4?Sh|-1K!fcft?{cq)7%qAFLcpXq1tHKeWo#tzSBil zNZ;CM`7@c%htZQXqlWRE*qM78N84^G=_H4PmDfvK z(F~;IAuvrlPE+G^{|VTg#H;@>iQgzTNJ7fqq-+x35jYbtsPzn>Y2?Rp?@oYa13-Cl zy>!MQOo*8;bR$m^@+Bd1y^yVl6d{GVjrbFple>{Cg?wa)e43EYR>~DZ{*{oov6L8) z5fSoM-Yps10hXO1~9n_mXL-~ks0eDgW27XI5RU=rQ@7yjAs z^$thxr#Cp9E$p}a(Bb@T1Nabdo8te@zpcPLZ$4+5#ofFO_=pPkT}T7z?)?}%o}0NT zck?mLE)T(n1ayEqeM1Quy~)2VnAHzPS|hNhl^u}=5wN@qja!}?Hr1PL3|isf6U=mV zEvW-drVi5!`U9L8fZpN-u{3(3Vnv&YdW&B;KfOS`<&dT~cdW-&6B-X;kg`;RHDS>f zveHM(0gQPkvRe>Uc5%eNmG?eP=l4=5>B9pjQezT zkM4N?DKzb(2;0s!ax)`X_#B^m4-hpg^0k5E_AnDKt(_bNU56_juf527gFdJC{Nq-o zcMzSoui>Tvr&;lYi1pkdNBm>MB4~aE1C!Z}+>_c7F^=?truhv(Gn^mWG_M0#Rt^nMwyJ6VMILqo zyOC>ze0+#}F2MfEc=zK$TAqvUrHnU+(VYN%-AfrS52K%V(Y=)MzlG6{09a-GGvV1O z8?>=Fps5?yC8U#Y;%7M#80F#A!Dfd>(iS+k8pUTvvt+AG7i)igBod;8YoBS5ut$hWN- zP&QJS)Xy!tP9eE=%=mHKF;6*ao;nkZOvUWIaR6`5Lf&l9A5Lk>j}F)O{mvy{I_~l3 zaf{gIzu1;P;u|Z4%}Ld(cf8T|_95R~aijP6f}@l3>j;~@w`P~FFD~=bqzm=m$-e;s{n|y*J%1V+aGdZZG_}e08 z=VL(&ID*j`Ll)9oX(e++r0XKLemlb5LpLCEie0vin^k;c`@2m5`M7zEM_>VU0GbE+ zv2$ok0F+hJ_wx@zqvkWCT^E{#L9nCXHr{M|&Hzjb%hFw++Ri$NFU#eRuu|2^ndOWCgibHCOlb%l1)kqVzM^kOl=4#JtY2lsgZR*Wv0n3PoHD{_-H`cHh}y&^GO9?$mDhY&Vj3^|8wy()KoM;I72sOg0gDs@$rPdG3h>+e_Q@Z{1Qy;Q%tQ6{JL$b_O)fnO>ilg} zPHde21eLsdq^*?vYyNI?)AMS%K~>v_llPbsM&`@m%ODm~2V~gBb!WVKZ&SbO>!aSc zWpP#Sz4g4z_0jBAk?K9(91NVIOg}yw*~TtanpI^ zB||&rZw#0+((cr|g7U;NSGikx8SeW-qW)^?y*PiiQe3LyO*yr(b_F#a9bs$S%0@g) z2i)3-&%$kRizWK%RWs?igUQ4HSMBBDML~OM1Nfx&ayK|Zd-)!qZ7<&huP-G2P>-;j#@EA?HLxiglzzBI#Oah#JlB3ituy6v`Osf{Qt z%?^2(0ITWK^v}dqZ@lgN%=lRLn#dS4aJDjtWJbiYu`>UfSf3FQT1ULz+{BYRx;~vSr;LMd8R>y7j*e=;vC3DQP5~btoM?-&UR|WU7-3_S} zNXKr+{oSIGw+oBg{nxAaPX8I7N0}~=H-Rlh%l4)(&RuZu4VCiI^hxyL`fb z1!k4Gd92SiHp^~)Zx|%)mI@+EmyuAwxL7ki;*lsoq@p zo>g2NmOY3~6Olem*Sl?I+opJp%T@5d54A#V`|qQLQqt6z??)G+kmP%4?F4|o0GIr;39$#9TM*xt^sXT&QE&!CF!pU&T0kV^wLP=d#JU^bVTZv(Hwx_DGyh z&^PYw{ScB!0s+M`$$o9;q#LeZ>6FZsOL{7q z9{L4+8pV%+<J7)t+|7-)BF%} zenhR6bJ3D)Qn#J4mltCpK}-k75}`bXIt@59>R+k$OP6}o(71nPnGCCkz{owuk5!h1 ze5U^>^BI3vYFBZ#=CG!|_Z~Jknm=4?HOm=DOA%Zm(r=Blv%if@9s+v#VZwbt+#kcN#zSQAgw5V zv8E_lM?jyR0q18&N3bH-r*`(4@rzVjqfavshe$6=2@ff?+2*Z|W&isv5&uhIV3$VyV$Ksg$}~Sj3k@7Sz6V^;ymrL;XEra{ zgH(U9P(WBFbf3BrNdo2j_2DX?YYO(ar#$-WIFT`PRV*{1G;@2@-!i_dk_DBrFV=Ux z$WQ^vqH`a{R0GWbS@h;=GLoL-67$x7Nev*he+7_*-!#bI8WMn;cSwLa*JckRB7R^0 z>PY?q>+n5JzVo^rE7mio&#Gm&Y;P~>gC|N030r0L6M(SXR^Bzf*zTA3S4NsP<=1+)90w9tszt_u-FHWzSd5*U@=fC1T{&cl*H;7iQ$^DVC zEkYoJQdGW61B~Wg78h41PPqi%%j9L=;+u<89VK+IZ(QyzZf)MRW%|W7X1KTbyrKRp zsW&fgd!ui^zc=sdoIcD(T;nZ1Oc7fz&kx6%CzZ-~-Iuqvw{7X$?`cOw`db0d7fbk_^oKU$YwdGI{+O{0sZ*?K=QsQPmjjVL}X7(Fh7z=IYu-X4zM465# z+DHj<{?n5g8q>$BW+;<}9y(q(K5%DtWS_QNNvgGvW(F_kbP(_Hwb_Z$V*j<`?cSVK zB&LG_|C?v>bo1VS2Kqk_KuglOtEHq_sx(b)Kiim4U_~?*N)w&z4}g!Qw5u|^uOm-L z)dV7kp(p4Qf^);~Xx_yj^xyf;uS$52Bl4ta4Jq&Ob!a88!ZO z(iSxyDWw>VecImbF2+zZ*^WF?f9ks8TDt5wmU7H|ZU#BL?b>r`?iLC>-+#ICg~FBYxMv|Rw^K^oP$S7v-s0o3Gm6tM%$)8mUhD7R zqW8zwRc}lFHunzcS(NkqmqR3PZiY;HB6=-{lN2eQZXc{q-40!r36GQn(%6d|>G$RN z8Ux>dzIp2@m(b#pw|k3cNH~!}c*qrCi`O*o-ZFiLB4zn;)`ZRY$l?AD#8JIZ4wcd) zg&Pl?!dJUfV1N$kJyXCQ;@)Sv<48cM%l1~EDsJ1_x1ZyMm%d*FtBD;5`KP^*IViX* zw;g1gE=mEgC=*kHheLMr?#}6@mM9KVpW-b(RwerL<@v8j;M)Ei>-T(61zvgpDdijg z&&k|ilc{_GJ*HkDwe`@pH~Y42J-XlXg#tdwn#JsP+XUaA{ibb#Zyz>$otoh6wYCjz z^Ec#v0@goFhI5raIT`1B7oRYmY>c7IdbvxV4 zDaAXV-zj5Yo_Z~^=W4#{7n=^tkAs>Is$b+Z$_`Pr@A-64CIWj=mxqYd%983=n_gE+ z_){N+=^(KBdGDUh#QLkzD{-HRjNRPfB$Yvzh2p`#Uao~`wV+wu4YCwcHdf)UkbP2; z{c>@-b>^}DtJQ0pI`h5Hvs+P8^ZJa#tDo`eUL<~ferV0RO~(YU$qRlKXEv zGk*g++FtSM_RwclKj+oGQqwv8=b2e#>$~kO(wGNHc97-|v4#p&FLNU17l$3E zzdI<}w@*j6n3ia(Zr`IdB9p9cF$HRu$3zn-yJH4 zbPb8*|JC)k{q3Tt5j2}f>Et_ZFHjKW-zaidqX7_}` zP0{@L0wpq}LrRjh`3r)Xi{X*{`H-SbnPtJ3%tPo5l+pr5;WJ&B6*Z@mQfgIy*A|PG z(-wyj(pU#%mT*iF0_F^uasE29aU|LHttm;K$o%YCtj1U4M5|+^>Qe0yf7_(ojKg7v z3#tr)l1%ahK_>@6-$ii-L5BxH%y#cPeO#FT*fRT_El`Bbv@UaKW@Hs}xKmTr@P8*g zFa1v~y-krffZa9T0Osd$96ZX4e<|)A)ekv{XGT|GP3X$FAp;N$4$l{eDgqqfdrT3s zZ}K80h^k+`cf#OX&*Q?cL;dlw_S(V4+3^v-B(M1&n?*rn(y}&l+7jxIh~zH^ExkD@ z)T+$U{*_g5wU$O$i|^rr!~>#j;KIawp623PM5udVh1JDUH||0^$m4e33RX=yV9h&f zBK~@~58)=W-V)ou@2Ethy{xE})C%O-?V|x_xIzW8EO%aoEp&Y$bK>5BSmJ-d8!vq$ zDTe&Xz`dMVg-2m?{B$U#QP26b9 zJdt1gr|2c?5ZsXz6kFdGSG#n_CdOKnjnZ_)@G#CQaHFsr;!NuK z<047bm!**U(mWBf_m!TB{z>u&DRLX zoz9PhsRn*pVLCKlnK=$&V(=D8>@P{3H+>38;g)NuL=t;Yf2=x;!C>EwU3s}d=68Q?RnxaAzJ9T53!(3UMaj5me zmAdqYgLBl?F@hZh_)e`RT+GtE+NA%7y|;mnvbYxiH_1X4Sl9)l293JfMT25Z1TB%E z0YZonV0kfsB4Py^BO<~sQbi2zuH@liEmqpv*0xx+wbr(@wFuN|LNE!a2->SC*2b6W ztc%xx)Sw{y`<{88Coh0jd++`K@9*>Z1$Jhhd7m?9&YU?jbH**e3P_xMqpYC4h{s_; zoOxr@Lg5+)lB(){T*}A(tEN<&jv`?nf8da?X%H~;QkJi`>Ld1j)SuZ5*DJZ5ILzf< z^{C_VG>+)<9DU!_ukLlcACY)vc|z}c$=gJg0X6Mp@ybsx30k{tW%*hnb+WlcKU#ZB zUv&kEwB)K92a+pQifxO|r&(SWgQMkDxva(5ATxHX8Z#B~U>_USv)r0THOG_=8&e+X zYff|<6U+JHjqccX>6&t{F|jm?KDW5yvxy&Y<}g)>#iC9uF-CZeF(n$2L414m3y+8% zJQBWx2YMrm%!#4Gx|L%>a)}lpt1QX>U_D?o$!it|dAw+%M@>IXo+0u@DpzMJ{zZ4ulO<$RGxDj#nnl@CiiqtKYNPpOWWvYvTl3s1n_p zE4!C!z8%zAWprxB5?TqEZFKpT=Sa3FZR2>v7=&{$qf`zaR za{a?qwOSa6)|3-4TV}YkBp@a;+$-$?9S@|em4K(509yLir-$K6HlF#DO}A|h-!pT( zC70WHQJ-f^HW&P%!1=CPY5F(UEcoR)cK9EEIn=j#__sEF$NEMd+81Gld9&NhG$*@_ zdSt#AtB=_Sg0*3am2E8MBu1EC3;&f`F!gB71K578tA=?TN+Eq?mgkzGJfnpmcgsU1 za=TRI79PIkRTg$F?|(&d4z>#sH@f~p(}mHtypAd_hfos#`{fNfy1bGvEN|+6wY(=^ zKB|2+UCRTQZfhVo?G-LL0P$UG6)h(!q{$vEvHkiII3Sj92fiUSRhN_3u<;SeAO6OM zpB}HGi75yR8!*S@RrjqD5T|d+O^3WuWRq_i#X;15NuOxJXJcuwhn#2ha^T!swYDBK zYeTy+bc;@RGe$h{HVgg;j~@A^=?;GEa)(bf%k!!;s=ogK`7X@Wa%3;Tqa*<=V&p7R z^?*>ELVPRgM@~V4P2_m**L;LvF{WrweVZ3RcZjO@mv6gl=|CY0~2Qv+K(0(vtR8IR_ z%H3PjZc@VmYqF~bHZGOi}lq;SD z7D!|@{YZxp+FCCHKp~^%rRH~pJp*h+cF*5Y>RRy$-!wJ73O<@Yf6TRV1F;j}<~b%Rgz$0WwN)zV?`bsI*x0r(&Qei8t` zn7$N%S0u)HRIYGYBW<5c#HS4SqzY`GeDM*omJ$q*R40kgSpW)Q{taH=hAf$dBWu;u z)Lr-ZUvb1gFjA40WF=V{Edbi>09wCG_9XxvNTKY>0rcb6#FZHehO2{={){dt;@>lab zbv-LX4b|m1G*sU=uL(Y|x>bf?MmWSc49j!Y-pzrzrLO9eRsLd2f&;=L^;UGz{PO^o+Ld_-D8*awjc;) zdG#XW1bLD))w@dxQoWC;o;l0=1!(vCgfTnW%lh@r-^hj5U&TJCts zFNd&QQ0jFnQ9&1!x)#AH4?K2$X!A%ll(!dK_oz6YaO@+s_H{bmjvcT`KLB{-hgw!$ zvJIZ_T)L%dJ}y=JcYB=y_IO*F$KzY#;gG0e zJ~WA%gd=L5U3Fm5X*_-rKO^jY^fvT(^@-l*cZEHPaej3oNN0{JIflo1o^`0k;J0wJ z^Ef5&ID^L@%j1*^62s$^Dmfr(cZTM1bO=07snUuqEbd41I64F#r&O(gEZS)_k0T)t zk5j7d{r{H73F{{@x*O`Gf1Qd_W~Ru`zXh@Wgk~rUL8H&b-q5`G$9Db=f5IVrujL%*RN!pL^bbK7e13S zZd}YcLq74Y8lv?WdetAU(zCOQ?6r~6uYR|ZiY?ZfIkw>ZoEZ~Q0+ZiYn=x&6sOyZ` z!b{P|%$Q#?_b%kkW{0|xw>x$2o#BaM3v=9Y`JaF<{+0k|+%fzQA!o~28g~r;LrAqA zWnRe4sQ?)jaV0J@UxU}9PVn)l_y>lHd|=*o9OlR4P@40qomq&dc|MoAn{q#j`LS}Jp>wx~;J@a7!qVx&|3rlU zx!vM_rsMfJ{Le!Kb>U8;U7x#-M~Tpt|A|R%n*VteS3Cb>m$es6{Sy2S)%zFx&$k@R z`x0!o3-Y196Lt6>9Gd@eJnqHudHl~o)~>UHyeM7M7rtOQoRHrY)wyaN6zPJxOLxtOp~#Nhl)7M0KUX`MFvI> zdJwz6vBC!DM>u5ac^=!IdRi#Eg7y8e`C&5vv_7no&2*an&t{GoJTN;J#-wp4#P zoHvSj2BsP5>!hQ7ph!uMmX6XI4%Vo1_1UqZ~ zz6lhn0kFi{Ak(nyyjV}{5_Gx8*vEG)xXudb6hr1*_3#CtC;E4AvrXQgO@PFcK^d3{ z^t5(twU}LKz)WSaP!>^;2J5 z=#)!Nw8~E`Ja=1PBFpEi#rn$St2U;k_lcOU0%7YUEEXI}7@m@xdKF{wUjk(Ng#c+F zUr$vua~escT9oAvzAVOxX{m^`NU|dNwtprJRBc z*c$ZgkV~zQfU`ZZn;d{i$991f#vX(%L(k*WRVnHmLZS4e;^it7+hk7{Fh-cu4@T79WdD4t-U)p zE832(h(`pl*3;C|Yo801m{#jAU?++O5KWT@rlgBN5wU1`7^lt>sI9rJM7)O5OW{VY zU1sso4np3O;Z6$F?~hqLtF~5SnlC1~&|jiI@rTq^-LeeYE<~5aiyo+wa^ehU@U4-qvHXNSY z|tQ50PM*rWS2#9bUl zYpFhC&|PhAkGTPtRDLn>i~@KT_l>2l#uAVJkC}GU0p#OUepN-VXKi^e-xD-$o>AUI zu2cBprvM6p3fq!C=|PLQa<$tR|EXJ(%k|Q7=)gl*0A``cd}azZ0+kA(E9?_p&FGZD zidTqKVo${qd%DFuT*Dlog7FJ4YkGExM0QuVtw_)dEc z6~T&0Qzny9?v(bFo^D||sO2dphp6OG5uDCostE78VD$-*OslC zN*hXpatNTJc53i~M9$@xC#Jr1faozPe&j(&UX8fM9x$&w%wY^6TZDSB%#rMN;TFiy zCz5oqWIa@}3Z;HYkiOgvPhm?Sn{gs+8wxj}1=aaRVS zTjkP`r{)v7V~TVS?F6PC_a*9lVl;jG`x;hIqehL%L?C+j1z=Zi@iR zj0I)UZL3aoVD<)4oT9!A**{Lrbx~`MTU35$=qr3nC-D25|;{>%MeUGEN#LyC-q}o#kfkG!d_*h3H_>1dKi;# zq2f@d*f+U7WXANjZ^NGY7Eg}`J|$vuCUP%LD`!JxhBDDYIia~8_4q^27zrGz zZtNVmoDabY8*@O2_}8c}&lu#WQo^9$LQth@Q>>`&noqML*9zX>2bIVELe6RmSQECm zE43DJOVsACBBeBCVU)Mu=GhAG4C*6;!230IUH0DINMdgm!X9Qg_&m z63IrWAGgB>Ea8m(K7?^%oBf#^C3G(dlp*d%pN@U&ucCY`2o*f0# zyX-Yv^hji}R}xidlllj*N~J2mQu&gQ5+~%(9N9@-*eT>}CuASzf>ODiLcC5$_J<&W z{oYZ-Vmi%Q_uzFu**hBW*WuQf59c4fr=>+iS}hPUn!C+7yztv>ru6 zL11SD_50L5E*-LLR#(BnK`RJ`#vHGtv7If z`>i@jWVW+5NTKh6JVwJRH){%%UxPBj!{}~+ zIur@7&USG0)*PPaSW9U1Rxj~F_#0RHxuS~~xB7B1v1D4bo<>P`FJu zALKIi80uo>mAHkP%Sx(dWtsIDti%eCU0jqTrcUt5{=70NLNC$R;Xr1tuZI^IW!~r= zZfd@js2~Yff?mSKPEu2ehddn#7=Q>rncPK?^FDQ%r>H5Mt=4erJhdJfLLl;J@&jfJ z0Xf)`8{JYeMZNoqo)`-27?gR?n_RYs>!hI##7y2zb`0GL*r0NiS_m-o$+`D%ag~~v z%YQ_KrYwPY<0#J0jq*y3RDFBQzer5YA}^Gf-F3_|VwUNc#$qoAj81_$?dN*}4rLzb z<5zc*s7hElp^RlG1FeFT&X+#?0)} zrqb;48e(EsV2K?Po5q(IQ?r*@gGQ#D?67thX!m^W&e!fa+AZP?eYd1N6eB)!FN`Cu#4)(V8yxmH6%!)*hs;Fel_h>kl(3 z7G?fEQ@_r`m9uc48o5(eK%C7$)0NSrk(MrI>5^kC&((uxWtm3~S4W>E1~Y{pi<8gL z;E=WJ<%Go&is=E~5=$sS~HPRQl#Xj!fd`d^TqNg%g#`dlmhDOP%4 zJR3BVDku+mAce?H%1yJ#^%}e(vn+=U0U#{~=V%l8<*}p>%Wi6}TKobk!f3Xj)t|+% zTN*zJTAsSnZk}%1BY)LR1Kzpz`0;0k%Tv?;EO;(?h)p3moq!kPf%P;6g;Y-pa`NWo zPdzU_B?SU1e`chg08?flsaB3EM#H)a@v{QNO7MD@nz1ok(&W8CnEtg&?uMx)QFGbGw(D z_XsWn{uN@!dCUEBG8ByYy>)z-tJceO53-GX9|C_lzk8}~->Ns$X}gGisS=1v?Kvd1 ze5hYWIF}uLVI%dC=h39eQ{R6T7+>P}$zhf}wdFPZ&UXAx(|*fe$4?-n(+Y(0)Q{c( zW6;EFld$+sDlEO9^2`2Fr8;sW)2TMKI1~3le7MZ{j@%a(7J+#xvrEm8274k>Gq*at z+pd}RlbX3zzEd;pCpB}cclOvd(|%Gjw{lT4XV%`d^C4#7fz++)FfR4@(;A1En*9$u z0mZn~kJ|$($F`884^$y3d1(!@*;h7{0XxXidRN`f; zb?ve4$HivAP-Cbq6{?-?K?szog+Sh*$bcHVXNr&SiJV~Vgsgc+Wd;``qW1Mhn)b(; znz7SL+nRWp(7q48ap~{gJFt0M+tURW(`Lad4?0y~JkR*eHE%=H9uV-Sy36>;XhbPg z9#3?BS{+c=Tq3P@o42`(+Kk&gzB~5=A#@U;@I~P=du8kkiRRfrg64hq?m)lRT4O#$aX#GTu{yTO&GDK6rW3rkoTI{3dYz>gMR(y&<=gM! zu?Q0uN_0M@D%5y_D8y?o)n@XkiZHaspa~L4iOK#%mR=Ofsc$_S=$RVtHn{J(n6t{( zH8o>j;fv=XKuo=bc9&1p33q9j9;?q~&X%vP&t={tnvXuNK9^j>hTr(!kQgx`9a9JXzr~!3$8* ztJ~XM^u|Q4V!z7Z2Es8KT?%Em+PY)X{s-)PY=3oQs=92c-YOGg_GvF)i)%P zu#pww;|-#U!I0Z2&sC#*b8*dt^ka<{1u+hw4ho>$ zK}}rsr8A>`xQ5fI^~vtR%ebiTt*O~o2P|RqGc=2tsv53=bZ&jpTl1!`W?KuPMt$%y zQV?TK2<%2 z-dKHE0wds?v0U)ZVF5JObsb;-SHg3XR{COX?){hGx#pYg@QmZ^1kbg6s+%!1Jnxdg z&w*!We1Gn%;rp(i3sF7_-#h2`&R5HC#qsj%(%;ZU=$5E@i+Ix)hty4nqz0WJxeyo} zjhR!0Fv`Z(F_baC6J_+Mk=F`k^r%a)ZGt!+rzVJJOPCPEVd6t(;HIXDU2szn^b70z zyWbr(lKw08{qAh5zN@h9`u+r`uI~~Fllq$C^M&=*2aIwU&4c7Fw@4>mbdhF$FrPWd zZG1ZA3MJb;Os=f2P{_DI7!{eHdaxAH%0Pc9@u7pPkF+vSS+2vZOyf?KpEaKMSh6s~ zCJWx+EyL7y?jEOy1f{lr!1lHQ5o61s5;|$EkKE1E8NTZ>N~_|da{|9 zpYf%ZVQ8ekN5ZIq-1fMT=pE`oMbg$ix-~~%uJ2F|I=g{s_HPIDG@EKcKi#C;+qptb zdb-k|6?;XH6usSxCR)%dm(2wTr#S_ZuWMS#W z1qch!u~;L;&a;Y5UYtc19ONf@UL}m8s4L4)#Dc|SW9vTRgajY5)hkb**m}>Wsp18i zkKh7(w*VqMt?*pT>j#ywz-)(?Ku`60``XuW0cBy2Z&!e11n=P&Sk9i`&f zOR#ThkxW{2#67)BEE`?odrn)Y-Ai!abWxplf4ChtnQ5iy+JC1NM--HwINOS|3q9no zS#dr@*|`*~6`1p8#~u``FTuX)qJ=u{p1%{hYDy_7E4-K0nurcj(^O~egT~;e>jKOPR<^2 zo5tAJ1wVZoP8nIypmm>rG&uISlyQ0F{kEM&^dP%Ck~UJp=+e6xa9ssiO`~*v#wcN% z3P4eL_b?WsGn4OOn7o-pCSX7TXf-7HHT*Qb7@t(1QB?=FB%g=bbOEvFCu=a9ZepTI`0_2 z{M5TJbbwlbzX-|Kph~#qB8!U_^Ll6Z_@FL3AyY3!)oDbYTuodmQ z2c@~j6m*c!hQB0!E-KTS$dJ~Rw`;>B1Faa`(!pnpbQ@zmteomuIla16=nk55IR*dO z1aU)*wrbDKE~37d7+v)ddIKK-0eqjaxZKvOV=Sw|_q3QQ73HuWC zyN|$Cl-0HfAwBKG4*Gph$EyA~^c#L$6K^ItTZQZG96M!Q)>R)62O^#lp!0T6Ls6Tr ztW8iwmgWwstdjCS%6N9sZNshxsbp+rjfYRk^j1y^sb5#o3UEbGW~3*hb-3=pk)FuO zW==4{+@@|I0Z8KE8})g)=q`FSvI-A(XRJx(kcr$!_IAb>hxq_&UQ-V)5lnFqb?jLmBIBnHAu z(XD<4t9ZyHB(h1VKCeB1>D6+)BQGSxK`vK^nEC=or;taw7_A-$fF5#4j1k$8*LlSQ z$xldCv$O_m(DzPHc&y>`|2^ViJ>nr<&~-l3zz6mLfxWtb#XA7hb6VjxCbC>T@#r}% z&vv4JYO2pWqSNagl55ekk@xiT9TJU>$syw$2!ADV;b3KYYA_&3K!1a=Wnhh{xAdpK z!P!Jk%{c+*6T#gyMi+#V#?*;W@H{dXOxF4sQ(27}Sq=_^+j*&X9Q5rzR?t_|w+{W% z`KvNyKQzUFLEbz{uum@LiRuQ9zb`K1`1_Fw*75hD0-B-h**q)}%H776=oYupb5)t2 zEz8*N@l0MMRr$7iea0s8tGR2;AoCVjfI2kQK5gN@!sROCHmaG0q;jJ%#v8p&HY9H#g|#7ht7Lz?4aq-SXP^tO z(_?s2dmZo8;uIkSi$c1ptJ=36e6e1-O1@Z@D4WR)|AW!)RgWQ)Oua^LpwfM_-Ryfh74s0Im6mTx{#XY72)CBrtSr|%%e8pP zhH~rTF%UxE!xl-tktCmr0S*V#_f@H7W=7$Q#FCc~`q(-yd&ahfyQlia zUJUnfcC)-{L6g=iEZbOt$Y|xOuo{24w3!>IXKSI$`T7RxIb9$sBjo1N&(g_vDE63; zX@r0?c_8ZTrpH{$Cb`vesU(mOU-icfdw*P7Ran>RTR%fE1#6QC|1r*{TA zc6eH4=Vp`>-sN7#)dhN2XAOZq$-U2d~3IwO3i`KpUo@f5EMk* zE#2AcMX!;3y20mIcl@ujI-m_H6Ry z{n?vFd42wIdA|Iqz#)HTaG|g7Re8R?u=WG3!>{P_vPw5c6|>lrjWl^ck?pNY>8yMikY~x64x@V-Dn%clx!>WvK-X4}#3G1eU8Y*FS3tzxr@8!mEjiF9ZndEa4Cp$(b>}SAa2L6o{?sRig6o~n*|BYeTOiXB*Ae22%bsnr zo7LZ|gEf5Vu3Xwt0lPw0Wm9Jm{6+D|+Cm$y1>m;SUdqVTD8%-6xsCzmfL?Nn3HDn1 zYh3sqKVbbyiI|R!V9|n;;lU#(cK7I&i#J^Pq<{qMTk6HcYvm zriUDSjG>((o%Av**-@!~;5hWQ*K?ZQT0xrL1|(CNt^;aE-Vu36P&!%uk{obEZ?qbNE^u;|sXtiJ4?04s(%=i9mwggHKhw zgmW$|W>+l>o*6?%zJuDwIB4F8tu~%*<)|33|AOS5b`B)3LA_k=kh~XhNp1c@+O8yT zdI!n-wPb7!D~IGw$c6fU4!!%9OzfPl%;hwj&9B;|uF~(&xkbRxqH`1c$y@l)_%#x9 zYVZ=@6Q#k)(1p_AShxZ?e9?)-UC3uA5_i@-8wnvD4r&tJ#M*h3G7Dul(w!}=0W}WAo&@t8POeELZTFrnoE!|09BqSqHf2aMU(7{L4$-^- zz$QNgp9;6>ZCef7jPn%7RR5iHx*szqpS3BS7E-o^lO>R{ST6lzDK<@dA%6gTrh4N{i?a2>!>F&7!_HsC z;a_%^X6O!%a;Vz@T-K52zq!dhONLa_DC@}aVoxInpIg&ezPq0#5LJy$WArs4f92)Vp2=_KznsC?Q=rZnQYFT;_Qxb=?t)mv_OJNo< z?U=%Ho&6Lw?wK!`zxtfS`~_lCiYqw_5@J&ZYanT5)(l2xG+AS4MEe+$0ozxPAsMxd zAuu5$`2_GkrpnI@0g^J`jFJV-DINT{`t{Z?sNaGUS3Ve5cQ}?Z??Fb0eZg^>ktfvC9oRG9!p}{EnPTMlk6l`Y{RLe9 zwuxDVA87ig`Z>+Eyzcm`t9Yi>!B0{eaaYURRMwR8xaD)d=70%Ws}~D}@*Fj2%9X!% zqA5DPby^{v3`(x=&|#1uOs?E8{O>Q1ez+&8L~+ zvui$OrGFzSkrp*JjVYE`NM}y6MMnJ)8TH}OmyiFDfl93RJByBjYA}L5J(?olP_GnO zm~lF#iQFhx%Z<*E5hU1Cej&koBB!QCcEJq^I$sANoB=m&;mkNW$s9m9!%5~HAg7#U zwz$2z$Kmc6cRYbI5LtqgV1h`FBmttLpXdbE;q`#}4hb~aYiO9}0%~#KGc~vr6ZmV5 z-W5UNQ(&ic&y3Z5a*6JrvvgeXsR+WS5QlE;J58oC*c$B(KY}+I^qnTN+0-Cu`c9N7 zPABO*O*n{&GBhpTWun)}c7#bXAE{db0pg?397H~|sGcfXE#e)`-_Fuua_~0+ZosQ4 zB1kGhe_L;3kp7dEe!i{UW{`9_y)2vl5^qk+gC%lOyh?K1Twv)RnlGLN4w1;}8^6|7 z=s4>;omlFD?>eHbjr$KVahkbMK6~litxa6nMxlJA8g!vP zDM|-v(c1^(q;EQ%)>hK)TiUbGTH~6nNNcFWW*M(lkKj_1+aq;I_iClYqT>WKQ%4nW z0y?%EpOg0)s>t&T-)H#c9~dZI-)HzM!`1e3-eWkT0A7nFQc48?Ct=Rl#HTJ|7I(b=eHkx}RBsHXCew1%^JihMC=M17bW$OD6AT5)W zx3{N!7jCuF9>*l7=u%yD%HP|oQnAI`vS zmXzohGJLTAMJf(GvY*Nj9$)hm^n)?B z#GG7?wEP@>{^6>MqL)^MhA!?KdogmNZr_Xwc{3yBi6La&3KnS35po|jSF@xZOpb@? z=PhPqBIIOoAWsrNTPN_w!OLZNTF^X`#AA$4QkO|(%*mzJlNtfxppb%cJq+{y;5wS4 zl8A-arnSCs5SV;f+9~(-kR9)1j`XOvVS7^D*Qi531FO3LNtiu=WPHS{RI$H+iT_Q2 zy0x5bhzqRxSAcdUMW6aM0Ifl>7mc<^fq;g<5@V7DvomykHNe_ZCpq{eaec8iq_3X? zO5=^rz)Vc!+QD()89zV{sh;!J(6-rv1Uk2a$J=rHBZC#(ivL06FLICTU-!VbyvO!H z52s)4q_Gm0zCRB8@K~ z$voe}=6?{hLs&q)0a;F)7uHR{j{{sFhKK{W;=T^cESG~#GZ_(PiCh`sU5VxO#BP`X zGL^))@!7zOet+a_RLAC<69yf%&1i2g0?ia>_t}&O)*!erpK}03l{w21*ff=C z&QTt;kUd36^ zVp7>}{xQS4uL4wf#>Lrh3`EWluJK!&^#-G}@7S5%%S}kxcMPbJkAC64<1egz$LDy0 z-P(7w_Z%HAl?!_9Tx#1UYeUmwYm>jScaBQ9lgKor^;U%83|$x5D0?Cfhi5$cO_W2m zHv6L9WIwD6Z=&}Z_c-C3I@k`qsko&*Kwrc@L08=3a1tNi>J61o#2vmIeH8J41GvoijG8jf23N~+Yx2qED^`)h?8~1iZ1OF;Cv0>I5>Vx zV0Qx7XG9N?337(rsY%Dgc;{=MrR@bIkHvF*$nO6Q9V5-J?)U{Xn}%^c^-xCmPu8tp zG+OV8#9Nka|e=>2HeL*wewVTlf9E zC~RKthFv%(;r{hq z=;OX#;|2J|JgU!$%`H@a`{FSfI~I-Q-OZvMzLERlA1|Fq@pk?REsQ>hCeng#wHgg`=hB&?u)+VjnON&FS)ty!G-GM;P;h=9ThL;Xs+p z%(330S65x_UmP&qLH!orSa0KKe+CB+Qzu(0JW?Z#YIo{FeAvn8MKt4FVf#~GGkfw7 z*s9Sk{S3$ewQ-Pr0rz$4=I^#dbMCdPZz ziXXDX_ydJFKnF>0T1Pq9EYbe?s*dV@>0Vl#Z#TOZ$1z~m zy|fOFNsS{|kHXnFqFYO3n5v6$+c3HOc*#3@>8SD2TcfTX7@#f-gJR0)ETI(o%H_fw z^J?WX~-RHd&5`Jy5fi*Pv4zCCqxH7eMUSrsq^}l!{{?keqvYKnF`UXic zu-<5Hd$0ceZZ~Y1<9lLlzwnw;{8k)ExBRo4@rLh-)jh;#o-uV$#yq29P*&o`!?*k? zdT7qFuWgb7jNNT-T8RfXuqS=0L^fWUXOs@giav9M8K^XRsK*`sYZ?j?5#Ie8Zc zb&*%24Xt&>-ZcUY9_k+N^-ZfQ{Mba}6L0jg@g~M>F+yULh*2O$Kn(T^d5N`?yq6;$ zJJBC7fTM!0dWHVJo{REowoI#?I^>QC^Vn(od+HRTcgSaJwimRAHE>W))eK)jO%@MG z#D>)1XnR8|yr>LSXI8!Wb87$V)1>zP#N5NPu5Q>YQH*+ZcKZTc`d>OeU7#{J^u~1E zvGx{v79xV^(eT;}0Q3JUjR~j!MVi!EV?w9)UVFUucD@fT_sh*5khc;cner=_3*Dko zK~p=Kjera$GG^mV?sv}-Sa-Q$-Z?+f&+wJ zj`B19TgrFQsZxH?mnnbEhb0~5ujqf=_7{MzyxGR`jBIml@LTd(y20Mm4I)C8oZL3p z^8vfW_u63hlRkH|4fdS%Kh$8?JHe`Fmtv!PwOXZGxo;}(^vRt(KN$t=f}Mi8>?T87 z7P2APseIX7mSj10`MG2haLUi~_tnj|HkViNoMA_|)8DlBe-Pzr{?_S1!aiNf7PPbG z%c;hWqRJfK%D=&DCaTkjYI_>$%$>gYKk(qJ#gJflY$ES_z}%G>@*iSlyy3g^O#(Lw zUux`ZLt9FUPZsuf9>7*p&#;#!lWK!*8f#K$ zpIMn>mT|JuZ!GXThbx!o8qZJ*;i;$ct~b48z~cB~q6{xFBq8;Q{^JPRBA3NoT$MSg z)BIC%X0zoR{-@C}@KF5K$Onmvi`?drAX(&*WiAO$?wGGiz6KK6DL!Hz$sH?2HkHPu z5Z*w^Md4MwIlrDeasKGrG8G5A8~YPs(|zVA(PGmTKG~e??^OPXGk1x1q%DzS8XWv2 z`aC0NhcSPL)B#Q{kKGeL2T4cJzzI2AxdS%CKz>jnK=ot?P|!o}O6U9HT6TyyG95l2 zzC9=U?h*C=X*Q(OI8rAe4-WSQ8tO$pH4FA0j_B5@njhE{+Kw3aLYh()!=;|TS?Hr& z*I6e4qa@%R33$9cz|}xNUkS*;rG9*DfcinTmIQRf3`)$KotTV;LF(Qbkp<9_AfqfF zuTqA~paYbJT_F1s*hB2$Eyt3DnikV)iB~SiGXQmkWVPA*tWFdXPXc9c$)%!(2qoM1 z=h6RKhqrm*utjcP><2_ipjgp5oNr|MHcap*R@?!oIpgG8sb4NbDeEjZ3Qj4;&1o7x zJZ6a~Hj#ClN5%3Gqb(H?NewPbdFZo11%++lU=_8P-;?677h;K>BX*o^;pKhc&^BZ> z(w|wyhihZO8UlQG4L*Uh0$k(2M5;EDdSu;lnemDSw9t;~Q>zv}4GyVg77@sz zq+C=S`&_Q4*xr_+ccS_%`h7-0@_OoG-j;zpD^Hh%Y;}QgsBO>34eTLaAr+koy1aeF zSKEURqy+Pgm(}l1m9>c{q#nZovWMe!0&uMh$yeG;q!~6&R!I)bp0D)V`CwXw#)ZlztzBK$zpiq@?Paes>Q;wd$jp7x? z%oT28Ed?IAxII*JVYsil`4kp3;b5sCMHDxgE^BZ5oxAC#jE@+kx%vuL{FBd+`z(T5 zQmrcWJ@h$CB~ssM9N|wSC*#liN^IHHR+Em$4426Ll4ZWwdq}QTHo0pW>BhlkN&IDe zlNH1)P7Bz>1B*ZN#d0h_d;E2Jcz8v$O#?YH=Znt*VYJ@dC`a7lL-`_PK8<825~bRf z_G7#>>zr`Q=Ad-8U~d1!q>R{}r6(D?is~b+sc#B<-$5^<^_ew?{(eiZqAkAC?L>GX zHKOLw2a#O+J3M$q(U$PJHJAKs$$;cPdef6zj2*tx{fP+~OckX&Y7Vt7@=`!iy>Ik( zx!*_@s{xECmhf=Wqnu@!jS1F~(vUhA{oHh??%n;Wm<A5XnC9XIm3>^F>kZ#-)MxDEr6p)>r}p?ZoSs-N?L`Y=Q6uf09Bs5)*yJm1 z!|QLU%d8e!-{HbC6dLE(T=ugiUrT;MKNdA{b*}V<#Ld#E(tXmxo>p^5@0+)V4DOe< zNqzo<*x2%cEU=5CNPSHzY zzwfT6NLW*R^3%S%AIFvP%0N*I6rk#&FEgK%gEAU?wdVm-sM~ewC5{Z}F|!i~3)9Nv zFG!|^^BQ$tBV~Y8a&k7GVq9uhhSs#14-p9@ytx?%$v6$b6159w`p(G|+659hxf#vS;ruDaO9;qA>gPcRjzQ}2kmSnN4zO4Tb_8fl&?qu)b{iu+ z#tbiePTasLubm|Nv)n|?pJ$Bd%W>neL>yE*6#)p0T6yh=6IN9O#|n>ESX&VsocuM% z&uEaR&Ze-y-=?tPi-gkGw`3;rN}`SKPW16o{nXiEH7duJoK43eKyNq@c?$wOpKx_H zeju8@T|E@HIuWDVBM|P3%YM#BU`*+>-~04@_Aia@>{;-|+Y*dHU+hpfB3v%dx8cc7 z2LAd9H(%^c37Mgvar3RL<3l|T`!OZ?7o0_G0BdcM;o?=jXsS0cMfBynW80Pvp*Xj1 z!zac|$=^y-;f%=H55Pj;g{SBRU-WEpNPf_RK&JBKaC#g-c#P)Y8AbcU6{PU{Hr&c4 zO(r?}qwihj+t6C`Nz0;<(hz0_zE2scgWkTZ{=M!!{$BG*>!P7d$DZ&K--e!2{z&5` z6sxChmRN;pW51Qd;-~80?Vjq(0%D7kZgF${yE1RcTazzs$ zM&7yNJ<;`DpX|Bf1=s6%Z*%RosFv|UavSlS3<|eJ-_4dh$iDvFem!>dXj_5ItFJ5a zs5DhWEIFR6y3U8@LgCa)Ig&li6kKr&+XD*bt@0Ebh){^lWa0|<@@?>2G2gl@`eruK>fh|wV^@zID~@RR^eNm{ z_+s*6YF7WI*RFvtemcxHqsxt!2U;&Rl^gEdRLa;=|9)m-X1`41WzGLE#?(o$n3{N> zAj~SLJsV$*>2$5Jf8@M)dY&PG4uBP!g41&lmjVcwz(?v?|DIoWQuKw4`Vaj@yCUO- zzYv`xE-tgbAcSS$Zpg5wUS*cB^NAvJo^oxAGHl2y*WI2^yBY>0nLw7oi$4K9X#Tn6tOylp2%1+&S z31P#08_pO*65ZJUNm&A&J&lAR$gH8zbnlJPRwrxfVQqPe`ldJtf_?NDq3~%QENH>I`*Vi!}i-(UGFuXlwgBd?OJ;jc(5oqPSH_*C>feqSYZ} z6ng}T6EnZ5yQuVNtkt>uVBxfx9aT}XDxifZa6zaqu@@8Aw zHKJ(WqK~yJ<5{Up@?8!rN_^v4U-T_;Q%EN&dFOLrWYHntozG)OArIb+=E}(-R$wW; zHuo|Q$a~)EbT}w|W?--^Qiy2$eV8>z`r<#AIx#sX<*ueW05fAh-JC6PWfrh*Fd8>| zjc@xKOZ*Av_z=y{Vdz;hDF&3wSzJzhP+)2;E`6~dQaM>?X37+|hQ%kg_iUms_8A9- zf9wAVOPI?ss0QaR_1i`=Tr6d@zSshg-aK8l1$`?g<5m-?jKm61LZ0I|iwi(weNT{_eG~okQ%-mYnF`Bc z?5}@|nRjyHW_OhN_C#~}Vf7M>px%~LILIf*o^#*e#2mneg|28s|evCwUx-SLc4de6?EOU5@lCESI>*e&_j9f-U^UxsB(>SkV_AO+a- z`fSPFy6r7fB>8%ilXw}n9po*5+!u{eu2ffmAH*$yUq`g$P7L)~ul8>Dlb`y4Z;ddS zQU~2jizV`d7_h;8)pL@-UZlQ(o2*4z;aOv|Fj55Y%*B796m^lLo{RB0ef*GA?^3Ie zg~e1ikmub(BtOk=#llXER0=p)Q z9}2tlV-rtTz~J~|r&ANSIKgOwE!qAXW7TeSX zpc6T6kh}xKIu>+}76}8E0L_pEdO*1sh`4GK+zr^JevvN%F3u}Fe?+8AIM!;PO$C5) zGZIeTFTkai&(b)}fmg;Zs~p{#NKt^Wo~giZ5q$;J!#8San6>yzSkepvgl!JYwz?)L zGZo)mB+q0ZqGrur+cL3`WVm^$m1wFh6SG9kH!YFcO1_C$u*S+Ru+bXXK}My{UOxtl zC{DgN?<7#lkUX7o3L<*bV2DIec{)pOdfa=C2FWL=#@on#yDlc6eluT#O>6z%b+W{e zoYcHeY~f!yZLJ}ngeB!U1}-9xv}#Pt%ZbQ(Luc7&H9$J&OE;$OUo~bTZ)SIh;`J_! z$ir9c-ATd54k~%SI9^e|_zp|M`}LPRDieDcZ_zgu7Y8*RisdT&K#p9$4VdB|pbG&T zIZ_p7dyyqM-h8IinzA{U1|^flXcU`Jzj>pmW568y+T*{jnx^jWXr z)YtRjjd6C|&4-(kAUPm0K_(JW(j||fB<1>dVm@UebC*le)@oa7D?N!v`;}*FWk&`` zWp%`jIs)5-6*^j-^;sG$)^VolIL%HRxueM~pyX$GtTFzn{^S8>Nv7@pR15C5+nO2i zu?Ck-HIKUfM$SaNBF&cr^emV?PMypl!N1sbE6Jyja%rh0_~WYtm{3p{r#1;$t?S?~ z5#Z>$<0oTIV$1%gC9))t6)d0P&x%k-wi>b4Y6LPCg0$J*Xe)1NnNBZF=bi&y9A}4G zE+(%dt-60cg!TiJ6XQn~T)fa_NbcM@&?N=6KaeDSo(`3~7;!o@M~4D-LfzWOYmV`P zHh$OgVjj4$Q7C*G*F%jhMa{m6y9VwWxYL;EMYWC{81YDl)ex7Y5aHUN@mYdOJPVsD zf>H&maI07wrzqRODJi-$PI)CrJSTWpY?a}lw-4sY1$K>Nkz}fWyiUF|^lem+`tA+T zK0&|84!XHm-N|>VVN>XNC?rw>S5*}*HFJhdAve`X00)9xRgX!)sP=$53CNcKB?0F; z0qx^c6lt3`xy{jfX&^(;7~_uKF53T|0DU;1#1Lr2#bH8@6gFAtfiVKr z@A=jnB#k%(<{7};w^|YD--NsI7-^4gSoL&gPRK5L#uvMfD4qC8wXz$9+l^rbN1RCN zXrP_rWYOMEQJ!J7Q})0B@htANv*OJ zF+RfJVXi&u1)>Y5Ihbq`9>I-3GR>&XhPw&NlAaI-H2e(G}<7^BG+bK+LXC-|0 zHH~-gvX1HBAajP=y+o=X)R&*!-yj!RW6kSQ=;xAb&f!lt8MNBYeb4&*v+?+zhrwblu+;ow;I zeGeYv;Kh}z<+zb~JC{$}-ZnXJ(OuQM|Zmx_0SQes^)0F?{|k_$Va#Mem9;KR7R6Yo}Whb$;Yc3j2-ny&M@{H ztwyA^@U_C`f&2Tnve3U`uXvAEY$SX%c)Y*x(7=8DKZ<^uiCXFgirC|#mdhUGbS+{g z>*M?8_}0RGJ+?jXc@T8U4zE*;&Ko-7)NZ$J_;Z1mn!uTZ|#v+4Kb91JuBH(KJ$ zmzqYuLuFk&12|smHFfphHBf8%wD{WouN5`+zv7+6116;-tr}A}x25Jm1jv-C=zKkr zuNOmZx;v1y?DT*@VW}%UAXl4yZF;rYS|I*=wYgTCdD;wUGpNmcZ4T0Afi{O|bEr0p zwOOLgQf-!NvqGC8ZBEtZbZySm=4@@w(Pou4=WBDJHpALns?BBEtkGsno3+|pt<5#s z%+qbTPrL8e<~nUYq|HaP`It7>Yx8k!Zq(+J+N{&&R&6$G^Eqwq)aGBcxm%mBYqLe0 z?`TtL)1}RPU6ZBST&B$$ZN{`&tIavuoUP5(+MKD)>DrvC&9FABv^ig!A#D!TX0bL) zv{|ana&1;qIzSxIkanXT%OtB2G-#TgKRK&!eGscdzI(Opdh zyQ18Y;i}O5J#VSa_*V@&ok9GH$l9Vh;dec3ZW*IEa2={Fo%`-6R^hRX1F3p-&4Ut%bB-Rr;R#P`g43q3ibzAi+C8Z;; zt5RS!L%lBI#@4~*yA!&@Pt2GiEfHbCtT%%7kZIT2w3EHMhU#BBLxaa#D|OQPtGAK^-E~ zosOq;;^E|Ve*tu=*+AYYT1=+N~ zza(SA;1|uti4mvTSIxSnz1~wQC6Qfl2k4|=0iG1xjIc@c*IRH)?%Jc_whg#_WJla#Ys2iNH_WIMtbdT z^5|~z(>*!okqp~w_mLESg}Ilb$(3e#aaObMi4i%8Nx4}&adf|-H9u?ru$ROA;Uk8P z^)Bj(lK-rc-eJv)ywNTB!(NWOKe&!#!seFLCwd$}6S6L>YnbyuE~C2gsRN8}j*_R` z!*+)KgX_%gsFmnLoYo8LW;LwOnAJeR(c3+)NOog4|GrXJhPsX6uX;j_7?$n}>#lB4 zpD}Rw=*cX-ALooza(%|tI^kY#CFkqe>FFk$FUypuXoK>c8~-?RcGW?ORzHyhc#%_T zT9um;)GEB%cF#Da?nqs#^nsbd#>73<#~xxE@qqy-P}0-N_g!e8ig9i zs~;%FS^?8h;tGxC-IR(=y zeMagG6GjChyh2Wq)cMxdoApA6>SdA z!rg0l;V05B9r37pA!K693^QYf4P^}?6L1K4qHmr-gqND-3D|5kj(DkF7Nq6T?is*U z)3MPW-9eJqW~Knkdw03rYdO)m2LR4Nm(IF!+S3!>E&20P6rCQ{6z&~w4EJc;`CypR zQu7j{4}{Vu1`EKV(FX@hUmQ-KDBMJ$INXKWkr=&~NFF}m8xx}s4<5gF@c6@nn}@v+ z$=)=Pyi@-8j)>Q+@7;F{yHYLwUd={t>D;zmMsF#{>cYWwB@G*azN?`s7s#Yfbdh62 z6|Y^e+m5P_gJ|Kx^ib+qc*c+5pTV?gh%3~pMH*>t_`GJE!PQ+hFk4V*XnGC0p zaZv%Ks6x7xY8dg=$X$&@t(f17iTRTnG5@qo%)czfoVWUW4{0lLpSFGy)>d3}oz7eR z@O*9krV8u+@5JxNGDo|O_*xtZaje79q-&4?1k94d)gdFkMu$F98B&jcS`Y~B47^5FgpLm#Vs!U8zx9v%ceuP0}wd9mN^x=_)^oa)uPK-WC&mF`CNZJ2v zXxn{i-I?8_k+ZInVI@2aJu#ISW-}_kgtpj2DkJidIifhLe#KBdl-{+6Qh9DvRt&vv@r^B!0nw%YESCKxIl}|p?(H8wb@-WL z z*X1Ifs#pMiOa_8#1HGbKbFBe7UbZ#r` zWVE*gWe(m}In6jt(j;!*J;nEP^P{WuMO$N{$C&0dNAEVrzeD9#?7M!!+{;-zUbG-Q zcYd#CmX6gK7mb;_AkwROdbMlDF)1UXNIRhQvb1k_9YU}0*M`sLo%nFx@P%TXI6Txn ziyb>Wv9j^Zaz*-@!-rB2Hk=LZNOiY8ZaVSh58i1e(C6B$zwU28~H^>DlD(kF)TW01*0 zOn0wEY9KT}qa&Fdx>aY+cz)o6CHtA%dKZg%;!rV98zSaK1!4{#ggI~ZiPN>!yFy#1 z;CU_3t=H1e6Up8?gz`U6Qey3PL*#>P@1}}0eC`I9+1EXEBI>a zR)Q(@Zt7O5Lt&x2g=|-~d-@G^uBMu)d<)R6Z&SmYx6N}=IHo`wYx=|?`TtLbFVgYFxO`^(Axj^_rC)In_puR;P1)T z-LA*@-OcYu{N(TTm))+t{EqO;eZ}o6;5V6HHNP0Y@A7+u-v)kL`Mu8XAU{8A%^<&v z`Ay(Ai{DayF@9_L{hZ$he%txI!S7>!-Cv~)enEcQDX#>30>4@O7V^8B-#UK3<@Y4N z?fl;0_ddT*`FUtZ9={9uh4_7w-vWNi`Q63uNBo{5-}U@LEpFEkegS?x`5pMX+w~g1 zpAvQ_zXkX$!5%`sbFeimNH2dc+OTn9d->(_E9MvCH;do?J#N=S{MPb|@te&r#BT?` z7Jl=IvmW~h`FXJe{4V5I!Y|BE{__4toru>D+r#e&Zu$G}8mHwX7*e)}bizn|mh=O=&Vwx2(*RDVC2 zW7+cI$NhMx?}Gm<(Q&@WfQ1wZ3f!?}_vBB$9XoyG2&cXXx9uAK#hzw54@KY#9=!0d?&!`I)m;F3!s3vT&8?0pG9 zRMq$Y9cEZWR5W)}o(hQz2)H3`!{UOPlHih}%)ksd2{Y5o;F6|enp#$(m6}>nUo$H; zD%)LXwak?E&63I%+nj8(Quu$)eec3!U=YRn*6;s4aOb>x@44rmbKl+HT^vSxWKV-+ zvr0zEFu`Uu8>G3${6aIQ&$ndf*c|3e8>f$UILWnt3hNCN15C?-Xn_uWp_4-ORk|`f zlL;lPf;5}OX|s-WIBX7Sp=7aI&5i^qI$F9`p~|ZSGj+`|0)1)Ld#mt$hA96VZs?q`KJ1*w^SwdD8m&#_tOnjMtRihd-r)8$Yi z2TGo8&Y45HyzQt7r8q)VTFqJU^3H+*F00ly(&$hU#__9HA{4%wd zK6abaX~~A_NQc~fOAe1wD5<2KmtryCrw22k56_Qgp8c5{ewc7&Ddv2$3t6Q)IT*VQ zekAi2V5%@h_(^6tTb26oZy%2ymy$+Qe>ojFnTlk*@S?=ovI^}e8Yp-PiVx^K;79q4 z$~V<#f(HXXD%)ec_zL=M@S}LV>F4{Pf7l28b|3TyebB$}gZ>@RQ(fmRPtf3+=_2I+ z$OnDA5Bg(1&6D%a;9i|AT6ox~BTwWM3 zL5w+>VFsVmmo7y;>_!-132t|ShT`0!gmJozIdga^ql#z&)5ARz{uv@+)^nMS*Pu6cpYkr|z1bmZAG9p*d>YJvrsl;iR&uGxjz(K)t)s91AO&cL|AgH73k z%{lRL{W6{Tw!A3hzJjQ@=zh^LoF1(Va%Tc+#f_SV68Z{;wvP&@P^nsP@O@2f}X&}LP)2QR3G&&azrD1(EBJDzzv=Q%umj1;d zEJ5STTh45U&1#E^iSDlyHZ+k1Mpq_!z9@4UeIzMCj*9fqqr+jOf;=LH zg#*O^V~Y|iK!jAL1Y|fYa(B)-+hMWJp{{}v%p7@Uhm>Qq8*?nE0962aIR8wCabDJ3 za}IArRsJH3WJAX&H{Ui7erbrC^b;~1RLNkNV6@CNr=a=GuoRf3-cm}TgI7@KfGZr# zCWI{o59(uk6kei_eX-sT<#94a*Xo&PAnQt~t z%+1AkG9kfi#Au|ZJ`H{U_M{Y2hp92Dg&KC@FWd=}A&~g5?|P8vh^D?ej>_t}XnfVD z6qfv`ZYhE;W?(8C>aqyyMR;Ge>NhKuuuKc)=^a*MzEjR;(~?uTJTnwLOTk73n-rX< z;Hwl|pkTX#oeG|--~|dEYqX9sXJ2k~B-$O98yAc%w2m#zPb|z!H`^!XxF*=gZIjs=jz zK^Vg1%!W9Yd`M%4I13<8q0lz0e9iJK#_9KMG88KMhQJJP%CrA5{Fy6#M&%9sEqj z1z_m}0$VG80CNX9AO`#*l0pYz)D~3#Uq4dre=G+kP-DvTWC$ew``4Bab=(x4uqWW7 zdNJgyt4uV$zHL}}P}Hw#PtlH|qKdNRMmdbuJhMat#7jrZY3Nbp)Ffcx1ky|ep;P>Kwwal;HDwXnqv=u z7kK%T?<=Wt9@GVjl#;_#x%<_0e@W2eJE0n?+`ag`Ea>@C-RcnMbZ=SBpVIw+!iUmP zfZAObNH!U2xHqrnL%tUpudb>z%5hvMAAhw1U?tMc%el&39dASvJ{>I!fM25%qgy^; z%;htG2@=MMF3cI{NW-NV#tcX^GwA5b9_r%>`v}GU7nEP6zmCCmF7-{&o<$`{eGzv# zWcjD{*W6>}erpM^dK?XLIb4kX>)vs4y+oLDqQD|oN^q;M&LO&U(NKP`k7kb&cYSeE z-6ZNKJl4sNx9jk$kB_MLq7!t@TQu=QH57=-$iGFCU@dAS4eF%;)J_-6kE*%9l0V5z zmFZt4zep2`MLb{3^ilI<8h{@_3(x`l0RezOKoFn_fIf9K1%v>a0h$9^073yR0j&U+ z09pgu0NMiD0onsPD9{nm32-T(GoT9~3?Koz0=faZ1Hu6jfXe_q0Fi*6fL?&!fIfgI z04Cp~`vPJBu?oZi`T_a_1^@;E1_9y$g8>PEA%LNPVSwR)5db|P5s(B(2BZK+0!9Hw z1I7SS6&MQ`2N(~y954Ye5s(JB0x$`X4#)sZ2224=1xy26378I;0muZ*1k3_t0So{m zfIb^G4oI5|2e+G2;etRBd(7Cz{JGs@$6xp#i7+9pF@J7%+N2BrqxdtXH0ICko-(a5 ze{T1*=@m4*+KVx-G1ldNPJ zDoscqnVgk2a#9vB`njral{EjahKnz+a{*29l}|}w-4M|ztW3y28fMti7dSD^MbDBv zl#}M+t0a9+aD$f8a|=58G|wF~HHAe13->z}cQ~s#zs%4Sia z+TzTz;@c^GGZlQw!9e79F)b>81x=9febns07m-3MmfPgaHp;6TOlA>wF~ZWi06k<1 z2kw9Y3)wx>Ix`)Z%oLxGoi0TMLJU1_fFpr;7$`( zg6>Z|U&cAhKehSG`6atBH`-~r2KfZVx7rDxvm$#6UNjv=H${w$v^ zzw2f*QuvyK4#4oLqI(S%QE&N@=juXpp*h-Q<~XuvbpojPysq#O@gG+41sR9h{0))$ z=3JLFY?$P*VGz3c$xgfbAx1Q}DqyqtAR4J?on97R!yJubBJ4->wzx^rn;@cnbx)}Lc%9Q!10jtaI z#o}MSP0!a|>A+BWQ_sjw^QL4^dtJ8Ex-7DL%4*t6->7MKE8zuwiC6fNBQ@zghilqH zz4(WE`P&tLTFXasMg}E*VK075<|piSukhtw^65bzbHAQls_2&n`KUc4pfW-03MoA( zF4AAxg>^hI#RwDnfS$Qw*n_|@9vH(z_~r?t-=SwEFfluUVc5gqyB%R+q!QQ_FreWx zTTSU^hXvosQE?hj&suxnOF5=9K~s!%K_c$bM-!Rn@kCa-J(;DgNMv-)foB%>`hX7W z0q8XnA!&Q`h$kH|84^|79#AIFrx0pV^#grfc^{5X>5I_+n~k1| zDGT+pF(2y+`b7^AeE@3lYn8Q6s^3-G?MW=un8Nx%k11Nlx&YVTo@ZOIIDA3YY_ri0 z<_3hN`qB;Tovv`^a3SwYge5G-0lwC^lp}6x8$z>d*WDEUVzdv$M*u1hT8wSvtBNI~ zlrcVCULB57g9S8s5-q^VMITbaQd+F7HJS09!nVL{0)u-XBLQLF{wXq_tNr7Flpmo_ zL-HF1nS=#?%8CmY&nQxAic`g~zV=#O&h=mGanu3IbdH?fZeZ`WlGqCQF1UX=anz`( ziIXOzP8ch8<5J)G3fLJdnx^`+THr<85RDtlEXDl^IH z&&+>O`U^!AoS1WUp~YcNpEMO?yg4K1=j0bUv7BTM){>a>`^8ng?}p^Zt&o|3Fwg&r z4)x}L&?iU}3iFj@4s|B-cS7&Q?nM2ivKO629|1hW;V0$(b?e>Iz?<^Eh(q0;)K%Yk z(}zI$4hV0|rvqIRhOt9JR$4;vQkTC5Upt1PHstZ0d)>;*2f zlPN=aG}n39z=Nf8Sp9FcVAP=GC=~YuTF~#rQa&?w0n9dHkcg;4o$_9Qoyhp43jw92 zXva%#P2_Gh-+%gS>=QD%9Vu1oF(+Y=ZFGwKA^RKhlspO!iavIu)siy@os4<2X{&^6 zMRgf18KFJx8;B0({UgUb8feIS9E@|(N23uq_>_WYJK+6z@#^-sYCP%8oQL7EZJsle z)+A1voSu=Dl$bm&V^U&`3ZS9weYrJ-w}*EkP8#3S29hM({Go}~1;dA8!wTMyX*k@~ z`A?7Zv%|PyieU(9kH6-a7f4-)NjV7#XgjhdPR_`hI4Uc3LdwW#BhwMUBG20l!z0yI zKEuZ_RyJGSN3#QTG%h8mPLC|CHZQPQGvzlR_YdSb0GU$$t){O^zghu~7Rc+8jsv$q zu%CdbzI=R+Jgyb^CcGo6PYuwapUj>i|6(V{q(ZAajbW(yVur;Udih_Ma!CU|=-@^{Wr%%XNyVTMolc zGLk$5691L!dF8RH-X|I|lHx((2*^#e4c`38k3izTb@N3&nPauhvks5W&!1ZmJu++h zgy|Dv2hC1M$O?}R4^K}+MWqi__$?pwAA+Ph5Dd`81^O zXtQfP61P?|!z&qu-CAf*rwtNQjrnK~;FxN~RwF*Rg508x?}+qo3cIg#B6l*B)|oI* zATLq7EW(RCRRVV^2f{94f0%@=LHNZdTa*F#Q~BHrMiQ`+pY2B1Y@XRO!F&YFI(Kkx4KyFrL+kOb?vyqMohX0ITae33Z&jSEj1;CQw;agIxa8Z3S3DXGYxl zh}(fKQh^0(n)=Y*v$|^rs&GZ+fQ8`MHgv42qCsP!KvovbdS+!~w~aLm`ym~87FCJT z_VnnXv^PiqWSbs6`bem^->%l#UYN*2=O!}4JYeXAI-- z4}dkmZs1P9Si;EjsXBbol0;TU#*MU8rLh}s0_v!L(RZ}iL`_}0{y)F@yK4TTJ*Y|^ z9z~2z?k{BkQ(2UNsVzAPL+z{*-fW#KOQh~^xG-Bj*Mi*?w5tfCAWX5)bh*KhAR!N> z@cEDTz=O(-fa+~V2yCLRGVPs|Clzf@c@|#K62>l5c|U;M`*9Rvt*&XF!-9Se&4Sa% z8gMB@4?^AtLHS)BUbtJVcC4ef8y#r4QNF53s`=03J8iS6`%&e~7&OBU2<)klyK2}* z>2x`>9kw~>mfJ0M^xsSl+K$Tyg`&SA9MNaPctGjGS^4HFlt6l*9ay~QV>YQ=z)9Y5 zT`fQj-&}ArRr}EslBd9eU6|l!GF!2iLlKxF<$HTUBkELvbyv%EbIDb59+o0S%1dkl z%U~&NJpQ5;%$N!Elovd}-GD{7V%X6QVP(KH*L4ONi1Lo0x5J&@{ls*MR~{0crN~iy zyUpeDWYbg(isYSWc#Yy+P0kn<6+5sesO#$gIL-OFG#!rVDMuFH6@e*WkkjZ$qsn#*>o&Ew)VV%lV}sZ&O+MPD#Ja!i7~~llgIO6xR3s^yvZ91$W>R3ZgN#$_-RyB>b@`u(U|!O z3a{uZi>2&|B6k5b`}dc*&&5<1k|oOan*k!ln|22B@GAeK%I*l6GW(dYL2ByW{VXm?nI%bDhkDa4u<9!Bvp-nI^#uNLWBw^ z-{a(0M}v7IHJT>$a8SaksyO~h&Na^_D}iAcD|Myt?|LtwQJ}IQAU)q~wkHb?Qh`f@Z4$%YcoVr%TS}(*&P1k6MAv9D zrMnZ^IM61ewYL@2>tv^y9^jEE8h|9;K%}94NR%6nk-XiQN=-}><^NQlTQj`l5;K1a)q9-o<-T(wJgq%Aiqi*^OeLwXdgs=n}d$kP(E zQ>TTrCz0!0vwlEVgC+-+sY~bVLfGe7Iid1X-QLTMF3nZpTWK!;NUk)thIuLc`_3X@ z8Xrzq<g zjc%NhnwUr6tLSm+112J49bd>HD|ER_LV4jV1%d7g@aD z1+qLtP;jX3B&eOV){7x_B(0v1kACHuHuoU@KDz$Hi$r#iHK({ zXh=^x;+25YfN3m6b%U4w>iQcSXlQ3GhyeV24f_68HC;vCwgP!ND?w7fQ_ttG2E?6XTd++?8@Nt`sp+#AC0vyMpPLzV)gXd{MOr1U# z&axqqf+v}C=8mK;n23vTm3}E^XO6?d6UGC+l*VPimjaK55%0JT`Q+G@99W$mSJ}|e zA(drs3|W|dk$kqtWME|V8ug3*Pt*}G`ZG22V=n(7icu_$M8qPZs?jM9g|#{h?RMUB z$Q!ebE~L4G)^#}Pdou5=a<>8;!{k_?nxbWN>kmOGFujLzVCt)!YrdJn2taz&`W{+* zZ3?4zu@p)YKXsWiRHDu$!;&})BhAlYd%Rp(Ip~0xIuDY-n-oV$RLQ*-@lZYK1}6E{ z^ZcASejp#8`atfibANli^Ch_jV%t6|M;w&bD8*<@B0$a$S(p>2{zqoE&6b~qkpZvQ z1PxB8K#TeBhuT`yb`e?%pZMkSc)u996#2ohLbh`{I?mDi&yV@>#M055trKXvPRo4* z==BF;5*1$+fNFu)Ub9;M^*A)G$M1h$|K1cp-lD3Pzz^NX5MF`EOOa&P|NS;P1$f!i z&>k%v?bFg~{R3qD|Ix2#FQ~6b-(rP54$qRx-XG6u{{gU5zeo+Gm1Gk&s{B-KgIB2r zNB7DhDz$1K`I*i~`bx?5Zje=IskS6Pg|@0h(6kdu#rc3g3jj0vtV^F)=!u>QH<2B@ z7?Q6{!O6UTg8!)%FC|Moa(nBc*l8-i@z8*H=^a;AhVe>Gj*z|{%OG-u$Rkzno#z@Q zkMKqpK5AHk@TIat(8?6{9IWr7{pRl#>_xVrSR@#-3%5#YkC(xqd&Yk?ezbSG!`S!c-e>my+@zhU0|MKf^r+@$B&ogH$ zDt)HR-{iqFQKNon->`4+ZkuR#aUE6Rv5_5zX^(XL^0_|`Rgg3XU*2?}U4{Ljqkq25 z?Gumg*>~oVd6mEZd6e5j-kpdepF{`jlgcCOiR^_|8uXSn^f)jxEf*KNx;3(x3y4PTHxU%xi>(604oLb!eE;U{J; zXf^b@N6xh7_CZtrynNtoq0hf|=2C8-xN%Ip?VI&QU!Do)_5%smMZ9*s>pgb154Zok zVgH8LkE|%}bhbaYf3c%iyN$v9PYyUcl-qB4bU?2^^Wq;(JDbAoLq@#(=CQY5Sw83N zcy52@^|w0qNcs4s>(6Fz`}$WSo;`f`oLh^}W^()T`?9YM&)@OUGiOcQ{_BTX&8Fo( z^q+Um=5zaHKfdtEt*1Zx>Eu}#w?E~sd~o~D#~%-_Sj6qC$1ckE&&pmIQL&uc(_^0N zZ>Ze!>WGS)xP9_v&#b-a`U&f&SKP+!dl&b#htK={n5$w7x378Xi>L11dkh!CZsqpd zu63O$*%Y5_IFSiap%^L~N{iazx4NzgN7- z?K_q%EPMI05qGq%JjCq*LwfgmF*NgdbmiOJ{?G#~cR`9W8I1wE7oal;`U)P*T3>o`hZt7$BH-nk-59q?FTelxc&32 z;yd=HCj98SA%) z+doU}cB^^bj?nf}HH+n?||&h0}}?%(>sqRoGn`F+Rjp($JMA3uKXv)}st%J@LiX(9J`%A>4jv$d-Hl+#LGVWNmBN|K}mu zA4riq?AlAY{rV&KUo&f5ihH#-oZF*5-l5eW@4Ej!Z69u5Q<*ZW@0PqJHIi=3YhuWR|-Fzx?&*a|@9CaW4-um<5lSi|DOZR6&Pc!r! ziYSErD%d;2F6N`Gg$0?}mOLPN;!uzDk>GCtra6BBv_)^eSYa)n(U*WJMKgWhpyj^! zSmNS#nGi0RpTZdvF>x{dV*1Anh#43&C?-B;a4a1=5f|Gpwtwt^*nzQwV&h{6$Hm0O z(is$S{o@A24U8KU7aupcUrfK)esnBF|9%7d4eU3lUwps8{bTya_K)jN2UQH{Kd}Fx z{_*_>4~Q8MJ0NaAzX5b~#lQiB2E-2-JTPWp?7+Bz{RZ|QNQYSr8W=xt@SvDMv4i3U z^&8ZG(11a7yhZ$=!SONivGH;7{o?z_4~QQaPX}HM9t;r&Bl^K$Js80T!^yQ)?rXY% zyCFdgz^#E>BA?MD5P?WfCys|UE8mmlq>%kZ(qY;<4;xc4H_9n#VF*$%4?7>RPwX~% zp4YuDh3~hUfuO|S4tIKI!aY-QPxGRmskn#2eV~edmf~J^YYL<91cFbNpjXO75$seZ zL|&nqgxe90=AniA3FIOCSMk}3XPO5Wd_Tmqn5V`g2a!IM-*WR^aV9f%Yhod!3y1M% znjFSF8(#{>JkXuux(kMQ2>ac54pZ6xP#OuSD?a(;Q<6dE=d=_%x z&0@_SuSN0Um|IvG!bc$dG8nn7!h-^JgDiw;m*qzFtwx^FjRNMDD*RdLtwW6BRN^9 zLN`UB^Q=$dWk>L(Bl75*i?9!Xo%pHto70AJ6TapzQ12&Kr=Q8PAPYzM8tK?!1m#dW zf1clZ#MT~hT8rptSG-Y8CWiLDCm)~($JyOz}TLk_kNFipeIkyjq*2B zq5odRT@UxJ2q)b4Dem6sR{?i*`e{%IDE&mZ{))Y}yj^K4Io7A~v*T4Y3jzab(<}O^ z)Dkj^I=+P>V;N*u*Y%-_dkj7d)3;%Q+WaBTjF_3IKeBto^x$h)d(XhqX*7zC&GI@x z_dRmC6nP75IYuwB43U-wVd zkJ5nNg9JlRUmEOF(mwz(`k&QRXe*oSoWEf8&G*Jkon~0I`lg~wJAd4~#kld&eMe-@ z%zFH@6$g?z6nD{j!GRn%Vb`@cJrOD9zLRL*0Sfw)TyxFy!HW*zx3*{<6n5-Ix^K{b}wE2 z=$?K1-+9mT0;Ob9~HE$7SwO!gd>)OS;9{!_kyDnj)Mo*YH zZF=Uc#Y-N4>FsxpdVc)H;auY?T)*MfzFC(=_r3q&C-)yX^4_sc`VAZV#;ggee7K_W zaOH%F(`N(*wFvFe_lJ{K+n`}1l13J-t*A`TD}3eEvNzuU;H!#CCS`TI?wIbnl%P)j z{wYf;75r+F)IOU7%JI7!VlRG_6Iez{x>=x=VwbXoIwYTKbL^ zqVv}_4bU`i(z`@w;(5cj(sL;T&9{_ZFI!$UT|9QAeP7F^1)=jJdj*Ww zxo_6F_h~z6TQp+<8V!{7LoW6U);9GE)wI;L^1q~2Yri&r9krMGch-e#uF}r&+vE3! z-`gSYG-JNo z?j3OWNO`N3H{5bp%^W#lqRBix^NA;yUw>zlK}Bn~2L=xrZp-@N=yCT%Q~rh#AT8F;uFS<9iNsyc?#t% zLykFjj&uICOK#ly;KL=QWqn7?>bB5di?lcEG<~Dp*LBv$wzyOm-lU6vZ~qis^Iq-; z1HyITy2zmZO*QVKrGuKZ4GwZ|9IVX=Y7*1dzpJ*BzeXRg8|NRX)9RW8H3`&9J#-;W z25J-hI|k}P0@G3l^=sBIFkq=6Z0XVox-Kn}n|BBd4oC^<(WJ2Hh{Rq2L;QmSt_aZh zhid)Zt7ml^6BO*;HmlpnrojQtE{P8c9@tTfiejlDJw&sVjR{KcJa}o~sNl}p(W!&9 z&4Yrk+qP^|ZedgRi#P6B-gnI#*NwjC>FWju_R{$oE(;zN9O-|_GW*D;eM4L7{km-U z{*vo{y06*Nuq&3{bc1e=e=}{9z|dO_?q7qQLDqJo+|NvH(#n0y($U)MlUlU7KCSo4 zciivw9Ooab^IKj#G(e-9?BA)s-_quNbf%Cg!OgUpx?zJmH|wKof?OEj-n8tUro_+{ zGP!q%4sr)X26dSfq8p~Yv~~MPO^bFbXy{e7pZ9|IZ}Xivw7`?rc}CJhPi*?cWC-=_ zX~m*XinmrYWaFH`SJ2XSFP1$GH+_P)j(|?^;@W|6K#!X&u@n#?_b_4_n9t% zg~lLu#h&bCPf_e3;UL-{Y7eWodPxgKJR8w(p!kcyk7U4Bw`+s1?GxNbn#p#_PgE}4m`uk`(cK-BUAgf* z6yIBeYqGLjHZ!fzqpcP-Whk1L#P2Agon8}+6R@s4m#@Pr{f|6W6MflhpcIY$1ki!2 zje$D*yU`F28%uB~TY+&to|X45h3a{-g_R2d=9Uu<_@4@bg^aa6d?_`Wz31JwLxCAz>8lOi00MJS(kRR736b zi0nn%?s`V^I}B@_BUO5zyvKPC7*M~7psw(A;NI{;L6C~M<7ZaXS zq;1t<6nc5_dkuQNMxWDfy@*;js@gA1$Q~J1CX7>*24c>ob0l z2EOEz_g+%Ea4o8Te8|gFt{!=m#pNbn@gce8I8t$Zj)XSI?JJP@1p#I6#eSr}UmDmyitfIo zcA~1jzblD(cEa3=vqm0FuE`9x>hzMU2qk~uMy~2Sqz>eRUe45YgsF#~pAq66iw}B{ zUf$%sf7xjg(-y*`xfPID`u16U!S~0 z)6nxv*iLyp{M!ga`*VbSA0E4sU4dHdCw7$4wZdY`x3<2Kz4#7X+WQraJAQGTevM9r z5-;^BsGnB^JM{@lfot>$6uL$5;{y+1f=2fb3hj9gqlpF@#ys?ogx;Tmw>lk~Y2U&GmN|KpjS28PkIGHKC zGSHRboswW`_u0epw}mKR8aE9FhMHCH{zh1+zoCZO@3*1z`E)#OPCmk`*|B8r`>N$r zdDuOWh5AMY7%j|{bSarOgbMfD;6~|J;LLI5JF{?NMIOq$vtJy)KDE#y^5bN>s+Zob z!hj9|@qjn&V4VQsAAFXBp6Zz-bUbk5Vj&%)fbL16@+kL3Rdtjd&xWVu z?;0)8v7+>hisJna)*9|)?*dHkyt#sf?7|)ul~-tie+&4NZW>@Jr^4U!q+CwRfZM@c zl*dWuKChXTA`HoJ&lB?4wHS60Kc%a>E~N379sX2D>Vdlg)3Ch{o~e%<;uY2do_x<2 zu$pJ}`$U(|j9swO=*g)#QG||yQZ~@>DS@KLQW)*cvjbB-kOHjcBc8)m?v#$@kIMB| zDBRWcR~p=Jgulqgc;rys9*NG4$dU3T)6r5IKQK$8jkfr%pu z*@BK$?_4(mpC#7@5jaunEghH5e& ze5hYJz8-!x<%O`=637P%N~G2Ko%E^pPf>V>d+}}$J7tB_kJrra<*-wmRqEwlmYK}Q z%k-W-#$@KnO=e|=WTrPIa|wz;Pv0QttHM#+GtJ8`^2Cquqq6TS&v<MdBSWN z%7L7o^qzPDsLGq~f|}&;j)%V=Dl&3F8g0;lGm?<+c^~1>0nU;Kk=6PCIUlrgpFg3B z=WZW#;$C|ZH_aW@C369`$0~Qy(-^i&$4`CGo5T(Fm<$rUsS&7)cRH=9;OW8dyze79 zyR9QM(*f$W?SiqqgL-(hqM`6C`SK3+c4uV3ktR++eyD zx*y)V&4KDC245)cGpox(>8xZ{j`C2Rg|dJ$Q4GIxfv^3m@}}I{=i^uR|7*_&l%lQf zfe0Ulq56ry7k`=*!yyE;S68|5Ri>}zUwb?h^R(R78GzMoog7mBy%_C@nxD5kb)7Gv z?gO(&l3D0Zq&xb;UVY#iqFs3{>9gTW+9#z!=Qg9 z#{I?Q27f#J^>|LZ7PRL$D_q^bu`B$G5IzRa9xwhe3V%2J%V69@uZlku^9>Y#DdaDK z{D!-eaCk&=)%TE+$7Fv!a2iZ0*;V1iJtN{wC12+!%k2re!I&XHm5QSkr9xM3?7-4z z<-XbXz|`mc9T-KB6$4X0>>(H$OVl1eSou;OLH87BC@%@9O>cKO=+Fi%-VuhZD0=S(FR9+WZ{H^2s^ao1ga^RlbK-=OeFp>nP83>P&`b#V4Aubloo5r|Ge{qibn z=mjxw!4{*X58r^R? z^Nb>?(_dA?*6_zyChw0w)$!Nv?-Kup&Ziq*l;^|Jkp^86&JBBS;1XbJv&A}3L3f)% zSF8V`-fV$zB0o1~en!Ok1Tqe~QB2tP!A^5t!v2zCrweg-OBxv+-4p)OOR^4nV5&nK zd%lo2KXKkYSl7{Ci|plVeL)H2!43oVD2y2I)Jjih&F}rS>mTq}EnX0J!3o|phey0i zzpNhT8NNz}iwxrZG^D;s`#PDgH>L7hhG)-->T)lABlA2Tek4Id^Jnn^c|K<`!qEJw zfZFL%eYqJGH(Dlxs|yz`k|Ir*RijhYscR~)@t_+GyUxQ|x3u(!-&K({4<|sO9quXO zi&pxa?pNe_X>lK34D3`s48ZF0Q3^Q+lW=gScJVWWr}KQRDB}V zeg-7%|IPdJMB0e^<%E3;(kdM3U)cRSryfO?}Q7@{jlVV)(Aa55g0N z&^e6rvd|1x-zX)$Cf7UECl~b&9yut)#vD2oT5wQZ7Fk;#{1;ikNBwU6#!FySpZD= zMbPzC$)S|LTJ3uQzX7VQ`n=)quNd)CT~H3(5BOUMLG6zk{>t+0Qz-}#`nsG(!+ z#axZB{{~+4j)eWRV%Pte!ir$j&~$bAbh1;ON9!k+AJMVpPg1XgG2usfmdjQK_or(5 zQGR<7fm_3`wc?jafiDo|ds3MDh+IA*<7&#v3ry%prh)kmbmOc1LwRh^cG0m(=_%=f z%{veI@Z*iCkKfVmHO;Q}4?+DJbKB|(eGD!zyW+~UU;}%UJts>3+UtxeaL&!ibjTMH zW#YiBe%%6QI3EWH>zIPP`Ih`Mt^cMy{luF;bW{qH;~+zN5|Yi^hMJM?1ud~ z>6R@P*7!4t{PS`xCTI8pJR)!U^I{c^l`>@2sO;g>W!cGH4HY;hjO>RLO!hz8V68=4 zxx5Ph_f`JOI;ODoFw>xmfE^#=Jt5zdegY1|jmm=QooctA;T9RIV=k53bw_n99&RbB zu&=-^2x0S8bYH_Q26SaAw}Bt)*llpjL>dZceN4xsIM`Kg1L5`}=uWG`PJ`PXxTUG+ z=EJQu!g^G68{xJabYH97o`KsAxYY&Ekluhjkaq{nEijv42#zAI?_erm+P?>VU?#y_ z1+yGx9n5x^CtzNLISO+cCiHzB3x^p9GXZ86%zT*TFt@?n3-bibL6}cqeuWA60CB*C z!yH6>df*8#vtaBnx4;y`?1I??a}eeem~UYIfC-{^3KIvD29phAg;@-<0%jA;KJYDp zNh{Z}{xA|uFwDra0`VY z7^ArD@EdJ*rO8)%VEwWkw@+yaCt^8I4m-_~@kPsJ&cGrOy7#PKT)Ne0r!|;3xkIM} z>lZi5;&8gAvgIr}A6Frb;YWkB5uDE`2OanwR!utrZ59?6TuJecH#)_>r+YP{YTUho z!+(e(eE~XK1$6a5qH`2JI?xj{Ys4ciP_80iY_5N`EyI>^O}gEjW68DTjHhcWdC0;V z6oLy@(rFPFQB21Y(^Q;(PRB}P$v)PDub6$-MnawByajxn^%?W~UUn z+-54wSJD{ixJ|r2y5<3k60zz|Gm@aKZH`HcpQZsS$#>8xFBOHTTL3s3bQA* z*TY8||(_hqxGzg{bIK z#F8Y$aFE>7T_zkF#r&CrZ+Ravxq6_>p=!Ot0 z3Zigg?Nq5Jr*f)^MySXJQ~2sGvk4dA$cOdI8aUXSa!MB9%nH0wE7IgSyj^5UUPyl+ zju{verD4Sk-osV?{C*hLit-I9g6mo+V~s>#!{wijYi4q0qm(HUj~h8@!pQOc;^dnV zyJ+Q-II7Uf?~{t@H;^T!Ou=14f+Cb5HaRa7?+Ms%LJ7sv(m@oRGJZT8=tnsZnagQ& zOl2j0lW>h1Dg#F{t?T8qP9@c*@)ecjG*O#A+cr2k#)x4hMfW@ZT%TVPdRp^+(`aZfVOEgJyAho0~l_`p!}URTfT{+zj9{=o05$C zLo!k?9~s*pYbNQQ&eilKjPD9fVp&e}?5tc%J~9#*m>F(PM{HTxl0^>K z!$?g4?pt=y9suyR=34Sldu8F0aa@R-g;5?>nL!Fm)eV!vOLg%a-Q$>*2mT6GT_o`` z4+vC%87EFj&sk>NElQVvFq|jEZvnx%J6zV>0$vOHLsENI7Dk!=gdC2xYl=sg>_trDVuL)}ebwP#5IW9ei|Lv7)m~iu`OuZ3}LcS~QEth0w^c z^4m(NW*%50J?H`;Fy-@$j15=CulVFD)dN;-X64{^L|F=)HAHb!6`O0%LYcdYQG)RL zj~VS2jHPK<9fc54@)z)^{Me{i+%M1HwiktR{e_yui-O*>+Piifxbsj=;1ym@8#RG9 z2P_P**YF>%yQ0wSSb&S4cvl0{(OBz5l`FeMRj(_RJu3ETs@_8ScvOSvqM4XWo9aw4 zXBXz>nH^~~bBs!3lmBF^Tq3ILe^judAL+0^ zWx|*GXVva1lK(yajVVBD<7qyW=BGx&(1c2V7@9vNzyHDiQs93n@P9uA5O&Yi{%m_hwSD6Te>S^gwVgc*e^lCne*5$OY!yDB346>T(1W+I zZ!CiyX)5gO4S&`aFHP8QNSiRaS#U?*9Hfp(nIyN=8Wuz^Fw?O;7pRGS%#~;#n!i9s zbHKLUgto($nv$3?f6MnDCptPEXtVOi{pp{i4=S?ipAKHwuSe*$eu+JT_TG8(9nGFF zPQW2s+a`qCM@;T&(|@9mU;5bW@$tHzp<35(3qL-4_Q8xtZr!+L`>ElDgJS!QXfpfC z_m*tfeVgmPm%e-M*X&b&zWRqBOP^W!-q$CsZIbLcg@d1N$##FgfCa3%W_p`NM;0b7 zAp0-urkUfWUllvU{M4rJg4l<@&Se3=t=kp;@!Pw5No@8<6`J-tCckk{SB?IoZGnaz zr<0TY+)s3F=T3ZNCvt&@A{ zW*+tfo#D{WWksyG;8#uip<|!P_>w#S-lWtJbz;<;=38WI)6(~MKL4xXj&C}JvfZ!G zV*xMR^J(0#54sV~tTXiahD&s?X{mHjeri@)zMY4>Jct31w!db4GFTaav1^4QCB zyL4>DcJHiUA+v_{4`;Jy3_AR8Zt>{@>-O)78|>%4>UighM;uQE>e%FxP89`LWX-zcQjPvc zTpjWL-sf*LSg!3lq$O+p`d6McJAe84(|ZFypR?cwRy?g@<&w?&De|=kJ5@YVGR$Ki zo&C9{d;yE-weWPriHtX=rnY$by*GyXrENO3a>;iu{^2)$G#fkVJJ<%Cba+%)m!sn;EB$!yPi9&WvOO7rlS+Lm6j zBJ7TqtZ)0p?IqSF=1fcyK8c)(Nnw5PJBsayIb(OTX@=9EE}zMssaW>GZ%@4Fd139I zFx@wQtXcQvy2BBBr@ogp?wOb+y~am}jM$PI=KlVkB|kj2bJ>}uy-rM+xunaFbG|&_`42k~Xo%h1dyl8Fi_|nDe@9yTe?!BnQ!7uEevT1V1;M>2P<=)-W^LRv1?DSVFJ;%l+q|bjp zQtJ7|>v~J~@|coye*38IxboV^%wwv9irz3)1*uU;%yUbk?*S?WG z@ZoRXx_#AUXTL8!(Yd zbl)efPKPaCe`aI&$xD`=N|9b)Us~yT?DzrG?_o{W_wc*=NnOQCkT=i%X?*F>mPL0x zp*z{UBDi8@<-GN0;&1ynIq|2F=&O@EqmPd4W1 z?w*I{7Bo52e8jlLDPMJGlYR)=voFFkI6*QR{ZZrL7l?2HG$jW{u9+sV@hawF`~ zCzdU0UU~A&18XwQ>|g;4ruw~E65$y{N8h!=L88x~9*f0R5w@-0ilU>fUL; zrfB+VHg2)$t0C;o(51&(|KNJ4&A7!IJz*?$`XOuUyYi;y=%$@|VSEQo(eB^h`f>a( zDej07hi<=wJ+LjP

    _W`F&IUHvLeueRuWu&F!aD&4#5Dt5i}-J5?TxfAcu6pdY7 zx^rub>4&Dg+s^N%+dHubZVNh-zWRd>;}*})n9IVCv^2ch;+{a`6`uu*y@&rGr zSxb+n-!G4cPk{9rzp`JPsY|A1t$2Rs_478bT+Md9)6yMt=IJio9$oX>x{8N(?JwCE zYS?f}TW&jjpyIw=`v-rsSEo-h2bTWkX)*kUD9x5$gP1v_(jBGA?A4E%n^m@-;rG;} zS?plv3JspFn8FT*@u##2>>E@lPv~MMk7D0kN^To}40AuTa*1cwn^*m`zs)Nz&to69 zuXyf;tq*_mN5l-jgBK=^TA z?0x9uvFV3~_Zm8}G+p<8D`{|+Cg_FA!Eeo*G47AcS6_Mh%0*8tsT{wrn}i@qi~Wk` zoj%#-uGg0Q^xd&vI%%HJjd^}FJJo#2v{QX^TRdEG|KjeY>)9J01WLy|BeG7N{A`e4 zs~LVNrcUlfFI4`qZb`diEe+$`k>B|h*-p>v`}@2fJA+01rpwu>kjjd26*Cu&)@P4% zcR$`jf7hpX?>m0%r6mxlTw0(l$~)bH_>J((ZxVCmKDITi;_jm4hoOH~a55L=vjrc4;`q=a5v{NTfwO%^o^WK_Y+xBHA zRvde8-I5J2efMnJ$NF7AC*bIxgAYzk?RREQYP(&yj%Mvk`MY*)I5q5Z7XQkRz1{s^ zIJxB2%JnbhM^EvyN59>)9IC?SCxJn(Em`^#`+wir&2M6myXT(=u6uIT-OWpz z_!+JbD%JQIZU`!EuPGU&Gpu6s^*RF@jYOTn&E_ZRiaKaKD}to%e&sD&>Mzrk_U`5m z33BJ9up3&kldD*(ZY(0G<>~BeJ8W;Ei5&SVak^!UEph7BA0%(~tApZ&h(dWl8!?(X;Gx?Q_B zempHJXjV6N-%lNuKEAb6>W1luy4>`z|Bz63$I~~k*Umg2>Yo1osPfIvmpyiL)=vBBI*-`df<*`@&jD?D5pFrK3|ftg}x0a>E+-cI4%{eLc@u_TPAVfbk~wcCQJ# zX`ZGAnF_m6z@ zN7K}k;n!|(-S6r7NZ?x!`4x>k9d3AU|E;clzyD(S>F$rOy7YR_x3}D1THNdAC9OPP zj9!|x=DGK$e{@CBK4;UOH>R+;^M?d{)Mdae*X^FPN;~MT(jI;#_n(M;f9}Iqw@wOw ze^O~%O?>H(vG4zSYR}Rre}}|I2gh!-ExxnM*MYxQcUWd)!Av?B1w?&Hq{XX#MU{-fcx zX*Yx!-(ADnpOQ)MU-HGCdlu z^HquCzxepx%b91%%n?Js_&W2=8-9G}?U%ob!t#NKy9EsXfcssRZHPEaPPc|?`+jy5 zo0l%*twjD6(V)xX}ozFp4EY^y#bEy%B^W2`$zC*2>q?CH<;T;3$UqoyRZ z@|~+n6NB6XvRSgO^pb4%p&<9v7g+~%vqH7uNo;I#NN7tw)C+Dr|$VAL&pw$`p#94bS@-%{m>W7+g|}T-Po9A?Z4~& z4JSB(G=JfqPj3I^wJVyiQ&$ZMcrrM7NzS!hajox=f)@=t?;r7fSbpCxBK%m`H>;o9 zyS2A@_}iOrWTkiC-~Q0#Pd>VBd<$ae*?H5{hn^lxKE;<-WS9StX6xnWj{D%H(qDKi zU%Yk+#u!AoecYM$tz~)kHeZ9m$TjI0%^3H$Z@q*Ix$v$7`Uk&Gvpra;@qatmvf!rS z@feS>)R7ZXb|o3EOG`|_n4Rfi+%Os@;TOPHv&oPD=HEltur!!r7>{C#fTe%4PUn&x z`l)rUguO0PN_6Mq^>6WSpw4xrLpj2_VK5`|?}A3?Tvs}f8PP#`Crtzu5=)`(!aV~`~!8akrsc2{?IuFhVmHYwHopL)9e>Z zf9NH2rncv=(zy)0OJUqFb{IWOqvC3e{)qdp(3#SYbS#1)JxNE&mz?nXTlGhL7ei+c z_>hjpFr;G|OpGrb>vKoAzg&Nk4W+^i>5z#`O>)@exzd&4CzTaUQm9$5FP6a134O{Kj{HOdI=qi z@k~0V!RYIY`=8(k85^rVy~~SQCjZWKX{`Q#r>uWPT>n=6DbK+e8k;8nM*S7t%M{r? zz*OHz7m^kVj|;8?E+o#zgn_*D-i7Yoa+knQe?I*GP5PfhcXe8ngVsRw=Squzi~i@K zyE+{_{}=SXK;3yd{M+?!jP8`T|IPY0R`>s={)jsbrZMeOef7M$jMw}8cfWt=TnyuZ z5pvOU+PUOV`-A?X=uR@I`PTKUl2gcgUf7!__))u47mp%u+Pdrr8v|43gGXI_>vgLu z4z*ij<5BYx&*14R4M;CZ(0OC{k?tOtdUaC#OB+Jx9f!BQAw24%@#ZJ&2;(aaNI$)x z6BusiqdU(_^~ojt1b<&x&|N6@#h2W{(^neM`*n-3cy6ffly+5h37*fHPedHPa6@?1 zN8^jHa7Wns(x4RndKl8{T)LEjMiP7pHz3U4UjM1(6VH&dzBD+O-sE3r-T80PUwKy- zk_I*MyGT!g|4sT|KpND_??P{Z|84p!Y2a>v+@(Ut`fvmI{3FW0&;jzsz)+rUNSSww zaK3Ou`1lGd+#AB9J{rO2To^pgM|Y7vr3e@5i+6o;2|r(9g}b1;P%QY=hr#LwM9jqvloDGs4!VJLy(bAAgmf+nc}2Poz~X>>bA2-Vh%3(RlMy z+Yzol-OJ!F5j}82+r}E@p+32UpIV-}o(0{7;<|W}8~D|yd#(Nq=o^{_9?Aw;Sdkr$1!!rF$9tByXL)?VvfIH25d# zPkMUGRqU;2efEo)2KB{5es##|EqlH8y7+@9<$)p?N()0>H0N@oa4_}8-4Oo<#M7ua z&c(km{ud(+&J}+{(y%_7bMbGie`C|&T=CbZTSNTL#s6aXLk>NRry=rq)0``QZ~F7K zpNs#+@`qehr<`{hoGbqG)z_Q;T>LMl|9PfC3Fv+HHH2K=`kb#_@cFy&InsdgM-hzF zP2s{?D}EIZ!Rx%RFTQ`ZJLIM`D1p&8Ca!<0 z{*BRD9rl0vSCygj%J(AO)M@!|d=`3KATIqk>a3Re0`#VOw+Kd3^ZB0b)_Is4524LSd+IH7N&>N7fz zweoZregLI`9O2$>jy;Txpa(Z&xDdc@9$&S7<%->-B@(1Z3mKnTB4aryewFl6W1h-zmtSb5 zlFXIFhCp$y46CGbB4S_+FyfpDH_jRSCjymi7^=@H&o?UH|6Tfd$?U6-`j4u&8YpvJ zx|AcV8z%JcN?#FABV?{i4|1b?rWgGG3j7zyT$e6oh{tfTdOJRy&s9fq{B$5TVO16ePH$;B$iGiWGJPqNg&=4)jSPbKaNrRy#sa^oh zMUkK4f+>P2KL<~eu>^)>G{ER#F1VgU*b9~)VSUM520xOMWVFMOj8eS`d4ZnbdtUN` z{{OXiHSk%EZU5SuO8QtVhSc4RXVL2VJg@KTTAD1DXR@-0?rf{YR%=^Xq*g)^CPlo- z5Tarc^`vq~5k^BEA>1iM#gL3=+WSAR-S?hrclW*4hwAtK-u-@u^ZPiD^Ei+5_`22v zX{Pj1C#N|YJR673p1 z5$Jc(?v`ag`sv$mRyQ4Q`XkWpK1U7aRJd5)q9eCT)N3FX0PFQoV|kFE*JPxpTAdZhW0`rT{Yb8~yYw*uSC~T7xtPODZo--uv;UKX8V^7M#J67x(=I)*e^>2kB{!j~Md?=Y^Kd ztqYwSY`1_{!TWZ~;JQd9@U=vSPDuW@koF)yPAK`0K)WCPWq=^fp(PzZ?)oPJ?T!4! zxVM=z&@(ymgwhvjUNiC<%9Cc>p?I)gMVLJgkZ;U6*cs?~tHa=O=n367*p4(mQh#tA zEiosQc0c+W<-t8SF#lj@h{(H8T)}oEIwSQ5*9GV)#JnKSe5l8|$HUbz=djKY4p)GN zh-VIWhH!W=&l9dcQs3d6p&499On)TY&GjGZ86x2d$K&SuBH=ll{zExKB>c_M8g48S zp2O{L!5L~Wr#uq=a5Og87YWai^hY=Y)n)XpH>(qxqcz;vk#}%9>UU zr9V*mobo^QWlrg@XBx`M4P}kdP}a7McKYj>)=s&f>FAX8jMY$WW-jtA!l*9YY|(H%llIK4>wj_G@CAx+_E^j-EHMK1MBk?mP!6Cnl>%Uc`=NeB^kIDlpaMYmX$}{q zp%Or8plecsG&EOYUUN7b$J{uuh6R)ZYC_gmqfP0cGv)LFz%8=>8Na zeT4u@gU3z((X0b^i|IR>`?eHUOX+JVzLw0xp5B)7{8-b6{VH60(t1jBXL8ML_MV%= z(bBOH+T8omcjXO-=UCC#3~h~c9xwV@LL24N(V`EyJOHX&8uffQ+_VpK-164QEA$^w z4~HY%yl{QNwHWid#%oZ|2#$r87;7(IpB?-K=e`G9q_)7C4JZ{(mQqEbCdUdEa<}?v0-SV_gM~b(-y4L zF;74q{?_+_eJE{ozu?}qbiYq;$XIY*4f->R>0AfS?L))0s93Pv|9=evc zL+Oar4!5?YeJ!Oi9KJ~Og!YG9dnkP^p)nl3P&y*D!>v8kzGi5wz*ty0jzmvr|Dn{wbJ%lIiZ0we<58+CKaj zCH?yZw5$n~WlVcot7F>Gzi&XlOF1PLIOUW;SzrI1)2^>y7bwdn(fQb>q1@k4Zm(-7 z*VQ(Z{+foe#?w&NG9G7s9piV({ZUQJV1G?uonPvoHzp4t1rYqsRMxC!#l)lVgL{nycmb6F`bJuG-$$}F z_V54-0o4Hay9})#wfBI1SU@?ze~>*xX`pSorVMaMH-h;YfC@kjAROL9?rVknmr%=Lt>cegRl0{qS4bkC>t=H}9|;C$5S9a0|p00-P9`sm(t zyz#8z>Op+LGTa<@pKD%)tDo+Z;u?#zH>J4=J;61>GITt&9h^r?jJau`cq#r2KBHDj+dl#gP4HtsAE5Dmj`scm8tA!0_jUL|$K5}n^W0;!9y%V{4xJxZbKLd^eHEcJ zhO~WX|1JCvvp40#F_FKJy&L5_a33tjX>H6DqE zu=rf-nv93i6P!m&jCtJc&^pE`4gOFZ?sk|pE#5zLZMZh}iUm}=_jK1o*SN>R)kEjE zqzydbXsAJdS?Kz3d%F8V=eM-&qQTjhw!^J;?-i~dZq3o`3%94c?`ZB74wri`SDngm z86Ygr!r?jGKG&Y~9ryqlhl}fQ)?q&?ALRf~xb^rg)$aI{g>7gyq25pb{vrO>BA^Vw z;13nj{EGv~F5oX0BHz-9`N`jjdBfL+>8gj?6*K8hbWJb*$#1;iU8i=hMB) z0^miN5&%!=nFBON!cRr)h<~tmSo|$TjP>pWp_JL}y`n!}H=3IIK~H)IVP=x?M4?Z$e@+{XUUIcQV-!SQms4((9f zbpH(3yv7(XFh97yNg1R8>&jeft5K);f^%ux6N)FeHniWhE|dnZdn{0Q&J)Dt9uM}N z2>3zQ-^L%{u5g|EsNZh@KfOi|;$Q9kBgz;uAGvybtQYXDlO zeRPb@aptZ=N!Qk|1H9#YFQOOa0R;W9lo&LQ;0I@@h;*KVp$)7Jl@;H?*3t0@YlFDF z821C{J7^-CEm%u&&@%;b(Ys=UG=+=>=QJrJ>_KUA;|;E%auBRLWefMBba?}NgokQn3Yp|ATmo~I; zw9J|gv`k59XeC|5FwqPP3{(Rx!e6g%#Uvp>q^&&s8_5{P;|Yvmhm)9i1deoU2I9rm zOf34Gnb2Bo7-K|nac;r&`4c^*1^Hu&&4lqqW3=Mzyxf8j#mNPuvx~+Sj~!W(oISQc z8&O=)djgl>DHt(k^vK-ek|DW8#iPfLF%!7nY=YIH-N}u(2IS<9DH&Zd(KEp{r8kRd zp2DKB*}28VV~hG0W#^49$;~bqUzBSmT#(=yGok>Mfx#_%54p16*qq$n1ICOQJGd}s zL`iN@f~RC+A?DmPdW^s)SVo^9?ZN#VB64zzvx`O-mVh*C$dw+7#53MO;K|F)FU&16 z`nac1x^r?1bH{+@?1>b^f7>N}1I%%{!<^4e&jAOxYV??#u{Ra>?l-oeVCJPu@WrKAO0O$DcS3HyC!hY;Oc+r-V9W%Z8Mi)ubl+?$ zG-krc5&6Zr^yV9JH(eaKr~eK&*%~+7rwN%xpT_fI<$vYL%IKTXH#K#@<(Fh-1uFmF z{=dl&YMBb5Wq)Tob6<09`G>@r$DHF?b5OUdqm5=d;UMiTfA#0hh{W@H`5XB+xr1_#a;D0u3)SW7hia)dL#xof)%I(aK183ZKc%nH zP2+82n~`benA6N8OR+Mn2d(F=AFbB*#r9ykz}{n1FQyzcO=Rz9W4Jhu=eBS=Ifn1g zU&k-tU*Uh_PZG`%9u<0ueZ}SCdhu&n4ud5XMD-XjC$PvxKG9Hm5= ztte`m>Q$ds*Q)!~)3w1`u6C>Tmo`&>T#qvnjf;$(My(NR4l&1=&zo3?qhBbSHQOsx(g2oPYUaVQQ}SFed5RB z9x++ESh`)BD=n3h$$GMtWXN85vYe=hN;>FyPWeHJRxeTqsW+%UsCR0QX{YJu>V5U^ z^xySP#$cnsSZZuAPBOcg$>vg1wXU$%Tbr$4ta4>oE>k8bvy>IeYs&XZy>fxds{_=l)f}~0 zy;XfcU7)See$k@!Q}sRiwZ=@N!g$ZvVJtPbn!8Qiy3`tMjk0dCZnNfEPgyIiji4kN zH#OD1-+mSJ?4@$#Wte;vG37$7;X&a!VU>_2=82DpJH)+Wok*l7rI)1NBrho>cabN^6!`&lvzDwssi#9;s;%#> ziS|sJK9EZ6mCY8jce4xF)41+jA5P;6xiW4R_ax-^ZQRUG&fo{~*Ye}}75rPgpC1o7 zo{#}h#7-hB-7h^ZEtB4s{w;keT~4ke&k-MapPVO4@-^~Ad8Yh|TrK+{ z)i*1T;MO)PJCxs*9+2;A)Em{w>VMQ^?O)m^ElVG**BR-i$G*_k?JMnUdxHIxT?yW7 zv3J?jsZv1iBkii(&nJ|y;&9+tA?+4943E49BmP<>MWQvXJuWZz@2 zvZ>G+SQpKn&TeG4v9q~KPT{lo8T?%J-|E-uZb)+{?My96OSWXIzg2E+v-VhftrU76 z6%3Py;!*Bd?j>%G@RmTtG;zH6jJQ$kA@!98OB1D;(u2~YIQ=^559wqQPgr6?awd|Q zWFDy`Ysdx?rQD$WsEkmzsUx(Hw0`wtxAjZ(Tl8dODCBXu@xHOkV5%GVD2RqQMl2Smif@Xa;`N_JI;f|r ziE3|kq*|mV>#{xy)IDM?wkRK8v>AVcU;7PvDKzTYd|&=w!rQ_&;YaASzT!afDzQ|Y zCjKCHm4-^ArBbOJTzN|RK-wn#48ELBx{=GsATolClJn)Ke{?(=*W)|V>QEUhHYqo~n&z{Pi!zFU} zau0KlajUpDxhiPf@41eA7rqBCg1-KI2LA}ZpC2U@2)7A~gcpQYh4+Qe1;6l<5GUq{ zGsOqQ*Trh_OYs-+FEK_MB<0{XTaj2I%l+lS+BR($G)Y?{*C;lo7_*Egp-p}<+L)Yq zwOL}mXuf5hY29kguzXe*ySIIrJZ9tj>Mtszwb$lo@p>X|FI69)XX!Kb+4>v$7JY}F zV6cW|3^J}Ya*XN5y~bL@XRf#2x0u){M=vM9LR`*W#SQ14;Z|@T!EXKxYZ1p^#ox%^ z#-9ahQ-rI8TZQSu{lZhiOTtRw3*iE>O57%X2ks?E$?##*arf6rPfIJLH=qr^f_3Xe z&L+KyPEyEV@)&sw8ud~+Q_hwPDXw#l%nMso7db<6@(uHO>B--UA!u z=+Yv#lb{GAgnRLN8BrB47xTr_q;Aqh(llv~R7jSR*N7#bq@*cVEAJ|tTB_cm&Q`am z-L+)As43c;kjb<3T>U2fHvK#!-?-WEK?b^**O-gVHRf38^2xAmQI2ln*fH#M_CIV_ z?mljcaF;MwSS*-p8&O#4eq2HjF>a+9@_3irk#x3UE z=EG*a`H8iv!S}0ydQ$#7<+MV?Scs;eGR5CRfC*1!OsSPyR%fl)g$PsJL61t1MU6;+6cM>{I>%O=qj= zu-YTl0@$9r)o;|+S_kOQe`o`tJ#W(%X`jH;Izu<$YYoTyVT?A$`9`vl0gqy>`HuOi zxzqgJYz^-w(GskStjn#dt&vudHQBlgKG+lR!d6*KMU;~qx!U;7u*_R6rZUR;1^27i zNn9a+Gk-cfuQcHyVWF^0SS!3MY=KVNBm60}fi>+a_7sWOPt1TecuV|1G{^vQJ5IHP zTnqd5BrNF`@VTARNl8$8DM@;T?$>|Q`&tvNGU%dm>pOUX`>g%e8Fn}OeCQ>{7vcLm{0@FM^y5iF2ce5lBuvD+nkftuv&9=>7e0qg_yL+xk!7UY4vY$LIKcy_y*BB?8r5Rbv@owtrn%9tPj*<%s5jq`oxe`Xsv(sP1F;w=?ZLyV$;& z%A&tPmUGz}?r~wYuwLj49-S}t78i>z!*9J&x>b6gB+D}1)l}s^=_sTQfX zsC6n+6UC$h&Hu>#l&_Rs%6{b(^-?uceO;|qx2rYk2H50nS~q&2(VInoQ#2I+ID zMoJ(8WO4#Lu(@PDSw}XJ?c^8IUE?(%h>dpS<4yY;dmqK?X}}xJc43oPkxgOK*(^4P ztz>`ZqG8X@=T-h<_$=26lb}9=2B~u z6^9stNr`skrjos0oFLvMJ}5pRJ}(+_s+^%@DQCgEcuap8wq-N??celzy*2LgLQ^*{ zhE!Y&Kl5qmmks77=$Ad_UUP_bC*H+}mLHPY$sTCmYCi$bu8Kxa8PU#1gvIPD+<1Np ze;@xS{{(b(FL)Gl;Xy2u&W07d8ussbvXkrq5C0;?@bz}f-SqSI-g*HjuCux#?zs|? z##o#2Ml-{}QX*JFmQas3)k9n>RZCwZ+IpQ#RaPn=Dv4@OH3K@}259?V)y`T9BAMH@ zH}pFFB4dP6V%%Z82wT+Ayb5;yPV+&WNm-6DuQ>>G3^V7L7g;&hBxsmttk{8H*xd0Q}}cEOJQZ6;8TTk;cj7tuvHid?{WeBglk|4Y3|yG4&T&oxyu-5d|88wGzq+VS`AVdt`K<#<@$p>i1_ zs8^A<*rI%`{EYZ_m^w?Huf7F8x=Itw$z~U;#QM@|2Yq#o{R)k{tD~75kUW5`V{hQ@ zM7(`Ie+T~n{}`xU0k6Oh8&J!~3SD85GKCVMOgL3cf;Vc4gCW&-h^yh>y-8*&70PNQ z3ck^o(3n+PJN<0E%q%x65v}z_Y|!wAQ`jV-Ug}KFMFeyW8At9U50N*>yJV<5R-Pt% z5k1dTZbMdM8)6oZwnEzq>HA9);T!x@Ki5!=tBi%lDC;)(`q4}&XpUjeWiMn2wBbnh z4)$Jl4I;QN*^ZFAo?JFJiN8V^1)KG>@I0~x?+JsHJY|}4m-4vstTI)7PW9n!)v7V@ zi3e$U+BEGh?Q!i{El;1U&(jy`EA-EF-M9ns#Vd#}-m$-+_llf*9RB;Ka26sVUB3wW zkcn-@%tPO6+&kPZ?qt3*_+`Tj9VX<#0<;wqL>V#Y3~`S5E_~s7v6FO$)LT+uGp~?7 zk+w^Fq&lfJ=}OKg66s5>B*V#QQc9+id&!H){CrFH!LD|}TkS0?@QQDPjbA8#1nqVf zyr}1tKI#UXp`(_lY1+kj7msPWey@2WrPYJ)11NU!=Zd<-lQhKLh2$1^Kud{kmDvv> z_N}6xFx$$p%N-DpB*U*5Di(>4ii^Y>5mT&jtP%scx>hch7syrcn}#T#D3gsj#xmmr zV=MfZUe-V>%en#jdo}d;PU}xt>27rYlvXtD#l&+L3SFen$SJZakCMNYXPX<%{bn-s zdMiinOm;A$?qcLH2JtzHr6}}6fY&&Aw^9=>j*h7egAGI9a=WXD@ee8SOM*dmhY>^iS!A@nsAGk}N zt5#?m?N2GKg{>T0_AQqwTqo?8+bU0ZM0-Yi zL95pM(CjDa9duQ{N*|{`qpyOmXc_~-!y;(b|1lODZy43a7UK_ibUmP7i8;#bfm2 zJjXx9c8IdBCGWsyi*jFOsPcsJBCJn4SfBCgJ*poXwyn0ss4+f47Q|r;ZWqU^Om!y`6so+lBjZtBYU{*9o6s|7h`4@dD@zTf7q9eLgZK)UT=#Ux0nsAZ|v4xJUe5 zTx^_bb~Sm^FfViLU7x<)*w$egrCZH6_N#2 z*od=^hvuFwzAJq!-2rX4LH|SVhS%KH%Ev1n=j0rph2C3Bea4!GcN)cZW_v={TI@J> zD$e;V`wF`jc@~EAAX6)GqmjRu0V!U}z0B?4_Hr?NSH36D@hRe^&?(u_DwD*!#rg1o zH;G^26fshJX_s`aa=Y0U6vsI4FAZ7B&!sf-Ju8_f&`yXIPKV`8 zK!(4!AUZjc{_ubX;r_1^a)cX%LP)_R_}?>-f0%=;MFp(Y65&N;Pu3!mc}J)g{taL0 zYhfoM+r5YY8L_q49y!Kwi2UlsSg8vlU0q6%21?25Pva)cPS0 zKO8dqj`p+mhjyx-u8-1-^=bOuxb?T7zji=_ood7*^K%K_{bZvjqP9V1HvHO`%~#DB z>tw4B-uqB%1mf3sorvdWt37!87;@y54Zf5oCXgrZ0FI`!LlKu0u#;eq=d({CLRrCn zg1q^5_Ivgx_BZ$#t+;kvXD%K&uk*Ry9N{ePQtnDFi@T1?LmWSio9*OtR&hQjWA`Dx zN_+`<`hlzA_94g9vYTSq7^Xe$If-X^gHPep`Bd28VUVtTu@L@doYYlHlG3CSX%W6? ztb_%QK{mF6EJ9v-BP`8c5)ZGuP%ed)StM7=E9H$&T4Ak&`&4_#3VWQ4L5FMNu8 zrBs=rl*4nLuPj3R;8Qj#Rq(%dDm6;2Qim@{@v28ng4EJ4BpGTJe6l=57G>%T_-6BP zYnAFsc$6E}D#V;yp!asd6?d|l^|9;WD=k8!`*UMYwy>fdc5q!)92d9H~ z%fYoB;8zNGRHb_1ldXp*xmim?9xR55!+q9?rNFchceY&0fj6@S9zh&@0xxpL3*i$b z;a<{|4ChuV;oofpHxo5cOVu*9VbJ3F+H&B`*Gu$C@bH%CF-Ci2I|~ufl_BR@4jWzp z53>@PaG$XrmT$A+#}}F!W3R!OF=i|xSdW=#vZjdaMyi=%W}04D`$D{yGIKht{v2~2 zZlVIYvqk0-_`b`{mGA_RM}^N*WmcP;O~z_(#aeMzyw%n6SS;RFij|J9b6zXY673Xt z$Am1pSX&@dJHBHgFg=t=O) z(jc|-jU~ovqk)t0uwfqX(lBeGXWBY^p*%^nlE4=Qe95qefiF4WOo_$VZINloqUSD* zVK$=Jfiv&LnG?BQoamf8lN-i~c<;;kG(;&&gjyjDa@bYsC1pv4kiqHr<}e>GexU!QsFJklIO|u`zx%pkDZ@XyD`wJb!xf zazs@Xkgqgtp%$lS>cjNqh{@XDK`h3XJ639;QyqSp7b07%~XJN`>oPXO< zix?pu5!FUgP1@3YM|ljh73X7Mp;(sQXF9i#Tf(j8)^nS=t=w+Mwzh|L?S-?_FUUFk zB7P+-&=z=GqL7LxEeCPhbiCIk&X?ONWP=;N{87!9E)A0!-sEzrR$}lqBc3GTt5gai zge*e836_!>$eB}ZSV>kwA66rK?gK}*AVW|i*TOrF1wUA24&Lk%yxKY?Mr{vmRt{Z8 zB_T!2(6aD)sn1jfuPN2x%z9*kn2H$Z-_OkF7U4ux_pFERsp33*5-e_-^VO{!wsi^4 zvmPhf%-8UBya65Lg%7+NH(Cd7CBlcKTBlAlaGFeHdE-bbvMQNm7|DU$mcTQNL&i1{ z-|Tv6b;wxITk#?{Pha{Le231!yUjC8O+S2wrZ198UoYofDwbiTLIyJt-2~+@-_fz9 z(6VLFvoqk^ms@kJc~*tB#HzHGTUGdeyw%!)Z~tWtxtGcqW*+ob4BHmEH<9fH`I=VaE;cp3I(^+I8@-(X*$=C@k(N#{w z>!Eg%z7rNNh1$m@N_#a9(R?L-OJOB6`WAI7Y}*c4x806)W3(8pEi7ET*0u4r6wN@i zm5MKw>5!penipC-4|=;)n*>>!4r!XD&C}+?CN4xKeu=hHTdnz^(>KCWY;kO4622v5 z;VVKaH2NI8z~#{7n~gZ=>N#eawGv;8tC91Lp`SUK40wQfY$039&VlE;6@Eqym%|rA zcb3A-o5#=REBGqBtF7?sc0d;Q!a~Lgi9!-|X9_a#>%r3B*fdBURV)Ah!!Z8~!M=)8 literal 394240 zcmeFa3w)Ht_5Z({EU?Jx6C`S?QC3}P5VS<85=D&=A+=PaAW)?i71KabQ`iVqs)5}I zkIP!xV!yVvt!-^5nRzxBE`Du)zyJUL z{lEVIDEpje=FH5QGiT16Gq>jp7cU7FheDwU|2jHCp%py!S8abk{%14M2Mt_xP-uDI zKODUxJnj!iPiUAvJKi|!ny<{d?5g+`mtB4JHOctpSH@>GT^*l(b-d>M@$sv!nRexg z2OfApBFOsq%`@M;`ddZ!6#jiB_pN&_=l!Cmi|?IjpW%BO?6c3k->}c#_g=xX_{n1X zy!uXk=~px;Y|k3hof8U;3-<{fwC1}P7veUBjtTb*9~25T zz=hkwHu$O;z$Jjq;!L%Ji$bB^Hn!^-no0;LUs~KNR1~V7ZxNMFiS4uVVN*tq>lG?f z5sf^T+n}C5!+M9N4GM*p#CwG%^o+4@HAj;U$Pi!MJsvtMpl^SFCnm3)nXsUpy3=dg82UmnAO?g=XAG1bK!;P^k69 zuhdVUHk&9#)CG9Q?1fi-Vsa)}E}PKQ057o@Uh9doX3x3;Jj*+H7`mUAL3`mMnxF7n?VKWSp>t?l#QZH5tVJxgv{J87KglknPehz^O&LOR!@k=50B>Lo1z$pO<5ljZ0GUf; znc|k#WR*WAmbyMdEuQZ~rRM^*yaJS|jkH%o7nD`oJ_loxt8*_AhrB8^xj2BazD1%#=iVYF?r&ocjzo z{)9xWKP55FJU9Wyl#0Lyfc*9rs(S^~%&aiiw!Gq{CkV6H zVvYuLw8iwl9J{$DarmN|#KGPJHHor%_)%gmBvC^MwyLbp^P)y5CB5JFP&N6dUO#K_ zQ`=q&uk&l7Bfa!a#G<{oTA_W6Ynw}}{Tpi9$J934uyOnnRi{U$CQU#T5^(~~o1)MO{*Ri;!+$7ke;4uFe$!%p_1AvW5(k9V-LzB? z6+3v*P5%L;s+H9HH{A+sGj1fenzAY+X2}OdakBQj@0azHnvhX78R0V)UG{rfBxOs5$Bf zMWKQ~^;R!yIY@mGWOK#h;!qaE+@XXtRc0dc*);!tHr?z`k`-y_B7 zhBu3wccIBr)TntE6#NJv{fgJJiYIhTSQ+%KsPt3I1l~wH!Q4fH+!)@d$GC@8JxD4k zN*Am$m#9 zAoDGWH4-sj&z5Js^s8ipPN)kwdai^*97QPley@w85{jm;S`J=#b8#p?HPse1>j$EY zCK6a?ejT=KwK8OR`yEKLy!|zRc)Ok_>Pk)Hwfy-b%hGal(SqVmS;^%IML8_G6q*o@ zvXMo};}HEb)2&UD;9z+V4o;=qa&rjj^B3(EIod|9NE10?ugF0*atMu?SHtwoR#H=L z9=ZvsX-##6y``;E@lzmPogiQ84V1bFg(jL0&Wi-UGf-_afHxD;(%STv9Wax}sw+fZL4P&F0pMz2R?~R z_S1pC^dEb))zQ?W%=}^zl{{4PrS>X2iuTgjyXZrNS5)?7aAYqAN6hl(fWbW@#o&mU zBp!;vJtM{7hf?u}hRkNbe;%{|ZC-Z&2x za4x5u+&%lm`F;WC??^&!F>jp`c!`TDH{ayHMr9tk{z#aL$fOe^T=D6|Fb6D6R5)O9A`Z}=PHYEpQ>sSb zhkyhM)N|9P&JifPL!l5n+`m0x9KyRisvjFIbyn@#Uq=xG|-Rd zQqL%)5u&uvDl1#G5+VK&q3ZG0s<)cNOn-Ia5kOGa^DxvK9uB8NB^#~5} ziP-p#3u389N}5L|ioF&_{SY|i9caDr9d#wCN1`rbwu>l(nDX{WVk%j{3~Qzzn@&6rs6TMhJiyU|x6STN2|;_G$1riRCJ_fmk?U#_ ziDKSM3OpTe?s>CFuEnzAbgRGBONZe!ttzRR3(4lPT09F+*8Z1(7(UZql;s&okV8a@ ziKms5%4hx8XLzRaMVnoQ&}^+o(?m0|#JZaBL9^=HYr?Tv*YF#i6~A&8&&XxTRj;cFt*effEGweQILAecYWq>f6z_ppqTa9VTiJ@0(obx_kzE5v z5UmR8GAwg;q@%KVH!OE4Z}s{+v7p~F zEd|#GM58unY!d7Tdtg(!^a#P%;-YHl4T!xMR6h)*bYeND!p@ zCWle>-NdW1a|W0*RYZP3xB8hO1a-{*P+~I_u-lNq;CSiAZlgj=9a5INQQZ?xz?DSq z?cLTW7mF(Vm((t8xhVRznIhp%@{HUq;&1yoR0x)Le9e~gh+dVVCNa$X7cb(y2oUUV zwQQY8I#^`;k9U7fVjewhxOXeg3T-z6Ngkf9fN$Q&9H1z`ixsE!tZYh#e*UM{RCRVHzTQjxM>;-+cy>#?5#g5%BhY5+17mmMx zj7m@zHs#1fuVlXr)*R`j^{hbG@;gCJF+OiKCDr*a+wQ=4%+QO__b*MDNvkM^&Vq&7 z@+d{3WU8Is{&;*I1tCqaCs!8U- z-DI2$tId|tfsDTokdG-nEgC0v;${RSx8XyZX@qS2mkW93f4xWlIzI-l#zy#=^dUdz zzYl%tOh}QlDEb#Hiv9(QqQA2!g#E74z17kRUkk%OXmWwQmdmzTYj&zxlrNTFGZnLY z6n@RofnPJNN9USKji;G!U;;(NwS8s@V8L)V4;(F<6^5(h z#jzwbQa2xDNB&L;>M>FylB*UugpsY8Q5uLRK$!;PI^Yujb^41Py3ONng~{B1-E8@q zHHU9!By)D{-9Y9E3P8ySgFWlRf`UP_;B~G$)Z-%t{2y4-)=-)h$Mj^G>8cD*r( zikiNFs~^dXjdYyq_&C-o_+&+9pk*TSUld{|0xtr{mzYsJ0!23((4552Bx#+`0;Fz; zhLZg=*G9|{yiHW_Q3`$}imT)(3+e-D(T-D0tVg1EP(3zL4j`zR!|$}uS2P?77rs$L z$zs}M|0xXYrD!aMe?9aEcv}~EM;CY}ATxJDxVtO#t}gJtF7P)2xQ>wlFq~bSSVB@- zI+8gjI;qYKK3n5{G#HgovWgBjjmWIF2C?}Rb(j$q3l0I&X#D*$jmG}mh?^kv$3)u4 zL}R!kxzZSwGG|4YX^gv>#@BgKnoE>sN}`bg<<3%Dd=e3xD>R<-C{nd))|0=6R=Vtr z(0KC*zC3yjCD&-f#@9_U6(7oVD`|H8DsH-je4}I%QzEJ-_R$HVGpfxAzV-6ZAz~zT zQ(U-dCY8M%h$@P!qOX#)ntOeT@yrZ@=<&IAfI%Te-hwMZ5KEM7Pcie-Rf@Hu<}ExD z*t~hBvN&A9J<5Xb!@AMf&`fR3P0SCtk-9sXRI9XUaL?o-HH}gish9L3>GigpT0qPI zTc^dgPLwkRBYY})Q|fcCA_wfVNUtRe^4>*W9TZuP)S0L)vM->fm=^q!xP5SBfr0~$ z)B~Gm&Jahg5V#I7=zHye=6-%`-&+arU~BJlLJtpwj@%sl&b_KNnc2vZRBb4ewK1x< z2+Y*Zh?n{q%qG0Te1%+Q93hFl0!S?T;1Hr*#|k>t5u^eX$MhHQr}EhuN0^EyogwUE zv$aQ1NWfW%4<_;9)+8>gzY zOz*_MQuua7!Klj(Y#;0F=dscLH>VTdg_1>M`*{yITI&6=efQCf(oThDd=l6kK&IpE zB&Tit7xvxy_jYUjTh-*xovvixRxox?YR!k4aH=gr3lx+c!%mdei&Z|B(@eC@{MV4U z51JM!I1nwZjhbt1=F}2iPopcK4&HQ%r4}!gnVKFxe@@Q zrj$WtBw|*v;waMCRkMI%M6IBntNSqjkY22w+wxeTX=vDzWDIq2JE6IH{4Oh@(jitt zA3d!gp>05t&7h0eZ-eRM~!HXX-v=$7>lv{>TeLRO_WWW#(Jt>$F-HNHP=e|1ZeQ zh3)^NWM=KD1(|sm$jQv8lKsofcRKOEDSRt42ZR6b$xKU^%v@zgkm30JRsX%r_>!3e zzz$@lAE4QJO3>~f0a%$)drM~GG%gO(RD2H&*|{asgHM1JB!3dnJXlEnP>{S+%rijeO=ZE~aQjf~%U^`BiUW19EBB z66$2~VIXCHp|by^Hd=bk|0tRK=Sc;b+ydleGTCqcGWlpHew*;EOxA$^?`bpnJq3H{ zPBFKhOvmSb0+?cQc4lhLQiP*Ix&Z^rOMOW=qeOx=lFtNE13YuUzt8~1ZU3VhAX!;x zfJPwK0Po3r*pCTP(}`a#eA@tP!T)y}AUP*c3STyV8z!aj<^NtOTxZsR8Vm$$0nL5< zSf%hg04W6xAsguQ&J{X_*)wxXSDJ4s%?*V#^Mf=RJXUCpaXG6#r*qw-i>#sHQkYF zjhqppS9mR-Wogy&0WN5kzK*Ai_&ReIZZF)hdn+m*lOGTzo8RpUFXH`w0ch7oepTNvdutgDGOH{&MT_e~{*CD3bSAONP}gk5Rsz30j=Ei_F2l zTV?R)rC(;|g>1B%Sfdc&alj3NbHjH-hM*S?4o=E(LKfPm_slH+vX0rBrP^Q?N0fL9aa!(0s^t0o!Xk z0J2N1H@o6kGP4~p%l4z7RGMFPR5|yAtiveKI*bA!eT3K2NY(bJlj<{vHPCML*;j35 zb=Ic#6Vzr5#Hu!D@(gNo7N9wiALsu7tT+a`3VKA0>{f+MJ*wc?=d~~-gyw7MgoQLb zRHP(1+`No8GigSYRWbltf1JN|g>u51s#%ZIKaQ|EujXmMx~2ni*CQkkDn9GxDFdEP z8gIV#qaIv9o~OA54%&7CPI?U)HPm_!w4RY6xwr5La$?o_PiIw!mW7L%?(EpKtR#Qh zvi|u~mc{cYEo;u7xNLs@_+<<7gO;W8$1F?dk6PA}KYZCu`9qg2%pbgLQU0K1e*S=E zH|KjV%jAoeE!Miz0cSJ&G~sks+)9}}nUXlwe}YA)Q?wZ|T2CVm7ZR`Y62sXv@NEdG zXW?JmOMV&UTn&vQvXO6(@?#4Dr}^U+MtDx(8RcJ0OPZ%H8n>{-yMM7w4Lrbmz_Fqp zjQ)(^HU3iDSKvUy=~EK5vyRLC$}vp+$-Hzle0F_{xifVt=&H`o&)#n7V6IA?#(#-- zsV4vB8AZrx`6N^F!yXLw(%)swDaaM6BGM&1M=YWBy#?Q;mG&oVUix^&26HqA0h?zB z%O>fkVDua9RZ7K2wxb$?2{Ee-#zcI!|DG2kehTqZ{fQ<1d8O1tlb8fd_9vG4=amyZ zG~=fJ{E2b@yaWMS+pYB{R`}-)1wZZZEBuMW{PTtrJrjJ(jEN)s^JZpN5Hp8?ze<>uY5_EdG7BMSm4a8uQFe%KAagH={VW0KF~4|-t0n- zHa7r8qnS_5iJK=Y)brxz5uQQMdlb+t=Vwy>OmlZv_^%ayyWZJZEp;ror9-p?vl1hQ zK@0Z#9EUVbNP=11I-sXinh69uYramoVC|i(me7(k-p=7(u>^v#yQc+&2i7YDJj!mvt)u=Ilwu ztUm>B-QrC}QtMMIlO32Y&oeae?JOo6|DAvJq@D4M$ zHzfu$!CP}HyX?|--yRW)Ct@fMyTdD;*hG;;h%_SJ3J4&D4h|7g!6VwwQa2QEBPM3Y zEcu|-9VeMLI_zkZIXB7x*(^%Frd<|W!fh%G^htFWbX>^JiWnN%Qo1-X7n3tn($N?- z%YR|rPc!dW^x7aPzPUgx=(Uy+w#x=YJr7ZXT#dvl{n3LJ$x_cCbH;rIFIKVH+ClVk zLB+0CGX^zmhUhvo8W-77qFB3rqddeMD79-fA{k2EJL@}o518lT;hXsbYvS%0%ws^# zO}*kQmyr0vT8>z4*K&T?iT^#}TQ~J&@VmRIC9LH<3o*f3j_9&$Ik#JOF~M^JWX*$f zK3m-PT)9kMm^sxhke_BMDPdy%G&5Lb+V$S!fW*?aGigpMa;*7gWVVFc&yLsy-%2); znQd4c!M=p;faWj!STpjk0NLeEeZK5(=@_0c|8>39wEmV=E0E?HG4t||ToWv{Xkc5$ zZeerI9W<7CVpB&4n%S~E!UP4t;>3rp5tb(22Vk&Q5{7p*Hg$DP#PV6KW8>mPwFOA{ zu1(06kYIP}Qrm4(JGHZaabc(GVk^ovq{8K})Czx-%#LaP0sg26L)-0=C9mZOW*&1x z_^}ka5-CU}B1>95LkQmGLA)y#dSg@sdQ0@s3e)Y0Qb6Qh_;eiA=gF?lPF@OCy@H*w z>g)<7Z^>EEW57|*Yg});t$HUR>Xt&aLRbc5E2b?mmX&UIE*y!v5LZ?DXcF?*yL5}~ zrd*3IhLCBT$0qcMzuYPcLKIQx>wxO(wxI1Ui=}oGW5*o!XBe}q(DOUHJgwafBK45o zDRg{)BN>Yqn?4aQoWKXvmD~(<>|r5GX^nj{YQuJRzU)hlL4zVh%f74TDl+hsR)i*( z34!JjEd|lu{1d0cRvcB(VatJRhdbGpuc}l2f1|^`&e0BfNFez8*I_r}ul}FVVSPoe zJ<8V$$my^jpJscWgkUcn_R^6B{67LY9d-@)|5xa+t0+M_>`Iksb=YM~`2}P6jW~VZ#B5&Y(1wkkb@g0qkj$tOg{p0#EIT!k|G_(lq6#wUW zGh3YEH!E?}-4OmeAhp$+VYWJ-O#H9=&jQn>ANMc*&By5GhfisZUL;GqVpD z1!U;UJ0E z@-;GGpjJXMRzhrQdmIptbf#PCYB1ZFYqcEQ34oJa#+K!#D`AYLIFi|=wiUCHW=2%C zXErjQ!mUCHT9h5q3U~WhAw4Y?@n^oYvsm*C;##)poM40HgK~5$TXXogp$x5T=1{ED zcC&%hgS^i|X_?=+hqd-iQc@2$=64Dy=89F^uB+QoTNMUyOf-ine|tuGK#>1%1}OMq z9ROE7zqTZx--^FjYYm1Vr`o8d5XdrQ{2g6&@>-6gYIZ)*PWt7(hPc`cwz~|l8wxoY zfE6Xw;Mh(=os5xd!JzAI#ECevT54M_wOu=|T}3UvB#NW%FxrZ|69y~ueGvzz#ns*g zk%0VaSf}a$#w^Lnf#^<|Vhs}@TPp?PBl{!=SyfZ1emmL55oHYfK)R?@xpw9UpnArV})~ z>n++&K+9vvYV-afC>_{m$J~C0T17IVrFEr5)vI|1dvb*M?A5#o7|kD9I8Whk^J9tp z;bytg%ZLZnbEYcZ=k2Z&G zv*&wL>q-lK3FTPg@AligmM3&%K@(u?O5a#e6;B}B>Vt51xQ=XVvk*FP5kb(V{n1SD zsUpcUXtqdpa+JsLY@`LeP6#&%{h@iTG|&+*0HoHIrrI?_HZq}Eum=b# z%#H~rvnZ686v)|O4>?0&KH~4F?8v$asX)a=Z|XEE5I!kOHS8XK0-+N4Y8l0gKgO;_ zKCFgv4^nBs*^uirlcB6&2dFS-2b698I6FW+B5>rjX*J3_xlGH%5-6xzDX3EV*q_9? z?D#U+g>lqj`XvQ(cnG??F#Rox%5Lb8$`Rk`&s~6+VOX_ zbz#Kg@dU%;q-0DmWy&kl8J*?U?J|{wS}i`@MQ`tneqSUVT!=ozMMuN{n_8ocdGFvL z^#=fCZrwv0eVbB0Ux6`#m=b(** zAO#tO%1{fyzjuLu4M4Vn{|zwAQ`$8wX$Jm>g}1OJ{LlezaJ}7%3bm2&gqw!KDrq>= zn@YF=rwB*`&X4G-v?qegpp$FYI+jy;qJsPzcvU9)meLt@R@n&x-W1;eQHR91Zk zlz0!UpT8qZeq6pn%1mqk(af$7h(J>_;eguWT0-zhe@AA@fLOg0vT}8r%wIF3Xrfuc zp-)U3bd^ftOwdo6WPzrrzXSEB>ISK1L?)U{Ph@|y*K$AT{tgbz+MHdA84-USccAn{ zM({+Izk_2(O7nD({rEaFyeFpD@)r;ol1ADVNS2ynM&iJ0SCn=`e`s$-GDR0R-w)=8Tx_;B4l{*^ zinbZlgv*oH%=&tJO}K3OtShhJSsK4AK8x!oorkuTRw>L9&oL?Xk6lmdL-&o$Y8->n8BJ>ZVo?Yi6tm7c;T+t zr9U%PG}w`PbU?#v$3sJ7ME$qj;-D%U%&Ek>zL5MZjT`aXq<+i&>@3u8+TuC=d&7t3 zy#s>*`~v{#U#$RTMkXH8G@%r~UqQ)#AW~h}YU(F>$z4k@WmNmSV7(~hB?c&MmvwD! zEhtR>hstg5L^#yJ16eiyIRahfG!z#-d`(ko&KsdJHT)ZqliH&<$U$JLS?)r^IP5iY zcQzSXfG~Q8%fGU9CH|-K*L_*`cv{zZjux0qryTr(zpd>b1H;>%=}2`HUweu7z)6*_ z)Tefbyj$0XHwsA3_8yp3v}fR@1V*|7*ILZ61olp?iL#Hz=FrL|5iXOaCHbNAcTm9) zCOx&F-D9eTa@eV|Qf)=T+!<=xm@o1-p3w`&c&T4}8uB~2q*~OOpG~*tv=B?H9cx&E zb@hiuQvzX?G=7t+V`vS_#(HNbhV$oVuM0Qt`dd??>hXuv;9kv6ujU2+sj8=w6UMeY zo2+O)?Z^J^Yio1YVZv5DPIPuoxaw)IW?S>F&9f@WqUtH{oUQp!`@8eUdILFTcvSk8 zxqbZ?@`rc>Ygl5~_1c`UUurl+^ z0R>I*2Ou|ba3GoxH~XC5X6HCf~ct_(@E_9sOA|=1e^_MhVf$!ppyZRftrH-IVCao^x)cuWMW>^ zF;sj7EUjAWrML2&SU28O$a~i2BQO1$n7^^*gDhPRn!H6{rG1h|(t=O-C0|aAT0?(5 zFYHw+$vrI|5bCe9PF2v7>Zzpe(SrUB%Uvp^CabW(y)UMvMdN<$D>){)puY85QD+igQ zpwV*VXn^!90Y8$X7zn3?{9Pym)e!6QpHXXF+I4Kfa7g{M^F%3%(B82&kieX-%Oi(* zz2IaGS4p(Z&mAGMel??4gMd2o@?iltled!6vLz_19l!4+7@X%OHuWDeh_J`AfLNHA)Q;q7%|IpNt zGIjpPZEqI*5C6TrRumW*3+{)%ePp=la7G8!1^R>QNr+EdGoB=I|3MQ?DK|I`txZG28xnaAoWC#}!%il+`ret*zmW z#BtA9>a~zJx~?e0t_%=`$hQ|bcS+3?dS0|aSotnQ;Ck2|nkEDxg$`2mNx8r6@a^cR2YR=K#2bh_ci0#!L*v^Ww z>-65j%YjWx5$%%uGGMl5fM%J8XJdYLc&2J|^7!VtCD~+x#eh(DZYeVmlOtv#=;JY? ztj&KBFIBt!?M*M(>8FFt2*pYvoDL9B7VzEQVlL*^Ef^|tHLb191gc9==ZWr4q5uI6 zstF@q^)WDKr#4&wW3Z8>+f<#kGF6!Z|3|k;+pdXqLu;|s2WK6;;(F~^I!Jv zf5N+aYqag}QSZ(dqHS+P`#ux+Mb?pFvmD+FG#AMCTAGpa+;)Bff1Q>*hLao!pX$1g z#{59$S+FzmWni-+1pjj{0(NB)``9ctb<5%rWzl4_XzP)MEoZ+}Jl-vf-zbZdY!?63 zBa1B`OU0v#4Jz_0VDk^Q^o-B_0x;+#!C-IKpwx$~EvT^k7%O2-Vk zhKcfSP1t^lU#pkdV@Sb~)ytJIffghS+L!__VHA~x$D1;1-$C+uG2>U5BcX8Lg**-&wJyaA~RBKaNhan z#TS1v|2!?rq02uXw}1cqbKU&&GjhMj1K7(yAJplem*bz8Ip;irbAF)w@;eKD`97TT z=S73s%IstljC0FB0Fox%&CMn~?MeCLJ?zP#_PFE^-dyM}&ZzwNUGmZYx=VhhXt$Gh zrvbUGEZ4Eu%2OU@oS#Jw(#Eonji9GRm~j$P*sDviP9@tVJM<5M+QeEop=NQ^)uCsn;<7Z z3-&^>3-*dLNp6C2w!6~M!{z+g)kGGRN8B*r;=m{q_9kEh@heqsmkKmMpnN7+jH zvF@K{&#h^>aC=zev+aN5aKLxMx)J;Cfr5sG|S;BAuFe{6$RVjoRP7bxc69NCC=LRf^uWyU4u6?jOGkU3z-?OpV?au~PjgD$2DhWArMg+0doLlnlLErUX6+UQ;k$-zQ&cPd&wgO}FuSoyO~4WIr*tR>9~D@BTHJ(nQ6diri&_uK}8;__4j{8GwhF77RVutm8D_QK!4N3;8}F|D=F?r;tw& z@;ySX7jn7_xkbpy0`eRo4;AtzAy)}`l8{|fP8Ram0`j>4SBAS^SpT%hW2rT;aW8C)ujrcZU?T}ED}5x)3-Ahc5ea$8;^Xbe!$E@J`BDg4-W zsRDTD)8bx95$9Nr;?*q_9S)?i{Sj75JJ)%UpOGQf0=K!B_SGSD(o>$^=)K6E$7 zk?e$QR;Vgt2>`uHDm;|@MyK!CG%MTFZ@hg)pezq4_>E2H$`@+v#af;vDgF>UGw(!%+NXu z)8FYoVgBget@7Dw+IhnS5Y?TF7w>u3EVkG9qGHO4z=DwQBfD~A^#>>?UVlvdz0ZUR zmJxf~Ef8$Q;bdZnjf)e_AX<#=U~tlUaUwz#J)o4w4DGQ~&WPO%@n)`hWs4KB zKQpsy$x>-H1KV1zGujASjlxVKBuEMZ9;p-ZrawR{9)MU(F%_z|3rf2xC{6cQbuyu| zG?O5@AryB4ePn?98yb$D)_~^LRtIad2&cU!k)Raa(OXftx^5D?G3*e8^CB_=!dd}) zis+1L)PxeGnYUd-)Dj&_e}6R5^!oi zolu5ZF81u1tlqn!m73P-6msQ+J*bOe`qg`lF74a(2@x?%HA+02~CvRrVoM=!z@uT>yZ6D3Nm9mla3COzQ(jqkM)0a zww>@o4@oweTeytDKG(!gfhXRA4@LEUC*U?H*4m!l!sWnb!{1P>^bCs3VROuT$_c?A)B)R1G}Ia(0oQw8eL8T$o=B) zjFja=vZiau$9Xda@R3i(N!yZwsyaa=_7&zlJct61MiA4Qsd@s zz@WTe1Df0UvE}_3z>UnCRo($T%9AGFKMQO#1?6p0A!EsFQtrU z48TK!L3uFVm-4=kWz$u^w+Y{Wc`Fqgl=njw@*)@RPO@jF&69vZd4B*jtNF3zJq++r zh03c_dB^uC@24MAUh=xY!MWUALmrdzmz%Hf3<_xgG?VzTgvnb|D`mx=yHe*>>oRrg?MOPNT{n#v0iVeE-SAb2#W-(2{w4=o10+fn~Hmi;U3QUB{*UQXGYzr9l!lyg8WvYn!QeTcfT(O|Q8|8w5mTXdUs zRPuJ``Y1kg-^aOf!9UcFw)smaQzBu~woLOwatZ48BS4eo$JT8Lz(aA>t&zH!CSIK} z@HHSA0|%Tcef|?TN*}&0l^Zqh^9%_6 zC!l$YAL}Un1%N^+JRV9Oipx}P)+S9pp?m4y z(qHa}9O_sVA>MB@ha4;sGrv(@&f54bp!pF$wz+=-;8>{3^~z04A!3mt0vpXbidJIl z3(?bEv}2w8NVyVbY$5tw7wy=lXv?;WLi7*-%d!&z#HxbFD=sBZ>dBnsF#%(8Y{wB} zUgsGw<_$obUMvna`?p&zbZz;+4;)+9-v!7zcyam$I~m!v?Z0!se+n!sU^f92_WS4h zfxmL@^X%+;^PPa-1@oFV5onGdAXf7x&2P%>n}!GC^arSMM9l^$%XubXzRg|V{$%Ri zIC`Uk$|M*NqRE@s`c&gSf5WrH&J_hW=liilrnW3oSMF~jDq=rb#8|+15anGyHsb&8 zH#9Gw=)6*X#XNFcrSZuHb>0Ut|J}`)M6wY>lOfCma)si$n;>%!n}4X2f-k5uo5Vu* z2JYMdm#J2PXt#MhaAX@v-3(}62t&oZL?busEE zh9BiG}{MZ*bBJ+W_=vn(rjx?{l9yIGl0Ii!eose5dBomdk z=#L0~SmSDCE2ORm&|glw9Bi<-?Y|1KaR%PT!am73H1zTLRtIk61h_dFlI1`tOY1<{ zirN}LYoqxm+r@1E@zRfj>CRG#`uq`ggKyV*2m8&~JHIWpHs-HW*_H+IDlM{XwwW{E zATBrA<0z}hLi^^qyJ`sKc;~HI#r<&|sn)PJYK^~@_T5OWcc4GecXbe`JZOL=O19h9 zsAizsA+AiRRb*iH>tR)w+D$fRbkf~&Ir*adl+xx!#Yg9R*(Dr1eX^W2rqr%teL8+( zo8-)#(-0>o1QjWYW}q4o>Q`6KLP4&xumk6Hyy#LH?J<7AFOQ zqusx*mf82|JXJe5b3!3h|wP9!iNZNV09?-#rIWL8X=VZ`uqPIb$#5GCSjEV{8=W7)`! zW2>I>%NH;%NBt=av^lAaXM`p#XWmh~ur+Quiu&hzq42WvqGGm}AMExI!~Uvm$@0uV z?uj{6Hcs+yrlLUl5PN ze?bM!jR?F|#pa^V=_50pZ4s2n2S1t8%3aA%)laq`nTZ2Q#<*^;ZJ7 zc^-iOlB8)%(~GKifpQd}@;Q>9%E!#$dqG=kie3n-_tJ9%a)Qc;KrxsO>Z)Wm#)~wM z#^MTJ2=;C{7BMst%5q1dLqL+w-;bfXP714K)$s}GXpmRQW)@>^$=8zZ$(IXKy&g#E zT1dyN-Q)-bM6-P5khIu%B{&R?QMGbI@+0-&pN`kMjx5$FVjzK`dP3&=jK3ypdc&W1 zqZS(#s9NB^@MJuAi$|SlphP9NgZM*8MCW&_W3WJ|CVK!VOh*IriOykcfV3Mj^={7Y z2jAdo{;+QQ1IC+cUqaCBul<}4a3dl5{%Y>CSWordq}Fr55Vc!lY4 z5Y5yxG5+TEF){&y4^E@sSS}b7W%79q^ULes#>4=AEcFbgc}oX}MzfKJ!Jz4om|?1j zw5rX3^FGk34kuO5Nqg851M=5%Fo8KUcycGNx#hrCo;ZP;WYPX-nG;tL7bgxD4a-c{ ztyEE)g`cen4Pf&^32)k=TReDcvg`vDl)Ry8>zwPd6Z#hAzgjqtx{fo{TWhQll&+$L6bHjN;f19@#0G@e!{uat9s$3U-k)Y?0$1Oe={+ql_;*twlE$U7%|G(MmhZ{r@zw8e@}FsOl;-$`P(|g3`#p0M=1P) z^5QN@Xj*firH3nS{r5y2lss(};pYDIEWB-K*-~;cv{h;xh!ML^sh@Im5K{T7jVV{n zMOBy`*DkH2#irc}mDq+#`GPIA@>M8{g*7ITMkPD?U3sEF^{?EnGW~VoC;GP+%B&5X(J5$!|ufhBsp%wkqrrp_bw?&SAuJYN` z$lJvGBt3Z;lVWq>_&o2{HDFm^f|l{pIesfUg8pDNtUd?NE(mM#Ooj}rS~q}($EkPZ z-oD+Qn4-7Rd)1H##u0-z9KEq>ySHE+xTix&(=d#;=Xn94j6$Ql-mQG7YJFAddtO>z zrIaQiW%>T~OHgLQR}geZ$BeCPJ^H=W$nR-NFDYfnp7}yWKxo8DYX;wI8I4xSAGd@s zO`??2`yL_Oem6RIr!WQzkBa(h{EZJmwj0UXOi6$W_mWD@bFOmWS)RYDp1QKrPip!O z9!iJqvI9ky6%Ag|LMkbLB=2HQfJsnDCZry09Lad~NVzJCY!gtHIX~jJs|;RBDMYz9 zzh2zDBb*%4yn~aG4TBAHA*W#o77%uP~m{s+I1bjsFZ~vKyvN6O6H-?pUK@BP{AD%EA`XXh`YM1sbJh*|V5dZnjy|V)yXMnL9gl zZEotDzr6CLOGPe{VQF-12j|C^rTTW&-6GuSXF(#ELS?TP%<{LQ-a2zu; zq3oPeZc4Z@Vm?RKc9~%uKvhu2wx&N~PCPKn^Wdm*pS96ENO*?i1>wWFsS)Gta8(a_pWS%WV|ItOy>r6dYsh1U^ z?*~9MmXH|1I033l?4=i<%Qi;pmvqg4f#&AFl-;^ms{MU?8@4}fSJMvO zP-g~RYxg)Y%FX4UOf{vUgEwmAm=Q9+rUA!KGI#UPs(({IlLD;#0JHQ9RlA!GGD)@Y z_UpX#^|U#sVYbb_m9a#*$U=K&q!pvM|MEmLW2h~Qjvl8EB#`@x%2(i2GSqZf{vgK0=_%U;c7L&8e~Yw{R`Ft|!`j7(apLgmM4cYX6BBr3-Si6e zjKc`Ez@ml!ns3E@R*NRHy@&aBI+!g%+gmHltj}wvF#?GRZD<`0LAK$?08n*d21Sbf zfbS9#fRgV3l+ZJADg@iT9Qa`uLT|OV3*{(;{o|euO`+(%kzT=*6Qq2Kl4?#w>1miV zKYhyiH_3!uEWoSja~i=v_=7g$*v&h2W+^YyDr2e`Zkzd#?<$pB?_K>u%t;+Sh7}rwZCv%}F^=*1l>&%C!!! zO#j%xxSP->%1vxl549jU^{-A?kX-s#ms^k=`d61)FwU>bqgFm=btKg~eE#lc>g6ps z58*W5d$O>$b1RVBq+U0I78q?u)^;gPEwvrP?&Ax+2k;1V5q%wd;{HnY2%M!){7IG+ z-e^9j{A#4v&ryDMD|<-!XO|2l{e^&5EAT`5*o)~@>)&wU*{4E*+ZfBg2fXaxNBV(*sY$=Qs1 zqTsjJ0!fy75xgJ2J!<{-t*2OuM2h3EBf~P;eE2x|Rfw6}ft26xKwqgg(NtB`->RF{ zt7FZofLGy^TRqKOvaUKFx_KNNs6EzufDw&js7Iq@nAl3tan)Q6Pg=+SSEF6WVDW}P z1{TH9Jt7c}TPmGpnnZ@(JNdPMj1wUPJrv^rEC^EMWlli%mK1ZUQrk(LlYyLsz4=+# zVnwSUXQQ1)A01PErnoar$77_icNDB5jeiuryu_h>jFq7FF%JJZupEU?1Bp?KRYE6q zr9G%aWCJ;FG~eq?d25jJ!fq*puYHRq$&D5HbV3W_T~eR6pE9;WoK75WqpTpOag|6V zF-#|p3c_iKw4D+pH-*vW$0)0EV6}OiaOF|xSjxh7EW%Z6K}Jf0@H(?`Jyoxkj64tI z*!xZTM0+tP>c)D|d&)R+vJUpz78>mZEEs*De|?ERTmD0-Ke}w)=yKN`M-LPN-Es7h z?W5!5potre{{HC1y3rM`TBC;ui7JgAO!}BVde{mT=8ql2%&(IeVN+m30D z7qwQD28mkRu&;C7pZh!jjjIeyL|9g2LO_f*>3%q_Ly#@|K@B*x-;FHclG8}g~(wfU~I1oT5eNU%R#pqQFRKo)vM(c zin(vAzt~oe)Ux5#9*U$rIvdjb>U_)_>`Xg)HWC$#zozj~WYSt&GlAT|_UTGXP6gJb z+9=1p+)HnO=exi9-WX|c{{qMmLG1YQ2z|9Q*U4xkF+{2D{vgd}`Dp2!yc3d=C z_4MqsbKm9M6g!dv^n5X}-$u-*bMuJlhF(PA!MU#xXj#nlI14W3g$9v~P_!h%9R0Z> z=0%eiW9pV*2dblT{Q8LV>|X6wA<}Vpq;~Z3(r;0j)DG5#Eliqsk$4AKeQ#LrHKm-WLvPvLu7|EWQPOYcto$ppUnc z2l=ZncH_go6e5PZ^myeD% zL6erM{2*J}FMEABe_r#Bzcn3`JwIIaqW>J9iSlZ8S3Q%Qd^R5akmj>~>_2hsxZF&1 zc6KZnUQK&;a=2=PSF^Es$L3ilWk-jrp7YMxn6L1k$R{-4@7>=o{TTO8?JC?qwd1up zKg@pFrhQHKPhGDRHM_i;S6g0bdPY4apeW0lbHMTPeXe)y(Q&BR1}YMWBq^Wg&3-ro z<}-~UD^CdMam#b3FAEyatUVXOLyoifNcLpUWK(^RgkC!d&D^mUDz5-7+eHU@B+^Owq9Vh3!EU=umaf1=MVteOAJwdwlhg6Aepqsf>b{Ht zuzWeWp&2D%=7F%KLkb*}5m*=&Mem@r3Z--l-mP<`)zem6Av2eX4jEpT0l>EyGgwPo zqidUnO+wa6I|j%hzCOY|9?7Eu(uXJsq#rAK-BzpwAe#8zp<1J?Y|S6Eay?zn%;yuN zUcY;Ew%@Apx4-S!47!?f#HV!;cVL4n; zI6W?w6q^@_cbLxtsT$t|&o9IMu{Xe1M@u+6J`NXNcRs>M-ATkJx?mL=dx=`DmK*o| z_KyBi0At;i?+Jf*=Bz+$ljJM0oyjv0+p7TmZRTRdh=X4Opx;MBUiwz$=oBqAi*luK zB%Hk<>_4%@>BorwT>i>tRO12Ji^E(6UGs8&qSM3Y^6Ia}3gRZ`s`*d&lK@D-+@-uK_ z|MiydE%I#37Xi7J|2>3Qxg8xXbRAm$Ppb-;8-Y}jTfytu@*UjjY5i7r;in{1?Vmig zFt6FO?E`z$>fO`PAf6|$aJRC3nsl12E+v|Rh?aJ^B`B% zsuq?5s?*w;e%CnGg`_< zxQLDUo*g?Uq8<>-iBUcvFq%?Ly9(k&2rHt$wcxD~* zz4Z57o(c=NcuyA>EpHr6ds-h(55taltK(~zL)&GF1ni**v3RIhya$^`F5QDo_VZkO zxw{Rjo;i@iwunn(+nW&?lk%+O)xU%DPE{F!!k97r*m~s>rz1Xoa7Rm1L58o1f0IoP00YKkb-I zU3A9p*s~fqAfmO<2nf-~)BN*qe=?eb#+Yjxqw{NxWA6_PymJ9k?XE4TU(|K(gUp}; z!eD@)V^CMEg2$)^U>VJ&$tL~fzE7Am%3e1IB!{?Le%LPm-0vup0qO~!!I`@!0hKH$ zz}&;T)kn)*L^Q|rf;vV84;>d@ZI=Meq5@t9;B@9VoBHLCL!<<| z0d*=s{uT0y+q_E6XaW#~N61+!teRJ7(e|n`e>+yCDmN;%^8n0vf!@MDvU^O2T+&Yh zh#4pY#n89K6MKsv8Y$}iw)Ly)Puk<=kLhjp!jE9it#Gp+JB)*n7Ynz5?0KQ%4h0nl?ECszs7-pLZMQL%OY&he)7 zGtTbjeu0}O1efvFF)r&1vO5@8qbfSEx;J8@^|ZPtcUs-Y%j%w&m|B=-ThhbiK0k~@ zQN#A{g2~;6$=wy$Ij6R9Fq^q9JO)Z#$>AN`?s3q~eS2EnkTqFk1>0ck?qlswv}9LM z$#N*s7ciy@>)aB^J{Mb~f03>9%b40pA~3O=c<9M0X{czDiJrKBUc8i@f`17k{Ovd( zS+@nH2S28x(f7}fJO3SikfZ&!1yqVLe~M!d;BoAWCvq?f=9HGnsQpHX3qA*xBNjhJ zJ_lg{422fJeh&Z_1-b@M(B-(u5l7aQL3b{~zjuj&Z-3*V=ihl)=2EI!#@uiORwa|l zOu+T$-4fPdn`bJ&$eCtuEgeg2G?XoJc*vb4wAqEb&GhC(mtUOx_@I)@Z-mWHm1e?$ zjx*P#NGBFSjmyIV!J;9Xun5GjJRM!{wbYS~-`4zkpCl6}Ob?z(zs9w4-?b+@6i99tIGC<2TX@L^r$Ss&BriFEi0advSLrVQ3C@W8_RzxbaOKSL2zm1|YsvVEt*wz6=~S({@l0Nge4N zMoO^V>>NAUfQJi{=*d}f<9$kC?x|JDK++Ldj~b@;VbV;`bdH_wo?N6}22Hrl->x#1 zQNjG1A+@=bfbpjOwgwlu_2~Xh_Jrl*TLA_qXtSgaA zfK5gB7-UKMRvyjg!7=asx<@XXdCi@qh?jw89IBjO022O-<+cIUcnPkG6Za~3aLq7^ zEI#8<^UIOWc_Tbqdnj{dI&Z}%8@Qf*_H2GjW?gf|l{{nIFx<#9dQJSR(|Ja&oEA@V z)9{$frq9e+KV9mRfkr}MyQS3vg?F@s-X%*!(mv)y(Q5s=l?Hu!yY47Ddc*an6Y-esiW!X{tXd=$0Pp==js%5(|@`4n@V`_rGedt zlSKEb8N%w!-#>B5m4%!C0#fJszWC%cU&79OQLJN+zk?aCnN{7o&OmjYVvw2WYDKBmnd{k^ zpy`f(r*rfdEw|DD*h;#Ju9vqE8Y5q?JU$xAJ4OPbb5=v zWbzRocZb~4s#kF)WZEBRP5Xn*0s7GBrWVf85^_vZAM_FBZHc=#{PVt2ld`89R4tgtmc2=rysN91~=a-F7;V+ z_uq7UjcJ@ZdsgOU#NBNCB?Q{f2R;wv1m~MfO7+VryG#wXI$KELa;2ZW+LY#f7D^xq<5)M=^ks0LuJ-@45FTlMO_>`2U{5Gr8xU zd(L~#dC$9@_iW20VnP3y#Gsf(!M5uc$NoTnuO}T1mIwIbHVIekGC#nl(&}~QxN**2 z(7{y2T>Lwy)r$z}QQ08R;yhQAtO0N}jSzk9(y#Y6j*xb{wL9J-mk>8Ck`g#o`qgG_ z*)dv;I-kh4ek{=x_nG&<&8eu?+rnZWD-qte-_!&hZI$hXGC!x)^umO}t&m_BW2^-i zo-x{ITD^2kmXE8zNTTsh%FK>}?isiri8+i53Gz;b6a6 zekQaA$GIzIE%-zffP4(?fMcn^y^^p^;m1VI%B!6!7UCT|3ZW`?2On|yBW?vps9K? zc8uNMp?0*(A}QNmOk7;v1C@o>DA_Ef2TvxA@IYG~)!hW}zC@ZS)UAyaYhLI};hd95 zKI+(^es7Xm>Nf}B1Vl*!lD6^yKU4Wg?L<~1az2!Ac*5nIC0j@$krXOPaQ>(a_gKU0 z4=&~8n>TtX{Nla}o>g_w9UL2esq%+lJC!_=Sm>(eVoriJ@7vTSNMj?2=$z=wl4uym z#n|F4meoxnwBUgC!?Pkpnz=WlJn2{$Gqa;LmDG!Pl0SR8Ec&Nw=nzWkZ*=$(_ z*N4aB7OOAk*0tqg7*-5Dp0jVNU`eMx#`?_EE8Q+LpLJ&o$NIx-w3-dDDeD%?tL7KG zf?vsB6FVJgZEtI`_@nY>DTvi%HG5#rm>lsQnqNST9-t0n*pFb(-zS=gDf(q!>q#Kg z%2J^=v|-Qr-hzk1Ay|7=r+w z1tu!xk5t+in~63NH9`jqzqM%-`Ks0YQF25VjLkI0W;B&%kigL)ll+bXnMumXSihq^ zekiYF0u#;6yj^Zt7XvXx_~1EOlV0+IJPAeLJo5M{z1?#C8; zFW}ZXdsZ&Gps(bekXRp+<#D23eoOCL>g5C|4fR4lTAZDX(Ms7OEdb5!2$VL>Vn@QU zo2D}g>A;x|{|e(&_DYPE%ZC-?<1s-6kXWcExe#dBQWo;Tyq#KFm+^!c%7qx#lB10nZtyj- z)4LNf+)3S>o=hf&X0}4iO{kYGPSmmcOxOcce6+Ps(G(NE)`pD%MF99@K6x=ese61uQJzH+-#4C9P@% z(&T9c4`PyNHRno_(u{>u1LaRkWReoV?VZE&4h+w+8I@^GrJ3q`u>xTXwU))p&byI- zkYl=Gf?ZVCC><)OM)lA;Sw?AgQ)#x!S(=3bfoy?_MNim9OV#VWst#bR%bY;f0p!Qi zfXm<5R9YmNNGqgCV{7Di?U+a&)YVy+2?@>n1)hk3{F!m83@$W6f~&!>i_IytMv6KW z5Cp|Ek$-ldvJ&T1^B*}KJvOIOElKCB#5uL1m~l2Y-!X(02Zdwcw7b4Ue7D&$wwzZs zwa8krrT7RfnlpY*MU|Uk8X-%boecAcjC59;iVrW%EN)9#Bqf;7f%YUCFCI~kI?T;0Og&)%MUOn6N& zHGWcfWAIDK!azwJ!KzuY5jXowu+pvP_RLDdm0YcAM|%gk`T!C+#JIL6R;s+{uxvEV z%6=p^;&7*d@iEZNzDtE}ia`kun_;&2S?11fXx5gFll`!Qz)Ejqtk*nahr7+7Rzv4D zxpO_Lnu%CNmm7g%IT>vz7j=a4)@waMIRhw>up0c@^oYKG1T=Am_-u7_5kp(4j<#%~e!Lp>dl3=c zrp!-D`IB{|%s{)kFx9I0 zquW|#x0lA9LE|o>anrl0a%H6h`cxVgzoxq+mpVxr){>;8yCi2jNzSAxaT%9%#-gHr z)rRHIrikK8wc0CEpd+@g#!Cn|`CyKv#MlJ6u&p~g@Z6-7k4V4d_LS0}l=584k0q=v zv7(o4k%!qoYs*pT(G55Ql4L-vLGD`UVz{}aXffPwlV08<<#tK)GO;Snt|rnv-))-5 zoHREIUHw_oSYtKr(a7hGN00{<65^MCAW?#5`l=MxwaWjbBQL{0mq_c#%Ub3t37>W% zLkyIN%e=<=xHXFizeG&3B1|WuqLq+&-?2((lGQI+amsMsuu5s`C^%DUP+z_dPpahx zGS9#VqR#5fi7+2p?_wto!ajgsDBB!2yO(@J>#89m2O_Xa830dX-^&jiXwE$IffY1n)A* z-L|%DqHG$l+aS$|ol?ihDrb(MP5#>?MGA+=%)elKQUz>c#l{F5wZauwz_bf%mJ0NMxCEz_&;)?x%QHAQG zwpm2M((;c7Fr95-^-U`%B{I5qh@#VuJ32y$+9m>J_JCJ#Fi{=JfFyH>K&I+BrNR6W zC(*!FuKvh?DZs6mLMZksewg~jgv{JK73EeCW+hK-3H7X>Cm;OQhj!OSj<_}+AfvP+ z$>otL@eu*o-sVhc^N%F1b_J}x>L;oY|3E5{DV4|}6#J$P3yv0KAPj^sqzi166yqT# zcm$MK{6W{Y1Q*j1V8&Y)MqD5o)mh|&w2ql7$Msjoi(Fxg&bj; zn46g>_hHHFJM|*D7t2eNJ+w$J$w*f_lVMd~#eE1t^PMZL!NHh-2QP(}V=u1zn;Q${ zyM`yQ&*cf8V3cLea950Z3%Ii~6XOLgpGP7mJi<7qkSm=r=9frsC0)F#W75pFFPA0* zVR!h}T5)Qx@?UY~x8=lDX^!0M;mZyeyDIWxBbfO%Z;4nV9-#@o`Ca9hiG6Fu39*J# z`*tq3{SS+ALzw3xEJCX|RV3i9pLNUy_#UXGzIs7#NgpA1d13>;i+<+rMM(2jR^sdf zE9T#Lo1sob{wtvx##b*8t$Rc#cm#1g8E_G`lL3{-49U_V7Pu1|VFwAvt5~DY0P7!q z@SW+`ao7Z(7$A895Mrhp9Qn<@8^!5m?xT+SPJt{CxdBcA#(QHv_;t6?yKnhaQGl;< z=A6;@k5pW53hnPz>D609tFo@RawVPUck2ZK{q=hJT2b*RsT)$H<(~NV`er2Pav2R) z{DY8r&avtPVt=PymifD_N(kI12@53QRg$oulh7eA`UAS+K1{lstJys%+}<;vBPczI zbF8gM_Ev}-dkwtbyw5_e87=?dukq;x&P8`=ZB(0g)XlsaHoIEoG|W?hJ1eq~;x zzj2{Q-(htof3a-%n-M6#l#+{t+nPhGGLtLmoFCj8dT*Z20ba&Pzt9$zn9G>p(K({{ zVy`g_hpQZmlo81&E@PVWs>qlPA3`++`bfY2n(yu5QJcl3$T*j25@lu20^28>q@S#$; zERG>IQ$R221X^lMe1}$)PoCuDSC#(~`6pAiEE_xiq{<&-$)C)tJ_TGGI~`y@Mfna= za+2UaOgwcKZFNL+kWSF1Pyu=bEeai~ybidioWf)q8wv+76;^I;T3~NK+)RKEW!8rh zbGh^3Ndh3d0I7a8Sv+N-sL4&{ENGTV5?>&HWBfaO^Tm(hZxPEpSo~>Z1SF}RqF*E@ z+o;l5dtiPaSc=6fl1hU@%`wi0adv5V-!kIYL$w7Ip&x8?_tMuRp05nukpa2oW3-R>Z%$Py6YrFuknNT=6{0WhQo7kTLrRIfnG!cE}KoC7P!F+2PF?NMk8c#AqIwx_Gw|cztI>c3KSwoE*8tT4I+kN z68>W76EkLm2w=|!eYD>gQZm^+xa`f~cw}0DeP~YAR<{ zr(p$^9I0IsIkk@;t;kZXVm#rri1<9C&!qB8E%}dsI1lh5H;rD2bGV&-NL!hjM5Y;i zD9sj3ZCI2Z1Y(CCog}M_vdi1xW&(F$J6w@VR$CsGp0?oHg6XK?J}w}v`ifiRi_@l_q)T6YQxa>Hh`P3+>~l{db~GJEXGmNhvJ5sh$M+>bYO<4I{y^Zs@1ocvu8tfGm< zylT_Mghd&r0aawNliSwEO6Q5x2Czu)Oj{o_+V7~3vqc~GmJ%ig0eNIONhOqlh0!uZ1J?E2fc{rG_p;UHrblFtyZ>Xw)E~qylm{OBkfS~ z2o9#m@>rhMA_8=*=+{8DxsHjeyjFLE^W(0HmM18=g5#?JnfD*CF+sWmG4IY&ij zJ1V+yzQf|(=;vhqE`dSH#Ek1=X7{?u=5H5)u4;N!Q#*5i0nF^n(jA`eWMri%`1W*7a}%npe8emFC`_$US; z(${!$+6E#2LNoiGZ(2Ou)yz)0NqG1(^Y6&HHvbkA=*qvIRbMFny^C{myEU`_T=P%j z-}NnOrmHjm7IAh4>iAzhO#UzbqC}54{QhV0uk`i5iGN?dtSA1xU~VV=Jv#e3#3ZvC zCRY*Y*1jIm(9XhNB>Q>|N1+=2p=ty@CGX=77P#XOTmIqU89I5Q>S!EdTg6+{$syL`M3v(W zJ7SwUJHy(>h}}EG#5zfKhN;Q1&oWWf$rbibb98rtdpHaHq$7`@+pr^j-Ngd$fe?Fx)?Ne_K#(8-pPOcW7Y&! zw+n;R0Q3v6jO1wi+v+g3e~*9ri3>V$bEY##b;{Mk%}M&$=HI=VzY7QNmATWdb5vJe zW%KY<0$q7H`+vVsJiLrut=;;#8`ZX#q@`e=m4|l(yPcz&!r==4<>CKhJS=_PMI--f zmV&jO-xCjCaaCuHoW##+ynH$92D6OH4C9hawW?E=CQns!tHmrjE@#lZufyujMN{pC ztvZ3OEPctJI(yFX~4NIRktS6Q>rgmWI&&$tGOtJa7oD> zcY5IGQyKDiV`d*cKkxXYTYmog&j0fBQS+S|G=G8lS^E0l#Lt&;S8DgGwI82ySbnaQ znb>4|TRF7VTE(vR_6HMfd;2{CU7305{hgTkKfCo}1WO{@lymadi%H-6CoyyO{BG@S zlYP-&5PSP`E9d{yTQ81AIZIzBGxNW2O<3*MdSd2X6FV?-$Nf`n_I9SSx3fCg+hyI_ z+gamn{XB?3SC)R|SDje;KdYaw;~1PamQJ>}LsxcT>5`+Hq;l+S>z10%Zm?sw{|i~V z-QKo$Q}tkP7u!p=k2p!yZc);jWTM3&%`^T_+uNUKui3xQ-u^qs40NxbPZ-~UrIYOK zqw{A^xWv}Yg$@G4g*_H$U)F5+f(;=H=h+!pNU(y>?#rj68;GJiZ{h`SXyf zV&wnoW_ux+^mVeB`xolw_s-~vkuT*Y<#vB|bM<@0%>C<|nCqLxyvi)xk8%P}1>vBC z%gw$Qu^*gE*Em5S$n_OfKfRmH>*h_c@3pJ1)>l{Wcdh-!FjkiMw2;A(x7CfVs_5y} zTTUMP-9zokePesM^bN};Gf8Jo(>`cmbA5Ts>(kdr+%)Z0_PwjW+3pR!T~+75SiRxZ zWxsNhxQwcmQKd2Ld|Gg!5*p!L3L-iiAKlgEY%n*2_J<%JrfI9#M$B3DC4nzf&>Bv5 zZfly;ES2VTw|eBH@M!2I=}(!aeJ4sa!s>YWY1*uYccy9c8_Tpux60@2k-e9+a<KbVsClEtGyyFj=KG=pCi*x>}$JAno# zu+$0M=L8lzfhsE?9T&DH#E2m12fq9xC`%>f-(>SjYB^2&;Uc?X^H+yji)Ig&ef-lK zqys@r5zZD)AM?6qPZ$ZleR0`1T|^S^^1(In@%f4B=*%>zV>KVWEw4x4O`E=Au@KMp z+-UUm^w2?{zE>N)CHjUZbZD?vx9sU9T!lXRwe(lhH&-7@a9@VD;7krW(VL@YuSnI7 zpOuLG4}Xa$?I~AuN3YXbxkw|oF;d!m-d4`}*Fp(4+*NbZX5!AT&jq=1(m;{6;3G1G z_7Bq*yhng8ijJj=xJu=CZNYXs<}G4YgboyGq1D8k0l{&)STNEeT|<}YOmc` zL^l_?xq&_~Yf?GXcm60jH9%%Y=D{U5KgGtWgdWuogrbS+jR{T{D182@1dSWCS-Wi* zjpB#`e6;$3>Zp`gy-}66UzN7qDlLmtf_Zkp%`%p#x<_~RO;<%uE;pZKx(Yusry0!R zP*an=czQD@&A_42*1;B3eMMKe>UadsgN1D-B8aA7YERWdugShfxhHwMVx{X#+8YxL z-2AxRm_6-{S@*bV%qHzNT}qDXdwOoj1X9qDSrHnd9}vpXx53CCk4SF71(Jv>M`5U` zaBDWiD7_^Uy#XO#p0jSY_9F-F_<8oe#vJ?m%@R*5ikD9$A-!sejhh3-g#7?kE1-%? zkig+U6=~s)Fb~N#!F=B`*u(4(eOKy2xnMr0aI1FPPTp%?3KkV^4OW2QZ1cw@STO3w zlfMv>vqmdN3i_my0FzU*gM{Y^WV0kF(l-C4r{#?^E(QTQTWHR_h|HX7qmCMqFz3Bw zOWVnA-Mb7v)UG>)4SQE-K)?XJ!vSi5%Vd$BI+m4o@+$Wv%jQm12L(i8Zzk4fx1OLJ zue^v{1gGLivCu)B$QSS>LS+fTV!?Y@T|UG?^Afy=$KCg;*!u{|KcKhaIQw*P%oSQ} z7NiOVQnAT2w1VHPM0uw0$s-E&HT!~@9A#Q70J!eFaHKuNDYz%T-!)8lR*0Zw{%`6E`Q5_J?^JMEZXeM^<`mkTzuGK!qSPCcy|dK^T`X*1nu4%v&Vc+iPs5n5CxyHoZm1g^zlsEK^PCf(Mx421 zceSftecVBp(_ELUPK%$WZ+%+A+!)ShN%L@3-Ec`DNu%ZfUvn+Tqil`Fec5}xo8%;l z+N=zHrKFPB)a<>1;oeQYs@g1Ht!D@#canFqIrvnCO{yO84b{hb^_{&^Cyy^T@8Y<4 z$ek0jS9v+t?DCZy0=V*I+C`JHQ4#IS{hk$k!yw*7o|z9-lOYM&q~kO+g=$c)1e}o$ za+6M^f?++nFQ9Orp-}GQFV)v~a#FM!#bhT#Ooq1uia08GPvd0>t?B@e?xcQx`Z5zC znPKFC7=8By({oBYYBE7huha>subZ(36=Lku-a4GGlZoIkZV_hn0_G%Rq-S!X(wF$! z_(XX|XqBJM$!vN~bKm6U8tflYAlEMRs`T(O6M{@WqD)Ouc7IG6!q(GvXM4l>9971Z zxR3F)k0`4rNIN{{@8p}Dw*3c*VVy8X&R^l7A&!8u`%uoSD*^*$kjxmvWl%Z&`Rbjb zC!>e@R_}jDE-s>f=N`-LYajHAJe~bZ%%4OsRjW&jc%sHdnZ~7A)rYjNa75s(dSld- z^LYX@5q>;#gj#tH30v=Z@*dhTIJzqxNu|yz&^ZH6q`MHiU+pVHgb7jbo@rldn8mxC zGLUV*7w|5}+6@(O<)$2&6XMvoTY49VyE&iZf~&Y^|%6tVX+t?h`^c zxdv5T+mKe7mfsM|;3!NqqiAQLnya)WQI5r4(!e5wB`druyc=ql1n!iqBA>J{`9xhqelwNeq6x=2e54D)mhWjS>4YT>?IUIb4L$}dOaiXf0lrtsR^dW_W7Mkt1C0t%)6S z{`ft>GluJjqKUz9FNbzt&4~BH;TUNvIiyxFY{yk174$7q36i=G4tzp=jGc_7Bvp{A zP>weDJ60KgOe*6;&RsUr>P125+`p z(Rb4?3LRjmeI8K}&x<$z1mlMTOVzRI_xA)ct1HO#t|0f39gwY<0#K9uZ!q2Kqh?AZ;~BEJa#!ST;2tT%6KRGcBc5jh zcLGgJN`dD3ywHL`i;t3<0shW$XVvFFO_x6QdZffvzk@&VO!@N5_AhVCmpA#NjgCT| zWkT1Y^lfq#mY8`2I=ARMRv{<``1t@g#(I{AxNKEl9W~SKaj*=bbE9ZrEu7~UDq9|U z^@Ne~alrHya_4wqR0{{>YP{9zhI09mI(>zS=#?+SO=tBt-5?x?CJ(?(OJ}rF>SB)aVC& za0#y`^iG;3O@%a&rl*NEu+@N06|ls1^@`l9)WA#J8AFs-_q9mY?r7W-dSfs}Rsl1T z)f|ndUmQBv2jwBTTBG~>Dv}0`WzClC7~>@+@8x-SsGgmOC(o6;9NA{qpLkDO{Xg{O$! zsZyM+4xneRP4Rs3i2x=_{0GwS8A`-(NEKo0m__lJ?BFe6cYY2jML-O(?btkk32uoh zu%m|Rt-KYnvK_VEb zl?V5uP0BLn`M|Aw6}$|=y~5Kc8kDEszG0n{L&*)LwRgjq;vChd;GWakZ&{_Uc=}#kjliOx>z%Myf z4mBm17lMn8*`G+%B=omAR*R+@!ygkjgnm#g%!7Snzl1x*Ksr^vrD6TG4u*%t$YcV+ zU!V-nEuocHhqlOFX%`;QF5D_cXY4W9O7iXF{trV#s;t%5=`Vy{PYa|0HZmLgS{u11 z`hiEuo$7a#>DD5`CX`6k7UVHoa&f&l_n$71>TGR^>Dxp%VdtU6+THurQE~L=uF%Rh zR3DI_cH2qhjXg`bQvS7{t^5yrfA;cUCvR+wU4C3H-#hyDzx6rF-z4QfOS!83s{F@9 zeCH=ljy@*zZ4LUh1yi`hPhT5-w^!sRN|0~V!prDx0aty%8WqeZO9vP~NP;2CASU-s3Yga@&otj#oqsrabjB45@xYHDeRRx-)bTBCaMomvDw@sv>0w|Kjc`IX7z4@k*_1 zTlGOj$Dtc3RjV^(vg+|vKy8YL-f)N36~rdk)p`KlJlY|UG*pH`Sr#@+rFoZsE;y)1 zNK3i-V@-${OO|8^%)!Kq&;dgha$;ksy1uh!pT0+bUJE}D6+9+pZp$fF7ewQI;y-Br z{*d#%9_izfM9cs3=Rg0MRG{(o4ewUJ&eb2cMm(2Ft8!OrCEMa>x96TExs|Guj1q{( zdrL;kJh1ZEL>>E^)SOYnFftkajQJjwfpNnJY9Q5aI7O8~qzEP&Pjjz}ar=|iq-JT- zS0w)wYZ#WFfS@`I#H=zOqhnpM5tPVSzY0Tbh=mQVQ&XN>SMx{pQ= zI`e1SyUw3!p?*^ESP!n7$H;}qS)>RrBF@U=CdgdiS96s$X`mo+Ph~tU(`Rb(k9o4~ z?Q>`^$XwtOsw2@oPoF(X3fzuf!*V-N+#{4L#j$(i(JxC;G7IQs7H~94tDjKyaxMA# zTrDKfse%s#ZI2%48@VV^v+>p(MMAmj)s!yQi7o6SB`NOd>xCnxw~l+}lZ1PNO2ABw zlo$ImAGp&cmqlH0s%NKKu?RRDB;<`8B_QfDoufm+6G5ktpdx< zMFM=Ko}`1fqJ~vrv8_T079HenvM>{OZ;HlKXyztUO+tVo!Ou!<^fn>R&>O=YG5>b# z*JPKAHMH>11at% z_ZBy8ML5$q)qC!}7#YYN`t8m+(Ls&hb+X-uRT+z!@-GRx~mmd*Eaxakwc9PtS zSu=>u5YgP!2tBXzM% zc&jcnpSn{83(0EMg3MCcHg}D{=3ODY+`Q8&BMHUf20^kGem@4a@1iovCB$@Mb<2?@ zEj6u{b?|&Cr&NVFxXwl;#3a@IEIFU;XF7sI~C#U|>mRRlk z>asuk>^H_mtEnWjY2iQv0mFIsTkm|o&-s2g0msXY-?z86V2LSC=?47Ei*4WU!cI=` z+<@Z*AB<)aP_E#y$X(?GKP_O-iRTbl>UJibEDI4vj4!js5fc2pVqco*iT_gB11h*! zsX-O2p_OW$Gd2&MRKFh7&hW*AG3y&tIDSjL%} z#)A6x8NT>Mou`&Bcw61($((Y>DSGpp*yE7KtP0e(SBT~@Cx1nq$fxz0 zws+3qFTNzrZ(rt_GVnoPr_Zw%pH(>jTcZDkxaI7c~jy?Y#yort$_lP)BhS)~| z`<}48mwr&AgwxB`d#1dT9^s)Fw!n6;4COsQ{v!LmnD-psOYHZyX++6iZa(~kB}AqJ z%4Zktw~NjhY88d@R7L06j#LJ;s%V*^6j_nk8FW%rr060^Uv7@JiVCeNYnwNA`oNi= z<9;RPkGY@4Yp)bIuZpa5`ZBBkG+pnC>HN{7=gC@vIVVJ8se$2Y9YNL3!M>`hH4U{s zxg^aU|NeQ21XHo6M`J#0+tmm9&aUeZ%FQ1y7Xs<9TAe`VWz|L2+Q|CG4c zc#?&SwLEQHtRtv!Q77L77xfa;6E1}2?D^^E8Nx7&f0jEjZ>({Wd4uFvr=cz;#8mZ} zHWf;5K*wGo!T4x%EMKil<}Om{f+s4{(Np#L9z4-P-Sxl2iE2J@vIt3lNJap7T*L~X zlZ1?Sns2Gaywt~9Pvg_=3Y~`ey2BI6Dz15H-ucE^<|`+%X6-U*SqmZ7p?%$*h-aFO zyv(>tqE}eaU+Y|t%k7F}ITfK?7t%+yMg&0o_?~Mw+NoU3A^{|+wcg2Pt$4b5g_3G*OJ+jv$!ZCY{yKJ> z*gsiMSRDaq)iD9v8Jc6idluvSkdFGg;A>1^h)74?{mR=dSG<9U;XBj`rB&C??Ma1SPiwm8k9Qk?bZNI*! z+zi$!JacJe+ERDy8<06`EpJuxnBw4RpFUj~oTY3$E7qAhU8#lt7o1Uw?2-G}ZkEj~ z-Z9vI6t0X%r@Hb@r)Vn2f;FeYI?KgQ;xHOdtc7 zTDOB{A}~{0y3i^hep$C*#Y{ai*wn6Izh;3AttwF~%p9_@=tWi}mFt_~oly%p=dfyz zyHfg2RIYc2J;!My3)@B!a);Y3q~04Ju@Dm>AwZ_+O)al!V_NawVKbf)-bjP9wXm$v zQ*@}eKIzP(9M*sTuH}Tcr%PL9X6b!>ljR&#W)fF|w!F{0S@KM&z9)Aj_0JZ{QmDvL zlZ1#PVutWV#8RGZJhUxuvftY#A1q_yz~8KP{k@x-A8rPSiC#5*`=6_Mu~qYstdwF= zq3ZIa^-{Z!ch*b2Psm;`^@Lg<+P+>Y3wNiimkQo*8|4n+bdWa%#*IEx2;&N<*pH$c zZ_E&bBXi*>S=Yk&<~=?#zFC&qtDwg9T_$-vfyCR!+F#s8FyIe8;~S@6=hf%Sji;Hl z{S1uIN$%Rx6dh0F72bF-f1|!jt9!X<$LwPbK?lpkDYl;c2Ltre3dJJ?^VOAYN99`7S>(KmeYzAQ(5BaMX7HwL7yOqVsTUW)aB z&fq{xs}kS75SmNuw}XEW3A)^2!C*4OYj8xo#mS0hIyG<-RjsjK2CGi+v(e4qseSh z#7Dslt*+9g$3}$S9*)-aaN+7lagn+pKv3{3Jvm6aD44C)omEPbtk7G-q4W&WofzGj zD%I)3)O>udgvgj786_R>p6J`DeYg{sejX&yiON#Ij-#(j^^c^x`$l*A(sxVdctO56 zTs$%fv~xgul+4x#Hf~8@A8TM3ZByf-Cn#M`3+e7H1mP=>bdFlebMZCslPUAg*Ix# zsh(F9>N8$Zs9&MowIZIvjkv6xs@uq-gI2ex9E2%axQGrw!+fBx(`shmNRORO1kBL7 zI5N*&*sQ;(mT+q&t=Nqx7B&Y5X?1>mNFcmXdg$HQ7AbRZl@zVNtG^NxhhFXGs<)*x z2WoZa=%0*oI%t>PlH5VNstzRe(D_ymy)zsl%^=~4(YLG~g8bu^g5(~0sOmsBU36Tj z-Xg-HZ}cr+`bVmZ@@c+w(OYTJw+5uYC|#sJRI{XqE*fBD1gQQ4sySh4jw^CWOK5-Q zoXp3if7Fy!d{*-M&(J5g-f(&KC#t6|GmceE5@Xy-Umc_R>NuPqdMtnAQ_@v*n)bjR z72Nc8dv9%K+3KkoR&Nzpy|r2DtKGGd9(#!%)7R#%a32VLa+>~}c2`5yUU&9Nt!`b_ z&R$jfQ-b}%YxGt$sbBCRd8TuZ90AbH#{9AZ0>Bek{!FTr+sQcKbtosVd4v zxcrV#q$n4Bixl%MoErFYW2#F(SHHlcJvuQEsJ)`sG<}j=Ff2~`YVCK zh1-JP)9Uht^Ws+knp@1Z@PbZ7>g#e>OR-XDSQR>mLT^-s4sr@@OifV*a;f>3twKvx zp|NQ!q{!c=$IwDTCVdNIB8uH3gzuCn4q$7?q!Sy300tJuv~Vj}CJjkq9}q+kr|(t5 z$=dfY`vm3Ev-UX5?w8+CO_Rv+vxZPZFa1F7ilFSa@MyRH6(3erk(=5+K!{bC&x!mE z9Xu1MTkZ)S7dm)lkezsWmFF*Y$5WQ3poe^lu<344TIsIYsGA6BE&NkDp062^BL6~f zc+ET{(Kc11*mI;@+6%6u!&re0gxDKI;mA4&eh-Q7DVXl)9uI2gRl&sm9kcsO7o(WI zE^rkgJo{J#npX>N zrd&&bsagrz4kn>(PAb&ljSrT;heP1z+{WN>B+Afk|2?yURYhqa@E$_$CP5!P?p4dk zLn~i$gmmcOW!i$TBd-yU%X&ZDtC#0jnPT5$1rj?X&oa-$sZGV+t1t|jihZPW#ohy> zPIleHJ;|}3px-1h3AZLC6i<|;h2OCea?nA@VEnA)$ZT|_#%^S*>9Uk32i(sJ+W*C9 zwTsn&cK3a%SX8VlRtYp}Gcd+TKmvVY4-$CTAL~!)54&T>@L1-FwOC*KsYyJNX)(@b zll1-=n{p)Jjcu|5=`nGWF2$a5nnPPw(#D66iOHTx(x%1!V5Lo4ni9L$3igiOX$ATb zw@`v9PxhC}HzT#llMNeDv10(LGL(~Hy=0ID;4-=V1Wzl&X~`L$2adD}l(e*AQz{~zm%kCL zE^hB52BRBE^spzk&Q8ns2J1ToOLO|M6~rSpqXH27J?V(;AG^c)d`zr{0F7Q~eHaj* z$7gM6N__Uiy~((&cZ?fzB#USdse`k*DaP3XPG_f4><+85B?-BWhx^9Pu@gL;;uKFZ zua!&~J%&*$ko(3x{7qFAjrAr@-|B9Ghd&WT7Cc$2yUaC8RMClc`~ekzwpMrU1!7kY zfuA$-H)7vc9o#W{;4t2T#ai7hWI`7f1>)yNccjKIr|UBEWtKxy9XE_OEj&YE{`3nl zYn0k0VR~!qBv2zlO5$hgyf~=W`4A zt!1IsuLZvsYW;?T_{wpSxgr@`)$rqHW|V}Uf- z!r=H&>$EmFX%DByenBIar7B)XhWce2>PelU{!cR0hk%-#s~J5YbumT7wby0d4Q=&! zj~uE8-WTEdfnf7ks}F<_S!F~AD^diRPCe-gSrB1atB16(jP13$lS;9eV>N`^KKwlC z!;h0cJdpH(vv*jU6562#6*~r`x2CTbZaz+z5%DRhu?P1e;x|gFcT$~tL`l6q zz12z?_Rz+p&OW)v&UUhkde>WWU!&7^OQ-J#6;(x|%0D3F-bO9x^c(eKw7a7EjY!6- zsBoUFiI6>GCm9IZS}$fyZMnO)EJd&Iz(zF26-(@4t>k`BWg%-TJg&;GR=qA;<>kKd zl0cwpk6)`>v2bEw$ik|tvPZcZ-JaSJ?%Hpr)Q<0i1AIiUWuADNz($By?M!2mJeXCr zpA{N^0;+kbx0g$KVlN{Q`>8|?ccLzks1Q;4FX@N0y7w3+_zMro__ALqHk$4W#4pG8 zOn)U7rr7FoQJ+9xZ(z`{qdKeUIAB=n`f z62GZys)2yV zPmCJ0bp9t*q;gE9Ph<*5nMy3%hI}nkNi=vVjm-ctSiz> zxsDXi`0h(*xXp!Y#2@BmN_Nq!YHl~xY~piB&Ddt6vzMO)!YaxMnRhTlu0FtFUWnPe zq-*AdPG;xo!;+q-p`_Kvd(!Wzu)kar77P6rx#;o=P|79{CgPV(TV$R4{4n5 zou5BDO#0{gF}V)x)uicXm$8X(1K}oq>+LuP=C-8wRvT`D=T{iZ4CCAD@||#;r@Vj2 zFU?Npz({@;k~Wt#ck=8=#yX7X1~m|;B=Tc?M}&-`5)>$IY%d{>n%enJ~jLV1#*?x*8^TH=bn@0s5C z1Kz9OQVU6+iOf7b;eJl5@)1}6Wa_nrx~cEdhXh(;_21b$=o)cAYxZ*JW#^`-s;K8P z+JzsfAyTvcQOnNU7dO1`elhyKxBAc%!{Dj~Z&C-X?k*{E`ZH2qZlk_Ccf*{ME~);+ zs{byPqDE3ws~SlPb`5_bE!9HeGGXwcs>E6}yE&}Z+B;HzwT1Decp}>>hg|czS=Gfh zqv=fop!(o-{EaLD7asP%?XG6jn&z6DOPyq`YxI1U9ZuYhHvaS&^hTsRC8+zD;SGZj? zl50@&&BrqKulY7LDBPqshqk)3MPqr%-K4L5OaO*nb+v5QU&~#sZ(`M_`?dbB)~wMF zY9%X1aqwqa z^A$taBFf4C^M;`-*an=vx`@?tvna(T|4Ep?{>kP$y_mHg63A`R_Yc}E!(I0?y`~1d z^NwY73HX~cs#i*}qiWv&QQvrg7a}jId4JxZ>Q97;ZqBZLrs|Qm_Q!>`yL2cA^J_+;LW-0b+jOQIS!Fm; zjy$Q5qG8xfem?VT>P?$j3A1h>lvpTTpB2#e4q7KvaPx8COW_jy6=nqn?Y{YpnvL_n z0?`iXfdt%}q@PyD&c*g*R!Hn#<^N!Pt|}S55&u}|Hv{|5N3ANq45EhQugTvR%VY#z z-z+C>45n2THxn}NZClgi|2?l-im1&FGbW+;eCE7EDXtk_X=;#=J@GP<6-&(EyPE$X zBX-YMfw|oOCwL=T5hTjo%ep?LN;`mi_OYvfwsh9=ZA<+9yUg$OZ!4y6doeGcDaC*; zdp~@(Dq@1UqtnHm3zSt4NPDzKyM z_+WqI2ETa*Z>s#W2*`;59seb*_mT58v-QpQyNX8%(vPW^fO+lr-Bk65WR??pg8f1X zSmuui!%&kaKGuAe?w{e4)~qHZNwn~f`P!5wxtm5SQf?ZphUJ|g_Xo1RKNR&$)?X+$ z2THAnyYa&_fA9`039aQ+0ptEKe?qM+kbNI0#)%SV^f3oMjzB#BUIfJUg%^3k2&mI2 zwzh<0R4(9j04@A;C`4}@tIy6bF7g>ut3PHtxywaY93 z-rr>Z{f*3D%o(7+YGnO**wi0;^u6?tM=RZ;Z!t3J^^EGsL@M1{xM%i@c=WRBwcG2c zW&S=;Rix%WMkh9yMn-kvrW;PzGwPX|YpRULPc|;{vKP>FYq$NJpwIHw&=Ksj|Pm#k}xWectsUmf}fJP$#+7p@ETMJ0sy;nxVQ^s@J5B~wZzXsmVmcCBRdxX8D> zm3!m;7n3ke-yZq4H{RPoH107{hM}GD7e`7OTb=nR;Aa)GQQ}tsmi{bk zhQ6hcM(?=FJ#nvmtL9zb6S=`_d}$aOO$(n$vjO%}WfZCI4bAhp*i8f`LJdB{mA{75 zSjs)(ggB$jOM{j_gwaoQFs_GvW%@wal`49Cry^B#pYf6K8E3&+Bk!3&|f>?Tpi$Q;N_fYOKNpI|qwk2KFbq}B@S8??Ih z=738iy1wl1B)tl6m|=wWNcX=Dz{-Sb&-nK9(f%zk>p??9FUg)rU`D zoX5NgQDFZ5ZaRM)vmq@0hsTl1o`u{CYK-)@~n2 zf9V{*^J*mPgnH2%vP4OLMyrxzdYJI4EmY6oU~@8Tu3SG834s0q=n6j>Trmz0b3Gpuv@1CfIFr3(5=^D+6LR%vV`g!m(u z7QPdhh#X^%*ZdjLGyFpBcd7(hc%gh`s9mai@t*0ky!sTMo~AdlHw$@@dd67qbO=PG zBl;ndu{APtYpcF;)2>LFEFnbzVta_*@faJjsAlsL`dQ*J%V$O;y zD%=z-6JfcO50WH!jEKx_@sXToQ}~J&zFXo~ddF7oiCpZBpW8v+lJ`&gYa&0ttmLcY zmx^m)xsra`;=&EgF_&x|OU}x@`fK_+LzBV7_pRv|A5QB6J&pTjupX#NzR?e9W**N# z)<~@%pYls#qn?zb#pvBK`Cuz!4@^EOu|E7#<-qs_H0AFP38N?W zrXZ1M^(7+2&1}Z-#wb^(cE`+2h}fJ%T1DeG5YSsgtFqNFA&Jei{sQL?`N(E-&;eH? zQ)b{ffOD%JhI7>t&Y!m`=58gz{M9}cULxTitFXg5m_8YVGljgBtk|elep>vU12&7E z{tBODL4Nfi*`zf4J1XKy+4bChUXtEi|IOnc-2mh6W;7V@JAI|3=ETHk)gV z*j#7oJ3Clhy|6!psC-OfcQ&|!UowVcSY%8#Pu-K^GHV^ch6UK1>qOkBA_C?#Ct^B* z$80`fsL|@K>}Os`oU-u85TM8oMn3D=^yd|YJucad^NrD7hsV5;abB~J#HJE8#S=Ox z;0`d$sKytc5CAD1M+}TlMtH!_Jg6%H9--lV}0f>*v=gE6R|}6qKssj3(6?RD3u|CdJWAl!msrj zACM$DE-Z!Ej~z?F?>4URHI7V@AYYZPzNS-GXa20`uC6@Sv8{)YE7`Js9f3t}Awb&= zYmZ}CPf&*SHuIK0i`;1X01nz1K8}Df-)E*c z5xog4EX^u%2U#mv$w89Y9VC=DGB(?MfVl#rbcmQ)@QBN}B5EwCVAA_`*+u@AfN@i^`9Ds?PY8r=Y86Ji=|gj#6Md7U>(!z3G<};n zPYNIDOU&_FWA2eYHRdibZo<}9gYIuQ5DE#zPcXmC!yX-fg9a>osdgfWJrUW(! z&CgM+9x(U4Z`X7`0c2mMs)ONzP0Bo?p8A=a_@c;nGXY0@$eLP=wE)DKgBLL4uhtAb z@?5!f?6vLc;19@F>^a$$Gi3c77DUJ@u${|?SXl}riccBPrOP~iv553gqfaFKZc|PC z^fAgjxY@>LRHikRW|B(0BJwc2P4aNntf@S$zE%c*e{5Dlzx+Wo!s&de2vdl;XP2!x zbYH+>UAIV-H1k3|Alwt`7hZ$r2<%#}S zo`_J@Ex8bv-7UX<&qnKS2*C3H!^7^D#RQ#NID%~!aSFwA2-s3B^xjY~=dBfcbBApC z5nTnMvRl!HJOhF-o;fzIhp2Z?VAexcSDe9T0OWys$(CVnBgh0y_HrK>A~I{%!wUHY z3i)f9^-7XI`dhL@_{|;F?==9*_z^36gv@hEYkbphjPT`ebZ;Hm(!vyHDOcWeaH~-& z`)02awWEL2I@PsYzGhR0n+^B1YYWtFpE8MKW>juIm7tY!C_&DD<>=QuLh2M)8mGQ9 zVw$Lu%kjomnwf++;2m1ZR$s2>oegIyf2Ni*hV7y`69coVMst76 zCcBRbP|30m0w^6yDKkH6MFg=;8t3rDNr~ej_t34l{Z0zqiv01KbpnEuP#@xH>$JZT zbjGpu+y4r=Zoo(EBLII`OHoX^p7*vPTtsc&QHP;_mEu!=3rN|os2 z2orHPO%3?fT1bfCNomi1Hn?NGwl(Y<3y;*W)4FTel~&zk{L)>+c2iW(4LjwC4SS0G zi0gW~pxo@m;qoz=T~?hztFkaP=IcGzyHIsV2pC;D{S)M^qmxzd0`U<$HdEt-E+S*qlj4WmG!VYzoA)MI$l=VXH{Yoc+LE?-EAUVD6~>o zCCj{#5emak@u6T}rb2(YabMLNy{drhVSsc3ESAxQ#WKtb$QSv3>lN(G2sNs)&2ID1 zes+QPsb4IbOu0HdqL^~n8x995Asu=zPi<()wDmz2#3eF4+tvq4KUjj^6DVG4DTNcI zqe|3v9_th}q>~_B6vTRT0SZI>Fe1j4K7qd-o$y)pQ8T73;5K4`+bG zJi4WT-Wa0e@xqzPiO<)0jG};<`xf4Y4DmLcMhJm;zNFMM#nFHnU*;3nOl_H;$1$~K z1GPtK`82((zn%)zoTgGw9&;d#uHK3BOHAVm2xT;Glp{*}rREciQ_5q0c~H zRo#?7@za-oVO#m5tnw8n$V&5MgilMx_~LF#e7(Q4_*39}+fJvwFA}1?M=tNaZpxee zY0I15R^Iom@{UALOS>t}qe}Z!{JMXK)4q=geG2+*=%&0S{$%>e+ADTwF?=u-nNoyx zS+G|OT{-B|Ba)ZhYu}QE65=3~eK>L`gE_0MA~UUuoXHZbDIUGTtIrZ=d4a(UN10zw zA!8m>3G1DDWI1xmZ~E+d*y7`G^5ZP_pyQx5_u~whkty=>BSN(Q>uM(!l`q2F6Vtc= zp(&zsieE3!Xk+6YPVq@%GNQFf4yy)-p)aTWAGMWVc~s>$cT;}f&rtsUSKHc8i1vRK zTOPY!Nm1F8hG|}`8ei7lco+JtvyNEYuT$eco&5Zfl&|D>rB(is=-uB<*%@}(hrzd_ zAJf~)>;37<%kHMU-}SZW-5wueun#qE$uchS8>2EfXGC`9iEFC%9c+!@Y37nw>_Nzn z3E*6o0chJU0dvynVqd70lXAEyb^`7nF-O$u3rU*4ak5#?!Y%9`VH>$G1HV6ZmdCx7 zYaTMo&8rwRhgNZW1$`%8@l1SwH%Q-M3;|J0hAj0_-WbXepJRUVGPutY+TTxzz8|et zJ<|0VI+K;+vw-xc_>D^}z%uMB&d}X*N6iRNo`smUVa~jNV4a=5L)s#BHgENHA&8{) z2Sbff++->TI{6sbGptO$m&2+be;KFqm+$8F)7&oA06(VA4RS&#b?T4Y7~0l|0;>^2 z=>~K!t2b%GCA0+YwVU7xkf+BMP?t<|O`oJ%i#s*M8InQ2alZKi^F(SSxsibQ(4KN4 zq6FGK$A565|19ZBvpQJ2*v?tz19F&EX-?vXfW3?)$M&7v5U_nG-y^GXhD;-X?_>fG zduTb4pyTvy!)Nt-ISe*9zeRt+K5Cz1hiV}{V&(FoMLb@{dX8A<_JQ$oJUA8a5jB2N z;s!5gsQ9q>7_F4|)@nXE23VyY5;GQ*>k?$_FW06BH4&7KDD(2F7IzcrH#f3N&`4ca z=BphO7-vX=VsRB%-iyO$ox2?>%oZw~Lr7mKWBs2}17L_B;fX*Ml>pXAAre)A{v)MA zijHwUNI4fvZF(80#w^yKX|=MplvAdI$D3aQq(bEJ1mL`5Vtx6hc#R#AfN*9)C_~MJ zOfui8a2PE!;*(`EnY~CiiRHKl8P#$46?`TfW>ootu<>gFd> zSgr;RAY2W6%+PV936BCSrwhf^L};Un@*D^j|fHnY1`SB;nZmNacJ7czP1^u~# z{tpR>3nuPW10>}!%LPQObxbG%NqHWn{QQkGa?Pihink5On zE-4lD43-8AYZ~b(ZbVOw^m^HhIG}c9AMH^(a+*Fe-Rvc~)S|P*76*PT4OU5$5hTm? zIQ%k9NM;C{e&h_>SxazIhY149jWQQh3Q{__QFhOFM(y3KC(vp}k|%lO?(g76dBn=x z!&D>F1u;MQ72>3i30MTCQ2Uq_V^N5TS?a{J5!N4_7@;tg<~}E;!HRJx7%G&$Qf1kY z7g(!(0;k;k$!1tH9H^pT#8v~3CMEkY zVA!2<6+?gXY}QT0zQ?jLWAqSXTtQ*9@>^Zu=D(yGGgLJukMF9|)G|kvD>SEc67f=d zOZp%nm7hnesmA#q`yqcqw~9ON57dK;Dnh#{wQE_CacZr{XDiUWiX;Dw(OJg0?55G# zl*977EJeI4#5O=Id7T3zrTaN0@?rNfJZcL`ljKtQ5HDnGwn9plF}E|QDALgaC3};} z-3PK${Io}ODi)XIFAmdi{DjQ2uB7;n%f7>|BRb`h3YF2a5%bmJl{Gbitaa3Rn9jrnWD zahMujQ|XK6%E6*)4stLbeI1OZzO;~At;`e2sqcB5;^knB@b84K)q;?|<|)A>Ox^11 zy5dV#Np^H}k3+79)IyMM{J|YpNp^H{A7^C*L)|&KomG-cQNrcsfek4Z=Oa;&86r`T zC9GG1Ny33lMMM1;p^=qMKSwU+q$H@)F5zRhrLQ z3Gw=7nE&{Yb1qXU$Atrtzio3LkjWpJhA21ptnZOb-T@2Aa~;Z)TxRCIW|4{NZiiNm zVO~G%VzFGjpQ0CUn2G&nnIY~(Gg{4dVr{y4>s6r}A(`vR8e46B@td!(mBm^shi&7R zdYfyrBnpC_2*h$EsT?^bQ@6}tB5+mea`Sg8qqQ4s=qAY_|3gh`%67jw>J8<%UMh1v z1wgHMlTchs61(@vTTd1Gu=tJ`HOnVAx#pUJ`_^TAodby_%^ zm&Vd;ckFlqsO{sRNh=qGm@U8`Q3fz%m<3K}@w+-QUIu^Jn5qAu#0WP=s4~O^E;lDw zs9}T~fX=e9S05lAGcE_{nPv&Kw#>I;LRQmHr(sBgOqV`byKA(pH}fSPQ5Lm%CW)xg zdO#?-@)XnmZEMeb*bDN-{NN?X$g0ibtH2)9|9Pw$*J^6e=OmJ9ng@1}i0jp2atx~Z z#B*&^+D{UU-AnV06BuvZM_TzuP^6UnGcNX-V~`2v+#k}CiY-JdK*XkTx#v?DN;YHc8vDF)IrD!9_}N(`OfWRdP0Shs&9WaMrN`=yVxTO!!udF zcyT6{vWP1Lk@>6Zln_pD9LWe{a0zA2@pWC2ccZeCrSF~f>d(w^Byo1vnYqe~99@;K zY-Bs5TCcvy%BV;Leht*CHS43INfVCo%%t@nOl%EWAoTUUXTcYQwU9NcxMQ64l;*el zF^px5xv-e{V6y}}AW6hsw)sqr)t$F21YLjpfzzE~*|Z&6sf55bvl#h>B(bo)(2~3$ z{ge*yGHkTgii_j??VP|s06}#ZE*nJy;r`$jAePN+4=0s)t_9~xFjoGZ3yo=ueyy!%phRZhQ}S7M($%t44w+l*R~%!TuQkWn zZyhO%{XWNsv$EgYsWUt!6Ji3b4*d~aw_(~amA7i)0?}Xpb`M1NVV=EA1bQR862^OW zWcM-==soXlu?n6A(b#KXB5>UNs6r5ZHJwz1vls$|lWtRQM@ZKboYZTMNc|!lG!z6A zEQk}}q~@a1I0vnIjXgTJ7%oD@JzC}MOs4SCoY*Z``;8H4=33BeOm*hIbL?2&F@08! z_V|^&2~Ux0`dNb1``;cbMo(GVDDFTinUY2XVJle#EN)=H=u^bVltk?-W zTDDSgfggsHrM^nd@Tek{qd*mtvooGieDDmzwl@%8kjY!>3M%i*;%{AhFNcd+XG9a;8_SRZV2mtObG6^%|dX(mBR2` zF~m$^u^trtip74}EWV-aNgn96q{uvY^iD37m^6l+t(7(zx=G(tjiGUWcDG?{H~WAm<@hGp^2s=w7r#A6>& zl*N}pU&7cfVKwtp1shjb2G8;f$!S$VIML$RT(fHv3e--h{t;fxHSgn*ax23eYpn2u zOT1tN&2I+!Eh(y16_Je$D-=3<$+&`(73Ls>YN@~$Y}Gz%r8x=)C=07hujzEh{G<`K zru6Y2k`jgR{ZtHsvVc;}GJZ!%lhm4pCOFG{d1hP_Jjy7_Vuc*Vh>_iySyuL78NV6d z{%+R2{HB*>Eq;(+?}KIc%d_Vj3$wVJ?sWT0%jDVh?eE@~)$DRkfAGHh09B}%cA@$G zGzaP`)gUma)-&@;1_jt`yqaGX;FaR|a#9wv=1^GSMW5 zZvG$Rd->Y6a^GhDCV4jdQGsF2e_LK>24q!lR7PFO`-98~JHEGA{W+Q}!W5BQ4sX~* zuah5GheE|#DQayE_lH#Mo3T>L%mkTA#UN8Hi#Oa?@dyaDUlSuZ79K}wKB;JSZMS{* zN_jC<6c9ZW3>$fAeqL`Y7-~D@@kzY1lc|NYet4calFmWKylIoKOVn3O4-x;{`!-12 zo}`HI@{O;>spK_M*6f)~ADWY;Bg`PxpJybOy88CCtG9Wo=Q(!V z`dH;|=Vg+)e_8$DSn+!)EEG8`9fXWqYgzE62d!UObA@v%X^P+Mq6>WTJf_@UR3ltbmk{Yt+Nnqtc`)XA*}2mNCu z28WmpAipb7HdO>OIbHXZK1E*h#_wBPn!|afuX6DjBIip^dhyM$EBmO!<-Z_Yl)2bh zI{hQ+UXl@;>EQ&A&r{&%>MFz~luTu7d_MWDtZO&-&YF?<9t2=otP54mFx zxe($5>G5Oi{Oo>#eoZO;qNy-^b?Bd>cNq7cyvz3c9j9+~{R`b*I46i72e{eZ1#xc1 zS>JWNIN2F51Eqb-;$vsJ_jUHmK!0MI3z41iGLQ(}1L0juIQ1wo>rj7^^)3qmiSzzY zyO+Shf`kR>`T+@K63D!5~SY{njkM(*wL#%hkxo;f* zr?q$P{)~t%&*F4a}m+aqZ^bYs>a`b*~`a1*sS?6rwOTs_27wHu-WzI_3)*yVz`k6n% z3}VaEnMF2B$UoOm{}bvT_fM?dzC=bUExNtJgO6$CF>pXgu71OVXd^Eco&Gf z-IWtf#>2^URz9k_KT|U{7YJW#ag`yfk(kYS zBIQV;@;3 z9dMInubhp$_-$(jRky@R4pOU>Z6p5bs@fm{{Vnsh7vnpr8KguhBbFb!<)73`UgUl^ zKZG|!BjYtMDX>O_w+2S@%!9Cp&6U$*D`ed0S(L)%8-D+{QMfF6uW}QlPw&s0iJUE@WE9w)J9JcVmZ@QZTkchzUtNT$A!oYWt4eL^ zpTw&{azVvYeJi05<~j9gE<7}T8WqQH;q!RH)A(?Gd$8eiY^;{$OF-WrG`L%|s$YTw zv2{Mp;oP@u|8TdMqKIoYhxOXVX>(r+bra)CPl}p)Gv9M>Oe}r*&YL44V;_Sa1EX5a3uN1)ZWe;kkd9)3MlzCAKs#cbt{i5Fd4!tuNT* zvV%mTz<4PDypt&qw@UBcAPB#eo8OrT0pqNNUewH3K{(7H)mVDQm83*Bdv zmnctDV3tYRD{#z3blWVJBI>TrO{6$XpP=V76}W^6Csh~q*Iw~tGv)fB5EmVS9blrF z`+xjvE=ZRj;{Q1nUPaI1GWYIPDzSUSzt)4lQ#zM!=*8bb9R9x0H~uCL{cEJY5cJ=d zA`1F2secCa7xsYu#s5AH`nbL>5#KV~$oyQ8V28In^=q_L%Ii>u1&|fq@)KTLO1lq9 z0q2>*TXqP>ZcuI7^ISHsvIvRxsaJT*R6i}(P0DBaTy=xOmG+wo6E-Yke%eou=J zx!(Hj&Xc;%79Y}4qbkWL(3EO5M=CQ9{kFT=#1NnLKCcajGKK<taW61xa{#qlp8dm}YHB9Lm7e=+iO(xd(iaYe9$P+0`rKH}Na7|o+@NCeW)WHUH8_D|Lr|Sl+M#)w1mY&g5hZ5tkk_PkzRL>< z$je8)p=U(iezj6V%|v|@;e4Zn^UeCqy`y@5zN@;>;}XrPFsZrbNBb2|LO^mS2Vj!X z?~0~MWDxYJx%KE1Q-Y7Wk^;9fgkC)RogRocD?Cx%gmIg9JP+H!xx!3-?bYcvl9V!U zluyEZCdmt`VjWeX-x6x39{VRWSt`D99EB$Yg^;X5Mg&71TtBPu#zR#1<2XDD4(IB- zt-wOd1&I<^1tcldp9zVtTS!zR5l7qebm`9 zKHc>#{1WwD`UUD+`6cSxp+xmF!KeJ`a9`5PMJoLODr@rH{1K(l_HDAfZVv+kFU5qU!%6e9`~3;QNqY8@_`i z1-@4KB=GH!7w3epJzJ2sOK##dv6kq?t^P~RwG>m^34;XU=6Oc({$?L51&j0Szln&t zQPwTpw_gt&G(5}oQ@MMaeWrZZi`$}Cioe?MoSl@KXBHMIk_r1vBXgX-z)be-pJxuIEX-< z3cQ8`-e?LD1Wx7Fr#2jI;7W`bM1~GI^{ow2ufC_^0|%y;xZcMu!BWm>uk7Fv8ZVov z2ilu`9nzy_pX~2(w%&6!sbMw9^z5(pb!?OsxFK>L3q;l-)(7|Y>giwW2nX7$=lAP~ zT#j&S`vX4Zzf61OMu{TYp`WVw*m07!Pf26`Sq-0f^`_7^r(V7g4-aD(qy=g?l+R`H?Z zWGp##cSVC-Hr2QG@*hg@(Rgd=iPo-{oyo|c^xs-?X>{qZ(^p-_FR}2BJoCa^++hhX zqYz&DuDit@dXHtd_)uJQ>AULMcpcag`FFWT;4{O;t#Dt+aFU#0IYai&w)TbB5P5I@ zc~3FYo{xAb+Xe^M-wjWa!_$3oBKnZ68+_3z*7BGY=nUAevZ!s&Ls1<7Q`Gqmt{0AsU^iH%2G)u!q)a1}Hg( zK!z^8E1DHN{=T+)86$1Xqe3OZXob7F{e3z=Gw_h!SS!#0l~%aD>YYFxK5OSlSD5t9 zEyRU5#C=l;7@l5P|DuynsT}y)SV^eaa1k1JqX){@6hqv^Cw2r6jMQr0Ae1X{ky2Z7 z-xw(KXp!#wYq)%W-U)5>li)GzJ7}ci^xJCbr!xJdC1RbDG<<*6eLI_dZA(r}=3!@e zMn-sUX0z|rr&zt3eHe1cyjg>%xH!W13TuL*6m1kU{R!538}wYxUO~B|;Llx^Ev5cB_46 zu-yEQWxtN*gy(b!N$i3o^j$&}ryz=anodirM>8kjFacxdY755-jKLoB@+9q`25IFZ2We8mugin z-lzLay))V8*1@B%UH5fFD(L@O31$0U?R=6ixx(o`TDWbJBYBP)`=GX*SGjv5Pa|80 z7qrtoeRutVq~L+f9iP_D<6GzhO`o$r*fpRohbL|F7GoA3*)`uDeL?$6PJdGMrsU%N zkvk|}i%F2d_mFe(HM@OT^n+mGE)xmB!!iqm1#jKl8T&5wV(X)vQx2#j?4x#Db&#)np@wGfx}<(^q%WyevPi;ZRsy%)y%Y_<_p7=hc=2_2?eVWVwos;Bc~BQ{KJV+2@M#%DtE7hfh1IHN11m* z;Gkp}B*Bmms0#Thxy?)0MlX~ciTPlC*PDsMQ1y`Tt@3uE<<~lemS5+u&~lIbr_-}cNTKJa>HHb# z`G4rIMbDDersv3i@K)r>;*Q*-(V+-mm6V5p2&+;Yzj{-6&c5*E%$cz=7Jkl+-K-#$ zFW^{JA_}7?wgdm@$D^rrIp7Cj@sQqVj#n0kb$Ie6wvGAbX5p;0_b`*p{r@WIMQg|N zX)6E8MB}Qv<2{%a613w9NL%9D%70sUA5Z_YeqTOAo$@Zh+)2dwJ7yE^@C0rO+>dTN zyxdJB7`o`_bqn`eai&~q6u0+Mrf<1HmTzpi+Rva%@AjrF#d^9^{-ISYRNfxfr2F7> ziQ7UdOv%+VWj%lR$Lv;4_cs5|47MGg|H$5wILKuFjVI+d^e_ovQo8q^y*)#JADR6n z`@1Lqf7RcgTgA@V--(=;l$biepP|2v(%*sc{(4E6v8U|*CY`gta%5VY!)cBACxP|8Lsl$rH@d_z95IfGe*R6ORR?*PxP{r>15Zc}p8KY&1%eQ?c**rKNS87 zC~eNT4akc~b>r`mAI9;woKymT)i(ZAv9Ek!;cq%6`{HjxqWtxCc^iMy%o*`l$cKM~ zzpue_&N?a2j=xiRs@R$FCtXqaQ+@hjvEc8|KR5&aih9@~!(Tw3``PEE>u(bl%0JTZ zooMo%a2j)t)T+0>Bc-LUz%HGs(m2ZJEmYbA|GiXX)F)wU9Kmt8FLU@)7DR4-A1;29 zy@9#pN8RHVpY>M$?%bJ)+>=%AIRAS{30I^^&ogj9SgmP}f3j)ovOf=I;G1qhDTFalnCS%r?5Z<>i-A|8ZCtgj9zq*w!s`wLZVE%jKWt1?c_tRB$ zh&mY)osDO)XLJ*OzG8unc#Mc)h}s+yMsGN+v=vu^DpYAAPZoC=#p~zxD7*VgRTivm za89{ZtI9*lK^v9yqVs49AxyNV8c}Kb+*@jk!P0AjFTHiFlPkZzLqI|}@bFEUC37h* zBO5orwztq5MX`|BLSs-J+WbJTRVq%8*^9!H-HSN7%UIMrS=2hLj>S83kA{=N-*ZL& zLdR7Kv8__BJsL}#`Za4ZD))-Cx{0t`O;(`m_k*8|ME{j;EJ@O@(P|3V>6!?TBDK0n zBDf-d)f|%m<`=RFMn8pqg8~`GqfULiR&$+RZiYUd7#$E^U^aZ55}lZP6fu=TsT~q< zJ3Cx{kTQIfm{d_@8sjdfem>ykFpm*X zJ1Rbo(UAsoK*igl{<8H3Wo$4z^fqf3AgUL0^d{$thG>$p@`5C0T=hq^U>-GW&E{t$ zga_}Hc8fcvEUG%Xh&%4SHhsZ9RFy(7z@k+ylgYTiL=9Np9%@de)0Q4h6b8NIRU5j) zHguob&=DL1!e2z_Fa6!fN7NdZC#iJ8f_ANPEC8$-YTN={tVq*p4(nUh%v>uPz;}Zm zkIXydAFS2f;tXv{k^tAD>WZf6TWwvNen_i18tmF%mOi1l-9KEb88Hc^5gQ79L2Gmv z1CbW!h%Q9rLUW4VgZAl7hXk=+&>HL_th~OUgOUK_AEwm|o}_P;X!jl&fcJPA9i96Q z*a>~yzv1H{sqdn!NqrloquMz~@(#Nitmixw{s=bSFc2T}Ruru;Lwa`3jpvrWb0Y8rj ze)LT)MHN&UrCj=dj2s++Y9pt#8{9xp-vVl_6$di7~A^#&; zo8hVagS?p%7B15Q?Ws*RCaZ=>9w&6*up?D9PhujoZ@7|h@Sy%cio$*Z_11m}C0y}N z(O$NlQG59W`ZJMI+E9>5W#-;p^eGW;MdTGsLdxAeEJE)1jLV2vgnT26$oS?Od!}q7 zk+1=|PO`9)-AIK03{vM97h8-d-0tF*)&?w@n7R1@Y$Y>DgTK zVXHZTp?7oL@Gs9uK=-s{rvvNAZl=X+9MrSMfL&vG-x?MCCA|?+WYD7&&8zO%0Pf>70mSC<==ZOwQhq=|V&_||w34Xy>O!06`U@MBgG4Yzrx4#qjS zy^UY{KxP)n@O5SZKk7VX3JJRv>bFc-W$E5#1U?Oqj@QmFxr37TJr=u)iu5jR{tXybNNiEb2%INo&;dU4~tCab#A@V?^A`QZ_=uY zdBu{l*bxh$Z+0u=TQ~g@`NU-RBa60L4{P@$5?awuJY2QI^-dN)byt(6w1kxTt-*@X zu-ERs{CBr;ngFQA3nP`>`ryMZM>rL!lR&~op~Jb_2@3-SEo{~GhR}iJ(D5X__()(r z-9}X(*s1hAVQ%W$2F_J)_{Xwzz368Z~iI_RVQGiZ?g=cCMs{%wiTje)cJU_rCqYF7#s7IdZhDzibMsuQ!e2opmed zGn`)DaHJ-=%onke?lJQ%i8oF^9%6}aGv9lh&53f7xQCQ=druS<)_HZsrc*KWogWfL zJf;uQrxJ~Ev14xOy8V-67j53OTGmp38lhnYsA;a~T=Nf9V>w5_ha>K3mPDK)@6RYhx^D*~6JD7U~C>u;A? z!+QlzEeTQecq6u0V! zi61vrZ45%?tq!fKp7-iB^I$B{W*)pwRTU~f=m^{$E@we&H{YZ2@W3Zzr_@9=AUe6v z>STK9dgN%Lp?QKG8L3Mw% zdqs)UXJ)9}ouu#5w=7L-N=gZBwp@VgomZyQQ~%erSNh*DAJv@yir{0;@c}s;sjOe| zC%vKK02?@>@x2~8K4SSF*96NVs0@?(RZn(C>ljqy?j%GFW5y}0I+tH7vb`rQ_b38` z-iCVpM~gV0$OxXeTC0?U(clTRrkD&m3Z~*p@}tO7VNPu@-YYWz!nzc$y^?&xL;%q$ zyE03Cs%8etr>oSb@A0I!sCEnwJlBQHT4osYl5&q~HLh#&Y3~-A$)~v~{2KY! z=$|S5@m8mN6P2rc8_h4TC5+zIB>9kGe-KMqJ|xSBWck3fRV6TKkhspA#5K7_ce1-) z{{1il#GHdhVUEP;tQts{B0odyGUlE%?skQ`TxBEZM5gM*V!*DLFlWXT+P;gl;TnpV zwF_x&j>)MDomjM%(}~d?RJ?4FR+EzZj#AD8>yH|p+XZA1`L!Bx=h5ROjy!oe7oBMk zz4VXjoh|ZPxxsp!46M0ts4oqn=9A6_l7Xiq&&t=4a89ifoebqurrMR>Doq7GR!v6~ zs#zL81F*bJ+UiSSK}gwpTDtq;Hd;e*IAB4X2TxBSR%v7mG6KwCv>7IPqPL(>nXZ)7FP% zDX7M2wf*5Ser23m<4Un!3qc9~I^XKhaD(bxD{*@_@ZFD zh6ME59QX+FKXSQMaj5BJ?i+^ddbU)Me@}foi0R^JYS}lDdvo_HtZ#DeR^#y>3eEFy z_}S~VBJCPzH~xC7%H0VHwVHX!bR#i(O(#`Vfq#w6qAqc2R;23eKg}Mx8P?E6WH)5Y z?KB>9%VGI&ZcCI4d9eo>eLQqLS$iBCWNO!-81N6pY*Kv{ExRB;_YI-02Ip46{sq>{ zr1;C-@=`9V%M20d_DW`A(43U~fuBV_1#(>D`P!KftB#OS&bkBpL~;_NKnc_QFu%w$ zO-U|&vP-|yt(ST9o4t{Hd961@Q}x}EGRo!dMMOY)Kp;!f+bZkXuP~1O2_g8aw(13P z1XuJMAGm_1I0%PdU92}&e4zMMda5(hUmBfb0!QJNJgB!sK=ZXX zr8roM^%?HS$DBlRXZ@(34YkIOju8>;Y)W3xLBc<5+Kj-*m>}poUfcN@K46baKey)X z&{mIAHMwP8yvup_Dq%3mYzNEthw6{%0nTnwCbSuz+)#5W`$|s#F~b=<(wgXZX*KB+ z`b=Fpwa{v&Phg%a5E`AW0ztXFOX~gZ+gi=+3CRf(@pYVJOw=UTTLM3c-aKJJN7%Q| zKY8>5Cf<2)O`8>{EdJ3`W5pfx%C|3?1$A&toVTTHJZJUcIs2O&$vSbki`l8z!if zK(T;n?yOKtwPZEj>bv<3D}RI8`Rne5&Xy;~C?#aYxX&Gqddst+dC4fy-z1aZSs94H z5xs-hdZBtR1XkGKPgn8(jGN$ZKj1rY#ov*G!wqbJUw^fMbE-K9n|*J-NeVHK>B7%W z%f_LN(L8O3iR(>GfR4%2)X|L8D&ageA2J0W2o zF&mL%M6?-$Oe(TXx7a+2+fZ6s?mMQ|qocNnW3Sf-J1W}O(Y&Y?S>Cy|f%zD5;2(7# zZFK3|{Uh}4p*P%!y@LXSny0FxBRoP3phV~m7cOo*+Pr#wkT$w9JIFh2G|qD5&pq;| zME(@WpB(vCP_j3eLp&W=vgvINQBTdp ztQ{MI?yXF=>iIXI&ojjv1P0_;pJh*U@9+ex=MRLPw^tVqWZ4YQb9)Ok@S)d4uNVDxR=Biz+Z2B*|2yLIL!jLkNGVI zx!6dfg9>f#W8q4B-Svq*?-#G{*?(A{*x!Ef`ey#a`d+~8%@?oFd6xR1KOyl2%KtzP zW2YaQWj=RN_vmFXddVrXuw;LgEg_qu-1>yh8hmxz15=Bb1c!6PDEL3us~QqU!T(Ep z+Y44$`;wvj+WV4pl48&5kWZqvN|qPrv}cuoj6`-3d*GaeMQ{nuAK5hiUm<*Wxdq`v z{MrzfkrW8;l1~ERH{`{cAnb#`UhsLh{!`%Fz087dJHIx3?~oMuUXxD(UxU0j2Yl@~ z??#{SB-t!|!WvStr52sk?VDifX&4Zw*fVuYSXcFiStbe^(Cg~GMNIU!qCLoW84_X2 zyI38=IV8Do>kb#l@**yq$C%`C-0`ei_QZG`mKJN}!K{2wPTs14Lf<4Y4@V=EjluJV ze#(pl08(9U{fLyfzX}XjE_v2B3Y_M*bL1zq$rT;f++Qlg)5sUU&1mMP?ZV%)lH>k|v~1qwiczMjyD;I~ zXp}sgg=GSSmWH1t^*veTwwx}hqljnM0U2OOgwFK18lZ&g%{!=3bR9U1b#C+?7fFED zMB5=nO1=Dvwf5=7oIeY??ht$^bbSSMeU+>2=BxfVvNn=Z$jVg63Oy&Qp_z}yO(Bc! z`frF%{{k3`?CZwZU#K*kpDnl=jQ47B1?b+8wCuu&9KiJLyC6a`Jo^G&V9%+oeqP=% z?i*amo~o0blN_-F0GCtuyogCi4)*VC^fC@}`%BvIdQ-^mJ3a{lQ;d< zEvih0S_&B!JHTX?JVRUaskj7^yPb3a=>p0WmVBTBJr~uzX%(I>zP`vH0i$J%M@eCG z)OmuV+8{t#Q7*@kG8<1S)rXe0At_Q#whhUV3TbL=HdoijZV>m@3xF{n7{_fu`RMXz ziG#$e^+Ow66_Nc&^!`hOH|B8M7;H?25YFdp<4{GUhPwUkiW?UN9(W*-v>^!%-Fels zaiws$%vRL=ox~d6h>2TGqq+vA`C3*F6s$tKwCB=sTu32}{;uFzrdlb#;!NuSe(wn{ z@yv?7%jB&%y!$Ed;IA$G$@(R!t%3gGwD1&H^z!((ztj%B`D-s+JM>Wen>#vSqs*n+ zv{&H)7D8t?6=n}|n#mW^cf@0wUP9RL8D3+mB^hf~&rpJWPJP`_N@>1UCFpASfM(=? zXg*h|CjP$-m3oXznl7+gw9Gp<0Dc zbT_=8(|fo^gvyx%wA$bN%N45T3FzoW4-3QvKvH7%+o5q-x9>I#C-F+iWt1nhs*{^E>jfHNb=d| ztXb1*!C4{;jyX)=v=^M5o(ql?u@{_B%(-l!@Yza=L^?aMwq$uT=ToylZj;&_Jj!A) z-J-F;IMx8!sY2xt%v`!{5A+m{&s+|FVHi3W@)uIR)Ep!r`?FnmPptd{klpoF#d$YM zy6hpfU`4;98g$tWnmp=|FNo2Fgw+sYhrWzq9SCX6V8sNLG@}_)xvA zCfQF$EQLtnxbT01XL78yU*n8YX^Ez~c{!UpMG-)_vD-d4!s6J2V^Btn@qfUkH;*}!WDio9!J~Ntf0V^$fqa~rzQ&P{ zE&lUhAomSiG-~SyWToP4dRQ3kcdtU_N+YvvsCFCHM0_DoVTXYa#3iZSrxMy?AqI~H1sDC27# zJm<#jVWv0IN1+EMR)%y1%z75Fqzi_lD2Xva$t;-+Rx@x=Dp;@`D`#Nz9=KL}g`hDM z^-9s`jiOHxgA7zq|0;F8oBNKE4&>F?&9@Q>4K(u`SRhCfrQIWC%{h$3O|fCOpH!x_#`DFv@I`yCX1vaQE*t^9x3Xd*0acs6iK6*NUh46%LTra)Dv=%V7M_* zV9(p)FX9fE)dr?AHy{gSHhkiVPJxW}fXJ*fl$hVM#LRe!c`Wo&_`{UYC;b~f8Irm! z^?j}fa&@Y52i&rvS=nhFulPjSX+;K9Y!f@JiZ?7vsIEo&w#aYEclKI-^95_EBA>pg z#N1h`4xlBByP{xz)g;J`RUHjn6urv4nhY#^8EV6nTOZGdcriq8G7sEm^Ol1oxVjhf zYv4nCv1Sk>0XrWlE28fhnzi_8axvYkrDNP;-IRK)so$%xAxFZhdZHM9R0ipz4P-Bq{o(2y+a0#1;u*~L69HSs z#f$ee-ESLc$pdyL?Pwnsq;V7eQelhAT38b1y%!5N{M{mf7sl%eewZ9Q0oz>(7deyf zi0jqz;WjU%gm^s|#;+}_oJZ2^$DetT>nIHpJ!TD$jQGFF5A&+@O+GAk%rjHi@WOuQ znLpzT>sd*utQf+E+u4}%1+L?^Dk&nFP7)%T4%*~*HoRQwTfrxn^=YO01b64x{#r`T z2h?k}CGu{ubFoB!%bFY8!AT_H(eAgADCQONznMTXzl0GS$A4o>rvs8&mB?BUo=z~* z+1c~;mef}NHL%Sh=ykfjDfNUuJGUWsSL!yqGXJn5z4C~xUi`?iH8pf`v{9)leEvyN=7h*Ut6Fa5I7al0g;MR_%gZswO@KIYHP;JJ*29P_2{cHXSsTa2J|0HGOMpOZZk->W=Vm zIy{{|6ya!Bt0~OBnrG2L+#|@LhaN`TP2n85IF8pGk_Ea)R71C$UmGp>$za3_sJc+F zQ1uO93Qz2TRekqjEPDi<*L|fIIpSY+>tpP$qGN~_4%`V z2xKsUFB4du{nta1(ntL`gjb~4${~5N3 zkPgd=9sPklt!?}Ws?1-!pf-*G8bhBmT-goQE#wPlQK{We=I4l#y%gB!uQBa+*AXr; zrXRv#xg2%udRhUfcl7m69zVb0=-NK@v&)C)Fe@o-u0&PIU?hslcX90O^U9fHK)fIJ zILrzUmOC4V`kZE!nC~Lbt6HGB-Y`&~a+%pz|A8=v{^M?0Hi?kupN2#=&HNpV!Pb9} z5`~!m#@<@4QDr_I+I#u3p1lO{8<{$9%*k5PM z{`#jxT>*G2OYiUL^8MjH->v?L;$ErR)Nw!nAh;vy(|>Dpj`^nr z^h})zY$v69cHb9JWnV!!HR^y8&P5EDRLQF>=_qq zG964svDI!juR}wV=pW-diea539)bq*-%VUJV&BAxu1w@+-w~luF?i%3h3n*$4?A33 zA;`EN<4~VqQfiP#5-fQV*u3#XI%GxDt?jJJtD10`C^~75)`{iDwKi<{`Qi z9qj8cUz#7s(Cd481Vjm`o`a6zNH*Y#9IF9p<7cQM!~T`2VM?T>o2 zD)iF*-7nv7>hpc0Xs_!;j|~jux6a$q%sk4KE&pgE^ACb)JnBser{K-N{1sbUeB~ch z=VGK$Oj&OA*79JTem!Bm&V5}dKu^KXRw!<_tbB}oe3w!X+rDoWh{*=ak0UyalXh#6 z+xIJj-j0iSEoW%y>Ct?1gM1Olen*1bU$w{81}Y2RF?DjJX&zSyw4nSPeH%7I z_`;BDWF~zzZ?+-pjW2H>_-+HfxpDaP6VAP5cR+#Ppxujw3Ome8fdVSzMq7zFK|mD( zQlJ)@{pFi{aFL+Mb-hWj8`K#Vs85OCo7)tq7T8m5u(2J&7+o&)m_Pi5LTH@+#!7Gs zPITwAg&N&@af@_r&OT#K+aj!tK*H=dSjl}I6EJnFWG%%o$P^=_J&T%MQ!!Aa2lLEz zA6ne091HgP+;?Juo%75m?hw%nL+yH0;UOs~Y|V=Y7j6*w_6sj+GhZo(Y?}2QbIr)@ z3`z+{%xDLTTR0-31jk>NfzKp#>-ylP{tnEZkIb`2?-&X0uR1tm!mR7hJSky+zq}TE zeDTK0d^@5n{yHLstm9$dW;_OAo6S8jgL^kzX~M#^cz^9WF7eiJVgsh1Q#$ZIhuI7< z__Fz3TIp7@_vLpM6?Fe4zZL&voay{2y_D7J5y+O~&cL@oL<;}SfHxCp%nt2fxl(1Z z5dz?=`rt+CQkf(x?!^n)psGk}y~A$Hxr)bZVY_cN;lDm~W6VDU8oi6dny0ODY?l1JsmN}qnGjnvj?tfKt3*eb?+j?fFxt~# zdLzQL#2-liy1zpXf&pj8tP;~>2+xwUF0XS9G13E%LSDr44fG3jrueyZJw1CE0Jt<< z8lOjF4m~|P_(5{8%US)F-z$#4t9~okWk0xPu{-#=rd9nL&)66xg*nG6D+x~`(2>5i z*OAHB!xt!h*F^J545?>DCwBWwS+g>G*djo{XUn#R{a$HNT=z6^vY*=G|Aw<^g6KL{ z^`j5bG3H-yL)T$Nsrnm9nQrDD5^AydGYKpAE)Id$Cr4+jPmU-S46s_wZmMti(4D$T zdtryW;Zrv|g0azi>fjx+Z}u*}xOBg;gb7O(f~Y#34&g6PZ_%FHnn3~GB?r4#g>Q9_ zK2$cp*)po}Uli`|Y??W@1W}WTYd+3iP(O@>OrJd5A)*d9j6r*DkDJE1Je}GmM!e4W zRI{kz$8*#&d&qnXOL|CTvt0MDP%pb#t4i7Hm$LWb)PmzT4*;RRaPH1)ST>Y+4qfK+ zY*1-4KRK|B4|#3Na)nBcbN+iwu{)^D@MP$>x|92}0=rAhKe9swWQ%(ByIj$QLS{ss zCaT2M`APl-`T<2nlH1&}#zK%QTejVoO9weGBR18@(D9VO`OJ;;g%Yf71D190n5dvq z9KyO3MWxV$7);uM?kp7i5LKGRKjc2tvsv-&k0i`x91q}wf2NWK1}Lqg=Ie+~G5=f= z7YlcjQmf5%%~La^P-6SS06Y5BcRBUVC0;BQT3b0;G&{@(gVv<%fpZ(*?KyI3ZF_i5 zdU#U0;rGT6044-HTIg|^gOj|>!A;gJY~xNsgK@o$d4S6SmJDMBnXzNuA1?PAEBkXj z@J+638ik~Mt!wob#5$$lU*pN;I?XRmsfQh(9Bs$~NanEbnC3fvX`toO^3AEo0$<@e zuHN8$H&{*>`G?X2{hKFcN;Ymr7-KI2q_W>exZdfI@Aw{)+zZS=T6je!)~k8jw8_V5 z&&bS+-@nM)wREz6Jk;PUn_#5hIAIQ58YEqs>rVf>&bRf3D+29( z8vOnaNJZ^N`hdK5moCS`oz#Rm>00Pt08p-q$s-N^ zP(6Z`RxWwd>;NNQyJ>v-1b?HrQENz^)214onNC}Q6l~}9Ntwpj^SRy#Y%&U~YUJXz z53BfeOzGMB^DneHM+rmW;&hPUJfx~95`+~fgmFotSxglidYMbV*&W@+)dXXlcz#%jl?cOLV}+mvEW7`Oee$9x>eu)+g~0_-2UW`J{-Q6|TFW8gfI z|D>JQM82^OaU_M#E1e(tWgCtD@K3z0eoGGHPRaG~$?72P-MIfPj^F+)$8SUP#O}i- zF1D_jtna`LK{SmMEsp6vliNSyhl|S-9c6>b_nus=;OOjKxnn+9CZ+yf!vRk!I>0D5 zp=3VF&F&BTH+(oGbt{bVl}+gN-Fa=eM&+AwUa(0WinUdI7R$y9WxiCQXp&ro~kCIUV zI2OT5k{E!?i^xd+E?QgBqyReS<@LXlJxIK^uzWyOJkAn#CgkQ4z#r5Mq7+ZXnSlvD z$-)Tq_Gz#(dsJXsq)z6R!k~Wy*n1T0Y1J-JDHy~sE5hzs)bO?d3rW~A9fic+2g^;v zHB}JE+5B1~e~?_+(swjOM>=aYH*WEaRlCq zj-VEok;Od4 zg9}`2rG9m@y=QuXM0^pFCMGZ?twWsnE)VFzz8o>pC)txo_!mZUl84GBxuOjgxxDWm z5+|2qHo@S21l%wr@7qK&7=I4r!f_t&(gu1RZ5kA!^^T>V|Z}|2+G~tE#JkKyUfO$?4@}K2OB(Z zc3?^3Nv9PwrEG+!@RJ zm&V)ne>-DL2U4S7QT_5~N%2i&SCUE8>V9pacy#x=!i#;l zM)>-IMvtWzjLREtM7taDI{}){hvkJHOP3x0-Ci>~&E}(jB@w;>Ht)D5BbiCYBVPZ~ z;3F400^bo8PM5hIK4rUGFF%;Xfe$JhuF%PT!`f|d;j$oZqs0fV{P{tz(|h|(-l~1ay;8_lkJ|G? z29Gd?=1wVjx7)lfo;OckoQAmJyj3loPog*0EPBx2R@?F4Gu>lC7H)37xy71V1;1$# zc|V0$x4XD15E#ToIlI0sB+gu)IQZ~5^iKa!f$zuUQ+@d9*yK^^ol@qS zL3)u}ue^RV`_G$eUd6NdLrN=6+K;80Q?f0{kX=09+|79itTrE{eN-EIai`(yM9)S? zt^V$`de~<5cc1liQgmx5+R&eJ_sr@jYSdP{qetq)gn#iJl+5O5)8hLd>ZkH^)ohpV zEZHjfvRdhGLTPF_W~sjt?;6GXX)oT!_pLU1Oh=(t#t*+BUvLOJ(PNxz?1DcQ2Oj%X zm$FW8&Tj7uHg;qk=N-_C2*~H4mwS4&`NGuG=tV;46n9k5p^KdcZl}eme~UG0Vn;&* zt=6d7W7rwwKq`(_rL_fr*5IK7Zn2Ty?s!E8PmMJ5JKm~AA9C#n5-IM~=bZe91IZ0# zMM)Nc^c*lYnT%s=WU|BD>9bn+f1&;*-=}_mcl`iwZK32yi}p6YJafs$x_3IWi>&h{ zIfrnDXIl3>`A&ZO{wVfLpNRbBvJb;7elPRYt(GZqkm&Ts-K=)>TByEd+6z_38SJ&j zKl`-E7rh;$c*Qt*j8)8XjN+K z%`=Y|aQaZdVp+#IJc?miHa|lBPd~IY`e)t$t7zYkK?k}PeLa=nv|YX`ZzbC5&&Xmrfooo* zLvlZ(YOzg9uyD9lRva-Y5y4iOlvHMm!cYG3RvN$EN^xUC7)=%a;O|5-)dS6e4FQcC^=hp5eu=7C`F)s0OJR_I+3kaE@3mZ*b%v(A9K*e zge{Xs(mZve&6J%yabdcqWvny&lo|q5Y2uxI01ge}GCYI>dEF8*nbmRmZ6iIy<#~|5 zWfyFe>28IQC>xYpFP_lJ`ICA!tIjqyE@Lsl5SSHe#Dg)QFJuESJ+A?0B>)KY573L* z^gyg+T*kbZ$opbaB3h0{Ep!c~bV9>S=jzTWMEG>}UKwnDvUpR#uZQ2F(QhYvvMIPS z%vHN5vV$~vg&1gYYl+&&=`UwL$19TgB-fGDPldU*GWJH=_Zs;(VmSY_WRNFM9zUXY zSP{lH$0N4snY7`#iHa*F6A|Zn>~Hft*;>`VfRr_!p$a#)&lBwzdv@$Un$S75a_8mJ zr&QaQRw`(?0(A+a=#GIC7h@m*pqR>Qs>)zr#IPhPX$piSAPGHZom8l5Fx zG29Tu69N#?0oB7(@*pOn>S?XiH_~CGkC=d3dg;BPMrYYQv?IBU^z(V?(n7zIF|n#a zPn1DYij7at5DnGlCD@$g+8Ef0+$xLQb3>!nO^L20BMvwV}>j}(P}b>j?eTOx5fO;aX{oe zXhql>WX-oSdu1GmGJudh9u7Fx?BaecRf+&SfdV{0a5t*@S2a zajtVw-YI=oz>J<}#aCgd7t-`S47)2jOz+CuuD5AZwnLHAX;>(8Hn9iuE8nPQ;Ge>{ z3|Pk^^nWD}==~QnQjb4E--7ugUVm&@WC=-n--BNC28F$`BN!NC<)I|6Lw`p@Lc_=IGAttr)o9VPZRYOdM3SD zyvu*SAFWlh=qki@q;h;1^-x}1%#X(cy_pSj>U+V@JIaRA2^U|e2Ai(_q9Yq*ziRkE z+|AdEyZMimyZOe{!$iKFVmpqnYG*Bo&R*<3li<;9R$8QNydM4pS4WJH8l$J?<=zJLk8T^il3BxRsBTW>}D5E$ZZQZ1#W z9|E1-T9Mt_^sG-+#L1H9r7*4AH?-DE1qm=ka*~EhZkrjKn;}G3srtjg)?Hy=M%arG zvWzW1azp`m%U+yPT0rk*b`qoPl+du~ehV;`Q^%Z3nBNOU3h}dKu7F{zG%&#g;B_>D z%QTk~L|)tn|DokCC9f2+OBE^Z6Ip|1 zt8UFFq)z2R=|Umm#e5~cED?+p!LYoALM78XX~XQ|2A2}SPY1%gdwb{mN+URD`+{ifveV||Q0EWgwF9b=3g&w?tI8|mlK zTt@uK<)ysv0>hODV&rMFl&@5^VfLTBk4Hi%i@uk&TdNX#7$6ieCo}gQ`?xGa;Y#~O z*J*+acTO%vnnPq6$&h`3u&3o6VerJ)n3GiXnCRxEei6iqr<|6 zwGs`hQwup6aZo)9KU|@YGJq(5C?^3xw2cQo ziM*3nU!G;$osf6l?$A@Q_9-t(clg)G0*E9<$im?`4UbmnCt z2Xg7$Rr6|(_ouhi{<`+$=fgq5*u2qQpi@6#tju#d4>S5QN`;*qbc{l_xs=MepZBN8 zYU%dKAb+L3aY~?x2CVt(Cuq77X^x3V(|=n0z)l6s5s`)x9)jj@q-V)HsUpve)Q>4o z;~dr@&kT~W5TQqtle#oy7-@#!2og3&k{r|7p>sHD&y=Z<-_9>p#B*p>7fJ?eC&RdSLQN@*LWhh(J^mzu`MHcj4JpHwYozA_ za@OcW&h5kt!;M{Gt5zx8U)DQWSnz6z>v!B?f2OxaSN5c@YUKfbiyt54TtsXQaShSM z&A=Ah>H9#uVscdKEs&FxG!YAW=InI|HA&%TWv0Yf7vV30q zFI{WQZ4Gq|&{oOGOQ`Af(5Vz{Rgq|AZInkxgLpX{xe!EV$y=hJ4bwvJVP6-_cfS5u zYGemV`Jgw7CrxrKTM>LXxn6&JmD5p`n+;bA&cmDel8vBFRTYt`l#<&0{et6sfs61IsjUjA#)a(fCxtRuR#l?u zJ;p63B5pmtp6B4BN%h(j|3wNQZWbU0X|JT*a3|Lxw5sp(+G>7iym{@(@A1;`q(tS) zzWDse*0)rAD$V;-gLyu!>Q25xZdu9Nsz|!@KIL@*u@+Y3(4KskSI$H0oyN)mpNASh zhZw!wsDTrKkugZ%9&3NY@$6uSL;*NLu{9Zx2ZYd1tJxY2=tRMii>=J8CC*TN68N;Y z6C9SmAuj(1s##x?G+8EPnjEtoir&aF+$Dt2WR1S?1v^Ko9F8A~X0m-aptcVOhNL#6 z9;!HQd5-Ubpx3ewY3)gW#zU>#3^_HRY(&NJpmc1Nm;#y~{Q*}G5HCLtncRl!XGZ2! z>zTtn0&i(GTPojqxL)5*CjeJgHt^_yUg^(r3B9Fv#{1L4mrMn|_{@I-p61Ex6n5h- z5Qf3Qs@^GGdfUoJCpb;iR^0<#a;E9&&WTe=h9Hx?vO!Y8xDH#=2kTx{4*8>(D2ANy zzpZ!T-{HJSr*v&(p`rqhc$P%ZCo+%c7Ok>|BoH*I?-D0L48-t#XiSx(VjXiK22f5K zw3W|LQiJ~Bfqr;hvY!g#Y zsV-?+&A0-Y?QWH86c8uko!j7?tq(9{Z3Bc zWwYl6RtIL6UWBSuoT@~^JWFkQV_ugcMgN0q24K|z1@4Y6u@Ptg zaeECRK?d}i$ugFyVyQ8vmz{=(?*p;Yka5Hg!-|!LMFtGtGRhENcSJmUs$OP@0!^k` zppZ=@H!%ImOU(2VHVLu0>7j(^S#=j(ff~|7P3ib)%ptmE3sS0F*eeppH{QtIWROiq zpd5d+Az$=LfiYs=`H~{?53dEf{1UlVQ`?Mn^29%? zeOi7fBP+uQCM4_4GraO@RcW%`SgRG{`#N62Nityy_3FA8);OZKILx}qr>b{wcgruB zXEX`Wa9lqeeb6$$X_Cd{qN!N%aY~Q7RUNBHb@hE@5ElkyUVp~l;LL_<% zVpSILS`F8D{RA9q)S|VrtI)S;HRoIF^H#)cZ$yp{YX&KJ3m=K;whC6}bNnjzf1lZ%LBLkqLVV#Nd(jOH;@$I^uC^dy@bi7JgO z!qCqL0CjOO5C4q|l=qC%7`{y$P2AwhfcH>7gW0tNG~0OC=aZ?`4UKh+4r zNBtf$h-rme^AMBPNR5n}^KHd{2|`eV?^C`TB_gRnSS2=LbqQgW*o4&uVG)DI;pFCQ zs9#V~*d;L8-ic_P)E zFL3Y@d0HICL4|?gddro!i9B$j_KNd{yR*63FchgHClpIAyD0c@QhoV*JYEd+nZa>% zT3Ql~dP8)eXn_``apRRq?EveeB1>8S;bQBk?=}O$zBjQ7soqb1HM~F}L#uai6aTJI zSIW{`BR`{RN3_fA(s!r5d{mLcyg-mC@nym#VZ?GpQ-~a6iDEMk>_M4@t4{ zguW~COOQv+{)d+Dj$s*4@o4a z!VZG=l1GRFx>?RTBQNn9epbCXcyMIi9ws6iRNI1- z?OCRNDk=g{rqrp`oXp=}HbSXN(C3J4;?OB@Y>+U9&E_yxzBD*r^jn}&{Je~jLiAPS z$}|)|`B<{qg)_yFGI@%=M>z06{I;YXBjecUD7Y^LY)33gv#&nbOXGD2{~}>9_fKGY zN+90QiL3mB^^Vak`gUh)=mdvYNer0a$11|g9!*iR{#|_V?NSrrsru2!w5K+?H$h(M zfgyQ^wa4?pv$gfShSc1dqW(MsE6HL^FiFFqicAQI#n}-N>v$f;j9oMxF2W-}ewci! zy6^vjuaOUVWZnQqx>i-dXhAA-8Ah#AB%F%8>{%rYVjSu9hLK5E9Z1PB39nfH|KAxoB@?{ zx0Q36R{Zeyi8ruITuKNH9;WvUR&m4fe3XTP!{g(%~}eo6!h2`MI95U)$f_@b$Za1l3Y#D+*Ezb`qJ&0-da1tvrFC2{fd}5-P*^x`w^ylxO9h-O9Q$_Trsxr@URsbrKC-d^tD{IFKo!;>hb39Sq z)I@dpaloEcb@jLFk|%S|Rj2jx6YA;(*hwI@x_FpW9I#)h%I>f$lPA+Sy|O&M_W?|T z{#w=jT&fd{y{PIMVb>*3=A_f>I&K3dY%g%3jsLq7wap>*|B(0Y@ljUS;`dB4gb4(m zK_W(t5_PmmrJ5*JB2fb-0V#oqBtc7*TBRwqHR24QB{(pN%#&d(=M;N9Ew)k7+8$3E zZG86nNHdh6qS2^-?g7TNw{cxe((GFynnp#nLK;#`*rQT*IIim za1cAF8qy|}XPL^AP0C#<9@gLB+Un61MGR_xddca(MCCSc!t&CnFXyA2ICA#L9REg( z%5_11uHs>>>d*Dt1WE6yN@krQ+uxCy-TXDU;uThzZ&I22`ZE^~>)QUzrMJJT%Dj8h zdBdBFS9!b2_3Qn)iih?7n7)oM{#lief|l$mAHdaDWm(#?#97{q;VyFZWymBIm$j7q zPhLK?FO!(1x|iS?(GFf90jw0@%&7MnqKlHurHrR^k3zSgd1N%A@@|CGkAHb;c&4QG z`A<$cD0&+@44HE$U-*FCZzme*m6g$ZX?&RrRG(*N@hukx|lH{tfJ((l-75>WyT)$55 z3H4YcFVS~-^f9~5a^g7iq3e${*#S%JJ}KUOJL?NHIM8p-&X~xqb4ceIncnlhh0A%s z>_D5T++8x^{@0$*h(I&X$U4f+VvJF{=Kytnnk;4Y+;WCNl8&NgTPUsoq9Z~oh~gN} zZ*f?>P&r6J5X})`F>{0VbIeA<% z1CI-3XkzLXB{|HPHz+n#yllW_{rNAtu)3w{3#^8hkw;i9p@CEnif{o}$9<{<vNCtef+2xCquGeuCw}+$iZaC-Q4N&4**xIyik9IVK#!}NJFI5Ev8rfTcpB0# zzH`E5V|n5Mlc1Y&$cUBp0WJh%iue02t}8HlIna(l5R6pH3}Cd9;QsSE*JOlE2zyF; zNw)6DOrsYf+eGtd=pHMQ$6>hqL}+JVe{b-!;bCJCBFkrC3Ypum7Y9T&z3G_G%|0*gQ##y3^^uHg+kh1lpqi zAt!Z4x3G)hrVwHwlr1_XR5Ywl><&*W;8`b=sH`BC(pGe{GhCF9Usg-F^f_m{c^#4z z!PePIY^EvY4UqJPTVoeCrQ?cWDakwx3bpp^)|jtp4F2WT`A~U-t$m6qke>;5j|~;~ zDiQMDfBxj4i;WWz^2=3iMIP$RPY!<2FSh>uG+WeKiOKiNUtxx6ewz8k<<;2Qg>k-A z4RC6BO3D|zIkRJ_sIW7uCtm?N($s7F{>KW@pY4Qv<)ts1Np0MjP|5YU@ zJa?sfg3BH-H2hEo3lPp((IK;Ex~dF@sX8OBY#G7Aoj8PlE+U1q##bZQc!XLovb+r* zUqSmsiU6A_)N6d?&fe=VakJ02gE5u@NE<0gbea>T9>uBVl#E3G-pJIeVdh=!9FL9g zWofc-zEfA67QQ`$NriY|VMVHv=h*kaUG{t9Z>v(ny3~|h(mgOQTr4H#Qk+Oc?6}-- zsRqwi4Ys7g@c~%&lFapqX{2Y}_dWWxg|b-VD&3U6j#5$7l%4D{tK6|a^R!saK__ON zQ(`0RSvW{dIqYBy~m^-s|!1?Gz%rEl4`j}+u%&Af(X}4^%}}-- zk-ehOuPm^^uEu_Hl4{H~e$?D3Pa<%1G>Q-xj@^y*#F}f|)dA2cZNU8&EtYBmR#Adf zldVo-ZJ%pA3{&Bh3RejY@pWQ|rJePPixgR*dO{S@J-S1XgA1mQ^o_GoB(GkF(1uWo z-A6{@deuSnBUouoW^~Lx}YF?7B zI@Ag~sSEGG{=p}<29CKFa?(A9NQ1QJHNmFgygy`qXQCrq3)MaJHJJiBcJ=`L>D;5eFO1leg4AxwHFk~ShuER>KcLTC=I#h)7_vG`tfE&` zC$a1n@pJJLHgc6P8rXt5ha=~Ct96foG-w--%!XRe;*;|^LKwH?zK5CJ{{RdgddRmd z_dWB|2Ue4}8{*=!dN$73Vy85JcCCY6c#!e4`C?vU2rj86TD$$K) zd5|Dc`q6u>{UmaddJk#Tyi4X`rF7U>E@EZY8Zs=4zKWAZkD-bp!I7#+-E>BLh0u`8 z&G-t55xLIpWW;J~yzc+Xf6B zJ#`|Y`#e4oU)K|{O`pSJ-A9VmPJs)-D`MGWQ)E(Q#xU)3iM{@^zUw zv6Q|^y4bDOjMOXZ5Dx)}$?8Rdo#~Oh3s$wKZtx3=;-7b=FD1{GjZ(9aJ2DMK(v&9C z68?()9jJlkC$xRuT)M7O2A_sb_0CbvomFoAeYrgi=#4s%-N3XQs%+F4IFe)@BEbr^ zIC0p>$R`hH#sxkYY<>}9UY^*Dy_eK`KCU7A2ch)xHh@)xKsNp&BJd$R%HB)egS9 z_$1JoBV%`BbN4JtvbBX#y(;qXQSC+2*T$%H8YK!>}<3#p7mV)7lg z`h5lG2~1Bl+8MZUN?uG=@d4_xA(?_?F2_st&{m%r?e(OOjrs{eeuUyEqCm1PVKR8i z@L5!X0P|{mYz^U@DC8Wu2alJW@CBJNijqGDEH}b>E=g^s8M2v*yJnAUpGIwn=u}Nk zjJl;g{Vin<#!uhswXj`V@zv9XVaq19Y6?A}+Cfj~>gMSe4zl*~8h92)d04OgrV$ne z-AvW}=R@WefvvJz36d`3z7Qv;hCw{hJQOs87e$_Tj38K_I%xX#SX&15H%{EK4oEm0 zFs=DlE4n87pKZtCn1#RFx?O>EgCn2cW&GegIL7na#qV6Y`R{y>^Gn5jCtJqv_^smi z6u)2at7RAcZ+<`J_j7*F@r%DPkKdQjZ&w+O}p~K{bW6T~cwPUtbjds2_|NIHl{p(~YQnDj9 zOjS2_1=GnLLB zNA7NIZII)ZTJRpVCg>1>>D)X9CZ9%+!<~UUgEU@kZ7?%#ZE%dXHkc-(NQ87rY^{4n zOlu98KU$w819Xy3X~^?>^koyZ$KO_+39-J!din-gG%mrrvi$QB7rOEiFlc$|!)srL z{pcEP9V-(!MaJA#h_AM&VB)kE@kgnK_%V*iJxaObfcn|`mPMZ|oR>-Iyam6MIo-Q3 zt+ynF6)msNs;!Vb<(J#9qpk1&RQvsr(*2d$#IvUCR24-jNnK$N1M`EIgr7SHljWZ~ zT&QS4)wHv6>PO^QmDYQU9z@>z%iAUgHUZ_Gcy{kC>A}_kCY|H-FdhK9#aQ;Za8Y{XPB%}lws%nS0^MlS z-yQLH(`dBMNrNL5*1ETeU>>O4%jed4E^EhjX?F_8;A(5#o=pXg$}axgI&YBGXom!< z4>;;mksV|kZ&tj%;~>Og zM|?gsdn~YuT8ug#@j1fz9%z_N*)nVWDCq48`*%k2hGe1tqs1ES?Ad+@d4UDD8?RoQ z(>ynL!h!a4=SFe(eq_A5kR$TRp10x2Q^L6CZWWVj!@?wVBB|sX(Q9Sr;9nK{I{M5G zOEv5Zn(^w`A$^I1EeSf_UN+{9OOFl$5gNe`Y8tLa@g1)k*WYS=qe9&;5HAWnB_S2- z!~Ry^CDt3gPWwW%0SEWiQHoG1_{(9LJk&OZDsBTh`Jjk00D5i`tK7QzGJ8T6cC+FN z_w&FM7J+`|S!RV7t56giLw4&7i>h{c_9?1yM>xSM-=aXJN@g04VCy(F5U+`X0i}!B z);0Akn)i&M>%8Q=?-7Hd9>zpk)doB;!=R)PR)*{ROeX%qhOo44;38d z;qWX^cu`u-=Vmptw%cda>@c_ajliPOjQYmd!vgvy3h28(u;?NV7XBZ^3dn{0@?Rq> zgtQC0Yajt_F&-=Iso7!s6+#=f{7*8GFD~x(rN;h4a=<{)q6~*WN%HYsBF{_XuUFmW zWTzjX8nto=R2<-(J(8fV2O^7;6Jp6VJA8{?r#o4=DdAZN z((f3Gnp#f1k2SY^aCS>qYVz*n4auA5IcAijbQ@hry?zUgjpbJD35MxVZ~r6Mb;mKk zR^(RmLstZjlbNLUj2{xHF4|Q%f~{UPy1d4q5{a=IkfI*H{XLC=eCFD5M*_6I|7jLg zr5t-Qp!snXR)3)m;+Bn}glaoV$}I;~5yqmv2aTI++(!f!tPoLNrOoGbo(u2q7ue=Cz z4;OjNX&J;xGt0c@v`q7kG4X9x_t(H9XE1jvY?n}HQ8K#hZMl=Ug%7-|#h z!6CimA%h&M|vwwJPs7Jf{kg(DIT895MTDGIc<`qHfb zi08cuhy7IhMOqut`It|fsgyD+Bc8kD2pUkOM2h#W6Zr}73K*eq?>wh9Ymr@x>b+rq zSH#Zj9U-#sxBl?FO&=LhwcsD5G$)o<3h4=yoZH&_%n}#o89*?9;~kEgf`7+BSJld{ zs%|$XR#HxY&MQ#`%UIruoc2e_YS?czt9O@M&r9pth2!xfYYmBQQy}${4gL8c+1N$3 z=L=$j8PY?EqGgOFh3@ysm@MhG+3)6qE-+sEgcOMvZ1JcPBdYx+w^$48LUZ;6t9Ls5 z7ss-#xs*ZTmz?dWQeoI6tqTWSx}AtaSfdE<_3xI6dJax-o#=db;8a7Nhy$sXQLyeL zw#7wOYtE12T-qv=N3BGA#M)IwBzx-#WD5~&P(~Yaju$m-0|$;I`KNR+qOM)n!tinD&8=&_#0M|a{HoT5^nxklaV zfK;zX#Je>;ev+_HeDV7C_tz1Q=NvRa;%Dx!$){8%!JVd{lp(tI8a3D2wA$ zxj&h2ns0-+Qb1y9($#Zuj8Vt$OaTSALH(6)hK9ZR>ycT9f2xL4xb!5L@0Upb*CAiW z5l`+0!91_iKT41oakJG-l_NYFLt=7>&o1LZ7mVO{K|K~iY?XPfi2ioEL=F-CyT;Gu3yS%}bH^`qA%frS>f$rURTa$iLtbQ z!Ht^JWn{g#9uKisRZn%~8_?fo{avZQJ^I_AzcLgOzYCZ>Ybw7yeqxDEcC^V7COkIz zcIq@T6ar`H?;QQj*WZBtmgsN2{#NO4v;MBs-!A=a&|fxbyF3lc)*|KgXgFKL8Tva% zfAjS>pud85CEZHCw55Q3xJL1IqHocMiXRh(GKL$4`NpGXao7LUShB+VGVwn(?n5yJ z4my4>6UXqZ@{0Hl{?B{2+7Z@x*W;LLc-DKnZJ*WNy|&NG-eWkzt5xn?sasIW%~=5o z!(5|k(?>?uD!Vo0dM~*WMBl3j)UvAMugb~6q^e^YHJ?K@>s7{8%^#_taY7tSiKony z{5qv~$ZrL{M%D_i^ak_kX14^Yt|jn!0-0ObOd}{+LRRWzTjL=mlJyvs$tq=|STgO_ znP!lwgs1E95}i6lx`;y6&=4+^Hpx9-hmX2Nhw z$bYpCmuagSt;3sDeo*~&xSHnDZXI5)!}sd&m853?S9!PU2mu}87!l@53j$ICEt{hQ z(sjga4U1f}ggZ1mTf-g=FV=96+9#m4LuVN^ z&khk;TE(8Tp2d@s-WoNtajf+%(P_HvEsXgVBXfl}1DNwEByHRAytmVKtnoJE zm}`t!@9nXDR(rc}7$a7BJu;N!nQg~-*(*v~gy5d70zjBD5=6|<5j`p)wkLIXrw-58 z;SL>MrNbL^_#7SHrQj9bl{$Q-4iD(?W*y$3!>e?7y$-L};hj3XM29!)@PH2Q(c$?z zyi14A(c$V*f%KXVm;Ft3gbvSEu+8&Q?bqQB9bTftyJTk4KlwV`qrvec1u$pX{lDgT3gm^k7)oi)cq2Liycz9p6 zb=v1GaE?aIaDn_b`_Fs9$#LqMrAK7@ej&j(<^@+Q6A`!qVP5#smmZ;`>R(_3N2Q)b z@eNIJg<4{RcyE-m2|g10Kz!*u9A7#Q$Cpl4eCcG_ODAx6kS{B67$F3xKKVjBMECDE zMe8+M)&NVC0Dr-#o#emi!d4*%@$r=?FoIGeKo2bL1y6�<&5_0{ z2k+(o&@_xX9C|Bgf^pwxfoHIJ*n06f?p*dZLI27=^|JR6TbtUj+#JN%$mHlC>#RX$ zc%~g0p=-ucA_#9vQpg!3P5AapXQ?ISS>sJ(?UT`JZzld~!<%e7FhgoPR(TiUP^Sc) z#W-O0E*AHa9`GAIPJjprvLiR^IF&k07cf&{X$b`?d;`|;ES(&OGNei&9XErX5%@U` z=WFc~-(y$m*Rc+C5nub?uc(R7O zG(1kj4H~Z0utWF7EDd++@Q{Wxboe3-_vrBFG@P%)AJ?!)!yOu)qv1vkXKUEfa6rSm zHC&=$H)AgCtJm-$9bN^@6sYlLstth{4HBdFeMXDf%XnwDGkSLm2gC!fd9Lxs78tr$ zusz7UV|dpq{ElOd+Bf`PC(1_WT)FkGCI)uvgNLs0r;2Za@_htfdwmZ)uiXKL06Bcj ziHLnVTT-$Oc<7$6J;kZXA$}ZgRh5_A%he!$B4bu|Nn$x^-R;d2=QQFTP}>k$C~r<= zRUiFTa`))mv*ST>O#5gWyW|{7uTdMCN+RdGkEqdoF|{u@OV_Zs%g!cQ=f~6M(>ZHY zKS=g!%c1fm1WWWDLBT|y157{Nt&VGUZ%Onn70l^ONAJ|p1M%o36u!pWsR{?R>gX$V z^adThUcso<)Zq;}e5DR=*5Lsi-l@Z@barm*=T1AJEuGJ5(yYa8BAbB(mIotOZ2Ymrw^1{M3iHF>(z>f=fCVA;XzK zr!lK|ej%YsOYp*l*1o?&Hi#{Z7n@|)QA#*-vAs|B7Yms(-M1iK?EHJbtVmyhE-urm zQpIIjm3%dS?E5&aS^QBHlW*gQU2RS755F0wlw^&K$GKK~W^%_qEEn?sX5SugffxH| z@;}a9Q}=l|O^Ov|Wzcpg75&Pk`=j-_pqHR06Mle2WXElFXNla@h=u1v5Kl~bEPd%j zNALT>Df3hwgbx)JnKl94mE8jF)!>Lq54@=8pEPJxUL@cj`$Dq?{JjQKDklh7ufgQX zVgdh6gPzJV0heiTNab9>*a9hZSY?&C=ZSkrWwp5P5O+%Da&gZP_t46pin~bM?#f?^ z`#NzaS3WE5E9^MG7x%^D9#pwb+@r)jtnzhn4-vOfxfORGqpV^hXR}e%N!Y|U@teW# zJN&BnJCo)2 z{<@p!@JEAft~j@FAdB>q)0m`{C7Y@JH|vU=A?ScGR$Y~O_zYyMM&Mta%3H0>Cz5q= zt;`jd*~S{GTjG|j?mVjclC!4QKRZ19bEmLYC-kva@7H`wSgSXXf>V=!bO6Cs-?`x= z=|20(Vqf>kgWGt(DSXw?zR(@+=dM(%L&%r9kNtzqDV3ir1aeuTEwu64r+s!ZjN za73G5mO7_|%Ult^g_6<(*6%V*`rU~B5hv`!gU#0Sfw~c>J-lUjmrK8_AiJmob@aCYRqvZ&hRx>Iv<5QM&l5B3j-&U zUB1jDUi=6Wu&!UFhP6Lhe7=pd=bKvfx7WD?hn>E25s39qLO&?H>~i5`qe9dj-N7uV zo8=S%=n=;9-!M+do;Hr)+tdIGNKAbtR7tlN*m4L z9y_Z3_3eetb1t0-ucNiSu%q*fiFmIMPfrV%r(+pl4g=O+D3?e+`)v~gmh3%{vLl6i z(YY%CmVyxy5uzkSf3&yMAdUkidaIRy&S}*%gK$JIz_-yORcetc$#S&8`2q?mvMW4C zza8rHH!PXMs_Jj)9=N7MI!_gN7FOnzSvH?Qrx5Lq8EsJNTcAKra8FH;`O{4 zqrZ3=!)qcDmx}O4Cf<3A?9QXr(s^Cy7V=?x8_;Ev5;So-%t4cf*(xn zQ}LbHH^@i4;LYnf0X%Hf2-+M!(Pc!W-y@Tq=8*6dcQ|!vque0p1{Y66h$P?X|BUyS zCDy$p(u42&0nckVr3zPlccj{il(y1CoJI>9l`p(H^RR%eaG0nSXA@sxxbUC^^7?42 z3hIY#_8aeBBz!N7NWzn1!{}?O1v^vz23zxG&BYTnt)$nLLEwLyoz|yZZVi1x_pZHg z(G4A%<*qCKTWB(>p^L4#=46;s33wQX`GV?{1!y$?8E zsQpS1oIWm~yT!TiY}??eZ#3pk{ly@Vx>;`C>MBGccmx?7*Bz*S28{$h9IY{lNbCwG z5hSAQXeXw;k{y=gMx!8+b%IV}o55N_?roLq9ZXE(E&%RVlw#?QzM` zdzfjBf+*Gr%7{)EP!NR;<_jo@LRBi7BcLFPb%HXY7YiteLYYR5jucQ3#X3P5QI~*% zE0o!_=w~os8Uja@hg%6aoM}4lBk@U^H{zLGtfA~woqPG$Dk~=y> zKAz~ea0`M9Ggd``tLP4qT1 z!WeoLC3i6vU-b+93vo_O&x!df^E@@az!0t+pPiBpaRmpWetmfj8Q>m)JB=Uf!%@ah zPQr3HmNQ;5>C*Upjo&r=3i-|C_g#MT`N>nrmHd9i?|1w}hBUs7+vf)njk7o9QL-tI zh_9ux-dj9u%CRIZFww(_BA&7jp9p?U=@+jXRM{gZ+5WR*4+1-(!h>yvpCQA=&f2~1 zGa^(T<4*~vs(JqpCL_luwR<2=UEd1b?C{_=SGJ=FvF?TL`4wb3gz_#i-{Wn|*qqN_S6S`xWtkhTx8BkD?81R| zvW8DeiG-$L&F^YFjrvJjM!sMv;N3tnerDwkWCr56&AB%?oSR@hjBoEnQzId#UYa4Vz!zT;z9-O z{Nk|D9~4+T;`rbF*VPq_IH5d4h27qsyn2<)e@R^-Z|i*{dcC8AAK!@L2~p_L)+j}{ zeC%2JCSRT-yAu&RoL?9i|95|W-M5^f;_krvSVe6RQ7wm`H~rsAsH^A(ccZ3}m-=Q! zPs=?$Nr}ZhE$@4lZjwA`V3TAD4|U+udV{2Iy7$N8p4IaF`mg}KZKS@-8lp`tP zX0m{>A9E zVi4NE@NOv8iIv;XOsA7KN;91aq1nzv#N5zUQ0^|Xp6W{?7J;X_k8^3{;qqa#t;~9) zFD#OhO?HWc%a9ifWS(H%7we@S*DH|XfYH_^@ z^~uAU)!c@V5PjH%NG$T9*+jO!`5RfZm|P`PBxUo(GsE`$|5Q>oKA+Q(>I+YCiB#!+ zj&~wWwHYN9rQJr&<1+e4k`{MI^4yUsXU?YBZGj{5KBLTu@s>kI!7iiV04gcIJCOx_ zdEka$nVk#D)myyC9mFsS-izGi%spxpY!pp3*NaN*Lq_3-*wrY%zEZI(`}vjVw#J%m zve^?mTk&H8NA@lJcQo%xHf^H6vPu%8d#<1boP+)YBwQ`z`FNC_vjdGdTw{t{Vq2}c zOJp>}UN=%}qkKaVfnU|^-sl?|J6D`7?hd4He)Q))p_%(|#-(Eh=K7Lzoh%$XW7LMI ztYgo_u{!;y?u*)x;}Vx#(Uyn-^OK(}4!ArX-f3SR5AfBO$4_vE7r3qW_^Lb7`#99? zQIF4l4d6W;c?5B7!KiX@P~}C}cobEah&)b7z_{VmiM`xF^A9^?WbW$U+JL zXjYuqj9bZOlt^;Vq($PNVY@5Eovqx`*r06p0y=C^keGlCHu#(d1$7#p<-6l) zg{;D{b&O4c6P>ZVgu1V21_+Hh4&bB{pbjaE=Yi zX+&C>Z-Z_PX4~L64c6N&%2eQL^>zntBP4d+T^U3VFBiTVtg(DJ2Ay0iel;1G@A4A9 z(0aILAc4bQ3^NO5AK$@tIA)8a3>0~} z9U7T7b5_y(sh@#VgLE`zaml@z7<6PaHMFHQRJJSeg*zkC3s@Dw3j-pm4OK?w8pR}1 zAsPIYC#;$DAvs3>#4$axS}n@B*rt`;C8#Au;j>$NueDO3*~rQ0=Ta3&{UZA#466(Q z{sACl{$09Lh6;(l2TzA@W4r@Ca_fQIiNC6CtL?zx1`g>BgnQJgLym|VLA;l7F+8i4 zw2*Yu3cL*uqDbnC020iwoISLr#v7n89JYW5&peg<4#}lEMBqe3l%(T4%oD@&vNxTi zM%GNhFT8zJf&JnvDU!d8p^luVBEzXt^;x9_foy3b$$X5C->l=$*7386ubS$Tb}_IS zDg$KUbb@-FU@-~op^@t3sn8V)f02BJ_n6A>Wp6-7U#;_Z==v-sfogo3#Gb7)pQB^1 z*Rh-FBFTQW&b~*5uTbJq(pt5uVYIE(xpwP#T`FC_c#$kg$!CnpcZCweQC+O!_se8W z)!}M3Q?C?Vj|Nq4T)e4Y7;A+NuhQYqYq&(iTQ!^y3_^`d+)(2Te4>N-V=aACNe=mk zwkOdFNA$apSY9IlMb6eegb6Zp0NYy&fErT1`O;{MTjG({<@@XFMPMZP4F({avZQ0sXDg-#PkQqQBYto6i@dM#XV3 zY3vnYWWoqlHM5sGY(8d@sv?|3zF;7>SsSy|+AFCOZ!+LLr&?GYaj;5(&5}4%_GK2G zr2yTdz`He^FJEA{%m}vo5)B{H;Tamv)Zy70PSdbQ!;>}a(C|17_ei5b@s$b&)$8zC zI$R9~jP{VgAjn1Pi}ZvJSA#r@rt9k))Gslu5J${&dm4L4|bvWA;AJWj(aHC(CTdJWIgaFvEb8V+a}j)2|48h%d0 zb2R+8hVwPtq2X)|H)=RT!Rx&iFk_D{6&b$WHdKK04^0P!$!t-xzyYATL%bB`wL%*`%U{>}Wi* zR8^-!+vB6I>Y0tVebO+8L)0~wsJAc#6{V{XJNFSq^4QgW*dk#mdfgO_m8s)UU5?&h z-1d4Yn%TcriVDPSuahF5xa~Dkbho(e_3;RN7&ZF#@_3|1gAHmmJOYb~NqrwEh>{R6 zd}NJ;kNDY6_4#9~9c-)W5j@d@2hsj`P=)_;zY6Dw(5c|xrIHJ4_PhJX)YaQKq55pZOH11#(9`dbbX3wnJCx(3J{&v_^;4+o3P(&?-B0jSdai zp*wYGi5=RiL+99`2X$z^9lBqKX4|3iPF9*wulnmz9v1_~B@2Hx7Leg%4j3aI_1b`l z-#;=_xkvnLs{MVmfNxy*{dC^B+_~cSRcs8p&9}@qMX|p0YNXIw#}jfb~&KsFvi#w2O7`4JR&P$m8N7LUWB!<)8 z*=B}^b5~Xj!6DYA?Q)Ua9~)|&kBj?g@BPPw2zD-z<>rsN)rqo8o(x65M@8fM&UqfS z3G1cX=8t!7$=XIUjM}RS<~2$znLd+8izAZatV~5L#;!?vWrGk9?)VvhOd4C`5nL;=qpUa6<>QplfS{k9Ey+Mq@@^Zqwryf%q%(3TARy$zS%Br4o8Dao}} zB^e`L1j$l%ST5!$q|p|h$o%Gj%q$rk86+|ptNOXXn{8bfkXUhAh+dzNw|U%*ZCA6j zr>*c{Vx+id-D0Xm_47Uak>6xD3}+gl9%B`E;VRu-Vi|X;*~A0z3j@^$6aB@Czr%bt zDpyHA+_&GJ?}@AqO>n6`n1C(>|Dn^@=jGvR)Z!dzg*LMOVk0S5n2RtCFS7i2X{AdG zaFT&_m&B6cxd%rO9-AVO+v}-uvWGr#$Xb#Ijgi{tQP7K|Mx_IPNmI;~jw@cy=dU?n zjD68g7kYdbRz5`6T7M=#R*`4v7vlSx<2**9jl^~?ywMb;s65@|Z+Y3RRtkt$X8TJl zmFt~&8o`L5#o~s@V^VC1h5AbhgTdb5Flr!$L!E1s#x+2sl0NMWSL_ZKccR5X$lA{v zHA0w(j6K)vn7h(gJFPcT){EMev(Yaf{Vi2G>Ae8fY9^zs=tQLKMCgscN6mrb0sr{% zr9Hm!uuvmq#|b+gdIKGhIxLeg)O-3aH`bON3$`6IzfhLAlFVIVcPy3@>>4c=qEHa* z?;u|AV?fR^_7`~c z9Z;Gvw4ET9PlA^b0>M0|S-puczD%L3>(2*Cddb*7_ec&$lG`X)8S#Tk$PTnCYok&7 zEDJH`bESaUn$qGFwn3z{8P@blSzCoW)oLu3)e2yN2x`QY`sAXXhin?S;E-@qxY6U$W!ze|ur8Bqg2r38l8Q(|TbFS>)39 z3Fdp@!sl}_CIo%fz%JR)1ye<%Bqj@&+?3n1AQ4poaI#4zv#3+QeP7xtlU_;CG_82A zz%eh$y0cYHJYKrXWHno?NB=IUp{Y@(`BNLkZLgQ5-PtZ8yczjJD_T~~!}Eq)Pv5U7 z`a$L6^j{FJ?GOd5k*)ka>HYgMnqUW-NDc8WvR0zNHqbiv%B?QBn6{?;QO;`gjom47 z6qCNOKRxzGb>q?#O3$7VyBhkj^K%=Ve;Eoh%^qYHM1Nk=Tva(ynSjP#HvEcCvtobD zn7cCagtVZ&uuBR4hGhpZf*s^dF z#~v`MFDf>&g;-Aw(etbE`Kw1BSoim)kyF6X)JG(xP@thDs$xGw;y8eqO?TL~_`%NqvfSc6NoRa-qvN!jU*R3Vi zJQ9x3K8B5tYej*TiMCSTJv4C)ds7( zoSbGG>xWE4CuxV-v3!uEK(#<`d0FrFuzzn|QHE$a`!~t3xEmcTs#9}zsBZNKV#&fm zto?6-1JylTKA)x$r?kG(E1i4q`ja|$1u1B(-MJN3E0ia@bDMG5ojZ*v|3c>`lYP8% zhf#=hZc6ZB1OU%#E6Q-jQcvn&4TKk@w-vb@Pd3n6DC)keX@;*-dg;y$^wK$%ReY=^ zcd1@N%`i4LVWB?OoX=mn|OA#N?RX1yj$kc-w<7KsQ?@Dd*l zL2%eP^;mWLSch%q+p(eXG;EzsoiyG0)gpF;3wGlS58KOMbN59spt<3Fn~_FCeDU74 zK|AqB8>Tb3-SM=+g-ka!ITx zE+x}Y`D6!!Xb!fvOIWsq{RtOHdYY)W*`ADA{GIJ`tPwmfpX6QP(!FL0ceLGRiQBA7 zMYThFewq|u&Ps33&rq&K-uC=VaRpm5)wH2|tl~j3*t%EyCi}HYPD?I4r*oVFFLLt3`P`s1tipt2PlWtRW9q~7QXj(7TIV^HG@E0u5?UwI@ZYIlvA z*ND`fq&9;hdouvT@b46KcpC+X1dfZnutE}_P&FrS_Jo^U1h6OA+emw&j6Xi?35j}7 z$fA_mW;%wEWlx}aOK6_xO668jTZzAoh@U^b`2#Qqx8aY}#C!mP@$Zv~NmG z)wC|M{}-CJgaYDCTPBJ7o0by%@c@iGuz9+zXT-=qR12J08pp`pv%g}3-WZ>tSEvPU zCsP>t6+4+sP)<=z3Mm)1#8){uIr_$N(AEKKYL(2ppS{8j{v~|WLMf$Bo94X9EEM`e zWj3xT7kj4DKim0!bb)mEd~#Du-#%9SQj+%Xe4C-#+1=fS%SI&k6Xjpn`3$m;?|dUE ztzR*craX6}}mnu&v!Yu!sE~)&?Ia>%H<7|)?S%)M4~i82p$J#Z!oA3mvsFr(605tI$sx7TWS2ht z#yxK&=RNBeFUn1!OSX;GI9Y8+v4<*mUGu$Q8&ZAe<7{db9GcCQjGgdka`^hKz-@y% z_$#KFpBAuhH&92Pg?gb`@r4$=O-}&p44diAr!F)}rWV>%JDCt+>hLaUT|v7MgV zho9}5?z&f|Lv+cJTvMkkXwK!1$`vvVp1w{`gOi3kPH*i- ze~zjuI-1_OPfjt?gCy@;K->_vPr1JRx+J3t(p+gAirr48TY9)FX| zsNsg~2oE*KwwQ}sT)j7;c}Aq1dSb~aU$P|*^|+lpUR9^=+;5fZ@jBDtXJUN3II5n! zU{~A8&bVOpXkq+sRO|+OpuT~c_!4VjgVOKx^|Ib`q~GPJePQrnw;P?5$9^xgIJb3> zuO`5Kh7(#!Q0s0)f!?oY(t|g-m2kGKx?k^;RTtmSn;K-pKbL+HN&KU8)PgwmzLyPc z9y?d1so@E!5uXS8LC<(UWWMsDv7qh_f!Ji#TFO(wV_i-g#~ zj0#tKB8vw@=GzLdAyR+~dXC9`-OU}HM>i=sIiDNPoKV19fBn2ALy2P=g`#`-5`V`f z)vd{2_`e44z-)2uQsz7EPxTLOpP-1)&>13QFQiJ?1NwyABpewwiCtk~?PO6px2fE1 z#>B%S&6u7WKdJ8&dY0_|MQYm&uQm>nIUFy}eIr43%ZFyDHVD6fgv0P zQlO%Qm(nW`8ha>qNF>j=`MT8cz70ZCX-OC4d6B<0E)9ir&Ax<+jZGQbnX24Bv7Py%n!~F6V0W7J>GMt~ zzpQ@2KHUKJK}x7Zb%h^<3jcv%Zr5C9qP2;@d5UrHhD2)@4EPw)%B|&;URU^!P~j&; z?j~}NO8U7@deC}Ql4eQ?b-1Y0oRcmN<|21{zPw#N&DLp($xu`AQi_hnw$zQ|gAU>C>TWG~beVLORCRSGNyP$`!k$I^jD4%b5_`s~lhUbuv4l7r9oZt~C38XXA#a@Uj z?DCrLM8>8ysup~LmMeGggT$=u6j5Rnb(o#Tq>ZpE(z7<0yPfZ5Nzn!2R4=(sjZAVy zQic$i7f$g;rk>jyPWJ*$R_qZ6+e>c*f#iqN(2WVR!(;BUE&&muRM?Z~9}{>um1iu| zsmNE?{*&04l~mvJPh#aIQfi9-M{Scp0knZ?ilIH>FO`V;uCX+vhSQK^Jo>SXWp6M@ zQYOYB;*5F;&a_&O=kAU%j+_~?9PX?ZMVO$dw|63OrN|4-JI*wAmq+`)|}uno8I zIJR8UZ^A0$K4aOHQV|~-!KH&fxfSk~%lgJFdzZmN0@e3$of;|EsRC>WrNf^8im{fu z2xCeuakz%mD}#O+1J8wjbttr^oGf^?hVW_^aw#Fkm^iccd%!Sj@8NCsnA6wvCE?Nf z;b!%3cvZlf_Vew1K(S~S;G}ZaU3}H+f_rd$byb;?_H<+#88sc;1EO+EqM7OBbP_+s zM6`bJf*c6z1w#)-CLA)_ns*wR9Y%SpQNDSuv2%+tv&ESC2J(j+5NT{ig~XEf1qMZy-NAcsOxER@mhYU|(1bvYWA<4#Ze9@@_`?wqxcy{jH=R|gg+^s3?Qk#d|Z=9cK!h<-EQ(Q*cAIf3hJ<#yyLic*}&?&pgpX5zM zNp{JZn1jP9ooB!tN`_kB`!%zH`4>yEX5*yJZq2{H4bYm*ABF9|C4rPqRq`AhG&L_( zp&xjuHt}6LD*8BnjFRp!PsEj0USfGlO?mrtd_VuJy-BU%t2e1)DHN1*cpO|}oln4kYxOr+NqyJq+pGtkiJ!>t!)2ey<0uCa42dwVZyX-i5Jz&HNEOJ!ebjD&$Px8Llv!b=|Ijn%)`P~Y%iBu z>lV{@kUfdn-Nw^vl${ELcPD>}<$Y{vYl-#ljp~d8(|mNGx+~Ft3(O(KHy5tCbbam{ z_DFCN>tO`rjPtGp|D9p~{?jMdIL$cEu%@q(!+M5r1-nQr;~n6&y-_Pd+p){7D+$+! z_-vfyW~ECKIdF`|VMl&S=3Iq!${0Psxr3VmvE<+b8SMmQGj!I-zUgpOwmlsm zqb<19Sl-`0SP{@B*#tD3HF8SUX=H7lARpG8)Q9XK_%Bi9rJK@);BV92Y__8YAp7)Y zTYsROV5@x+wR$RK&cd^^F6&YE{e8;gqzNhKy^zs&-fN)4?ekvnIdupk9DZ4v<&vhT zL!3jJB28XUX0_q2EBrWAC`Y#a9N-St6@D5jJOXq8=#cfNr{c*r;o<-{;p78cRr~uY(yL9xw_&bp~>gqbBL4L*>X}7UfO=EY=^2GEz#$*?lfe4m~g_g5{A0S zZy-ESh%HSk>=2w|)ZT!9qzbjTay$wwax-3nzO;nZUYMfYR`nh=*Mil1u|r(gWwU$2 z)%#H}ksRzzGHODkFxD2o&y(g4LajD)GO#}}aLgI{lP@K3jJ^F?qSW2z4je}aOC|(p zaKh<(dWLQOi!0@Co|IYYww~mxXX8^it$*W>+R#_w=xYZpFlxrpg4q4$I~WZ((h~K= z2G^CoKQ~fvodb$yCQeX{OQi(?yN1WEu+?A6KiuO!bFaQz||l{rK%UYJbWEzm^9O zCDwQXz8t^(v_8IeeuC?Nh2KPxR~*0XCGr0Pzoq^!@!QUSj^B=4_fPQKZO#9;`0c)5 zeKmfYPPm>?B{&7Yb0ptFs22RssW)5Ez(b?R$d$z`$sUwFj5# zj~m(tO9IW6HBYE~K<)imeVwd8^jDKtY%o;NL_%%30W?7ftMvPS8_+7fzT`eShkb2= z2&0YQ2d%ciJF}bV$afZ5BCduM^<@4c1IS;FzNfU|1ulRk)+P0RNZDthEC|gF4 z(UQbfz@JR~G;1R?K5li{oZD+eFfKZX60E;)H_*q}_i#!ZYZu7A19rX9;k(^hje@N+ z)T7PpBG*i*h1BQ_HQD&t={1?FYLZJ$V&67|%|Ki{08W zqv=#Ym4!iK#7_~<6!wA3d(fVkF2-FZ=*eQ8)Rx$p_@`?tT^Yb>z+PpMh|1wsa-FKG znbu|3%aRyCo%%DA0fxp2x`Lzk`_?y+EGB|Fk8h&heOTeE*H5X`_Dk1~HF~@{C@l<* zlj%GH=u4*avq%45ozBbu)1J=z2E|MKznso@96Egx+0%LFj5AH=;S{W=vw>4h=N}H7 z&VOK5o<6q_kN9WPdFL0W*TkOAQ>e-R&!%%ZycuR||KU4HO7LhmaAzR@n0q)>hk~{dhY1cq!u*gLj4uS+RAJFiG$R832Sy&cOdNYBNYN zfTv=eBv3NhPAWXGxIjsFoYh<@m4e+Y*bq$?){w{T?FD>&jQU}X;ySDGXYpgh%eZWr zwq)X?`0;*M`vi3}dh%uRfu4^rClUa|1oD4s_ADQKY71>yk7eY2Y73tPNqkug{WHI` zb@S|GU)4JHw#?WByZ?`t2*;?9hQv~BpQ!S=8Xva4^YvDadZMPPPA*qhP}9mWxMD_= zM?B6GkF6s4;TWyfgdAxs>wyns?ECIFGhxgT(J>2dE3Cr0@(Th-*m=GVLam#AA?lg^ z7e+4tXq$9_^F?Pry^Ii}M$qoK&BpR$bh6f^v=CiNTGOTEvsv=_o;z?X$@hm)mv=De ze);!_ZLIAKr#`lNCq}4C_xFAfF82gCxMG)u7p8^p^q@b1c~`J2GIOLG_Qk1w3AH<3 zbV_}U8l+HqmCCf0zzKne)47gKC;Pfd?z|-bjp1v#AHA4>wgqf&R#+%pK<|x~{_E?m4xG5ssBu%(z=_#Lt?YKuBjn;rq{0Y93nK{`?514$>BR)3tBqw{ zoGYTDTZ|lx+8qMPqxb&)QAGI~_;XC3dT2KCd^b}1T)4PCT)4*E6)s~h_7uq}YZO0D zAf=~LFv8_7gs9&%mOV$tP6LHd=0Y~h+bK(g7bU(&C?1|tp_8C9%xT`j)36Z}co8<@ z<`n+i;)+2$zrYzbPIMS+cjux1p({L{zt+M_!(*Rlp!aRt!v6ieA4@lvd-|;lW88d3 zc)Ev^ZEOm?D3bS=QIX!klg&vY9BbdVW5XyQQGp!MI6}{~nN_D|)@PNt)XLp#EZa)l zJXh$RPpOE1zj||%IQEHFDnv!f)54QHk@?Ch`6rQrYvDcI&xo8oO05nYJBSADj4BvF@y0?EQ|cz2ADTGYcy-dbbIpkt&~KCEG0}8Rx+A8X z&7X$fPi(@1@51l!G9b|vY4|h!*hQa>FY*|*L1Kibqir%Jce~FJW4*0%cWq7K zsxU7+DQ$dFn*Xlw^we-!>Pt?d%#tWi_C=W#n^ZR``MRQHW7Wo3o}H=xs(6O}QP^F* zO#7zCeSPOk9u@ICBxM5J`Q2)6kl?eqD=(o|Kjil)zqmWzR{6&FBX4-3D|{7#lT5Bd zu1H>z=*IC|#w~d6)H~>;4F_Tb%Fk zHMjVylvOHWZ}hK!g;L(5)~cL8Oie zQTYqiT;=l<9IQz5NY*FZfY3=~EWd<#X+nPiBlPgjB=>~xJ9J3h4Cqwdg3ABB1-s)f zO1GdOmp*C9*e?7mW9_J#O}=w;npIOUcF5O%b}T2(PY)cq(&xp`H~OX`g!fTZ*d4Ce zkKBAtFA8YmuJb9mRD55jYaDPHmi>~iT^Z*-Hsu?GM-zM#koQ1&R?j!)uxNaP0ykXY zpIkT5%?;<@H{>N@CMdz|%-Qjr6T?7x35|kBA~RQWKuIClr4 zNt>|%?=%WJCz_?rv80t|ai_TrV~6fgWWKd!gvhuX`;U)w2xf~4nXN%IXQ3=c`q{aJa;S|kI+6jr(AqmXab!Z z8!8CfAyvqCI6Iu3x$O&PM2c6-z{wd}4cr9t@a4s;>9b%R8+q);)0&nbVM5V}4HMZ^ zhk#E4a)x-Ev4K5=5YCZc>nw##@x562{)7=2!|%8J=8^6Zeps<}poG*hieCo5Yx%`- zY<#|tGmCfEO}RkL`a2Yw1$!Wr{zr;-Fx2NZ=kx|U?77mOFM`0!I|-?qm~O1?SvVA& zIy|R2x(+Y&GOm@7hpFj?eZ@WztNJ z52dkObif;HzfcE>@Yq+z>|^4nLk&`JRcRRfL{pXwWLu;l(Ve^Df!gREQebvW<;~fs zW|LXb<^PUgr6k|&dM!SZ&>$vC-^EtnSKsdrD$;x6%(}tQ~?p-JrnXD}9#<*0^ZO1;VJ@@PB5rJWHUTJhe_`odUtluEI7i1-?7#K9@C&3P33Ix*Or;446E z(tq1YThzDuE7;fVIh$mcYKiYsQ*UOMYU$sl4%oX?G`>p>UwU}pE+woM*V;&tj|PLSZ2C3u)R2MhQN zAScmzh)i)Leb@Sq?Koh~QjWPRVR9j2<#4QE4gQMXANgHMpM00!cz!qWyMtdGSI9Sx zFJ|}O7x$ZmU3HT#fLeEP^cAvbn{=TQ;Oyvg0LWl6vmMd9`D>py)NRtJ2@^Q3!&n~V z8+boab`zyifYc8A0{0Lh#@gxV_D=F&9Uje%C334;Yj63Q>Mn_l9h&=z@A|;8EBxb( zwP$foF>2;WUYuWk9xYS34#u{SvHV7r&!%->qaMc7+&UI91*7r|fW$^E+M;`-mq{G4 zZzShM^=vH933)+Fkn$jvw2pH((seK1&z7q}K)0h`U< z`%)jP|4^>RU0jW)dqf2xmm!5KJqC59T0aWTGF#X~Qr zYMMOSv9I<3 zXJ<@1EG{nGkDHr8%&fbKa^V(ZklY%IMOvVcB{`y)3-pN6^>X3fp4AdATrK@2!d`Oc zp3a?n6j{nfT`JdYN#ZHhtN09e?kEC{OecsRyQPN|B_f&Gofs7?X|`}%le^kE99reN zmKy1xhtxRBU3-kg#M}epJ>3(zU5)p<2;vDLvOaS?2P&q`0HpDmZaM7%z2&9Z+^^a;Qb96`cS~e>H!NwFjBPT%8tXg;QTii^eG=ib#bB z@VA^u0u*eCOdTRe(A;R4>j&4J$jx#D{d#nvD#v=uufD=Dl(^ zSwPL|{p-M(m!B!-qIk^y{lV?#EXp|fyEsCi`)A~UpuUZvnkir`7rJF|i5o^IqR{dJ zof=|V0ypj9P-`B}-Oh-};_V+1BLUB|qL1Nej|d`}AxQ!rPaiIHOGYHMj={K+3;*HS zywF2?KsAzt_E(M1_rgW)@F?l&LLM^y_DFmtQE{lZBXgQ_i`>Q|qsaFEQ1>qIQC4T- z|4cH#1P0$hqb3q1>Zplgn`qi5B}l*wpal&|pck-it0_{qwaJX2B`{$^$;_N}eQKD+za8@>PmT z1UUV%D@+|vGM^HYuu~{-`HRw#f`mC(_5UgM`=q*5tnt%E(O1L(UB|!Z9ipCm52%Vp zJc8?&`2Rfr@@@|Q-{8N2|9<}W@&7*mG9P{|BH~$Hp6Ma+S7bKz=T>pE897z|7gg%P%Jn^oS zPfN2^^2`0CL$I5 zC@Utj(Z+*zd;&_}GiE?i*CmK4`7(hO(2BSvuLPv}KEp98_dVVqoUT}fFcK<2=+E=X zN!Np?g!K8ZG5unczlJu#Oo6ma6cX>7b>8+S?|xg8_drUd=3}%E?>adVf(G=l^0w$o zW9Dm-`{b-koYBxh93sf$%~TF8TT=s(CzQV^YhC5Mt>*um{4eBxG5^31{}biz!BV|T zZ`F6OK%GI#f9<$&8^?{aKll12f|O3Ybj`!YuV<})=wahNJel#~PpP^wwm=*u^fQr{ ztNZ)sL`Hs}*=cp=_-9lGUT?qZ`$Oi7MmF557Hu54r$}j0( zxxwfA@osZliitmEY__p<{b2X9MWgGy@i#zpTQtDWL<#0nb>$mivl-0)73M-Vj*C5{ zhgr%4g~x@XF0q|#uLRWmXW*z7*xpe`NO}1rmJ^O%`35L0$?_twJx-b)<|~5v1hxn2 zW_GI3>KiBNjRg9M4R-~y&pO-c=1q*(m5z=t{5WC*7R2}3yir5pR zqOSBOcsh&j;FYAdOon8RaItW^LG<1<_aK7 zH;@t4+9u7I#^kiNX@AWzTQ`%uy*3nQ|6*;^_L`o4$9rkUUYD zd{fi^$@zckqmS0+AKkyF>W2L73X>G3yiyMyeQWS~fwa$VtI8x)kzkZU7`2M@N=N>= zjatm3w{MdKg<7u!6qatBL~cPab$~z}n}OTIF<184jgy>huLSDmeXawWKu$~owX)B8 zc*}g3i-ge~b)^$K7>qfQS`<-60`6fH=g}!-AM;N3mN{%#0^|Pf2WqK^$O_Wi+Fwwa zw&@CE>ZJol>=Z=Oz@ROfH^JNPn|sM%`AZW6#R5iRtXlNAHCp>?!fLd7WVH0RajzG- zH&GU@zlxQ@SVR}|CV95mn@?Nx-OLS>#3m1n-J--Ov&N@|GoCh|FeuS9^f9tN01iCk z1nU!&l)ztC=vgAPt>|Cu4_)WGIr2EADqq=eaKnNb+DgPa3?q^YG_+Bh8GE)QM+n9+ z7|G{GZl}E#WL?a%##6lnTP%xAUSUF1+{WE}W}eq1;e5XSHP-SM@4=Y*?lV&I#q_QG z`^O7$#hDWcjp)LCwtt-OMuQ{E3f`p^Ou-K94^F)<*x(E{b^8f(m47g}EZyeIk{CZs z0V%g-|FGbBccsIAuxgk=e8#)vJd^8X++mnuBPe1N3r9xU3L(Iy+XI}C4&a33XpS*aOQ-clC%yj#HtFX&9s z1!oFOhFfvAf^UvjAc=qxKx0cD#VF>{iTnbvyi&lL!ecW2ii^E-fN1B6gNv)^#!Eh{ z8~@DBMdSAb@EbIK^M{Pz!;yuMTVnh&%<+2|AH*6gSVjwip{<`Xe!pIHx$$HFyW#!V zD8GQGIUC?#ra#FI@aC~`?II`G=3b)Gy6@%*RtiwTIpxBJ@i+6Gt*@!%_?lY?Oz7>9 zZzAh1sxpDkZqcF$Q<-P6GlBDjsmy5{;j7RUby@a)bZZ&c1jka0x+*WuUhbwc85b0H=;{Fs(Rk|cx$vr!HELv7+e+-1 z?u^_*W^zWagj6o3r=+|T4E@XHWzA@5z@_pM`c%MntMf2vtKRu=#51V18MHQaxFAt+ zqNxe?Bl45|5IIP1S(R|T;f4yd&*@|3RavjSjY-Z)?BX&eId%MlU^gfnF zhljEVr3`N>Zh9{-RZi!4J&5YMmq;mPL+$JNh4_EI0CT|la{>K*- zEi1y+eS@fEaQ!nmPR5}(=k8mHst1y?zls~JT^%VIclist(Ua9q{aD!YStg3l%tcj3as-9 z3Z=cYukF~maJI&V81LSj7dvitr}Z*7BRbiZY(f$)kOsuYZJ8(G2}j4SF<(lRv61Gz zR1tZZPAf(_NPo)_6rSnQHf99RKUT?VY~#0Eb2mJOYL*A-o^sW-o;#7#$m_Z`PGzvI zqlOCIduB75mmK?eE0@6ev_)xw#=N?D!`_XJA=lV}T(^+C?KXZ4->`R8e{!4WqMk31 z9FZJFSmydi0v}lQaH=mtc$0(sU5B+9@tQt2g;dU035dK>FfG32E7xw?)pZo3xNYmW z6|q_2*ytx3C0}k>Z|OP~J~iyy4UcJ?)?O)f<%Vne`aAwOjF^?1R;QWmn?3QZ3Vp`J zW@FifMe7L;NraHcmfXBW%F^4rj+zA!)za#a-d3TPPHYY~_W>`0g)AGX`aH4a!59t- ziB6k2SU(`h+Z(Fqr4zSnKWWJAn^TtPcb+20;sIVDD3|EJjEC9(Jge7p)#HClf4572 z-~Lba_w7si`_4uEl^ltlT4Ow@uce~|=gcv-NK0MlFXm{x=JXn{!@|M2_27Cgaonww z6eQd*k0tVxCqLQpdp?-+DuR#IYeSa7+vIj;u`CFxR%H?y-Vp51?wCz;!Yb zm{>zaRks+m1p#il4l8VAOi~s+b_85pM^r`Ri1GLZxa3yJ!jjsxcy3vGSz>$!@Kf7% zDT2;ZL-oG`KP&zeg8mKrs)BD0K~U+xIbZ^t|NMYegw%+ACgE>Xp*Osmr?)a*w{VsX zN`ga;+pBYJ*u#t)N5A+F4jQ;yKW*TSJFS81mZLipBRBu~fsr$@&TKyd*JO8_Y!ekr znX5O{98(QA<#^)2G}tI}r%$vgHqt6-7o>5gQl8lTeXQp2sWIO^ljJFJtj;7;EdO}x z&432(crNDEHpSICWU%kC%DlnloKfX`IOf}XAIoi3VReQS;yqWPQ*1l@Ws%8Wu5P`5 z2!FZyyK z=iMiV!e^qu3-}Nk_|L)T^ZRg zi&Pg#Yh6hqO|;i3_%8Na@cc4set~Jq`Ek|Xs6lH@yR9l+IiFeP+InUxH;jwT)eqFL zV+hssMpQS;Tw8BVRw5a9bkvo{x5DIXvD?F^t|Y~@=ajh?*bygHKfsrPW0L|q0=Oz} zr3bbRll1*^IAwG=CsSr0b+Tf9x^4z@mh*;Tn#3O}n-lpzSgwhHVFUa&X>UFH{(r{a z8bh6*Vs8acPX|8DUWIbR3C|{L6UJ$?x1KwUpcc7^Z)5qM&{OWvm(xRwSyCXz&0%6% zujtpy*JEFYoP@R}uC+e%m&6rAGY*xw^gbi~cjm{q)n@7C8w^Lik+l*RkEkfm!RigH zm`ws+%vyxJd-}iU=+E!>xAsd&HJ7-4jFYr!%!s_EZJd@}$Gqb-m+sw+$4CZFFTQ(l ztn5kkRmnNI-{2td2}Cofm6aG{GT*dg13-+XNgfGWP{HiO|Q*0RT^LM8~%JsUqNIvM6#^jrg`Ia=M zJkgkDx_@b7?p2MsJ2a=;YJm4IXh6l9&;#8UH=u=s&SeX=Cp0Hwl_e%h_*g2AFR^Sj zp*o-+ur&1L;}^*_Web7#=Ip*z^*!6`92`T`j_`LaIh z#`Kq)SZMHkYta#HMWM_smK()toWsXcndBMZhfIP^zzY7W%a5+#E48btKi@ycVLZ)L zB8}+|Hg;2aBOdYIUxo-{?`SFV#<5o~iy}S;D;BH>1>c;mxYU*aif3%tmY2DdMMhN! z*2^r{8qr7RJ)V$+1N5Zk13lR5-t^kta_Guw-wpbExMGg6ZMlQq2TzK_lD%16;UvOv zEUg3sck`VBn1koS4%TF6Mxru&!D^Sx&}p@I$XI$^Oc-`MwdHYg>J3EdIo2IK+O5@g z@JuwD(RmVrDo({Sof6!pgvSc)qk8^#S7--EXY*{|VSGhSb$u@(f3=NO{T14GKH&NZ z*AKb&RcPNhZN0m|^&Ia~dG|5@f25#JE6rY^J$<%9tK2)TLhEa?K2Aw~e0Q)>U{8XS zNJ-zIhJ!tPb)K*G$yfWd72gL9xNDs-)1_0$Qw@X^>XX<)E$?&FLVTgO{lj8+vT7$B zcczOoT?gX}{)bZ_lA{o9fcY4EW6?f;4EPa(Gj*mbcmJz)R!Ue#xBI`uP755Ya(6sE z`JDH()7*fuYEGX19==q)sj@#Ix4IolQxJauh!e5A_R9+L?N*?Erm3Sdc{5Q4Q>#4# z;6qC@2)xTGRZ^dL zda_u({DijhMyh5h%#<-A6U_Cl%qDNVLy3z4QKBYZVz;rV6}eIg2Wzg+#Yx?Wf3;e{ zp~lSPc{|q!WEKyAfsVY8dx_|Rz?j=VOSmQw)WhrT62N^uf(B>S8#q^31f<`YJXYAs z@f-&G@0SIh z<$WZo&1Cug%+Fv(=>FEK3CwnxLQzd}{zv_9#&Mv^fsnq_ zS@NSC5wxt>NO5ZYCb3?4C^kz0SX-INSDympsLUkFilW&XYhv|;l&KaL59zxGEiC^2 zKLWp*B<7TyA&uE~GIVz)+X-Rxn96njnT??9l+qjwWPyz+X$$~rm+LC+e1 z>@?Wgp=gF63^>+o;pJ~=iy+XPEWO)8OE3v7TCJp-=<_UjOi;}{QFXNir#caA0DMRuK%`NQ%Pv61{(lcW|@ES$?g zp;FGrf^qC&`XwJn#p!x5#-;yOIu6bXj7)rsl@FkjtT{`(Y{?+`h9FX0tvUY|BCuI# zVrp{c!t-GK=)63BK%KZ^3Vy^d!H-DQO(uSfRrnEqcqn!pj`mWmNs*$~KAn+Ng*r&d z@0St>m%&4?4vqN}{AK1Iy*t5PSd4HTyqK<%>K#&_yARBkS#n4MwOM9}mpmWrx^_ zgzM;hC(%_|!}h0P5s!|_)<4-&xtuFBDF@9=Pd6ObF~cdVbf0DHCFIZ-NnUlG@vI%1 z;>ZFHb|*WYuU=_^WFcsAN9DD0jM25)#=E8jKbRzY5cU?wtF9K8`gm*sKNjCCj#uI#Q?GmXunI0S z)!sw$;Z@qklqve&V8-CpaBUiwm@J1kCzAieXdRd->Y|>RjuDr_Kr0abJP9@e7jp8CrgP1PuYu z;p11PolR?$#W$3J75$%3wYY|IkVL!9cW>+l@&e?0Y){DYqQVzj$P`;nr({y&hW z$8)*6#zxilSK&VjeslI0jR_uGyy8TX)v(%U!o<40Tr5b zqntmsNZ^HjyvWjz7bV~&?=1az(Z%qRv`gTHa=j=4FEV^#0A7EIeq7}JG|n3txL3tBhE4J)~kN3Rvr(mBM##F}q9 z5m)D9DnsUuv)Xq@h8}Qn$JSBV1swg?7j0%3p z1BOa|{U-ZXv09)iqNe8dXj59yCTP#ex_O>aQXO$Yv+6i&lbY&9tgcnLp9()i*Ys#i|EYAxknyrN7q$6U;RWelMVoWGpUzlCU(^Pu z6yL3E#m)en*{BY;$f1>h^V?Jzoy`xB$)IS_ zOMqb!h)jW@U-l?(#<8YyiKnOZNW3~Ift3u3pRc!A>)0MFHdDtWpU}uF0m&s_cr+Kj zV}zZ(6N67Fnkr2U18Jy=rG#!q4p}32c_xV_<{6ELV~ZSMh%K@`kR5ln67V#=t~A{R zKr-rPI9zKc(BP_UQ^CSVMNS-bU8G?iirr(u=0R$MC_XD#Fs_yd_N@_Bd8k4OS`5`F zEqW061HNLm$<#fPmxwc!m~VB9^N@;n;Twy+T}BjiG+AYyCJchF0SM;u!W}7Kmtb3| zyjaF0V#MB!r-fSYTQ!1^%-0cQw?eeVMb7?3j%X_R678)BO-sSp5j9?#zv|jRFBZA% zqf#!R!ZwE~( zgEaA<@l~*qvn@&%{XXUto$33$A@jp3Z|s}erU$|MT{S%?8PY}9swMdFJ=hE4 zhlATwVprsEujw@roo9!>1NpV7{fUF`qC?4EgMzU}!N%OUi)DS<{=hescr0x{*ypR&c=$?k+1IE!29EZy>|a_&KBy8xs0+D zZDWaDZ$ksrHvTct(@}Y4Q7^|Bh~AB^*Cy)R6_k#em(~=U%i(>!qCFF{B3@Zs)T=fV z`qE^6iM&TAnL3|3EcD8>9n_oFpk}xAy~sEeKuYpo8SN7tm{~=NJ?dgMcPFQSRf~g< z^wW}>hKqfHEqZ6P3WIQ4B?&UER0R^s*`X<%pZYrQIA+(;3m7*(YhQJpxPd;DViahF zhy3|PY)^ildTRQ9Og=3b<=)VzO6G9{%Jbbq?gtC)#(j2wXH>A$7$%A6#6S^mt-?c9 z{|0>2OTDwG!T%4$Lx``pZ#zUT438gi*-Uf)jWWvG4DY!%E4eJ(t5PVoPzNNKtu2@?4w96B)?k;8iLcA!O!OwnS!? z%@GAeaktpGA@XV1eZhvj`*Q8z~uhk$#EBKb}P(0AOw}Shc+dwciLNl*0lQoV>DlVbov&l7_rUpZ5E~%%^dPR zRo>$fW{cY8{mj$2n9B#-9T>IACp(jh(IYUci`vJEuTm0f`T~?uITmyi$`PSkNrVKv zjbx4stgKJP5txbE(EL52>UNePYDbY(;!dV=U3IN7&0f2Ev0K}?L+wRM@bkL8fe*$N zwfn}fWMdbH`6hS;lfAJti|FxW+PE{&E8OQW3mIaU-!m15iIbCJE^Nb5Wc^xxKd}gA zMtDr?3G~LztP$UJ1cQ;R$0o(bfEKWo>ULo(yJETdyX6tyUELl$Isz6JK6+&uN9_p* zk(ucS6~>k_@cx$E!@1|}XZ17oMww=q-y-M8u*MTtD#tCjD%*_dUBR9k7Tp|j7*B!` z+kC(Xi!{~yPJhR?@9+@)D$A8heg?beaoUR_wrD*Y+G&QVooFlXArD-uxa)FUYnpH^ znLerM%a^tV$Mb9G&yjfue#5`=2lKD-)Io-U`6*+Vd@`7q{hjbKd8v5W3X7M$(Jj1e zoBV!G@li`3xrnFzmd;& zP;3S-W!G4TJ)GOXJP@2ej6i#6&VcHVVm(r%sOdc|StLVJ;uXX`kQJd57#U@ea^;SN zDZuudBIOUcH4lKrhHb_3f}Td+WQOj~85=LR|@5l!yc-F0Ns6YuuL#$B6L!IQov@=xBv-@A=XToAl1A z4TG?)+5Zb|(+&iuLbmIZ$fl4CU(E}-J5!MA6hs#(85&Q>P^4x&%E`$|do7_474VXCvpwpkg>R^KjCL(dM7A;ESnLhXDuAI;2E((pR)8! z%f%_duX6x~>7Qm}kBaHn{kZ9xHbh?kZ}oSceOMrLS$}8qyq1CfJ1_RodscxVVGj)T z&%2We>B0VsKa=PGRsMMselLKztbd-62psVL!48C99J>5y4bd-{gkVy^SlScp8=+0@ zmJrFmfH0LoFrYtb8?#bs4=(<);YtY}O~r}`_Bec_ON!!^??)Gtn`r7q-Bs6xW~4Yq zxl+2q0sefaVrdC|pPX878W{t{DYj=iqs3+o1Ldy@ErqHE4F0%yPC?83Vv#v~w}?en zD=Y;2Oj|L9_k=kp>ePZRZdYZERPn#8S7NxWa*brc%0H6njklg6%-Yj;270zFx}xs) zfw#24Cn<{@%!XVS==mFM)gfro%&Z{f#$5$ApWQ5`zhgq zerHXu9k}cMHM)0o)o@~=?u+GZ#v&Y;57e76{EAwuMg*1=q3N^C=Nn;6>o4l{zfZta z$E$X|S)ci$Uj6dsrAJF`+k*VCAnfgCCr;5`!x7M{*XiCDs7zZa`IJ zfIdik6qbUWRZb=Y>X%?Xt~jUr>sagZ74SZfCFY^{%So5m9QpOtasZJrwO?|&in{bB z|NAiq?T-_U&4qR1th!B1lchHr#dZniXE$cp?e^ZHy;|u`f5w*fW7rKZ+#`bdA$I67 z0BYf3)eX>wQ``7}VrJn7}n8|8I+`7fKj>%}EgpSi&(=c5~|RA2ZOcQfBKX8zJB zUx%}*xyADx;Vv`xY<))+*D5c;O(`|9aiTzy0k_K9Qwtu@01@FdV4ZsEkf)(ls|vJf zP1J7ILBI)Bhm#J_8`@%3Bi}|IRMi;XHAeYr)#g1JW=Ao$q@F_c)FDp<)kt))d;`Us zoqa9QB~`3m{-#x3i~3OYlP<~kk>kbEr2+d5V!;oL4S-n-(-!PKF=+aly^n_fw78X3 zN1D8yHe;E?m>=1CggkoZg40|cUN|c9nA)o1!u7B^vh@Nl7dUY?et2P8k?1U%_sqhSIRh$-9#+n5_yi@joP_?8t-`^G)rlZy z0(mS`!-Nm;vpA}>@%(<%foUbgi0Q7+%F`zo=-(@Bo=m?1Ca?LOETE8>^cBsMU3Poa z#zeDH+w#v@Og%Ky4b`#WZOtzj>30)?CU^$4KwNUz?3lvzqRL$Vw0ni=+6bPhACTZ~ z-u--OZ`a$H)8^2+me@p!D24Yf$*>bZme2-nCcY|Ph}|-j{*A?Uy@^C^`S+m|s}XF9 zGyRt=mT4|fPy%5c&guIpVL(1Hjcue~!>-MsoCnH|SekfkVfwg5pV!~>KQz^BBn#|k z*x5=u?Opm_y~oJ979YT(^Oa#%4K8ZWynMU9|BjjQ3G>~RtD`3Ym}D5J4|`VcRqY`I zoPwCNv^&~BKA5)ND+2^f-oxA}>ei-pYg6~*FthUaq;m*rx3+vAcN4sBZRLJ$495)w z;*!I&_h_}^*EAQWb^{#?9FP^Cle_}1dP{CMrA=u@xC2FP`IjIceMj)vh2YT(TJ1!h z#1r6A9Ad>|;wi57GXzhl(B{_bJNZ@qvSqwpqitN=kIF+foL0Ycl1CQnzk_4NcRu3Y zPT(1WJ6C8=;(Bo~Dml2vQTD0#abrD8!gr6G9H|p>XAKhPG;{v} z2|UmFo&Rt6#TV91F7bqo;R(C6o`-tAU)rdxSc%YxHu4kly3IBB?Fu2Sk;e^wI!j$i z_=o0mn4?zIt_6PrZ1isZKv!$-4toPJp@R#619CUF8DCNh8~nMG)mlhVC-FkOEkrM7f^nCfO*!#c#zputjgnNu zkq*p=Hft+5)yX8r{C-86mcTdZA>^n16N=(hOIb-dL)&|4`x#sRUA`V$Q(CAEkCFd;_G@mWy7P z#JJD!#Bl#57^lFM9KZi3_*XO&WV{^y5mH^&obv18d1oLrI&Qe|a8LT@vtE|puf}(Z z_EML+Y5U+@IC0i^A8aM1Jz!QL{x^SNd3z|Y z+#MTbDJAl~g-CdPN)R~qlMs^X0XAN_^rZ#*1BFzt&nY$!Rn#AG5%B|T*B_7(*5{8b|p< z?9fFS=^&BI33=KoKgP^A=j!w04@aW;0u#LC-n63(Xe(Msw4^eNILw_5u3vl==XZo= zwirtY7~IEVYVP5xkwh|#J+9;>cXaND^+>cIhMi%(UGuUGcwg}RFfACS;G%Zc1ikMN z+QS|%YSC&r`m!IV))TYJ*l81aXcEC`%IlT%fOY!EL_b0m=59cq<2NMIq%yZ?N98T4 z)$eEuuZ^b!6)$fqVtz9VUgwwd+;U8Vp z^>hiC7AU@J+tM%KaTPC1c;0BWcT#=AJ;)3lr@Z%xjo-%n9eA=|@14uxkxF*5K|eD7 ztfjhJ22KKB=Arh;a?eiWUtlRmiHcK?tiRwKwse?n>zX%9ZCe&Ipx~8Ss^3w13~zfPu*LIBD4^N94!ObQ1v6I4i!eph&zBAF z^UdC0%0pS?gYD8vhpg$p$O}#fX7hl!eLJJFo)LOBBlOiQ9q`RR)a3235sEwXMV)B; zU(J(X@a`#2BEx1A=2fqL-XK@`x>f$Ob^aE@*1VusuW$BlSioK!qGxR`n>9DGoh2hi z6fcGe3+)SL(8Rfs{}_08n|N^fBXcAFJn$-=&E;!Vw&xP>d>N>r^~7$do9bwqI?T>0 z+?!?`R=QP2>k+>YLX?A?E{R{F?8{Pp=d1Pr;TwJKx<{P-#Lb`ta}%hX?7BtZzqyv5 zZ8NEvXw_TP^+(N`wGaqEoR0r`{O7T7kmEzcR6|XR-k>&gc@Z z*9_riZafI`#tPx4j5#GEUS;xhlZ0?21m-#D|;HJWnC+!M>`{6~UfdCSt}YM}j#lFFX%M7>_t` zpkud_LHBHE@nKVcA!NqQgh<~T+-uWQjjwTr^9B4nDT|qe8$z7*9qheLTe*zFaN#P} zeQO+g)0CJie>XgXS|x{m&ACRW?=g<#?x)^dskh(vCF5y_k@dQ&Z2KVozu9*5kHfld zwWH4kcM&&+Y{AA0EIdn>|@ zr-Sn4+G<_vt?PR0`hs;`V_gI4IwaDB1+EG=5``T@9Go%RQ?Tf^%}{QC_-Km0Pu$)3 zY`{M+H=f&qOI}v=M&M7>&#jz^*AHwn^83k}Em=t}B}zY+5~FnW48x^>&g1mW^^66X zb8;J~XMB{PTSMg|P)_FrM~^W(uRqwEqXkcD)H1uajIYztf@gc&TXDYnF7R-79ZPk* z!Hp-l+eShTgW=X4Te+kg>36BG|BbKNo^|F2H`@rAQp(wjoDeDbs3#}2bgLtCd+?|| zm4vJ4fzAtdF;Wx9G1+AqEx3dNRJ412##U$I5T+UG@OBsFWZPSEj~K3eqjb2yAf276 zQ(7q?i+Zw2FEAV<@(+S;OFS+mUs>C0XJ3Y(;vzdEA98JB*rQPgK$I~SJcy10D%N~B zWn^%eJ2B1lR^M%uTw*v1X|G4MZr2qGFQ=1hhT+((&sgIiOR2q?UpWa>nlRodE$pX= zyrM7;r6i=&&};#x;c)A{s%_$9>B_H{^*LIG_8#^v<?~9enF1 zPZs1h!%i8LmqVKi)R?*QNzTh3jPFt~dECK%fcfEQHl5!bY;>f~c&#k+T<`;x796ArU1TkrySRrXNi)aT8xWMG;;{9I$URx6?K|J%u7 zE-f{tLJp~PpkUFBTP<=(;&|>E?6(~ZvnTqbMF{c#3?Z}(B?MU-7yUDVpGN6*;_amc z@06CXVP+nzNSS`iVwlPAaRB3k zuTB2zJNY0<27>EC2F}cb!Q+YyAOWY07w~soHBSx}b*E56j;i}-s+cVwGIKyJIf|k( z$eoosZ?ns!Bt99lOXrbzRE?@R5SuYOB~_8*ZBoFD->T9eR2jz%L9IU~j_{N*o`GwnmkOB^>${yW=~$C$eZ z=&Mhf;a~*0;1~n?7%=1F1TK zTNxFRbYx7ow;JhR%q0}y2$5Xb`p%+eZAv%Tkj*3Xf6oB@^N|{q)*s8vkFSf8kM|DqjyP`TA4ik&ET4$X15LL+v?q79A>6iP=9XU!P+- z{V%0|iwP!Wt4aTuv_W>LEAh(0o1XbULH<2Vl`Ca)G%P)5(TxdZQ%P43xL{LC<}RU_ z=sF&S{96W-zsf}Nr>U7Ao8+HmshO+520XQL1XIBvPAe}Otpw8F%cT8miYZ-Prq5eb zxEXcN78{+&w;BD)W+$e-*3T;spOz%FsPXUxQL&g#wR7v%dn|b*q~J>8mr&1pcBV3a zMp2SqKM-tkgd9KN&=U!|&i*B-jgPYJK2qlqBAf;>=ID-@NI0cLi+WeblrbDargM_> zNitGOxB8(7Wwr+y1tYuuNp;`U&I%~arJqU7%2Ntg>OAl&i*vmY?k-Njm=^3Q^lw$3 zz6o`U=Hx`3N!gfvvF=%*Xt+`;{1nqpThBhPm&pZl!tTpK)M-h?A#HS^u8OCYygUztg&Er2% zW|&DI8PVq$ZPOmMs3Zqe9}ksWr>Nv9TEl3HF(*{=-9>eKtTNN&0w}Pe0v0%Z86kx9qbl2-~BerR=lupJty`J@jX3 zV^@^pk4#oL#4ei^c_=qQ7lp*3jVHF7ZQ1ij5UqD%PUPkrteJatu5e`bG+;PN-RnJ( zsp?5(jO`)|l&_Ik_aNm8UY3>G?r@o~ZW>=nB;FI2W_)^&BWJy&VlW@T(CAy01D zzKgayw@#Vqo{1iNN)E9dkZ)>wY_XVi^Va4~A=21+ai_NVPs&gjwVo3^7)V@wt*3+A z1uyVJVCb7~OQ4H`Ugq!qFZVG)kE%Tp%r?DL+H+2izd?<($JpQ*4;!N$Ib6(k%!&NN zt%-J|0|?iDPg@4dXVsoBOM7NWd+PB@w%W7KQwMjTJ+)lS_BICb<7MkHA){|IRx22DBHYGOpuSr5l&6=?C#gqv@^u{{Ns8CD z?Tf4?4Vuaz?&xBdwyo7lirwDTZWX6(>!ys_Q%q71l=!syWR@6Nz*ESajAW<_gcSJC zQ+=Y%5t_?Pc%IeT)vCkP=_m?=i!SZnaIl++({EtB8m<)rop4V|(ROX>b|##@PDnF0 ztPHH5g?wuZQa7v>&}H=7`!WvdyqMxVA2@EuPh{iy%EQDx$-vx^mS`*gmO`6LYYPOD zB{7G*G)%x-_z*HdA?+<{5vpZZm1<5K#u8g!(a*BkK{LaVSG3w8Kr>1%_)e|wue@Tt z{fniZtCqN8S9P^#)XRN!nlPj2*QhMSM)06aL%&2ZbmPnV;l$MQb{Zg5VanUhvXsXZ zv^5``n1YU=bDj0w3TrakY$C5hrmu??w|cDPUgXr)ti8&LW{_> z;J@+#y`N|l7&Mn%7Hclo-zMrK*I4Q@r`wlEJ*(9qPht9dH`Cvu#G0f6<~SKVAqu_L z^Ay?_IOgM`@Qs68nr~8M0k%q_S|o|QG?_6miHeWX9qOYDE{TtRIPj4qs)dxuQ$s$I z$th}jZO}*a2R@QS6)`L_K|b1`2$2fqeGz*^!LRY!y)D6>9Bt(fF)GpH=p)AhN^fME z9mcE112~NLeKAz)>L4|=R!xa<+AJQ3@8dOjBZm)*vulzb$WIu%=nr_A(5J>Le~Mrq z*!M98q2Z82OIb7;QTbKwxwYwC3M%>A!`&&$oJf`z+OS%B*tIux!|D@cg~;|oWah(U zlg`50#sO43sZgqOK0x!O>Q+6uc`xn&)HU7*mLr>DbwGIJu(OO3b zbqGnFth$9Ayg%egHE4j|eOKt6v8BoO84e@Sn@6}Of5L$bjmL4B{;b^~!`!tyb?pYL zKfUzFe3)wXr%Cw6-r9rcNs8LE+8v1cz}pVpWT=dzU=qvS7H`-@vQeN|70X0fzS~1< z3sjD^1sycVc$)rHj)+}Fe`!CZ>Mis^jSn17wZCUX^ai2Lp zjZyJ=x@3GBqsw`1&A%9qpQ-+VZH$j9oa(boAHmDv+iRjqO+*DC3!?^g{$_Q4Wp$TDDtaa90Y&aqa@a=Vd&M4Rqq>GlRY*A(R2 z)E&_KJOL3&MmU$cZFJG=+@hvYzjU~HP@sV|g->Y#KjI82&=e6}Q% zzAsx>mj`iQPD;equdbIanVwzkx6Xzj$D=O{p8- zrvP|knZ;IAD@4gj^nb8^VAikq(SO9EP=tcPRMiGcYL2t$Q72aOknyy>pz866B~zq| zz)-U32Y<~8AJI-AQ`l1dVBwDHuNWo^G^Oa*zet;%p|y&YfR6X>P}mzLKQxq}pX<>Y zYEAwzh<>WBph{<~)HhsRi$gvvq!}KMI-_Jx#KDY3@J+|dc0ZmSu^WPY(DCmnSF#9U z*F84IF4|SFA%*ziGSl$*$I452OR?C6kC~R_{>TN&N!XR0kq_0=mU(1}q%gIYNC`*w zm?`d)oE$Pn0(+Wf>FefeWox>XDTwVkLT}hIgCekE=TivHWT)`+%%DX65A%cEub2CO zHt$>H{_oBE4!K`t-gnFWQuAI4qugKXXSQUU4fw@H`ze&Y36Uo3%`DU29FHL(_U0_H zH=Sv+BIeL)Z<4pO+@bG@y@?Ha1JCvYWBQ5?WcF#xvv|V#?1i_u@8GMke3P&?T~^u~ z${3u>uKoW1-&UqNs6ttp^%^I*Gv6cj=DBg0oWUkBE=zZ6+e$KsXHdep=C*7Rd(s~7 zii%;31voCiYqlOkO%YLX=dH~iVo!o~q=S#GazS5Gs$1Et$Ub8H1mARFC~*)@!e;VW zw??f;wjmAJOfQ<5D^{FaJc_cUNc{{p(P19sb8Xw+$l@;mPe^l+O(aR=5}Qaq!BC1+ zvau_)PJKirQXjE=Jn-g$hTUV|i~cu}4-e44y|LOcV9| zpzq=E@f5sk$uWq3`LeQ!t8Uxz(+P9uME>y#w!gu3l5bqR3BlvoHZvnDJBTaEyBEcq zFl(y%d&O~oE(-ZU-&gU9*$^q^FhR3I+@mf2Nc%-@;&0-hURs)t`&HytvtH*y&J>s< zFC%M5t9qTudf(!+Y>D$Mss=q3MWadawuh+Hm{E&QhsTqb4wytTf`Bet z8J%bVrj@q|T^uVf32%7tH9mi6wL|h3&2VHZd#}rj;Vfpd{Q{aTHK0GAZNs)bD8CU=Rctwef0+E+*C9RiWiIS9Ii!H zE_7-E2fqB>*fPK)v}CPEl;Z>ibYZ-h4;B$L zaG-YOewONLd(dVv!%Pmvz{#K_ZI*XQwUmp&{Q-?d-+!$@<$kR|nyu^??6H>Ub36@& z5B5w;?Aatd2H7)Ty~Li$fUec&$^4YjFaL_JDGigOcM(BFzJH@(5`~!bX`&sd)wF=D=_VZ44PR1qUwKMii z^83ro2AKBeb_npY{aY=fO~z~W;PFxq$@zeU{Y?KV0Y_h>#kpW)&I#pC_QvoQK9t4T zVUT!TmRk$n$Sa0xev*r>Q)E7*zn9a0)%+Cf0)CoDnS>jLm(HZL0bY9j0Dll+C3%Fa zDtn20v>%h}Xe$leaD~~zQr%#eEq0Ft#>cscjh!o3&~fR29?xynYIEcXCkFejvW0oG zB42YWju{=p>jXpA`;;g~>?qWf)gRh8cVO1d*r4a!^iDEvV$Gyg`|Iy7mJ zLP<8OF)n>wtqe$sntx-9wka$mn`(9obRwvcuq<~_2fFzHJZR62z8UD}3V%@3Nl)0f zoGe{z_m7O-DMl?}{cgbzdJbn(yKVmKj5+;k97j?%m1UiCxa|Ts-{%A-0BufW^7w=b zKU`8`YCf-m?IBYtigqj=J;BeeT*+ML$tMca5d9s^Iu$Yxie{bAQS5vTcfw%lI;O~~=2+{exPTDg~K^}Jsv z_wClbXz6F7kIJHusj)|8SAt~~M5oLBA@WmG6ff(6^&<0lON2QaZ&+dHm{W7JD52vo z$X#f9MyM={h}~>x&5DY{{~;>m(qTIMOH*+8XCEHBKTgX-S>%sD5pU@6^BWWU5#;<= zTsPTT)2<&0cBBSRrpo5S+Iq5Y0hH=AK&|#S+{r$`X8nlXWVlk1v;MfwcM(fou}drW zeDHkg({r?q1uKa_AyR;uQ+S?0v`5xp2!IsSzjl3x4MQX6w zkzX(G>T$G_eEwg_7Rw~RI_JAhqEA~NKA^IkVuK|ch)y@lW^uNII-=|wVY?X{fSmLq z*zc?yV=U_?09DV^?2>gwt0h}!>=|t%`}e*(I=&ni|D3CBY$()nu6J`GaQaav@c~=H z9qu$@0kU(jUUvDF;%@F4h4*07i9Oof4lU=jHuqSCwkN91eqWo-cEP0`WIMsmz@~AxiY@K7z%n<~*L=RT_sW+0_9qd-{8v*=U z1%7WAwhH`YYhLn&2|p873ZMh4arzUd10@g5Q=9g=3aOHZtf(;YUtv7df|Hq9zDCQ_PTS z#`LjXd6or#o9^(4!HF8L4kXNuh_lQ^6%3TGxl@4seQtg-`Jbg~kWcaS$KQotT(|h0 z$C67fnquUK|JcVd#q#~>JPF*zcAE>F8$4c7$R3kI+D!^k^umcPGrNtM-QY6&2cQ&_ z%HrzeYK!DJ`90Z5jpj?+R+iH{v-RVKThtij{imbt3TFT)IcRpz@oo&RknAe ztxA(1z1K*f!RrZY!JciR%A_s$74^n$l6%*JpUC|+a_?O5lH8A!`(X>#azC(pB~f%@ z{ThCxAQcCoh8Hf>zM1TB9W~b84)grn6Y{jRo)iVpcD7%_xy;@2rzI_NBR&upjdpTB zMz?vQr5GvDQUfSe!cON_!r?8mg+IKuqUM8sCYx=>W|SYBR@&3mz;G<{-KL)>Vs+C( z9&kXeIZEm>-}Mr8FR;x28ID7@<<@|PIC{60P0_L#>R=p5JfkzOnwT~4Ma(+Md&9oZ!7 z_N5`0)HF|t@+F=xQ_y2l0oO+b4x~MasNFF>?GJ2A5?P(HLJmrN>vl04YY$=zs#G`$d3;*{M}b-!4BSv1@-|~ z6pzw8?FT2ht)P}|JC;t?59n`O#pX7GYUx!Aa$Ahqu2KM=AqiOuVA(HIA5Ur)KwdM~ zO78Ko&vxw})T$TFTp7Yz)W>RUvlAc8^Nd#^ifLh9>>5VgtO4;VAMiFC(VK#4>jvGH zpiu_Q*GtgAYPm(huj2xWltg~;FRY$h6P9Yi6TRgjkJ31Nv?5Z$t|_#S)pGw;b)Vqc z@CVudb^`heIB2KDBL_c4EA7*JsJW!(=nxu9Pcv$S2DH+KF1Ao98f(zcTQqjeUUQt( zWxng=m<4F;RzfYWZ3ygu#$Is%Mn~-a{QkfhySZ~bL0g|^56kw6Qmoz#JZT7RU)v~z z6(RGzim>*#orJ7tQn4=kPm0?Wa1p|jh2$kv?c(Zy zAZ3%0R8P3`U^ugB{uE(x3v4tJKxpM(_n4my8=~QPhB29bquOb=y6DO(SHH6 zn3>%2G2^DfLTlUl0EAPUzDxUcZ}=mok*9o&f*H$RJ1aXD5)1#|pNLuxsimp|!EV|y0%H>us zgt9F_tk`aK!FLmlcUwdx*0v&|3_xemM-~Ti17jhTbY){oeqjarNPt1)zv!zZle&ba zPUo;vTT~<~dvTo=gj0C#U-%aD%{kF79S+JaYvB#AbA>l7fj7uZiQ)~r^}X72Ve;oT zu^h6*Y9WY%nVCi=V@CQC;TMtsz4M!8@rZ0vRl_|gw%pcjGW3jB4sBqt$77VYNLz!$ z$YyVn&-3V@;6Hd-5dDxFX<`y6w@4>10~89)QhXz^9Z& zt9!D>y7<0a}U_d+ z{r!V9oAwLFrJj%k?SwNUBtWzVBI~xm)EjF9mroGr|uc$fR zKSC?*HXK*dDVN@*c^hho|JT1PZJ+P6HI45wWgtW;C!yGDkW}$yzHHPRGSm<=EWXS? zK8-Ev19}S@Gv{3}Cm^g1Ed(G7{+OaTb~h=m{O$R&@kPDXyK1_mDQV4mmwd%$cj9^T z-DK^h=C%&QcURvk+`MU;(n4fB_|zvQauuuI2D>byo8nV0e06b!C7kNkd6tuG>M1~G z1}aP$Om{|It!E_(NUR{2gyu3qG?xdcKp1qoFxEy=g|Y6ED~xqF*A?3@)?Or+!Z4H2 z25T?((k%C8;lWAm1@_Hco*WB6)aWJ5Y+p`=v558(6(&2O!pwk&WPpeZ9**R)1`t## zOopk#WC@?kHdUBu0En$LLsXdU+VtK}Rbi}}2dgmILsXar)H)-w=XaJ0BdUwAsnc9x zQ!`*we-MCNq{2|FQems^Opc|(WazJXlo;6HSwmxuwdPZ;XDv^l#q(T1g6Wahf10H5gd(Gl zO;YvGI+Kdb->UnBB4b?#(dQar3c!vQI~9EjF3yIXmT?@@PTsm}jw$;5kabOiUB7P0 z&M6Gqi|tV92Nso%)x3?85&AsfE8@)YCPkq_y0E$+8qZOoO6YyM?{=Yh=#&+1==82p zEOrgje#p)z@|h!64&F~kwMmer8uHjATIYf))1lbL3#89#XF)x2g17sYe{7QBtSCG@8y z3H`}>7kT^K<@Bf1ZoC$V#S|(GOoA9T(lSC7P9tbhRHm8|N9{1z#%VxA4P^R_EF5dv zNnH68M)`>aaq>m(*(zA-U`le8dEjG!Os^6N#{VeMzs}hlghFBh%Zw^BFo8uf-0L*4 zDEv3B@^<3A#(^ynGo!?L8Jsa=Amt&p{0*e&je2|C{CMmt39#r`@c!UN2M32R9VCxl zrfs1whAJI;w|LPk7vC5-bZCk*R4GEinHJ}n6)vBoFtVZh-JvPz`p&c_t@cUYiEzLw zcX{kPG0n01^dn<9FD~usG>>CB4{_3fE^RuAG>q4jSge35MAOjf9>6PJ&i&X6Lvr$YhW1il z+sSj`Y?{ClhA8jj+hRNu{E?7zoRlJr>sMX8F-#Rk^PcCs*>?-Q`IKBLyPLAodZD#4 zQl@JwK8M$h^hLz5eqL%gu4>?D4;kmSQ|hUmi4?l#)P8lAXU0%aVYcQypbA1+$(M?z z=eM9HNnecBsxOf98lKYHfdHs5W1w#<-atLw`~s|F%inFE`TaXeJ)Y+cMgyesq*n_NMsQ5b)mt4IgBPU=(?r!VO= zC%fwdS}EEclUF1i;i*tPxxv7!t`DToY&$PZ?DozHw%Te069U{wW<;N-BDDsGJ;B@Y zyrOg!@S&6n`zTkoy*ay%Q+Y9|1-zZ@Nhe2`yS1JdD2qxmx{lj-2+$H06ZCT<*>3gS}Uc^2F_+m22o%3cAca_rgWs)8D^{rLWJO7V>VlaGY_dC2KyMexVYGN zQl>|q(`5tPqm1KY)K3X{=B1EJu))r6*M6#WW78d-1cDvbUh39In!ca^z;4^(=Id=Qa7P~e9%}mJK9*I}CnuF{5ruGD zggcd*Qq!mIr}Rk4vHRqgBX~OgIBd}kHGRwe{(0NB06!}4aE|QZ{tc;2itFG0(+S(e zuS}&nIm3thHzYifHl+^_e-I^`5tLpO=Qd2?GEeyh>FqbmaM5@A@4hj9hwN5%c$nC? z*~Wr&cbJ18Y`2k;ZeFsu0Co2mLCCBdi&ipWt#$z&$;GUj?3+>b4yXv1Ay_<`+p zJT#CT8sReAl@i-;rfUpoU z+%W?LGG{BZ1>45X0GS#jT#|>tl)G7s^tc5F#*>&8+|^Hj7>Tok#lnl6%-*7TU<+Lp z)+gUKx9n7+|Cr1vwWw#1&Yb_R8D-_#U8=~YvJUvw=?$wx^z-A z^v=v(#Q)RHFH~JUM0*@dhbY2T$9{M%_)W9P>B0w!-qzbP_fnLYXTiB}x2U*e=btmz zCxLOo->Na>@NAP!PmE^{a4m-5o4_QezKgqkAc9kGR{;*Yj>&YTz(0$(>DtQgije`{ z!7h!g$=qeo7>|D7W`Hj59Mh0$zdGC&yBXpWX00aiGPKgeG|Z*9JM!ur`FiVAz1Ty6 z4vtb3e*_6|At4rAnK&c{cwme0bS~-eUiv}r6i@+n=^aZvk1~9Z(WLCIliIKQC`KYZ zNe1yU$<}_|kO~^8{k>Ui_7tw!Jtm$@7Zg|_9I`nxyY#+09J2W2$n2ef0!g6-1YIOQ zr&%5cI3ZG*F+}kD@K za2B1>+cODpELMSZRPO;@ow;W+&lk033MD(Vpu_BA7AM1*gP#*@xWJiqyZVEDDex#t zFVU7Cqd7%qGJCY;?Iy%s%{D%?>C+t)Gp|CQ?u@?4b2DJzLR?zi;ZcsJ0yvM19g9c$ z-lE>j_Ns|Y0%hC$pXW;fOo6@gDu<^?)WbYIoY`LKlNiFevb#e1mNz!tliQuSzlg`o z9aVEFub3}OLs_1!=~7j9*D=Gjs;EgnkSTJtL_bq`J4R_cFs7g^4+8Y)x3QYq3GBNI z#BfSnv!eE~tQmDyU1x^jX4RN}HcQiOiB&1yxCY!Yc%YY)ow1{U-nHdpxaGnzk-zFt z%Dgs;^@izaKQiUE02nNO=bT!|SOR&3q9{ZlkD(#Jw0Wx9F4a8~s8{{DVT|HmJ~%lY*YeOFpotG#E0%_e#;D)=OBgVjt* z)=uV5yqVa;yN~H%Q44#G@8Lcont1q_TYIr*Ko3VhFqRU;7kwJ#g<0jndUzP=Wy}>l zd>_gZdU&Vk;Zk4R_$oSh3!jmAfI}Z0mKxs2$r+^MSWi65PNg`qK5yLHr;A43sGkk@ zjqBPQj*YW7Db+G~)}9-`NUdafPN|lnp{p|ml#Z!)?~1fVbP~}vaeUB%j}M0!t51u* zxk~g+CZf;Ni+!ki1QwTA;V015@R9)2bWRyvsgzMUakQoD@zaDy4PjsG>pGfRe%e&} z%HKi18c;4%t51kRR((kHvt|x>TzlzSus#Ju1<*L@)sr<;5zBt)RBfx~QP7 zyb1Y#&)j=AyGgM6d-^<|=Z|LZ+?l!aa^}oAXU?2CV~l>4Wq}#p7HjJ;@o75a88f=R z-ij88Fm_N2W0Rk9<*>ro!PyHh;F8yaeJt){{eEj=(grWSL6frZSb9)PVxyNH6iKWl zLlSFk+~8Y!(2>LriX_&OA&HTiv-F@Xi5&oll$^SRpQQ&KQS6|IVl7fQH8yVOwe+Bf zVo%EtqS!$Z#aguFC8>V4W)a1n*0R~iH}LUmJh9oFyaQi0Te)IjRDJm;#+?b8d+KdZ zaa=*bJ!2EAZsSh}2akTU_%+DM$5u3-9rN402_6qcR|A1B_b|Szu z_i!%YS!ASf+XlR5#Cj9OD`7X?F#->DJ zALAFV;re)YV)!v~izsf=Ul~Z(e(|!m953XXaJCR@qZ33A<5JM|Vga{*;J95z>}L{- zH)|jheY5yk%I5O8*9N=<;of81u~bs=$vrtAzreF;Qf!^CbORTz4X`G!OI)5)Z%rz3|Bya z@mx2rMMD|F8IR+{Y%?N;D=iMYEgzT~vAI&==y$b5IKtd>Dt7~qd(&(^b=*_j&cSdP zziZp7w0IaaD%(UTEU#uHzR?DP~4->c!kksJ28=eO!2FlcMn)=ji$}zZ4{dD zEg!IU;l<)jeDV%lsh2-5!pp)u$}HYI;4Q?o!{x05_Ab0gV-!6H(DoftX%uU(VCKS- z%xV7A+r)y!Y235MZ4xOZ1@^gvb-yk{4%o55&ecAfQelfLS<(Zxop||gSrI3-2#eO?cHq`v2_yw_8J+*O3 zM|rfeamnHG=!nK8hsvWBNOPRDXQ4GsW(=?$)j}3 z98YSKz!CU~{p7gM%*p!_qd!aVI}V@Yo9eiI8L#rpSRPqslz8nIujID*B)6H2+thNm z&a7=HUF*p(O%db2BbC4Y%arfKvf43=cFSMK{;5;G_V-=LQgA)CE=SQ-eLt8LG!M3> zj^gT>v&SR?KXBov&kO#OUM0%7!3o!byJg_SO>^Wwd}Cr@ zBg@}d@V@2e9PitM&^L0o{p)Pi#zh=R+$gT=b*Z8oM&hyxo8ce(_r4z6IY@}g8=~W+ zNyoHenOIxjfx-3p#4NlE9rot($vYOjDD#!NC-2%i8~?trFn?@ap?&!ET_Bkn zWcx}&P?xtn+vn29DgVXh^Q-d_d$F#6;1w5>9wLwWbgMv{WFN_?w=yOm<15CfDCPS# z$erbBje6&OhE96_hT0y|W4p?EbxO5Gh5$x_(@K|<~e8iT-KoBc`qFO^y>NL0DBD-Lf??#-UBf=`zjp!v2 zy;eg;J9ZnbHR5tR+F!l<5`K}SW$zK7QigY}49nCh=1Vbgdq2{uV(AeXW{nTlb>z`) zt11|~iHit|ttEljO@9C4p!%6x$j=F+g6b|F9g9DcVpkG;%Bd5-a{Hvt`NVPOL7iGi z;L4d!eb&u#+4BBGb??2e4{r7Dnb2_zwPk;MQLMu!u1!30vf$Z7O~+C>XVTcTIf|oT zX~}VJ(FFu($x%Ey7U`DsvMXEtgA+!3)D4^MX`jYGJ$_|0V5fDmHOdcO$TqltJ*dVI znZB^mw3e!@QTeeQ_!9L+ztSC+KiKGu@{b9`*2%pOYZJHR<7e!TOSqk{_wby^sT^-P zpM9oj)~Et^C^)p^jXsjNq(ChOP^kyICfy@RSeSZJE4m~ZP4a~#i&&l%Yvyh_CObI> z0ycei1Y8zNDzS@~<41)r(nX$nznf=RFQJ(#Lb3saXk7I%rA-S*$l^Jl?+RPqwLdD5 zNIqgG5@f8ICzkX!NGH1hl_>;BExoJj3zOM5_QcU1F}3zIQocWWi)F2py6nW^1*5U; zkp!dZ8KSMHB$TA$fo~eG#+|xwu zAp*cX6@A~D8BUY7S|M#E0@^I%w)RGwxDo$()a`A`RMl<`V+c^TI@gUTmxyk}>;z&p zF*}h!w;>kX3sit!JcBH&7QNyZz_F$Po@7G`+@uoM_g zKN36`A5im_9qv#+nsc~g`S>6=ls3IZJm(L>R#iS5#rie2WVpv@5-%s{AyJkdt>%!Q zEp@J8;RN56fwoaTPa0Rw5nTC37dH4q$jOn|VD$X^?u8pRt%(ldtHu`1JWHO2d0u0G z6&oJ*KDE+6(qmLYam?0bM@#;R9h>C3CUy9Z!yR?1Wwa1*W%YKm zyKMU`Vl@jbA>gtah&j|O#1MwjW;?{p=U}?u!E|iSHKvQUUSqn8i@-6SZ{xXxiQ2eY zEx1lFG1kVNY@1jFeDX_K1Xwjbi1hgUXz%taSr&MlRiWjlJ^X9h5It>mvj{V}&kLtr zy_=$2&LE|s5Q?TQsF7x~U^4?@m&JQUI_PcgR3WmhUL_xt$_K9yQUUh^2Wi1q)X(s? zj;G~E#4bN#jpn8PM6F+4k9~>Ni>PV7*g=sx4m{@&heHHhF(*9*Y>Y`9Z8#W4BO+KXFM=Jw2Xr9aV8;X<`heYw|jdfIGyu zRKWG--_Tu}sB|&Jl_o0Hb-+cWiR>h#iAvQUBoJvLE6J56D%D-I)R88-dIh( z>Iq~(M~ZloV9zYZnRs80#W+$#HjCMNZFeT{MN4<5wPs+B6j74JVt%MgcV<8)d_%}< zm-HwlOIUYK9EPrGGZV=x6i{DX>j{hZj}S>53E~y5FY$l z!o#_pZW&zom=tAcDL{oiw}K$bR9{Ge*|m(nWZ%OaId~|EAKr z2oHAYSLxEzl+zA;A^G8cFMvmWIQw?whs&={%MXh94EaG`ZTUgylq)}+LH;i#KV0^W z{}=h;RQs#XmmmIkv&awrHFW1+$q!p0V@Hx=I^~B?@LsH@@uM;D3IZZORJ##l2>dJg z;r)Fq1+NSv-K>PqYDpq!4OF>q8NH;?Zi2+SocYwu>^%Z5m-(L&B#N&RtV|0Mzd_ac zWdwPx(E_$-4C)6SmoYFI(HDRTeGmPP(gWw#1NXJA$QaZ0Y007du$ScD{-JMl2+B zyZ)pFBoT$QY|tAaZu|!bM^z#)4UKhpqkXOMD1MUu4?8*>bMQ3lkte`M%$=+ikO>e3?PJpB+^}Eu2KSLy9=`drjxVfB zn#iJGlkF)4(BO>X;pmbo3AR`Hp$v~J;mY6$JSIXyn(YUO61rJ*X5}6&_-w~Z^HH#9Ybjz}p z@&wB94xVroUuWT%(%7Z{v}@@i^!wC%9NgDxMl*^(sE02@{WL)u zB52_v#bt@{ezlK&r)s+OoH8pf1d+>1Y&* zOfJyvhbd8`5?Z^u?s$a#BAVH-ijW#K+?mv?D~=`ML`j%VNcBo51SLUM9t{y$9(*v& z`NADx&5z`COOaI_z~;Q#XAQCzYZE1X<|mLC6-3C%!scmZU~>#M(;b_!^HJsSJ*Hhg zr6DKczM@i}AM%COTUY;U1i#W%mM#DTGuHMpZz`vem42^965(T zY+XUO)lAm>&qnTv9Cl5N_o*|l`eI0NDi_lp0V&r1^N2_>PB5`&q}T#c?pTzs?s!V3 zQ=!=OgAk~d3thExfumNgA&2hfB?N%fP#z8`DAyl{voH%P76z?G(m|Jsx!B<7H!8q~ zIzfg)erjbPr)snaYm^wuFV<0#B-o+fiue`F#x9uh)pNj<%Vr%3Qw%sA#bD0NuU#aC zm^*bf;(`S0NSz|ZBg^ueA6CgZUjmDUaGY0T(b)umO(72li%uf=FRv9wJ+cZCX!5U`G^EG`CX~4v*^>4Y>dEAj=+smGeHt?%fKXvSUhA}s5AbKN% z>;gBela-v{(9LX?I@uYL+n_emD4o|fAYw=GI+cgyLJ?5)89c+FMaS@6cj+~_ewK@D0-UA;Dlf*NfN*Ch~h1 zzZyH7Ykd2M;9WtI6+uK{ZrEx#;&w97YGk(7lpOcP%gZRi2 z$(vicUFTgJTjSH&qu)y{!Wu3N<&kxd&@w{pInw&}k(%Y2BmL$W@nR4(#|UIDJN|D=8g{+H_ zqgci3TFKxe&bFZzYiKN+$s2ATA(ogP^G3fpB4~2UvdnG1)vgceN=TY&PRM`Mi0XQ=JEgx2|2MH+97Xb* zFCeY%wC4M#bd;!)6Ep@}zVPte=qO+jO(XkdUm7;m~Bm;iW=3G z+~|{xssKtoASYq_X;9>vm-tdu8dC7S0~4pH^~Yz_bF>U;)Alw`ZuHpHAQ=?-s%g8K zV~+9B&s(TT&+;V%virH?zq0!#RNIz61?z`meFh*C!*hW&cpEu(`LWy!8{cx%K-_Yf zpClV;=)*asA7Bo#MFu_jDSPh40<@_QGh`n2xol@gne4_kNk>a)M`!0rWk*dF^N&+(Gy?Tb>qTXzIf zN0)Bl(q}TY?l`88T(({7S; zQ$4OEfN+pzisi2l+FHCVQIp%6%!#eZ6{+ze{KOhhZcIe{Uh@<0cH<5&g~>GR%QGUz z{eE@EBhFMjoq(MDJ^=Lt?(S{D`m95}sYM>}xFD66X^&EGmQ5SQ2+757g^fFN#Rb$r zTtG$7HJxV(i{0pK@(&aOK;VvB>31prFs{6d0j80VMd71wC<{Nct!EaoO zk)Ny*jsOl=0Zf@AUpJn}OWY`!P-#4Iz$^mm38dol(M3m+It4JiM zsdj93*nd&#lGgWnC4UZ(dird_5kDIxpFua}T#25V1aYp|s~?36iXNk@tN_}wp0PZLRso(F5 z8G~T;^EOuRuQy*yDsH#zxrFyg`64B(BOka?2v*{(4KA0DDLCxR8(W85cg2jgt5-o4 z_33~0lgET)*ktm)MGnimWMa67Ggo{k{%+^8 zvt4##@juOEYjTh`xp_b9yG7HDC(BOc-m=(X&DPgTAab+uWaPx0uCcQv7CTKhZ>!Eb zR$_Z0H|P@9#Mb(~x{&Bysjn5kl`+3$a(x1J8c+6zSe0(CkBP*vHr9UFyG_E;zjA0{ zJtJC!i{)k8$w`O9bt=+V)JtN*KSaYUZ0=+aNHme+@Qz(O^_^GA!ETt*Bz{53Xp0bX z{7}3eiG7Qk^);5da|%Q!v6Ya}l-u~k^odf_hgc+3%NC(_V)<2|9vqft%ZVCc=3=wb zUg^z`)R&&iGdS;tP?TpN5~^Ro)Bnvy*UHm3J9N#wcAt0Dyy#pS#2^QKVcJ0#XtEG} zw=8zyZFNZZaMWUhr8#@Wc14uxO~;>4iD93@53Y0Ak}ebQeXC0`%|8gUWS%t7td zzKXU=Pg}Jg|E%KI$MZA<%7a^yoaX9&#*@Bqy;%*COh^25<^s+YHoXQBBzci@H8 z%lF$P^cG+FUh@{tVC@$$>?_`F-0=}1tDkpI-2}QA!dN3%r&e7j*@N`o=Z)4IPcT9t zTOafx2Ktbu|Bz20aVQxY%MDvZ9-gz{E>u4GOrwA`+Sd{F*o(T+KE0?LX^j&#iC)*8 zs^&w{9o^TB1XE#|e^dg(HB~~0QxnxV;=v_H8FmS8>U@4C%NSfBY1CDI*oY4#d-5E9 zwn%^_KJg&*M%yt>w3M|FO?`-<|jFSuIE94LWGQXRJpGtjXfz(GjO&2X0?{ zbaQ@KH!S&WV28UbCegxUv?58bJsw+A`stH{Qj>5=$T4}3XYrucWI+2Lc&t(5QR7ad zal?-0Kv=s~NfoyykI^m!NETdc+_0N8b2DEx?!2gRLnGeJyxJSL>-NZ=Y4vB`6UGp%pSlOpO9b{*Kv@LA5}z}K&Ah6`{Ad~QW=V|tANHC{ zeCCyYR~&SaTjW32|D4FT|9^w$T{r!k;92!x8lJ-lX25eOuj+JuG(69c#LtCiY?oZ8 zBa50)OJzr;2Rd0HItclz@rz9u^V88#pcp|b0h>Ve;j2@7MhKM;*?8^_QD%A5zg&6u z^;8~>^J$$j=;K#+_R?G}qe`7Fm%!Bdb&k1Ra%g>@EE~mu_ob%oH%*V6qIzSiptTP^ z0<2b#>!hYH{#oX~y;OzwIBOo}l1DFY)QT5fzUpwNDiK9`+1li_s~`F!rVT~E?xZ13 z{g-3INaa^r=Tm(%+F@ON6M^jN$Nh`ykNyJH|N2**)xWs9kwIt~K>Ia#W=zqXxf6g{ z^9dy~__cZ0-yUVCG^gwYp~M}#H+y^IFWfXEg+gO2^N_P1wpx>>v8*0#pJ;Az-ZBD2Vl zkX0^_r@~t=lmQH<2k@y)GQN4F*->5Ud-uOvU!ZG!L60MA_gG(;)c;oh?!BN(|LVHd zC+DL>Fwxm|Ra$XFm3}~=LF#yj)&jo^&pK79%Pm~{)J;-ezcjq`{0uUvVdUPB_+QRz z5Rj(*FEj0jhtZD782F@)w#slH?T7_=I?zz*Lm~6tLOrV(WFN93dn=J|KIVl%UTyip z;#6i}&rW4zovqESPvNUR+O3RFJ6ZNNbayM`rgV2JgLH{h=IHu+>W>WBm+H?6|F`=i zDDkEGQ@!B-%=m!3e)}|oAY%G7L+5_g->vW7@-FrLqicQB0Ks%b`dQEb z-%+}IKAHSN11jzJfV?Ma#50a4q6;fFaK2k~g*EaTc3z7THA0hzIIks%nj&7yHtpq% z2REK4YKHJSTzhfnV0)sbgx5-WO;pImh&9%j0_#$-g&kXRNFNKSgH%felbrXUCgl0j zm^!s~sB~<4dY~MENsp&6)nLbbzq)W#_GqT{o#ty~9L_P4nZDw+Myvp4pho?-Kdg~CaDkiA6SbtK% zu(^0a7-TN?Ef8=7P<$tkVO(G@0d?n(0Y#w<*>XZMWTH+t?IA1dI%I|F$}=*Ctk4-U zhM}OoUMo!UuVuV=4=!fBcm}SETpQxaa4psfl_Lz7C_<1vXdfXIBiiU!#}%sgf8-9= z-wDZZMP`sO><$%sqMj6hw#UdHe+bwy<%T!NnG^x)RGbzt0>lkv8V(&oG#7ne!xy4HZn{EB z!DC42r$RbxXls^EW>uINwm{ zHE;FeO2;dTh9aKgRLmb4kGIJM7xy3)TZ5c^>_)UsdL0lWz+UZq9?o9vjRe&!ezcT% z4FTy?9db(1RP_TOPKP3=CLfa??KEFi$6*{|evG&QnrY2l@-mbk=uc441Q1lFH;A01 z`fJk)pC#HD+5SP36*~lEj<+=>g-xG2M|P+A%$xkyaCS@+GkvXp_oeqYW5dK0`ufk* z+8;P-mo@^iwZT~1?x;A(VgE3mN3+z=iPx=vfI#xFRDTztIfG@SEJA|*XG#a`;Tk^J z9+3(j((IuSt-)&g>Fx}G0uN>eRNzEp=$yd~EBlV7oalalI-5X*;hrb z;#qL*!i6%g^XD&^cMZ?rf`t)z7X_-2Wq%~}4I$SkP`@b()N5=7Y9}o&)02A$9VNts zm(yD|oYaAP+^&8~$Oei@D+PcyP<&zs(OYd!XWU4LDPP|e9{nA71cW@d_oCYv9QYVw zk6Gnkx=v=Xp7B%FPbh&tita%e00dAnbM=mZe}pf!MG!z;)Fxy>z@*CDpq|;1R}Fqg zh=im9(14EWucKUDggm>;!@&j-VZNyRxb0}<``!)q`23%g?}H5@B7Ld;ocE3YOa0*j zS(#uQ!}M6C*Y7KfwGHV!A0J!t3Iqi;4Ti7VM7Iwy$B6Y!E;3gYcRTcR6ankXch%W$ z#5n|FOLplqGfEY>(E}x4)jzU~Qu{HEDV}>d>DpQ@ks0z zjtlo!-{N!4C~hTC&fe%J(brRVn=hzYyw3>=C7n))gY6hU)>FAzYI4EUx1__^YsmE+ zvd1K{yjGI%)Sh@X=wSqT*2TU=#qM$isEdTS8u1hmh&^ZT*6P25-o!MFLU@Q*MabMc0cY znBG+#qKUM$4^S2W36J_O*T|Spd^pi%u85UzUhIGuD`9Q(d+D>Hw#jH2NJPU|p!* zci%sdcdS(}zL;lEW~`x?0YjBod}8bQ4%>3plHlhz>#yg2k!BsHVs(w%jCyItlAyZO zjhL(>{)MlA$QP>VZi-U-?{on083Aiap;B%{ioo)!Fq)|VM#2|$EGkm(N}j4AnuPvI z@W8bc#;|vY>Q9taRpQ!@W7Av0C}4c~90@wqb^V*6&lM*trQ5CBf{Cg!nQ6#2U#Qtm4`Xv9@v^cK^S&Z*8V_|8UPg%_o+3>Q zUqx=-OE5G0-J^%3olKYtZ}eCmmBK^hnjIGWSbrHbFC`JaQKegUdkc7tZ;6&uE=Gd5 zn+mAw(dLYA zqufp1hb1$WxtqGHcxSWs4(OJLja^|CO!RIWyVGT37s*UB&td8w7EKTyEqY5hHQeQw zl+B6J$V_uv@p|Kq8=&qutCmgtrWqht>Z|GsvXd#`o`2v~Rr8~_e8)&4t&sd@k-u%U zCpXnklQY>{$Ct)Bo0uu_9&am4f`o(%9xI&Wh{}?8Pjp4{f4{OsR?sW~zyYy0mbC{9 zOC1+db1hdIZy=;s-?PbBoXSsins+E|7*XN+LV$-BjLg zG)*REX@?j6r*X&4OdRzLOQks{3qyU1kl>XG(a`|lG8?Azq?4(Z=QJMT7wKeW7PzQ2 zEm3navt%0hT_;+%LcNG92+h4plsEaI$h>(;rw#fp60VrUCv~bnZR&g<+WNk@B$sVD zxiBpt7vcN{h%pZ2lbziXTz_shs`i+Bz3s*w50f_Rwg8`mjAg% zQnX_lkU*|rL3DmZL-3k;0?FXDq3ag%41^Y5cQa4_RkLk-qw7Nr*Rou`dhWbyXzDaQ z8|&zCcl}sAJd5Tq`D~O^>z29mbPXYU)f}fEprmB9r>mV;&)B=u`BxH>?oA5z-7JLU} zZSc^VIiAGhx>-|H84GX5j$3PwYP_S8`}^jdw9Q8{yf`fkf!hcq;;0<^*frdo zZ0nB9DgHj|MW_ENhHnQ{-lMvZ$#Mkb0d3m}_xel+T0Br>tl{r;O+M>XuC7w(2gJ8d zYE-*7X@!y9rVOT`UegH~^3qT!ejR*mqu2&+;9HtEHgz2HLA?-jWRI5!AbS*2MbLa> zDr-T;%$6Ows`NIIq{JuEajqloa~X+x)QG)xjMCxN(pq^dK^UpDSIk7jvaDt_5$x|Ea*2}!h~A|Vac%RTk+ z9gMRkz#kG4Bs2sGZ3(G|y@_Y@T&39V>ZUQry9{+wzOLUexMPwP>#!{jcG}}D-Bkp+ zW1n)WADJ#bB8O&F3)@120kIGPlbnt6*Lzw#kSnCjrT;g$e96``GG`r>U`F^*_`iahx47} zaK6*hoNr5dzXRUK&Fb^;oqc#6TrCMldsX<~`>?tctnNc1x!rxy$0Yn&_}?c){?pDW znRM>|-JBo7|K`REI+@>4=Dh}m1}3l!2`tswEad@+=7FUfpoayTUulk0=mb|9PfRib zBTAmt9B<3l;&;nHmA?>uj{%B@B^!X|F1c|293SHp35Ta}y>PdvKv+KhmXV>pE6A^pBq2_#FO9h~y@p(8e)h=Z3f8fxN`NMX2c%LToOQ*Yk-n zZv+?GUz~3g<%f+Tw%d%n%kqspZn-ZW8=hZp++N8IpcCY384)}$W|Jj2VF(v0w{kQF zI>x;~{GxU+n*Jtrb1AW=hY^0c@|$07kKvcgei(vT%rvSvTo9-Gp#rPy6yzJOa z@j+4gmbXUW+)R8=s+Y~d6W4xrCFe8h0CGz)@eQ{UN*SwHrX!vqq^hB{G3}=JMR`@X zyQ8c3Z^U_K>~_&Suc8QRreBm8$Zz(U(Eh6YR!1{GoPaemUlq9#XA+3rUMMP@nFT7( zjn0>R)!B!H`&qSNYif~N0e)E3B^`^0IHrsx>XZhd3Jn&)?#x%Qg~V*S3X+V;}f5 zLF-)gD;`<{{96LD3E<$8JY0SOMv0OddfD5WhMp@jFE$LH0(UY2kXL325RD=NMiICI zDji#I1g`*tF5xfNnpoms%_#H%!Apc?BIxjo0B3TZU9`t+=0@mJV0q0@yaNx4Z@>}4 z)IeLsP;X+YFLk0@OKO@~?MvkmhsU-!H@pj`6`DEBPC-jsBBXGL3N|0Xiu`7y6L2S%L4)X`a1$lHbg$T zoVP(kwSr%+r{dQ>wmmj1(~x_Hb&S9tqK8LUm=GNK)~ge>V>ueUBK$D5ESou2E;siy zM$X~l+cku6I8gqHxyKm)Lh(z*FPMvikUq(2*~zF+2iRXk`&;+wl-2V6vVPP6@;8eo z_)%B@*k;Nz|uSjWU@2;3dkpPeK-mRDoI`I%|qSPO|B|fAR8#yPOy3aa+mykVt zK)KuS9jH6v@LdXBUR_e?67T7R)Q|VMw0e`c+89L#8uD?qk@}maa^f$~x=@x)nnEwp zJAB_?kbG5zS#V>cw$PdqQtv+~dkjS#i^9%< zlOl&gFA6&px`?ke{XLTa6uN+i8c6vL()373fRScUG1)Ak$!!|;pX2Y;50lr8VMFS24oOY-<0m1CuC(y z#Bg#*mFA$-X_jFZ^?(!=a*H~(vnZXB1(Zmw+@ZkU0hA;sa^i4rbTMiA=BzBzadf)D zLSLBO1%VvM4kp+3;Zr78q53qelM2NxP&3)&a&n=car7W-cv5n&=FhQS? zYCnB8*R_E0MSetLQ2pF4Gbm-Qq6{hX8J<$6P((h<&zvAe(@dbmr}?Uya+4Ey>sqhT zB#_i~zr!?2p4VfZ!ET<~Uy|q89`hW6H0W}+bJ!*M5pUhw^Rk^MUoDopT6@g%TQ|=; z(&nG^m}i-rXP(scE#A5krC$H&nJB3bK5-Mekg-?XgbdkC%V&B4!QCgQWpMkwym}J5 zpZy(u)Hi*}2SGt=X63M%HSFrKzOAm|t$eK!A0YF1RKTpR6yc^x)b^nCN#nqHrZq3u z``SkZBxF@rn9~C0%nHrEnO2UR6uCCGkE4rg$r9VwVKhA|d28!R*DR~9lO@LmRLvyl z^eWhsf2n&{AI|bGWi)*xE!nBw`3(4~3{Z_lK7wZ7CMp$1}@DJ|s#PjVhF>U;B9i*avFo%#<#_9@SRgXc1Durm3)&LCuE>JQ7dFXrmZYE1Lgpc zJ5pb<`q*^fCznup0aa={%Yg(WJ)N7QZ9+Ii7h;otqe<@fuzZ}}7diIsR+;Q{7@H9h zX~B4(>N8kRcJZ4v1TH@oEe37&8W-Xay=b51MT>c9u&w?5) zr)1|jOXq3(xm(UTsZ+Yu)ko*Kl*ww>1-jB!*7hN-*`vn=$(NDDx_Zspw3{#Vva8c; z)@<>b^`x5+8=4ax)^)P|&`s@{(C8+BZtc`;)*{hQ9%%_P84_d%;mXkp7K^six(w6&jGsXdXW2z0bS5VT6v$$X?G zfx!f>ly#Wx|E}@EoCUSk5+5_T>zOs@yjoDbeS;&k{EYxo#1OTbs5K0nhFZFEtk$ zcgpQQtW8#tBzMd1HXi9~G`%LmM_flH(6TWvW-YG>fZHc!?SH6Y|Eay5*@=v%1aq_nzQmLY>6A*!2m&S4Coj2NHo>A5N%s7b6h}odA`4`Lb~iR?p#44D=Tej9}j;<6^XmUvMprY zxsn&!FdgNW2>Z?*11of@(KMA0@erx;4tLn(Z6qi_EsGdOY=fJ-`s3?Zd$K@YmG|L;kfzHi#993Th?nsfe zHy#!dhyd%H?%gE0Q76;!H97!rZlXtVx4)I)`TEuAF9??WPcj~%0u5i$d+3@Qb&0%I z@M@Qf?ST$Up&0q-@GQc52~13=qqeTgC>8b4Y+Yn#n?)Ir(PkO4xLz6S8bXcFXrOsy z{*#m*FMEnbPNzG9ifPyj+>Zh75~1m@1ZmAG zY0al|q^Z(kk;Un7uZ+|2i3d|Cp4a{E)y!pnG zoDqocitxJ>OyhR&5E^cs2o*yK44foNleQdamdy9jAU;aK*1ReU~&OU!m{WD;E(qLh3p8ts$D4*78+y$3Y5) zWz`1MoYU}u_&q;PoNM(Z5bp=H6X)rTw^uM;kAjb-8l1c8*(U>iQxz2uy#&3uGjSZinU$e+PNMyt}g8Iof`7yWI>l2$4W8K`B zcCFBqLQOwf;~%JJ#P9VJmM@pAH$J|+r)3IHuVlkoq+3Z&ADxf*L>C*SwP&#AU|XL z{G4cxD4>TzPJrSF;`1(+_!TZ48DNeWVy-8;Ms%Zfq8qI!;-`jOdIKa_5t5K-2`eZ& zuS#c;f~sT_#FP9D!`^iSuIoc{X{Y*2zfSN^CsKodJ^=xL6Hn$>Q8w()vcD}-tv_ML z4&qHX`Nb4e{Jb#mYxF39nKFYjKaJW`^T55DXR~iAG>TTtQd5WMsWpqKb(Ku5y8s7J z>B_HHgc~)Sz}TDU+H{n@8Qc|ySwSq@5%e8hxbb8>{2e?0-C^0aCfZewH)J6E-Hv=i zsW*R12K{~mwO&uDAhX=}O((yol=_9TuipamJ?*wwt+ zTuZ}aj((N7qO+|cz^Fo1xeBd|fF(>mpQ$Nys9A{KxF6$EngDna&2KyaH+YCSX;0_m zsSrtOh=-pidwOqfMff+oQk87ak@&3hCKwtI3o(*3!P0p6QRhuCH6H%C{ib*9s(i_H zEH=<*O&8|Yj9yEv>gST!6RBD4oaK_(zYwz5?8lJMo(n}_y>1KI3;k`VHFkI88h1WH z)A69tUac*W&6y##Pzq%k-L#4n>^2MJzMq?O9Dn`Q-1md3bVSB|Kcgjgd=tgPp9ObA zS=T)LOmEW48H!M*SwHUu_APiu)7^aQUIBDox{%C^fG)QS(JPMhO+aDyCLk$m0=EHO z?hKtwvedDi=aJN~pMMel_`m@8BS=7NprDw3sryfqs{uZkN!NtQjgqC+G4(4|>b@^h z-ek%X=6dwWFxR2pG;>Wriy!eadeg1yGMmHxCsm4M_8?DSK3!nmi!Z=OUz@=E_CQ;8 z2Fx$eFc(jZ-Qaz;cBaz}-Y%@g;K_yc+4|#5IDdSUKI?D*1!ABux$|Qf0$euk*oJ|v`4&-=- z+Vre?+zzY=KV%1N5uGHPGcAvVrEG-+Zf0bPZb2?d3^QHsr&I@yuXTz5AT8Y40p zc_*E~W)^y&%3Jl9#kaIe9hW50H?_wT$?;rHniI z0Ukm{vr?N*7Q}QGGjg3^kD2z<4mVTLkutrKktsx`bUo5Aq0C2v!(r9(JxH>&{8J{* z#zTjWIB~u%tDzgaO_~GHx7fNPOq%G3BTtxC`@h79Og&x(;JzzlyxCNS zo;+e-G;m2kOx5kX0KRj7wkFsS54PWp#p|bh6-j?JJ^-PXuQ=>9J>x5Vdx9-gJiu2P z+nX660)o9vRK2xa85UVL9&Xf0ptlIUE~=le!-DXYVZ>bGXKCaYp|&!Nq)Uu^o)(pf z&$K%c(OBD^Op?s5;fZ|h7@nBDGWJiiM5(CkpBAa}zwhjyW+!gYiGN_Q_5NvgqU@g* zsfr)U{;4B&+Wa^9=0DM+ZrX^?r7P*KI%}q=IRyvQcT5T5p`l7FTJt34Q& zwoD_`FpW^MRpM3>Qb$i0Agyj7Y`!r?{ghYeI59U#>PJ`T)XrNUiloFCUki{_NwXx& ze;Hsc0IaENGFnlpeQOXhxR7uc!ZE@IC*_4U>B>5qL&L^B~AO-h+-f<)?}QiQNl z>Wui6wC=vwoyKNv8D;2uchJt|UeU*FCnRd!>mZCM;Iu=$3>GliHzLZRwXUn~aivn#`-FWsIas!x(EE(yR!}JXjwzE_CNiKloRE(Q*d{ru6@>-nF7}(Y zd(r7#?0pfeHIZXI36YbHD$#mWYICXzey3w-K0?g?HbK+G2rzGimYL%@^u6Ag|Lk~v zp8wlOalJiXhvgG`TC#ofV^UMI+QKPQ7 z3nJG)y+5Ib{S{44dQfhJUg-h3AH3;#K#bs*9FOA}590|LkcB9EqJulfAo+U%a901~ z+as4T97(}5r{P8uR6{nOYt)th!4i4At+|js8BO?*w3FVUU&*g!CVj-y45p=(aP?dW>bTWl+cK z!A^|9Y58o5Hm`Z^6O4{8u@Jv2*{Q>(hRGl&(-D4 z<`+Gp@@{7&7BXmURTbXYlA)dm7bAtO@kQ2@A*CJdRa!INUL_m`w74ijx!@BFCT$_Bk&9`y;paO%0M5 zw%1Qci^?Jms@46=xuHlt<2<9 zp)5{yxBcM}gk?At!t(J+Sy}+$(@|{HsT=FGyd34$GL#nrFRPzzn?dI%KIYZ<47h0t zcXnNtArx2tpi`925Q>{_bqLu=Ub{H3R0?+8P{TM{=3N^CU*?b;Nz?Ff!ZpnYJ$&p#o*XvyZ z*UA#0d>sf-udbet9HqX=5uq$e=oRG4)M{Hgo1hajg&)GM{KI`aCE3EyQs$TlKW6|L zNBF5d8sX>W-D%;c9AKfl2-w2USTcf9oR>dZO(xUl3qO;|4P1g*!q1X_y6D6ec;G5m z*;Mdwg`dHElZjHnER-5ye+-O+ox)FkrtouqFS_!rG?`tdg`dTB=57ewT_WQ+MD7^! z;f_DvmuF&`7JgWkF)52yS~DxOouLswN2a5g-GFk1M*QzESXTGE_^cY&-jI#0sWsqC zInjQrb}UQ1@bW8y<(r$QhmD0rK+BM`FX3pBSvyvY4$YaBso^ltG=Gwav(xzyZFnDO z)mGZ(F`(>s!KA%%%s}7>y z?CfD3!h@)DESw)}x}NiSeLPL~@peRmOM>OEEnI~0_9AF*$h=ASEOnhdKWA1ZZ-RBZ z{8v5#4f54OWFK>zHs+g8BmE+WH!~z+F1L!O-T*~{$kk$koIB>T0#&#KqJ6P0u#sGt zjKlL}ux3^YD3SpY6L?R9?2^*~S=%KJ$Tkp2y(&4~@?~?CV@xn|UH+|&l%M3yO}FcR z%}w7W^>65w{-m3J>m8)CB}a#K`>0C1REnLx$K2hOyNb~&h}U!vz(}qTCfA9r)kCbs z`5IMgU7=u(ojrav&qQ@lxJyc#dvxND+CIkV>R$;|Su+DxuGl)8)dAf10OO1JR-b}t zs*?I@eC-u1Y2Z&4Og7=?-pJF*N=d2~orte{qu-@3<-4Q5NN$%Iku4IeCrYD^c)gbi z-IT9u3A9%P?OFm(Eo^U*#U^79juSGLX2TZ&utLcOJEo6#s~4{XFw&kl@)_`py*}X= zBj|9lnnK;rdHSVOJayl!CHdLR7#@8jcAO8Q29eE$9fvhLo=(Zx?Dz^|Y<5h0;Ys;0 zWAmWgz!L@qv7(OzQeVe3NWxnpXJ#_xNPcQy`du;rE6u3$)%#$OOI8na=Sojx)s!zX zxpX#JJsoNsTPMTU16j@H(%B^S!;kcbM<%J7OUtqes4vYGsJ~F7x%BNla_Je5dG+$3 z6F&v4o%}jzE3v-6vIkZgR6CY_5q>=f|4Q&{p@BffVc0=O!KN9uQ%h;jwcKpilBe#g z)<<^r2{Z{Gfk&r8|MGm)=^Gp_zFMD;T0cfwnC9r;f+BV2=+9@UFEY8fr9Vz{aj};Z zAw>K%A<7h_|4OFV-kHqZ+HTJMfb8%m$?ESY>6lOeT4Ww?dU16P>X#Naoo#>fA3z9W z>wKMAkQX>lhqMqfUvf!em0#1$S7kz=A}MC$KuzM_pylJW0l_-rkrI5il<;$k2AzE( zC7eyBp3qrP+1}O|2MdA@`?I8kX&<=g+{10*Mw3|bW=aYEEGc22{V^!*@01b(nNosW zPA#;jM_M3e=Ryhe&00oWuj;V8ZTgT(-EK{L?_YK6)SkMvbl2y0OP2me?pCG!@sYdr zus7LZ&(qgC4lz$p9SwDqcIZ|^PYW23pZ@*GE!Qi6CEW(&h1BP?Iy(NyE&h)E;gMUM zIvJueL^pO(C0D_DQzM8Ns3Wc=0&-T+d512zZxfHpSM)$U3e^3#agWs+A%Q|#d$D`h zKXtmZT7oo32Qo9V?C~A)dp+OT#~{-acKxY(!gi_`*CA!Ak6}l26jd@y zhswd4c7_27rveN0;ZrA0MwJ|>Q$CO`#@#&P#p#M}UYvd?pD+zvFHR=!_#e25B6{-P zG#+nq`YcVUdUK?+%6N-Fs&pl#*#4UKiNB_~jKB8}1D%-3H z4TJFS_tzu`!h}jPz`Ct+cm#bTaRus`5wuf#BzTID_DCSEWV$%Ez9*gQJA{y*F3R-$ z(#>B}PmZmVZy^NYkf7f@A^uocp8~)o;2bwr$J{9n32c1v1LP1xC1QLLtSoFr1Gp;V z>Zd;C+}`=^-!cB>hZh=LK$#frD?hmKlH}Q5hKBnnM{~s4Dbn0I$1`DK9hWw#Go3;B zg&@*!Ibat?--D~R(Z2T4S_CWowEUoPM^e&dh>OgF#h-Y0m#2(Te~Dq-&|gjvyh`eF zPjgPnm{@nIxl#R&m8+SI;mZJsdH?F1fVs@a4Nld2&G`XyJ?ur>u+t`RgwH*oyN`1O z6EBr!-EBj&lJ9-yp7aTtR9k6>y0n5BvF`>WUMnIz4Zc9}Ij1h;a+g%vKw8Sg^I__{ zYOwu5q_@r(?dukp>L($qS_&BCENFgvZ{6Bj{P+5j2WTz{F6#bO`^w1coqU^kb?8FS z_Y^sov7eAkvt2}+_B1<%pvb&DI6*@1PEi{-W=ykFWbu{j3(q;FA%qg4PW@$^5Fr^& z(RTYp*mmX#QKF$|#tyQOD#+qpSTm8#VXE)|J>;Br3}1uXiTUPCas+6KM1Dp8TEZ^FSrQ zy^fKr6#Bc7l9^XyxqlaKAd1WN#E7evt$^M8Lh;MdS^BO~V^D=mg?y{KcbBtV3L8{6 zqcqTm2yP?5IfFSo90GbhL8(5=NbV^iJl zUFRUpLk{-1RQKNIY^2H1hv6JDV9m%EAE>nfR=?iY%Uc&6F9Hx`e4QW>^8^nWH;`7o zZPC{_yUuB*iK@IzhLqzU0l5jeHjpb0G@{(Uw}b^L)621SywaDNsqJ}s)3cdr@(6zx zsx6l|m8eR)-zQO%4@XMe;Pw@;ff6)*81EP7N++tKVZgA;uZ=nI*GHp7CR-LJ4_3R^XJE4Un%Bf_aD#_E;yUHIxEpbk z2KJ)jj}}aJ4$nmfO2HPEdCyIqT&FH)DNQk~ z(E>Oj6Jlk0@evSnd}6NFV|vSQjoC?X^5J?1$=jh2@H8d9&#$o4(_+SNo3apI{PPZ{ zk~)eX3$3bY2?H(qRsnHwZjm#00Ly|lpp*;tvo`~PoUItb`P^3e%dHyn=<4D!ax5td z(HxJGLA+upa5RKNO(i67yuNb~jjn@es59F$2GNi~wDc_}{q-#;fd%u#|KEa;?f>tp zNJRYq)z4cXXIaur%VAJN5n^1!fOV*Dc8Pl7Ja=5%32D(+8!VD}s7roI$lF`pm(KYU zLelbI(cDbIPwo)NWL`brXd?7k-?!LX;F1%a0W%79Ke<-soLnnZMO3Ff8lOoZWuvB` zYOmBODnOKTitT8EQk2?vu9N>D0pSG0Im?EGxyHcjAHU?eiCz`O=aQKVnFR0-(nEAhMe*R zIRu?t^IK3y_S?pWrxWQK;j;ZUN#|LmGm|=2rwY7v=1P7ig@-4F?q%;UoBve(q}SlT z`Jw7B?S@vuHaWN*eOrjND*h7-o7Y62EGj$XPjN-8+hvu7|KPN*(`Y;%mTdv**M{S+ zF`sQb9uLQzG{OH$?a{|>VMM>r<+JqnE5a-6%&u3GtiEe^Ku*V9KP1v??U@7!I9*1; zCa1YpQIeYVNAzEa;eWG>)sQ5=KvDyc^1*k$g?$oFX_PPM1L$4rqLe_5@6>3)jW4g><_o5g{^>o^d29oI7`-<`y0@70oLnV+wj7tJRD#0oUZ zZM_6;_N=p8q3h2w2%`PCK^g0I82Zj489x?Rz zdLs>Dpz{Y(b&bqedRAmNfc-g&%d|ohn&nubK_uKtWelB4k-vs|qw&<)^}<{Ao6)oY zIV*Ki(;A7hwXuHn<}--xlG$itUr_c4hO70&X%`2pO9r4kJB~&*)DTi<|Cgf@SUpP; ziX~x%BpjbkSS1NXlCWM94n6LC;WBAiUzpr{$+bn+XowKfGq*F|CYt+i19e+-|2;w| z^{i?BZpwR_Nuv7mIgS9jjX>&Vt9QAw#a^|M2)FR)AW4X(y7uE6ZmZIDPfpi8`}694 zjgG0y+`6YrRp6U;SaAe=`?E1VS^R!+@^kU+j}+_Rn|Y-#8&zt#VoPsvjFZOdEsi(H zZUag$ZvoUz-2oN-s(QH8*(!OA0I0+zwyB?Mgh>4uz-;4y9wljPNG-QjxrfR$r_FYd zrOtcI9rrGdvQADXbU}!t(g|IP+V$uWirSh^=<-ENI-yJD_oWlMAYHSY0Ma22gk8Pv zhBeOv?5SwPevj5$oO84&8rcrCQA&D_Q`fIiD7!0EwDX*j-ZTNfvaB#YW+gK zn*O)Xvh)jXx~qQ}-X%RlzliuQ-in5^zN|3+ZWVCVlX3T&F8eLNf^gghjM{UdUL6iB z5#Xmz?pWwkuV7pNjVVUtN?TT(D=Xs(eB#|${PM%z=pWE?3~kHFO%5SWJ@i$OfCxK# zyR6zB>HTU_>~-jsghYHgnGeh(u0zlHLx$k@Z(N58!x5>vQ-zY&YN$V+g!DRe zAsM@9|9+6pbvGg4Q=2IS_LuH=6$En}hwWwI<}tbT<^nJ7In7OijB+!)>eXK~$RN%k zyuE5|VEzm{;L2*gn{8RGyL>KpB*5*ylziUHUK#ZypFcgsmCv6f^snV}>*Awby_~R2y~Ip=Mv?}=Qj}4^7%A3{}lu>|!Ii5@FCUh+Jsa14}InmcbU#L|S`Re;r+f5#xppro-H#Pbxd&Hy zc2jIE@LKhDU+Jbz-zu$te z@1zy&4W8Te+YLm*AABW%fu|oc1e?EHsIMdm@+$AzHjnLexjLs%;@~eK!userPZ8DR z;*24Lr6|u7HGq=qW#WiXgu4J=%MYZL`{(pl{hd}$7p0CWq(Ll%xdzcQ=kf;OR1Fl+ z=>Dw9nK)U(Icg)d=w6v^^h?Uu?r#bSi02Sl1(mLW-w1tA_!_y#=sv!%e{p2JikGM5 ztj!-Dr?@kxhXZHMMRk1_(Oi*oClAI`tW<;M`c^f_yWV`gH92VWKJV+B_ZP1>H}m4% zY`)+6{-DkKz3*>6P`r7LXY#}eb#pqVs4096+bwH(m_E+QQ$rTn<8W)Zj2@m(3v~~t z%sIZ{0F}=f$|!f38~k9o#x-^gjJI8M>oM`uP@s8GnNj|R($W7c5!TfaB)qpFL6^v zrA*IR9Xmk0xpTP7*QestEF<{=IqPUoBhRU-fmr8;!0QOo4;>@?FSc&1v@kh?_ym9k zD_l&XPa31b&QoIx=};{luh-JNqb=0$70wftpMI}#o|W>PI8}M5!fc!4oucLlxB}`r z9t?d04|8YBCi*|;Saom29*-em+2Ws!=EazzE+Gpgtow?FJ}&(tI;nve6=)M-wY9}-|})^Y(R}`AZpobWk?WI(-xM>R<*&=={*6!yV(7~C=s1I5L+1$70U z8Pq+`Q|UaO+2j%1HFXb2>~OX36HMMsq&>xe{_bKaQFRv2kT46RY zhO^H;sq5uiug2Q^=AJ8)v!v@?F6L@+(tMY7Py4Bpb`#crUBA1-NejSJ)03ZoFcm0W z+Q`MG2b0Pth#7~^SoT}+C~RAz^-PMh3$hYc(*8BoO>(54p7842gqn`O9Z+~i}&P42DDmj+p*@+;`qsQhT-Fo+Hi664wsBN7(6!n4R|`ZlfL zEvN>B1W1!?PEc|ZoB*hK8fFtx8*#LQK!LKmQ4&T;!a7NKJe{z65D9sb;0uxPlKgWzI>zp|bd)?Q&g`A>a|hpunzF!0>v`&P0X#!aU16z@0mNj{yTX8{MUtO`tA|6$mRk70m>ZiZ|gG~sAbbIY4{QlI; zzDpBgyM_Wjf3xiH?_iL{7&$0_cHrOwI_o$mi?o#-G0cF!obHs*@*ObPz7HJu7q0sM z*!vcMD2uiKciH7Cx>(*X`Btcqh}={_)J1l^lot}b6$&f62nxH~Uc8*FR*`Z;$~vB| zcCypG>_nY1vr-VRT@<@oT2X1OVM%Ifsqp_j^S%S`E})k6ec%84{|9DfXXcriXP%jP z=9%kTok76T?apg_aQNNye}I-iP}wAA0Q2+H-+dp;SStKWSNRv7mH&6ve;z(oOZj7? z>%#f#w95K#D}Un0%Z^Ih4&}o~EYjdcHtxv;Yd1`fz>7^QkW0n#+h}Mzty)xw0S$-I z!7j>mvdQ-V=Qx6fGuc@)&+ePwY*-jPBt8f_=yf^9hpXCj$GK_({LV zd(tB7vv#CMRNz7+HPZO^kK7pw?sqFTL$xdWBR)ElzC4Ivk(qXdCIl_{4&=Z_;}!S; zd9mz7Fb2g#U^0+1(^Q|+Q3&LkgwMkx(>o19+PRhb$PwD*rvZ}Is4bfa)=`nsgp#Cz z=juyOYqX_l7#ciZdIwQCdQ&+DN{O$Cz$0+TpLOrvz!CT}855rnLd%`s+j|<1u!0GK zWk*zu?~O$15J|`my{Z@6GwV@c#-3Rhd}*G(Q5JzO&67L4xL907dudkb6Vw{BNp#X) znz5*uQew;ML}U|NKgod~eqnJx2Y$58pvMW2TQNnFChLF0FX@Sq!$1zeey2dPn;|m^ zlD&ZV1|U6Gv}}=f#ujN9+ag723p`^(%g1V(hRLr)YdmL2FmevZ#{@_w>gQDo&gNoWE)olFkdY$)c&`OqBzQIrL`!Lwh{1JX&6iUKqq~8c>MtGeDWr{1?;j05M zf77oDFWZfR;CpDLXcA>rxJIFK&cFg%+4qF_&Qo9RJLYLr{i0oY4s&Y^xdzX6Z!yay zB-2|&x!~HFXKPv2MrvAG{Vr6^c=%1!>i6L1MD2Hm2-z{Yov*^Zg9(NW6YRO%H=Q%}iee`H>@iRgw zjPTjcDUiW3E5dbUO%*zoC+SXn;G_6163p=VjJv3n(V#igiTNZ}X)$vtqz*v8sgeMu z^VCM~*OoqV77}R|sEzzHy>x|ua;X1T8g2=vozt%HVqI->6>1N)sks7(<8)8i7aF20 z=!%Fi{KVJ$-#EiRP_I$O}=zu^kH5LW}aWQHR!`spt|>u~-%Vi>Jm{{?l&g zuwpmLcc$JYmG4(7U#=?U6RrNsdZYW-A6!?V#iV?Kok0Cwtsb@Sye=J$eW-i%qn>vb zjz01&MBxf6i*T%BwkqW#t^RZOuMLhMR9zanCCrNJR4E^54WHI`_PpaKFIL=4LHaXV z{TH;Wj3Zr5tZxEk&k-t8KI#iarY2sYsemcG{`_;#U4u7Y*5Ehl*$Du$7gHGQrDRv6 z={%=T9r4uSZe;bo)3lY2Flv-NWgvFjhP^%a(1f%~~XhwN{MqAWW zXr@+ZmaX<+RSV4z?~fAE%cq6lwezxHJfC2?5PeF!rY5AOTw=Fyu6!7)WkhsuI95Rz(+kB9BpY=^(-H0K_`)zGQKhZGf)mZnb3EUBjqC7!D^YAC z@ioZb?4AHpCUGkgDMx`?F$khZV(M+PwNafj16@rXQp&?4OSgxQAs)a+7FvUx ziPM_&vKyjj!c!=%3Lk;hK5bbMCZE7OhcE|yZJ^guy!V|Gx%kd>x&x&zkM|zNCanDR zs7&t{a8Ogqz+jB}MxhWrN z1s?x75`~zIrf`KI8k2t+2)JVW`!l@5!G@@f(SY118RJF-$cC?d(V?CtkrFKt4P9e= zxg_HNRR6Nd6OH3N_%OO>R`|;F2#kgUR;FLB#gl}Q1)lWIl`1^mcNF<-wy7l!2P%WZ zIa9EVl~nyzKt-Pkr8_mg{hRiqI+t6|dOyH~lFd0k#t*!5Qd)D;^))IZ8{ys!@B`Py z5?&_z?R^p+(zll$!>{tRNY8dUc@T<$(Bl#|PwZ+SCaUom=l}sNuar-T$ZYCNg&r5d z#_1TmQzd`TVJ4DbZT3d|zzNCmu;h_>f}FZF9A8mk<8b`@=pidmupPRH3aoO{MT-Du z7Eb8*gh;lgDrBo`tTzbJ*jOG)DGtLOl7wkZ-H>}JeXwFc>8%hDa9;?56D#sJ_Uo2Q?QpLplhO z33p!v;n%2(74BG*xmFhK61)SD3~Mpb_)(t#soWLFI%I@r2lxze?=%|P)pSpCI1KMe zNK$f}`WZjHB#g5b@*RF`){#K>DQK$!Pi8{FZjvO2-_50sBi!_C~R zle-yuEY%Uca#D5=#oG=e{{7N#f~&s@s{ZD(&<{f20SBW`{&W_!WsPVIN1g-&VdsYp zA&|8uqKov$$Wd{TeRTrvKGGm3;Kn~WTY|K&(A5?cAO z``doB7axT8zJIOnsNImRDy>qOrg*( zKv<sgF5><9|4^4?jkr6>KIS?TS=j22imgUB$?Xx#MS^Y8-OGiW8$;%6?}TV4>YG zUR7EZ;MwlcM3#Ovx;_|FLyYd9Yd3sB1ni1>*Q9KBUZ&k(5DcCeqAjTSO;G(H&-QqH z)ifxynyA=|jY2EVqSa|POp_qL9)09TxU0VjXDvbdS`BI;Wj`qNL;Y3DY8Zv~FZ+g5 z=p6-xJ}>apAZL*k1{WvF?nI&L$Mf^I+Sfh;k`T#*;@_{2ELeSha(`a{dLyy=WFDU# zv?XTZ`E8IU663R`+8dzD^qz#IUdo23kow-r_J?tas%=k!=cANHXH~^yRYBPg1)e@O z^t%XW1h6=W5vEyQ#n7WE$ERtKY07Wf71WyXiQS4ZDoD+jYd6#%83BPr0l)G~_jmnL zPCGC6)M__mvijJG0+xO~x;_wM2-VUt_nA679m>@}mPV5f9*0@FR2gW}S9^A%GQJK9 z-AZ!wWh0Qkv!?<`i$;pd4*iIIumpP!Xx?83QH!RQ82XXaptWUqCk=P9aU+@<8OcW3 zY%N9O=@W^KoXCo_VV+OttGvZvV-lTWJm*e*UXiJSxDf;P5V=F6Y6OVJJ3$74{8NEX zOywY04*@AAq@wsHP0HsBY5gw}UzqiZG9Y~_7Z9q3(xw1=di-uBJw0#l&_oD$Q>Jul zK+13S2GuUrp86|W==tC)!=16g^UM2?^)&<+KQLSxXdsXPQ2EuzNSh$v zhcCSaow{fF?6ckkWSvEQmd59JI4A-zrh)cT474Pe;XxbEPHzYT+2}y83PXfRV^=Di z$%v3tv6u-!&Fz!qpRVP(kbfXSHz)r-93%tjBMVQu4)Rf)+Ol@V{9iDfJP80khSTpO z+3=08I+AyS$)4yu(h%*`pm23aU{gP!R)`PE<2>IgzUGeRfM?*m$vm14X}mL>6&CX{ ztfuA=l2qUbX($b+fq)7uuPV2E3r8-eykt(TE@V@b6e&(#GG}Yx-Z$3Eg(s1T)q{8c zbUHU7XGMdx;N33KpH}U#(1I>YGb(xvBm9V=dGCtWf2IAPaO@%8szFB@SfRmyhq~>f zD?6}wRC%oTVF+khOg4BGzc7vuRW;T3@UDPkejGJbx8$8j3k$e+fkT7nSJGw$YZag2 z2?~5kMLxBL_Dy&bY&|U)Yi!a&atN(f;LLV7L!2;^lplVg=S=lCfef*LX2kj^5vvDH z=IaQt@9+!wwu@N$??TMMD!F}nxn+7SK&}$K%B1`ydSw$@I0caD&Ab3w&vp1c^g76z z8>g1CJ~1MdPu6($Mt_pB(=ki6)jqo-Efix^#&4UzHn7%(1%j_VHCo;0wrt>@gNalh z)c5m{a3%b=S2}2KBr>oU||zYT<}I&#%TyvGHpMVY5N1C?G)f5(Y6S`l(Zd6A%t#%gl@aE zUCLUAL|b=g3vHe3w=Zq0hWg@8rD*9-w2RP8;He<+bWUKPe@1mcJLXfn)G&zFvEF;Z z?Ih&a;}_d4kQ>Hg3L)fO_;J35u|;YOtYOrIv>^W)`|XRoT0$OU8qR-}({~Ip9^rl0 z4Qx8td|pc`56Kg{w+4d#fW-t1NuByaJF#I|V+1_yGg#1;er5I7dm3J!)%~@7r@q4V z-w&$mI~LUtM0B-h*QxKSzYkon)uerG&1Gx9(8F(8V^iJFfu1k4udNCtAM66hs0ut2 zW7HKTXBWMSuQ{D4J!4vW_3JF*{inW?5{RzBbM3t;g69K_{4wg%?Tu*8`qDF@w}rWD z;#TIwXeQN1a3BtX2^EBq%~XgAeN3SC!L89hP6x**q?EjRHVwwbmK$d`m!0a9(WjX@ zqh9r;4m+=#g$FAdmK}8ybqrX)3)jx5ivOitC@2@S(OAzRBae(sGIV6bks*>1p^ety z6Y$OQM1g1Pf8so~?yt4|@o^%|cQo$b!t4S6nIU|zGAHS_$v6n+I)F2NUiZjl$j~vM zVnq_=eCmr$)H_k2fI`!kD3F7#oJUlcPtQS-HW7@c+WSMCUz4TsQN`nW-AyP9DJF+#$m)z_~wy?gOJ zztU}@GDl^4Ilni(+ghh5moFS;2uB$|pG{>5Z^_XwyrX}3X-bo`+w}6ALU2mKdkiFI zV(fAJkS=J;_c@RDD0fBB_4rA+M~_#OPJQDs9Q5q+Osg9T!n;HFmmB04xLv{ce5mJi z{be*!c6(08*M>H@5=+kn;4=Gu!5+#0sVd725!x5ec&f_{b=nsvg+ox^S&lS+E8W&Z zT2tCn-Pq4_+|%H3HN<}wzbpE9&jwGUXWCKnHh9thP9#o>h(8nkQ_mCle5mI$PYtp- zK$rNJK918&o)2WledUuH;(rR=?HcH*4z1ltXgQtZr_y;m?+f5KBMe7-PxES5;nYvl z5nTCd@>F|vu=U9|2+y5{2AJ5w@k}~Iy8%MaebEh`kJ&mv&*LdIJ*PD|`d{DVI>b^& zhx5*q5(OeGT`;YtBM@yd4rn_x^%vZFp{ak=GBTGk)6L8k%v{OLRm?18riqz(%*?b1^d~GIKmL^~}^UGmV+a%*GnX>c&CC_d zT*=H;%v{aPHOzc~nQNK3j+sv|^BHEYXJ#ccUt#7(X1>YHDrRnD<}PNw%gkD4e#p%I z%sj}qU6>id%y4E#Ff$IhOvkkFZR|jJYl3M{>Sy{XV)?tg z!TTC~=BqqG-l=F$Bokwqw)nu;-nSsG7UtT)13$xH@4cNxycZE?%>whh*1H@Y-Vb45 zDD6<#%?3aVg?jI!0FuJI^g6M328>Ma(=6x{m`Fa*n~5LZkqAkws=)!=C-LiD?|jMa z{RN_@S7gx^QnZ@+T?%(aLQ1E*$dhJ%kC z)ft4u-RUE$od<#I1W!luDAX_43x&xryx%~yq+&Qb?=+mnL<7&pp~oGeIYnU-LB$Z% zYYb{9mVw?p!8w&P#5!9t6h&~k6r9%}S`N6Frik^s%QNRv|xi#_qDN82TXO-_~fjB!w0sHFreY)@a zefv8caGeCuu2ZJS9{0fLqTXlkGy*`2LSO@MVaOmH`{|8mtYL@4j+n9}_|#{o_LqJp z(LTM&o!c8t{yf<9m#v0Y6@DbOB+r!Gogs8`akJx1oFWnk7;$zqM ziB)rE*OYIq$9Emj6~GqM2~{rQVOF+0!*RIxwK{B(nBCL=nJ`kW&4OLIF8=?||2-{j+*iHCEN@ zA6pEl3fIXQrFH$bP>lKFtU0D5Jcg4V!)cG!_ z=ae6wT{Az>O9vp|ogY%@C6=0qu1>6T*s8$I@UegQTGoG7WgZed6mK zAfptdtn5L-qfiA9QFOwf>dfoCw9m_U>A=#(k;2j|Wp09Zz;M>*XgT=svScJ%g|GaU zR}(9e0TQabXR*#i1oCbN07|cQ6Ny6;t6r!2xI?0zdn6HDa0a>YMLO4IO|B5{YE&TE zD`C%?B~zJ^s2t=V@|1qn4*(zR!VO4Quy;J*>N`l39!7CMSH{W=A*_NZEj;_%Bzf;2 zFV|X^Qu9d==d{3*o<3vCO_k*$!vusoKY#$gRGh!f-OPsq1=-x8;V@ ziBuP7o4V4l98W)Dq#qTAqX6ndK$99O3}+K39Zj5cHgVU8y|}481!>nul(h zkHeg$E~3LOPe-cUQ~Nv}DIci{6RUJJ8$o@c27_l|1c=krH4cf^6bgbGi+}j$Dw^O8 zXk(@9NP~(-*bFrDcWXBG0CdepkxcI~lo;2MOG7lC@fz=U+!X*9QcejpAxG@w)@+=q zr%2gkqOz79jYPF&O`qT08z8mg!175U??os6Qc-pgJ8p&V2G9h`Gc*dhcn6_ofrh7S z6*gWx6)Va7#|knZag+J#QZnCK46|U>Kb~M##RJTG#L28O8?&A)X4VUZu-4vPwiZ^o zLE|Y~gC7<2V;z3%WEiMGfpXp1`I(-w)hzTGtfc=74IL4H%TB{HIBB5UX;@Ekx5w~G zQ&$n>n_e-q>C}M=!!zhdQb~FpKs7ejGUsgQGS zWIYSja1_DiyYMJA@fNvDsaz+@)6>+|%aU1F`d02r<9oOclrDC5TKG}vMlbLX@Q89v z;fb3due1D!)HDwkmL=yqO6pwwOBY9|ar0Z(WuzGR_nyw)Bd;W@%gC$9>Nrx+J*aX9 zC05Pesu8^TDD1mg(>K3~F8&4?BThJa%qSm)rPI*zz20PG*Yrv04$X)Y_V07&+*kw9 zZ3Ie&FDT?MUr@{`NIz4Ax!H@DsOZdd%J?*XeS@ zS-H~_Z4C{k$0^?N8gv7bhjI{R*@%rOb?j~0kdRWI5j*eOQiWAvUFYum1!z$g@ zL+YLVV?cSK^k`I8;(?6NzBT~N5A)j4G--RX1XWvVZh&}M+L3|+5_eCZ;pt0pDsI`I zrTtg=i5oq^o<$lDUhkR_UT)Z5KIssUTlQ0t#XJFX#i16bxwykFOcm#=hK@5^Tpf1J zoG;9371Nc0xcwVOH)%&!;lh{m>XCUt0fMv7NE=yQM`i}8v2z1YSi$gA3;3Y@$T;9p zx>x04Kk9>Ik6TU$mm7eE7x|;*c??IFCd?0>nYdfZwPN;ukJ{tVc&-caWC7)a&k7)j z$It-sIzvnM21v=}&Uuzzig1=lCD-f>q*4P?fWHvpoJLlJb8_Ntt*VwriD{^xljW06 zxsI7@ znYo6UBKlra{}5(snE592Kh4YrX6|QZI1Bxd{XWS|f%)`c=0WCD%gk-e+{MgynfVGc z*E6#VgFnlD*D>=DGri0_%1jYvrK$#{{r~E(p@2S$dYT~oEjCbC1-%y90!?aDJnV!( zp$l{z^oMYN4}C4dM?uFx_kwO594H)z-VeP4dIR)x&<{Ybgzj-opl}WJFz7MR+0b*L z=R+@sUIo1t`Wfg=&^w?%hW-}%H|P+I^&<2r=$X(q=zF1`gWd-HK6D-QY3NQdfkGeX z7-$`ICiEO=JM`_)4?(Yo-UVF;eHuClI7UJbgB}k(9ohuF7Q3Ed4^1KohQUqc_l?~ln1t%qI-zqQbn(3_z@geG+sd3*?c z9NG*01vDvpoMh+7cJ>g--3#tW=ve4*==b6O1au?xzu|rxdOx%mdO7^+pbMezB|q4D z=mh8;(4>~bzd`;TCEH`M3`6Q@p=8r<9ey8DxHJ2XA@7S)kRzHENlV1hXe^-LN-dUd z{6VQHo>IHa4x72e>M+{P7W2F%#U)mg#b~#h9A@W|xhAtS3<^;MZZ|bHHj=y9hIGo@ zvh9WVRyU`XE zohMo?qEXD7Y_*v4#D&IUmzl+L*ziAjDm&7Y4zugbg87n1T$* z{_unzCceE?m@b6CCfZf?ll;h^=Rei#a1}fK^S6k32D@FEe@1GK&2F7<&UZR;>@J5h zM@9(6u;%A1H0J}II9w5nMA}+N@kIQp{yG8YG+ExO`|Aa9IP^fhpo7l4x&;@2G%HaN zCt{FZh(nyZD8R-_@FmuT=3JM}WOSNS#TZf8h&)N)+YX!BQr*+(EG?pQ)yvXv^2oQk zicO-$>J;ahouZAJ4Oz}Y(OMw7EJYTF6KP66tkz^EW|QBqn{W>Z_bt2oT4Cb zzc_?ZIah7dH`goWMJkh$b~uZ0+s3@O$l-LPib5XXar{%5YPJ|lkoHnJZU1yk*5(ol zYXO7BwdV3M4CCVBVu5X;*=RD`Q^jp^Iu=(+uHBqZSqUG)k97dVB{hvmR%Dqcmlf59 z>p#V2u>o+jVv*%E+NE$t+ZfS-P>^V(2-)s-z0iviQK*b&dLl=2(L%F0ZrTKKQIW-D zT_hG7Ev91g7^6uv+UL1SkPgEsAL-!exR5S;qKR4UJYyj3K{(;e>r#=OkYP2MrTVg% z%_fKFw2E`hqH(UnTI_O~W5o%mK#)V6XLVBXg-WC~SdlZq_vntyV(yq zHY`krLvuCe7m8>kVu2N%6jd`%M2=FmBOjw^F)tE}91bdlMI2Y;9PgT&N?da_aJmyX z$r!K_u=ZmX7a1L*!P7$^K@yPAhuItEV6*z5H017Viz_7j{3U)>ITW;^hov;*&M2mWw7@WjW7ZlrBHGlZ&k z;&((tYl~hD?ZA%$d|UM)mba9j+AgoZG3~$;etcYAeLyEvLDxY?9MmB;HjR)Tr9(C; z5nXBtm@>Vh2-1L(64y;97ypv&0j)1qRW3^lfS?HitNvA9!{{NL}s?&#Bn2=U`UJ5q<9$p=5;~g z^jm}`#bJ~-!H`>oR+b-5R+kh;FjTK1v_Fh8FRIrI!BD$79}K5mrA!-6YdUt4fViYC zy+7s`+N}@{;$oBJ&PcBt8=X0r*`QBm$B6VScC*TxY=qFIhZvk)RALqfiF%ivbr?(_ z7Mkq^81T&|f?h4n58_}e=LcN=zts6h9@3qSZ019A-bC46Iz5~y7pM^*o0!6QlSwWh zh=KHZaZ^(rkTNWgGOR8q$?|ipF1Q%a;r-qXUgQQJYJldd$bz|5kx2x{p@^Wh$fh#6 zM!Vez#-h7Nn#KXa-}I#GX#&*Tzd#vjl6L$N#HoVE#vSm{7I2bZJmVII{c>kU4za+ZC*KFw6i&$ zM7Npu>RI2qQMTvEwo$fCvOQ0>=gW49Y};hpA=?XOdx>mcYqX3t&z)qnr`zn4j7zR{ zS*~>zr@Q85nQc?@os+E#_2&G8fF(Zr4Q%SW^{@%&2HEB~{0ukM;jglN4mR~w_22cZ zF2Z3`I+w$ybb8A+aBvyzOMr)+Y#@_g2y}{yfsGmHECD{4!U84C=;oU3K+FmY$T24{ zWVVol^oZBw%Jy8@Hp_OQY%h>)i)>G_TC!c{8D>*OX{r()OEN4CLutwS3Aef+<#pu(X# zLUn@DLPbDzhPn*ua;Pp)U7@-`b%*K!)l*izpn5~~f$9r&1ynyM5$Z~)tDvriiiGM9 zH2`WLR1{P+)HP6ppkkl~L&ZW3fx?nXT)eCjpc0{ypoT&XgBlK%43z?v3N->M4QeFR zD5%j;I;eE0F;E#$dME?bSg3JORPDlpe901f|?991u7HjdZ?*TSy0(f)1an9 z&48K-H4Ewns2ibjpk_nOfy#x-gEB(7FIiD({*UQ!FsxrFvT=aSm?TnKy- z|I`a+*m=-2$GCKPuGRe2LNnByBAk1%Td5q`lDJz`vwwiEf9(kw zo*sHusAhk^bhh*K*|WVZ5iaQ8xg~v?Kkkszp*a{=N`Fl-xg_P|Pal|5s6U#ohOOqb zB=kqq2~-vU$#J^*c{lqj^X(r>yAv(S=)meKTY#j8@yw=F?3OHcV$V5W93{q~-+*S+ zf9T6()PJ~pwCw&1+N-=CgvH$gS{p%sN)?CH$$0#C_ZPmNf^`(Erwq0h47M9B^RQio z6{?)ar8y|s)MB{JTaO4o|1~_C_tV^)U`UJ5{xH-QISl>25DY*VjB;(3{HT5KbpDLI zXy4I>vMT4ym);&OZ9Qyk(PFb{N%{yPjD5q*Rwmn`lOwl*mkp zp7fLGO6t#~uQG2+o7|K?xBn|~p}eSUB6NH0GnID^szSi62ENL+0k1z{{JpgH5%-j| zPMil@xlT;Dk@~aNi*I^bYCmKX?YOP1v-apnFr-E3^TAw*7ue*y&zC3FDQ~m**=C+> zEfQhpONaBCSS;SJM!quvKOI^r+rar3)IUxONg@{|FSIe9Vc}dHHByWd2MiD`#-Go>97{+fT>Xq*xC*(9#UPuF?vZWHT7r`tCG;C7E7+lkMcBop zHSRdT68+Yqf@!az4sPPL-2V~TA6`OBD%sZTzhzpJ+upZY$|lYo7jVpmdIk zpJfvMjlBf8Nd}~GN_A{MJ#0>~OdZNBWGSsc2!5gT&kd@o#3kRZalyqs{Y?I98bBSYpAUC7UCk{gRk6Z;zL{|H|=i zFMs9vOb$!7yg%3;dTrFF&2C<(s71LB56XSSpT3{MUpay1<-M5x$LshE@Ejl`-Cp~` zB4Gg+cKQXS)MLrmZl4}(3vZ6CJ8#O z3}<$rBW{NcE#3heTJRtp#K}XPxI1BEpf+1fS!R0?_R-N1^3ZSSSS5|w$hY!z1{-_W z__%V6;KrvY+_*GYS2_mgnZ^j2FX@F5fWx_53pk2US*aIlp=lOQc+>dXd|v7~;EJ$W z@TW%~@iwTCg7~D!ra0_0laYEF^Zpa$sg@LRKq>)eG9-bDymJ*9N!cm#Po-0qbPT{` zx7utNqDpXB5{DWcq6sH0iND}@ti@d1ywg9{Ra`vQh%=v5W}+9P8S0JPqUX3 zqBo2gmpwJZAQzQcw8nrTiq$36Cutgg)zFm36e8yYE30#IldgOvT^L*9^zmB_KT^Mo zp8|d=4$#RnekT(|#0h#jMK^3zK9LJGGBY=g(x1W^Y!O-AGYu<-H+fw^%y^X03TBLyN|(r6g&x9>0bwU9pLi- z{{(QN{;*3vBc9{BndMD}5B=q{Q+0r+IY}jKk~MBXr)htD#%Lv`jl_^?5nq$)EEBe} z&L|(Q{;c{_mbDV}sDoaId`Sj<4>prCU=u%3s!JLFDV-@0yQQlH^rH~R_DOy#vbr3_ zOK@`nMBp4<5b`!kePRTVAbOB$oj*<`JI&$%F)KSg+mJgcJ?lD>MW#-h45m4*IgMO7 z4S)I43N%Ra<$2u$II62EtKtp$3c^<<`dtMBV8Gkh*hU_FP2 z>&=dQdl4(R5~ZwSv)Pt`gK|YglIcc>rC1WknmR)UnqgdEZWXLZAU*#kSCO3}V2x;j zVR3%3%Yp67W{9bn#Nzr*yWzg^vkGy+%vAfPzWIExZ+t0y^&1i&qD6yt~y!S1+7?VpUS?71ThD@C16|#nVX7>bQ+LmZ`j)vypYmwr@rXg z-WcoRv~t=h8 z>~_OWguhZ@FvAVFsV<8&tgRq_c270uFJuxeVCl>; zYibyUrMA|7UA*L%-m9|PSWFxX?AVH%4f1hqP9q*x;&P&9TVQJ6lH1H?-?8h@8n1Z% zZOP|6jBL3*Ny`h0^UOBj6^U>iY^4l;G4i{JIK(S?+;9jhJ>mBE_m|xO0(tn4%SYlC z31{M)G!~Ka?Jv2wK~rM2$iq)=k)^<@;MD}*dc4e!mFm@Z5kT3ugj!!&r~z)Sczs^P zdPzEy33nH@T$!+d>?kc~4;>scJKxjZc5H_1L1IzOKYxT^s75Hzhfa@BTwX(k~rHV41x^-f>Dh&z|X_>!Q@ zvcQ6Cpreo))yF~L#P}C%;{DB>vN<ds|sW38Gam5p-&@oVgMbUtSnF#~&AKnGu@v&umU5C7>E!DzS%Hq8JU()>0 zGQ#JmGZ$37kB1b9q6bngC6Dc;C88< z^7i^L+%(?OSW8M|rnHtI|77i&!w{T54Ea&pCm8?qDU6iJ%(l~wEiPVI5^Ko4Ve$== zi*>DsmzVkBXei?C8jh$e2ji za5I2zjdUf%!4_c;hdnUTHFPfQ8)2JZ&juX1Z-!0oTOwVFK63X}L7cY9?wy#6|VhjZ+MML}rhQ9Go2&F$3*`IDx4gvc%g0iM>G zc>F-PSzOq(2F2YX$xe9Q0A?(*}wmGXUN|1m-w zv<^Ctv_h{B0k8Q~fHH0>2__j+w5SHseNc7rj3v zC)#pN6Yq$d^iKNn-6?5&@1+-F7 zWP_Y)!bH?h#^s(ES5am1Fl%9#b5VKpg9^lEE@qR$ho-c&=&w*dp#@0IqzJ@Mkf#K1 z6;OI6vjunWWP~Zx0=n{-0rACJg1M5(XML&awlTQF>>NuVnayeFSrW<|GMe$7YG&Ch zJ%DYCGo2=4W)l*X{mdp3q9$0TIn49}0qJ}~Hii)}6ZA`$2y0+(fy|&P7(+EML8{IP zRBQ5YJ!+PYD43?WoHIyvy8-n-fwsG)M!{B!r#0V#HdqUCbLp1$;zA=xfT5T*US)rc zGmjBiC$^hy)FPB&wq;|4DeP?uU;o-uV+48Q!l$oSVP1b7h)ih^Um@K98t1_u?2+kA z)G!}@_Hm};(K*So5u8G&?E4J2?lh$xq6*4@z(SonU6c*9voMnlgU?7$`+3OtCAtV-or()Jq}dbu0x<&{`3S1KAZG032PQd8xX&{T-#^vn@Z$A$p43!4=j zlupV>I|Vc+lwb!sNP0IG({WuRn<=m*V#OwcZjba%P(O5XS_4(I4=D-X=^Dn%d@J?? zag+;P3c@p{pfpNYFfuLRX+_CttwY+8NOL$e+o$(UAMKCNzm3jZj7-j4ybV^IQ zTn~MI`bnjb&LH^`ur>V_n3oXI(AjjgdV$VMjD+TVLQ(%p{?Kj)?WUifnu@)w+$qzt zbEk~WoiJH%m}$tun1Vc&GItu{xY3+_d@)YAU? z-TC;nZC4Bbuic6@pv^dwaRL6{3Lh{Pe|(hb+G=oKV+;11kgkM1>hXPPpDYVD&HY5! z)R$j|gO8hVGNq_r$ivNSp9k~yja&5)9I?ELjhIy8K0r%|#X=gbr70EbBcRxY&hJ$M zCz>y8K>HUJ2`KPs-ecgfhhJ6*i42qzb_3ifL9(k~K#P zlWk=h?vrDLh!aQ$wi|H=BHpb?fcS!u)~E42hg5jGk#=3%dbkF|1%JARvTau9ZNCL2 z{Mip-Bl0ChHq{yJZ`I%%&vLwqd{Hmwi)uI18)QvdH)txM6` zhnJFvto%%R$FKo*71~(kLCMYF=(%A3zW^bC5lcg@qD@7tTFpX(sOjLvi2&@{(8Ck{ z%J1%zfAIO-B-{Ug^}mk-Xj`0B20%;;XUs=BPX52Iu>VaZVtrFZPiAQ7*$lNhFi5ih zA2OAsuVRnoa*l|%bI}M}Tz~{)lwinT86y40Q@%~#$*tB6@J2OpJ4GtZEt-}M(5ior z!gJ9`jJCaLd6j4l$RLx&Gd9-1;NZdm-Vgkg!pl7`WnKf{M54@(&y zH#~lL!tli5NyCQ@r&oZIho>aRCC4WxBqt^(B@ay=mQ3#grKAAG6l9-*q*D+rg}fF^ z^9kx4)LeB#GlYhe452a=XSctU=3Z$CAbGeBZkpdl)cNj%a=19aMIoFkrM$10F7V*y z^~g)wKW$Ep)d@Y3^oLdRo62l`t=;DOUlgDy*dP2!Z(X&o{0DG)5sO*?S2yC-soBCW z-$;9VRfnXupogvOlcEgH`>@jHa2J9h8RL8~b-;nv0G?R^x`MO zXqvMinK2l)1A@oFbDg-Lr(Dyay&J4iS?#n70Q{9mtlhn4A83K>Ez^g30BAl@tplaL1~vZ;R8z@~mmYdhqoGan{s zFDje9(!K6>m7p7=72NkdAP8Umj1PM}Gy=0g z_Pj0eDfNJUM<%mLif=rBmuhM312^9B!DjoTpYFe7NY~4DWPY*0X1R8+cK<&1XW;O;vOjk} z0XOkM?*0tFX-!>O|M<>APC>CV!DPmbP8?2k;sYc(CcAN-wfT5k8~ahF*b*FRj?FJL z(*fUHhih&WyoxL?2fHQcz|kSa1KX|F%l+bG?;Y`NIHufI^fvP+VCnUmw)V?pWMqK$ z@~2?`Iywycv{gsn%KrX!^quVQUq@cq-@lHI$o|w6={(LZ=vv6D;$+BF9o2$+#T9}u zI9?@et?wYL8M;U~;@gLLT@FU)^4lMgjwdSmGp$|6AU>%cuqjU+Y!P-IY+9QpB{5MS z4wT9cSTCZ?abM8jZK;Kod=v_VEnn&IgQ!{8G?acyXU7Mitu**6!|6VX>|XZp0pN(!{1AF zQwy8M_nW~ZsqHEIr7Z1UVqag#T3+V5{Zt6{4gC0UDg_e^;A-}jvj zXYLt$Hq2gfS=#cK&URt$;nUAd8nz~4>pN%rF!z)P#wT09zi;)oXCs+=XX^6)@02+| z5zfUh_sRRW-2dL*+t>9zm&DwM*I(29fv}`wL(io#_gya!z2?lk6v@P=pFBW z`Qfe=3(ies?oID~&}*Rn^X+BlvYGq7-TmL#^XP)VuRE8++$)}(drM^T`U9KJnV9>R z&vHA?EO`F$kIoe{_kf>jzWDp;uTLC1=Vb1U?xyFSdEwPp!y1<|clotTivx4#-qF8t z1#@S`RVU>&y}5gI<0|H!Hek~|tI8(dcSGYE=6>teXj|l>U%zxVu4V4KHy+;j=v!Yt zb$8BMR?sr#aT0`G`bJc@QCz(6O-1F<1-Cx`HpQf|S zO>GREWbK}&mO(n=$q&8WCcbnscm4MI#n|>G4u|*pL)V;MoHBaZ74i)FKV5@&-@NDk zs${lPj`L7C-`~6^;nuse*zHYxW!!z_`6rU!|ENSrV(|@EJ=A@`z$uTe6w;V`;F)b7 z#{Vn-hkprD|9R$xU8|DKUsS$@a~Px!n4j-;SIAC$Q9GNtAL@J4m|y$O-gcawD#RVw z?|MHKQ#9$`jw%xi|GvW3%k-n_vw^B&=Dv2(v43gAzT~k(*{>{8tzho0+aJF1-rH}y{a)27<{mlwzFph1hVELgTEpD`S$F?$Ij>yv zkDaQu%>7O7x(DBSbnF*jsh(i&{;N_BByD~8$+N2U%$@V-1CQGu+VM-bfLEA%&*mf9 zSz8Xi79a2?bAO$F)$#5p&aRvou#LH&T%7a4!+XSc3j*F{?k}^hy!pfp-5yvL@F8=j z#`U}Z;H&GtemLMDbKm!$Z*sEsefrFXfJ4lkrhod0PnSM?rZ(Uxb4Tc(czWW*g>Tdc zoMi4^Yjqor-SvEVkoqih$E=v~RK&4BAyT(f6tM_PeeRCLLJWBkA$y%?99Uv z-%V3@k-|@onER<1wce)g!`x+ipZ?pN>-6q&btH2S{(QY!cj(G3PpV^>`|c+FoFQxH z-BqPdV(#>ftJXf!J@LcO)M?E9Z0~Pgx%WWNfBvl2Gxw*9zT9Nla$mhxGm*K)25G&g z6u1#zRr1p|<(+x;0Q^a291}(!^o$(MY&G`2Q91pI?2y33?LUGfzn8csQNklKn;aUx{$; zzghP8uct=%E9*%G;fv~t$4ipk0@Awz{{Mt#@|^5`6z+b|Jp6ILaN-=)9!a&=zNN2i zv{ips(z_x!PsYB=$eV}t=+-%6> za|gx^Wc`5FJti9`LpCjt&d8mV&IR%O{s#JS`M1sVVj;ZZv=|-*D={vX=ErjOYz>0- zY3>0VXfpX2BAAeeyl5T82Ky@5{)-HJvW{z=^Q8N$Y|)rz?Z{{zUe>{$H{#MP^+(|8 zpO><}l*`R^h(qgFzrf~YgA?y@;0lqv)Pdt?cHDNsQFkVlV{w5wn)5q(f&7U7%`KV- zOXhb!OZ;Uu@*!R+%5EAt$nA!k&c1X1BOnyfN~v1Y-(r>Si?zg~cWNlT%wJ?aD(Az~ zi-SMWOOFcZ1e?40+6B*FL^{+qxch23UGAn4gz-x`{W!RZhbdKi^ye_G%VQ!5-huX? zL~Hu1XN3~A>V$Z9hUCKC5M~Vz*l{zpmBuE{s!FLTJ!g_b;8Q!hqWu3ZdH4$oj!63Ao zs(WCMfS&4J!F^Tzx{2yRfiVGtJH)Eu)bZ+sfTvZ@1Uwt?oaXtE-vZ7Ap3^j{n?he$ zyrjJ1UvV>L=B+GWwYpE=&pT~>H2st49R@zgWVuHUqI z%l4gn_I`F?`~z>jw`0%V36rPHm^CNYbJyK3ZFp@<^^TpNbne#u#++YHH8#0BmfZBk zmz}izEY?1Kb8orz-!J~wt@{=I#*UjjW#$bzb8fxu)$JdCbg<#4pY4vjov!=t-#sLE zKJCAwPF(|2)t!Tb0wY4E2L}Xq?U<>_ zP!CqCG@XOA;i;Ow{W}It6iYPo`@44qF0WMg3R-?nJuA3thwhxv5X@X%#BUECW(+#5#^)r18lhl~vg4{~<6LVbf~R;atQN1w26p<~0`cLqKGM0j^i z{9~GBpA85O4-9la*?Cz>#Nw!Hf+lL*6&m+ub#Jw{qY$K0p|AmH#Q|aJ4gnFW&YH^t zFTboyK-Yj?>OO&eHIb_M>IDIB2J8#?F#My?j{`ml_)Jw7=neQ$Y|#9q`c)M^aKxy| zQ||ufKOYSW4jndf)btaz`!rp8OrP=A&^>$WF1y2X*FSw*QS@+oEPdxq13!C2D7StiUYv0t-hU=et`rY@|1^4WA zRsZcfG~(6$2Sg<%r;fjNVrJH~>D0FJ^34Sc9E)$c?an8jd$F>rcF5>CSKS<_2JOun z)sR^C^1kYLZ68f!=oNv30`;0s*SMbxiqu4EqC%27sNAcU4G--W7UF&&MV%iK8rLoG zN_Fo*l`dIxU0{?(tqBbY4c3VRHQ}Md)Tx2Jf;Hj6nG=R5c1#QoT9(&u*|N!+E3_G% zdIpCD>B9$xx;l(bzb0rzU|7)gL8`zAb)dU^&Q;?>!rV{IxysNXEU4q<$su9Gda1!E zmgQxItCk7lL$dm&EDIhR)>l1l!ffqjX=bI~r+`Vu4xW`^!o)UbG zCLnJ>*x0bBz{^W*h7Lm_I_mm-z8zyUp=gCc?uSZ0>OcuP!>0`j*8uOJsE{kBhHFNu`*i6MrP6l4z2_KqZ=J2@ zNIxgJq}3hpN%vW4AEpvEjbT&dF^4ndKV`oFiDBp##B&n=p9DJ`?pd%I|A$R-)tzuC z#~OI?@dPJU70>fwxd>OE*~!UE884LYA+3HkLm<5lx)Pf3(?B=iw^DI>T+DsN+UGLZ zDgmWaxgP1hkiqtb$zAntDcy@bZ!5?&BH4xHDDK{jpI4GwR;}p~bq%{=K{p0safb$9 z*YSDmPEL0L;*(squ2E_awXl8KgABJ6FeHO;#p!WL`$;a_JiF0E8%M@@xctq__7yTw zmbD|=2Vd9a`D0z*Y%IZJkJ3k@`B8uAW({5ZNXFj7(=G2FxlMXuT|T~5O+f~g<4rdqEc>H3-r}jS8JeR&)%pys@IYe`G#rKaT z3=8P_6WlHrol9&4HCB2G7{|>0!g24(jz>As3R@C8A3VF^LN`Kuz*+fNe$C-H(r%T$ z=tq$4<}c@*r!ufUITWzOYe-(jT+&>eLnT2$q^ScX#Z*gr5=E8erNi{nTMZmqnZF-= zOZk1GwVS@Oe2QGo58oQ07I?q`FZXx#&2pP7fR2+ z#^h}R>1)>1PWF5oWBcs)4Wvxo-~IT44d#tfep4GtWz7<3g~Yr zgmMgN7hj3Kj0lL{tj>?GJO^%u{xjYKr=5Cye%ovx9FONK1dNLpELUMH{bgzzwf=eO3=QGf)@01JZ>Q4Vx-jAWcDNZWfDhY45dyHPloqlSCU@~ zi!udCb!~%9d+vXe-M7Q;0QWtz`w`eQzkXi!-vFE10<{lPA~V}Qn?W$7F9gHnmns;ahh%^Y!O+^ughk{?w9W0sMC^(>h|16Z+&jj8|+X*Km8O(XY z33WyOQj?U^my6SypUL68jP1pj-U^^{gSJZ54nB-B1lLYD-L%K!ai;ddK~5=`33w$( z#3O4in>fwFpNN}iore=Y(FDQymp>h)*vD@2-R09rk+IGoeWlKP6e6lnR>O z%3h5y8hf6AO*}B!51!&udgag*pQmMmKh0}M?vt_ck@)ZevK8miARXW#x97^LQ=(f_}XDj9WoAZ1M@NMBr8DxtqU{+gko3RwBKROIgV4?aI#w z3?}*5zrW<+9db;CS-ExlGbn1Cs^O!S_u%R6azSfgbMAG(YX)LGiq3YWA|~z|;5`+) zBL^IMp?Qhbo`X02?enZTcDzuBmbZk-v)ExMbj^*$>wJUb&H4Gm5>ir3b5qRu$q9)$ z?EQ8KzO6)GmJ5ZZrjDg&6ZE*f3jsutIexPDaky9kuI4{@5gn+VQhl#3Om9P;j=F}P z0gH~sk^#O5p#1!WF2ca}$Y?G^`<$nzX*ToXZ-slJiVz%FADx#wMl>a{DDk) z&Je(&K-&ME-!tK~Sqj=*1;TLmTDT+OUVXVl%eP?DoPIZK1PM0SbbjD@Xg;TJ-5xA# z>yg851T62X_}NB(wK?tbdl@{=_G&F2CB@S$^i@{2bSv$$a=aUn9<@!SYKMLJLyyWddR&A{F$%~DI_eJ$L?4~6c&{E)-Zd#qO?xXu2< z59=VDj~|z`Ux0LYz8g?kbZ&vWH^V(d;odI0=_5F7@hK`cmL|$Jlw%<57oln2gRA!L zPtpL22Uh6q5cY-SO2j96)cMil&nh3sr=WQ~U7A0)dLI~o;sITAyR~gadq$hA+9K6= zLl23!_U$S0)@az&{%YY*y!9Nkviz<4v&3IHdJP#Z?xGy9PAnP zKZU>gycaccl*mqjDatztxG2Zx*7!^OxHZ>pp;@|u1{d3(I4!P6+(h6L*GrOj;ABda zZFD21ls1oB0$|$z;%*1r#GjRFE*9CaI58J%usE_Mf5Hf_hS4Xf0O#g$IZx#7Q%H;I zh`UeAZsIAV;1t}$^-QmW?f<6Ix)IVnMB<%7n*M@10x)jqDx|e81@KT+NTUaAN+T~I zUCv~Inn34tA+IamQu;??F9El0k;ODuDxS&0amKJEfC?`O3{fIu&oDb1?x-=DK zs}KNHE(a*^qxAqh9B3h|T2$-y-2VK;hI~mLdl{PZfVTT*`}2i1^HWTQ__qXkUU$lQ z$qQD^pOvDg>G4)kvs<`A!fmJmH~bW2IAcD&g36!CR(xEtH9l7{di)y-ZKW3{N^?`S+%CAAwwPzno9cqjgP5)i6igih$xGm2 z)UIi4szX?vUl{S4ZHRmlVJGFV9QgfFwOD5m@~)KnP}Kiv?@HjCD8B#p016f;cR`>5 zS_S0T&2Dx#+07StRPo76j~+cSj}&uX3zBo;md6!iAPm^16gR~4YkQzuKiOU@2AXWQ&EXJY}KW5Are82#7Yr|diSqb4$ZPdEg-+=3@)@^mi z#X9J=-hgw^?F3FH^{W+!k3y6Rj6fZJz&YAnOK?GtlvBr=6GvP(RUbIFzQGY(WYcog zBUmmt>3D*p%;hKxf>uu5EJz zoe)UHy5WMGm!m}BM7Of>tvGg=;AB$2^LLSk zZP1Tw?sQB!YAfgtx#2|M)&obomF*2&O_VKgqZD$wn8!_5b7DRAC?q&>-R4CI{w zSO`c3kl$x0M`=+9fCd~u`ZS<3@)bY}Ks`Wl%W~8Oz#+hPz$btY0CNF3fKb@6Ie-VW z1;hdd0)_%c0cHRe0+s+i18fI;12_S=0>D$(lm?&xdIQn{vj86ewgUD8Y=A;Ql@@3p zKns8w5CeD`kO7zim=9PA*a@%!3IXLIV>o~ZbOQ7QBmzbOxak0n3rz4LAfi3780+4KM^Si{KDO0p%yxkdZ>I@qO^cao(?63~QQ`O}o&GJ;6$e#G>4yz^KTp^Q9$E2*s(-McLBz3^m zVOKmk(S8)Jdt!Qks8wWiG?f+*i$4j4fJ=$@kO&<6z?CMHUOUm$iTOfCQ>IFhNwrh& zn(?I|yv~=Po(SkMByFT4O;I@k>aHrum2OUCXqS?VS6X++f|-&@8sDRPCMzx7Me_~8 zIT9+35`c#)9BGJ*cY64f6QjRn7F8*uu;1!Mbw}-vHw&xZ2I!6t&ZVV-KlzX+MNLt4 z?lwHxWd>>y6`3^1$s4!juxkj_mVCe|276CT?q{j?_~?Nn-pw0thx*i$J=%A7wb)XB z$RFdld+&tLyW-0#0VHfg-XBYu)Od%Cq$Ip?zFZG{5j|l@Y+9`P;XeG$GSw~xpRehJ zZy=^5QA5kA-{hm(s%5(43kZZm^>VNW=?i!OmVDEoJ!YRiq|WF8nXZS&)BQT2MO0qY ze%0pq`WBdyuRryoHU&hJSCy+mG$P#GO8!nb#o}xx2HzosJw}&{CEt8VMelOzMBWPc zM0!%HE14exD2^TUhktOGmT)3CQiyy^0|Or4Y6|%Kt4y8^)zYs$ z=|-MtD%eeeNPO6lG$fI8r&Bj#-(HlNP?4ycUE7X!c3`S5Y&ZgcMi`Yw~9Pa99kzpvjK^!NK_p+OFMc;R3g45 z*1mh!_R%h{@-7*tZJ$vUQrovj7CwIB?0nP$uw-6txd+@5y1<2$cT;` zqPnUK&iQ=-s%JZV&o(yd@%9WyJ7%!yczb$=`lqmMskqFfA#sC}Q_$bQAc=}3n5;NF zp%90s)RXYHx^V=7X9`H0;CtS9KBg`O-l>C<2cy@=;iK93&|@5Sc_SzyMe_BJjk&Vi zK14#kxf(YZ{GC+ZNJIw@2s8{QEGi|5$0bp{De`0rMMV%@5s7ukI%t^Mr^-Rn^td=8 zNdkHP`FaX+)q%v0vb7O&lr~Xuj^{3*d6w$!9p4ZjW{87xMGZJ*OGzOgE+elGb?WRO zh1(y1z6)-|TI3W<6~fO^tNLX{($D!D>_I+g1E%WH0(p7m-}O6l200fU_zR!71bnT~ zAqD=vo77DP>!9>F_>Q6YGKzBspa!HTV=qm%)h$t?B^nk!uw@FrUc9LE70p`{p|Ey%cu>kMa)NxD$ACz=MtHH{>gU-G(P+jK;@|)Tsd1mpEG{K9H*6 zHWHm<7(=nQoA>Myjb~>tohMRR0a2NeNdt!u9-NdBLk>-`V3=R-$yCRP_Z$ zeq;pu%pMDF&KlD)I^g*|^mZ3lb@}+e{~kaKSU**d5~zY793c_WcDRkY2Pg4d#K}+N z4Alhwvwo@`r?`?-{uW1?ly&{E-7fKSB@mMM%DNjPyPhzwbH}@p{4aVREkJH}$ayI_ zziJO42QK6=hn%n8c=H3q|9=0o!2c}p|Iz}E6TkrV9t+PeSjaPySS(w}eR&Q-m(mWp z3aTH^10L4{IH#d3IMT(tP07hA&NdL1LkJ=Zd3HV&VFiSEpNIv4`g8Dc%mAId;7Lxr z7kot&9OX7~xcCr!jt~4?ANVCc@N0eGcly8|@_|3;178SyP)0dw103%$hXT~jY@9J; z`gEo3n{ehC@ppReuQ->h_jj7|FHbFj({|A>sa~GS!R4|mP1i3^4FPXgdaed(*wmG# z8kMJNqtRUHX)#?pR<2Y}oerWpMRs@0)P7VDX~6y&O9mmRnBJ)m=7%a<2>9(tTat*m zBP}YjP3)+JXOFbWcz8#xspmKL__2qOn`-{F(pdJhV;`wHEPw_(Ny`FWBS$_w{L8l(IkC|n(aThGDN_7M&1Ri{=h zE2e^%4J(>S-@vv@jPtU9GXFiWtVIJDB`Gxr8 z=Nd`XsG56!wa;93>EhA1EBx}z=xJ15@8YT13pSFNJ@ewZq<| zk-x3(mYG{eHP7$(R7uyPC+0t~z1PIu)u^=1_7ye9_pB1Wt+utsl(2c#sMew5Lp4-G zx`=K|EoF-6NU8X;-7HAro46+c?OU-NkBu$9&#Yss8vmZ#MRy z^=->G`YjuK&VRCArB_cpZCO>#zB(d^>AS1M{!;pb{hxDct? zJI7jL|M=LB#J|ES&Uw`T*)@U1Q$b#3;2+UexmxZUp9G$(Qe3HcYRSksMdIuu?b`g& z-WI!m%ZUL^zAkK7+%an75ay4o=ZCBve6_cITs86Ki($jB9sjXp^0}iWkDO}KWqkcF ziZ@VyHP%FBFZr!kT582{RZGtG-ScIi3r)&jr8<4u#Qx!kVHJz2n7WLQ{Iv9Qk9NN$ZoCejof6aq5}H=L&ZWib!vDYSOqWCFhFXpBY=Ulqx^Em;e6! z2)jVY7jC3F)rJ5ojt<^6v&Fdb=8tkLbrxP|^6*B#+`iMPF5?q_m8kt86Mm}sd)9}w zx{RM|52K>`?n$lr#^7EFfxRzmiLUFHyXvp6&qrU1v_zQpyjp{Le{oR$v8fLwl{0_P z$iF0USJl?LAF{*_4g6+S@$zkF_FrjhX*16+xAS!CvPD(G z{nK7mnby*8VRL~>3NEp<^y}Z8rIIR_g!c1a+x=;3cY|U-#JcsQc8964n6A`mIFwHU z=_fl-r|T2k-1A|U&!%SEpWZ+8kBzl;qeG2=GTbo@H{dr>zinJZ?pF6VfT&*|0$o}KZPnRC{`y{Z_=8n{bD%rg+ zv>sG-Me%#%n^@;iUwv0W^OM~acj4U6f`9dX{*j3fTgGiExiTxe&QI0iyI7i@@y|^w z9NGG>k>?wLg*g9l>OycyahKw!#&t9g>|$whtg88qqi=qG?5Azn5Xq()9gsV?uqxqa z@=vKq_xYS!6jr=?QR|L`MVKGV_{h#0mWx}mTc3)a{+;&dpFz8Gp!1oC=cxTvOIB~T z{}fTwaNn!dCcM|u&mNE*kUOGqYDCH5W5#hwk>**-hrgXWa4BqQ>%ihg51GF|x^K;~ zpWa;_VIZEaoVQ;QlD7eTz;)2!1LnIfL57gwSFv@lE7mb7&$X{Y@wzNtf* zelD*$V!zt^!nq4IC-nQ}F~7^TTT`c|{PgXt?ANxPSy%gG_W5VZAHJ&J-7AVMdM2vQ za=c#mC_6@vpQUw!TN77$0Z);fV=B>+#LuI zjejj`?EgfNrPKmPe3tDk@Tv>W!(0plXE!pR2p1s$bLgYlqDb z(lqyvsovPKGsv8L`UR?WH>LyCId**D@`!66jh$XlG3qIb{I@oVX)Q>?+BU;wF{Abm=pNCb~P^+WDCUlH?ZB}aU6R*w0 zt@7i6pEoN?-uObHZomxcK=ZDFy-)Odi8^q`9(4Gz;A`3|x=pqGW7Z{CTia9I8yB(R zk+p58zWI{>GsbIYiW~i!w5g%rkZoTC9c~_cZU341@h^QlY0cu__C*+nFzY`4yk?zx z*+vmdt$J0deF3GdL=NpcedVF3bK%dumi3;!*~$uEf9RjvzA!xg+l{Yeeg4;_h*47c9~$ajnz*WaPJr-+ z^-=%)_f9c~MyzIG{ zML{1A57e-6Oz00vTJLFL1HPF_g^Z%Hl4WXv) zesR+${m#Ff{8Nx6^9g2c?!_N34}81smk$^2T&44m$z5KuB)_@X%g7w!7Ya+aw*3B7 zHA~yo)g}!){C0zf{g#*)FrmNHKHILEWp@a{ZFtCUNhmYwp*2HlSUQAEdjI>i?H5p7 zPH6pimiJp#(fmtJo9N?5-hLe4Wq-;fA3xcD|FrW54{ZOn<@bTqipJ&j->G?z42+Ms zMo_PW1hoG7Fv!#CfwqIiU`j={3GTe|x#^eRoKq*^MQV{bI3~zHw;p3j2-Lh6GU?Nw z*FRoStml^>QgU#pwM~#kH;`%Hftk0%a zG`Gz0yZrH-tR|&I6webKEVbz!Jfeoduz*$K}z3h<|-VO!&uy=OWbmeTro zgg+H_ditgfiyli-4lH_Y*omyZ|pFCa55(CgA%`T z2P!3xo}q}?k5N(WyGAZ=8$U6oO(gd0lo?))D^?|G#Gp6$8iv*qxAz zQ1c&F>6W5HKX;u=koE>vLU&7M{}F;R>g>%9Hk7pha3b>G`rU=j-t0hdWSp2EWGnmw zI(xH40qThdJP>{2KI!bu4#a2vEB^9d)Y+RI2+sOXkBbLT=NoMCPv{SwX#nYCq_5pj z--DLESNcOQm(FDF`KNR)0BrFZrPci)Fz0aKJv`B!~ege|1ETPw}lO~@r3?X zw)n5;e;c~H+rj?-LH|3{UA4o1UH`k$o%HShvi^6g`@g9_>W%^2&Ae2apLZYQrN-}f z`$OkEfF0nHi^OAYC5L-H=#otG;Pp1y2A^wPNKJVWFW-R*!pR|wqg=&tsq(&TdGx%m4EU37OE`r=FQ;OWZ-qJ!Ul$%_OS6F$`DOso>sGoHfJWouOTsdgx$pkZT|QSFa+YR;Tj@>m zz534oivG^Fx)U4R(BED5bcO#V{qMjAH}!Xy-mdV!roYn$mNLj~b?I1ISOz{1#Q1mV z0C{Nu>Coc$X%ZE6-P17v4p8 zr=g2aX(4#uiS8~Nkp5!!#=k5wdn@OTD+`a(Xxw>ui=%95x)a@UOXKgBXYu6kmgln7 zO`&HQ&vaRMlt$yp&pnNDrRiRPd<~&TSk}4mhVf9ET&_HKdA!A4baxth<4JJfSDNlO zt!F@ARvXwsYj)OgQ+s>rLFh{RdD7o*+8b~1@TEJE{rdXdvn=w;Y6GIT1@OS>51D-F zUVuD}r_P>f(AnIyQ{O>0JUfAGP^_RtlrP17q|J~-_tqpEfe`&gvCGS@J??pc3 zFazvmk;jwfR`q+*-){O={O?sh$paDcz*W6`8oXnR#_sYKNcjMvWbz7k? zzW+2HauXZm1I%|**MC+2yV2Rb?Emz?K89|q-@EMQZp;5-+@;4IhSvY0&h9ebf!@UL z<^nYCeEzHP+t9xNw0AVeJjk{wgZ_D-F+a#U+>LBL^e5{H3*ffb6L%xazfsmhe=E|r zTr>Y0a{g0wLf^acXXJgXC52)54?k-KHNbaX)zD5+CK9nw6v-%p4t@x2L>Gi4Kv?Ju zt&Wg55dW&Ep#?9KCTS}*UJY$j zu^QR~9HGt65xVkS^!SPzp(`e@HbhwDaz{5Pwek{9X0?`=y_U%)ZvB50u|3qs-oPv7xL55OTll>#FB2WcH>9!I6GucJcow z!hb+!Z@Ltqp7?tu|9z7ACOz&({(nnm)O%fz+m-(w$xOzh6_5)cxHznGb^eZnC@gWgGBh?3e1B{%!ev$nLI( z9W;4vCch#2Z^~Z=*{|zygV1h?e@p(`k)6osCh`r@dm%q~+?LqX=OIqUn%SMkJ&wFPlAYAy&c{7Y z@@@y*%aSnq1J(b1$ZiAP0&vOf8It^e-T(NI{knaTA76?NL?^XBA+-9UE2Y1B+N9L9 zCm+<8=cUe@`Zs89r32BozzZ)`9?yDRXsue+At z7w^*Wx2uCMUfyh68qOD=JHg+M4!-!8CabqRUwrNqUj`lQpvm>c-;;oQqU2=UTn^_KS_$m}kIHyKOA zxtDzq;-$&zkw@m)_y<8|cNsin^fs5}fyV4!=0S@4ke~Q23!qfr^&sfsA-@&rmhnl8s;U}NVOMaI=F8#cOsvUuM z*tNv&uye_I*quD5MIZ*?dQQuX@4x<=Khoy`#LtkvbX)!DpOV`{CU1U`;O^^qEu&1{ zWVNBJ1rTzt?R6J2d6SdiNIx*&jhz30OgG7TyYk&5nMga{B#Sp(S>(GznaKFG0&)SQ zPniLxJ{Q`{R5Z*<;puCmCBcgwdU9^=aM43Sr6*$7Y1@+9q6 z*G>Ak=ed{lQg5z%zLT#n*@#XAZmQ3dhm+4ubY&^)MaBZ)G`EnA(9i%Y;HG--rF=f* zAa=?3RyT0Op6XnT@V?0BLq<=#5SioMZF4{6yM>GekmaT^{s75GY!D#HwoRxXS_$Ai_Q*w4B#J= z54=5PBX!0TySV=d4&ai@GbCj^arb2YaMtVMZ$tW~@#&J&NqdtV-ee;Vn37gvgmdC2qHkA2DGiN9T0e9^nfXhYlrD76oJ%Hb>RtG+wIqYkgO^2W=TJf3)O zW$y>hQx0G0`yq?BI(*6Fh9`a3?5*tmz`4oc?kmgGcmD3gM`+hL!a_=;(ic%SH7xeKF?8YWPCA>joYl$4 z#rF?qJ<#VyIZ7yz#wlTxoVk9U*{tK>od|&y$a5{m9n<(g6jYwEsk!)DONiAQxb}%{r{0cYy_Q z7nl)u!L8cF?pCMuR{T8eb*r=+Z?AIPs{GyN|9`C?dW8TA0Hpm$yL%nWzP48qf0XY2?!YTWLJq=}EjaT9W6Y zN1U`Fv7r@kQ(FQ@>L&Tub@di^@pFaVXxwpbba`%gQjgg!&sW_<<{RX3m2rih`JQPP z9SM==E(769_{RV|^}a42^6pvvK4iFoKkBmruD8#?r?@I=+{M^djknbsvi;jfI)3~QS5lWHFKgOO2DM(2_Ey%tE^l#fW$q=; zTb=H>ds&w^UhZ|d#YrEw0KD4F8=pJHxz$O=ffW#Qr@Zc@9O@(eBNw3YRvu5OhT)Zk z7078qiH*Gf5bs(9SO64WR7lQWRKV#1-du?Dma5b_TUBa{wJNpAQWfVcRVjNwRjRP6 z14x|UNFJdfw4{t$mhf=#bG*DTjGR-10%(BioFcv=68Gpw^ajKO@&Tj`O0`E>ss#@k zkPavSl;+>c+}_|51IPu~Zo$)AeKt?I!6O7f^v(m=0p7}$8AteohX#-i$iGc~Hqcw0 z;H%C8H=aaZ7d@%V;)HmFW+!Mob#}_=i$CdNcl|@%Uip`mG0KMkh^|COqF0D}S)}in zKj8%+yxn<_;e7q)k$0W$I)RS}%4xjtR?E8=DUCn!@&H8dc#kr)6MtPEq_4+4Xs_cv zX^1C}(jiTYxy>=b|NPjVB*hSx>xMIZqkl z-SeDrRUa2G_k0)bLEsO${xSQ2cb=Qx_q=_b{7HMpd)Sl)&b^&o?X89$v^V6rE*3<=yGM? z0!#*2t63@Avko9}f+Kl^My1_^kd!Ui1lXb87mL4mO5}M79RMWN;Px5y0KEZQpM}Mq7su* zvy!t$Yeu+{w4y<#NzX`2NXpDi%V?94FeEuEDIsfkMv}2{^TwLg0mBe^+*M_(o;}*7 zB__3sN=;3BGCgrXR#HY|P1fji(2Pt@WwnhJxwT7nSAD7wiAk9W8OiBc5KZaXLqnKo zhN}!TLy}U`lQQJi?j%I+#H943RLGn#nsE3#oz=!^92M1}SF&vkWFo;PU z)L4@;Aa(HY0fSW|`mjkwqOwE98&vumt!l2($XOY~Gqa*n2c?yECtDKTwg+C)Z1 zb?w-@w=?p;^#4zLkeMkFUUm_^k?x~U&=1vT=_l#m(J#}l(tobsrr)RkUVlvgoBoo% zL|@TR!_dI+sDUv^21=?e2~s<$P%0;PlH=uk*(x89&&YqsSL7Ju5aUwg$Hpzjlg4@q zZG!8iIMmUZ$zWD7p;}tommA8B@7@Uk zPg|Jg+D+P;+^f1UK8;_(=ksfMD_>r$D>fEeiF&cEI7pl(UevEK43t*O9~l+pHD#=6 zqRDFditsU0R4js)+IHGL+Dz^1+E27cwP&<%u`;)gyUNw$X+D-;$M5A2@s9|y&_{Sq zSR#BZB#D$hTmQ5EtUkaHXBcI8*|5-%D3wUb3Yf)El!&0MwzoD_Ytc^EF4A_@1&cq6 zS~=Y~##liKQMM}ID`%Cz6hBiBqdtyu*CT>}UM6!PYpm1$E?6 zR2G6L`WStMZpFO8L}|xqXKA-ISdzR;c1nfOlx zqiE6l8OBIgrL%H?@gZX!V{>DqG1kZ`QA&c6ri@WuRH~UCHMKTLrmm)^O?yqhm@bn# z^BsM{pRPn#r}J4Wcb@kXY6_1E?SvQ(}O=lKwG0ukWCLTt85sp}%Yhk?KeydUy}1 zuaqWbOO=dy#-ELClzz%UWs>rOGGBR1`9#@H`a^-rl6phCLc318M|(v3tM;T&VhRPJ?dBNwMj)6Lessq4Z&!w=_Q<`?oG@jvjt^H=ylp^8us z8nJ>==mM?cgk&L8$QGsvD}-&rFTx+fRiU=1frgx@h@Hd(=%+38z4XuO=jq?juhVbW z@74c^@jB12$gtV4!|;v4W+*XKlkqP zC8rs)jjvso=|$yrWwoL+eSsE-Kz53BOR69J3_Xo*&6t>8%1*f6_}1p9P=i#g4w}z)c&RoV8^o4+4tEexHxVkw}Csz)zY=p4bwfRdsSD9 zU%~I-O~MnxFrkLnM3lq{;ym#?@w~|B+vxk~ztc}N%r{h*8cSyBgmhV|BFD-p@=|%L z9B8a*Yyp4TT^XwUtXxn+OrMyxn|>tng!risgND;GJ&vADAHY~FqQ@~|S^+(ABl_Va z_7(O+_B>mWi{b`wZ*eQRU0jszg02!jk)H)m+EW-Lj2E^FhlTp+Pg&w*aiLfrz36Lw z7ehb8XhWFPTIwjh2v2idx+WRr$K@pXxEyQBfKT_M7D9x#nU9z+m|vMZZN9c1dVCjl z9{T~il3mAcW6!eJ*v4FQt{du}!o9@3%YDM_;J)H)+-dZmrF;?ptT;zpEbbMLh-bxG z`UrirzCYT>s{a+1Xdtze{N+LN9C@vLN`A=L-Pi{s@IB*t<0j)b7|&OX<&;{=8_II! zG<;N3(@@hGczv~Imx@vr5p5X_HABYd>pM=-yV|dFj%k(y8mpvxR z>_@FaJx%D=w2AIWkD*_n=g`aP&*_77d8Rhgm|>X7%v{vFi}{ZEof)Y8LtCN^VynVV z65F1QWuIn;v7^}o++psF+JD1QZ!g_oUAAtfu7xm5Tp~UUkF;I?t)4NoF?2H|8%7w$ z8-6zw8#+tzQmV8~ItVXXS8gWvl+$I4ybS)X5CG<_eR_4rhPj>g$^5!bMRWATAJBh`sgC=*t-*Fz0PChzb?&M~yv1#x!H1n4wG-^EPvW?SonTEEl1Zblo6zRm{mv!C@GBQUT_vJ^D&mFFa!CYUp7Y zXc#3;mu5-%(i&;2^aaM;X=$ml5&rX-@|#km1ej`>8k-VKL(qzoO)D|t_L-=3KjQMK zSG7yfpZ97HVCFuly`rta4q%_b{4$?i%s#@2Tr&3}w;UF{1{*fgJCO61`kDF#`gbAYH~P_rX@mKBjonc+>NyS*CfI6W5w3i=Vod zN}|)?ujZlWEu%NlU(pqrx=d4e)yJ79nFEXws~L`6#d6$YuC{Kn?xJoSf0ZALc`FM( z>YBc?VWVN0WR>bDc}k&D)l}QWnM|f=b^gV;%k`s{!X``TwajK_jP_;iT&!p|!ABp& ztaDMD1rIa}bIv;S>3!@`_ILITjQX|QH{217y7OFsE<{(tHx!x*tp&ZXK=@8(q#oar=lJe?AAS%&jL+t0@Y^vfUgIkZB3f{$kR^;2o)>b3`NI3c zYGH@aMeHf2i6h0C;%nj;;&b}<;Y9-t4Y4{sX1HW1GSrnc(qobqb9jtI<@>4Ym1kkG zchQHcV>ZiR-@@AHTQ-1ejrk*so6l|IPI13;)pd1r4+#=hK;6V|#8aYOtfH@_Z>(>o zm(XuU>&NSt>USEZNLQo?xtlydepa3aFZBjyk5h7?9Aa#MbzB=G6u08c0>R^$wazkU z`PxDYjIIyGPsKPxBgiyWdQVy>ZIXVLD$DPow>40@!;Vw2`uRvXqVzIR1%A|8lnoBV{roY^?y}HENE1Gk<|*$eA1JGoEsDP>(KOaH&Gb6jeg*L{Ha~Uk zUV~miucJ59U(-L)4KV^{F?q~;%vxqE^Rm{et&Mf!Wj0;dE?gC#$7pwagh6wGwQm)zYgM0@fY|<1)b1dct{Kt!$byasdi#_ zw9GcKroN$`(<@j5=IA%-59m+96V`#(Uu8IGXp42=Oes>HC{xDXn2CNj)-ZL3=DXmn zPMPfL8o^(kd#cf)bW_X=k#sEGhaN~bV>`36G1F+d3A$6l1)&M*G{R4g7iWuapx({m zH8DhA7dx+JhW=Q)EjMg6d}-(=jmFxfmONX2Uv6eJ7!Mea8_ydXz#C8@{^~xVDqR=# z^hPh3qWFHwX7+Wc+@G3tm7nQ3@DCTf~ zb={Z2SeTdK&zE6$Hc*?6zB32=r1jd}+HbIi_+5Kdt7F??u1aRp*|*_aK1aVf!X9Ho z(PucW6W0Ty=XvfG?oDnfw}m^-{lS%R!I)2`>0ZYSx(Tbq1G*n{XLN;Fm1+58K0z2K zPm*7fyBI$=9#zgOb)nBd(^S)IrZ-LRna-Ig+MjG0sYH4uc4p^!UPu=zNwjoSZfLZa z3NY{bt7EweU59>_{scX&D$@fq?Jg!9E7qRc&$JV`57FKwTr*t{NHJgcqpkt}7(bLB z#joMF@c}|LAx3ywSSWlT*abgWsF(PTxJvv>tfY^}4tSb=4%%I3cpdB2i`es3kXy=B zjKA8a=V3>-jyaCe=BKTN@%E^;0oRP9p}&VDwD76^7elNm z&NSFG60_QF6BX}hHwFD-G-io)^h?ZJ%=?T1BXbBlgMF2KogI!n!VavlE9r*nrt4krtR(VpNsL#|-)W59H z)33k@!e0GheXQYW!vX0M{AGR2Dvx1>-O2d8=_At)(|OEi{^}oO)uTC@%JZkTLa!j& z&S=n*owPl){j_Veh1%t;9xMB?x)r(&=u1E9{?wJ@>+&P`SNRF<6vVd_9oMfxyE_MW5!;}Q%WXwrmtbe`GK-h*{po2e69S1bxRFX z15=jiIn!p-L9!~(_oog(hbQRX^y_p!{VDCwRAU}yMC@KVVP7?fd6pr4$co+?tPRsP z)egnJd6G6y`=0h=^xQAB-)bo~n61HvW0jZyU%e7@)c5SKY)7sa_Y^k>Ej5OljB&mM z^ZGh&ANM`?6Xx}yu+Ku>`?}-UX*{gXquu!4d?NOjT?cFG1ZD)2&75OeVc)wI`=8ou82cu>LiagZh~nGvJ^46(ALfh&!XoTlFAF6C z@pONPe)`J#r}fY2r@+JR#jI_Y{=_H?lUrklk&2m=tP8(UepiZ>`dIx$n+9O~Jco7R zTc)L0XKjQJIBYtK`O%+>hIq|rfo?}fL9#&@17r>UI#%JI;Y4c>GtVU^NBa@xvM;qiV>DgV8o2`Q5a!Nux*EFWx@NoqyZbr(+x(~e zLH;mbQK*IWXmeqt@Vc;3cntnORh%WR!5Y6MtT7S3zl-4u!x2LjtXXAayMF1s(b{6PX(p%ZuLR;aia7mE$$!LWISkZi>U#tJj@P?F+c_Iuek-^F+ zWxO(3iNib*K;@up2YLeiA-x5=o8$Cv^m)23eC|82>o)8FzhVw*i`j*`hp<-Y%4hJe z@DB@SVTdqYSStJ_go$m$3*u?RIm2tx2zj!)_g^h^|)H2XG&7ThSY5^Yd`Fw1(fx@8ZA2=}bo}AT+AtC8()rRm(pu@HG+zDzt<&7N04tp!rKU1Ld0+Wfp-lBmJn4Uy z0QDTSm?^JK(|*i$&}A8B8{We%YQN!oXnYOlPPL>)*vIRo_EM_+ifof5<4ZVe3{dB< z>Dt-Y*{y=qd$hl@f3gp8)v=rFfYn42m%`1({^&ET$oFtn)fH$sPHNlmPw*+&7p&kn z@;00{J%Lld!NO!=xA>>{z5cY`-%u56wP@^PPE1+Dv!GYGf=eFio|hHU{TYN!o?lPqmL>uipc!?jabL^We=t zXScI|v2}2TH5i_J0#;4sbmW}Kplhp3&}Cx8&ei2%)%2C_6xMLXIz2qdd;D_#3;3ZU zSb<;S{e}8MOMw%*;VkeWoF%mqdCbJq#8<@6#I4u|JuMHBN6HiATzS4s;HEUw~vJ;5sW_P3SROP~OqBa21&B7dW0B1EVuxfr5 zYq&486+-iOUR(N}Ps~BNuZQu=N z!xM&|O=nD3Nq@Bms1GcZqesH-x!CW$&wb4G#Vol@Sc82?fpARtUAQJx5HrMa;$8!} zNhar_yXX%50DcJn0@fRg`DN&Pd-%_UuY^OG(fq_JVlDAeoSyw*C@)o3_nRiE1N?WA zbV=4=>~uEv#f+M5oQhrZCgXR;6BtYWI8~^vXq4s(uXIvkm8X@F7+X2$Yx6MUuE4pn zRrx|Wh#q%BNyQ1n4ATeLRd2>V;|J48`0_w11#;EpS+OCrmwY zrjcfP!8F^n!1OL=TS^m1^+#RRu!YDZ#rzOuE2xP4n4YJ?K_x#mbI`i zu(df2XTaG&49?$@b)$3>bua4{=swV`!cKIr?l4YvFX>8jFY|9rs!BhKy>vc2%P#I~?q{4DUB!B! zHctE^b^TG}vlx5%=;ueUlB&ix!r5OGRxwZWv-w5*Dzy7|{84!PW;l_E5uOr~gqMZ4 zgq5)NH<)*-iH)$Ui^8eI)8g}nTGH2K!i@=3_YJEVUK`C0 zWq3`0K8UZv*W~N*8vYT!1@^&ZX(=dV38bRY?oF{DlC@@>o$X``Am>T;A{)ykVl|t^ zje@im%$JL>Cs>N}>z(Q<^cdF^H+hk|XzUCo<5pxgc5nGuC)sc=&;os8Hg274d`--t zIXM0AB*u#U#dNfYMa;w6X(>){ZQ@Dz?~Ax$3ekt^HTrNpt)865;1(qwZ8b`7fhW$z zPH%}mANM>~eS!Xv-iG^PyPh%x8A1#-4I13Ci15OZh8UbN4#62?mcfG6##}?5VJXgB zR~f8^0^ADOaAs%6t#XhQBGtsX9gVv;vlNX}vRL@icxecBaN{tCPnKp#v!$hy2B(v; zxOYy(T$dt`lE=wbV*&1)?Kra~H+>;WDEwCf0>Qhe35o3)+_6=*V%*9=y0|L z%c1W?ve7up&tk{1ld*%J%`U{PA88>wTgXye5Ep`*g{E8!j>3vM2Wz@SoRrRnZ{3Pr z%tg|7^8%@32!d&HlM_p)(39zf=(&5;`y4Y9!|Y^Iv{{fNo)tMWPF&VwZMO$A^Eh1y zABs~A3-)+Lxa-Qnyt`H0gOjBCXs;G%FBvTst&hRIN<3~>(lK{h^fSxA~HFXc*eaobPH!Lkf%uT|GiHmsluWwR2a z^i~$)B>y7L#cP`Ch?N<{mSRZXjTC5Nwygv5Qf43C5lU>TLWrMhAt~b{ocd|op=26IX!klvk zXB!kBjXAYHACGlGI>yN;bq76z&s9gvR?GoK@Q_1r8a)aga57dX!D0-?O^%q0kwU}H z2lV0S>nZ5# z)(>H%pM>`*)X}`mo1s+IZs}KCqLHW*^i~rU_Er8m2t`poGs2Jw@n3(`Mm|& zFdz4lIm`^~R}QExb`mXC#028@Vk<_HO?wPCJ7=(i4nmb|}hw6Ik;&myyboj?{s)wA5RV{hCWG7z$&v+7ZA%%HRBgkT;>K#+m8`2rLBV8mO z7SG_OG#q1$(@%y!TMIvC$DIRZ52SWNoDe!1BRLVhc^pRbY>eln7|~lXrVnFOU!-Mi zq&8ODUrWX{@h%JDS=Pg=9EKH$Cn0|180PdC^wHU>M-PNIkH#7$5$8Nhu^!rrldxmx zuYs6V($P!zU>-lrw-Dmt5%=I(oWt@lxj)W*Q;g~8Ulz2^PTUC|!agn({VZMeMP$52 znqo|`rrxIhxO+>%Gb9U5$A~@g+@#~~A(4(@hTv4#0t<$)p{xe&6UoJJ3*mnPb-}P? zeO);E90&PqhLf;DA?y$YFCGd%-c)JZBe5te^H-DYv7`eCVx6|RZEjSBs^rJ=2 zeza9Cz%KEm9E6iNjWOETAERR&Rs^#l`7zbMi%O)rW==;>v%sI4aXvH-H%@y@2Z-Du z<)~QrnUgpZAHs~n8Yx%3fhE1{nA*dNv`yLmY)y{Lo>@3aJAf5g3)Qy0VcmGxcL;jL zDD(*ndPNRq&bhF79(F%VVE47U^*SqTzY{a*A*@GjXoHjL*>({;M<8bTV0h&EnB~Ly zrkH0%b?im*ozOx#@F978DArUW)=_h@W(vnTh{LU`8S`(9*c(1%z1RufCuowK^pQVg?OX=g?58KI|W^wg4@0 zXazEkJE`+&e~jfk>6p|XUc69FG;YPs!eQ9=j4?&YLZ1jmZ^*&eI%KjDn`+9b`>R0s yYzumGIA%?niNtwkH0GwmSQ`~#j|e(5p0z~~2>%`mzfSxW83jQ7@ArUO;Qs*M;bsf~ diff --git a/build/yarn.lock b/build/yarn.lock index 214f60fb46..928911be13 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -8,6 +8,10 @@ dependencies: "@types/node" "*" +"@types/caseless@*": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" + "@types/documentdb@1.10.2": version "1.10.2" resolved "https://registry.yarnpkg.com/@types/documentdb/-/documentdb-1.10.2.tgz#6795025cdc51577af5ed531b6f03bd44404f5350" @@ -22,6 +26,12 @@ version "0.0.33" resolved "https://registry.yarnpkg.com/@types/es6-promise/-/es6-promise-0.0.33.tgz#280a707e62b1b6bef1a86cc0861ec63cd06c7ff3" +"@types/form-data@*": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" + dependencies: + "@types/node" "*" + "@types/mime@0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b" @@ -34,6 +44,19 @@ version "8.0.33" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" +"@types/request@^2.47.0": + version "2.47.0" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.47.0.tgz#76a666cee4cb85dcffea6cd4645227926d9e114e" + dependencies: + "@types/caseless" "*" + "@types/form-data" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + +"@types/tough-cookie@*": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9" + "@types/xml2js@0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de" @@ -331,6 +354,10 @@ color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" +colors@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" + combined-stream@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" @@ -707,6 +734,15 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +github-releases@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.4.1.tgz#4a13bdf85c4161344271db3d81db08e7379102ff" + dependencies: + minimatch "3.0.4" + optimist "0.6.1" + prettyjson "1.2.1" + request "2.81.0" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -1362,7 +1398,7 @@ mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -1376,6 +1412,10 @@ minimist@^1.1.0, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -1453,6 +1493,13 @@ once@^1.3.0, once@^1.4.0: dependencies: wrappy "1" +optimist@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + ordered-read-streams@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" @@ -1531,6 +1578,13 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettyjson@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" + dependencies: + colors "^1.1.2" + minimist "^1.2.0" + priorityqueuejs@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz#2ee4f23c2560913e08c07ce5ccdd6de3df2c5af8" @@ -1649,6 +1703,33 @@ replace-ext@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" +request@2.81.0, request@~2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + request@^2.83.0: version "2.85.0" resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" @@ -1676,6 +1757,31 @@ request@^2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +request@^2.85.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + request@~2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" @@ -1701,33 +1807,6 @@ request@~2.79.0: tunnel-agent "~0.4.1" uuid "^3.0.0" -request@~2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - requires-port@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -1978,9 +2057,9 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -typescript@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631" +typescript@2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624" unbzip2-stream@^1.0.9: version "1.2.5" @@ -2129,6 +2208,10 @@ vscode@^1.0.1: url-parse "^1.1.9" vinyl-source-stream "^1.1.0" +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/extensions/bat/syntaxes/batchfile.tmLanguage.json b/extensions/bat/syntaxes/batchfile.tmLanguage.json index 2aee0692ad..e5f00ed382 100644 --- a/extensions/bat/syntaxes/batchfile.tmLanguage.json +++ b/extensions/bat/syntaxes/batchfile.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/mmims/language-batchfile/commit/3dd105c31484e5975144478dac1aa91d8f51e528", + "version": "https://github.com/mmims/language-batchfile/commit/6235c491be4dff49cd3966b50142874d7f79580a", "name": "Batch File", "scopeName": "source.batchfile", "patterns": [ @@ -46,14 +46,17 @@ "commands": { "patterns": [ { - "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setlocal|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)", + "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)", "name": "keyword.command.batchfile" }, { - "begin": "(?<=^|[\\s@])(?i:echo)(?=$|\\s|\\.)", + "begin": "(?i)(?<=^|[\\s@])(echo)(?:(?=$|\\.|:)|\\s+(?:(on|off)(?=\\s*$))?)", "beginCaptures": { - "0": { + "1": { "name": "keyword.command.batchfile" + }, + "2": { + "name": "keyword.other.special-method.batchfile" } }, "end": "(?=$\\n|[&|><)])", @@ -72,6 +75,17 @@ } ] }, + { + "match": "(?i)(?<=^|[\\s@])(setlocal)(?:\\s*$|\\s+(EnableExtensions|DisableExtensions|EnableDelayedExpansion|DisableDelayedExpansion)(?=\\s*$))", + "captures": { + "1": { + "name": "keyword.command.batchfile" + }, + "2": { + "name": "keyword.other.special-method.batchfile" + } + } + }, { "include": "#command_set" } @@ -110,35 +124,7 @@ "include": "#parens" }, { - "begin": "(\")\\s*([^ ][^=]*)(=)\"?", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.batchfile" - }, - "2": { - "name": "variable.other.readwrite.batchfile" - }, - "3": { - "name": "keyword.operator.assignment.batchfile" - } - }, - "end": "\"", - "endCaptures": { - "0": { - "name": "string.quoted.double.batchfile" - } - }, - "patterns": [ - { - "include": "#variables" - }, - { - "include": "#numbers" - }, - { - "include": "#parens" - } - ] + "include": "#command_set_strings" }, { "include": "#strings" @@ -215,6 +201,9 @@ "begin": "\\s+/[pP]\\s+", "end": "(?=$\\n|[&|><)])", "patterns": [ + { + "include": "#command_set_strings" + }, { "begin": "([^ ][^=]*)(=)", "beginCaptures": { @@ -294,6 +283,42 @@ } ] }, + "command_set_strings": { + "patterns": [ + { + "begin": "(\")\\s*([^ ][^=]*)(=)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.batchfile" + }, + "2": { + "name": "variable.other.readwrite.batchfile" + }, + "3": { + "name": "keyword.operator.assignment.batchfile" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.batchfile" + } + }, + "name": "string.quoted.double.batchfile", + "patterns": [ + { + "include": "#variables" + }, + { + "include": "#numbers" + }, + { + "include": "#escaped_characters" + } + ] + } + ] + }, "comments": { "patterns": [ { @@ -359,7 +384,7 @@ "controls": { "patterns": [ { - "match": "(?<=^|\\s)(?i)(?:goto|call|exit)(?=$|\\s)", + "match": "(?i)(?<=^|\\s)(?:call|exit(?=$|\\s)|goto(?=$|\\s|:))", "name": "keyword.control.statement.batchfile" }, { @@ -389,7 +414,7 @@ "escaped_characters": { "patterns": [ { - "match": "%%|\\^\\^!|\\^.|\\^\\n", + "match": "%%|\\^\\^!|\\^(?=.)|\\^\\n", "name": "constant.character.escape.batchfile" } ] @@ -397,7 +422,7 @@ "labels": { "patterns": [ { - "match": "^\\s*(:)([^+=,;:\\s].*)$", + "match": "(?i)(?:^\\s*|(?<=goto)\\s*)(:)([^+=,;:\\s].*)$", "captures": { "1": { "name": "punctuation.separator.batchfile" @@ -432,11 +457,11 @@ "name": "keyword.operator.logical.batchfile" }, { - "match": "&&?|\\|\\|", + "match": "(? -1) { const fixPosition = document.positionAt(lastEndOfSomething); - edit.insert(document.uri, fixPosition, ','); + + // Don't insert a comma immediately before a : or ' :' + const colonRange = document.getWordRangeAtPosition(fixPosition, / *:/); + if (!colonRange) { + edit.insert(document.uri, fixPosition, ','); + } } } }); diff --git a/extensions/docker/OSSREADME.json b/extensions/docker/OSSREADME.json index 28c0191ec1..bc514d5d8b 100644 --- a/extensions/docker/OSSREADME.json +++ b/extensions/docker/OSSREADME.json @@ -4,5 +4,5 @@ "version": "0.0.0", "license": "Apache2", "repositoryURL": "https://github.com/moby/moby", - "description": "The file syntaxes/Dockerfile.tmLanguage was included from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage." + "description": "The file syntaxes/docker.tmLanguage was included from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage." }] diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index b5feab96d7..e5c502426c 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -7,10 +7,6 @@ "engines": { "vscode": "^1.4.0" }, - "categories": [ - "Languages", - "Other" - ], "activationEvents": [ "onLanguage:json", "onLanguage:markdown", diff --git a/extensions/git/package.json b/extensions/git/package.json index 8928bbace1..c2851ea34c 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -834,6 +834,23 @@ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/" } ], + "editor/context": [ + { + "command": "git.stageSelectedRanges", + "group": "2_git@1", + "when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/" + }, + { + "command": "git.unstageSelectedRanges", + "group": "2_git@2", + "when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/" + }, + { + "command": "git.revertSelectedRanges", + "group": "2_git@3", + "when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/" + } + ], "scm/change/title": [ { "command": "git.stageChange", @@ -861,7 +878,7 @@ ], "description": "%config.path%", "default": null, - "isExecutable": true + "scope": "application" }, "git.autoRepositoryDetection": { "type": "boolean", @@ -964,6 +981,12 @@ "scope": "resource", "default": true, "description": "%config.detectSubmodules%" + }, + "git.detectSubmodulesLimit": { + "type": "number", + "scope": "resource", + "default": 10, + "description": "%config.detectSubmodulesLimit%" } } }, @@ -1090,7 +1113,8 @@ "byline": "^5.0.0", "file-type": "^7.2.0", "iconv-lite": "0.4.19", - "vscode-extension-telemetry": "0.0.15", + "jschardet": "^1.6.0", + "vscode-extension-telemetry": "0.0.17", "vscode-nls": "^3.2.1", "which": "^1.3.0" }, @@ -1102,4 +1126,4 @@ "@types/which": "^1.0.28", "mocha": "^3.2.0" } -} \ No newline at end of file +} diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 6910adcbda..7f2c43dd23 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -70,6 +70,7 @@ "config.showInlineOpenFileAction": "Controls whether to show an inline Open File action in the Git changes view.", "config.inputValidation": "Controls when to show commit message input validation.", "config.detectSubmodules": "Controls whether to automatically detect git submodules.", + "config.detectSubmodulesLimit": "Controls the limit of git submodules detected.", "colors.modified": "Color for modified resources.", "colors.deleted": "Color for deleted resources.", "colors.untracked": "Color for untracked resources.", diff --git a/extensions/git/src/api.ts b/extensions/git/src/api.ts index 2f4065bbd2..41b3103ade 100644 --- a/extensions/git/src/api.ts +++ b/extensions/git/src/api.ts @@ -6,37 +6,55 @@ 'use strict'; import { Model } from './model'; -import { Uri } from 'vscode'; +import { Repository as ModelRepository } from './repository'; +import { Uri, SourceControlInputBox } from 'vscode'; export interface InputBox { value: string; } +export class InputBoxImpl implements InputBox { + set value(value: string) { this.inputBox.value = value; } + get value(): string { return this.inputBox.value; } + constructor(private inputBox: SourceControlInputBox) { } +} + export interface Repository { readonly rootUri: Uri; readonly inputBox: InputBox; } -export interface API { - getRepositories(): Promise; +export class RepositoryImpl implements Repository { + + readonly rootUri: Uri; + readonly inputBox: InputBox; + + constructor(repository: ModelRepository) { + this.rootUri = Uri.file(repository.root); + this.inputBox = new InputBoxImpl(repository.inputBox); + } } -export function createApi(modelPromise: Promise) { - return { - async getRepositories(): Promise { - const model = await modelPromise; +export interface API { + getRepositories(): Promise; + getGitPath(): Promise; +} - return model.repositories.map(repository => ({ - rootUri: Uri.file(repository.root), - inputBox: { - set value(value: string) { - repository.inputBox.value = value; - }, - get value(): string { - return repository.inputBox.value; - } - } - })); - } - }; +export class APIImpl implements API { + + constructor(private modelPromise: Promise) { } + + async getGitPath(): Promise { + const model = await this.modelPromise; + return model.git.path; + } + + async getRepositories(): Promise { + const model = await this.modelPromise; + return model.repositories.map(repository => new RepositoryImpl(repository)); + } +} + +export function createApi(modelPromise: Promise): API { + return new APIImpl(modelPromise); } \ No newline at end of file diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index d51f0a25aa..38680404fd 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -5,7 +5,7 @@ 'use strict'; -import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, CancellationTokenSource, StatusBarAlignment } from 'vscode'; +import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, MessageOptions } from 'vscode'; import { Ref, RefType, Git, GitErrorCodes, Branch } from './git'; import { Repository, Resource, Status, CommitOptions, ResourceGroupType } from './repository'; import { Model } from './model'; @@ -328,8 +328,6 @@ export class CommandCenter { return ''; } - private static cloneId = 0; - @command('git.clone') async clone(url?: string): Promise { if (!url) { @@ -350,15 +348,18 @@ export class CommandCenter { } const config = workspace.getConfiguration('git'); - let value = config.get('defaultCloneDirectory') || os.homedir(); + let defaultCloneDirectory = config.get('defaultCloneDirectory') || os.homedir(); + defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir()); - const parentPath = await window.showInputBox({ - prompt: localize('parent', "Parent Directory"), - value, - ignoreFocusOut: true + const uris = await window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + defaultUri: Uri.file(defaultCloneDirectory), + openLabel: localize('selectFolder', "Select Repository Location") }); - if (!parentPath) { + if (!uris || uris.length === 0) { /* __GDPR__ "clone" : { "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } @@ -368,25 +369,33 @@ export class CommandCenter { return; } - const tokenSource = new CancellationTokenSource(); - const cancelCommandId = `cancelClone${CommandCenter.cloneId++}`; - const commandDisposable = commands.registerCommand(cancelCommandId, () => tokenSource.cancel()); - - const statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left); - statusBarItem.text = localize('cancel', "$(sync~spin) Cloning repository... Click to cancel"); - statusBarItem.tooltip = localize('cancel tooltip', "Cancel clone"); - statusBarItem.command = cancelCommandId; - statusBarItem.show(); - - const clonePromise = this.git.clone(url, parentPath.replace(/^~/, os.homedir()), tokenSource.token); + const uri = uris[0]; + const parentPath = uri.fsPath; try { - window.withProgress({ location: ProgressLocation.SourceControl, title: localize('cloning', "Cloning git repository...") }, () => clonePromise); + const opts = { + location: ProgressLocation.Notification, + title: localize('cloning', "Cloning git repository '{0}'...", url), + cancellable: true + }; - const repositoryPath = await clonePromise; + const repositoryPath = await window.withProgress( + opts, + (_, token) => this.git.clone(url!, parentPath, token) + ); + const choices = []; + let message = localize('proposeopen', "Would you like to open the cloned repository?"); const open = localize('openrepo', "Open Repository"); - const result = await window.showInformationMessage(localize('proposeopen', "Would you like to open the cloned repository?"), open); + choices.push(open); + + const addToWorkspace = localize('add', "Add to Workspace"); + if (workspace.workspaceFolders) { + message = localize('proposeopen2', "Would you like to open the cloned repository, or add it to the current workspace?"); + choices.push(addToWorkspace); + } + + const result = await window.showInformationMessage(message, ...choices); const openFolder = result === open; /* __GDPR__ @@ -396,8 +405,13 @@ export class CommandCenter { } */ this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'success' }, { openFolder: openFolder ? 1 : 0 }); + + const uri = Uri.file(repositoryPath); + if (openFolder) { - commands.executeCommand('vscode.openFolder', Uri.file(repositoryPath)); + commands.executeCommand('vscode.openFolder', uri); + } else if (result === addToWorkspace) { + workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri }); } } catch (err) { if (/already exists and is not an empty directory/.test(err && err.stderr || '')) { @@ -419,9 +433,6 @@ export class CommandCenter { } throw err; - } finally { - commandDisposable.dispose(); - statusBarItem.dispose(); } } @@ -1205,7 +1216,7 @@ export class CommandCenter { const message = localize('confirm force delete branch', "The branch '{0}' is not fully merged. Delete anyway?", name); const yes = localize('delete branch', "Delete Branch"); - const pick = await window.showWarningMessage(message, yes); + const pick = await window.showWarningMessage(message, { modal: true }, yes); if (pick === yes) { await run(true); @@ -1333,7 +1344,7 @@ export class CommandCenter { const remoteCharCnt = remotePick.label.length; - repository.pull(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1)); + repository.pullFrom(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1)); } @command('git.pull', { repository: true }) @@ -1345,7 +1356,7 @@ export class CommandCenter { return; } - await repository.pull(); + await repository.pull(repository.HEAD); } @command('git.pullRebase', { repository: true }) @@ -1357,7 +1368,7 @@ export class CommandCenter { return; } - await repository.pullWithRebase(); + await repository.pullWithRebase(repository.HEAD); } @command('git.push', { repository: true }) @@ -1375,7 +1386,7 @@ export class CommandCenter { } try { - await repository.push(); + await repository.push(repository.HEAD); } catch (err) { if (err.gitErrorCode !== GitErrorCodes.NoUpstreamBranch) { throw err; @@ -1443,7 +1454,7 @@ export class CommandCenter { const shouldPrompt = config.get('confirmSync') === true; if (shouldPrompt) { - const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}'.", HEAD.upstream); + const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}/{1}'.", HEAD.upstream.remote, HEAD.upstream.name); const yes = localize('ok', "OK"); const neverAgain = localize('never again', "OK, Don't Show Again"); const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain); @@ -1456,9 +1467,9 @@ export class CommandCenter { } if (rebase) { - await repository.syncRebase(); + await repository.syncRebase(HEAD); } else { - await repository.sync(); + await repository.sync(HEAD); } } @@ -1476,7 +1487,7 @@ export class CommandCenter { return; } - await repository.sync(); + await repository.sync(HEAD); })); } @@ -1635,6 +1646,10 @@ export class CommandCenter { this.telemetryReporter.sendTelemetryEvent('git.command', { command: id }); return result.catch(async err => { + const options: MessageOptions = { + modal: err.gitErrorCode === GitErrorCodes.DirtyWorkTree + }; + let message: string; switch (err.gitErrorCode) { @@ -1664,9 +1679,11 @@ export class CommandCenter { return; } + options.modal = true; + const outputChannel = this.outputChannel as OutputChannel; const openOutputChannelChoice = localize('open git log', "Open Git Log"); - const choice = await window.showErrorMessage(message, openOutputChannelChoice); + const choice = await window.showErrorMessage(message, options, openOutputChannelChoice); if (choice === openOutputChannelChoice) { outputChannel.show(); diff --git a/extensions/git/src/encoding.ts b/extensions/git/src/encoding.ts new file mode 100644 index 0000000000..5084830a6f --- /dev/null +++ b/extensions/git/src/encoding.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * 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 jschardet from 'jschardet'; + +jschardet.Constants.MINIMUM_THRESHOLD = 0.2; + +function detectEncodingByBOM(buffer: NodeBuffer): string | null { + if (!buffer || buffer.length < 2) { + return null; + } + + const b0 = buffer.readUInt8(0); + const b1 = buffer.readUInt8(1); + + // UTF-16 BE + if (b0 === 0xFE && b1 === 0xFF) { + return 'utf16be'; + } + + // UTF-16 LE + if (b0 === 0xFF && b1 === 0xFE) { + return 'utf16le'; + } + + if (buffer.length < 3) { + return null; + } + + const b2 = buffer.readUInt8(2); + + // UTF-8 + if (b0 === 0xEF && b1 === 0xBB && b2 === 0xBF) { + return 'utf8'; + } + + return null; +} + +const IGNORE_ENCODINGS = [ + 'ascii', + 'utf-8', + 'utf-16', + 'utf-32' +]; + +const JSCHARDET_TO_ICONV_ENCODINGS: { [name: string]: string } = { + 'ibm866': 'cp866', + 'big5': 'cp950' +}; + +export function detectEncoding(buffer: Buffer): string | null { + let result = detectEncodingByBOM(buffer); + + if (result) { + return result; + } + + const detected = jschardet.detect(buffer); + + if (!detected || !detected.encoding) { + return null; + } + + const encoding = detected.encoding; + + // Ignore encodings that cannot guess correctly + // (http://chardet.readthedocs.io/en/latest/supported-encodings.html) + if (0 <= IGNORE_ENCODINGS.indexOf(encoding.toLowerCase())) { + return null; + } + + const normalizedEncodingName = encoding.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); + const mapped = JSCHARDET_TO_ICONV_ENCODINGS[normalizedEncodingName]; + + return mapped || normalizedEncodingName; +} diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 4fac914dec..5df804da21 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -15,6 +15,7 @@ import iconv = require('iconv-lite'); import * as filetype from 'file-type'; import { assign, uniqBy, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent } from './util'; import { CancellationToken } from 'vscode'; +import { detectEncoding } from './encoding'; const readfile = denodeify(fs.readFile); @@ -53,8 +54,13 @@ export interface Ref { remote?: string; } +export interface UpstreamRef { + remote: string; + name: string; +} + export interface Branch extends Ref { - upstream?: string; + upstream?: UpstreamRef; ahead?: number; behind?: number; } @@ -361,14 +367,14 @@ function getGitErrorCode(stderr: string): string | undefined { export class Git { - private gitPath: string; + readonly path: string; private env: any; private _onOutput = new EventEmitter(); get onOutput(): EventEmitter { return this._onOutput; } constructor(options: IGitOptions) { - this.gitPath = options.gitPath; + this.path = options.gitPath; this.env = options.env || {}; } @@ -382,11 +388,29 @@ export class Git { } async clone(url: string, parentPath: string, cancellationToken?: CancellationToken): Promise { - const folderName = decodeURI(url).replace(/^.*\//, '').replace(/\.git$/, '') || 'repository'; - const folderPath = path.join(parentPath, folderName); + let baseFolderName = decodeURI(url).replace(/^.*\//, '').replace(/\.git$/, '') || 'repository'; + let folderName = baseFolderName; + let folderPath = path.join(parentPath, folderName); + let count = 1; + + while (count < 20 && await new Promise(c => fs.exists(folderPath, c))) { + folderName = `${baseFolderName}-${count++}`; + folderPath = path.join(parentPath, folderName); + } await mkdirp(parentPath); - await this.exec(parentPath, ['clone', url, folderPath], { cancellationToken }); + + try { + await this.exec(parentPath, ['clone', url, folderPath], { cancellationToken }); + } catch (err) { + if (err.stderr) { + err.stderr = err.stderr.replace(/^Cloning.+$/m, '').trim(); + err.stderr = err.stderr.replace(/^ERROR:\s+/, '').trim(); + } + + throw err; + } + return folderPath; } @@ -442,7 +466,7 @@ export class Git { } spawn(args: string[], options: SpawnOptions = {}): cp.ChildProcess { - if (!this.gitPath) { + if (!this.path) { throw new Error('git could not be found in the system.'); } @@ -464,7 +488,7 @@ export class Git { this.log(`> git ${args.join(' ')}\n`); } - return cp.spawn(this.gitPath, args, options); + return cp.spawn(this.path, args, options); } private log(output: string): void { @@ -654,9 +678,16 @@ export class Repository { return result.stdout; } - async bufferString(object: string, encoding: string = 'utf8'): Promise { + async bufferString(object: string, encoding: string = 'utf8', autoGuessEncoding = false): Promise { const stdout = await this.buffer(object); - return iconv.decode(stdout, iconv.encodingExists(encoding) ? encoding : 'utf8'); + + if (autoGuessEncoding) { + encoding = detectEncoding(stdout) || encoding; + } + + encoding = iconv.encodingExists(encoding) ? encoding : 'utf8'; + + return iconv.decode(stdout, encoding); } async buffer(object: string): Promise { @@ -988,7 +1019,7 @@ export class Repository { } async pull(rebase?: boolean, remote?: string, branch?: string): Promise { - const args = ['pull']; + const args = ['pull', '--tags']; if (rebase) { args.push('-r'); @@ -1008,7 +1039,8 @@ export class Repository { err.gitErrorCode = GitErrorCodes.NoUserNameConfigured; } else if (/Could not read from remote repository/.test(err.stderr || '')) { err.gitErrorCode = GitErrorCodes.RemoteConnectionError; - } else if (/Pull is not possible because you have unmerged files|Cannot pull with rebase: You have unstaged changes|Your local changes to the following files would be overwritten|Please, commit your changes before you can merge/.test(err.stderr)) { + } else if (/Pull is not possible because you have unmerged files|Cannot pull with rebase: You have unstaged changes|Your local changes to the following files would be overwritten|Please, commit your changes before you can merge/i.test(err.stderr)) { + err.stderr = err.stderr.replace(/Cannot pull with rebase: You have unstaged changes/i, 'Cannot pull with rebase, you have unstaged changes'); err.gitErrorCode = GitErrorCodes.DirtyWorkTree; } @@ -1218,10 +1250,16 @@ export class Repository { const commit = result.stdout.trim(); try { - const res2 = await this.run(['rev-parse', '--symbolic-full-name', '--abbrev-ref', name + '@{u}']); - const upstream = res2.stdout.trim(); + const res2 = await this.run(['rev-parse', '--symbolic-full-name', name + '@{u}']); + const fullUpstream = res2.stdout.trim(); + const match = /^refs\/remotes\/([^/]+)\/(.+)$/.exec(fullUpstream); - const res3 = await this.run(['rev-list', '--left-right', name + '...' + upstream]); + if (!match) { + throw new Error(`Could not parse upstream branch: ${fullUpstream}`); + } + + const upstream = { remote: match[1], name: match[2] }; + const res3 = await this.run(['rev-list', '--left-right', name + '...' + fullUpstream]); let ahead = 0, behind = 0; let i = 0; diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index 94ca406da7..d5bae6d498 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -17,6 +17,7 @@ import { Askpass } from './askpass'; import { toDisposable, filterEvent, eventToPromise } from './util'; import TelemetryReporter from 'vscode-extension-telemetry'; import { API, createApi } from './api'; +import { GitProtocolHandler } from './protocolHandler'; let telemetryReporter: TelemetryReporter; @@ -51,7 +52,8 @@ async function init(context: ExtensionContext, outputChannel: OutputChannel, dis disposables.push( new CommandCenter(git, model, outputChannel, telemetryReporter), new GitContentProvider(model), - new GitDecorations(model) + new GitDecorations(model), + new GitProtocolHandler() ); await checkGitVersion(info); diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 6958f46d00..41f75e81b6 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -66,7 +66,7 @@ export class Model { private disposables: Disposable[] = []; - constructor(private git: Git, private globalState: Memento, private outputChannel: OutputChannel) { + constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) { workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] }); @@ -227,14 +227,17 @@ export class Model { const changeListener = repository.onDidChangeRepository(uri => this._onDidChangeRepository.fire({ repository, uri })); const originalResourceChangeListener = repository.onDidChangeOriginalResource(uri => this._onDidChangeOriginalResource.fire({ repository, uri })); + const submodulesLimit = workspace + .getConfiguration('git', Uri.file(repository.root)) + .get('detectSubmodulesLimit') as number; + const checkForSubmodules = () => { - if (repository.submodules.length > 10) { + if (repository.submodules.length > submodulesLimit) { window.showWarningMessage(localize('too many submodules', "The '{0}' repository has {1} submodules which won't be opened automatically. You can still open each one individually by opening a file within.", path.basename(repository.root), repository.submodules.length)); statusListener.dispose(); - return; } - this.scanSubmodules(repository); + this.scanSubmodules(repository, submodulesLimit); }; const statusListener = repository.onDidRunGitStatus(checkForSubmodules); @@ -256,7 +259,7 @@ export class Model { this._onDidOpenRepository.fire(repository); } - private scanSubmodules(repository: Repository): void { + private scanSubmodules(repository: Repository, limit: number): void { const shouldScanSubmodules = workspace .getConfiguration('git', Uri.file(repository.root)) .get('detectSubmodules') === true; @@ -266,6 +269,7 @@ export class Model { } repository.submodules + .slice(0, limit) .map(r => path.join(repository.root, r.path)) .forEach(p => this.eventuallyScanPossibleGitRepository(p)); } diff --git a/extensions/git/src/protocolHandler.ts b/extensions/git/src/protocolHandler.ts new file mode 100644 index 0000000000..57c70c75e8 --- /dev/null +++ b/extensions/git/src/protocolHandler.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { ProtocolHandler, Uri, window, Disposable, commands } from 'vscode'; +import { dispose } from './util'; +import * as querystring from 'querystring'; + +export class GitProtocolHandler implements ProtocolHandler { + + private disposables: Disposable[] = []; + + constructor() { + this.disposables.push(window.registerProtocolHandler(this)); + } + + handleUri(uri: Uri): void { + switch (uri.path) { + case '/clone': this.clone(uri); + } + } + + private clone(uri: Uri): void { + const data = querystring.parse(uri.query); + + if (!data.url) { + console.warn('Failed to open URI:', uri); + } + + commands.executeCommand('git.clone', data.url); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} \ No newline at end of file diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 8d8ff647a8..cae0335516 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -728,24 +728,48 @@ export class Repository implements Disposable { } @throttle - async pullWithRebase(): Promise { - await this.run(Operation.Pull, () => this.repository.pull(true)); + async pullWithRebase(head: Branch | undefined): Promise { + let remote: string | undefined; + let branch: string | undefined; + + if (head && head.name && head.upstream) { + remote = head.upstream.remote; + branch = `${head.upstream.name}`; + } + + await this.run(Operation.Pull, () => this.repository.pull(true, remote, branch)); } @throttle - async pull(rebase?: boolean, remote?: string, name?: string): Promise { - await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, name)); - } + async pull(head: Branch | undefined): Promise { + let remote: string | undefined; + let branch: string | undefined; - @throttle - async push(): Promise { - await this.run(Operation.Push, () => this.repository.push()); + if (head && head.name && head.upstream) { + remote = head.upstream.remote; + branch = `${head.upstream.name}`; + } + + await this.run(Operation.Pull, () => this.repository.pull(false, remote, branch)); } async pullFrom(rebase?: boolean, remote?: string, branch?: string): Promise { await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, branch)); } + @throttle + async push(head: Branch): Promise { + let remote: string | undefined; + let branch: string | undefined; + + if (head && head.name && head.upstream) { + remote = head.upstream.remote; + branch = `${head.name}:${head.upstream.name}`; + } + + await this.run(Operation.Push, () => this.repository.push(remote, branch)); + } + async pushTo(remote?: string, name?: string, setUpstream: boolean = false): Promise { await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream)); } @@ -754,47 +778,53 @@ export class Repository implements Disposable { await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true)); } - private async _sync(rebase: boolean): Promise { + @throttle + sync(head: Branch): Promise { + return this._sync(head, false); + } + + @throttle + async syncRebase(head: Branch): Promise { + return this._sync(head, true); + } + + private async _sync(head: Branch, rebase: boolean): Promise { + let remote: string | undefined; + let pullBranch: string | undefined; + let pushBranch: string | undefined; + + if (head.name && head.upstream) { + remote = head.upstream.remote; + pullBranch = `${head.upstream.name}`; + pushBranch = `${head.name}:${head.upstream.name}`; + } + await this.run(Operation.Sync, async () => { - await this.repository.pull(rebase); + await this.repository.pull(rebase, remote, pullBranch); const shouldPush = this.HEAD && typeof this.HEAD.ahead === 'number' ? this.HEAD.ahead > 0 : true; if (shouldPush) { - await this.repository.push(); + await this.repository.push(remote, pushBranch); } }); } - @throttle - sync(): Promise { - return this._sync(false); - } - - @throttle - async syncRebase(): Promise { - return this._sync(true); - } - async show(ref: string, filePath: string): Promise { - return await this.run(Operation.Show, async () => { + return this.run(Operation.Show, () => { const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/'); const configFiles = workspace.getConfiguration('files', Uri.file(filePath)); - const encoding = configFiles.get('encoding'); + const defaultEncoding = configFiles.get('encoding'); + const autoGuessEncoding = configFiles.get('autoGuessEncoding'); - // TODO@joao: Resource config api - return await this.repository.bufferString(`${ref}:${relativePath}`, encoding); + return this.repository.bufferString(`${ref}:${relativePath}`, defaultEncoding, autoGuessEncoding); }); } async buffer(ref: string, filePath: string): Promise { - return await this.run(Operation.Show, async () => { + return this.run(Operation.Show, () => { const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/'); - // const configFiles = workspace.getConfiguration('files', Uri.file(filePath)); - // const encoding = configFiles.get('encoding'); - - // TODO@joao: REsource config api - return await this.repository.buffer(`${ref}:${relativePath}`); + return this.repository.buffer(`${ref}:${relativePath}`); }); } diff --git a/extensions/git/src/typings/jschardet.d.ts b/extensions/git/src/typings/jschardet.d.ts new file mode 100644 index 0000000000..9c553b129e --- /dev/null +++ b/extensions/git/src/typings/jschardet.d.ts @@ -0,0 +1,11 @@ +declare module 'jschardet' { + export interface IDetectedMap { + encoding: string, + confidence: number + } + export function detect(buffer: NodeBuffer): IDetectedMap; + + export const Constants: { + MINIMUM_THRESHOLD: number, + } +} \ No newline at end of file diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index c409a1d08c..b00642d693 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -303,6 +303,10 @@ export function detectUnicodeEncoding(buffer: Buffer): Encoding | null { return null; } +function isWindowsPath(path: string): boolean { + return /^[a-zA-Z]:\\/.test(path); +} + export function isDescendant(parent: string, descendant: string): boolean { if (parent === descendant) { return true; @@ -312,5 +316,11 @@ export function isDescendant(parent: string, descendant: string): boolean { parent += sep; } + // Windows is case insensitive + if (isWindowsPath(parent)) { + parent = parent.toLowerCase(); + descendant = descendant.toLowerCase(); + } + return descendant.startsWith(parent); } diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 747060bcb3..3fb8a6f087 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -145,6 +145,10 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" +jschardet@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678" + json3@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" @@ -253,9 +257,9 @@ supports-color@3.1.2: dependencies: has-flag "^1.0.0" -vscode-extension-telemetry@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856" +vscode-extension-telemetry@0.0.17: + version "0.0.17" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.17.tgz#15123e7edb34e7b9724b6056f54a869bbb922cb7" dependencies: applicationinsights "1.0.1" diff --git a/extensions/json/.vscode/launch.json b/extensions/json-language-features/.vscode/launch.json similarity index 100% rename from extensions/json/.vscode/launch.json rename to extensions/json-language-features/.vscode/launch.json diff --git a/extensions/json/.vscode/tasks.json b/extensions/json-language-features/.vscode/tasks.json similarity index 100% rename from extensions/json/.vscode/tasks.json rename to extensions/json-language-features/.vscode/tasks.json diff --git a/extensions/json-language-features/.vscodeignore b/extensions/json-language-features/.vscodeignore new file mode 100644 index 0000000000..d30ea9070d --- /dev/null +++ b/extensions/json-language-features/.vscodeignore @@ -0,0 +1,7 @@ +test/** +client/tsconfig.json +client/src/** +server/bin +server/tsconfig.json +server/src/** +server/node_modules/@types/** \ No newline at end of file diff --git a/extensions/json/client/src/jsonMain.ts b/extensions/json-language-features/client/src/jsonMain.ts similarity index 81% rename from extensions/json/client/src/jsonMain.ts rename to extensions/json-language-features/client/src/jsonMain.ts index 8f03ed140d..102a081756 100644 --- a/extensions/json/client/src/jsonMain.ts +++ b/extensions/json-language-features/client/src/jsonMain.ts @@ -8,11 +8,11 @@ import * as path from 'path'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeList, FoldingRange, Disposable } from 'vscode'; -import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient'; +import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeKind, FoldingRange, Disposable, FoldingContext } from 'vscode'; +import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, CancellationToken } from 'vscode-languageclient'; import TelemetryReporter from 'vscode-extension-telemetry'; -import { FoldingRangesRequest } from './protocol/foldingProvider.proposed'; +import { FoldingRangeRequest, FoldingRangeRequestParam, FoldingRangeClientCapabilities, FoldingRangeKind as LSFoldingRangeKind } from 'vscode-languageserver-protocol-foldingprovider'; import { hash } from './utils/hash'; @@ -57,9 +57,6 @@ interface JSONSchemaSettings { let telemetryReporter: TelemetryReporter | undefined; -let foldingProviderRegistration: Disposable | undefined = void 0; -const foldingSetting = 'json.experimental.syntaxFolding'; - export function activate(context: ExtensionContext) { let toDispose = context.subscriptions; @@ -70,7 +67,7 @@ export function activate(context: ExtensionContext) { // The server is implemented in node let serverModule = context.asAbsolutePath(path.join('server', 'out', 'jsonServerMain.js')); // The debug options for the server - let debugOptions = { execArgv: ['--nolazy', '--inspect=6046'] }; + let debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] }; // If the extension is launch in debug mode the debug server options are use // Otherwise the run options are used @@ -100,6 +97,21 @@ export function activate(context: ExtensionContext) { // Create the language client and start the client. let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions); client.registerProposedFeatures(); + client.registerFeature({ + fillClientCapabilities(capabilities: FoldingRangeClientCapabilities): void { + let textDocumentCap = capabilities.textDocument; + if (!textDocumentCap) { + textDocumentCap = capabilities.textDocument = {}; + } + textDocumentCap.foldingRange = { + dynamicRegistration: false, + rangeLimit: 5000, + lineFoldingOnly: true + }; + }, + initialize(capabilities, documentSelector): void { + } + }); let disposable = client.start(); toDispose.push(disposable); @@ -130,13 +142,7 @@ export function activate(context: ExtensionContext) { client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context)); - initFoldingProvider(); - toDispose.push(workspace.onDidChangeConfiguration(c => { - if (c.affectsConfiguration(foldingSetting)) { - initFoldingProvider(); - } - })); - toDispose.push({ dispose: () => foldingProviderRegistration && foldingProviderRegistration.dispose() }); + toDispose.push(initFoldingProvider()); }); let languageConfiguration: LanguageConfiguration = { @@ -149,27 +155,36 @@ export function activate(context: ExtensionContext) { languages.setLanguageConfiguration('json', languageConfiguration); languages.setLanguageConfiguration('jsonc', languageConfiguration); - function initFoldingProvider() { - let enable = workspace.getConfiguration().get(foldingSetting); - if (enable) { - if (!foldingProviderRegistration) { - foldingProviderRegistration = languages.registerFoldingProvider(documentSelector, { - provideFoldingRanges(document: TextDocument) { - return client.sendRequest(FoldingRangesRequest.type, { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document) }).then(res => { - if (res && Array.isArray(res.ranges)) { - return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type))); - } - return null; - }); + function initFoldingProvider(): Disposable { + function getKind(kind: string | undefined): FoldingRangeKind | undefined { + if (kind) { + switch (kind) { + case LSFoldingRangeKind.Comment: + return FoldingRangeKind.Comment; + case LSFoldingRangeKind.Imports: + return FoldingRangeKind.Imports; + case LSFoldingRangeKind.Region: + return FoldingRangeKind.Region; + } + } + return void 0; + } + return languages.registerFoldingRangeProvider(documentSelector, { + provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) { + const param: FoldingRangeRequestParam = { + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document) + }; + return client.sendRequest(FoldingRangeRequest.type, param, token).then(ranges => { + if (Array.isArray(ranges)) { + return ranges.map(r => new FoldingRange(r.startLine, r.endLine, getKind(r.kind))); } + return null; + }, error => { + client.logFailedRequest(FoldingRangeRequest.type, error); + return null; }); } - } else { - if (foldingProviderRegistration) { - foldingProviderRegistration.dispose(); - foldingProviderRegistration = void 0; - } - } + }); } } diff --git a/extensions/json/client/src/typings/ref.d.ts b/extensions/json-language-features/client/src/typings/ref.d.ts similarity index 100% rename from extensions/json/client/src/typings/ref.d.ts rename to extensions/json-language-features/client/src/typings/ref.d.ts diff --git a/extensions/json/client/src/utils/hash.ts b/extensions/json-language-features/client/src/utils/hash.ts similarity index 100% rename from extensions/json/client/src/utils/hash.ts rename to extensions/json-language-features/client/src/utils/hash.ts diff --git a/extensions/json/client/tsconfig.json b/extensions/json-language-features/client/tsconfig.json similarity index 100% rename from extensions/json/client/tsconfig.json rename to extensions/json-language-features/client/tsconfig.json diff --git a/extensions/json/icons/json.png b/extensions/json-language-features/icons/json.png similarity index 100% rename from extensions/json/icons/json.png rename to extensions/json-language-features/icons/json.png diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json new file mode 100644 index 0000000000..53ff50c6a8 --- /dev/null +++ b/extensions/json-language-features/package.json @@ -0,0 +1,111 @@ +{ + "name": "json-language-features", + "displayName": "%displayName%", + "description": "%description%", + "version": "1.0.0", + "publisher": "vscode", + "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", + "engines": { + "vscode": "0.10.x" + }, + "icon": "icons/json.png", + "activationEvents": [ + "onLanguage:json", + "onLanguage:jsonc" + ], + "enableProposedApi": true, + "main": "./client/out/jsonMain", + "scripts": { + "compile": "gulp compile-extension:json-language-features-client && gulp compile-extension:json-language-features-server", + "postinstall": "cd server && yarn install", + "install-client-next": "yarn add vscode-languageclient@next" + }, + "categories": [ + "Programming Languages" + ], + "contributes": { + "configuration": { + "id": "json", + "order": 20, + "type": "object", + "title": "JSON", + "properties": { + "json.schemas": { + "type": "array", + "scope": "resource", + "description": "%json.schemas.desc%", + "items": { + "type": "object", + "default": { + "fileMatch": [ + "/myfile" + ], + "url": "schemaURL" + }, + "properties": { + "url": { + "type": "string", + "default": "/user.schema.json", + "description": "%json.schemas.url.desc%" + }, + "fileMatch": { + "type": "array", + "items": { + "type": "string", + "default": "MyFile.json", + "description": "%json.schemas.fileMatch.item.desc%" + }, + "minItems": 1, + "description": "%json.schemas.fileMatch.desc%" + }, + "schema": { + "$ref": "http://json-schema.org/draft-04/schema#", + "description": "%json.schemas.schema.desc%" + } + } + } + }, + "json.format.enable": { + "type": "boolean", + "scope": "window", + "default": true, + "description": "%json.format.enable.desc%" + }, + "json.trace.server": { + "type": "string", + "scope": "window", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "%json.tracing.desc%" + }, + "json.colorDecorators.enable": { + "type": "boolean", + "scope": "window", + "default": true, + "description": "%json.colorDecorators.enable.desc%", + "deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%" + } + } + }, + "configurationDefaults": { + "[json]": { + "editor.quickSuggestions": { + "strings": true + } + } + } + }, + "dependencies": { + "vscode-extension-telemetry": "0.0.17", + "vscode-languageclient": "^4.0.0", + "vscode-languageserver-protocol-foldingprovider": "^2.0.0-next.2", + "vscode-nls": "^3.2.2" + }, + "devDependencies": { + "@types/node": "7.0.43" + } +} diff --git a/extensions/json-language-features/package.nls.json b/extensions/json-language-features/package.nls.json new file mode 100644 index 0000000000..f9d52e8ebc --- /dev/null +++ b/extensions/json-language-features/package.nls.json @@ -0,0 +1,13 @@ +{ + "displayName": "JSON Language Features", + "description": "Provides rich language support for JSON files.", + "json.schemas.desc": "Associate schemas to JSON files in the current project", + "json.schemas.url.desc": "A URL to a schema or a relative path to a schema in the current directory", + "json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas.", + "json.schemas.fileMatch.item.desc": "A file pattern that can contain '*' to match against when resolving JSON files to schemas.", + "json.schemas.schema.desc": "The schema definition for the given URL. The schema only needs to be provided to avoid accesses to the schema URL.", + "json.format.enable.desc": "Enable/disable default JSON formatter (requires restart)", + "json.tracing.desc": "Traces the communication between VS Code and the JSON language server.", + "json.colorDecorators.enable.desc": "Enables or disables color decorators", + "json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`." +} \ No newline at end of file diff --git a/extensions/json-language-features/server/.npmignore b/extensions/json-language-features/server/.npmignore new file mode 100644 index 0000000000..a6661ddb7f --- /dev/null +++ b/extensions/json-language-features/server/.npmignore @@ -0,0 +1,7 @@ +.vscode/ +out/test/ +out/**/*.js.map +src/ +test/ +tsconfig.json +.gitignore \ No newline at end of file diff --git a/extensions/json/server/.vscode/launch.json b/extensions/json-language-features/server/.vscode/launch.json similarity index 77% rename from extensions/json/server/.vscode/launch.json rename to extensions/json-language-features/server/.vscode/launch.json index b564bb8569..57d6e4d252 100644 --- a/extensions/json/server/.vscode/launch.json +++ b/extensions/json-language-features/server/.vscode/launch.json @@ -8,7 +8,8 @@ "request": "attach", "port": 6004, "sourceMaps": true, - "outDir": "${workspaceFolder}/out" + "outFiles": ["${workspaceFolder}/out/**/*js"], + "preLaunchTask": "npm: compile" }, { "name": "Unit Tests", @@ -26,7 +27,8 @@ "runtimeArgs": [], "env": {}, "sourceMaps": true, - "outDir": "${workspaceFolder}/out" + "outFiles": ["${workspaceFolder}/out/**/*js"], + "preLaunchTask": "npm: compile" } ] } \ No newline at end of file diff --git a/extensions/json-language-features/server/.vscode/tasks.json b/extensions/json-language-features/server/.vscode/tasks.json new file mode 100644 index 0000000000..e2e2358082 --- /dev/null +++ b/extensions/json-language-features/server/.vscode/tasks.json @@ -0,0 +1,20 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/extensions/json-language-features/server/README.md b/extensions/json-language-features/server/README.md new file mode 100644 index 0000000000..27be5ab1bb --- /dev/null +++ b/extensions/json-language-features/server/README.md @@ -0,0 +1,173 @@ +# VSCode JSON Language Server + +[![NPM Version](https://img.shields.io/npm/v/vscode-json-languageserver.svg)](https://npmjs.org/package/vscode-json-languageserver) +[![NPM Downloads](https://img.shields.io/npm/dm/vscode-json-languageserver.svg)](https://npmjs.org/package/vscode-json-languageserver) +[![NPM Version](https://img.shields.io/npm/l/vscode-json-languageserver.svg)](https://npmjs.org/package/vscode-json-languageserver) + +The JSON Language server provides language-specific smarts for editing, validating and understanding JSON documents. It runs as a separate executable and implements the [language server protocol](https://microsoft.github.io/language-server-protocol/overview) to be connected by any code editor or IDE. + +## Capabilities + +### Server capabilities + +The JSON language server supports requests on documents of language id `json` and `jsonc`. +- `json` documents are parsed and validated following the [JSON specification](https://tools.ietf.org/html/rfc7159). +- `jsonc` documents additionally accept single line (`//`) and multi-line comments (`/* ... */`) and accepts trailing commas. JSONC is a VSCode specific file format, intended for VSCode configuration files, without any aspirations to define a new common file format. + +The server implements the following capabilities of the language server protocol: + +- [Code completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion) for JSON properties and values based on the document's [JSON schema](http://json-schema.org/) or based on existing properties and values used at other places in the document. JSON schemas are configured through the server configuration options. +- [Hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover) for values based on descriptions in the document's [JSON schema](http://json-schema.org/). +- [Document Symbols](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol) for quick navigation to properties in the document. +- [Document Colors](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor) for showing color decorators on values representing colors and [Color Presentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation) for color presentation information to support color pickers. The location of colors is defined by the document's [JSON schema](http://json-schema.org/). All values marked with `"format": "color-hex"` (VSCode specific, non-standard JSON Schema extension) are considered color values. The supported color formats are `#rgb[a]` and `#rrggbb[aa]`. +- [Code Formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting) supporting ranges and formatting the whole document. +- [Diagnostics (Validation)](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics) are pushed for all open documents + - syntax errors + - structural validation based on the document's [JSON schema](http://json-schema.org/). + +In order to load JSON schemas, the JSON server uses NodeJS `http` and `fs` modules. For all other features, the JSON server only relies on the documents and settings provided by the client through the LSP. + +### Client requirements: + +The JSON language server expects the client to only send requests and notifications for documents of language id `json` and `jsonc`. + +The JSON language server has the following dependencies on the client's capabilities: + +- Code completion requires that the client capability has *snippetSupport*. If not supported by the client, the server will not offer the completion capability. +- Formatting support requires the client to support *dynamicRegistration* for *rangeFormatting*. If not supported by the client, the server will not offer the format capability. + +## Configuration + +### Settings + +Clients may send a `workspace/didChangeConfiguration` notification to notify the server of settings changes. +The server supports the following settings: + +- http + - `proxy`: The URL of the proxy server to use when fetching schema. When undefined or empty, no proxy is used. + - `proxyStrictSSL`: Whether the proxy server certificate should be verified against the list of supplied CAs. + +- json + - `format` + - `enable`: Whether the server should register the formatting support. This option is only applicable if the client supports *dynamicRegistration* for *rangeFormatting* + - `schema`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content. + - `fileMatch`: an array or file names or paths (separated by `/`). `*` can be used as a wildcard. + - `url`: The URL of the schema, optional when also a schema is provided. + - `schema`: The schema content. + +```json + { + "http": { + "proxy": "", + "proxyStrictSSL": true + }, + "json": { + "format": { + "enable": true + }, + "schemas": [ + { + "fileMatch": [ + "foo.json", + "*.superfoo.json" + ], + "url": "http://json.schemastore.org/foo", + "schema": { + "type": "array" + } + } + ] + } + } +``` + +### Schema configuration and custom schema content delivery + +[JSON schemas](http://json-schema.org/) are essential for code assist, hovers, color decorators to work and are required for structural validation. + +To find the schema for a given JSON document, the server uses the following mechanisms: +- JSON documents can define the schema URL using a `$schema` property +- The settings define a schema association based on the documents URL. Settings can either associate a schema URL to a file or path pattern, and they can directly provide a schema. +- Additionally, schema associations can also be provided by a custom 'schemaAssociations' configuration call. + +Schemas are identified by URLs. To load the content of a schema, the JSON language server tries to load from that URL or path. The following URL schemas are supported: +- `http`, `https`: Loaded using NodeJS's HTTP support. Proxies can be configured through the settings. +- `file`: Loaded using NodeJS's `fs` support. +- `vscode`: Loaded by an LSP call to the client. + +#### Schema associations notification + +In addition to the settings, schemas associations can also be provided through a notification from the client to the server. This notification is a JSON language server specific, non-standardized, extension to the LSP. + +Notification: +- method: 'json/schemaAssociations' +- params: `ISchemaAssociations` defined as follows + +```ts +interface ISchemaAssociations { + [pattern: string]: string[]; +} +``` + - keys: a file names or file path (separated by `/`). `*` can be used as a wildcard. + - values: An array of schema URLs + +#### Schema content request + +The schema content for schema URLs that start with `vscode://` will be requested from the client through an LSP request. This request is a JSON language server specific, non-standardized, extension to the LSP. + +Request: +- method: 'vscode/content' +- params: `string` - The schema URL to request. The server will only ask for URLs that start with `vscode://` +- response: `string` - The content of the schema with the given URL + +#### Schema content change notification + +When the client is aware that a schema content has changed, it will notify the server through a notification. This notification is a JSON language server specific, non-standardized, extension to the LSP. +The server will, as a response, clear the schema content from the cache and reload the schema content when required again. + +Notification: +- method: 'json/schemaContent' +- params: `string` the URL of the schema that has changed. + +## Try + +The JSON language server is shipped with [Visual Studio Code](https://code.visualstudio.com/) as part of the built-in VSCode extension `json-language-features`. The server is started when the first JSON file is opened. The [VSCode JSON documentation](https://code.visualstudio.com/docs/languages/json) for detailed information on the user experience and has more information on how to configure the language support. + +## Integrate + +If you plan to integrate the JSON language server into an editor and IDE, check out [this page](https://microsoft.github.io/language-server-protocol/implementors/tools/) if there's already an LSP client integration available. + +You can also launch the language server as a command and connect to it. +For that, install the `json-language-server` npm module: + +`npm install -g json-language-server` + +Start the language server with the `json-language-server` command. Use a command line argument to specify the prefered communication channel: + +``` +json-language-server --node-ipc +json-language-server --stdio +json-language-server --socket= +``` + +To connect to the server from NodeJS, see Remy Suen's great write-up on [how to communicate with the server](https://github.com/rcjsuen/dockerfile-language-server-nodejs#communicating-with-the-server) through the available communication channels. + +## Participate + +The source code of the JSON language server can be found [VSCode repository](https://github.com/Microsoft/vscode) at [extensions/json-language-features/server](https://github.com/Microsoft/vscode/tree/master/extensions/json-language-features/server). +File issues and pull requests in the [VSCode GitHub Issues](https://github.com/Microsoft/vscode/issues). See the document [How to Contribute](https://github.com/Microsoft/vscode/wiki/How-to-Contribute) on how to build and run from source. + +Most of the functionality of the server is located in libraries: +- [jsonc-parser](https://github.com/Microsoft/node-jsonc-parser) contains the JSON parser and scanner. +- [vscode-json-languageservice](https://github.com/Microsoft/vscode-json-languageservice) contains the implementation of all features as a re-usable library. +- [vscode-languageserver-node](https://github.com/Microsoft/vscode-languageserver-node) contains the implementation of language server for NodeJS. + +Help on any of these projects is very welcome. + +Please see also our [Code of Conduct](CODE_OF_CONDUCT.md). + +## License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the [MIT](LICENSE.txt) License. diff --git a/src/vs/workbench/parts/html/browser/media/htmlPreviewPart.css b/extensions/json-language-features/server/bin/vscode-json-languageserver similarity index 86% rename from src/vs/workbench/parts/html/browser/media/htmlPreviewPart.css rename to extensions/json-language-features/server/bin/vscode-json-languageserver index 7e1f29be5f..ae3839511b 100644 --- a/src/vs/workbench/parts/html/browser/media/htmlPreviewPart.css +++ b/extensions/json-language-features/server/bin/vscode-json-languageserver @@ -1,8 +1,6 @@ +#!/usr/bin/env node /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -.htmlPreviewPart { - overflow: hidden; -} \ No newline at end of file +require("../out/jsonServerMain"); \ No newline at end of file diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json new file mode 100644 index 0000000000..3f4cc7718c --- /dev/null +++ b/extensions/json-language-features/server/package.json @@ -0,0 +1,38 @@ +{ + "name": "vscode-json-languageserver", + "description": "JSON language server", + "version": "1.0.1", + "author": "Microsoft Corporation", + "license": "MIT", + "engines": { + "node": "*" + }, + "bin": { + "vscode-json-languageserver": "./bin/vscode-json-languageserver" + }, + "dependencies": { + "jsonc-parser": "^2.0.0-next.1", + "request-light": "^0.2.2", + "vscode-json-languageservice": "^3.1.2-next.2", + "vscode-languageserver": "^4.0.0", + "vscode-languageserver-protocol-foldingprovider": "^2.0.0-next.2", + "vscode-nls": "^3.2.2", + "vscode-uri": "^1.0.3" + }, + "devDependencies": { + "@types/mocha": "2.2.33", + "@types/node": "7.0.43" + }, + "scripts": { + "prepublishOnly": "npm run clean && npm run test", + "preversion": "npm test", + "compile": "gulp compile-extension:json-language-features-server", + "watch": "gulp watch-extension:json-language-features-server", + "clean": "../../../node_modules/.bin/rimraf out", + "install-service-next": "yarn add vscode-json-languageservice@next", + "install-service-local": "yarn link vscode-json-languageservice", + "install-server-next": "yarn add vscode-languageserver@next", + "install-server-local": "yarn link vscode-languageserver-server", + "version": "git commit -m \"JSON Language Server $npm_package_version\" package.json" + } +} diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json-language-features/server/src/jsonServerMain.ts similarity index 68% rename from extensions/json/server/src/jsonServerMain.ts rename to extensions/json-language-features/server/src/jsonServerMain.ts index 1431e8712b..77e492623a 100644 --- a/extensions/json/server/src/jsonServerMain.ts +++ b/extensions/json-language-features/server/src/jsonServerMain.ts @@ -10,19 +10,16 @@ import { DocumentRangeFormattingRequest, Disposable, ServerCapabilities } from 'vscode-languageserver'; -import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; - import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light'; -import fs = require('fs'); +import * as fs from 'fs'; import URI from 'vscode-uri'; import * as URL from 'url'; -import Strings = require('./utils/strings'); -import { formatError, runSafe, runSafeAsync } from './utils/errors'; +import { startsWith } from './utils/strings'; +import { formatError, runSafe, runSafeAsync } from './utils/runner'; import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration } from 'vscode-json-languageservice'; import { getLanguageModelCache } from './languageModelCache'; -import { createScanner, SyntaxKind } from 'jsonc-parser'; -import { FoldingRangeType, FoldingRangesRequest, FoldingRange, FoldingRangeList, FoldingProviderServerCapabilities } from './protocol/foldingProvider.proposed'; +import { FoldingRangeRequest, FoldingRangeServerCapabilities } from 'vscode-languageserver-protocol-foldingprovider'; interface ISchemaAssociations { [pattern: string]: string[]; @@ -44,8 +41,12 @@ namespace SchemaContentChangeNotification { let connection: IConnection = createConnection(); process.on('unhandledRejection', (e: any) => { - connection.console.error(formatError(`Unhandled exception`, e)); + console.error(formatError(`Unhandled exception`, e)); }); +process.on('uncaughtException', (e: any) => { + console.error(formatError(`Unhandled exception`, e)); +}); + console.log = connection.console.log.bind(connection.console); console.error = connection.console.error.bind(connection.console); @@ -59,22 +60,28 @@ documents.listen(connection); let clientSnippetSupport = false; let clientDynamicRegisterSupport = false; +let foldingRangeLimit = Number.MAX_VALUE; -// After the server has started the client sends an initilize request. The server receives +// After the server has started the client sends an initialize request. The server receives // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { - function hasClientCapability(...keys: string[]) { - let c = params.capabilities as any; + function getClientCapability(name: string, def: T) { + let keys = name.split('.'); + let c: any = params.capabilities; for (let i = 0; c && i < keys.length; i++) { + if (!c.hasOwnProperty(keys[i])) { + return def; + } c = c[keys[i]]; } - return !!c; + return c; } - clientSnippetSupport = hasClientCapability('textDocument', 'completion', 'completionItem', 'snippetSupport'); - clientDynamicRegisterSupport = hasClientCapability('workspace', 'symbol', 'dynamicRegistration'); - let capabilities: ServerCapabilities & CPServerCapabilities & FoldingProviderServerCapabilities = { + clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false); + clientDynamicRegisterSupport = getClientCapability('workspace.symbol.dynamicRegistration', false); + foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); + let capabilities: ServerCapabilities & FoldingRangeServerCapabilities = { // Tell the client that the server works in FULL text document sync mode textDocumentSync: documents.syncKind, completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : void 0, @@ -82,7 +89,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { documentSymbolProvider: true, documentRangeFormattingProvider: false, colorProvider: true, - foldingProvider: true + foldingRangeProvider: true }; return { capabilities }; @@ -95,14 +102,14 @@ let workspaceContext = { }; let schemaRequestService = (uri: string): Thenable => { - if (Strings.startsWith(uri, 'file://')) { + if (startsWith(uri, 'file://')) { let fsPath = URI.parse(uri).fsPath; return new Promise((c, e) => { fs.readFile(fsPath, 'UTF-8', (err, result) => { err ? e('') : c(result.toString()); }); }); - } else if (Strings.startsWith(uri, 'vscode://')) { + } else if (startsWith(uri, 'vscode://')) { return connection.sendRequest(VSCodeContentRequest.type, uri).then(responseText => { return responseText; }, error => { @@ -110,6 +117,11 @@ let schemaRequestService = (uri: string): Thenable => { }); } if (uri.indexOf('//schema.management.azure.com/') !== -1) { + /* __GDPR__ + "json.schema" : { + "schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ connection.telemetry.logEvent({ key: 'json.schema', value: { @@ -257,17 +269,21 @@ function validateTextDocument(textDocument: TextDocument): void { connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); return; } - try { - let jsonDocument = getJSONDocument(textDocument); + let jsonDocument = getJSONDocument(textDocument); + let version = textDocument.version; - let documentSettings: DocumentLanguageSettings = textDocument.languageId === 'jsonc' ? { comments: 'ignore', trailingCommas: 'ignore' } : { comments: 'error', trailingCommas: 'error' }; - languageService.doValidation(textDocument, jsonDocument, documentSettings).then(diagnostics => { - // Send the computed diagnostics to VSCode. - connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); - }); - } catch (e) { - connection.console.error(formatError(`Error while validating ${textDocument.uri}`, e)); - } + let documentSettings: DocumentLanguageSettings = textDocument.languageId === 'jsonc' ? { comments: 'ignore', trailingCommas: 'ignore' } : { comments: 'error', trailingCommas: 'error' }; + languageService.doValidation(textDocument, jsonDocument, documentSettings).then(diagnostics => { + setTimeout(() => { + let currDocument = documents.get(textDocument.uri); + if (currDocument && currDocument.version === version) { + // Send the computed diagnostics to VSCode. + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); + } + }, 100); + }, error => { + connection.console.error(formatError(`Error while validating ${textDocument.uri}`, error)); + }); } connection.onDidChangeWatchedFiles((change) => { @@ -279,7 +295,7 @@ connection.onDidChangeWatchedFiles((change) => { } }); if (hasChanges) { - documents.all().forEach(validateTextDocument); + documents.all().forEach(triggerValidation); } }); @@ -295,44 +311,44 @@ function getJSONDocument(document: TextDocument): JSONDocument { return jsonDocuments.get(document); } -connection.onCompletion(textDocumentPosition => { +connection.onCompletion((textDocumentPosition, token) => { return runSafeAsync(() => { let document = documents.get(textDocumentPosition.textDocument.uri); let jsonDocument = getJSONDocument(document); return languageService.doComplete(document, textDocumentPosition.position, jsonDocument); - }, null, `Error while computing completions for ${textDocumentPosition.textDocument.uri}`); + }, null, `Error while computing completions for ${textDocumentPosition.textDocument.uri}`, token); }); -connection.onCompletionResolve(completionItem => { +connection.onCompletionResolve((completionItem, token) => { return runSafeAsync(() => { return languageService.doResolve(completionItem); - }, completionItem, `Error while resolving completion proposal`); + }, completionItem, `Error while resolving completion proposal`, token); }); -connection.onHover(textDocumentPositionParams => { +connection.onHover((textDocumentPositionParams, token) => { return runSafeAsync(() => { let document = documents.get(textDocumentPositionParams.textDocument.uri); let jsonDocument = getJSONDocument(document); return languageService.doHover(document, textDocumentPositionParams.position, jsonDocument); - }, null, `Error while computing hover for ${textDocumentPositionParams.textDocument.uri}`); + }, null, `Error while computing hover for ${textDocumentPositionParams.textDocument.uri}`, token); }); -connection.onDocumentSymbol(documentSymbolParams => { +connection.onDocumentSymbol((documentSymbolParams, token) => { return runSafe(() => { let document = documents.get(documentSymbolParams.textDocument.uri); let jsonDocument = getJSONDocument(document); return languageService.findDocumentSymbols(document, jsonDocument); - }, [], `Error while computing document symbols for ${documentSymbolParams.textDocument.uri}`); + }, [], `Error while computing document symbols for ${documentSymbolParams.textDocument.uri}`, token); }); -connection.onDocumentRangeFormatting(formatParams => { +connection.onDocumentRangeFormatting((formatParams, token) => { return runSafe(() => { let document = documents.get(formatParams.textDocument.uri); return languageService.format(document, formatParams.range, formatParams.options); - }, [], `Error while formatting range for ${formatParams.textDocument.uri}`); + }, [], `Error while formatting range for ${formatParams.textDocument.uri}`, token); }); -connection.onRequest(DocumentColorRequest.type, params => { +connection.onDocumentColor((params, token) => { return runSafeAsync(() => { let document = documents.get(params.textDocument.uri); if (document) { @@ -340,10 +356,10 @@ connection.onRequest(DocumentColorRequest.type, params => { return languageService.findDocumentColors(document, jsonDocument); } return Promise.resolve([]); - }, [], `Error while computing document colors for ${params.textDocument.uri}`); + }, [], `Error while computing document colors for ${params.textDocument.uri}`, token); }); -connection.onRequest(ColorPresentationRequest.type, params => { +connection.onColorPresentation((params, token) => { return runSafe(() => { let document = documents.get(params.textDocument.uri); if (document) { @@ -351,86 +367,17 @@ connection.onRequest(ColorPresentationRequest.type, params => { return languageService.getColorPresentations(document, jsonDocument, params.color, params.range); } return []; - }, [], `Error while computing color presentations for ${params.textDocument.uri}`); + }, [], `Error while computing color presentations for ${params.textDocument.uri}`, token); }); -connection.onRequest(FoldingRangesRequest.type, params => { +connection.onRequest(FoldingRangeRequest.type, (params, token) => { return runSafe(() => { let document = documents.get(params.textDocument.uri); if (document) { - let ranges: FoldingRange[] = []; - let stack: FoldingRange[] = []; - let prevStart = -1; - let scanner = createScanner(document.getText(), false); - let token = scanner.scan(); - while (token !== SyntaxKind.EOF) { - switch (token) { - case SyntaxKind.OpenBraceToken: - case SyntaxKind.OpenBracketToken: { - let startLine = document.positionAt(scanner.getTokenOffset()).line; - let range = { startLine, endLine: startLine, type: token === SyntaxKind.OpenBraceToken ? 'object' : 'array' }; - stack.push(range); - break; - } - case SyntaxKind.CloseBraceToken: - case SyntaxKind.CloseBracketToken: { - let type = token === SyntaxKind.CloseBraceToken ? 'object' : 'array'; - if (stack.length > 0 && stack[stack.length - 1].type === type) { - let range = stack.pop(); - let line = document.positionAt(scanner.getTokenOffset()).line; - if (range && line > range.startLine + 1 && prevStart !== range.startLine) { - range.endLine = line - 1; - ranges.push(range); - prevStart = range.startLine; - } - } - break; - } - - case SyntaxKind.BlockCommentTrivia: { - let startLine = document.positionAt(scanner.getTokenOffset()).line; - let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line; - if (startLine < endLine) { - ranges.push({ startLine, endLine, type: FoldingRangeType.Comment }); - prevStart = startLine; - } - break; - } - - case SyntaxKind.LineCommentTrivia: { - let text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength()); - let m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/); - if (m) { - let line = document.positionAt(scanner.getTokenOffset()).line; - if (m[1]) { // start pattern match - let range = { startLine: line, endLine: line, type: FoldingRangeType.Region }; - stack.push(range); - } else { - let i = stack.length - 1; - while (i >= 0 && stack[i].type !== FoldingRangeType.Region) { - i--; - } - if (i >= 0) { - let range = stack[i]; - stack.length = i; - if (line > range.startLine && prevStart !== range.startLine) { - range.endLine = line; - ranges.push(range); - prevStart = range.startLine; - } - } - } - } - break; - } - - } - token = scanner.scan(); - } - return { ranges }; + return languageService.getFoldingRanges(document, { rangeLimit: foldingRangeLimit }); } return null; - }, null, `Error while computing folding ranges for ${params.textDocument.uri}`); + }, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token); }); // Listen on the connection diff --git a/extensions/json/server/src/languageModelCache.ts b/extensions/json-language-features/server/src/languageModelCache.ts similarity index 100% rename from extensions/json/server/src/languageModelCache.ts rename to extensions/json-language-features/server/src/languageModelCache.ts diff --git a/extensions/json-language-features/server/src/utils/runner.ts b/extensions/json-language-features/server/src/utils/runner.ts new file mode 100644 index 0000000000..fe594edd39 --- /dev/null +++ b/extensions/json-language-features/server/src/utils/runner.ts @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { CancellationToken, ResponseError, ErrorCodes } from 'vscode-languageserver'; + +export function formatError(message: string, err: any): string { + if (err instanceof Error) { + let error = err; + return `${message}: ${error.message}\n${error.stack}`; + } else if (typeof err === 'string') { + return `${message}: ${err}`; + } else if (err) { + return `${message}: ${err.toString()}`; + } + return message; +} + +export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { + return new Promise>((resolve, reject) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } + return func().then(result => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + }, e => { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + }); + }); + }); +} + +export function runSafe(func: () => T, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { + return new Promise>((resolve, reject) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } else { + try { + let result = func(); + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + + } catch (e) { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + } + } + }); + }); +} + +function cancelValue() { + console.log('cancelled'); + return new ResponseError(ErrorCodes.RequestCancelled, 'Request cancelled'); +} diff --git a/extensions/json/server/src/utils/strings.ts b/extensions/json-language-features/server/src/utils/strings.ts similarity index 100% rename from extensions/json/server/src/utils/strings.ts rename to extensions/json-language-features/server/src/utils/strings.ts diff --git a/extensions/json-language-features/server/test/mocha.opts b/extensions/json-language-features/server/test/mocha.opts new file mode 100644 index 0000000000..d3e46273a0 --- /dev/null +++ b/extensions/json-language-features/server/test/mocha.opts @@ -0,0 +1,3 @@ +--ui tdd +--useColors true +./out/test/**/*.test.js \ No newline at end of file diff --git a/extensions/json/server/tsconfig.json b/extensions/json-language-features/server/tsconfig.json similarity index 100% rename from extensions/json/server/tsconfig.json rename to extensions/json-language-features/server/tsconfig.json diff --git a/extensions/json/server/yarn.lock b/extensions/json-language-features/server/yarn.lock similarity index 56% rename from extensions/json/server/yarn.lock rename to extensions/json-language-features/server/yarn.lock index ac7f8a5021..26fe2245dc 100644 --- a/extensions/json/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -2,6 +2,10 @@ # yarn lockfile v1 +"@types/mocha@2.2.33": + version "2.2.33" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.33.tgz#d79a0061ec270379f4d9e225f4096fb436669def" + "@types/node@7.0.43": version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" @@ -48,9 +52,13 @@ https-proxy-agent@2.1.1: agent-base "^4.1.0" debug "^3.1.0" -jsonc-parser@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.1.tgz#7f8f296414e6e7c4a33b9e4914fc8c47e4421675" +jsonc-parser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.0.0.tgz#62ff087a7e753875febf3c55f1fc0cd737c36b5a" + +jsonc-parser@^2.0.0-next.1: + version "2.0.0-next.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.0.0-next.1.tgz#445a824f765a96abfbb286d759a9b1d226b18088" ms@2.0.0: version "2.0.0" @@ -64,35 +72,46 @@ request-light@^0.2.2: https-proxy-agent "2.1.1" vscode-nls "^2.0.2" -vscode-json-languageservice@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.0.7.tgz#dc00117d51d4a7ac3bde9204afa701f962f00736" +vscode-json-languageservice@^3.1.2-next.2: + version "3.1.2-next.2" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.1.2-next.2.tgz#da5346e5c22edbce739f29c110eb41732d41dc2d" dependencies: - jsonc-parser "^1.0.1" - vscode-languageserver-types "^3.6.0-next.1" - vscode-nls "^2.0.2" - vscode-uri "^1.0.1" + jsonc-parser "^2.0.0" + vscode-languageserver-types "^3.6.1" + vscode-nls "^3.2.1" + vscode-uri "^1.0.3" -vscode-jsonrpc@^3.6.0-next.1: - version "3.6.0-next.1" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0-next.1.tgz#3cb463dffe5842d6aec16718ca9252708cd6aabe" +vscode-jsonrpc@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0.tgz#848d56995d5168950d84feb5d9c237ae5c6a02d4" -vscode-languageserver-protocol@^3.6.0-next.3: - version "3.6.0-next.4" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0-next.4.tgz#5b9940e4d6afafd5b63f9731dbd3a9bcc65b3719" +vscode-languageserver-protocol-foldingprovider@^2.0.0-next.2: + version "2.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol-foldingprovider/-/vscode-languageserver-protocol-foldingprovider-2.0.0-next.2.tgz#fbb9cfdf5b8c4ac451826ba6312f1f88379f35b0" dependencies: - vscode-jsonrpc "^3.6.0-next.1" - vscode-languageserver-types "^3.6.0-next.1" + vscode-languageserver-protocol "^3.6.0" + vscode-languageserver-types "^3.6.0" -vscode-languageserver-types@^3.6.0-next.1: - version "3.6.0-next.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0-next.1.tgz#98e488d3f87b666b4ee1a3d89f0023e246d358f3" - -vscode-languageserver@4.0.0-next.3: - version "4.0.0-next.3" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-4.0.0-next.3.tgz#89a9ce5078e3a86a78e3551c3766194ce4295611" +vscode-languageserver-protocol@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0.tgz#579642cdcccf74b0cd771c33daa3239acb40d040" dependencies: - vscode-languageserver-protocol "^3.6.0-next.3" + vscode-jsonrpc "^3.6.0" + vscode-languageserver-types "^3.6.0" + +vscode-languageserver-types@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0.tgz#0bba63b0fa82a714394a4478f55a596ee4ed7d0a" + +vscode-languageserver-types@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.1.tgz#4bc06a48dff653495f12f94b8b1e228988a1748d" + +vscode-languageserver@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-4.0.0.tgz#8b792f0d6d10acfe363d02371ed4ce53d08af88a" + dependencies: + vscode-languageserver-protocol "^3.6.0" vscode-uri "^1.0.1" vscode-nls@^2.0.2: @@ -103,6 +122,14 @@ vscode-nls@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51" +vscode-nls@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350" + vscode-uri@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.1.tgz#11a86befeac3c4aa3ec08623651a3c81a6d0bbc8" + +vscode-uri@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.3.tgz#631bdbf716dccab0e65291a8dc25c23232085a52" diff --git a/extensions/json/yarn.lock b/extensions/json-language-features/yarn.lock similarity index 57% rename from extensions/json/yarn.lock rename to extensions/json-language-features/yarn.lock index 926601edb2..ccfd30a4ce 100644 --- a/extensions/json/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -28,36 +28,43 @@ semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" -vscode-extension-telemetry@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856" +vscode-extension-telemetry@0.0.17: + version "0.0.17" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.17.tgz#15123e7edb34e7b9724b6056f54a869bbb922cb7" dependencies: applicationinsights "1.0.1" -vscode-jsonrpc@^3.6.0-next.1: - version "3.6.0-next.1" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0-next.1.tgz#3cb463dffe5842d6aec16718ca9252708cd6aabe" +vscode-jsonrpc@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0.tgz#848d56995d5168950d84feb5d9c237ae5c6a02d4" -vscode-languageclient@4.0.0-next.9: - version "4.0.0-next.9" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-4.0.0-next.9.tgz#2a06568f46ee9de3490f85e227d3740a21a03d3a" +vscode-languageclient@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-4.0.0.tgz#635f5bfbcfa1385dae489b394857f1db8b459a7d" dependencies: - vscode-languageserver-protocol "^3.6.0-next.5" + vscode-languageserver-protocol "^3.6.0" -vscode-languageserver-protocol@^3.6.0-next.5: - version "3.6.0-next.5" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0-next.5.tgz#ed2ec2db759826f753c0a13977dfb2bedc4d31b3" +vscode-languageserver-protocol-foldingprovider@^2.0.0-next.2: + version "2.0.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol-foldingprovider/-/vscode-languageserver-protocol-foldingprovider-2.0.0-next.2.tgz#fbb9cfdf5b8c4ac451826ba6312f1f88379f35b0" dependencies: - vscode-jsonrpc "^3.6.0-next.1" - vscode-languageserver-types "^3.6.0-next.1" + vscode-languageserver-protocol "^3.6.0" + vscode-languageserver-types "^3.6.0" -vscode-languageserver-types@^3.6.0-next.1: - version "3.6.0-next.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0-next.1.tgz#98e488d3f87b666b4ee1a3d89f0023e246d358f3" +vscode-languageserver-protocol@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0.tgz#579642cdcccf74b0cd771c33daa3239acb40d040" + dependencies: + vscode-jsonrpc "^3.6.0" + vscode-languageserver-types "^3.6.0" -vscode-nls@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51" +vscode-languageserver-types@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0.tgz#0bba63b0fa82a714394a4478f55a596ee4ed7d0a" + +vscode-nls@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350" zone.js@0.7.6: version "0.7.6" diff --git a/extensions/json/.vscodeignore b/extensions/json/.vscodeignore index 0441631b57..77ab386fc7 100644 --- a/extensions/json/.vscodeignore +++ b/extensions/json/.vscodeignore @@ -1,6 +1 @@ -test/** -client/tsconfig.json -client/src/** -server/tsconfig.json -server/src/** -server/node_modules/@types/** \ No newline at end of file +test/** \ No newline at end of file diff --git a/extensions/json/OSSREADME.json b/extensions/json/OSSREADME.json index 57bcccdcca..391402b86f 100644 --- a/extensions/json/OSSREADME.json +++ b/extensions/json/OSSREADME.json @@ -1,6 +1,6 @@ // ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: [{ - "name": "Benvie/JavaScriptNext.tmLanguage", + "name": "Microsoft/vscode-JSON.tmLanguage", "version": "0.0.0", "license": "MIT", "repositoryURL": "https://github.com/Microsoft/vscode-JSON.tmLanguage" diff --git a/extensions/json/client/src/protocol/foldingProvider.proposed.ts b/extensions/json/client/src/protocol/foldingProvider.proposed.ts deleted file mode 100644 index 8906dc5aae..0000000000 --- a/extensions/json/client/src/protocol/foldingProvider.proposed.ts +++ /dev/null @@ -1,89 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TextDocumentIdentifier } from 'vscode-languageserver-types'; -import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol'; - -// ---- capabilities - -export interface FoldingProviderClientCapabilities { - /** - * The text document client capabilities - */ - textDocument?: { - /** - * Capabilities specific to the foldingProvider - */ - foldingProvider?: { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)` - * return value for the corresponding server capability as well. - */ - dynamicRegistration?: boolean; - }; - }; -} - -export interface FoldingProviderOptions { -} - -export interface FoldingProviderServerCapabilities { - /** - * The server provides folding provider support. - */ - foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions); -} - -export interface FoldingRangeList { - /** - * The folding ranges. - */ - ranges: FoldingRange[]; -} - -export enum FoldingRangeType { - /** - * Folding range for a comment - */ - Comment = 'comment', - /** - * Folding range for a imports or includes - */ - Imports = 'imports', - /** - * Folding range for a region (e.g. `#region`) - */ - Region = 'region' -} - -export interface FoldingRange { - - /** - * The start line number - */ - startLine: number; - - /** - * The end line number - */ - endLine: number; - - /** - * The actual color value for this folding range. - */ - type?: FoldingRangeType | string; -} - -export interface FoldingRangeRequestParam { - /** - * The text document. - */ - textDocument: TextDocumentIdentifier; -} - -export namespace FoldingRangesRequest { - export const type: RequestType = new RequestType('textDocument/foldingRanges'); -} diff --git a/extensions/json/language-configuration.json b/extensions/json/language-configuration.json index 53ccbd2354..9a73ac64aa 100644 --- a/extensions/json/language-configuration.json +++ b/extensions/json/language-configuration.json @@ -12,6 +12,7 @@ { "open": "[", "close": "]", "notIn": ["string"] }, { "open": "(", "close": ")", "notIn": ["string"] }, { "open": "'", "close": "'", "notIn": ["string"] }, + { "open": "/*", "close": "*/", "notIn": ["string"] }, { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, { "open": "`", "close": "`", "notIn": ["string", "comment"] } ] diff --git a/extensions/json/package.json b/extensions/json/package.json index c694c60267..2f36b9bfd0 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -1,24 +1,13 @@ { "name": "json", "displayName": "%displayName%", - "description": "%description%", + "description": "%description%", "version": "1.0.0", "publisher": "vscode", - "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "engines": { "vscode": "0.10.x" }, - "icon": "icons/json.png", - "activationEvents": [ - "onLanguage:json", - "onLanguage:jsonc" - ], - "enableProposedApi": true, - "main": "./client/out/jsonMain", "scripts": { - "compile": "gulp compile-extension:json-client && gulp compile-extension:json-server", - "postinstall": "cd server && yarn install", - "install-client-next": "yarn add vscode-languageclient@next", "update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-JSON.tmLanguage JSON.tmLanguage ./syntaxes/JSON.tmLanguage.json" }, "contributes": { @@ -88,93 +77,6 @@ "fileMatch": "*.schema.json", "url": "http://json-schema.org/draft-04/schema#" } - ], - "configuration": { - "id": "json", - "order": 20, - "type": "object", - "title": "JSON", - "properties": { - "json.schemas": { - "type": "array", - "scope": "resource", - "description": "%json.schemas.desc%", - "items": { - "type": "object", - "default": { - "fileMatch": [ - "/myfile" - ], - "url": "schemaURL" - }, - "properties": { - "url": { - "type": "string", - "default": "/user.schema.json", - "description": "%json.schemas.url.desc%" - }, - "fileMatch": { - "type": "array", - "items": { - "type": "string", - "default": "MyFile.json", - "description": "%json.schemas.fileMatch.item.desc%" - }, - "minItems": 1, - "description": "%json.schemas.fileMatch.desc%" - }, - "schema": { - "$ref": "http://json-schema.org/draft-04/schema#", - "description": "%json.schemas.schema.desc%" - } - } - } - }, - "json.format.enable": { - "type": "boolean", - "scope": "window", - "default": true, - "description": "%json.format.enable.desc%" - }, - "json.trace.server": { - "type": "string", - "scope": "window", - "enum": [ - "off", - "messages", - "verbose" - ], - "default": "off", - "description": "%json.tracing.desc%" - }, - "json.colorDecorators.enable": { - "type": "boolean", - "scope": "window", - "default": true, - "description": "%json.colorDecorators.enable.desc%", - "deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%" - }, - "json.experimental.syntaxFolding": { - "type": "boolean", - "default": false, - "description": "%json.experimental.syntaxFolding%" - } - } - }, - "configurationDefaults": { - "[json]": { - "editor.quickSuggestions": { - "strings": true - } - } - } - }, - "dependencies": { - "vscode-extension-telemetry": "0.0.15", - "vscode-languageclient": "4.0.0-next.9", - "vscode-nls": "^3.2.1" - }, - "devDependencies": { - "@types/node": "7.0.43" + ] } } diff --git a/extensions/json/package.nls.json b/extensions/json/package.nls.json index 3d268d7391..6307b6dcab 100644 --- a/extensions/json/package.nls.json +++ b/extensions/json/package.nls.json @@ -1,14 +1,4 @@ { - "displayName": "JSON Language Features", - "description": "Provides rich language support for JSON files.", - "json.schemas.desc": "Associate schemas to JSON files in the current project", - "json.schemas.url.desc": "A URL to a schema or a relative path to a schema in the current directory", - "json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas.", - "json.schemas.fileMatch.item.desc": "A file pattern that can contain '*' to match against when resolving JSON files to schemas.", - "json.schemas.schema.desc": "The schema definition for the given URL. The schema only needs to be provided to avoid accesses to the schema URL.", - "json.format.enable.desc": "Enable/disable default JSON formatter (requires restart)", - "json.tracing.desc": "Traces the communication between VS Code and the JSON language server.", - "json.colorDecorators.enable.desc": "Enables or disables color decorators", - "json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.", - "json.experimental.syntaxFolding": "Enables/disables syntax aware folding markers." + "displayName": "JSON Language Basics", + "description": "Provides syntax highlighting & bracket matching in JSON files." } \ No newline at end of file diff --git a/extensions/json/server/.vscode/tasks.json b/extensions/json/server/.vscode/tasks.json deleted file mode 100644 index 6a159d6a5f..0000000000 --- a/extensions/json/server/.vscode/tasks.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "version": "0.1.0", - "command": "npm", - "isShellCommand": true, - "showOutput": "silent", - "args": ["run", "watch"], - "isWatching": true, - "problemMatcher": "$tsc-watch" -} \ No newline at end of file diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json deleted file mode 100644 index c597f26e5c..0000000000 --- a/extensions/json/server/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "vscode-json-languageserver", - "description": "JSON language server", - "version": "1.0.0", - "author": "Microsoft Corporation", - "license": "MIT", - "engines": { - "node": "*" - }, - "dependencies": { - "jsonc-parser": "^1.0.1", - "request-light": "^0.2.2", - "vscode-json-languageservice": "^3.0.7", - "vscode-languageserver": "4.0.0-next.3", - "vscode-nls": "^3.2.1", - "vscode-uri": "^1.0.1" - }, - "devDependencies": { - "@types/node": "7.0.43" - }, - "scripts": { - "compile": "gulp compile-extension:json-server", - "watch": "gulp watch-extension:json-server", - "install-service-next": "yarn add vscode-json-languageservice@next", - "install-service-local": "yarn link vscode-json-languageservice", - "install-server-next": "yarn add vscode-languageserver@next", - "install-server-local": "yarn link vscode-languageserver-server" - } -} diff --git a/extensions/json/server/src/protocol/foldingProvider.proposed.ts b/extensions/json/server/src/protocol/foldingProvider.proposed.ts deleted file mode 100644 index 8906dc5aae..0000000000 --- a/extensions/json/server/src/protocol/foldingProvider.proposed.ts +++ /dev/null @@ -1,89 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TextDocumentIdentifier } from 'vscode-languageserver-types'; -import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol'; - -// ---- capabilities - -export interface FoldingProviderClientCapabilities { - /** - * The text document client capabilities - */ - textDocument?: { - /** - * Capabilities specific to the foldingProvider - */ - foldingProvider?: { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)` - * return value for the corresponding server capability as well. - */ - dynamicRegistration?: boolean; - }; - }; -} - -export interface FoldingProviderOptions { -} - -export interface FoldingProviderServerCapabilities { - /** - * The server provides folding provider support. - */ - foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions); -} - -export interface FoldingRangeList { - /** - * The folding ranges. - */ - ranges: FoldingRange[]; -} - -export enum FoldingRangeType { - /** - * Folding range for a comment - */ - Comment = 'comment', - /** - * Folding range for a imports or includes - */ - Imports = 'imports', - /** - * Folding range for a region (e.g. `#region`) - */ - Region = 'region' -} - -export interface FoldingRange { - - /** - * The start line number - */ - startLine: number; - - /** - * The end line number - */ - endLine: number; - - /** - * The actual color value for this folding range. - */ - type?: FoldingRangeType | string; -} - -export interface FoldingRangeRequestParam { - /** - * The text document. - */ - textDocument: TextDocumentIdentifier; -} - -export namespace FoldingRangesRequest { - export const type: RequestType = new RequestType('textDocument/foldingRanges'); -} diff --git a/extensions/json/server/src/utils/errors.ts b/extensions/json/server/src/utils/errors.ts deleted file mode 100644 index 507e8a7bf6..0000000000 --- a/extensions/json/server/src/utils/errors.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -export function formatError(message: string, err: any): string { - if (err instanceof Error) { - let error = err; - return `${message}: ${error.message}\n${error.stack}`; - } else if (typeof err === 'string') { - return `${message}: ${err}`; - } else if (err) { - return `${message}: ${err.toString()}`; - } - return message; -} - -export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessage: string): Thenable { - let t = func(); - return t.then(void 0, e => { - console.error(formatError(errorMessage, e)); - return errorVal; - }); -} -export function runSafe(func: () => T, errorVal: T, errorMessage: string): T { - try { - return func(); - } catch (e) { - console.error(formatError(errorMessage, e)); - return errorVal; - } -} \ No newline at end of file diff --git a/extensions/markdown-basics/package.json b/extensions/markdown-basics/package.json index d2425177be..8583ba0c8b 100644 --- a/extensions/markdown-basics/package.json +++ b/extensions/markdown-basics/package.json @@ -7,9 +7,6 @@ "engines": { "vscode": "^1.20.0" }, - "categories": [ - "Languages" - ], "contributes": { "languages": [ { diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index 7d7d9a5391..820134b366 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/07f55fa7c0dcdbfeb21b8970255e96dd9c00b6bb", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/e667795f83c83e36dc6f90bde14632a963c52e34", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -1668,14 +1668,103 @@ "name": "markup.fenced_code.block.markdown" }, "heading": { - "begin": "(?:^|\\G)[ ]{0,3}(#{1,6})\\s*(?=[\\S[^#]])", + "match": "(?:^|\\G)[ ]{0,3}((#{1,6})\\s*(?=[\\S[^#]]).*?\\s*(#{1,6})?)$\\n?", "captures": { "1": { - "name": "punctuation.definition.heading.markdown" + "patterns": [ + { + "match": "(#{6})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.6.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + }, + { + "match": "(#{5})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.5.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + }, + { + "match": "(#{4})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.4.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + }, + { + "match": "(#{3})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.3.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + }, + { + "match": "(#{2})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.2.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + }, + { + "match": "(#{1})\\s*(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "name": "heading.1.markdown", + "captures": { + "1": { + "name": "punctuation.definition.heading.markdown" + }, + "2": { + "name": "entity.name.section.markdown" + }, + "3": { + "name": "punctuation.definition.heading.markdown" + } + } + } + ] } }, - "contentName": "entity.name.section.markdown", - "end": "\\s*(#{1,6})?$\\n?", "name": "markup.heading.markdown", "patterns": [ { @@ -1933,7 +2022,7 @@ "name": "meta.other.valid-ampersand.markdown" }, "bold": { - "begin": "(?x)\n (\\*\\*|__)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?`+)([^`]|(?!(?(?!`))`)*+\\k\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (? # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whitespace\n ? # URL\n [ \\t]*+ # Optional whitespace\n ( # Optional Title\n (?['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)\\1 # Close\n )\n", + "begin": "(?x)\n ((?<!\\w)\\*\\*\\b|\\b__)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whitespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whitespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=__\\b|\\*\\*)\\1 # Close\n )\n", "captures": { "1": { "name": "punctuation.definition.bold.markdown" @@ -2075,7 +2164,7 @@ "name": "meta.image.reference.markdown" }, "italic": { - "begin": "(?x) (\\*\\b|\\b_)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whtiespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whtiespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | \\1\\1 # Must be bold closer\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)\\1 # Close\n )\n", + "begin": "(?x) (\\*\\b|\\b_)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whtiespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whtiespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | \\1\\1 # Must be bold closer\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=_\\b|\\*)\\1 # Close\n )\n", "captures": { "1": { "name": "punctuation.definition.italic.markdown" diff --git a/extensions/markdown-basics/test/colorize-results/test-33886_md.json b/extensions/markdown-basics/test/colorize-results/test-33886_md.json index ed8d6a43aa..185d172e8a 100644 --- a/extensions/markdown-basics/test/colorize-results/test-33886_md.json +++ b/extensions/markdown-basics/test/colorize-results/test-33886_md.json @@ -1,7 +1,7 @@ [ { "c": "#", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -12,7 +12,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -23,7 +23,7 @@ }, { "c": "h", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -177,7 +177,7 @@ }, { "c": "#", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -188,7 +188,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -199,7 +199,7 @@ }, { "c": "h", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -298,7 +298,7 @@ }, { "c": "#", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -309,7 +309,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -320,7 +320,7 @@ }, { "c": "h", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", diff --git a/extensions/markdown-basics/test/colorize-results/test_md.json b/extensions/markdown-basics/test/colorize-results/test_md.json index a3dd8829df..eb09a71c81 100644 --- a/extensions/markdown-basics/test/colorize-results/test_md.json +++ b/extensions/markdown-basics/test/colorize-results/test_md.json @@ -1,7 +1,7 @@ [ { "c": "#", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -12,7 +12,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -23,7 +23,7 @@ }, { "c": "Header 1", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -33,19 +33,8 @@ } }, { - "c": " ", - "t": "text.html.markdown markup.heading.markdown", - "r": { - "dark_plus": "markup.heading: #569CD6", - "light_plus": "markup.heading: #800000", - "dark_vs": "markup.heading: #569CD6", - "light_vs": "markup.heading: #800000", - "hc_black": "markup.heading: #6796E6" - } - }, - { - "c": "#", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "c": " #", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -56,7 +45,7 @@ }, { "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -67,7 +56,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -78,7 +67,7 @@ }, { "c": "Header 2", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -88,19 +77,8 @@ } }, { - "c": " ", - "t": "text.html.markdown markup.heading.markdown", - "r": { - "dark_plus": "markup.heading: #569CD6", - "light_plus": "markup.heading: #800000", - "dark_vs": "markup.heading: #569CD6", - "light_vs": "markup.heading: #800000", - "hc_black": "markup.heading: #6796E6" - } - }, - { - "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "c": " ##", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -111,7 +89,7 @@ }, { "c": "###", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -122,7 +100,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -133,7 +111,7 @@ }, { "c": "Header 3 ### (Hashes on right are optional)", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -144,7 +122,7 @@ }, { "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -155,7 +133,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -166,7 +144,7 @@ }, { "c": "Markdown plus h2 with a custom ID ## {#id-goes-here}", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -243,7 +221,7 @@ }, { "c": "###", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -254,7 +232,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -265,7 +243,7 @@ }, { "c": "Alternate heading styles:", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2025,7 +2003,7 @@ }, { "c": "###", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2036,7 +2014,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2047,7 +2025,7 @@ }, { "c": "Horizontal rules", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.3.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2201,7 +2179,7 @@ }, { "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2212,7 +2190,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2223,7 +2201,7 @@ }, { "c": "Markdown plus tables", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2233,19 +2211,8 @@ } }, { - "c": " ", - "t": "text.html.markdown markup.heading.markdown", - "r": { - "dark_plus": "markup.heading: #569CD6", - "light_plus": "markup.heading: #800000", - "dark_vs": "markup.heading: #569CD6", - "light_vs": "markup.heading: #800000", - "hc_black": "markup.heading: #6796E6" - } - }, - { - "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "c": " ##", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2366,7 +2333,7 @@ }, { "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2377,7 +2344,7 @@ }, { "c": " ", - "t": "text.html.markdown markup.heading.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2388,7 +2355,7 @@ }, { "c": "Markdown plus definition lists", - "t": "text.html.markdown markup.heading.markdown entity.name.section.markdown", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown entity.name.section.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", @@ -2398,19 +2365,8 @@ } }, { - "c": " ", - "t": "text.html.markdown markup.heading.markdown", - "r": { - "dark_plus": "markup.heading: #569CD6", - "light_plus": "markup.heading: #800000", - "dark_vs": "markup.heading: #569CD6", - "light_vs": "markup.heading: #800000", - "hc_black": "markup.heading: #6796E6" - } - }, - { - "c": "##", - "t": "text.html.markdown markup.heading.markdown punctuation.definition.heading.markdown", + "c": " ##", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", "light_plus": "markup.heading: #800000", diff --git a/extensions/markdown/.vscodeignore b/extensions/markdown/.vscodeignore deleted file mode 100644 index ebab1d50b9..0000000000 --- a/extensions/markdown/.vscodeignore +++ /dev/null @@ -1,3 +0,0 @@ -test/** -src/** -tsconfig.json \ No newline at end of file diff --git a/extensions/markdown/OSSREADME.json b/extensions/markdown/OSSREADME.json deleted file mode 100644 index 33c460e00c..0000000000 --- a/extensions/markdown/OSSREADME.json +++ /dev/null @@ -1,38 +0,0 @@ -// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: -[ -{ - "name": "chriskempson/tomorrow-theme", - "version": "0.0.0", - "license": "MIT", - "repositoryURL": "https://github.com/chriskempson/tomorrow-theme", - "licenseDetail": [ - "Copyright (C) 2013 Chris Kempson", - "", - "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." - ] -}, -{ - "name": "textmate/markdown.tmbundle", - "version": "0.0.0", - "license": "TextMate Bundle License", - "repositoryURL": "https://github.com/textmate/markdown.tmbundle", - "licenseDetail": [ - "Copyright (c) markdown.tmbundle authors", - "", - "If not otherwise specified (see below), files in this repository fall under the following license:", - "", - "Permission to copy, use, modify, sell and distribute this", - "software is granted. This software is provided \"as is\" without", - "express or implied warranty, and with no claim as to its", - "suitability for any purpose.", - "", - "An exception is made for files in readable text which contain their own license information,", - "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added", - "to the base-name name of the original file, and an extension of txt, html, or similar. For example", - "\"tidy\" is accompanied by \"tidy-license.txt\"." - ] -}] diff --git a/extensions/markdown/icon.png b/extensions/markdown/icon.png deleted file mode 100644 index 48e0f035e7b173d9ab2b97ed88655f27ba24cfc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1218 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+SW-M)978H@y_sw1C+#TGcARtXcNRnS4M$lyL>x68xmG%@ zQV|vOxZx@?;YF?sW2nQXmX!+Z9UhE|p_2}6@^2_+yq&6*KHpGi)3pt|=S9Bn+3#P~ z8~J|L_qy|cK9?m-Wdgbb2VnpB=f>B?@7()0D7|W)Rry$~{&K$==T@^@%~Hn}c`?oH z%$k#L*IBI1<lf|SAbWGO<&nexEL@NGTiWNn+y6u5!2#Z`_iJX}m#8!JU^w0Q{+mr{ zW#!7My>b&DO_1_j>$X8Ajq3&L-eA8y8#WyHeu8P;x^-6`J$kf4K0S%k;R@@w2`5vW zI3IAXoRufQz{J49z`-EEpuph3U=Vs{hQ-UUl}l#zroDKqJ#~}Tlh3#8k9)3NmbLZr zh2!hj?hVYpeod{cHn`Fwh9T&W{PpV#`|G#<iu(KWuXp9mHQUZ#$S}LQ`@6i--t@Y< zxNNzowfiT2y70DSSut0})~Kwj;*EM%ch^;I+;Zec-emR(`CUG;RudkTTg9%*p3P}v zVe#ht?8gd+>y(@RJ1}T2e$mflRDaww_AwU+qmP8-uA?HSZ1Qe>arFAl5a_G8?7ShP zi)rf&J9buqYa&U%WW)|6FB7<I&dMZ_%4Jv^tkj?o-0^a@5hKrRC!hItX*s_(Byl}; z6JD0j<=*gHnbBt>!vROeinwd5J}WVtt+BN>4*KJ@)2B68pyADto2#d6?anfrzWC6# zHB5Hv)_=ddx9{A%4o{cT+ye%3GIDKkO>TStdA_}3zSG`WcJ^u8%bV&ALr**06uFsU zb}Z_dXON4}vJ+{WvsOnK6}{W=X!^^yzmK+7uV%O@qUBs3^Epi8$!{g2PL4M}UYvIM zta9}F)@qB=(+B3*=N~t0RhqT0V$-v^`#TcW8%Z{6KDxZK)MjdJgT=CduKC^<zMM2! z{5hZFkXZb8)8N}2U6USIUpDW|PYzPLar2&8(b|x5rr-6N!6*E$d}$RtSbX@=<oku` zzc=r$ZP>BQfb+6=+vm@l-CJjcU7q=?nsKpD;-qEzJpsSZ#cbwyQnM^vChQImmr<+d zY`e?eHx@j49rZd|zacT$Li4hC+LlR+dbOK&KT<c`6}eT><yp1oCl%lOi;teZFQ)%) zovPsZj~4@zf@g>RW>nE!c4tGL;E|oemDeBneyV5Lpm^lLCEZnx-n)KqC@>1Pyv=x( z_fe@qWY+ceuK6X=l8h=RoLSATK5}Ky6ggOM`bJ8(IOCEDzjYs*ywNte#(qNl(@Kwu zYoC?wu9%n`wru*wM_;;+25EKae>lM5{;*N7fgLFoH!vt{V|Y@yB!N9JOH`#{_5$Yc zurPr})uYp+dLO8rvHW&5*Lp^Q{<rpS*((O~zAj#uH{YE9ox=IWGo|HN=k-~9m@lt? za%OPNr^nG#%tIuNfVnZ|YR<2VYK_<2ssj#h6wu#b{ee~GYTpX}thRn;99f)!p`iai a6A#0oUpAZKviVv;$~;~DT-G@yGywoe+8dex diff --git a/extensions/markdown/media/Preview.svg b/extensions/markdown/media/Preview.svg deleted file mode 100644 index c60599eda4..0000000000 --- a/extensions/markdown/media/Preview.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{fill:#f6f6f6}.st1{fill:none}.st2{fill:#424242}.st3{fill:#f0eff1}</style><path class="st0" d="M11.949 4C11.697 1.756 9.811 0 7.5 0A4.505 4.505 0 0 0 3 4.5c0 .6.12 1.188.35 1.735L0 9.586v.828l2 2 3-2.999V16h11V4h-4.051z" id="outline" style="display: none;"/><g id="icon_x5F_bg"><circle class="st1" cx="7.5" cy="4.5" r="2.5"/><path class="st2" d="M12 10h1v3h-1zM10 11h1v2h-1zM8 12h1v1H8zM8 9h2v1H8z"/><path class="st2" d="M11.949 5a4.431 4.431 0 0 1-.226 1H14v8H7V8.95a4.447 4.447 0 0 1-1-.227V15h9V5h-3.051z"/><path class="st2" d="M10.294 8H12V7h-.762a4.527 4.527 0 0 1-.944 1zM11 4.5a3.5 3.5 0 1 0-7 0c0 .711.215 1.369.579 1.922L1 10l1 1 3.579-3.578A3.485 3.485 0 0 0 7.5 8 3.5 3.5 0 0 0 11 4.5zm-6 0a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0z"/></g><g id="icon_x5F_fg"><path class="st1" d="M10 11h1v2h-1zM8 12h1v1H8zM8 9h2v1H8zM12 10h1v3h-1z"/><path class="st3" d="M11.724 6a4.469 4.469 0 0 1-.485 1H12v1h-1.706c-.771.616-1.733 1-2.794 1-.169 0-.333-.031-.5-.05V14h7V6h-2.276zM8 9h2v1H8V9zm1 4H8v-1h1v1zm2 0h-1v-2h1v2zm2 0h-1v-3h1v3z"/><circle class="st3" cx="7.5" cy="4.5" r="2.5"/></g></svg> \ No newline at end of file diff --git a/extensions/markdown/media/PreviewOnRightPane_16x.svg b/extensions/markdown/media/PreviewOnRightPane_16x.svg deleted file mode 100644 index eefaadfcc7..0000000000 --- a/extensions/markdown/media/PreviewOnRightPane_16x.svg +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> -<style type="text/css"> - .icon_x002D_vs_x002D_bg{fill:#424242;} -</style> -<g id="canvas"> -</g> -<g id="outline"> -</g> -<g id="iconFg"> -</g> -<g id="iconBg"> - <path class="icon_x002D_vs_x002D_bg" d="M9,5h5v2.4c0.4,0.2,0.7,0.4,1,0.7V2H1v12h5.6L9,11.6V5z M2,13V5h5v8H2z M11.3,12.7 - c0.4,0.2,0.8,0.3,1.2,0.3c1.4,0,2.5-1.1,2.5-2.5C15,9.1,13.9,8,12.5,8C11.1,8,10,9.1,10,10.5c0,0.4,0.1,0.8,0.3,1.2L8,14l1,1 - L11.3,12.7z M11,10.5C11,9.7,11.7,9,12.5,9c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5C11.7,12,11,11.3,11,10.5z"/> -</g> -</svg> diff --git a/extensions/markdown/media/PreviewOnRightPane_16x_dark.svg b/extensions/markdown/media/PreviewOnRightPane_16x_dark.svg deleted file mode 100644 index c18634bbaf..0000000000 --- a/extensions/markdown/media/PreviewOnRightPane_16x_dark.svg +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> -<style type="text/css"> - .st0{fill:#C5C5C5;} -</style> -<g id="canvas"> -</g> -<g id="outline"> -</g> -<g id="iconFg"> -</g> -<g id="iconBg"> - <path class="st0" d="M9,5h5v2.4c0.4,0.2,0.7,0.4,1,0.7V2H1v12h5.6L9,11.6V5z M2,13V5h5v8H2z M11.3,12.7c0.4,0.2,0.8,0.3,1.2,0.3 - c1.4,0,2.5-1.1,2.5-2.5C15,9.1,13.9,8,12.5,8C11.1,8,10,9.1,10,10.5c0,0.4,0.1,0.8,0.3,1.2L8,14l1,1L11.3,12.7z M11,10.5 - C11,9.7,11.7,9,12.5,9c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5C11.7,12,11,11.3,11,10.5z"/> -</g> -</svg> diff --git a/extensions/markdown/media/Preview_inverse.svg b/extensions/markdown/media/Preview_inverse.svg deleted file mode 100644 index 87700309c0..0000000000 --- a/extensions/markdown/media/Preview_inverse.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{fill:#2d2d30}.st1{fill:none}.st2{fill:#c5c5c5}.st3{fill:#2b282e}</style><path class="st0" d="M11.949 4C11.697 1.756 9.811 0 7.5 0A4.505 4.505 0 0 0 3 4.5c0 .6.12 1.188.35 1.735L0 9.586v.828l2 2 3-2.999V16h11V4h-4.051z" id="outline" style="display: none;"/><g id="icon_x5F_bg"><circle class="st1" cx="7.5" cy="4.5" r="2.5"/><path class="st2" d="M12 10h1v3h-1zM10 11h1v2h-1zM8 12h1v1H8zM8 9h2v1H8z"/><path class="st2" d="M11.949 5a4.431 4.431 0 0 1-.226 1H14v8H7V8.95a4.447 4.447 0 0 1-1-.227V15h9V5h-3.051z"/><path class="st2" d="M10.294 8H12V7h-.762a4.527 4.527 0 0 1-.944 1zM11 4.5a3.5 3.5 0 1 0-7 0c0 .711.215 1.369.579 1.922L1 10l1 1 3.579-3.578A3.485 3.485 0 0 0 7.5 8 3.5 3.5 0 0 0 11 4.5zm-6 0a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0z"/></g><g id="icon_x5F_fg"><path class="st1" d="M10 11h1v2h-1zM8 12h1v1H8zM8 9h2v1H8zM12 10h1v3h-1z"/><path class="st3" d="M11.724 6a4.469 4.469 0 0 1-.485 1H12v1h-1.706c-.771.616-1.733 1-2.794 1-.169 0-.333-.031-.5-.05V14h7V6h-2.276zM8 9h2v1H8V9zm1 4H8v-1h1v1zm2 0h-1v-2h1v2zm2 0h-1v-3h1v3z"/><circle class="st3" cx="7.5" cy="4.5" r="2.5"/></g></svg> \ No newline at end of file diff --git a/extensions/markdown/media/ViewSource.svg b/extensions/markdown/media/ViewSource.svg deleted file mode 100644 index fccdf83d46..0000000000 --- a/extensions/markdown/media/ViewSource.svg +++ /dev/null @@ -1,3 +0,0 @@ -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ - <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> -]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><polygon fill="#656565" points="10,2 7.414,2 8.414,3 9,3 9,3.586 9,4 9,4.414 9,6 12,6 12,13 4,13 4,8 3,8 3,14 13,14 13,5"/><polygon fill="#00539C" points="5,1 3,1 5,3 1,3 1,5 5,5 3,7 5,7 8,4"/></svg> \ No newline at end of file diff --git a/extensions/markdown/media/csp.js b/extensions/markdown/media/csp.js deleted file mode 100644 index 15d5e33b67..0000000000 --- a/extensions/markdown/media/csp.js +++ /dev/null @@ -1,49 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -(function () { - const settings = JSON.parse(document.getElementById('vscode-markdown-preview-data').getAttribute('data-settings')); - const strings = JSON.parse(document.getElementById('vscode-markdown-preview-data').getAttribute('data-strings')); - - let didShow = false; - - const showCspWarning = () => { - if (didShow || settings.disableSecurityWarnings) { - return; - } - didShow = true; - - const notification = document.createElement('a'); - notification.innerText = strings.cspAlertMessageText; - notification.setAttribute('id', 'code-csp-warning'); - notification.setAttribute('title', strings.cspAlertMessageTitle); - - notification.setAttribute('role', 'button'); - notification.setAttribute('aria-label', strings.cspAlertMessageLabel); - notification.onclick = () => { - window.parent.postMessage({ - type: 'command', - source: settings.source, - body: { - command: 'markdown.showPreviewSecuritySelector', - args: [settings.source] - } - }, '*'); - }; - document.body.appendChild(notification); - }; - - document.addEventListener('securitypolicyviolation', () => { - showCspWarning(); - }); - - window.addEventListener('message', (event) => { - if (event && event.data && event.data.name === 'vscode-did-block-svg') { - showCspWarning(); - } - }); -}()); \ No newline at end of file diff --git a/extensions/markdown/media/loading.js b/extensions/markdown/media/loading.js deleted file mode 100644 index 9790347215..0000000000 --- a/extensions/markdown/media/loading.js +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -// @ts-check - -'use strict'; - -(function () { - const unloadedStyles = []; - - const settings = JSON.parse(document.getElementById('vscode-markdown-preview-data').getAttribute('data-settings')); - - const onStyleLoadError = (event) => { - const source = event.target.dataset.source; - unloadedStyles.push(source); - }; - - window.addEventListener('DOMContentLoaded', () => { - for (const link of document.getElementsByClassName('code-user-style')) { - if (link.dataset.source) { - link.onerror = onStyleLoadError; - } - } - }) - - window.addEventListener('load', () => { - if (!unloadedStyles.length) { - return; - } - window.parent.postMessage({ - type: 'command', - source: settings.source, - body: { - command: '_markdown.onPreviewStyleLoadError', - args: [unloadedStyles] - } - }, '*'); - }); -}()); \ No newline at end of file diff --git a/extensions/markdown/media/main.js b/extensions/markdown/media/main.js deleted file mode 100644 index c6316e35fe..0000000000 --- a/extensions/markdown/media/main.js +++ /dev/null @@ -1,344 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -// @ts-check -'use strict'; - -(function () { - // From https://remysharp.com/2010/07/21/throttling-function-calls - function throttle(fn, threshhold, scope) { - threshhold || (threshhold = 250); - var last, deferTimer; - return function () { - var context = scope || this; - - var now = +new Date, - args = arguments; - if (last && now < last + threshhold) { - // hold on to it - clearTimeout(deferTimer); - deferTimer = setTimeout(function () { - last = now; - fn.apply(context, args); - }, threshhold + last - now); - } else { - last = now; - fn.apply(context, args); - } - }; - } - - /** - * @param {number} min - * @param {number} max - * @param {number} value - */ - function clamp(min, max, value) { - return Math.min(max, Math.max(min, value)); - } - - /** - * @param {number} line - */ - function clampLine(line) { - return clamp(0, settings.lineCount - 1, line); - } - - /** - * Post a message to the markdown extension - * - * @param {string} type - * @param {object} body - */ - function postMessage(type, body) { - window.parent.postMessage({ - type, - source: settings.source, - body - }, '*'); - } - - /** - * Post a command to be executed to the markdown extension - * - * @param {string} command - * @param {any[]} args - */ - function postCommand(command, args) { - postMessage('command', { command, args }); - } - - /** - * @typedef {{ element: Element, line: number }} CodeLineElement - */ - - /** - * @return {CodeLineElement[]} - */ - const getCodeLineElements = (() => { - /** @type {CodeLineElement[]} */ - let elements; - return () => { - if (!elements) { - elements = Array.prototype.map.call( - document.getElementsByClassName('code-line'), - element => { - const line = +element.getAttribute('data-line'); - return { element, line } - }) - .filter(x => !isNaN(x.line)); - } - return elements; - }; - })() - - /** - * Find the html elements that map to a specific target line in the editor. - * - * If an exact match, returns a single element. If the line is between elements, - * returns the element prior to and the element after the given line. - * - * @param {number} targetLine - * - * @returns {{ previous: CodeLineElement, next?: CodeLineElement }} - */ - function getElementsForSourceLine(targetLine) { - const lineNumber = Math.floor(targetLine) - const lines = getCodeLineElements(); - let previous = lines[0] || null; - for (const entry of lines) { - if (entry.line === lineNumber) { - return { previous: entry, next: null }; - } else if (entry.line > lineNumber) { - return { previous, next: entry }; - } - previous = entry; - } - return { previous }; - } - - /** - * Find the html elements that are at a specific pixel offset on the page. - * - * @returns {{ previous: CodeLineElement, next?: CodeLineElement }} - */ - function getLineElementsAtPageOffset(offset) { - const lines = getCodeLineElements() - - const position = offset - window.scrollY; - - let lo = -1; - let hi = lines.length - 1; - while (lo + 1 < hi) { - const mid = Math.floor((lo + hi) / 2); - const bounds = lines[mid].element.getBoundingClientRect(); - if (bounds.top + bounds.height >= position) { - hi = mid; - } else { - lo = mid; - } - } - - const hiElement = lines[hi]; - const hiBounds = hiElement.element.getBoundingClientRect(); - - if (hi >= 1 && hiBounds.top > position) { - const loElement = lines[lo]; - return { previous: loElement, next: hiElement }; - } - - return { previous: hiElement }; - } - - /** - * Attempt to reveal the element for a source line in the editor. - * - * @param {number} line - */ - function scrollToRevealSourceLine(line) { - const { previous, next } = getElementsForSourceLine(line); - if (previous && settings.scrollPreviewWithEditor) { - let scrollTo = 0; - const rect = previous.element.getBoundingClientRect(); - const previousTop = rect.top; - - if (next && next.line !== previous.line) { - // Between two elements. Go to percentage offset between them. - const betweenProgress = (line - previous.line) / (next.line - previous.line); - const elementOffset = next.element.getBoundingClientRect().top - previousTop; - scrollTo = previousTop + betweenProgress * elementOffset; - } else { - scrollTo = previousTop; - } - - window.scroll(0, Math.max(1, window.scrollY + scrollTo)); - } - } - - /** - * @param {number} offset - */ - function getEditorLineNumberForPageOffset(offset) { - const { previous, next } = getLineElementsAtPageOffset(offset); - if (previous) { - const previousBounds = previous.element.getBoundingClientRect(); - const offsetFromPrevious = (offset - window.scrollY - previousBounds.top); - - if (next) { - const progressBetweenElements = offsetFromPrevious / (next.element.getBoundingClientRect().top - previousBounds.top); - const line = previous.line + progressBetweenElements * (next.line - previous.line); - return clampLine(line); - } else { - const progressWithinElement = offsetFromPrevious / (previousBounds.height); - const line = previous.line + progressWithinElement; - return clampLine(line); - } - } - return null; - } - - class ActiveLineMarker { - onDidChangeTextEditorSelection(line) { - const { previous } = getElementsForSourceLine(line); - this._update(previous && previous.element); - } - - _update(before) { - this._unmarkActiveElement(this._current); - this._markActiveElement(before); - this._current = before; - } - - _unmarkActiveElement(element) { - if (!element) { - return; - } - element.className = element.className.replace(/\bcode-active-line\b/g); - } - - _markActiveElement(element) { - if (!element) { - return; - } - element.className += ' code-active-line'; - } - } - - var scrollDisabled = true; - const marker = new ActiveLineMarker(); - const settings = JSON.parse(document.getElementById('vscode-markdown-preview-data').getAttribute('data-settings')); - - function onLoad() { - if (settings.scrollPreviewWithEditor) { - setTimeout(() => { - const initialLine = +settings.line; - if (!isNaN(initialLine)) { - scrollDisabled = true; - scrollToRevealSourceLine(initialLine); - } - }, 0); - } - } - - const onUpdateView = (() => { - const doScroll = throttle(line => { - scrollDisabled = true; - scrollToRevealSourceLine(line); - }, 50); - - return (line, settings) => { - if (!isNaN(line)) { - settings.line = line; - doScroll(line); - } - }; - })(); - - - if (document.readyState === 'loading' || document.readyState === 'uninitialized') { - document.addEventListener('DOMContentLoaded', onLoad); - } else { - onLoad(); - } - - - window.addEventListener('resize', () => { - scrollDisabled = true; - }, true); - - window.addEventListener('message', event => { - if (event.data.source !== settings.source) { - return; - } - - switch (event.data.type) { - case 'onDidChangeTextEditorSelection': - marker.onDidChangeTextEditorSelection(event.data.line); - break; - - case 'updateView': - onUpdateView(event.data.line, settings); - break; - } - }, false); - - document.addEventListener('dblclick', event => { - if (!settings.doubleClickToSwitchToEditor) { - return; - } - - // Ignore clicks on links - for (let node = /** @type {HTMLElement} */(event.target); node; node = /** @type {HTMLElement} */(node.parentNode)) { - if (node.tagName === "A") { - return; - } - } - - const offset = event.pageY; - const line = getEditorLineNumberForPageOffset(offset); - if (!isNaN(line)) { - postMessage('didClick', { line }); - } - }); - - document.addEventListener('click', event => { - if (!event) { - return; - } - - const baseElement = document.getElementsByTagName('base')[0]; - - /** @type {*} */ - let node = event.target; - while (node) { - if (node.tagName && node.tagName === 'A' && node.href) { - if (node.getAttribute('href').startsWith('#')) { - break; - } - if (node.href.startsWith('file://') || node.href.startsWith('vscode-workspace-resource:')) { - const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-workspace-resource:)/i, '').split('#'); - postCommand('_markdown.openDocumentLink', [{ path, fragment }]); - event.preventDefault(); - event.stopPropagation(); - break; - } - break; - } - node = node.parentNode; - } - }, true); - - if (settings.scrollEditorWithPreview) { - window.addEventListener('scroll', throttle(() => { - if (scrollDisabled) { - scrollDisabled = false; - } else { - const line = getEditorLineNumberForPageOffset(window.scrollY); - if (!isNaN(line)) { - postMessage('revealLine', { line }); - } - } - }, 50)); - } -}()); diff --git a/extensions/markdown/media/markdown.css b/extensions/markdown/media/markdown.css deleted file mode 100644 index 4e1cf15fdc..0000000000 --- a/extensions/markdown/media/markdown.css +++ /dev/null @@ -1,266 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -body { - font-family: "Segoe WPC", "Segoe UI", "SFUIText-Light", "HelveticaNeue-Light", sans-serif, "Droid Sans Fallback"; - font-size: 14px; - padding: 0 26px; - line-height: 22px; - word-wrap: break-word; -} - -#code-csp-warning { - position: fixed; - top: 0; - right: 0; - color: white; - margin: 16px; - text-align: center; - font-size: 12px; - font-family: sans-serif; - background-color:#444444; - cursor: pointer; - padding: 6px; - box-shadow: 1px 1px 1px rgba(0,0,0,.25); -} - -#code-csp-warning:hover { - text-decoration: none; - background-color:#007acc; - box-shadow: 2px 2px 2px rgba(0,0,0,.25); -} - - -body.scrollBeyondLastLine { - margin-bottom: calc(100vh - 22px); -} - -body.showEditorSelection .code-line { - position: relative; -} - -body.showEditorSelection .code-active-line:before, -body.showEditorSelection .code-line:hover:before { - content: ""; - display: block; - position: absolute; - top: 0; - left: -12px; - height: 100%; -} - -body.showEditorSelection li.code-active-line:before, -body.showEditorSelection li.code-line:hover:before { - left: -30px; -} - -.vscode-light.showEditorSelection .code-active-line:before { - border-left: 3px solid rgba(0, 0, 0, 0.15); -} - -.vscode-light.showEditorSelection .code-line:hover:before { - border-left: 3px solid rgba(0, 0, 0, 0.40); -} - -.vscode-light.showEditorSelection .code-line .code-line:hover:before { - border-left: none; -} - -.vscode-dark.showEditorSelection .code-active-line:before { - border-left: 3px solid rgba(255, 255, 255, 0.4); -} - -.vscode-dark.showEditorSelection .code-line:hover:before { - border-left: 3px solid rgba(255, 255, 255, 0.60); -} - -.vscode-dark.showEditorSelection .code-line .code-line:hover:before { - border-left: none; -} - -.vscode-high-contrast.showEditorSelection .code-active-line:before { - border-left: 3px solid rgba(255, 160, 0, 0.7); -} - -.vscode-high-contrast.showEditorSelection .code-line:hover:before { - border-left: 3px solid rgba(255, 160, 0, 1); -} - -.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before { - border-left: none; -} - -img { - max-width: 100%; - max-height: 100%; -} - -a { - color: #4080D0; - text-decoration: none; -} - -a:focus, -input:focus, -select:focus, -textarea:focus { - outline: 1px solid -webkit-focus-ring-color; - outline-offset: -1px; -} - -hr { - border: 0; - height: 2px; - border-bottom: 2px solid; -} - -h1 { - padding-bottom: 0.3em; - line-height: 1.2; - border-bottom-width: 1px; - border-bottom-style: solid; -} - -h1, h2, h3 { - font-weight: normal; -} - -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code { - font-size: inherit; - line-height: auto; -} - -a:hover { - color: #4080D0; - text-decoration: underline; -} - -table { - border-collapse: collapse; -} - -table > thead > tr > th { - text-align: left; - border-bottom: 1px solid; -} - -table > thead > tr > th, -table > thead > tr > td, -table > tbody > tr > th, -table > tbody > tr > td { - padding: 5px 10px; -} - -table > tbody > tr + tr > td { - border-top: 1px solid; -} - -blockquote { - margin: 0 7px 0 5px; - padding: 0 16px 0 10px; - border-left: 5px solid; -} - -code { - font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"; - font-size: 14px; - line-height: 19px; -} - -body.wordWrap pre { - white-space: pre-wrap; -} - -.mac code { - font-size: 12px; - line-height: 18px; -} - -pre:not(.hljs), -pre.hljs code > div { - padding: 16px; - border-radius: 3px; - overflow: auto; -} - -/** Theming */ - -.vscode-light, -.vscode-light pre code { - color: rgb(30, 30, 30); -} - -.vscode-dark, -.vscode-dark pre code { - color: #DDD; -} - -.vscode-high-contrast, -.vscode-high-contrast pre code { - color: white; -} - -.vscode-light code { - color: #A31515; -} - -.vscode-dark code { - color: #D7BA7D; -} - -.vscode-light pre:not(.hljs), -.vscode-light code > div { - background-color: rgba(220, 220, 220, 0.4); -} - -.vscode-dark pre:not(.hljs), -.vscode-dark code > div { - background-color: rgba(10, 10, 10, 0.4); -} - -.vscode-high-contrast pre:not(.hljs), -.vscode-high-contrast code > div { - background-color: rgb(0, 0, 0); -} - -.vscode-high-contrast h1 { - border-color: rgb(0, 0, 0); -} - -.vscode-light table > thead > tr > th { - border-color: rgba(0, 0, 0, 0.69); -} - -.vscode-dark table > thead > tr > th { - border-color: rgba(255, 255, 255, 0.69); -} - -.vscode-light h1, -.vscode-light hr, -.vscode-light table > tbody > tr + tr > td { - border-color: rgba(0, 0, 0, 0.18); -} - -.vscode-dark h1, -.vscode-dark hr, -.vscode-dark table > tbody > tr + tr > td { - border-color: rgba(255, 255, 255, 0.18); -} - -.vscode-light blockquote, -.vscode-dark blockquote { - background: rgba(127, 127, 127, 0.1); - border-color: rgba(0, 122, 204, 0.5); -} - -.vscode-high-contrast blockquote { - background: transparent; - border-color: #fff; -} \ No newline at end of file diff --git a/extensions/markdown/media/tomorrow.css b/extensions/markdown/media/tomorrow.css deleted file mode 100644 index 96edd12b02..0000000000 --- a/extensions/markdown/media/tomorrow.css +++ /dev/null @@ -1,73 +0,0 @@ -/* Tomorrow Theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #8e908c; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #c82829; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #f5871f; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #eab700; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #718c00; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #4271ae; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #8959a8; -} - -.hljs { - display: block; - overflow-x: auto; - color: #4d4d4c; - padding: 0.5em; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} \ No newline at end of file diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json deleted file mode 100644 index 627e6c3e4e..0000000000 --- a/extensions/markdown/package.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "name": "markdown-language-features", - "displayName": "%displayName%", - "description": "%description%", - "version": "1.0.0", - "icon": "icon.png", - "publisher": "vscode", - "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", - "enableProposedApi": true, - "engines": { - "vscode": "^1.20.0" - }, - "main": "./out/extension", - "categories": [ - "Languages" - ], - "activationEvents": [ - "onLanguage:markdown", - "onCommand:markdown.preview.toggleLock", - "onCommand:markdown.preview.refresh", - "onCommand:markdown.showPreview", - "onCommand:markdown.showPreviewToSide", - "onCommand:markdown.showLockedPreviewToSide", - "onCommand:markdown.showSource", - "onCommand:markdown.showPreviewSecuritySelector" - ], - "contributes": { - "commands": [ - { - "command": "markdown.showPreview", - "title": "%markdown.preview.title%", - "category": "Markdown", - "icon": { - "light": "./media/Preview.svg", - "dark": "./media/Preview_inverse.svg" - } - }, - { - "command": "markdown.showPreviewToSide", - "title": "%markdown.previewSide.title%", - "category": "Markdown", - "icon": { - "light": "./media/PreviewOnRightPane_16x.svg", - "dark": "./media/PreviewOnRightPane_16x_dark.svg" - } - }, - { - "command": "markdown.showLockedPreviewToSide", - "title": "%markdown.showLockedPreviewToSide.title%", - "category": "Markdown", - "icon": { - "light": "./media/PreviewOnRightPane_16x.svg", - "dark": "./media/PreviewOnRightPane_16x_dark.svg" - } - }, - { - "command": "markdown.showSource", - "title": "%markdown.showSource.title%", - "category": "Markdown", - "icon": { - "light": "./media/ViewSource.svg", - "dark": "./media/ViewSource_inverse.svg" - } - }, - { - "command": "markdown.showPreviewSecuritySelector", - "title": "%markdown.showPreviewSecuritySelector.title%", - "category": "Markdown" - }, - { - "command": "markdown.preview.refresh", - "title": "%markdown.preview.refresh.title%", - "category": "Markdown" - }, - { - "command": "markdown.preview.toggleLock", - "title": "%markdown.preview.toggleLock.title%", - "category": "Markdown" - } - ], - "menus": { - "editor/title": [ - { - "command": "markdown.showPreviewToSide", - "when": "editorLangId == markdown", - "alt": "markdown.showPreview", - "group": "navigation" - }, - { - "command": "markdown.showSource", - "when": "markdownPreviewFocus", - "group": "navigation" - }, - { - "command": "markdown.preview.refresh", - "when": "markdownPreviewFocus", - "group": "1_markdown" - }, - { - "command": "markdown.preview.toggleLock", - "when": "markdownPreviewFocus", - "group": "1_markdown" - }, - { - "command": "markdown.showPreviewSecuritySelector", - "when": "markdownPreviewFocus", - "group": "1_markdown" - } - ], - "explorer/context": [ - { - "command": "markdown.showPreview", - "when": "resourceLangId == markdown", - "group": "navigation" - } - ], - "commandPalette": [ - { - "command": "markdown.showPreview", - "when": "editorLangId == markdown", - "group": "navigation" - }, - { - "command": "markdown.showPreviewToSide", - "when": "editorLangId == markdown", - "group": "navigation" - }, - { - "command": "markdown.showLockedPreviewToSide", - "when": "editorLangId == markdown", - "group": "navigation" - }, - { - "command": "markdown.showSource", - "when": "markdownPreviewFocus", - "group": "navigation" - }, - { - "command": "markdown.showPreviewSecuritySelector", - "when": "editorLangId == markdown" - }, - { - "command": "markdown.showPreviewSecuritySelector", - "when": "markdownPreviewFocus" - }, - { - "command": "markdown.preview.toggleLock", - "when": "markdownPreviewFocus" - } - ] - }, - "keybindings": [ - { - "command": "markdown.showPreview", - "key": "shift+ctrl+v", - "mac": "shift+cmd+v", - "when": "editorLangId == markdown" - }, - { - "command": "markdown.showPreviewToSide", - "key": "ctrl+k v", - "mac": "cmd+k v", - "when": "editorLangId == markdown" - } - ], - "configuration": { - "type": "object", - "title": "Markdown", - "order": 20, - "properties": { - "markdown.styles": { - "type": "array", - "default": [], - "description": "%markdown.styles.dec%", - "scope": "resource" - }, - "markdown.previewFrontMatter": { - "type": "string", - "enum": [ - "hide", - "show" - ], - "default": "hide", - "description": "%markdown.previewFrontMatter.dec%", - "scope": "resource" - }, - "markdown.preview.breaks": { - "type": "boolean", - "default": false, - "description": "%markdown.preview.breaks.desc%", - "scope": "resource" - }, - "markdown.preview.linkify": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.linkify%", - "scope": "resource" - }, - "markdown.preview.fontFamily": { - "type": "string", - "default": "-apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', 'HelveticaNeue-Light', 'Ubuntu', 'Droid Sans', sans-serif", - "description": "%markdown.preview.fontFamily.desc%", - "scope": "resource" - }, - "markdown.preview.fontSize": { - "type": "number", - "default": 14, - "description": "%markdown.preview.fontSize.desc%", - "scope": "resource" - }, - "markdown.preview.lineHeight": { - "type": "number", - "default": 1.6, - "description": "%markdown.preview.lineHeight.desc%", - "scope": "resource" - }, - "markdown.preview.scrollPreviewWithEditor": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.scrollPreviewWithEditor.desc%", - "scope": "resource" - }, - "markdown.preview.scrollPreviewWithEditorSelection": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.scrollPreviewWithEditorSelection.desc%", - "deprecationMessage": "%markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage%" - }, - "markdown.preview.markEditorSelection": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.markEditorSelection.desc%", - "scope": "resource" - }, - "markdown.preview.scrollEditorWithPreview": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.scrollEditorWithPreview.desc%", - "scope": "resource" - }, - "markdown.preview.doubleClickToSwitchToEditor": { - "type": "boolean", - "default": true, - "description": "%markdown.preview.doubleClickToSwitchToEditor.desc%", - "scope": "resource" - }, - "markdown.trace": { - "type": "string", - "enum": [ - "off", - "verbose" - ], - "default": "off", - "description": "%markdown.trace.desc%", - "scope": "window" - } - } - }, - "configurationDefaults": { - "[markdown]": { - "editor.wordWrap": "on", - "editor.quickSuggestions": false - } - }, - "jsonValidation": [ - { - "fileMatch": "package.json", - "url": "./schemas/package.schema.json" - } - ] - }, - "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown ./tsconfig.json" - }, - "dependencies": { - "highlight.js": "9.5.0", - "markdown-it": "^8.4.0", - "markdown-it-named-headers": "0.0.4", - "vscode-extension-telemetry": "0.0.15", - "vscode-nls": "^3.2.1" - }, - "devDependencies": { - "@types/highlight.js": "9.1.10", - "@types/markdown-it": "0.0.2", - "@types/node": "7.0.43", - "vscode": "^1.1.10" - } -} \ No newline at end of file diff --git a/extensions/markdown/package.nls.json b/extensions/markdown/package.nls.json deleted file mode 100644 index dcb40cc42b..0000000000 --- a/extensions/markdown/package.nls.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "displayName": "Markdown Language Features", - "description": "Provides rich language support for Markdown.", - "markdown.preview.breaks.desc": "Sets how line-breaks are rendered in the markdown preview. Setting it to 'true' creates a <br> for every newline.", - "markdown.preview.linkify": "Enable or disable conversion of URL-like text to links in the markdown preview.", - "markdown.preview.doubleClickToSwitchToEditor.desc": "Double click in the markdown preview to switch to the editor.", - "markdown.preview.fontFamily.desc": "Controls the font family used in the markdown preview.", - "markdown.preview.fontSize.desc": "Controls the font size in pixels used in the markdown preview.", - "markdown.preview.lineHeight.desc": "Controls the line height used in the markdown preview. This number is relative to the font size.", - "markdown.preview.markEditorSelection.desc": "Mark the current editor selection in the markdown preview.", - "markdown.preview.scrollEditorWithPreview.desc": "When a markdown preview is scrolled, update the view of the editor.", - "markdown.preview.scrollPreviewWithEditor.desc": "When a markdown editor is scrolled, update the view of the preview.", - "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Deprecated] Scrolls the markdown preview to reveal the currently selected line from the editor.", - "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "This setting has been replaced by 'markdown.preview.scrollPreviewWithEditor' and no longer has any effect.", - "markdown.preview.title" : "Open Preview", - "markdown.previewFrontMatter.dec": "Sets how YAML front matter should be rendered in the markdown preview. 'hide' removes the front matter. Otherwise, the front matter is treated as markdown content.", - "markdown.previewSide.title" : "Open Preview to the Side", - "markdown.showLockedPreviewToSide.title": "Open Locked Preview to the Side", - "markdown.showSource.title" : "Show Source", - "markdown.styles.dec": "A list of URLs or local paths to CSS style sheets to use from the markdown preview. Relative paths are interpreted relative to the folder open in the explorer. If there is no open folder, they are interpreted relative to the location of the markdown file. All '\\' need to be written as '\\\\'.", - "markdown.showPreviewSecuritySelector.title": "Change Preview Security Settings", - "markdown.trace.desc": "Enable debug logging for the markdown extension.", - "markdown.preview.refresh.title": "Refresh Preview", - "markdown.preview.toggleLock.title": "Toggle Preview Locking" -} diff --git a/extensions/markdown/schemas/package.schema.json b/extensions/markdown/schemas/package.schema.json deleted file mode 100644 index e76ce046c2..0000000000 --- a/extensions/markdown/schemas/package.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Markdown contributions to package.json", - "type": "object", - "properties": { - "contributes": { - "type": "object", - "properties": { - "markdown.previewStyles": { - "type": "array", - "description": "Contributed CSS files that change the look or layout of the Markdown preview", - "items": { - "type": "string", - "description": "Extension relative path to a css file" - } - }, - "markdown.previewScripts": { - "type": "array", - "description": "Contributed scripts that are executed in the Markdown preview", - "items": { - "type": "string", - "description": "Extension relative path to a JavaScript file" - } - }, - "markdown.markdownItPlugins": { - "type": "boolean", - "description": "Does this extension contribute a markdown-it plugin?" - } - } - } - } -} \ No newline at end of file diff --git a/extensions/markdown/src/commandManager.ts b/extensions/markdown/src/commandManager.ts deleted file mode 100644 index 174f30cd44..0000000000 --- a/extensions/markdown/src/commandManager.ts +++ /dev/null @@ -1,36 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -export interface Command { - readonly id: string; - - execute(...args: any[]): void; -} - -export class CommandManager { - private readonly commands = new Map<string, vscode.Disposable>(); - - public dispose() { - for (const registration of this.commands.values()) { - registration.dispose(); - } - this.commands.clear(); - } - - public register<T extends Command>(command: T): T { - this.registerCommand(command.id, command.execute, command); - return command; - } - - private registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) { - if (this.commands.has(id)) { - return; - } - - this.commands.set(id, vscode.commands.registerCommand(id, impl, thisArg)); - } -} \ No newline at end of file diff --git a/extensions/markdown/src/commands/index.ts b/extensions/markdown/src/commands/index.ts deleted file mode 100644 index 087f93987f..0000000000 --- a/extensions/markdown/src/commands/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export { OpenDocumentLinkCommand } from './openDocumentLink'; -export { OnPreviewStyleLoadErrorCommand } from './onPreviewStyleLoadError'; -export { ShowPreviewCommand, ShowPreviewToSideCommand, ShowLockedPreviewToSideCommand } from './showPreview'; -export { ShowSourceCommand } from './showSource'; -export { RefreshPreviewCommand } from './refreshPreview'; -export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector'; -export { MoveCursorToPositionCommand } from './moveCursorToPosition'; -export { ToggleLockCommand } from './toggleLock'; diff --git a/extensions/markdown/src/commands/moveCursorToPosition.ts b/extensions/markdown/src/commands/moveCursorToPosition.ts deleted file mode 100644 index 84be98db7f..0000000000 --- a/extensions/markdown/src/commands/moveCursorToPosition.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { Command } from '../commandManager'; - -export class MoveCursorToPositionCommand implements Command { - public readonly id = '_markdown.moveCursorToPosition'; - - public execute(line: number, character: number) { - if (!vscode.window.activeTextEditor) { - return; - } - const position = new vscode.Position(line, character); - const selection = new vscode.Selection(position, position); - vscode.window.activeTextEditor.revealRange(selection); - vscode.window.activeTextEditor.selection = selection; - } -} diff --git a/extensions/markdown/src/commands/onPreviewStyleLoadError.ts b/extensions/markdown/src/commands/onPreviewStyleLoadError.ts deleted file mode 100644 index a2d1fa4d1f..0000000000 --- a/extensions/markdown/src/commands/onPreviewStyleLoadError.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; -const localize = nls.loadMessageBundle(); - -import * as vscode from 'vscode'; - -import { Command } from '../commandManager'; - -export class OnPreviewStyleLoadErrorCommand implements Command { - public readonly id = '_markdown.onPreviewStyleLoadError'; - - public execute(resources: string[]) { - vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", resources.join(', '))); - } -} diff --git a/extensions/markdown/src/commands/openDocumentLink.ts b/extensions/markdown/src/commands/openDocumentLink.ts deleted file mode 100644 index 90532d8bea..0000000000 --- a/extensions/markdown/src/commands/openDocumentLink.ts +++ /dev/null @@ -1,74 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; - -import { Command } from '../commandManager'; -import { MarkdownEngine } from '../markdownEngine'; -import { TableOfContentsProvider } from '../tableOfContentsProvider'; -import { isMarkdownFile } from '../util/file'; - - -export interface OpenDocumentLinkArgs { - path: string; - fragment: string; -} - -export class OpenDocumentLinkCommand implements Command { - private static readonly id = '_markdown.openDocumentLink'; - public readonly id = OpenDocumentLinkCommand.id; - - public static createCommandUri( - path: string, - fragment: string - ): vscode.Uri { - return vscode.Uri.parse(`command:${OpenDocumentLinkCommand.id}?${encodeURIComponent(JSON.stringify({ path, fragment }))}`); - } - - public constructor( - private readonly engine: MarkdownEngine - ) { } - - public execute(args: OpenDocumentLinkArgs) { - return this.tryOpen(args.path, args).catch(() => { - if (path.extname(args.path) === '') { - return this.tryOpen(args.path + '.md', args); - } - const resource = vscode.Uri.file(args.path); - return Promise.resolve(void 0) - .then(() => vscode.commands.executeCommand('vscode.open', resource)) - .then(() => void 0); - }); - } - - private async tryOpen(path: string, args: OpenDocumentLinkArgs) { - if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === path) { - return this.tryRevealLine(vscode.window.activeTextEditor, args.fragment); - } else { - const resource = vscode.Uri.file(path); - return vscode.workspace.openTextDocument(resource) - .then(vscode.window.showTextDocument) - .then(editor => this.tryRevealLine(editor, args.fragment)); - } - } - - private async tryRevealLine(editor: vscode.TextEditor, fragment?: string) { - if (editor && fragment) { - const toc = new TableOfContentsProvider(this.engine, editor.document); - const entry = await toc.lookup(fragment); - if (entry) { - return editor.revealRange(new vscode.Range(entry.line, 0, entry.line, 0), vscode.TextEditorRevealType.AtTop); - } - const lineNumberFragment = fragment.match(/^L(\d+)$/); - if (lineNumberFragment) { - const line = +lineNumberFragment[1] - 1; - if (!isNaN(line)) { - return editor.revealRange(new vscode.Range(line, 0, line, 0), vscode.TextEditorRevealType.AtTop); - } - } - } - } -} diff --git a/extensions/markdown/src/commands/refreshPreview.ts b/extensions/markdown/src/commands/refreshPreview.ts deleted file mode 100644 index 338f24c3d9..0000000000 --- a/extensions/markdown/src/commands/refreshPreview.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Command } from '../commandManager'; -import { MarkdownPreviewManager } from '../features/previewManager'; - -export class RefreshPreviewCommand implements Command { - public readonly id = 'markdown.preview.refresh'; - - public constructor( - private readonly webviewManager: MarkdownPreviewManager - ) { } - - public execute() { - this.webviewManager.refresh(); - } -} \ No newline at end of file diff --git a/extensions/markdown/src/commands/showPreview.ts b/extensions/markdown/src/commands/showPreview.ts deleted file mode 100644 index b54c2677c7..0000000000 --- a/extensions/markdown/src/commands/showPreview.ts +++ /dev/null @@ -1,123 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { Command } from '../commandManager'; -import { MarkdownPreviewManager } from '../features/previewManager'; -import { TelemetryReporter } from '../telemetryReporter'; -import { PreviewSettings } from '../features/preview'; - - -function getViewColumn(sideBySide: boolean): vscode.ViewColumn | undefined { - const active = vscode.window.activeTextEditor; - if (!active) { - return vscode.ViewColumn.One; - } - - if (!sideBySide) { - return active.viewColumn; - } - - switch (active.viewColumn) { - case vscode.ViewColumn.One: - return vscode.ViewColumn.Two; - case vscode.ViewColumn.Two: - return vscode.ViewColumn.Three; - } - - return active.viewColumn; -} - -interface ShowPreviewSettings { - readonly sideBySide?: boolean; - readonly locked?: boolean; -} - -async function showPreview( - webviewManager: MarkdownPreviewManager, - telemetryReporter: TelemetryReporter, - uri: vscode.Uri | undefined, - previewSettings: ShowPreviewSettings, -): Promise<any> { - let resource = uri; - if (!(resource instanceof vscode.Uri)) { - if (vscode.window.activeTextEditor) { - // we are relaxed and don't check for markdown files - resource = vscode.window.activeTextEditor.document.uri; - } - } - - if (!(resource instanceof vscode.Uri)) { - if (!vscode.window.activeTextEditor) { - // this is most likely toggling the preview - return vscode.commands.executeCommand('markdown.showSource'); - } - // nothing found that could be shown or toggled - return; - } - - webviewManager.preview(resource, { - resourceColumn: (vscode.window.activeTextEditor && vscode.window.activeTextEditor.viewColumn) || vscode.ViewColumn.One, - previewColumn: getViewColumn(!!previewSettings.sideBySide) || vscode.ViewColumn.Active, - locked: !!previewSettings.locked - }); - - telemetryReporter.sendTelemetryEvent('openPreview', { - where: previewSettings.sideBySide ? 'sideBySide' : 'inPlace', - how: (uri instanceof vscode.Uri) ? 'action' : 'pallete' - }); -} - -export class ShowPreviewCommand implements Command { - public readonly id = 'markdown.showPreview'; - - public constructor( - private readonly webviewManager: MarkdownPreviewManager, - private readonly telemetryReporter: TelemetryReporter - ) { } - - public execute(mainUri?: vscode.Uri, allUris?: vscode.Uri[], previewSettings?: PreviewSettings) { - for (const uri of (allUris || [mainUri])) { - showPreview(this.webviewManager, this.telemetryReporter, uri, { - sideBySide: false, - locked: previewSettings && previewSettings.locked - }); - } - } -} - -export class ShowPreviewToSideCommand implements Command { - public readonly id = 'markdown.showPreviewToSide'; - - public constructor( - private readonly webviewManager: MarkdownPreviewManager, - private readonly telemetryReporter: TelemetryReporter - ) { } - - public execute(uri?: vscode.Uri, previewSettings?: PreviewSettings) { - showPreview(this.webviewManager, this.telemetryReporter, uri, { - sideBySide: true, - locked: previewSettings && previewSettings.locked - }); - } -} - - -export class ShowLockedPreviewToSideCommand implements Command { - public readonly id = 'markdown.showLockedPreviewToSide'; - - public constructor( - private readonly webviewManager: MarkdownPreviewManager, - private readonly telemetryReporter: TelemetryReporter - ) { } - - public execute(uri?: vscode.Uri) { - showPreview(this.webviewManager, this.telemetryReporter, uri, { - sideBySide: true, - locked: true - }); - } -} diff --git a/extensions/markdown/src/commands/showPreviewSecuritySelector.ts b/extensions/markdown/src/commands/showPreviewSecuritySelector.ts deleted file mode 100644 index 9fa497b77b..0000000000 --- a/extensions/markdown/src/commands/showPreviewSecuritySelector.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { Command } from '../commandManager'; -import { PreviewSecuritySelector } from '../security'; -import { isMarkdownFile } from '../util/file'; -import { MarkdownPreviewManager } from '../features/previewManager'; - -export class ShowPreviewSecuritySelectorCommand implements Command { - public readonly id = 'markdown.showPreviewSecuritySelector'; - - public constructor( - private readonly previewSecuritySelector: PreviewSecuritySelector, - private readonly previewManager: MarkdownPreviewManager - ) { } - - public execute(resource: string | undefined) { - if (resource) { - const source = vscode.Uri.parse(resource).query; - this.previewSecuritySelector.showSecutitySelectorForResource(vscode.Uri.parse(source)); - } else if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) { - this.previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri); - } else if (this.previewManager.activePreviewResource) { - this.previewSecuritySelector.showSecutitySelectorForResource(this.previewManager.activePreviewResource); - } - } -} \ No newline at end of file diff --git a/extensions/markdown/src/commands/showSource.ts b/extensions/markdown/src/commands/showSource.ts deleted file mode 100644 index a35b95ce5f..0000000000 --- a/extensions/markdown/src/commands/showSource.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { Command } from '../commandManager'; -import { MarkdownPreviewManager } from '../features/previewManager'; - -export class ShowSourceCommand implements Command { - public readonly id = 'markdown.showSource'; - - public constructor( - private readonly previewManager: MarkdownPreviewManager - ) { } - - - public execute(docUri?: vscode.Uri) { - if (!docUri) { - return vscode.commands.executeCommand('workbench.action.navigateBack'); - } - - const resource = this.previewManager.getResourceForPreview(docUri); - if (resource) { - return vscode.workspace.openTextDocument(resource) - .then(document => vscode.window.showTextDocument(document)); - } - return undefined; - } -} \ No newline at end of file diff --git a/extensions/markdown/src/commands/toggleLock.ts b/extensions/markdown/src/commands/toggleLock.ts deleted file mode 100644 index 06c9a26685..0000000000 --- a/extensions/markdown/src/commands/toggleLock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { Command } from '../commandManager'; -import { MarkdownPreviewManager } from '../features/previewManager'; - -export class ToggleLockCommand implements Command { - public readonly id = 'markdown.preview.toggleLock'; - - public constructor( - private readonly previewManager: MarkdownPreviewManager - ) { } - - public execute(previewUri?: vscode.Uri) { - this.previewManager.toggleLock(previewUri); - } -} \ No newline at end of file diff --git a/extensions/markdown/src/extension.ts b/extensions/markdown/src/extension.ts deleted file mode 100644 index fc99e18db7..0000000000 --- a/extensions/markdown/src/extension.ts +++ /dev/null @@ -1,59 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { MarkdownEngine } from './markdownEngine'; -import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security'; -import { Logger } from './logger'; -import { CommandManager } from './commandManager'; -import * as commands from './commands/index'; -import { loadDefaultTelemetryReporter } from './telemetryReporter'; -import { loadMarkdownExtensions } from './markdownExtensions'; -import LinkProvider from './features/documentLinkProvider'; -import MDDocumentSymbolProvider from './features/documentSymbolProvider'; -import { MarkdownContentProvider } from './features/previewContentProvider'; -import { MarkdownPreviewManager } from './features/previewManager'; - - -export function activate(context: vscode.ExtensionContext) { - const telemetryReporter = loadDefaultTelemetryReporter(); - context.subscriptions.push(telemetryReporter); - - const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState, context.workspaceState); - const engine = new MarkdownEngine(); - const logger = new Logger(); - - const selector = 'markdown'; - - const contentProvider = new MarkdownContentProvider(engine, context, cspArbiter, logger); - loadMarkdownExtensions(contentProvider, engine); - - const previewManager = new MarkdownPreviewManager(contentProvider, logger); - context.subscriptions.push(previewManager); - - context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(selector, new MDDocumentSymbolProvider(engine))); - context.subscriptions.push(vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider())); - - const previewSecuritySelector = new PreviewSecuritySelector(cspArbiter, previewManager); - - const commandManager = new CommandManager(); - context.subscriptions.push(commandManager); - commandManager.register(new commands.ShowPreviewCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowPreviewToSideCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowLockedPreviewToSideCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowSourceCommand(previewManager)); - commandManager.register(new commands.RefreshPreviewCommand(previewManager)); - commandManager.register(new commands.MoveCursorToPositionCommand()); - commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager)); - commandManager.register(new commands.OnPreviewStyleLoadErrorCommand()); - commandManager.register(new commands.OpenDocumentLinkCommand(engine)); - commandManager.register(new commands.ToggleLockCommand(previewManager)); - - context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => { - logger.updateConfiguration(); - previewManager.updateConfiguration(); - })); -} diff --git a/extensions/markdown/src/features/documentLinkProvider.ts b/extensions/markdown/src/features/documentLinkProvider.ts deleted file mode 100644 index 0e84e76672..0000000000 --- a/extensions/markdown/src/features/documentLinkProvider.ts +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; -import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; - -function normalizeLink( - document: vscode.TextDocument, - link: string, - base: string -): vscode.Uri { - const uri = vscode.Uri.parse(link); - if (uri.scheme) { - return uri; - } - - // assume it must be a file - let resourcePath = uri.path; - if (!uri.path) { - resourcePath = document.uri.path; - } else if (uri.path[0] === '/') { - const root = vscode.workspace.getWorkspaceFolder(document.uri); - if (root) { - resourcePath = path.join(root.uri.fsPath, uri.path); - } - } else { - resourcePath = path.join(base, uri.path); - } - - return OpenDocumentLinkCommand.createCommandUri(resourcePath, uri.fragment); -} - -function matchAll( - pattern: RegExp, - text: string -): Array<RegExpMatchArray> { - const out: RegExpMatchArray[] = []; - pattern.lastIndex = 0; - let match: RegExpMatchArray | null; - while ((match = pattern.exec(text))) { - out.push(match); - } - return out; -} - -export default class LinkProvider implements vscode.DocumentLinkProvider { - private readonly linkPattern = /(\[[^\]]*\]\(\s*?)(((((?=.*\)\)+)|(?=.*\)\]+))[^\s\)]+?)|([^\s]+?)))\)/g; - private readonly referenceLinkPattern = /(\[([^\]]+)\]\[\s*?)([^\s\]]*?)\]/g; - private readonly definitionPattern = /^([\t ]*\[([^\]]+)\]:\s*)(\S+)/gm; - - public provideDocumentLinks( - document: vscode.TextDocument, - _token: vscode.CancellationToken - ): vscode.DocumentLink[] { - const base = path.dirname(document.uri.fsPath); - const text = document.getText(); - - return this.providerInlineLinks(text, document, base) - .concat(this.provideReferenceLinks(text, document, base)); - } - - private providerInlineLinks( - text: string, - document: vscode.TextDocument, - base: string - ): vscode.DocumentLink[] { - const results: vscode.DocumentLink[] = []; - for (const match of matchAll(this.linkPattern, text)) { - const pre = match[1]; - const link = match[2]; - const offset = (match.index || 0) + pre.length; - const linkStart = document.positionAt(offset); - const linkEnd = document.positionAt(offset + link.length); - try { - results.push(new vscode.DocumentLink( - new vscode.Range(linkStart, linkEnd), - normalizeLink(document, link, base))); - } catch (e) { - // noop - } - } - - return results; - } - - private provideReferenceLinks( - text: string, - document: vscode.TextDocument, - base: string - ): vscode.DocumentLink[] { - const results: vscode.DocumentLink[] = []; - - const definitions = this.getDefinitions(text, document); - for (const match of matchAll(this.referenceLinkPattern, text)) { - let linkStart: vscode.Position; - let linkEnd: vscode.Position; - let reference = match[3]; - if (reference) { // [text][ref] - const pre = match[1]; - const offset = (match.index || 0) + pre.length; - linkStart = document.positionAt(offset); - linkEnd = document.positionAt(offset + reference.length); - } else if (match[2]) { // [ref][] - reference = match[2]; - const offset = (match.index || 0) + 1; - linkStart = document.positionAt(offset); - linkEnd = document.positionAt(offset + match[2].length); - } else { - continue; - } - - try { - const link = definitions.get(reference); - if (link) { - results.push(new vscode.DocumentLink( - new vscode.Range(linkStart, linkEnd), - vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([link.linkRange.start.line, link.linkRange.start.character]))}`))); - } - } catch (e) { - // noop - } - } - - for (const definition of Array.from(definitions.values())) { - try { - results.push(new vscode.DocumentLink( - definition.linkRange, - normalizeLink(document, definition.link, base))); - } catch (e) { - // noop - } - } - - return results; - } - - private getDefinitions(text: string, document: vscode.TextDocument) { - const out = new Map<string, { link: string, linkRange: vscode.Range }>(); - for (const match of matchAll(this.definitionPattern, text)) { - const pre = match[1]; - const reference = match[2]; - const link = match[3].trim(); - - const offset = (match.index || 0) + pre.length; - const linkStart = document.positionAt(offset); - const linkEnd = document.positionAt(offset + link.length); - - out.set(reference, { - link: link, - linkRange: new vscode.Range(linkStart, linkEnd) - }); - } - return out; - } -} diff --git a/extensions/markdown/src/features/documentSymbolProvider.ts b/extensions/markdown/src/features/documentSymbolProvider.ts deleted file mode 100644 index 0678992ffb..0000000000 --- a/extensions/markdown/src/features/documentSymbolProvider.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { MarkdownEngine } from '../markdownEngine'; -import { TableOfContentsProvider } from '../tableOfContentsProvider'; - -export default class MDDocumentSymbolProvider implements vscode.DocumentSymbolProvider { - - constructor( - private readonly engine: MarkdownEngine - ) { } - - public async provideDocumentSymbols(document: vscode.TextDocument): Promise<vscode.SymbolInformation[]> { - const toc = await new TableOfContentsProvider(this.engine, document).getToc(); - return toc.map(entry => { - return new vscode.SymbolInformation('#'.repeat(entry.level) + ' ' + entry.text, vscode.SymbolKind.Namespace, '', entry.location); - }); - } -} \ No newline at end of file diff --git a/extensions/markdown/src/features/preview.ts b/extensions/markdown/src/features/preview.ts deleted file mode 100644 index e8dd0c47d6..0000000000 --- a/extensions/markdown/src/features/preview.ts +++ /dev/null @@ -1,299 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; - -import { Logger } from '../logger'; -import { MarkdownContentProvider } from './previewContentProvider'; -import { disposeAll } from '../util/dispose'; - -import * as nls from 'vscode-nls'; -import { getVisibleLine, MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor'; -import { MarkdownPreviewConfigurationManager } from './previewConfig'; -const localize = nls.loadMessageBundle(); - -export class MarkdownPreview { - - public static previewScheme = 'vscode-markdown-preview'; - private static previewCount = 0; - - public readonly uri: vscode.Uri; - private readonly webview: vscode.Webview; - private throttleTimer: any; - private initialLine: number | undefined = undefined; - private readonly disposables: vscode.Disposable[] = []; - private firstUpdate = true; - private currentVersion?: { resource: vscode.Uri, version: number }; - private forceUpdate = false; - private isScrolling = false; - - constructor( - private _resource: vscode.Uri, - previewColumn: vscode.ViewColumn, - public locked: boolean, - private readonly contentProvider: MarkdownContentProvider, - private readonly previewConfigurations: MarkdownPreviewConfigurationManager, - private readonly logger: Logger, - topmostLineMonitor: MarkdownFileTopmostLineMonitor - ) { - this.uri = vscode.Uri.parse(`${MarkdownPreview.previewScheme}:${MarkdownPreview.previewCount++}`); - this.webview = vscode.window.createWebview( - this.uri, - this.getPreviewTitle(this._resource), - previewColumn, { - enableScripts: true, - enableCommandUris: true, - localResourceRoots: this.getLocalResourceRoots(_resource) - }); - - this.webview.onDidDispose(() => { - this.dispose(); - }, null, this.disposables); - - this.webview.onDidChangeViewColumn(() => { - this._onDidChangeViewColumnEmitter.fire(); - }, null, this.disposables); - - this.webview.onDidReceiveMessage(e => { - if (e.source !== this._resource.toString()) { - return; - } - - switch (e.type) { - case 'command': - vscode.commands.executeCommand(e.body.command, ...e.body.args); - break; - - case 'revealLine': - this.onDidScrollPreview(e.body.line); - break; - - case 'didClick': - this.onDidClickPreview(e.body.line); - break; - - } - }, null, this.disposables); - - vscode.workspace.onDidChangeTextDocument(event => { - if (this.isPreviewOf(event.document.uri)) { - this.refresh(); - } - }, null, this.disposables); - - topmostLineMonitor.onDidChangeTopmostLine(event => { - if (this.isPreviewOf(event.resource)) { - this.updateForView(event.resource, event.line); - } - }, null, this.disposables); - - vscode.window.onDidChangeTextEditorSelection(event => { - if (this.isPreviewOf(event.textEditor.document.uri)) { - this.webview.postMessage({ - type: 'onDidChangeTextEditorSelection', - line: event.selections[0].active.line, - source: this.resource.toString() - }); - } - }, null, this.disposables); - } - - private readonly _onDisposeEmitter = new vscode.EventEmitter<void>(); - public readonly onDispose = this._onDisposeEmitter.event; - - private readonly _onDidChangeViewColumnEmitter = new vscode.EventEmitter<vscode.ViewColumn>(); - public readonly onDidChangeViewColumn = this._onDidChangeViewColumnEmitter.event; - - public get resource(): vscode.Uri { - return this._resource; - } - - public dispose() { - this._onDisposeEmitter.fire(); - - this._onDisposeEmitter.dispose(); - this._onDidChangeViewColumnEmitter.dispose(); - this.webview.dispose(); - - disposeAll(this.disposables); - } - - public update(resource: vscode.Uri) { - const editor = vscode.window.activeTextEditor; - if (editor && editor.document.uri.fsPath === resource.fsPath) { - this.initialLine = getVisibleLine(editor); - } else { - this.initialLine = undefined; - } - - // If we have changed resources, cancel any pending updates - const isResourceChange = resource.fsPath !== this._resource.fsPath; - if (isResourceChange) { - clearTimeout(this.throttleTimer); - this.throttleTimer = undefined; - } - - this._resource = resource; - - // Schedule update if none is pending - if (!this.throttleTimer) { - if (isResourceChange || this.firstUpdate) { - this.doUpdate(); - } else { - this.throttleTimer = setTimeout(() => this.doUpdate(), 300); - } - } - - this.firstUpdate = false; - } - - public refresh() { - this.forceUpdate = true; - this.update(this._resource); - } - - public updateConfiguration() { - if (this.previewConfigurations.hasConfigurationChanged(this._resource)) { - this.refresh(); - } - } - - public get viewColumn(): vscode.ViewColumn | undefined { - return this.webview.viewColumn; - } - - public isPreviewOf(resource: vscode.Uri): boolean { - return this._resource.fsPath === resource.fsPath; - } - - public matchesResource( - otherResource: vscode.Uri, - otherViewColumn: vscode.ViewColumn | undefined, - otherLocked: boolean - ): boolean { - if (this.viewColumn !== otherViewColumn) { - return false; - } - - if (this.locked) { - return otherLocked && this.isPreviewOf(otherResource); - } else { - return !otherLocked; - } - } - - public matches(otherPreview: MarkdownPreview): boolean { - return this.matchesResource(otherPreview._resource, otherPreview.viewColumn, otherPreview.locked); - } - - public show(viewColumn: vscode.ViewColumn) { - this.webview.show(viewColumn); - } - - public toggleLock() { - this.locked = !this.locked; - this.webview.title = this.getPreviewTitle(this._resource); - } - - private getPreviewTitle(resource: vscode.Uri): string { - return this.locked - ? localize('lockedPreviewTitle', '[Preview] {0}', path.basename(resource.fsPath)) - : localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)); - } - - private updateForView(resource: vscode.Uri, topLine: number | undefined) { - if (!this.isPreviewOf(resource)) { - return; - } - - if (this.isScrolling) { - this.isScrolling = false; - return; - } - - if (typeof topLine === 'number') { - this.logger.log('updateForView', { markdownFile: resource }); - this.initialLine = topLine; - this.webview.postMessage({ - type: 'updateView', - line: topLine, - source: resource.toString() - }); - } - } - - private async doUpdate(): Promise<void> { - const resource = this._resource; - - clearTimeout(this.throttleTimer); - this.throttleTimer = undefined; - - const document = await vscode.workspace.openTextDocument(resource); - if (!this.forceUpdate && this.currentVersion && this.currentVersion.resource.fsPath === resource.fsPath && this.currentVersion.version === document.version) { - if (this.initialLine) { - this.updateForView(resource, this.initialLine); - } - return; - } - this.forceUpdate = false; - - this.currentVersion = { resource, version: document.version }; - this.contentProvider.provideTextDocumentContent(document, this.previewConfigurations, this.initialLine) - .then(content => { - if (this._resource === resource) { - this.webview.title = this.getPreviewTitle(this._resource); - this.webview.html = content; - } - }); - } - - private getLocalResourceRoots(resource: vscode.Uri): vscode.Uri[] { - const folder = vscode.workspace.getWorkspaceFolder(resource); - if (folder) { - return [folder.uri]; - } - - if (!resource.scheme || resource.scheme === 'file') { - return [vscode.Uri.file(path.dirname(resource.fsPath))]; - } - - return []; - } - - private onDidScrollPreview(line: number) { - for (const editor of vscode.window.visibleTextEditors) { - if (!this.isPreviewOf(editor.document.uri)) { - continue; - } - - this.isScrolling = true; - const sourceLine = Math.floor(line); - const fraction = line - sourceLine; - const text = editor.document.lineAt(sourceLine).text; - const start = Math.floor(fraction * text.length); - editor.revealRange( - new vscode.Range(sourceLine, start, sourceLine + 1, 0), - vscode.TextEditorRevealType.AtTop); - } - } - - private async onDidClickPreview(line: number): Promise<void> { - for (const visibleEditor of vscode.window.visibleTextEditors) { - if (this.isPreviewOf(visibleEditor.document.uri)) { - const editor = await vscode.window.showTextDocument(visibleEditor.document, visibleEditor.viewColumn); - const position = new vscode.Position(line, 0); - editor.selection = new vscode.Selection(position, position); - return; - } - } - } -} - -export interface PreviewSettings { - readonly resourceColumn: vscode.ViewColumn; - readonly previewColumn: vscode.ViewColumn; - readonly locked: boolean; -} diff --git a/extensions/markdown/src/features/previewConfig.ts b/extensions/markdown/src/features/previewConfig.ts deleted file mode 100644 index 041371ff70..0000000000 --- a/extensions/markdown/src/features/previewConfig.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -export class MarkdownPreviewConfiguration { - public static getForResource(resource: vscode.Uri) { - return new MarkdownPreviewConfiguration(resource); - } - - public readonly scrollBeyondLastLine: boolean; - public readonly wordWrap: boolean; - public readonly previewFrontMatter: string; - public readonly lineBreaks: boolean; - public readonly doubleClickToSwitchToEditor: boolean; - public readonly scrollEditorWithPreview: boolean; - public readonly scrollPreviewWithEditor: boolean; - public readonly markEditorSelection: boolean; - - public readonly lineHeight: number; - public readonly fontSize: number; - public readonly fontFamily: string | undefined; - public readonly styles: string[]; - - private constructor(resource: vscode.Uri) { - const editorConfig = vscode.workspace.getConfiguration('editor', resource); - const markdownConfig = vscode.workspace.getConfiguration('markdown', resource); - const markdownEditorConfig = vscode.workspace.getConfiguration('[markdown]'); - - this.scrollBeyondLastLine = editorConfig.get<boolean>('scrollBeyondLastLine', false); - - this.wordWrap = editorConfig.get<string>('wordWrap', 'off') !== 'off'; - if (markdownEditorConfig && markdownEditorConfig['editor.wordWrap']) { - this.wordWrap = markdownEditorConfig['editor.wordWrap'] !== 'off'; - } - - this.previewFrontMatter = markdownConfig.get<string>('previewFrontMatter', 'hide'); - this.scrollPreviewWithEditor = !!markdownConfig.get<boolean>('preview.scrollPreviewWithEditor', true); - this.scrollEditorWithPreview = !!markdownConfig.get<boolean>('preview.scrollEditorWithPreview', true); - this.lineBreaks = !!markdownConfig.get<boolean>('preview.breaks', false); - this.doubleClickToSwitchToEditor = !!markdownConfig.get<boolean>('preview.doubleClickToSwitchToEditor', true); - this.markEditorSelection = !!markdownConfig.get<boolean>('preview.markEditorSelection', true); - - this.fontFamily = markdownConfig.get<string | undefined>('preview.fontFamily', undefined); - this.fontSize = Math.max(8, +markdownConfig.get<number>('preview.fontSize', NaN)); - this.lineHeight = Math.max(0.6, +markdownConfig.get<number>('preview.lineHeight', NaN)); - - this.styles = markdownConfig.get<string[]>('styles', []); - } - - public isEqualTo(otherConfig: MarkdownPreviewConfiguration) { - for (let key in this) { - if (this.hasOwnProperty(key) && key !== 'styles') { - if (this[key] !== otherConfig[key]) { - return false; - } - } - } - - // Check styles - if (this.styles.length !== otherConfig.styles.length) { - return false; - } - for (let i = 0; i < this.styles.length; ++i) { - if (this.styles[i] !== otherConfig.styles[i]) { - return false; - } - } - - return true; - } - - [key: string]: any; -} - -export class MarkdownPreviewConfigurationManager { - private readonly previewConfigurationsForWorkspaces = new Map<string, MarkdownPreviewConfiguration>(); - - public loadAndCacheConfiguration( - resource: vscode.Uri - ): MarkdownPreviewConfiguration { - const config = MarkdownPreviewConfiguration.getForResource(resource); - this.previewConfigurationsForWorkspaces.set(this.getKey(resource), config); - return config; - } - - public hasConfigurationChanged( - resource: vscode.Uri - ): boolean { - const key = this.getKey(resource); - const currentConfig = this.previewConfigurationsForWorkspaces.get(key); - const newConfig = MarkdownPreviewConfiguration.getForResource(resource); - return (!currentConfig || !currentConfig.isEqualTo(newConfig)); - } - - private getKey( - resource: vscode.Uri - ): string { - const folder = vscode.workspace.getWorkspaceFolder(resource); - return folder ? folder.uri.toString() : ''; - } -} diff --git a/extensions/markdown/src/features/previewContentProvider.ts b/extensions/markdown/src/features/previewContentProvider.ts deleted file mode 100644 index 2ed484a9e4..0000000000 --- a/extensions/markdown/src/features/previewContentProvider.ts +++ /dev/null @@ -1,187 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; -import { MarkdownEngine } from '../markdownEngine'; - -import * as nls from 'vscode-nls'; -const localize = nls.loadMessageBundle(); - -import { Logger } from '../logger'; -import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from '../security'; -import { MarkdownPreviewConfigurationManager, MarkdownPreviewConfiguration } from './previewConfig'; - -/** - * Strings used inside the markdown preview. - * - * Stored here and then injected in the preview so that they - * can be localized using our normal localization process. - */ -const previewStrings = { - cspAlertMessageText: localize( - 'preview.securityMessage.text', - 'Some content has been disabled in this document'), - - cspAlertMessageTitle: localize( - 'preview.securityMessage.title', - 'Potentially unsafe or insecure content has been disabled in the markdown preview. Change the Markdown preview security setting to allow insecure content or enable scripts'), - - cspAlertMessageLabel: localize( - 'preview.securityMessage.label', - 'Content Disabled Security Warning') -}; - -export class MarkdownContentProvider { - private readonly extraStyles: Array<vscode.Uri> = []; - private readonly extraScripts: Array<vscode.Uri> = []; - - constructor( - private readonly engine: MarkdownEngine, - private readonly context: vscode.ExtensionContext, - private readonly cspArbiter: ContentSecurityPolicyArbiter, - private readonly logger: Logger - ) { } - - public addScript(resource: vscode.Uri): void { - this.extraScripts.push(resource); - } - - public addStyle(resource: vscode.Uri): void { - this.extraStyles.push(resource); - } - - public async provideTextDocumentContent( - markdownDocument: vscode.TextDocument, - previewConfigurations: MarkdownPreviewConfigurationManager, - initialLine: number | undefined = undefined - ): Promise<string> { - const sourceUri = markdownDocument.uri; - const config = previewConfigurations.loadAndCacheConfiguration(sourceUri); - const initialData = { - source: sourceUri.toString(), - line: initialLine, - lineCount: markdownDocument.lineCount, - scrollPreviewWithEditor: config.scrollPreviewWithEditor, - scrollEditorWithPreview: config.scrollEditorWithPreview, - doubleClickToSwitchToEditor: config.doubleClickToSwitchToEditor, - disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings() - }; - - this.logger.log('provideTextDocumentContent', initialData); - - // Content Security Policy - const nonce = new Date().getTime() + '' + new Date().getMilliseconds(); - const csp = this.getCspForResource(sourceUri, nonce); - - const body = await this.engine.render(sourceUri, config.previewFrontMatter === 'hide', markdownDocument.getText()); - return `<!DOCTYPE html> - <html> - <head> - <meta http-equiv="Content-type" content="text/html;charset=UTF-8"> - ${csp} - <meta id="vscode-markdown-preview-data" data-settings="${JSON.stringify(initialData).replace(/"/g, '"')}" data-strings="${JSON.stringify(previewStrings).replace(/"/g, '"')}"> - <script src="${this.extensionResourcePath('csp.js')}" nonce="${nonce}"></script> - <script src="${this.extensionResourcePath('loading.js')}" nonce="${nonce}"></script> - ${this.getStyles(sourceUri, nonce, config)} - <base href="${markdownDocument.uri.with({ scheme: 'vscode-workspace-resource' }).toString(true)}"> - </head> - <body class="vscode-body ${config.scrollBeyondLastLine ? 'scrollBeyondLastLine' : ''} ${config.wordWrap ? 'wordWrap' : ''} ${config.markEditorSelection ? 'showEditorSelection' : ''}"> - ${body} - <div class="code-line" data-line="${markdownDocument.lineCount}"></div> - ${this.getScripts(nonce)} - </body> - </html>`; - } - - private extensionResourcePath(mediaFile: string): string { - return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))) - .with({ scheme: 'vscode-extension-resource' }) - .toString(); - } - - private fixHref(resource: vscode.Uri, href: string): string { - if (!href) { - return href; - } - - // Use href if it is already an URL - const hrefUri = vscode.Uri.parse(href); - if (['http', 'https'].indexOf(hrefUri.scheme) >= 0) { - return hrefUri.toString(); - } - - // Use href as file URI if it is absolute - if (path.isAbsolute(href) || hrefUri.scheme === 'file') { - return vscode.Uri.file(href) - .with({ scheme: 'vscode-workspace-resource' }) - .toString(); - } - - // Use a workspace relative path if there is a workspace - let root = vscode.workspace.getWorkspaceFolder(resource); - if (root) { - return vscode.Uri.file(path.join(root.uri.fsPath, href)) - .with({ scheme: 'vscode-workspace-resource' }) - .toString(); - } - - // Otherwise look relative to the markdown file - return vscode.Uri.file(path.join(path.dirname(resource.fsPath), href)) - .with({ scheme: 'vscode-workspace-resource' }) - .toString(); - } - - private computeCustomStyleSheetIncludes(resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { - if (config.styles && Array.isArray(config.styles)) { - return config.styles.map(style => { - return `<link rel="stylesheet" class="code-user-style" data-source="${style.replace(/"/g, '"')}" href="${this.fixHref(resource, style)}" type="text/css" media="screen">`; - }).join('\n'); - } - return ''; - } - - private getSettingsOverrideStyles(nonce: string, config: MarkdownPreviewConfiguration): string { - return `<style nonce="${nonce}"> - body { - ${config.fontFamily ? `font-family: ${config.fontFamily};` : ''} - ${isNaN(config.fontSize) ? '' : `font-size: ${config.fontSize}px;`} - ${isNaN(config.lineHeight) ? '' : `line-height: ${config.lineHeight};`} - } - </style>`; - } - - private getStyles(resource: vscode.Uri, nonce: string, config: MarkdownPreviewConfiguration): string { - const baseStyles = [ - this.extensionResourcePath('markdown.css'), - this.extensionResourcePath('tomorrow.css') - ].concat(this.extraStyles.map(resource => resource.toString())); - - return `${baseStyles.map(href => `<link rel="stylesheet" type="text/css" href="${href}">`).join('\n')} - ${this.getSettingsOverrideStyles(nonce, config)} - ${this.computeCustomStyleSheetIncludes(resource, config)}`; - } - - private getScripts(nonce: string): string { - const scripts = [this.extensionResourcePath('main.js')].concat(this.extraScripts.map(resource => resource.toString())); - return scripts - .map(source => `<script async src="${source}" nonce="${nonce}" charset="UTF-8"></script>`) - .join('\n'); - } - - private getCspForResource(resource: vscode.Uri, nonce: string): string { - switch (this.cspArbiter.getSecurityLevelForResource(resource)) { - case MarkdownPreviewSecurityLevel.AllowInsecureContent: - return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-workspace-resource: vscode-extension-resource: http: https: data:; media-src vscode-workspace-resource: vscode-extension-resource: http: https: data:; script-src 'nonce-${nonce}'; style-src vscode-workspace-resource: 'unsafe-inline' http: https: data: vscode-extension-resource:; font-src vscode-workspace-resource: vscode-extension-resource: http: https: data:;">`; - - case MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent: - return ''; - - case MarkdownPreviewSecurityLevel.Strict: - default: - return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-workspace-resource: vscode-extension-resource: https: data:; media-src vscode-workspace-resource: vscode-extension-resource: https: data:; script-src 'nonce-${nonce}'; style-src vscode-workspace-resource: 'unsafe-inline' https: data: vscode-extension-resource:; font-src vscode-workspace-resource: vscode-extension-resource: https: data:;">`; - } - } -} diff --git a/extensions/markdown/src/features/previewManager.ts b/extensions/markdown/src/features/previewManager.ts deleted file mode 100644 index d3d332a80f..0000000000 --- a/extensions/markdown/src/features/previewManager.ts +++ /dev/null @@ -1,141 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { Logger } from '../logger'; -import { MarkdownContentProvider } from './previewContentProvider'; -import { MarkdownPreview, PreviewSettings } from './preview'; -import { disposeAll } from '../util/dispose'; -import { MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor'; -import { isMarkdownFile } from '../util/file'; -import { MarkdownPreviewConfigurationManager } from './previewConfig'; - -export class MarkdownPreviewManager { - private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus'; - - private readonly topmostLineMonitor = new MarkdownFileTopmostLineMonitor(); - private readonly previewConfigurations = new MarkdownPreviewConfigurationManager(); - private readonly previews: MarkdownPreview[] = []; - private activePreview: MarkdownPreview | undefined = undefined; - private readonly disposables: vscode.Disposable[] = []; - - public constructor( - private readonly contentProvider: MarkdownContentProvider, - private readonly logger: Logger - ) { - vscode.window.onDidChangeActiveEditor(editor => { - vscode.commands.executeCommand('setContext', MarkdownPreviewManager.markdownPreviewActiveContextKey, - editor && editor.editorType === 'webview' && editor.uri.scheme === MarkdownPreview.previewScheme); - - this.activePreview = editor && editor.editorType === 'webview' - ? this.previews.find(preview => editor.uri.toString() === preview.uri.toString()) - : undefined; - - if (editor && editor.editorType === 'texteditor') { - if (isMarkdownFile(editor.document)) { - for (const preview of this.previews.filter(preview => !preview.locked)) { - preview.update(editor.document.uri); - } - } - } - }, null, this.disposables); - } - - public dispose(): void { - disposeAll(this.disposables); - disposeAll(this.previews); - } - - public refresh() { - for (const preview of this.previews) { - preview.refresh(); - } - } - - public updateConfiguration() { - for (const preview of this.previews) { - preview.updateConfiguration(); - } - } - - public preview( - resource: vscode.Uri, - previewSettings: PreviewSettings - ): void { - let preview = this.getExistingPreview(resource, previewSettings); - if (preview) { - preview.show(previewSettings.previewColumn); - } else { - preview = this.createNewPreview(resource, previewSettings); - this.previews.push(preview); - } - - preview.update(resource); - } - - public get activePreviewResource() { - return this.activePreview && this.activePreview.resource; - } - - public getResourceForPreview(previewUri: vscode.Uri): vscode.Uri | undefined { - const preview = this.getPreviewWithUri(previewUri); - return preview && preview.resource; - } - - public toggleLock(previewUri?: vscode.Uri) { - const preview = previewUri ? this.getPreviewWithUri(previewUri) : this.activePreview; - if (preview) { - preview.toggleLock(); - - // Close any previews that are now redundant, such as having two dynamic previews in the same editor group - for (const otherPreview of this.previews) { - if (otherPreview !== preview && preview.matches(otherPreview)) { - otherPreview.dispose(); - } - } - } - } - - private getExistingPreview( - resource: vscode.Uri, - previewSettings: PreviewSettings - ): MarkdownPreview | undefined { - return this.previews.find(preview => - preview.matchesResource(resource, previewSettings.previewColumn, previewSettings.locked)); - } - - private getPreviewWithUri(previewUri: vscode.Uri): MarkdownPreview | undefined { - return this.previews.find(preview => preview.uri.toString() === previewUri.toString()); - } - - private createNewPreview( - resource: vscode.Uri, - previewSettings: PreviewSettings - ) { - const preview = new MarkdownPreview( - resource, - previewSettings.previewColumn, - previewSettings.locked, - this.contentProvider, - this.previewConfigurations, - this.logger, - this.topmostLineMonitor); - - preview.onDispose(() => { - const existing = this.previews.indexOf(preview!); - if (existing >= 0) { - this.previews.splice(existing, 1); - } - }); - - preview.onDidChangeViewColumn(() => { - disposeAll(this.previews.filter(otherPreview => preview !== otherPreview && preview!.matches(otherPreview))); - }); - - return preview; - } -} - diff --git a/extensions/markdown/src/logger.ts b/extensions/markdown/src/logger.ts deleted file mode 100644 index b7a11e86ee..0000000000 --- a/extensions/markdown/src/logger.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { OutputChannel, window, workspace } from 'vscode'; - -enum Trace { - Off, - Verbose -} - -namespace Trace { - export function fromString(value: string): Trace { - value = value.toLowerCase(); - switch (value) { - case 'off': - return Trace.Off; - case 'verbose': - return Trace.Verbose; - default: - return Trace.Off; - } - } -} - - -function isString(value: any): value is string { - return Object.prototype.toString.call(value) === '[object String]'; -} - -export class Logger { - private trace?: Trace; - private _output?: OutputChannel; - - constructor() { - this.updateConfiguration(); - } - - public log(message: string, data?: any): void { - if (this.trace === Trace.Verbose) { - this.output.appendLine(`[Log - ${(new Date().toLocaleTimeString())}] ${message}`); - if (data) { - this.output.appendLine(Logger.data2String(data)); - } - } - } - - public updateConfiguration() { - this.trace = this.readTrace(); - } - - private get output(): OutputChannel { - if (!this._output) { - this._output = window.createOutputChannel('Markdown'); - } - return this._output; - } - - private readTrace(): Trace { - return Trace.fromString(workspace.getConfiguration().get<string>('markdown.trace', 'off')); - } - - private static data2String(data: any): string { - if (data instanceof Error) { - if (isString(data.stack)) { - return data.stack; - } - return (data as Error).message; - } - if (isString(data)) { - return data; - } - return JSON.stringify(data, undefined, 2); - } -} \ No newline at end of file diff --git a/extensions/markdown/src/markdownEngine.ts b/extensions/markdown/src/markdownEngine.ts deleted file mode 100644 index 4a6d156bdf..0000000000 --- a/extensions/markdown/src/markdownEngine.ts +++ /dev/null @@ -1,171 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; -import { Slug } from './tableOfContentsProvider'; -import { MarkdownIt, Token } from 'markdown-it'; - -const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/; - -export class MarkdownEngine { - private md?: MarkdownIt; - - private firstLine?: number; - - private currentDocument?: vscode.Uri; - - private plugins: Array<(md: any) => any> = []; - - public addPlugin(factory: (md: any) => any): void { - if (this.md) { - this.usePlugin(factory); - } else { - this.plugins.push(factory); - } - } - - private usePlugin(factory: (md: any) => any): void { - try { - this.md = factory(this.md); - } catch (e) { - // noop - } - } - - private async getEngine(resource: vscode.Uri): Promise<MarkdownIt> { - if (!this.md) { - const hljs = await import('highlight.js'); - const mdnh = await import('markdown-it-named-headers'); - this.md = (await import('markdown-it'))({ - html: true, - highlight: (str: string, lang: string) => { - // Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155 - if (lang && ['tsx', 'typescriptreact'].indexOf(lang.toLocaleLowerCase()) >= 0) { - lang = 'jsx'; - } - if (lang && hljs.getLanguage(lang)) { - try { - return `<pre class="hljs"><code><div>${hljs.highlight(lang, str, true).value}</div></code></pre>`; - } catch (error) { } - } - return `<pre class="hljs"><code><div>${this.md!.utils.escapeHtml(str)}</div></code></pre>`; - } - }).use(mdnh, { - slugify: (header: string) => Slug.fromHeading(header).value - }); - - for (const plugin of this.plugins) { - this.usePlugin(plugin); - } - this.plugins = []; - - for (const renderName of ['paragraph_open', 'heading_open', 'image', 'code_block', 'blockquote_open', 'list_item_open']) { - this.addLineNumberRenderer(this.md, renderName); - } - - this.addLinkNormalizer(this.md); - this.addLinkValidator(this.md); - } - - const config = vscode.workspace.getConfiguration('markdown', resource); - this.md.set({ - breaks: config.get<boolean>('preview.breaks', false), - linkify: config.get<boolean>('preview.linkify', true) - }); - return this.md; - } - - private stripFrontmatter(text: string): { text: string, offset: number } { - let offset = 0; - const frontMatterMatch = FrontMatterRegex.exec(text); - if (frontMatterMatch) { - const frontMatter = frontMatterMatch[0]; - offset = frontMatter.split(/\r\n|\n|\r/g).length - 1; - text = text.substr(frontMatter.length); - } - return { text, offset }; - } - - public async render(document: vscode.Uri, stripFrontmatter: boolean, text: string): Promise<string> { - let offset = 0; - if (stripFrontmatter) { - const markdownContent = this.stripFrontmatter(text); - offset = markdownContent.offset; - text = markdownContent.text; - } - this.currentDocument = document; - this.firstLine = offset; - const engine = await this.getEngine(document); - return engine.render(text); - } - - public async parse(document: vscode.Uri, source: string): Promise<Token[]> { - const { text, offset } = this.stripFrontmatter(source); - this.currentDocument = document; - const engine = await this.getEngine(document); - - return engine.parse(text, {}).map(token => { - if (token.map) { - token.map[0] += offset; - } - return token; - }); - } - - private addLineNumberRenderer(md: any, ruleName: string): void { - const original = md.renderer.rules[ruleName]; - md.renderer.rules[ruleName] = (tokens: any, idx: number, options: any, env: any, self: any) => { - const token = tokens[idx]; - if (token.map && token.map.length) { - token.attrSet('data-line', this.firstLine + token.map[0]); - token.attrJoin('class', 'code-line'); - } - - if (original) { - return original(tokens, idx, options, env, self); - } else { - return self.renderToken(tokens, idx, options, env, self); - } - }; - } - - private addLinkNormalizer(md: any): void { - const normalizeLink = md.normalizeLink; - md.normalizeLink = (link: string) => { - try { - let uri = vscode.Uri.parse(link); - if (!uri.scheme && uri.path) { - // Assume it must be a file - const fragment = uri.fragment; - if (uri.path[0] === '/') { - const root = vscode.workspace.getWorkspaceFolder(this.currentDocument!); - if (root) { - uri = vscode.Uri.file(path.join(root.uri.fsPath, uri.path)); - } - } else { - uri = vscode.Uri.file(path.join(path.dirname(this.currentDocument!.path), uri.path)); - } - - if (fragment) { - uri = uri.with({ fragment }); - } - return normalizeLink(uri.with({ scheme: 'vscode-workspace-resource' }).toString(true)); - } - } catch (e) { - // noop - } - return normalizeLink(link); - }; - } - - private addLinkValidator(md: any): void { - const validateLink = md.validateLink; - md.validateLink = (link: string) => { - // support file:// links - return validateLink(link) || link.indexOf('file:') === 0; - }; - } -} \ No newline at end of file diff --git a/extensions/markdown/src/markdownExtensions.ts b/extensions/markdown/src/markdownExtensions.ts deleted file mode 100644 index ee9f4ff510..0000000000 --- a/extensions/markdown/src/markdownExtensions.ts +++ /dev/null @@ -1,81 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; - -import { MarkdownContentProvider } from './features/previewContentProvider'; -import { MarkdownEngine } from './markdownEngine'; - -const resolveExtensionResources = (extension: vscode.Extension<any>, resourcePath: string): vscode.Uri => { - return vscode.Uri.file(path.join(extension.extensionPath, resourcePath)) - .with({ scheme: 'vscode-extension-resource' }); -}; - - -export function loadMarkdownExtensions( - contentProvider: MarkdownContentProvider, - engine: MarkdownEngine -) { - for (const extension of vscode.extensions.all) { - const contributes = extension.packageJSON && extension.packageJSON.contributes; - if (!contributes) { - continue; - } - - tryLoadPreviewStyles(contributes, contentProvider, extension); - tryLoadPreviewScripts(contributes, contentProvider, extension); - tryLoadMarkdownItPlugins(contributes, extension, engine); - } -} - -function tryLoadMarkdownItPlugins( - contributes: any, - extension: vscode.Extension<any>, - engine: MarkdownEngine -) { - if (contributes['markdown.markdownItPlugins']) { - extension.activate().then(() => { - if (extension.exports && extension.exports.extendMarkdownIt) { - engine.addPlugin((md: any) => extension.exports.extendMarkdownIt(md)); - } - }); - } -} - -function tryLoadPreviewScripts( - contributes: any, - contentProvider: MarkdownContentProvider, - extension: vscode.Extension<any> -) { - const scripts = contributes['markdown.previewScripts']; - if (scripts && Array.isArray(scripts)) { - for (const script of scripts) { - try { - contentProvider.addScript(resolveExtensionResources(extension, script)); - } catch (e) { - // noop - } - } - } -} - -function tryLoadPreviewStyles( - contributes: any, - contentProvider: MarkdownContentProvider, - extension: vscode.Extension<any> -) { - const styles = contributes['markdown.previewStyles']; - if (styles && Array.isArray(styles)) { - for (const style of styles) { - try { - contentProvider.addStyle(resolveExtensionResources(extension, style)); - } catch (e) { - // noop - } - } - } -} - diff --git a/extensions/markdown/src/security.ts b/extensions/markdown/src/security.ts deleted file mode 100644 index b860aa1dfd..0000000000 --- a/extensions/markdown/src/security.ts +++ /dev/null @@ -1,154 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { MarkdownPreviewManager } from './features/previewManager'; - -import * as nls from 'vscode-nls'; - -const localize = nls.loadMessageBundle(); - -export enum MarkdownPreviewSecurityLevel { - Strict = 0, - AllowInsecureContent = 1, - AllowScriptsAndAllContent = 2 -} - -export interface ContentSecurityPolicyArbiter { - getSecurityLevelForResource(resource: vscode.Uri): MarkdownPreviewSecurityLevel; - - setSecurityLevelForResource(resource: vscode.Uri, level: MarkdownPreviewSecurityLevel): Thenable<void>; - - shouldAllowSvgsForResource(resource: vscode.Uri): void; - - shouldDisableSecurityWarnings(): boolean; - - setShouldDisableSecurityWarning(shouldShow: boolean): Thenable<void>; -} - -export class ExtensionContentSecurityPolicyArbiter implements ContentSecurityPolicyArbiter { - private readonly old_trusted_workspace_key = 'trusted_preview_workspace:'; - private readonly security_level_key = 'preview_security_level:'; - private readonly should_disable_security_warning_key = 'preview_should_show_security_warning:'; - - constructor( - private readonly globalState: vscode.Memento, - private readonly workspaceState: vscode.Memento - ) { } - - public getSecurityLevelForResource(resource: vscode.Uri): MarkdownPreviewSecurityLevel { - // Use new security level setting first - const level = this.globalState.get<MarkdownPreviewSecurityLevel | undefined>(this.security_level_key + this.getRoot(resource), undefined); - if (typeof level !== 'undefined') { - return level; - } - - // Fallback to old trusted workspace setting - if (this.globalState.get<boolean>(this.old_trusted_workspace_key + this.getRoot(resource), false)) { - return MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent; - } - return MarkdownPreviewSecurityLevel.Strict; - } - - public setSecurityLevelForResource(resource: vscode.Uri, level: MarkdownPreviewSecurityLevel): Thenable<void> { - return this.globalState.update(this.security_level_key + this.getRoot(resource), level); - } - - public shouldAllowSvgsForResource(resource: vscode.Uri) { - const securityLevel = this.getSecurityLevelForResource(resource); - return securityLevel === MarkdownPreviewSecurityLevel.AllowInsecureContent || securityLevel === MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent; - } - - public shouldDisableSecurityWarnings(): boolean { - return this.workspaceState.get<boolean>(this.should_disable_security_warning_key, false); - } - - public setShouldDisableSecurityWarning(disabled: boolean): Thenable<void> { - return this.workspaceState.update(this.should_disable_security_warning_key, disabled); - } - - private getRoot(resource: vscode.Uri): vscode.Uri { - if (vscode.workspace.workspaceFolders) { - const folderForResource = vscode.workspace.getWorkspaceFolder(resource); - if (folderForResource) { - return folderForResource.uri; - } - - if (vscode.workspace.workspaceFolders.length) { - return vscode.workspace.workspaceFolders[0].uri; - } - } - - return resource; - } -} - -export class PreviewSecuritySelector { - - public constructor( - private readonly cspArbiter: ContentSecurityPolicyArbiter, - private readonly webviewManager: MarkdownPreviewManager - ) { } - - public async showSecutitySelectorForResource(resource: vscode.Uri): Promise<void> { - interface PreviewSecurityPickItem extends vscode.QuickPickItem { - readonly type: 'moreinfo' | 'toggle' | MarkdownPreviewSecurityLevel; - } - - function markActiveWhen(when: boolean): string { - return when ? '• ' : ''; - } - - const currentSecurityLevel = this.cspArbiter.getSecurityLevelForResource(resource); - const selection = await vscode.window.showQuickPick<PreviewSecurityPickItem>( - [ - { - type: MarkdownPreviewSecurityLevel.Strict, - label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.Strict) + localize('strict.title', 'Strict'), - description: localize('strict.description', 'Only load secure content'), - }, { - type: MarkdownPreviewSecurityLevel.AllowInsecureContent, - label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.AllowInsecureContent) + localize('insecureContent.title', 'Allow insecure content'), - description: localize('insecureContent.description', 'Enable loading content over http'), - }, { - type: MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent, - label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent) + localize('disable.title', 'Disable'), - description: localize('disable.description', 'Allow all content and script execution. Not recommended'), - }, { - type: 'moreinfo', - label: localize('moreInfo.title', 'More Information'), - description: '' - }, { - type: 'toggle', - label: this.cspArbiter.shouldDisableSecurityWarnings() - ? localize('enableSecurityWarning.title', "Enable preview security warnings in this workspace") - : localize('disableSecurityWarning.title', "Disable preview security warning in this workspace"), - description: localize('toggleSecurityWarning.description', 'Does not affect the content security level') - }, - ], { - placeHolder: localize( - 'preview.showPreviewSecuritySelector.title', - 'Select security settings for Markdown previews in this workspace'), - }); - - if (!selection) { - return; - } - - if (selection.type === 'moreinfo') { - vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=854414')); - return; - } - - if (selection.type === 'toggle') { - this.cspArbiter.setShouldDisableSecurityWarning(!this.cspArbiter.shouldDisableSecurityWarnings()); - return; - } else { - await this.cspArbiter.setSecurityLevelForResource(resource, selection.type); - } - this.webviewManager.refresh(); - } -} diff --git a/extensions/markdown/src/tableOfContentsProvider.ts b/extensions/markdown/src/tableOfContentsProvider.ts deleted file mode 100644 index 2406829d3a..0000000000 --- a/extensions/markdown/src/tableOfContentsProvider.ts +++ /dev/null @@ -1,95 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { MarkdownEngine } from './markdownEngine'; - -export class Slug { - public static fromHeading(heading: string): Slug { - const slugifiedHeading = encodeURI(heading.trim() - .toLowerCase() - .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`]/g, '') - .replace(/\s+/g, '-') - .replace(/^\-+/, '') - .replace(/\-+$/, '')); - - return new Slug(slugifiedHeading); - } - - private constructor( - public readonly value: string - ) { } - - public equals(other: Slug): boolean { - return this.value === other.value; - } -} - -export interface TocEntry { - readonly slug: Slug; - readonly text: string; - readonly level: number; - readonly line: number; - readonly location: vscode.Location; -} - -export class TableOfContentsProvider { - private toc?: TocEntry[]; - - public constructor( - private engine: MarkdownEngine, - private document: vscode.TextDocument - ) { } - - public async getToc(): Promise<TocEntry[]> { - if (!this.toc) { - try { - this.toc = await this.buildToc(this.document); - } catch (e) { - this.toc = []; - } - } - return this.toc; - } - - public async lookup(fragment: string): Promise<TocEntry | undefined> { - const toc = await this.getToc(); - const slug = Slug.fromHeading(fragment); - return toc.find(entry => entry.slug.equals(slug)); - } - - private async buildToc(document: vscode.TextDocument): Promise<TocEntry[]> { - const toc: TocEntry[] = []; - const tokens = await this.engine.parse(document.uri, document.getText()); - - for (const heading of tokens.filter(token => token.type === 'heading_open')) { - const lineNumber = heading.map[0]; - const line = document.lineAt(lineNumber); - toc.push({ - slug: Slug.fromHeading(line.text), - text: TableOfContentsProvider.getHeaderText(line.text), - level: TableOfContentsProvider.getHeaderLevel(heading.markup), - line: lineNumber, - location: new vscode.Location(document.uri, line.range) - }); - } - return toc; - } - - private static getHeaderLevel(markup: string): number { - if (markup === '=') { - return 1; - } else if (markup === '-') { - return 2; - } else { // '#', '##', ... - return markup.length; - } - } - - private static getHeaderText(header: string): string { - return header.replace(/^\s*#+\s*(.*?)\s*#*$/, (_, word) => word.trim()); - } -} diff --git a/extensions/markdown/src/telemetryReporter.ts b/extensions/markdown/src/telemetryReporter.ts deleted file mode 100644 index 6d93a328e8..0000000000 --- a/extensions/markdown/src/telemetryReporter.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import { default as VSCodeTelemetryReporter } from 'vscode-extension-telemetry'; - -interface IPackageInfo { - name: string; - version: string; - aiKey: string; -} - -export interface TelemetryReporter { - dispose(): void; - sendTelemetryEvent(eventName: string, properties?: { - [key: string]: string; - }): void; -} - -const nullReporter = new class NullTelemetryReporter implements TelemetryReporter { - sendTelemetryEvent() { /** noop */ } - dispose() { /** noop */ } -}; - -class ExtensionReporter implements TelemetryReporter { - private readonly _reporter: VSCodeTelemetryReporter; - - constructor( - packageInfo: IPackageInfo - ) { - this._reporter = new VSCodeTelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey); - } - sendTelemetryEvent(eventName: string, properties?: { - [key: string]: string; - }) { - this._reporter.sendTelemetryEvent(eventName, properties); - } - - dispose() { - this._reporter.dispose(); - } -} - -export function loadDefaultTelemetryReporter(): TelemetryReporter { - const packageInfo = getPackageInfo(); - return packageInfo ? new ExtensionReporter(packageInfo) : nullReporter; -} - -function getPackageInfo(): IPackageInfo | null { - const extention = vscode.extensions.getExtension('Microsoft.vscode-markdown'); - if (extention && extention.packageJSON) { - return { - name: extention.packageJSON.name, - version: extention.packageJSON.version, - aiKey: extention.packageJSON.aiKey - }; - } - return null; -} diff --git a/extensions/markdown/src/test/index.ts b/extensions/markdown/src/test/index.ts deleted file mode 100644 index cd9d72c91c..0000000000 --- a/extensions/markdown/src/test/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -const testRunner = require('vscode/lib/testrunner'); - -// You can directly control Mocha options by uncommenting the following lines -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info -testRunner.configure({ - ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: process.platform !== 'win32', // colored output from test results (only windows cannot handle) - timeout: 60000 -}); - -export = testRunner; diff --git a/extensions/markdown/src/test/tableOfContentsProvider.test.ts b/extensions/markdown/src/test/tableOfContentsProvider.test.ts deleted file mode 100644 index 7c1a46f641..0000000000 --- a/extensions/markdown/src/test/tableOfContentsProvider.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import * as vscode from 'vscode'; -import 'mocha'; - -import { TableOfContentsProvider } from '../tableOfContentsProvider'; -import { MarkdownEngine } from '../markdownEngine'; - -const testFileName = vscode.Uri.parse('test.md'); - -suite('markdown.TableOfContentsProvider', () => { - test('Lookup should not return anything for empty document', async () => { - const doc = new InMemoryDocument(testFileName, ''); - const provider = new TableOfContentsProvider(new MarkdownEngine(), doc); - - assert.strictEqual(await provider.lookup(''), undefined); - assert.strictEqual(await provider.lookup('foo'), undefined); - }); - - test('Lookup should not return anything for document with no headers', async () => { - const doc = new InMemoryDocument(testFileName, 'a *b*\nc'); - const provider = new TableOfContentsProvider(new MarkdownEngine(), doc); - - assert.strictEqual(await provider.lookup(''), undefined); - assert.strictEqual(await provider.lookup('foo'), undefined); - assert.strictEqual(await provider.lookup('a'), undefined); - assert.strictEqual(await provider.lookup('b'), undefined); - }); - - test('Lookup should return basic #header', async () => { - const doc = new InMemoryDocument(testFileName, `# a\nx\n# c`); - const provider = new TableOfContentsProvider(new MarkdownEngine(), doc); - - { - const entry = await provider.lookup('a'); - assert.ok(entry); - assert.strictEqual(entry!.line, 0); - } - { - assert.strictEqual(await provider.lookup('x'), undefined); - } - { - const entry = await provider.lookup('c'); - assert.ok(entry); - assert.strictEqual(entry!.line, 2); - } - }); - - test('Lookups should be case in-sensitive', async () => { - const doc = new InMemoryDocument(testFileName, `# fOo\n`); - const provider = new TableOfContentsProvider(new MarkdownEngine(), doc); - - assert.strictEqual((await provider.lookup('fOo'))!.line, 0); - assert.strictEqual((await provider.lookup('foo'))!.line, 0); - assert.strictEqual((await provider.lookup('FOO'))!.line, 0); - }); - - test('Lookups should ignore leading and trailing white-space, and collapse internal whitespace', async () => { - const doc = new InMemoryDocument(testFileName, `# f o o \n`); - const provider = new TableOfContentsProvider(new MarkdownEngine(), doc); - - assert.strictEqual((await provider.lookup('f o o'))!.line, 0); - assert.strictEqual((await provider.lookup(' f o o'))!.line, 0); - assert.strictEqual((await provider.lookup(' f o o '))!.line, 0); - assert.strictEqual((await provider.lookup('f o o'))!.line, 0); - assert.strictEqual((await provider.lookup('f o o'))!.line, 0); - - assert.strictEqual(await provider.lookup('f'), undefined); - assert.strictEqual(await provider.lookup('foo'), undefined); - assert.strictEqual(await provider.lookup('fo o'), undefined); - }); -}); - -class InMemoryDocument implements vscode.TextDocument { - private readonly _lines: string[]; - - constructor( - public readonly uri: vscode.Uri, - private readonly _contents: string - ) { - this._lines = this._contents.split(/\n/g); - } - - fileName: string = ''; - isUntitled: boolean = false; - languageId: string = ''; - version: number = 1; - isDirty: boolean = false; - isClosed: boolean = false; - eol: vscode.EndOfLine = vscode.EndOfLine.LF; - - get lineCount(): number { - return this._lines.length; - } - - lineAt(line: any): vscode.TextLine { - return { - lineNumber: line, - text: this._lines[line], - range: new vscode.Range(0, 0, 0, 0), - firstNonWhitespaceCharacterIndex: 0, - rangeIncludingLineBreak: new vscode.Range(0, 0, 0, 0), - isEmptyOrWhitespace: false - }; - } - offsetAt(_position: vscode.Position): never { - throw new Error('Method not implemented.'); - } - positionAt(_offset: number): never { - throw new Error('Method not implemented.'); - } - getText(_range?: vscode.Range | undefined): string { - return this._contents; - } - getWordRangeAtPosition(_position: vscode.Position, _regex?: RegExp | undefined): never { - throw new Error('Method not implemented.'); - } - validateRange(_range: vscode.Range): never { - throw new Error('Method not implemented.'); - } - validatePosition(_position: vscode.Position): never { - throw new Error('Method not implemented.'); - } - save(): never { - throw new Error('Method not implemented.'); - } -} diff --git a/extensions/markdown/src/typings/markdown-it-named-headers.d.ts b/extensions/markdown/src/typings/markdown-it-named-headers.d.ts deleted file mode 100644 index b525589725..0000000000 --- a/extensions/markdown/src/typings/markdown-it-named-headers.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -declare module 'markdown-it-named-headers' { } \ No newline at end of file diff --git a/extensions/markdown/src/typings/ref.d.ts b/extensions/markdown/src/typings/ref.d.ts deleted file mode 100644 index 37d9f00e11..0000000000 --- a/extensions/markdown/src/typings/ref.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/// <reference path='../../../../src/vs/vscode.d.ts'/> -/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/> -/// <reference types='@types/node'/> diff --git a/extensions/markdown/src/util/file.ts b/extensions/markdown/src/util/file.ts deleted file mode 100644 index c8acf43f6e..0000000000 --- a/extensions/markdown/src/util/file.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -export function isMarkdownFile(document: vscode.TextDocument) { - return document.languageId === 'markdown'; -} \ No newline at end of file diff --git a/extensions/markdown/src/util/topmostLineMonitor.ts b/extensions/markdown/src/util/topmostLineMonitor.ts deleted file mode 100644 index b5fc311909..0000000000 --- a/extensions/markdown/src/util/topmostLineMonitor.ts +++ /dev/null @@ -1,75 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; - -import { disposeAll } from '../util/dispose'; -import { isMarkdownFile } from './file'; - - -export class MarkdownFileTopmostLineMonitor { - private readonly disposables: vscode.Disposable[] = []; - - private readonly pendingUpdates = new Map<string, number>(); - - constructor() { - vscode.window.onDidChangeTextEditorVisibleRanges(event => { - if (isMarkdownFile(event.textEditor.document)) { - const line = getVisibleLine(event.textEditor); - if (line) { - this.updateLine(event.textEditor.document.uri, line); - } - } - }, null, this.disposables); - } - - dispose() { - disposeAll(this.disposables); - } - - private readonly _onDidChangeTopmostLineEmitter = new vscode.EventEmitter<{ resource: vscode.Uri, line: number }>(); - public readonly onDidChangeTopmostLine = this._onDidChangeTopmostLineEmitter.event; - - private updateLine( - resource: vscode.Uri, - line: number - ) { - const key = resource.toString(); - if (!this.pendingUpdates.has(key)) { - // schedule update - setTimeout(() => { - if (this.pendingUpdates.has(key)) { - this._onDidChangeTopmostLineEmitter.fire({ - resource, - line: this.pendingUpdates.get(key) as number - }); - this.pendingUpdates.delete(key); - } - }, 50); - } - - this.pendingUpdates.set(key, line); - } -} - -/** - * Get the top-most visible range of `editor`. - * - * Returns a fractional line number based the visible character within the line. - * Floor to get real line number - */ -export function getVisibleLine( - editor: vscode.TextEditor -): number | undefined { - if (!editor.visibleRanges.length) { - return undefined; - } - - const firstVisiblePosition = editor.visibleRanges[0].start; - const lineNumber = firstVisiblePosition.line; - const line = editor.document.lineAt(lineNumber); - const progress = firstVisiblePosition.character / (line.text.length + 2); - return lineNumber + progress; -} diff --git a/extensions/markdown/tsconfig.json b/extensions/markdown/tsconfig.json deleted file mode 100644 index b0c5b388ee..0000000000 --- a/extensions/markdown/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2017", - "lib": [ - "es6", - "es2015.promise", - "dom" - ], - "outDir": "./out", - "sourceMap": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "strict": true, - "alwaysStrict": true - }, - "include": [ - "src/**/*" - ] -} \ No newline at end of file diff --git a/extensions/markdown/yarn.lock b/extensions/markdown/yarn.lock deleted file mode 100644 index 18049ad211..0000000000 --- a/extensions/markdown/yarn.lock +++ /dev/null @@ -1,1798 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/highlight.js@9.1.10": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.1.10.tgz#b621f809cd9573b80992b90cffc5788208e3069c" - -"@types/markdown-it@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" - -"@types/node@7.0.43": - version "7.0.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" - -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - dependencies: - ansi-wrap "0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - -applicationinsights@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927" - dependencies: - diagnostic-channel "0.2.0" - diagnostic-channel-publishers "0.2.1" - zone.js "0.7.6" - -argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - -clone@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - -cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" - dependencies: - inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" - -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - -commander@^2.9.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -convert-source-map@^1.1.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - dependencies: - boom "5.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - dependencies: - ms "2.0.0" - -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - dependencies: - is-obj "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -diagnostic-channel-publishers@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" - -diagnostic-channel@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" - dependencies: - semver "^5.3.0" - -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - dependencies: - readable-stream "~1.1.9" - -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - -duplexify@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - dependencies: - once "^1.4.0" - -entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fancy-log@^1.1.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.2, glob@^7.0.5, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" - dependencies: - multimatch "^2.0.0" - plugin-error "^0.1.2" - streamfilter "^1.0.5" - -gulp-gunzip@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz#15b741145e83a9c6f50886241b57cc5871f151a9" - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1" - dependencies: - event-stream "~3.3.4" - node.extend "~1.1.2" - request "~2.79.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.0.tgz#c165320732d192ce56fd94271ffa123234bf2ae0" - dependencies: - event-stream "^3.3.1" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz#24e40685dc05b7149995245099e0590263be8dad" - dependencies: - event-stream "^3.3.1" - queue "^4.2.1" - through2 "^2.0.3" - vinyl "^2.0.2" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - dependencies: - glogg "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - dependencies: - sparkles "^1.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - -highlight.js@9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.5.0.tgz#46ae51b9db00f70052bcdf196cd404757b6582ae" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-my-json-valid@^2.12.4: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - -is@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - dependencies: - readable-stream "^2.0.5" - -linkify-it@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" - dependencies: - uc.micro "^1.0.1" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - -markdown-it-named-headers@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/markdown-it-named-headers/-/markdown-it-named-headers-0.0.4.tgz#82efc28324240a6b1e77b9aae501771d5f351c1f" - dependencies: - string "^3.0.1" - -markdown-it@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d" - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.3" - -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - dependencies: - mime-db "~1.30.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" - dependencies: - is "^3.1.0" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - -qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - -queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - dependencies: - inherits "~2.0.0" - -queue@^4.2.1: - version "4.4.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-4.4.2.tgz#5a9733d9a8b8bd1b36e934bc9c55ab89b28e29c7" - dependencies: - inherits "~2.0.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - -request@^2.83.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -requires-port@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - -rimraf@2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -semver@^5.3.0, semver@^5.4.1: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - -source-map-support@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.3.tgz#2b3d5fff298cfa4d1afd7d4352d569e9a0158e76" - dependencies: - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - -streamfilter@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - -string@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/string/-/string-3.3.1.tgz#8d2757ec1c0e6c526796fbb6b14036a4098398b7" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - dependencies: - has-flag "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - dependencies: - extend-shallow "^2.0.1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -uc.micro@^1.0.1, uc.micro@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" - -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -url-parse@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - dependencies: - querystringify "~1.0.0" - requires-port "~1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^3.0.0, uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" - dependencies: - through2 "^2.0.3" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vscode-extension-telemetry@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856" - dependencies: - applicationinsights "1.0.1" - -vscode-nls@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51" - -vscode@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.10.tgz#d1cba378ab24f1d3ddf9cd470d242ee1472dd35b" - dependencies: - glob "^7.1.2" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.1" - gulp-gunzip "1.0.0" - gulp-remote-src "^0.4.3" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^2.1.0" - mocha "^4.0.1" - request "^2.83.0" - semver "^5.4.1" - source-map-support "^0.5.0" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -yauzl@^2.2.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.0.1" - -yazl@^2.2.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" - dependencies: - buffer-crc32 "~0.2.3" - -zone.js@0.7.6: - version "0.7.6" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/package.json b/extensions/package.json index 2185edb0ce..d3693f4971 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -2,8 +2,8 @@ "name": "vscode-extensions", "version": "0.0.1", "description": "Dependencies shared by all extensions", - "devDependencies": { - "typescript": "2.7.2" + "dependencies": { + "typescript": "2.8.3" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/powershell/language-configuration.json b/extensions/powershell/language-configuration.json index 29445c790a..02e7a9ddec 100644 --- a/extensions/powershell/language-configuration.json +++ b/extensions/powershell/language-configuration.json @@ -14,7 +14,6 @@ ["(", ")"], { "open": "\"", "close": "\"", "notIn": ["string"]}, { "open": "'", "close": "'", "notIn": ["string", "comment"]}, - ["/**", " */"], ["<#", "#>"] ], "surroundingPairs": [ diff --git a/extensions/powershell/package.json b/extensions/powershell/package.json index 37ab53991f..5fcb928726 100644 --- a/extensions/powershell/package.json +++ b/extensions/powershell/package.json @@ -10,6 +10,7 @@ "id": "powershell", "extensions": [ ".ps1", ".psm1", ".psd1", ".pssc", ".psrc" ], "aliases": [ "PowerShell", "powershell", "ps", "ps1" ], + "firstLine": "^#!/.*\\bpwsh\\b", "configuration": "./language-configuration.json" }], "grammars": [{ @@ -25,4 +26,4 @@ "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js PowerShell/EditorSyntax PowerShellSyntax.tmLanguage ./syntaxes/powershell.tmLanguage.json" } -} \ No newline at end of file +} diff --git a/extensions/python/language-configuration.json b/extensions/python/language-configuration.json index c2c4aabc86..4717d09750 100644 --- a/extensions/python/language-configuration.json +++ b/extensions/python/language-configuration.json @@ -43,8 +43,8 @@ "folding": { "offSide": true, "markers": { - "start": "^\\s*#region\\b", - "end": "^\\s*#endregion\\b" + "start": "^\\s*#\\s*region\\b", + "end": "^\\s*#\\s*endregion\\b" } } } diff --git a/extensions/r/syntaxes/r.tmLanguage.json b/extensions/r/syntaxes/r.tmLanguage.json index d9d295d626..db37b8421f 100644 --- a/extensions/r/syntaxes/r.tmLanguage.json +++ b/extensions/r/syntaxes/r.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Ikuyadeu/vscode-R/commit/b3ef459a3999160d97ea28f4754fda810417f99f", + "version": "https://github.com/Ikuyadeu/vscode-R/commit/1cd3d42a6b2e54276ef2d71fe33bb3fefb1d6cff", "name": "R", "scopeName": "source.r", "patterns": [ @@ -168,6 +168,10 @@ "match": "(\\-|\\+|\\*|\\/|%\\/%|%%|%\\*%|%o%|%x%|\\^)", "name": "keyword.operator.arithmetic.r" }, + { + "match": "<=|>=", + "name": "keyword.operator.comparison.r" + }, { "match": "==", "name": "keyword.operator.comarison.r" @@ -177,7 +181,7 @@ "name": "keyword.operator.assignment.r" }, { - "match": "(!=|<>|<|>|<=|>=|%in%)", + "match": "(!=|<>|<|>|%in%)", "name": "keyword.operator.comparison.r" }, { diff --git a/extensions/shellscript/.vscodeignore b/extensions/shellscript/.vscodeignore deleted file mode 100644 index 77ab386fc7..0000000000 --- a/extensions/shellscript/.vscodeignore +++ /dev/null @@ -1 +0,0 @@ -test/** \ No newline at end of file diff --git a/extensions/shellscript/OSSREADME.json b/extensions/shellscript/OSSREADME.json deleted file mode 100644 index 3776c2af3c..0000000000 --- a/extensions/shellscript/OSSREADME.json +++ /dev/null @@ -1,9 +0,0 @@ -// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: - -[{ - "name": "atom/language-shellscript", - "version": "0.0.0", - "license": "MIT", - "repositoryURL": "https://github.com/atom/language-shellscript", - "description": "The file syntaxes/shell-unix-bash.tmLanguage.json was derived from the Atom package https://github.com/atom/language-shellscript which was originally converted from the TextMate bundle https://github.com/textmate/shellscript.tmbundle." -}] diff --git a/extensions/shellscript/language-configuration.json b/extensions/shellscript/language-configuration.json deleted file mode 100644 index 01b6a8a282..0000000000 --- a/extensions/shellscript/language-configuration.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "comments": { - "lineComment": "#" - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"], - ["`", "`"] - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"], - ["`", "`"] - ] -} \ No newline at end of file diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json deleted file mode 100644 index 446e98b078..0000000000 --- a/extensions/shellscript/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "shellscript", - "displayName": "%displayName%", - "description": "%description%", - "version": "1.0.0", - "publisher": "vscode", - "engines": { "vscode": "*" }, - "scripts": { - "update-grammar": "node ../../build/npm/update-grammar.js atom/language-shellscript grammars/shell-unix-bash.cson ./syntaxes/shell-unix-bash.tmLanguage.json" - }, - "contributes": { - "languages": [{ - "id": "shellscript", - "aliases": ["Shell Script", "shellscript", "bash", "sh", "zsh"], - "extensions": [".sh", ".bash", ".bashrc", ".bash_aliases", ".bash_profile", ".bash_login", ".ebuild", ".install", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv", ".zsh-theme"], - "filenames": ["PKGBUILD"], - "firstLine": "^#!.*\\b(bash|zsh|sh|tcsh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-", - "configuration": "./language-configuration.json", - "mimetypes": ["text/x-shellscript"] - }], - "grammars": [{ - "language": "shellscript", - "scopeName": "source.shell", - "path": "./syntaxes/shell-unix-bash.tmLanguage.json" - }] - } -} diff --git a/extensions/shellscript/package.nls.json b/extensions/shellscript/package.nls.json deleted file mode 100644 index 9360510f79..0000000000 --- a/extensions/shellscript/package.nls.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "displayName": "Shell Script Language Basics", - "description": "Provides syntax highlighting and bracket matching in Shell Script files." -} \ No newline at end of file diff --git a/extensions/shellscript/syntaxes/Shell-Unix-Bash.tmLanguage.json b/extensions/shellscript/syntaxes/Shell-Unix-Bash.tmLanguage.json deleted file mode 100644 index 0089e5aa5c..0000000000 --- a/extensions/shellscript/syntaxes/Shell-Unix-Bash.tmLanguage.json +++ /dev/null @@ -1,1283 +0,0 @@ -{ - "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-shellscript/blob/master/grammars/shell-unix-bash.cson", - "If you want to provide a fix or improvement, please create a pull request against the original repository.", - "Once accepted there, we are happy to receive an update request." - ], - "version": "https://github.com/atom/language-shellscript/commit/4c3711edbe8eac6f501976893976b1ac6a043d50", - "name": "Shell Script", - "scopeName": "source.shell", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#pipeline" - }, - { - "include": "#list" - }, - { - "include": "#compound-command" - }, - { - "include": "#loop" - }, - { - "include": "#string" - }, - { - "include": "#function-definition" - }, - { - "include": "#variable" - }, - { - "include": "#interpolation" - }, - { - "include": "#heredoc" - }, - { - "include": "#herestring" - }, - { - "include": "#redirection" - }, - { - "include": "#pathname" - }, - { - "include": "#keyword" - }, - { - "include": "#support" - } - ], - "repository": { - "case-clause": { - "patterns": [ - { - "begin": "(?=\\S)", - "end": ";;", - "endCaptures": { - "0": { - "name": "punctuation.terminator.case-clause.shell" - } - }, - "name": "meta.scope.case-clause.shell", - "patterns": [ - { - "begin": "\\(|(?=\\S)", - "beginCaptures": { - "0": { - "name": "punctuation.definition.case-pattern.shell" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.case-pattern.shell" - } - }, - "name": "meta.scope.case-pattern.shell", - "patterns": [ - { - "match": "\\|", - "name": "punctuation.separator.pipe-sign.shell" - }, - { - "include": "#string" - }, - { - "include": "#variable" - }, - { - "include": "#interpolation" - }, - { - "include": "#pathname" - } - ] - }, - { - "begin": "(?<=\\))", - "end": "(?=;;)", - "name": "meta.scope.case-clause-body.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - } - ] - }, - "comment": { - "begin": "(^\\s+)?(?<=^|\\W)(?<!-)(?=#)(?!#{)", - "beginCaptures": { - "1": { - "name": "punctuation.whitespace.comment.leading.shell" - } - }, - "end": "(?!\\G)", - "patterns": [ - { - "begin": "#!", - "beginCaptures": { - "0": { - "name": "punctuation.definition.comment.shebang.shell" - } - }, - "end": "$", - "name": "comment.line.number-sign.shebang.shell" - }, - { - "begin": "#", - "beginCaptures": { - "0": { - "name": "punctuation.definition.comment.shell" - } - }, - "end": "$", - "name": "comment.line.number-sign.shell" - } - ] - }, - "compound-command": { - "patterns": [ - { - "begin": "\\[{1,2}", - "beginCaptures": { - "0": { - "name": "punctuation.definition.logical-expression.shell" - } - }, - "end": "\\]{1,2}", - "endCaptures": { - "0": { - "name": "punctuation.definition.logical-expression.shell" - } - }, - "name": "meta.scope.logical-expression.shell", - "patterns": [ - { - "include": "#logical-expression" - }, - { - "include": "$self" - } - ] - }, - { - "begin": "\\({2}", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "\\){2}", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.other.math.shell", - "patterns": [ - { - "include": "#math" - } - ] - }, - { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.subshell.shell" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.subshell.shell" - } - }, - "name": "meta.scope.subshell.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=\\s|^){(?=\\s|$)", - "beginCaptures": { - "0": { - "name": "punctuation.definition.group.shell" - } - }, - "end": "(?<=^|;)\\s*(})", - "endCaptures": { - "1": { - "name": "punctuation.definition.group.shell" - } - }, - "name": "meta.scope.group.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - }, - "function-definition": { - "patterns": [ - { - "begin": "(?<=^|;|&|\\s)(function)\\s+([^\\s\\\\]+)(?:\\s*(\\(\\)))?", - "beginCaptures": { - "1": { - "name": "storage.type.function.shell" - }, - "2": { - "name": "entity.name.function.shell" - }, - "3": { - "name": "punctuation.definition.arguments.shell" - } - }, - "end": ";|&|$", - "endCaptures": { - "0": { - "name": "punctuation.definition.function.shell" - } - }, - "name": "meta.function.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)([^\\s\\\\=]+)\\s*(\\(\\))", - "beginCaptures": { - "1": { - "name": "entity.name.function.shell" - }, - "2": { - "name": "punctuation.definition.arguments.shell" - } - }, - "end": ";|&|$", - "endCaptures": { - "0": { - "name": "punctuation.definition.function.shell" - } - }, - "name": "meta.function.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - }, - "heredoc": { - "patterns": [ - { - "begin": "(<<)-\\s*(\"|'|)\\s*(RUBY)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(RUBY)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.ruby.shell", - "contentName": "source.ruby.embedded.shell", - "patterns": [ - { - "include": "source.ruby" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(RUBY)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(RUBY)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.ruby.shell", - "contentName": "source.ruby.embedded.shell", - "patterns": [ - { - "include": "source.ruby" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(PYTHON)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(PYTHON)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.python.shell", - "contentName": "source.python.embedded.shell", - "patterns": [ - { - "include": "source.python" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(PYTHON)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(PYTHON)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.python.shell", - "contentName": "source.python.embedded.shell", - "patterns": [ - { - "include": "source.python" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(APPLESCRIPT)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(APPLESCRIPT)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.applescript.shell", - "contentName": "source.applescript.embedded.shell", - "patterns": [ - { - "include": "source.applescript" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(APPLESCRIPT)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(APPLESCRIPT)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.applescript.shell", - "contentName": "source.applescript.embedded.shell", - "patterns": [ - { - "include": "source.applescript" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(HTML)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(HTML)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.html.shell", - "contentName": "text.html.embedded.shell", - "patterns": [ - { - "include": "text.html.basic" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(HTML)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(HTML)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.html.shell", - "contentName": "text.html.embedded.shell", - "patterns": [ - { - "include": "text.html.basic" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(MARKDOWN)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(MARKDOWN)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.markdown.shell", - "contentName": "text.html.markdown.embedded.shell", - "patterns": [ - { - "include": "text.html.markdown" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(MARKDOWN)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(MARKDOWN)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.markdown.shell", - "contentName": "text.html.markdown.embedded.shell", - "patterns": [ - { - "include": "text.html.markdown" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(TEXTILE)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(TEXTILE)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.textile.shell", - "contentName": "text.html.textile.embedded.shell", - "patterns": [ - { - "include": "text.html.textile" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(TEXTILE)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(TEXTILE)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.textile.shell", - "contentName": "text.html.textile.embedded.shell", - "patterns": [ - { - "include": "text.html.textile" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*(SHELL)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(\\3)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "contentName": "source.shell.embedded.shell", - "name": "string.unquoted.heredoc.no-indent.shell.shell", - "patterns": [ - { - "include": "source.shell" - } - ] - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*(SHELL)(?=\\s|;|&|<|\"|')\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(\\3)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.shell.shell", - "contentName": "source.shell.embedded.shell", - "patterns": [ - { - "include": "source.shell" - } - ] - }, - { - "begin": "(<<)-\\s*(\"|'|)\\s*\\\\?([^;&<\\s]+)\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^\\t*(\\3)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.no-indent.shell" - }, - { - "begin": "(<<)\\s*(\"|'|)\\s*\\\\?([^;&<\\s]+)\\2", - "beginCaptures": { - "1": { - "name": "keyword.operator.heredoc.shell" - }, - "3": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "end": "^(\\3)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.heredoc-token.shell" - } - }, - "name": "string.unquoted.heredoc.shell" - } - ] - }, - "herestring": { - "patterns": [ - { - "begin": "(<<<)\\s*(('))", - "beginCaptures": { - "1": { - "name": "keyword.operator.herestring.shell" - }, - "2": { - "name": "string.quoted.single.shell" - }, - "3": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "(')", - "endCaptures": { - "0": { - "name": "string.quoted.single.shell" - }, - "1": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "meta.herestring.shell", - "contentName": "string.quoted.single.shell" - }, - { - "begin": "(<<<)\\s*((\"))", - "beginCaptures": { - "1": { - "name": "keyword.operator.herestring.shell" - }, - "2": { - "name": "string.quoted.double.shell" - }, - "3": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "(\")", - "endCaptures": { - "0": { - "name": "string.quoted.double.shell" - }, - "1": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "meta.herestring.shell", - "contentName": "string.quoted.double.shell" - }, - { - "captures": { - "1": { - "name": "keyword.operator.herestring.shell" - }, - "2": { - "name": "string.unquoted.herestring.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - }, - "match": "(<<<)\\s*(([^\\s)\\\\]|\\\\.)+)", - "name": "meta.herestring.shell" - } - ] - }, - "interpolation": { - "patterns": [ - { - "begin": "\\$\\({2}", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "\\){2}", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.other.math.shell", - "patterns": [ - { - "include": "#math" - } - ] - }, - { - "begin": "`", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "`", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.interpolated.backtick.shell", - "patterns": [ - { - "match": "\\\\[`\\\\$]", - "name": "constant.character.escape.shell" - }, - { - "begin": "(?<=\\W)(?=#)(?!#{)", - "beginCaptures": { - "1": { - "name": "punctuation.whitespace.comment.leading.shell" - } - }, - "end": "(?!\\G)", - "patterns": [ - { - "begin": "#", - "beginCaptures": { - "0": { - "name": "punctuation.definition.comment.shell" - } - }, - "end": "(?=`)", - "name": "comment.line.number-sign.shell" - } - ] - }, - { - "include": "$self" - } - ] - }, - { - "begin": "\\$\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.interpolated.dollar.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - }, - "keyword": { - "patterns": [ - { - "match": "(?<=^|;|&|\\s)(then|else|elif|fi|for|in|do|done|select|case|continue|esac|while|until|return)(?=\\s|;|&|$)", - "name": "keyword.control.shell" - }, - { - "match": "(?<=^|;|&|\\s)(?:export|declare|typeset|local|readonly)(?=\\s|;|&|$)", - "name": "storage.modifier.shell" - } - ] - }, - "list": { - "patterns": [ - { - "match": ";|&&|&|\\|\\|", - "name": "keyword.operator.list.shell" - } - ] - }, - "logical-expression": { - "patterns": [ - { - "comment": "do we want a special rule for ( expr )?", - "match": "=[=~]?|!=?|<|>|&&|\\|\\|", - "name": "keyword.operator.logical.shell" - }, - { - "match": "(?<!\\S)-(nt|ot|ef|eq|ne|l[te]|g[te]|[a-hknoprstuwxzOGLSN])", - "name": "keyword.operator.logical.shell" - } - ] - }, - "loop": { - "patterns": [ - { - "begin": "(?<=^|;|&|\\s)(for)\\s+(?=\\({2})", - "beginCaptures": { - "1": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)done(?=\\s|;|&|$)", - "endCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.for-loop.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)(for)\\s+(.+?)\\s+(in)(?=\\s|;|&|$)", - "beginCaptures": { - "1": { - "name": "keyword.control.shell" - }, - "2": { - "name": "variable.other.loop.shell", - "patterns": [ - { - "include": "#string" - } - ] - }, - "3": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)done(?=\\s|;|&|$)", - "endCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.for-in-loop.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)(while|until)(?=\\s|;|&|$)", - "beginCaptures": { - "1": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)done(?=\\s|;|&|$)", - "endCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.while-loop.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)(select)\\s+((?:[^\\s\\\\]|\\\\.)+)(?=\\s|;|&|$)", - "beginCaptures": { - "1": { - "name": "keyword.control.shell" - }, - "2": { - "name": "variable.other.loop.shell" - } - }, - "end": "(?<=^|;|&|\\s)(done)(?=\\s|;|&|$)", - "endCaptures": { - "1": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.select-block.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)case(?=\\s|;|&|$)", - "beginCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)esac(?=\\s|;|&|$)", - "endCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.case-block.shell", - "patterns": [ - { - "begin": "(?<=^|;|&|\\s)in(?=\\s|;|&|$)", - "beginCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)(?=esac(\\s|;|&|$))", - "name": "meta.scope.case-body.shell", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#case-clause" - }, - { - "include": "$self" - } - ] - }, - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=^|;|&|\\s)if(?=\\s|;|&|$)", - "beginCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "end": "(?<=^|;|&|\\s)fi(?=\\s|;|&|$)", - "endCaptures": { - "0": { - "name": "keyword.control.shell" - } - }, - "name": "meta.scope.if-block.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - }, - "math": { - "patterns": [ - { - "include": "#variable" - }, - { - "match": "\\+{1,2}|-{1,2}|!|~|\\*{1,2}|/|%|<[<=]?|>[>=]?|==|!=|^|\\|{1,2}|&{1,2}|\\?|\\:|,|=|[*/%+\\-&^|]=|<<=|>>=", - "name": "keyword.operator.arithmetic.shell" - }, - { - "match": "0[xX][0-9A-Fa-f]+", - "name": "constant.numeric.hex.shell" - }, - { - "match": "0\\d+", - "name": "constant.numeric.octal.shell" - }, - { - "match": "\\d{1,2}#[0-9a-zA-Z@_]+", - "name": "constant.numeric.other.shell" - }, - { - "match": "\\d+", - "name": "constant.numeric.integer.shell" - } - ] - }, - "pathname": { - "patterns": [ - { - "match": "(?<=\\s|:|=|^)~", - "name": "keyword.operator.tilde.shell" - }, - { - "match": "\\*|\\?", - "name": "keyword.operator.glob.shell" - }, - { - "begin": "([?*+@!])(\\()", - "beginCaptures": { - "1": { - "name": "keyword.operator.extglob.shell" - }, - "2": { - "name": "punctuation.definition.extglob.shell" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.extglob.shell" - } - }, - "name": "meta.structure.extglob.shell", - "patterns": [ - { - "include": "$self" - } - ] - } - ] - }, - "pipeline": { - "patterns": [ - { - "match": "(?<=^|;|&|\\s)(time)(?=\\s|;|&|$)", - "name": "keyword.other.shell" - }, - { - "match": "[|!]", - "name": "keyword.operator.pipe.shell" - } - ] - }, - "redirection": { - "patterns": [ - { - "begin": "[><]\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.interpolated.process-substitution.shell", - "patterns": [ - { - "include": "$self" - } - ] - }, - { - "match": "(?<![<>])(&>|\\d*>&\\d*|\\d*(>>|>|<)|\\d*<&|\\d*<>)(?![<>])", - "name": "keyword.operator.redirect.shell" - } - ] - }, - "string": { - "patterns": [ - { - "match": "\\\\.", - "name": "constant.character.escape.shell" - }, - { - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "'", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.quoted.single.shell" - }, - { - "begin": "\\$?\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "\"", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.quoted.double.shell", - "patterns": [ - { - "match": "\\\\[\\$`\"\\\\\\n]", - "name": "constant.character.escape.shell" - }, - { - "include": "#variable" - }, - { - "include": "#interpolation" - } - ] - }, - { - "begin": "\\$'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.shell" - } - }, - "end": "'", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.shell" - } - }, - "name": "string.quoted.single.dollar.shell", - "patterns": [ - { - "match": "\\\\(a|b|e|f|n|r|t|v|\\\\|')", - "name": "constant.character.escape.ansi-c.shell" - }, - { - "match": "\\\\[0-9]{3}", - "name": "constant.character.escape.octal.shell" - }, - { - "match": "\\\\x[0-9a-fA-F]{2}", - "name": "constant.character.escape.hex.shell" - }, - { - "match": "\\\\c.", - "name": "constant.character.escape.control-char.shell" - } - ] - } - ] - }, - "support": { - "patterns": [ - { - "match": "(?<=^|;|&|\\s)(?::|\\.)(?=\\s|;|&|$)", - "name": "support.function.builtin.shell" - }, - { - "match": "(?<=^|;|&|\\s)(?:alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|times|trap|true|type|ulimit|umask|unalias|unset|wait)(?=\\s|;|&|$)", - "name": "support.function.builtin.shell" - } - ] - }, - "variable": { - "patterns": [ - { - "captures": { - "1": { - "name": "punctuation.definition.variable.shell" - } - }, - "match": "(\\$)[a-zA-Z_][a-zA-Z0-9_]*", - "name": "variable.other.normal.shell" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.variable.shell" - } - }, - "match": "(\\$)[-*@#?$!0_]", - "name": "variable.other.special.shell" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.variable.shell" - } - }, - "match": "(\\$)[1-9]", - "name": "variable.other.positional.shell" - }, - { - "begin": "\\${", - "beginCaptures": { - "0": { - "name": "punctuation.definition.variable.shell" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.variable.shell" - } - }, - "name": "variable.other.bracket.shell", - "patterns": [ - { - "match": "!|:[-=?]?|\\*|@|#{1,2}|%{1,2}|/", - "name": "keyword.operator.expansion.shell" - }, - { - "captures": { - "1": { - "name": "punctuation.section.array.shell" - }, - "3": { - "name": "punctuation.section.array.shell" - } - }, - "match": "(\\[)([^\\]]+)(\\])" - }, - { - "include": "#variable" - }, - { - "include": "#string" - } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/extensions/shellscript/test/colorize-fixtures/test.sh b/extensions/shellscript/test/colorize-fixtures/test.sh deleted file mode 100644 index 4c5bf8f7ea..0000000000 --- a/extensions/shellscript/test/colorize-fixtures/test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" == "darwin"* ]]; then - realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; } - ROOT=$(dirname $(dirname $(realpath "$0"))) -else - ROOT=$(dirname $(dirname $(readlink -f $0))) -fi - -DEVELOPER=$(xcode-select -print-path) -LIPO=$(xcrun -sdk iphoneos -find lipo) - -function code() { - cd $ROOT - - # Node modules - test -d node_modules || ./scripts/npm.sh install - - # Configuration - export NODE_ENV=development - - # Launch Code - if [[ "$OSTYPE" == "darwin"* ]]; then - exec ./.build/electron/Electron.app/Contents/MacOS/Electron . "$@" - else - exec ./.build/electron/electron . "$@" - fi -} - -code "$@" diff --git a/extensions/shellscript/test/colorize-results/test_sh.json b/extensions/shellscript/test/colorize-results/test_sh.json deleted file mode 100644 index 36a9ce993e..0000000000 --- a/extensions/shellscript/test/colorize-results/test_sh.json +++ /dev/null @@ -1,1960 +0,0 @@ -[ - { - "c": "#!", - "t": "source.shell comment.line.number-sign.shebang.shell punctuation.definition.comment.shebang.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": "/usr/bin/env bash", - "t": "source.shell comment.line.number-sign.shebang.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": "if", - "t": "source.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[[", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell variable.other.normal.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "OSTYPE", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell variable.other.normal.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "==", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell keyword.operator.logical.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "darwin", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "*", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell keyword.operator.glob.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "]]", - "t": "source.shell meta.scope.if-block.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.shell meta.scope.if-block.shell keyword.operator.list.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "then", - "t": "source.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "\t", - "t": "source.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "realpath", - "t": "source.shell meta.scope.if-block.shell meta.function.shell entity.name.function.shell", - "r": { - "dark_plus": "entity.name.function: #DCDCAA", - "light_plus": "entity.name.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "entity.name.function: #DCDCAA" - } - }, - { - "c": "()", - "t": "source.shell meta.scope.if-block.shell meta.function.shell punctuation.definition.arguments.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "{", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell punctuation.definition.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[[", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell variable.other.positional.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "1", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell variable.other.positional.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell keyword.operator.logical.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " /", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "*", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell keyword.operator.glob.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "]]", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "&&", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell keyword.operator.list.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "echo", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.positional.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "1", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.positional.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "||", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell keyword.operator.pipe.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "echo", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.normal.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "PWD", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.normal.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "/", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "${", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "1", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "#", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell keyword.operator.expansion.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": ".", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "/", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell keyword.operator.expansion.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": "}", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell variable.other.bracket.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ";", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell keyword.operator.list.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "}", - "t": "source.shell meta.scope.if-block.shell meta.function.shell meta.scope.group.shell punctuation.definition.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\tROOT=", - "t": "source.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "dirname ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "dirname ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "realpath ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.quoted.double.shell variable.other.special.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "0", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.quoted.double.shell variable.other.special.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "else", - "t": "source.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "\tROOT=", - "t": "source.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "dirname ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "dirname ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$(", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "readlink -f ", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell variable.other.special.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "0", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell variable.other.special.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell meta.scope.if-block.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "fi", - "t": "source.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "DEVELOPER=", - "t": "source.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$(", - "t": "source.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "xcode-select -print-path", - "t": "source.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "LIPO=", - "t": "source.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$(", - "t": "source.shell string.interpolated.dollar.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "xcrun -sdk iphoneos -find lipo", - "t": "source.shell string.interpolated.dollar.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.shell string.interpolated.dollar.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "function", - "t": "source.shell meta.function.shell storage.type.function.shell", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "code()", - "t": "source.shell meta.function.shell entity.name.function.shell", - "r": { - "dark_plus": "entity.name.function: #DCDCAA", - "light_plus": "entity.name.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "entity.name.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "{", - "t": "source.shell meta.function.shell meta.scope.group.shell punctuation.definition.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "cd", - "t": "source.shell meta.function.shell meta.scope.group.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "$", - "t": "source.shell meta.function.shell meta.scope.group.shell variable.other.normal.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "ROOT", - "t": "source.shell meta.function.shell meta.scope.group.shell variable.other.normal.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell punctuation.whitespace.comment.leading.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "#", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell punctuation.definition.comment.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": " Node modules", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "test", - "t": "source.shell meta.function.shell meta.scope.group.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " -d node_modules ", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "||", - "t": "source.shell meta.function.shell meta.scope.group.shell keyword.operator.pipe.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ./scripts/npm.sh install", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell punctuation.whitespace.comment.leading.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "#", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell punctuation.definition.comment.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": " Configuration", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "export", - "t": "source.shell meta.function.shell meta.scope.group.shell storage.modifier.shell", - "r": { - "dark_plus": "storage.modifier: #569CD6", - "light_plus": "storage.modifier: #0000FF", - "dark_vs": "storage.modifier: #569CD6", - "light_vs": "storage.modifier: #0000FF", - "hc_black": "storage.modifier: #569CD6" - } - }, - { - "c": " NODE_ENV=development", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell punctuation.whitespace.comment.leading.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "#", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell punctuation.definition.comment.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": " Launch Code", - "t": "source.shell meta.function.shell meta.scope.group.shell comment.line.number-sign.shell", - "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", - "dark_vs": "comment: #608B4E", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "if", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[[", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell variable.other.normal.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "OSTYPE", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell variable.other.normal.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "==", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell keyword.operator.logical.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "darwin", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "*", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell keyword.operator.glob.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "]]", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell meta.scope.logical-expression.shell punctuation.definition.logical-expression.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell keyword.operator.list.shell", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "then", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "\t\t", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "exec", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ./.build/electron/Electron.app/Contents/MacOS/Electron ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell variable.other.special.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "@", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell variable.other.special.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "else", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "\t\t", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "exec", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ./.build/electron/electron ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell support.function.builtin.shell", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell variable.other.special.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "@", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell variable.other.special.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\t", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "fi", - "t": "source.shell meta.function.shell meta.scope.group.shell meta.scope.if-block.shell keyword.control.shell", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": "}", - "t": "source.shell meta.function.shell meta.scope.group.shell punctuation.definition.group.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "code ", - "t": "source.shell", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.shell string.quoted.double.shell punctuation.definition.string.begin.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "$", - "t": "source.shell string.quoted.double.shell variable.other.special.shell punctuation.definition.variable.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "@", - "t": "source.shell string.quoted.double.shell variable.other.special.shell", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": "\"", - "t": "source.shell string.quoted.double.shell punctuation.definition.string.end.shell", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - } -] \ No newline at end of file diff --git a/extensions/theme-abyss/themes/abyss-color-theme.json b/extensions/theme-abyss/themes/abyss-color-theme.json index 3522dabcfb..85f5f9a4a9 100644 --- a/extensions/theme-abyss/themes/abyss-color-theme.json +++ b/extensions/theme-abyss/themes/abyss-color-theme.json @@ -309,10 +309,11 @@ "editor.lineHighlightBackground": "#082050", "editor.selectionBackground": "#770811", "editorIndentGuide.background": "#002952", + "editorIndentGuide.activeBackground": "#204972", "editorHoverWidget.background": "#000c38", "editorHoverWidget.border": "#004c18", "editorLineNumber.foreground": "#406385", - "editorActiveLineNumber.foreground": "#80a2c2", + "editorLineNumber.activeForeground": "#80a2c2", "editorMarkerNavigation.background": "#060621", "editorMarkerNavigationError.background": "#AB395B", "editorMarkerNavigationWarning.background": "#5B7E7A", @@ -409,10 +410,6 @@ "debugExceptionWidget.background": "#051336", "debugExceptionWidget.border": "#AB395B", - // Workbench: Notifications - "notification.background": "#182543", - // "notification.foreground": "", - // Workbench: Quick Open "pickerGroup.border": "#596F99", "pickerGroup.foreground": "#596F99", diff --git a/extensions/theme-carbon/themes/dark_carbon.json b/extensions/theme-carbon/themes/dark_carbon.json index 99aae6ff41..91b26ccd12 100644 --- a/extensions/theme-carbon/themes/dark_carbon.json +++ b/extensions/theme-carbon/themes/dark_carbon.json @@ -53,7 +53,8 @@ "editorLink.activeForeground": "#30B4FF", "editorGroup.border": "#333333", "editorGroup.background": "#212121", - "tab.activeBackground": "#212121", + "editorIndentGuide.activeBackground": "#707070", + "tab.activeBackground": "#212121", "tab.activeForeground": "#ffffff", "tab.inactiveBackground": "#444444", "tab.inactiveForeground": "#b6b6b6", diff --git a/extensions/theme-carbon/themes/light_carbon.json b/extensions/theme-carbon/themes/light_carbon.json index ea15f83139..1428340607 100644 --- a/extensions/theme-carbon/themes/light_carbon.json +++ b/extensions/theme-carbon/themes/light_carbon.json @@ -61,6 +61,7 @@ "editorLink.activeForeground": "#3062D6", "editorGroup.border": "#f4f4f4", "editorGroup.background": "#fffffe", + "editorIndentGuide.activeBackground": "#939393", // Workbench: Tabs "tab.activeBackground": "#FFFFFE", diff --git a/extensions/theme-defaults/themes/dark_defaults.json b/extensions/theme-defaults/themes/dark_defaults.json new file mode 100644 index 0000000000..cb9e20066b --- /dev/null +++ b/extensions/theme-defaults/themes/dark_defaults.json @@ -0,0 +1,15 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Dark Default Colors", + "colors": { + "editor.background": "#1E1E1E", + "editor.foreground": "#D4D4D4", + "editor.inactiveSelectionBackground": "#3A3D41", + "editorIndentGuide.background": "#404040", + "editorIndentGuide.activeBackground": "#707070", + "editor.selectionHighlightBackground": "#ADD6FF26", + "list.dropBackground": "#383B3D", + "activityBarBadge.background": "#007ACC", + "sideBarTitle.foreground": "#BBBBBB" + } +} \ No newline at end of file diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json new file mode 100644 index 0000000000..9767fa79c7 --- /dev/null +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -0,0 +1,163 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Dark+ (default dark)", + "include": "./dark_vs.json", + "tokenColors": [ + { + "name": "Function declarations", + "scope": [ + "entity.name.function", + "support.function", + "support.constant.handlebars" + ], + "settings": { + "foreground": "#DCDCAA" + } + }, + { + "name": "Types declaration and references", + "scope": [ + "meta.return-type", + "support.class", + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type.numeric.go", + "storage.type.byte.go", + "storage.type.boolean.go", + "storage.type.string.go", + "storage.type.uintptr.go", + "storage.type.cs", + "storage.type.generic.cs", + "storage.type.modifier.cs", + "storage.type.variable.cs", + "storage.type.annotation.java", + "storage.type.generic.java", + "storage.type.java", + "storage.type.object.array.java", + "storage.type.primitive.array.java", + "storage.type.primitive.java", + "storage.type.token.java", + "storage.type.groovy", + "storage.type.annotation.groovy", + "storage.type.parameters.groovy", + "storage.type.generic.groovy", + "storage.type.object.array.groovy", + "storage.type.primitive.array.groovy", + "storage.type.primitive.groovy" + ], + "settings": { + "foreground": "#4EC9B0" + } + }, + { + "name": "Types declaration and references, TS grammar specific", + "scope": [ + "meta.type.cast.expr", + "meta.type.new.expr", + "support.constant.math", + "support.constant.dom", + "support.constant.json", + "entity.other.inherited-class" + ], + "settings": { + "foreground": "#4EC9B0" + } + }, + { + "name": "Control flow keywords", + "scope": "keyword.control", + "settings": { + "foreground": "#C586C0" + } + }, + { + "name": "Variable and parameter name", + "scope": [ + "variable", + "meta.definition.variable.name", + "support.variable" + ], + "settings": { + "foreground": "#9CDCFE" + } + }, + { + "name": "Object keys, TS grammar specific", + "scope": [ + "meta.object-literal.key" + ], + "settings": { + "foreground": "#9CDCFE" + } + }, + { + "name": "CSS property value", + "scope": [ + "support.constant.property-value", + "support.constant.font-name", + "support.constant.media-type", + "support.constant.media", + "constant.other.color.rgb-value", + "constant.other.rgb-value", + "support.constant.color" + ], + "settings": { + "foreground": "#CE9178" + } + }, + { + "name": "Regular expression groups", + "scope": [ + "punctuation.definition.group.regexp", + "punctuation.definition.group.assertion.regexp", + "punctuation.definition.character-class.regexp", + "punctuation.character.set.begin.regexp", + "punctuation.character.set.end.regexp", + "keyword.operator.negation.regexp", + "support.other.parenthesis.regexp" + ], + "settings": { + "foreground": "#CE9178" + } + }, + { + "scope": [ + "constant.character.character-class.regexp", + "constant.other.character-class.set.regexp", + "constant.other.character-class.regexp", + "constant.character.set.regexp" + ], + "settings": { + "foreground": "#d16969" + } + }, + { + "scope": [ + "keyword.operator.or.regexp", + "keyword.control.anchor.regexp" + ], + "settings": { + "foreground": "#DCDCAA" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#d7ba7d" + } + }, + { + "scope": "constant.character", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#d7ba7d" + } + } + ] +} \ No newline at end of file diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json new file mode 100644 index 0000000000..c2a15addb8 --- /dev/null +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -0,0 +1,356 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Dark (Visual Studio)", + "include": "./dark_defaults.json", + "tokenColors": [ + { + "scope": [ + "meta.embedded", + "source.groovy.embedded" + ], + "settings": { + "foreground": "#D4D4D4" + } + }, + { + "scope": "emphasis", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": "strong", + "settings": { + "fontStyle": "bold" + } + }, + { + "scope": "header", + "settings": { + "foreground": "#000080" + } + }, + { + "scope": "comment", + "settings": { + "foreground": "#608b4e" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": [ + "constant.numeric" + ], + "settings": { + "foreground": "#b5cea8" + } + }, + { + "scope": "constant.regexp", + "settings": { + "foreground": "#646695" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "entity.name.tag.css", + "settings": { + "foreground": "#d7ba7d" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#9cdcfe" + } + }, + { + "scope": [ + "entity.other.attribute-name.class.css", + "entity.other.attribute-name.class.mixin.css", + "entity.other.attribute-name.id.css", + "entity.other.attribute-name.parent-selector.css", + "entity.other.attribute-name.pseudo-class.css", + "entity.other.attribute-name.pseudo-element.css", + "source.css.less entity.other.attribute-name.id", + "entity.other.attribute-name.attribute.scss", + "entity.other.attribute-name.scss" + ], + "settings": { + "foreground": "#d7ba7d" + } + }, + { + "scope": "invalid", + "settings": { + "foreground": "#f44747" + } + }, + { + "scope": "markup.underline", + "settings": { + "fontStyle": "underline" + } + }, + { + "scope": "markup.bold", + "settings": { + "fontStyle": "bold", + "foreground": "#569cd6" + } + }, + { + "scope": "markup.heading", + "settings": { + "fontStyle": "bold", + "foreground": "#569cd6" + } + }, + { + "scope": "markup.italic", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": "markup.inserted", + "settings": { + "foreground": "#b5cea8" + } + }, + { + "scope": "markup.deleted", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "markup.changed", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "beginning.punctuation.definition.quote.markdown", + "settings": { + "foreground": "#608b4e" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown", + "settings": { + "foreground": "#6796e6" + } + }, + { + "scope": "markup.inline.raw", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#d7ba7d" + } + }, + { + "name": "brackets of XML/HTML tags", + "scope": "punctuation.definition.tag", + "settings": { + "foreground": "#808080" + } + }, + { + "scope": "meta.preprocessor", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "meta.preprocessor.string", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "meta.preprocessor.numeric", + "settings": { + "foreground": "#b5cea8" + } + }, + { + "scope": "meta.structure.dictionary.key.python", + "settings": { + "foreground": "#9cdcfe" + } + }, + { + "scope": "meta.diff.header", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "storage", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "storage.type", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "storage.modifier", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "string", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "string.tag", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "string.value", + "settings": { + "foreground": "#ce9178" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#d16969" + } + }, + { + "name": "String interpolation", + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end", + "punctuation.section.embedded" + ], + "settings": { + "foreground": "#569cd6" + } + }, + { + "name": "Reset JavaScript string interpolation expression", + "scope": [ + "meta.template.expression" + ], + "settings": { + "foreground": "#d4d4d4" + } + }, + { + "scope": [ + "support.type.vendored.property-name", + "support.type.property-name", + "variable.css", + "variable.scss", + "variable.other.less", + "source.coffee.embedded" + ], + "settings": { + "foreground": "#9cdcfe" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#d4d4d4" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression", + "keyword.operator.cast", + "keyword.operator.sizeof", + "keyword.operator.instanceof", + "keyword.operator.logical.python" + ], + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#b5cea8" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin.php", + "punctuation.section.embedded.end.php" + ], + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "support.function.git-rebase", + "settings": { + "foreground": "#9cdcfe" + } + }, + { + "scope": "constant.sha.git-rebase", + "settings": { + "foreground": "#b5cea8" + } + }, + { + "name": "coloring of the Java import and package identifiers", + "scope": [ + "storage.modifier.import.java", + "variable.language.wildcard.java", + "storage.modifier.package.java" + ], + "settings": { + "foreground": "#d4d4d4" + } + }, + { + "name": "this.self", + "scope": "variable.language", + "settings": { + "foreground": "#569cd6" + } + } + ] +} \ No newline at end of file diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index 8833ff32c1..4acf07cd7a 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -5,6 +5,7 @@ "editor.background": "#000000", "editor.foreground": "#FFFFFF", "editorIndentGuide.background": "#FFFFFF", + "editorIndentGuide.activeBackground": "#FFFFFF", "sideBarTitle.foreground": "#FFFFFF" }, "settings": [ diff --git a/extensions/theme-defaults/themes/light_defaults.json b/extensions/theme-defaults/themes/light_defaults.json new file mode 100644 index 0000000000..2ee46debb3 --- /dev/null +++ b/extensions/theme-defaults/themes/light_defaults.json @@ -0,0 +1,17 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Light Default Colors", + "colors": { + "editor.background": "#FFFFFF", + "editor.foreground": "#000000", + "editor.inactiveSelectionBackground": "#E5EBF1", + "editorIndentGuide.background": "#D3D3D3", + "editorIndentGuide.activeBackground": "#939393", + "editor.selectionHighlightBackground": "#ADD6FF4D", + "editorSuggestWidget.background": "#F3F3F3", + "activityBarBadge.background": "#007ACC", + "sideBarTitle.foreground": "#6F6F6F", + "list.hoverBackground": "#E8E8E8", + "input.placeholderForeground": "#ADADAD" + } +} \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json new file mode 100644 index 0000000000..a4b6b642a9 --- /dev/null +++ b/extensions/theme-defaults/themes/light_plus.json @@ -0,0 +1,164 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Light+ (default light)", + "include": "./light_vs.json", + "tokenColors": [ + { + "name": "Function declarations", + "scope": [ + "entity.name.function", + "support.function", + "support.constant.handlebars" + ], + "settings": { + "foreground": "#795E26" + } + }, + { + "name": "Types declaration and references", + "scope": [ + "meta.return-type", + "support.class", + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type.numeric.go", + "storage.type.byte.go", + "storage.type.boolean.go", + "storage.type.string.go", + "storage.type.uintptr.go", + "storage.type.cs", + "storage.type.generic.cs", + "storage.type.modifier.cs", + "storage.type.variable.cs", + "storage.type.annotation.java", + "storage.type.generic.java", + "storage.type.java", + "storage.type.object.array.java", + "storage.type.primitive.array.java", + "storage.type.primitive.java", + "storage.type.token.java", + "storage.type.groovy", + "storage.type.annotation.groovy", + "storage.type.parameters.groovy", + "storage.type.generic.groovy", + "storage.type.object.array.groovy", + "storage.type.primitive.array.groovy", + "storage.type.primitive.groovy" + ], + "settings": { + "foreground": "#267f99" + } + }, + { + "name": "Types declaration and references, TS grammar specific", + "scope": [ + "meta.type.cast.expr", + "meta.type.new.expr", + "support.constant.math", + "support.constant.dom", + "support.constant.json", + "entity.other.inherited-class" + ], + "settings": { + "foreground": "#267f99" + } + }, + { + "name": "Control flow keywords", + "scope": "keyword.control", + "settings": { + "foreground": "#AF00DB" + } + }, + { + "name": "Variable and parameter name", + "scope": [ + "variable", + "meta.definition.variable.name", + "support.variable" + ], + "settings": { + "foreground": "#001080" + } + }, + { + "name": "Object keys, TS grammar specific", + "scope": [ + "meta.object-literal.key" + ], + "settings": { + "foreground": "#001080" + } + }, + { + "name": "CSS property value", + "scope": [ + "support.constant.property-value", + "support.constant.font-name", + "support.constant.media-type", + "support.constant.media", + "constant.other.color.rgb-value", + "constant.other.rgb-value", + "support.constant.color" + ], + "settings": { + "foreground": "#0451a5" + } + }, + { + "name": "Regular expression groups", + "scope": [ + "punctuation.definition.group.regexp", + "punctuation.definition.group.assertion.regexp", + "punctuation.definition.character-class.regexp", + "punctuation.character.set.begin.regexp", + "punctuation.character.set.end.regexp", + "keyword.operator.negation.regexp", + "support.other.parenthesis.regexp" + ], + "settings": { + "foreground": "#d16969" + } + }, + { + "scope": [ + "constant.character.character-class.regexp", + "constant.other.character-class.set.regexp", + "constant.other.character-class.regexp", + "constant.character.set.regexp" + ], + "settings": { + "foreground": "#811f3f" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "keyword.operator.or.regexp", + "keyword.control.anchor.regexp" + ], + "settings": { + "foreground": "#ff0000" + } + }, + { + "scope": "constant.character", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#a31515" + } + } + + ] +} \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json new file mode 100644 index 0000000000..67c7bc44af --- /dev/null +++ b/extensions/theme-defaults/themes/light_vs.json @@ -0,0 +1,375 @@ +{ + "$schema": "vscode://schemas/color-theme", + "name": "Light (Visual Studio)", + "include": "./light_defaults.json", + "tokenColors": [ + { + "scope": ["meta.embedded", "source.groovy.embedded"], + "settings": { + "foreground": "#000000ff" + } + }, + { + "scope": "emphasis", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": "strong", + "settings": { + "fontStyle": "bold" + } + }, + { + "scope": "meta.diff.header", + "settings": { + "foreground": "#000080" + } + }, + { + "scope": "comment", + "settings": { + "foreground": "#008000" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": [ + "constant.numeric" + ], + "settings": { + "foreground": "#09885a" + } + }, + { + "scope": "constant.regexp", + "settings": { + "foreground": "#811f3f" + } + }, + { + "name": "css tags in selectors, xml tags", + "scope": "entity.name.tag", + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "entity.name.selector", + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#ff0000" + } + }, + { + "scope": [ + "entity.other.attribute-name.class.css", + "entity.other.attribute-name.class.mixin.css", + "entity.other.attribute-name.id.css", + "entity.other.attribute-name.parent-selector.css", + "entity.other.attribute-name.pseudo-class.css", + "entity.other.attribute-name.pseudo-element.css", + "source.css.less entity.other.attribute-name.id", + "entity.other.attribute-name.attribute.scss", + "entity.other.attribute-name.scss" + ], + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "invalid", + "settings": { + "foreground": "#cd3131" + } + }, + { + "scope": "markup.underline", + "settings": { + "fontStyle": "underline" + } + }, + { + "scope": "markup.bold", + "settings": { + "fontStyle": "bold", + "foreground": "#000080" + } + }, + { + "scope": "markup.heading", + "settings": { + "fontStyle": "bold", + "foreground": "#800000" + } + }, + { + "scope": "markup.italic", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": "markup.inserted", + "settings": { + "foreground": "#09885a" + } + }, + { + "scope": "markup.deleted", + "settings": { + "foreground": "#a31515" + } + }, + { + "scope": "markup.changed", + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": [ + "beginning.punctuation.definition.quote.markdown", + "beginning.punctuation.definition.list.markdown" + ], + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": "markup.inline.raw", + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#800000" + } + }, + { + "name": "brackets of XML/HTML tags", + "scope": "punctuation.definition.tag", + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "meta.preprocessor", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "meta.preprocessor.string", + "settings": { + "foreground": "#a31515" + } + }, + { + "scope": "meta.preprocessor.numeric", + "settings": { + "foreground": "#09885a" + } + }, + { + "scope": "meta.structure.dictionary.key.python", + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": "storage", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "storage.type", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "storage.modifier", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "string", + "settings": { + "foreground": "#a31515" + } + }, + { + "scope": [ + "string.comment.buffered.block.jade", + "string.quoted.jade", + "string.interpolated.jade", + "string.unquoted.plain.in.yaml", + "string.unquoted.plain.out.yaml", + "string.unquoted.block.yaml", + "string.quoted.single.yaml", + "string.quoted.double.xml", + "string.quoted.single.xml", + "string.unquoted.cdata.xml", + "string.quoted.double.html", + "string.quoted.single.html", + "string.unquoted.html", + "string.quoted.single.handlebars", + "string.quoted.double.handlebars" + ], + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#811f3f" + } + }, + { + "name": "String interpolation", + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end", + "punctuation.section.embedded" + ], + "settings": { + "foreground": "#0000ff" + } + }, + { + "name": "Reset JavaScript string interpolation expression", + "scope": [ + "meta.template.expression" + ], + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "support.constant.property-value", + "support.constant.font-name", + "support.constant.media-type", + "support.constant.media", + "constant.other.color.rgb-value", + "constant.other.rgb-value", + "support.constant.color" + ], + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": [ + "support.type.vendored.property-name", + "support.type.property-name", + "variable.css", + "variable.scss", + "variable.other.less", + "source.coffee.embedded" + ], + "settings": { + "foreground": "#ff0000" + } + }, + { + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#000000" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression", + "keyword.operator.cast", + "keyword.operator.sizeof", + "keyword.operator.instanceof", + "keyword.operator.logical.python" + ], + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#09885a" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin.php", + "punctuation.section.embedded.end.php" + ], + "settings": { + "foreground": "#800000" + } + }, + { + "scope": "support.function.git-rebase", + "settings": { + "foreground": "#0451a5" + } + }, + { + "scope": "constant.sha.git-rebase", + "settings": { + "foreground": "#09885a" + } + }, + { + "name": "coloring of the Java import and package identifiers", + "scope": [ + "storage.modifier.import.java", + "variable.language.wildcard.java", + "storage.modifier.package.java" + ], + "settings": { + "foreground": "#000000" + } + }, + { + "name": "this.self", + "scope": "variable.language", + "settings": { + "foreground": "#0000ff" + } + } + ] +} \ No newline at end of file diff --git a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json index 89cdcb1e53..ebcf0341dc 100644 --- a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json +++ b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json @@ -20,7 +20,7 @@ "editorHoverWidget.background": "#221a14", "editorGroupHeader.tabsBackground": "#131510", "editorGroup.background": "#0f0c08", - "editorActiveLineNumber.foreground": "#adadad", + "editorLineNumber.activeForeground": "#adadad", "tab.inactiveBackground": "#131510", "titleBar.activeBackground": "#423523", "statusBar.background": "#423523", @@ -37,7 +37,6 @@ "peekViewResult.background": "#362712", "peekViewEditor.background": "#221a14", "peekViewEditor.matchHighlightBackground": "#84613daa", - "notification.background": "#473a29", "button.background": "#6e583b", "inputValidation.infoBorder": "#1b60a5", "inputValidation.infoBackground": "#2b2a42", diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index 12719f1079..20f12faee0 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -13,12 +13,13 @@ "editor.selectionBackground": "#676b7180", "editor.selectionHighlightBackground": "#575b6180", "editor.lineHighlightBackground": "#303030", - "editorActiveLineNumber.foreground": "#949494", + "editorLineNumber.activeForeground": "#949494", "editor.wordHighlightBackground": "#4747a180", "editor.wordHighlightStrongBackground": "#6767ce80", "editorCursor.foreground": "#c07020", "editorWhitespace.foreground": "#505037", "editorIndentGuide.background": "#505037", + "editorIndentGuide.activeBackground": "#707057", "editorGroupHeader.tabsBackground": "#282828", "editorGroup.background": "#1e1e1e", "tab.inactiveBackground": "#404040", @@ -35,7 +36,6 @@ "activityBarBadge.background": "#3655b5", "sideBar.background": "#272727", "sideBarSectionHeader.background": "#505050", - "notification.background": "#353535", "pickerGroup.foreground": "#b0b0b0", "terminal.ansiWhite": "#ffffff", "inputOption.activeBorder": "#3655b5", diff --git a/extensions/theme-monokai/themes/monokai-color-theme.json b/extensions/theme-monokai/themes/monokai-color-theme.json index 208b6b3953..439ed05190 100644 --- a/extensions/theme-monokai/themes/monokai-color-theme.json +++ b/extensions/theme-monokai/themes/monokai-color-theme.json @@ -12,7 +12,7 @@ "list.focusBackground": "#414339", "dropdown.listBackground": "#1e1f1c", "list.inactiveSelectionBackground": "#414339", - "list.hoverBackground": "#272822", + "list.hoverBackground": "#3e3d32", "list.dropBackground": "#414339", "list.highlightForeground": "#f8f8f2", "button.background": "#75715E", @@ -24,10 +24,11 @@ "editor.wordHighlightBackground": "#4a4a7680", "editor.wordHighlightStrongBackground": "#6a6a9680", "editor.lineHighlightBackground": "#3e3d32", - "editorActiveLineNumber.foreground": "#c2c2bf", + "editorLineNumber.activeForeground": "#c2c2bf", "editorCursor.foreground": "#f8f8f0", "editorWhitespace.foreground": "#464741", "editorIndentGuide.background": "#464741", + "editorIndentGuide.activeBackground": "#767771", "editorGroupHeader.tabsBackground": "#1e1f1c", "editorGroup.dropBackground": "#41433980", "tab.inactiveBackground": "#414339", diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index 3e818bccff..3e1ad56f8a 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -494,7 +494,7 @@ "editor.background": "#F5F5F5", "editorWhitespace.foreground": "#AAAAAA", "editor.lineHighlightBackground": "#E4F6D4", - "editorActiveLineNumber.foreground": "#9769dc", + "editorLineNumber.activeForeground": "#9769dc", "editor.selectionBackground": "#C9D0D9", "panel.background": "#F5F5F5", "sideBar.background": "#F2F2F2", @@ -519,7 +519,6 @@ "activityBarBadge.background": "#705697", "titleBar.activeBackground": "#c4b7d7", "button.background": "#705697", - "notification.background": "#442e66", "editorGroup.dropBackground": "#C9D0D988", "inputValidation.infoBorder": "#4ec1e5", "inputValidation.infoBackground": "#f2fcff", diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index 59af89f8ec..8d69156514 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -21,7 +21,7 @@ "editorWhitespace.foreground": "#c10000", "editor.selectionBackground": "#750000", "editorLineNumber.foreground": "#ff777788", - "editorActiveLineNumber.foreground": "#ffbbbb88", + "editorLineNumber.activeForeground": "#ffbbbb88", "editorWidget.background": "#300000", "editorHoverWidget.background": "#300000", "editorSuggestWidget.background": "#300000", @@ -49,7 +49,6 @@ "list.dropBackground": "#662222", "list.focusBackground": "#660000", "list.highlightForeground": "#ff4444", - "notification.background": "#662222", "pickerGroup.foreground": "#cc9999", "pickerGroup.border": "#ff000033", "badge.background": "#cc3333", diff --git a/extensions/theme-seti/thirdpartynotices.txt b/extensions/theme-seti/ThirdPartyNotices.txt similarity index 100% rename from extensions/theme-seti/thirdpartynotices.txt rename to extensions/theme-seti/ThirdPartyNotices.txt diff --git a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json index f0b8612351..7d77408d2e 100644 --- a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json +++ b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json @@ -355,9 +355,10 @@ "editorCursor.foreground": "#D30102", "editorWhitespace.foreground": "#93A1A180", "editor.lineHighlightBackground": "#073642", - "editorActiveLineNumber.foreground": "#949494", + "editorLineNumber.activeForeground": "#949494", "editor.selectionBackground": "#073642", - // "editorIndentGuide.background": "", + "editorIndentGuide.background": "#93A1A180", + "editorIndentGuide.activeBackground": "#C3E1E180", "editorHoverWidget.background": "#004052", // "editorHoverWidget.border": "", // "editorLineNumber.foreground": "", @@ -457,10 +458,6 @@ "debugExceptionWidget.background": "#00212B", "debugExceptionWidget.border": "#AB395B", - // Workbench: Notifications - "notification.background": "#003847", - // "notification.foreground": "", - // Workbench: Quick Open "pickerGroup.foreground": "#2AA19899", "pickerGroup.border": "#2AA19899", diff --git a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json index c87a8b2655..588e21e893 100644 --- a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json +++ b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json @@ -352,9 +352,10 @@ "editorWhitespace.foreground": "#586E7580", "editor.lineHighlightBackground": "#EEE8D5", "editor.selectionBackground": "#EEE8D5", - // "editorIndentGuide.background": "", + "editorIndentGuide.background": "#586E7580", + "editorIndentGuide.activeBackground": "#081E2580", "editorHoverWidget.background": "#CCC4B0", - "editorActiveLineNumber.foreground": "#567983", + "editorLineNumber.activeForeground": "#567983", // "editorHoverWidget.border": "", // "editorLineNumber.foreground": "", // "editorMarkerNavigation.background": "", @@ -456,10 +457,6 @@ "debugExceptionWidget.background": "#DDD6C1", "debugExceptionWidget.border": "#AB395B", - // Workbench: Notifications - "notification.background": "#999178", - // "notification.foreground": "", - // Workbench: Quick Open "pickerGroup.border": "#2AA19899", "pickerGroup.foreground": "#2AA19899", diff --git a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json index 0b89e5b9e6..de15bf88bc 100644 --- a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json +++ b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json @@ -15,7 +15,7 @@ "editor.foreground": "#ffffff", "editor.selectionBackground": "#003f8e", "editor.lineHighlightBackground": "#00346e", - "editorActiveLineNumber.foreground": "#949494", + "editorLineNumber.activeForeground": "#949494", "editorCursor.foreground": "#ffffff", "editorWhitespace.foreground": "#404f7d", "editorWidget.background": "#001c40", diff --git a/extensions/yaml/language-configuration.json b/extensions/yaml/language-configuration.json index 010d773d3f..16dc5a02e8 100644 --- a/extensions/yaml/language-configuration.json +++ b/extensions/yaml/language-configuration.json @@ -22,7 +22,11 @@ ["'", "'"] ], "folding": { - "offSide": true + "offSide": true, + "markers": { + "start": "^\\s*#\\s*region\\b", + "end": "^\\s*#\\s*endregion\\b" + } }, "indentationRules": { "increaseIndentPattern": "^\\s*.*(:|-) ?(&\\w+)?(\\{[^}\"']*|\\([^)\"']*)?$", diff --git a/extensions/yaml/package.json b/extensions/yaml/package.json index 2792cc20d0..9d93689f94 100644 --- a/extensions/yaml/package.json +++ b/extensions/yaml/package.json @@ -19,10 +19,10 @@ "yaml" ], "extensions": [ + ".yml", ".eyaml", ".eyml", - ".yaml", - ".yml" + ".yaml" ], "filenames": [ "yarn.lock" diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 2a710ccda6..504d8abd96 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,6 +2,6 @@ # yarn lockfile v1 -typescript@2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" +typescript@2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" diff --git a/gulpfile.js b/gulpfile.js index 80c726a0df..cb5f1be6d6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -28,8 +28,8 @@ gulp.task('default', ['compile']); // All gulp.task('clean', ['clean-client', 'clean-extensions']); -gulp.task('compile', ['compile-client', 'compile-extensions']); -gulp.task('watch', ['watch-client', 'watch-extensions']); +gulp.task('compile', ['monaco-typecheck', 'compile-client', 'compile-extensions']); +gulp.task('watch', [/* 'monaco-typecheck-watch', */ 'watch-client', 'watch-extensions']); // All Build gulp.task('clean-build', ['clean-client-build', 'clean-extensions-build']); @@ -74,4 +74,4 @@ if (runningEditorTasks) { const build = path.join(__dirname, 'build'); require('glob').sync('gulpfile.*.js', { cwd: build }) .forEach(f => require(`./build/${f}`)); -} \ No newline at end of file +} diff --git a/i18n/chs/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/chs/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..bbb5b917ca --- /dev/null +++ b/i18n/chs/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS 语言服务器", + "folding.start": "折叠区域开始", + "folding.end": "折叠区域结束" +} \ No newline at end of file diff --git a/i18n/chs/extensions/css-language-features/package.i18n.json b/i18n/chs/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..e35e92e1f8 --- /dev/null +++ b/i18n/chs/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS 语言功能", + "description": "为 CSS、LESS 和 SCSS 文件提供丰富的语言支持。", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "参数数量无效", + "css.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", + "css.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", + "css.lint.duplicateProperties.desc": "不要使用重复的样式定义", + "css.lint.emptyRules.desc": "不要使用空规则集", + "css.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", + "css.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", + "css.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", + "css.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", + "css.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", + "css.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", + "css.lint.importStatement.desc": "Import 语句不会并行加载", + "css.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", + "css.lint.universalSelector.desc": "通配选择符 (*) 运行效率低", + "css.lint.unknownProperties.desc": "未知的属性。", + "css.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", + "css.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", + "css.lint.zeroUnits.desc": "零不需要单位", + "css.trace.server.desc": "跟踪 VS Code 与 CSS 语言服务器之间的通信。", + "css.validate.title": "控制 CSS 验证和问题严重性。", + "css.validate.desc": "启用或禁用所有验证", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "参数数量无效", + "less.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", + "less.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", + "less.lint.duplicateProperties.desc": "不要使用重复的样式定义", + "less.lint.emptyRules.desc": "不要使用空规则集", + "less.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", + "less.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", + "less.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", + "less.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", + "less.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", + "less.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", + "less.lint.importStatement.desc": "Import 语句不会并行加载", + "less.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", + "less.lint.universalSelector.desc": "通配选择符 (*) 运行效率低", + "less.lint.unknownProperties.desc": "未知的属性。", + "less.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", + "less.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", + "less.lint.zeroUnits.desc": "零不需要单位", + "less.validate.title": "控制 LESS 验证和问题严重性。", + "less.validate.desc": "启用或禁用所有验证", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "参数数量无效", + "scss.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", + "scss.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", + "scss.lint.duplicateProperties.desc": "不要使用重复的样式定义", + "scss.lint.emptyRules.desc": "不要使用空规则集", + "scss.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", + "scss.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", + "scss.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", + "scss.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", + "scss.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", + "scss.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", + "scss.lint.importStatement.desc": "Import 语句不会并行加载", + "scss.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", + "scss.lint.universalSelector.desc": "通配选择符 (*) 运行效率低", + "scss.lint.unknownProperties.desc": "未知的属性。", + "scss.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", + "scss.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", + "scss.lint.zeroUnits.desc": "零不需要单位", + "scss.validate.title": "控制 SCSS 验证和问题严重性。", + "scss.validate.desc": "启用或禁用所有验证", + "less.colorDecorators.enable.desc": "启用或禁用颜色修饰器", + "scss.colorDecorators.enable.desc": "启用或禁用颜色修饰器", + "css.colorDecorators.enable.desc": "启用或禁用颜色修饰器", + "css.colorDecorators.enable.deprecationMessage": "已弃用设置 \"css.colorDecorators.enabl\",请改用 \"editor.colorDecorators\"。", + "scss.colorDecorators.enable.deprecationMessage": "已弃用设置 \"scss.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。", + "less.colorDecorators.enable.deprecationMessage": "已弃用设置 \"less.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/css/package.i18n.json b/i18n/chs/extensions/css/package.i18n.json index 77b70e8330..402edf2078 100644 --- a/i18n/chs/extensions/css/package.i18n.json +++ b/i18n/chs/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS 语言功能", - "description": "为 CSS、LESS 和 SCSS 文件提供丰富的语言支持。", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "参数数量无效", - "css.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", - "css.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", - "css.lint.duplicateProperties.desc": "不要使用重复的样式定义", - "css.lint.emptyRules.desc": "不要使用空规则集", - "css.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", - "css.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", - "css.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", - "css.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", - "css.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", - "css.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", - "css.lint.importStatement.desc": "Import 语句不会并行加载", - "css.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", - "css.lint.universalSelector.desc": "通配选择符 (*) 运行效率低", - "css.lint.unknownProperties.desc": "未知的属性。", - "css.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", - "css.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", - "css.lint.zeroUnits.desc": "零不需要单位", - "css.trace.server.desc": "跟踪 VS Code 与 CSS 语言服务器之间的通信。", - "css.validate.title": "控制 CSS 验证和问题严重性。", - "css.validate.desc": "启用或禁用所有验证", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "参数数量无效", - "less.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", - "less.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", - "less.lint.duplicateProperties.desc": "不要使用重复的样式定义", - "less.lint.emptyRules.desc": "不要使用空规则集", - "less.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", - "less.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", - "less.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", - "less.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", - "less.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", - "less.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", - "less.lint.importStatement.desc": "Import 语句不会并行加载", - "less.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", - "less.lint.universalSelector.desc": "已知通配选择符 (*) 慢", - "less.lint.unknownProperties.desc": "未知的属性。", - "less.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", - "less.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", - "less.lint.zeroUnits.desc": "零不需要单位", - "less.validate.title": "控制 LESS 验证和问题严重性。", - "less.validate.desc": "启用或禁用所有验证", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "参数数量无效", - "scss.lint.boxModel.desc": "使用边距或边框时,不要使用宽度或高度", - "scss.lint.compatibleVendorPrefixes.desc": "使用供应商特定前缀时,确保同时包括所有其他供应商特定属性", - "scss.lint.duplicateProperties.desc": "不要使用重复的样式定义", - "scss.lint.emptyRules.desc": "不要使用空规则集", - "scss.lint.float.desc": "避免使用“float”。浮动会带来脆弱的 CSS,如果布局的某一方面更改,将很容易破坏 CSS。", - "scss.lint.fontFaceProperties.desc": "@font-face 规则必须定义 \"src\" 和 \"font-family\" 属性", - "scss.lint.hexColorLength.desc": "十六进制颜色必须由三个或六个十六进制数字组成", - "scss.lint.idSelector.desc": "选择器不应包含 ID,因为这些规则与 HTML 的耦合过于紧密。", - "scss.lint.ieHack.desc": "仅当支持 IE7 及更低版本时,才需要 IE hack", - "scss.lint.important.desc": "避免使用 !important。它表明整个 CSS 的特异性已经失去控制且需要重构。", - "scss.lint.importStatement.desc": "Import 语句不会并行加载", - "scss.lint.propertyIgnoredDueToDisplay.desc": "因显示而忽略属性。例如,使用 \"display: inline\"时,宽度、高度、上边距、下边距和 float 属性将不起作用", - "scss.lint.universalSelector.desc": "已知通配选择符 (*) 慢", - "scss.lint.unknownProperties.desc": "未知的属性。", - "scss.lint.unknownVendorSpecificProperties.desc": "未知的供应商特定属性。", - "scss.lint.vendorPrefix.desc": "使用供应商特定前缀时,还应包括标准属性", - "scss.lint.zeroUnits.desc": "零不需要单位", - "scss.validate.title": "控制 SCSS 验证和问题严重性。", - "scss.validate.desc": "启用或禁用所有验证", - "less.colorDecorators.enable.desc": "启用或禁用颜色修饰器", - "scss.colorDecorators.enable.desc": "启用或禁用颜色修饰器", - "css.colorDecorators.enable.desc": "启用或禁用颜色修饰器", - "css.colorDecorators.enable.deprecationMessage": "已弃用设置 \"css.colorDecorators.enabl\",请改用 \"editor.colorDecorators\"。", - "scss.colorDecorators.enable.deprecationMessage": "已弃用设置 \"scss.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。", - "less.colorDecorators.enable.deprecationMessage": "已弃用设置 \"less.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。" + "displayName": "CSS 语言基础功能", + "description": "为 CSS、LESS 和 SCSS 文件中提供语法高亮和括号匹配功能。" } \ No newline at end of file diff --git a/i18n/chs/extensions/emmet/package.i18n.json b/i18n/chs/extensions/emmet/package.i18n.json index 2728309a68..6e4d9cdaa1 100644 --- a/i18n/chs/extensions/emmet/package.i18n.json +++ b/i18n/chs/extensions/emmet/package.i18n.json @@ -35,7 +35,7 @@ "emmetExtensionsPath": "包含 Emmet 配置文件与代码片段的文件夹路径。", "emmetShowExpandedAbbreviation": "在建议中显示展开的 Emmet 缩写。\n选择 \"inMarkupAndStylesheetFilesOnly\" 选项将仅应用于 html、haml、jade、slim、xml、xsl、css、scss、sass、less 和 stylus 文件。\n选择 \"always\" 选项将应用于所有适用文件不限于标记或 CSS 的所有部分。", "emmetShowAbbreviationSuggestions": "显示可能的 Emmet 缩写作为建议。在样式表中或当 emmet.showExpandedAbbreviation 设置为 \"never\" 时不适用。", - "emmetIncludeLanguages": "在默认不支持 Emmet 的语言中启用 Emmet 缩写功能。在此添加该语言与支持 Emmet 的语言之间的映射。\n示例: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "在默认不支持 Emmet 的语言中启用 Emmet 缩写功能。在此添加该语言与受支持的语言间的映射。\n示例: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "用于 Emmet 代码片段的变量", "emmetTriggerExpansionOnTab": "启用后,按下 TAB 键,将展开 Emmet 缩写。", "emmetPreferences": "用于修改 Emmet 某些操作和解析程序的行为的首选项。", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Emmet 缩写中使用的由 \"-\" 打头有 \"webkit\" 前缀的 CSS 属性,使用半角逗号 (\",\") 进行分隔。若要始终避免 \"webkit\" 前缀,请设为空字符串。", "emmetPreferencesCssMozProperties": "Emmet 缩写中使用的由 \"-\" 打头有 \"moz\" 前缀的 CSS 属性,使用半角逗号 (\",\") 进行分隔。若要始终避免 \"moz\" 前缀,请设为空字符串。", "emmetPreferencesCssOProperties": "Emmet 缩写中使用的由 \"-\" 打头有 \"o\" 前缀的 CSS 属性,使用半角逗号 (\",\") 进行分隔。若要始终避免 \"o\" 前缀,请设为空字符串。", - "emmetPreferencesCssMsProperties": "Emmet 缩写中使用的由 \"-\" 打头有 \"ms\" 前缀的 CSS 属性,使用半角逗号 (\",\") 进行分隔。若要始终避免 \"ms\" 前缀,请设为空字符串。" + "emmetPreferencesCssMsProperties": "Emmet 缩写中使用的由 \"-\" 打头有 \"ms\" 前缀的 CSS 属性,使用半角逗号 (\",\") 进行分隔。若要始终避免 \"ms\" 前缀,请设为空字符串。", + "emmetPreferencesCssFuzzySearchMinScore": "显示的缩写模糊匹配应达到的最低分数 (0 到 1 之间)。较低的值可能使匹配错误变多,较高的值可能将不会显示应有的匹配项。", + "emmetOptimizeStylesheetParsing": "当设置为 false 时,将分析整个文件并确定当前位置能否展开 Emmet 缩写。当设置为 true 时,则仅在 CSS/SCSS/LESS 文件中进行分析。" } \ No newline at end of file diff --git a/i18n/chs/extensions/git/out/commands.i18n.json b/i18n/chs/extensions/git/out/commands.i18n.json index a566438856..de35e20588 100644 --- a/i18n/chs/extensions/git/out/commands.i18n.json +++ b/i18n/chs/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) 创建新分支", "repourl": "存储库 URL", "parent": "父目录", - "cancel": "$(sync~spin) 正在克隆存储库... 点击取消", - "cancel tooltip": "取消克隆", - "cloning": "正在克隆 Git 存储库...", + "cloning": "正在克隆 Git 存储库“{0}”...", "openrepo": "打开存储库", "proposeopen": "是否要打开已克隆存储库?", "init": "选择用于初始化 Git 储存库的工作区文件夹", @@ -75,7 +73,7 @@ "ok": "确定", "push with tags success": "已成功带标签进行推送。", "pick remote": "选取要将分支“{0}”发布到的远程:", - "sync is unpredictable": "此操作将推送提交至“{0}”,并从中拉取提交。", + "sync is unpredictable": "此操作将推送提交至“{0}/{1}”,并从中拉取提交。", "never again": "确定,且不再显示", "no remotes to publish": "存储库未配置任何要发布到的远程存储库。", "no changes stash": "没有要储藏的更改。", diff --git a/i18n/chs/extensions/git/out/main.i18n.json b/i18n/chs/extensions/git/out/main.i18n.json index 529951611f..914e060ded 100644 --- a/i18n/chs/extensions/git/out/main.i18n.json +++ b/i18n/chs/extensions/git/out/main.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "looking": "在 {0} 查找 Git 中", - "using git": "使用 {1} 中的 Git {0}", + "looking": "正在查找 Git: {0}", + "using git": "将使用位于 {1} 的 Git {0}", "downloadgit": "下载 Git", "neverShowAgain": "不再显示", "notfound": "未找到 Git。请安装 Git,或在 \"git.path\" 设置中配置。", diff --git a/i18n/chs/extensions/git/package.i18n.json b/i18n/chs/extensions/git/package.i18n.json index 4b8de536ea..fee1fb168e 100644 --- a/i18n/chs/extensions/git/package.i18n.json +++ b/i18n/chs/extensions/git/package.i18n.json @@ -26,7 +26,7 @@ "command.unstageSelectedRanges": "取消暂存所选范围", "command.clean": "放弃更改", "command.cleanAll": "放弃所有更改", - "command.commit": "Commit", + "command.commit": "提交", "command.commitStaged": "提交已暂存文件", "command.commitStagedSigned": "提交已暂存文件(已签名)", "command.commitStagedAmend": "已暂存提交(修改)", @@ -62,10 +62,10 @@ "config.autorefresh": "是否启用自动刷新", "config.autofetch": "是否启用自动拉取", "config.enableLongCommitWarning": "是否针对长段提交消息进行警告", - "config.confirmSync": "同步 GIT 存储库前请先进行确认", + "config.confirmSync": "同步 Git 存储库前进行确认", "config.countBadge": "控制 Git 徽章计数器。“all”计算所有更改。“tracked”只计算跟踪的更改。“off”关闭此功能。", "config.checkoutType": "控制运行“签出到...”功能时列出的分支类型。\"all\" 显示所有 refs,\"local\" 只显示本地分支,\"tags\" 只显示标签,\"remote\" 只显示远程分支。", - "config.ignoreLegacyWarning": "忽略旧版 Git 警告", + "config.ignoreLegacyWarning": "忽略“旧版 Git”警告", "config.ignoreMissingGitWarning": "忽略“缺失 Git”警告", "config.ignoreLimitWarning": "忽略“存储库中存在大量更改”的警告", "config.defaultCloneDirectory": "克隆 Git 存储库的默认位置", @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "控制是否在 Git 更改视图中显示内联“打开文件”操作。", "config.inputValidation": "控制何时显示提交消息输入验证。", "config.detectSubmodules": "控制是否自动检测 Git 子模块。", + "config.detectSubmodulesLimit": "控制可检测到的 Git 子模块的限制。", "colors.modified": "已修改资源的颜色。", "colors.deleted": "已删除资源的颜色。", "colors.untracked": "未跟踪资源的颜色。", diff --git a/i18n/chs/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/chs/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..9df9ff9043 --- /dev/null +++ b/i18n/chs/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML 语言服务器", + "folding.start": "折叠区域开始", + "folding.end": "折叠区域结束" +} \ No newline at end of file diff --git a/i18n/chs/extensions/html-language-features/package.i18n.json b/i18n/chs/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..10478bc7fe --- /dev/null +++ b/i18n/chs/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML 语言功能", + "description": "为 HTML、Razor 和 Handlebar 文件提供丰富的语言支持。", + "html.format.enable.desc": "启用/禁用默认 HTML 格式化程序", + "html.format.wrapLineLength.desc": "每行最大字符数(0 = 禁用)。", + "html.format.unformatted.desc": "以逗号分隔的标记列表不应重设格式。\"null\" 默认为所有列于 https://www.w3.org/TR/html5/dom.html#phrasing-content 的标记。", + "html.format.contentUnformatted.desc": "以逗号分隔的标记列表,不应在其中重新设置内容的格式。\"null\" 默认为 \"pre\" 标记。", + "html.format.indentInnerHtml.desc": "缩进 <head> 和 <body> 部分。", + "html.format.preserveNewLines.desc": "是否要保留元素前面的现有换行符。仅适用于元素前,不适用于标记内或文本。", + "html.format.maxPreserveNewLines.desc": "要保留在一个区块中的换行符的最大数量。对于无限制使用 \"null\"。", + "html.format.indentHandlebars.desc": "格式和缩进 {{#foo}} 和 {{/foo}}。", + "html.format.endWithNewline.desc": "以新行结束。", + "html.format.extraLiners.desc": "标记列表,以逗号分隔,其前应有额外新行。\"null\" 默认为“标头、正文、/html”。", + "html.format.wrapAttributes.desc": "对属性进行换行。", + "html.format.wrapAttributes.auto": "仅在超出行长度时才对属性进行换行。", + "html.format.wrapAttributes.force": "对除第一个属性外的其他每个属性进行换行。", + "html.format.wrapAttributes.forcealign": "对除第一个属性外的其他每个属性进行换行,并保持对齐。", + "html.format.wrapAttributes.forcemultiline": "对每个属性进行换行。", + "html.suggest.angular1.desc": "配置内置 HTML 语言支持是否建议 Angular V1 标记和属性。", + "html.suggest.ionic.desc": "配置内置 HTML 语言支持是否建议 Ionic 标记、属性和值。", + "html.suggest.html5.desc": "配置内置 HTML 语言支持是否建议 HTML5 标记、属性和值。", + "html.trace.server.desc": "跟踪 VS Code 与 HTML 语言服务器之间的通信。", + "html.validate.scripts": "配置内置的 HTML 语言支持是否对嵌入的脚本进行验证。", + "html.validate.styles": "配置内置的 HTML 语言支持是否对嵌入的样式进行验证。", + "html.autoClosingTags": "启用/禁用 HTML 标记的自动关闭。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/html/package.i18n.json b/i18n/chs/extensions/html/package.i18n.json index 426255de34..b9e3af7de2 100644 --- a/i18n/chs/extensions/html/package.i18n.json +++ b/i18n/chs/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML 语言功能", - "description": "为 HTML、Razor 和 Handlebar 文件提供丰富的语言支持。", - "html.format.enable.desc": "启用/禁用默认 HTML 格式化程序", - "html.format.wrapLineLength.desc": "每行最大字符数(0 = 禁用)。", - "html.format.unformatted.desc": "以逗号分隔的标记列表不应重设格式。\"null\" 默认为所有列于 https://www.w3.org/TR/html5/dom.html#phrasing-content 的标记。", - "html.format.contentUnformatted.desc": "以逗号分隔的标记列表,不应在其中重新设置内容的格式。\"null\" 默认为 \"pre\" 标记。", - "html.format.indentInnerHtml.desc": "缩进 <head> 和 <body> 部分。", - "html.format.preserveNewLines.desc": "是否要保留元素前面的现有换行符。仅适用于元素前,不适用于标记内或文本。", - "html.format.maxPreserveNewLines.desc": "要保留在一个区块中的换行符的最大数量。对于无限制使用 \"null\"。", - "html.format.indentHandlebars.desc": "格式和缩进 {{#foo}} 和 {{/foo}}。", - "html.format.endWithNewline.desc": "以新行结束。", - "html.format.extraLiners.desc": "标记列表,以逗号分隔,其前应有额外新行。\"null\" 默认为“标头、正文、/html”。", - "html.format.wrapAttributes.desc": "对属性进行换行。", - "html.format.wrapAttributes.auto": "仅在超出行长度时才对属性进行换行。", - "html.format.wrapAttributes.force": "对除第一个属性外的其他每个属性进行换行。", - "html.format.wrapAttributes.forcealign": "对除第一个属性外的其他每个属性进行换行,并保持对齐。", - "html.format.wrapAttributes.forcemultiline": "对每个属性进行换行。", - "html.suggest.angular1.desc": "配置内置 HTML 语言支持是否建议 Angular V1 标记和属性。", - "html.suggest.ionic.desc": "配置内置 HTML 语言支持是否建议 Ionic 标记、属性和值。", - "html.suggest.html5.desc": "配置内置 HTML 语言支持是否建议 HTML5 标记、属性和值。", - "html.trace.server.desc": "跟踪 VS Code 与 HTML 语言服务器之间的通信。", - "html.validate.scripts": "配置内置的 HTML 语言支持是否对嵌入的脚本进行验证。", - "html.validate.styles": "配置内置的 HTML 语言支持是否对嵌入的样式进行验证。", - "html.experimental.syntaxFolding": "启用或禁用语法折叠标记。", - "html.autoClosingTags": "启用/禁用 HTML 标记的自动关闭。" + "displayName": "HTML 语言基础功能", + "description": "在 HTML 文件中提供语法高亮、括号匹配和代码片段功能。" } \ No newline at end of file diff --git a/i18n/chs/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/chs/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..dac0ceb960 --- /dev/null +++ b/i18n/chs/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON 语言服务器" +} \ No newline at end of file diff --git a/i18n/chs/extensions/json-language-features/package.i18n.json b/i18n/chs/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..340eded098 --- /dev/null +++ b/i18n/chs/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON 语言功能", + "description": "为 JSON 文件提供丰富的语言支持", + "json.schemas.desc": "将当前项目中的 JSON 文件与架构关联起来", + "json.schemas.url.desc": "当前目录中指向架构的 URL 或相对路径", + "json.schemas.fileMatch.desc": "将 JSON 文件解析到架构时,用于匹配的一组文件模式。", + "json.schemas.fileMatch.item.desc": "将 JSON 文件解析到架构时,用于匹配的可以包含 \"*\" 的文件模式。", + "json.schemas.schema.desc": "给定 URL 的架构定义。只需提供该架构以避免对架构 URL 的访问。", + "json.format.enable.desc": "启用/禁用默认 JSON 格式化程序(需要重启)", + "json.tracing.desc": "跟踪 VS Code 与 JSON 语言服务器之间的通信。", + "json.colorDecorators.enable.desc": "启用或禁用颜色修饰器", + "json.colorDecorators.enable.deprecationMessage": "已弃用设置 \"json.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/json/package.i18n.json b/i18n/chs/extensions/json/package.i18n.json index 1f988f94b5..9f342e18f8 100644 --- a/i18n/chs/extensions/json/package.i18n.json +++ b/i18n/chs/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON 语言功能", - "description": "为 JSON 文件提供丰富的语言支持", - "json.schemas.desc": "将当前项目中的 JSON 文件与架构关联起来", - "json.schemas.url.desc": "当前目录中指向架构的 URL 或相对路径", - "json.schemas.fileMatch.desc": "将 JSON 文件解析到架构时,用于匹配的一组文件模式。", - "json.schemas.fileMatch.item.desc": "将 JSON 文件解析到架构时,用于匹配的可以包含 \"*\" 的文件模式。", - "json.schemas.schema.desc": "给定 URL 的架构定义。只需提供该架构以避免对架构 URL 的访问。", - "json.format.enable.desc": "启用/禁用默认 JSON 格式化程序(需要重启)", - "json.tracing.desc": "跟踪 VS Code 与 JSON 语言服务器之间的通信。", - "json.colorDecorators.enable.desc": "启用或禁用颜色修饰器", - "json.colorDecorators.enable.deprecationMessage": "已弃用设置 \"json.colorDecorators.enable\",请改用 \"editor.colorDecorators\"。", - "json.experimental.syntaxFolding": "启用或禁用语法折叠标记。" + "displayName": "JSON 语言基础功能", + "description": "在 JSON 文件中提供语法高亮和括号匹配功能。" } \ No newline at end of file diff --git a/i18n/chs/extensions/markdown-basics/package.i18n.json b/i18n/chs/extensions/markdown-basics/package.i18n.json index 46563e53e3..e0c1be03cc 100644 --- a/i18n/chs/extensions/markdown-basics/package.i18n.json +++ b/i18n/chs/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/chs/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/chs/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..d0a2ce8701 --- /dev/null +++ b/i18n/chs/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "无法加载“markdown.styles”:{0}" +} \ No newline at end of file diff --git a/i18n/chs/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/chs/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..479e1e30f0 --- /dev/null +++ b/i18n/chs/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[预览] {0}", + "previewTitle": "预览 {0}" +} \ No newline at end of file diff --git a/i18n/chs/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/chs/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..6a53189d1b --- /dev/null +++ b/i18n/chs/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "已禁用此文档中的部分内容", + "preview.securityMessage.title": "已禁用此 Markdown 预览中的可能不安全的内容。更改 Markdown 预览安全设置以允许不安全内容或启用脚本。", + "preview.securityMessage.label": "已禁用内容安全警告" +} \ No newline at end of file diff --git a/i18n/chs/extensions/markdown-language-features/out/security.i18n.json b/i18n/chs/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..43ddb78737 --- /dev/null +++ b/i18n/chs/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "严格", + "strict.description": "仅载入安全内容", + "insecureLocalContent.title": "允许不安全的本地内容", + "insecureLocalContent.description": "允许通过 http 载入来自 localhost 的内容", + "insecureContent.title": "允许不安全内容", + "insecureContent.description": "允许通过 http 载入内容", + "disable.title": "禁用", + "disable.description": "允许所有内容,执行所有脚本。不推荐", + "moreInfo.title": "详细信息", + "enableSecurityWarning.title": "在此工作区中启用预览安全警告", + "disableSecurityWarning.title": "在此工作区中取消预览安全警告", + "toggleSecurityWarning.description": "不影响内容安全级别", + "preview.showPreviewSecuritySelector.title": "选择此工作区中 Markdown 预览的安全设置" +} \ No newline at end of file diff --git a/i18n/chs/extensions/markdown-language-features/package.i18n.json b/i18n/chs/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..6790472bfc --- /dev/null +++ b/i18n/chs/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown 语言功能", + "description": "为 Markdown 提供丰富的语言支持。", + "markdown.preview.breaks.desc": "设置换行符如何在 markdown 预览中呈现。将其设置为 \"true\" 会为每一个新行创建一个 <br>。", + "markdown.preview.linkify": "在 Markdown 预览中启用或禁用将类似 URL 的文本转换为链接。", + "markdown.preview.doubleClickToSwitchToEditor.desc": "在 Markdown 预览中双击切换到编辑器。", + "markdown.preview.fontFamily.desc": "控制 Markdown 预览中使用的字体系列。", + "markdown.preview.fontSize.desc": "控制 Markdown 预览中使用的字号(以像素为单位)。", + "markdown.preview.lineHeight.desc": "控制 Markdown 预览中使用的行高。此数值与字号相关。", + "markdown.preview.markEditorSelection.desc": "在 Markdown 预览中标记当前的编辑器选定内容。", + "markdown.preview.scrollEditorWithPreview.desc": "滚动 Markdown 预览时,更新其编辑器视图。", + "markdown.preview.scrollPreviewWithEditor.desc": "滚动 Markdown 编辑器时,更新其预览视图。", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[弃用] 滚动 Markdown 预览以显示编辑器当前所选行。", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "此设置已被 \"markdown.preview.scrollPreviewWithEditor\" 替换且不再有任何效果。", + "markdown.preview.title": "打开预览", + "markdown.previewFrontMatter.dec": "设置如何在 Markdown 预览中呈现 YAML 扉页。“隐藏”会删除扉页。否则,扉页则被视为 Markdown 内容。", + "markdown.previewSide.title": "打开侧边预览", + "markdown.showLockedPreviewToSide.title": "在侧边打开锁定的预览", + "markdown.showSource.title": "显示源", + "markdown.styles.dec": "要在 Markdown 预览中使用的 CSS 样式表的 URL 或本地路径列表。相对路径被解释为相对于资源管理器中打开的文件夹。如果没有任何打开的文件夹,则会被解释为相对于 Markdown 文件的位置。所有的 \"\\\" 需写为 \"\\\\\"。", + "markdown.showPreviewSecuritySelector.title": "更改预览安全设置", + "markdown.trace.desc": "对 Markdown 扩展启用调试日志记录。", + "markdown.preview.refresh.title": "刷新预览", + "markdown.preview.toggleLock.title": "切换开关锁定预览" +} \ No newline at end of file diff --git a/i18n/chs/extensions/markdown/out/features/preview.i18n.json b/i18n/chs/extensions/markdown/out/features/preview.i18n.json index 963a70a043..479e1e30f0 100644 --- a/i18n/chs/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/chs/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/chs/extensions/npm/out/npmView.i18n.json b/i18n/chs/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..d549553334 --- /dev/null +++ b/i18n/chs/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "无法启动“{0}”并进行调试。脚本缺少 Node 调试选项,如 \"--inspect-brk\"。", + "npm.scriptInvalid": "找不到脚本“{0}”。请尝试刷新视图。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/npm/out/tasks.i18n.json b/i18n/chs/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..e0f67df3ba --- /dev/null +++ b/i18n/chs/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Npm 任务检测: 无法分析文件 {0}" +} \ No newline at end of file diff --git a/i18n/chs/extensions/npm/package.i18n.json b/i18n/chs/extensions/npm/package.i18n.json index 2c40df23aa..26fe779a0b 100644 --- a/i18n/chs/extensions/npm/package.i18n.json +++ b/i18n/chs/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "使用 \"--silent\" 选项运行 npm 命令。", "config.npm.packageManager": "用于运行脚本的程序包管理器。", "config.npm.exclude": "配置应从自动脚本检测中排除的文件夹的 glob 模式。", + "config.npm.enableScriptExplorer": "当工作区包含 \"package.json\" 文件时,启用 npm 脚本资源管理器视图。", "npm.parseError": "Npm 任务检测: 无法分析文件 {0}", "taskdef.script": "要自定义的 npm 脚本。", - "taskdef.path": "包含 package.json 文件的文件夹路径,其中 package.json 文件提供脚本。可以省略。" + "taskdef.path": "包含 package.json 文件的文件夹路径,其中 package.json 文件提供脚本。可以省略。", + "view.name": "Npm 脚本", + "command.refresh": "刷新", + "command.run": "运行", + "command.debug": "调试", + "command.openScript": "开放", + "npm.scriptInvalid": "找不到脚本“{0}”。请尝试刷新视图。", + "npm.noDebugOptions": "无法启动“{0}”并进行调试。脚本缺少 Node 调试选项,如 \"--inspect-brk\"。" } \ No newline at end of file diff --git a/i18n/chs/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/chs/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..c5281f1008 --- /dev/null +++ b/i18n/chs/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "是否允许执行 {0} (定义为工作区设置)以进行 PHP 文件的 lint 操作?", + "php.yes": "Allow", + "php.no": "不允许", + "wrongExecutable": "无法验证,因为 {0} 不是有效的 PHP 可执行文件。请使用设置 \"php.validate.executablePath\" 配置 PHP 可执行文件。", + "noExecutable": "无法验证,因为未设置任何 PHP 可执行文件。请使用设置 \"php.validate.executablePath\" 配置 PHP 可执行文件。", + "unknownReason": "使用路径运行 php 失败: {0}。原因未知。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/php-language-features/package.i18n.json b/i18n/chs/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..0871582ebd --- /dev/null +++ b/i18n/chs/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "如果已启用内置 PHP 语言建议,则进行配置。此支持建议 PHP 全局变量和变量。", + "configuration.validate.enable": "启用/禁用内置的 PHP 验证。", + "configuration.validate.executablePath": "指向 PHP 可执行文件。", + "configuration.validate.run": "决定 linter 是在保存时还是输入时运行。", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "禁止 PHP 验证程序(定义为工作区设置)", + "displayName": "PHP 语言功能", + "description": "为 PHP 文件提供丰富的语言支持。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/php/package.i18n.json b/i18n/chs/extensions/php/package.i18n.json index 0da24d197d..f946b5c864 100644 --- a/i18n/chs/extensions/php/package.i18n.json +++ b/i18n/chs/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "如果已启用内置 PHP 语言建议,则进行配置。此支持建议 PHP 全局变量和变量。", - "configuration.validate.enable": "启用/禁用内置的 PHP 验证。", - "configuration.validate.executablePath": "指向 PHP 可执行文件。", - "configuration.validate.run": "决定 linter 是在保存时还是输入时运行。", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "禁止 PHP 验证程序(定义为工作区设置)", - "displayName": "PHP 语言功能", - "description": "为 PHP 文件提供 IntelliSense、lint 和语言基础功能。" + "displayName": "PHP 语言基础功能", + "description": "为 PHP 文件提供语法高亮和括号匹配功能。" } \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/commands.i18n.json b/i18n/chs/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..71f03151b6 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "请在 VS Code 中打开一个文件夹,以使用 TypeScript 或 JavaScript 项目", + "typescript.projectConfigUnsupportedFile": "无法确定 TypeScript 或 JavaScript 项目。不受支持的文件类型", + "typescript.projectConfigCouldNotGetInfo": "无法确定 TypeScript 或 JavaScript 项目", + "typescript.noTypeScriptProjectConfig": "文件不属于 TypeScript 项目。点击[这里]({0})了解更多。", + "typescript.noJavaScriptProjectConfig": "文件不属于 JavaScript 项目。点击[这里]({0})了解更多。", + "typescript.configureTsconfigQuickPick": "配置 tsconfig.json", + "typescript.configureJsconfigQuickPick": "配置 jsconfig.json" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..cec1f8a1e0 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "选择要应用的代码操作", + "acquiringTypingsLabel": "正在获取 typings...", + "acquiringTypingsDetail": "获取 IntelliSense 的 typings 定义。", + "autoImportLabel": "从 {0} 自动导入" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..0e60e3412a --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "在 JavaScript 文件中启用语义检查。必须在文件顶部。", + "ts-nocheck": "在 JavaScript 文件中禁用语义检查。必须在文件顶部。", + "ts-ignore": "取消文件下一行的 @ts-check 错误提示。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..021db468b5 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 个实现", + "manyImplementationLabel": "{0} 个实现", + "implementationsErrorLabel": "无法确定实现" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..1d385873b1 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc 注释" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..77f30b069a --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "整理 import 语句" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..d22ade03db --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (修复文件中所有)" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..5410b68067 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 个引用", + "manyReferenceLabel": "{0} 个引用", + "referenceErrorLabel": "无法确定引用" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..cd6842c9ce --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "构建 - {0}", + "buildAndWatchTscLabel": "监视 - {0}" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/chs/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..d4107581eb --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "路径 {0} 未指向有效的 tsserver 安装。请回退到捆绑的 TypeScript 版本。", + "serverCouldNotBeStarted": "无法启动 TypeScript 语言服务器。错误消息为: {0}", + "typescript.openTsServerLog.notSupported": "TS 服务器日志记录需要 TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "TS 服务器日志记录已关闭。请设置 \"typescript.tsserver.log\" 并重启\n TS 服务器以启用日志记录", + "typescript.openTsServerLog.enableAndReloadOption": "启用日志记录并重启 TS 服务器", + "typescript.openTsServerLog.noLogFile": "TS 服务器尚未启动日志记录。", + "openTsServerLog.openFileFailedFailed": "无法打开 TS 服务器日志文件", + "serverDiedAfterStart": "TypeScript 语言服务在其启动后已中止 5 次。将不会重启该服务。", + "serverDiedReportIssue": "使用英文报告问题", + "serverDied": "在过去 5 分钟内,TypeScript 语言服务意外中止了 5 次。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..006fe31225 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "无效版本" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..cd5096356f --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "若要启用项目范围内的 JavaScript/TypeScript 语言功能,请排除包含多个文件的文件夹,例如: {0}", + "hintExclude.generic": "若要启用项目范围内的 JavaScript/TypeScript 语言功能,请排除包含不需要处理的源文件的大型文件夹。", + "large.label": "配置排除", + "hintExclude.tooltip": "若要启用项目范围内的 JavaScript/TypeScript 语言功能,请排除包含不需要处理的源文件的大型文件夹。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..fe9128f40d --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "提取数据以实现更好的 TypeScript IntelliSense", + "typesInstallerInitializationFailed.title": "无法为 JavaScript 语言功能安装 typings 文件。请确认 NPM 已安装,或在你的用户设置中配置 “typescript.npm”。点击[这里]({0})了解更多。", + "typesInstallerInitializationFailed.doNotCheckAgain": "不再显示" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..c9f87e17e8 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "使用 VS Code 的版本", + "useWorkspaceVersionOption": "使用工作区版本", + "learnMore": "了解详细信息", + "selectTsVersion": "选择用于 JavaScript 和 TypeScript 语言功能的 TypeScript 版本" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/chs/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..4bb999f00f --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "无法获取此目录 TypeScript 的版本", + "noBundledServerFound": "VS Code 的 tsserver 已被其他应用程序(例如运行异常的病毒检测工具)删除。请重新安装 VS Code。" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript-language-features/package.i18n.json b/i18n/chs/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..d12cc2e3f7 --- /dev/null +++ b/i18n/chs/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JavaScript 和 TypeScript 的语言功能", + "description": "为 JavaScript 和 TypeScript 提供丰富的语言支持。", + "typescript.reloadProjects.title": "重载项目", + "javascript.reloadProjects.title": "重载项目", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "完成函数的参数签名。", + "typescript.tsdk.desc": "指定包含要使用的 tsserver 和 lib*.d.ts 文件的文件夹路径。", + "typescript.disableAutomaticTypeAcquisition": "禁用自动获取类型。需要 TypeScript >= 2.0.6。", + "typescript.tsserver.log": "将 TS 服务器的日志保存到一个文件。此日志可用于诊断 TS 服务器问题。日志可能包含你的项目中的文件路径、源代码和其他可能敏感的信息。", + "typescript.tsserver.pluginPaths": "其他可搜索 TypeScript 语言服务插件的路径。需要 TypeScript >= 2.3.0。", + "typescript.tsserver.pluginPaths.item": "相对或绝对路径。相对路径将根据工作区文件夹进行解析。", + "typescript.tsserver.trace": "对发送到 TS 服务器的消息启用跟踪。此跟踪信息可用于诊断 TS 服务器问题。 跟踪信息可能包含你的项目中的文件路径、源代码和其他可能敏感的信息。", + "typescript.validate.enable": "启用/禁用 TypeScript 验证。", + "typescript.format.enable": "启用/禁用默认 TypeScript 格式化程序。", + "javascript.format.enable": "启用/禁用 JavaScript 格式化程序。", + "format.insertSpaceAfterCommaDelimiter": "定义逗号分隔符后面的空格处理。", + "format.insertSpaceAfterConstructor": "定义构造器关键字后的空格处理。要求 TypeScript >= 2.3.0。", + "format.insertSpaceAfterSemicolonInForStatements": "在 For 语句中,定义分号后面的空格处理。", + "format.insertSpaceBeforeAndAfterBinaryOperators": "定义二进制运算符后面的空格处理", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "定义控制流语句中关键字后面的空格处理。", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "定义匿名函数的函数关键字后面的空格处理。", + "format.insertSpaceBeforeFunctionParenthesis": "在函数参数括号前定义空格处理。需要 TypeScript >= 2.1.5。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "定义非空小括号的左括号后和右括号前的空格处理方式。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "定义非空中括号的左括号后和右括号前的空格处理方式。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "定义非空大括号的左括号后和右括号前的空格处理方式。要求 TypeScript >= 2.3.0。", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "定义模板字符串的左括号后面和右括号前面的空格处理。要求 TypeScript >= 2.0.6。", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "定义 JSX 表达式左括号后面和右括号前面的空格处理。要求 TypeScript >= 2.0.6。", + "format.insertSpaceAfterTypeAssertion": "定义 TypeScript 中类型断言后的空格处理。要求 TypeScript >= 2.4。", + "format.placeOpenBraceOnNewLineForFunctions": "定义函数的左大括号是否放置在新的一行。", + "format.placeOpenBraceOnNewLineForControlBlocks": "定义控制块的左括号是否放置在新的一行。", + "javascript.validate.enable": "启用/禁用 JavaScript 验证。", + "typescript.goToProjectConfig.title": "转到项目配置", + "javascript.goToProjectConfig.title": "转到项目配置", + "javascript.referencesCodeLens.enabled": "启用/禁用在 JavaScript 文件中引用 CodeLens。", + "typescript.referencesCodeLens.enabled": "启用/禁用在 TypeScript 文件中引用 CodeLens。要求 TypeScript >= 2.0.6。", + "typescript.implementationsCodeLens.enabled": "启用/禁用实现 CodeLens。要求 TypeScript >= 2.2.0。", + "typescript.openTsServerLog.title": "打开 TS 服务器日志", + "typescript.restartTsServer": "重启 TS 服务器", + "typescript.selectTypeScriptVersion.title": "选择 TypeScript 版本", + "typescript.reportStyleChecksAsWarnings": "将风格检查问题报告为警告", + "jsDocCompletion.enabled": "启用/禁用自动 JSDoc 注释", + "javascript.implicitProjectConfig.checkJs": "启用/禁用 JavaScript 文件的语义检查。现有的 jsconfig.json 或\n tsconfig.json 文件会覆盖此设置。要求 TypeScript >=2.3.1。", + "typescript.npm": "指定用于自动获取类型的 NPM 可执行文件的路径。要求 TypeScript >= 2.3.4。", + "typescript.check.npmIsInstalled": "检查是否安装了 NPM 以自动获取类型。", + "javascript.nameSuggestions": "启用/禁用在 JavaScript 建议列表中包含文件中的唯一名称。", + "typescript.tsc.autoDetect": "控制 tsc 任务的自动检测。\"off\" 关闭此功能。\"build\" 仅创建单次运行编译任务。\"watch\" 仅创建编译及监视任务。\"on\" 创建构建及监视任务。默认值为 \"on\"。", + "typescript.problemMatchers.tsc.label": "TypeScript 问题", + "typescript.problemMatchers.tscWatch.label": "TypeScript 问题(观看模式)", + "typescript.quickSuggestionsForPaths": "当输入导入路径时启用或禁用快速建议。", + "typescript.locale": "设置报告 TypeScript 错误时使用的区域设置。要求 TypeScript >= 2.6.0。默认 (\"null\") 将使用 VS Code 的区域设置。", + "javascript.implicitProjectConfig.experimentalDecorators": "对不属于任何工程的 JavaScript 文件启用或禁用 \"experimentalDecorators\" 设置。现有的 jsconfig.json 或\n tsconfig.json 文件会覆盖此设置。要求 TypeScript >=2.3.1。", + "typescript.autoImportSuggestions.enabled": "启用或禁用自动导入建议。要求 TypeScript >= 2.6.1", + "typescript.experimental.syntaxFolding": "启用或禁用语法折叠标记。", + "taskDefinition.tsconfig.description": "定义 TS 生成的 tsconfig 文件。", + "javascript.suggestionActions.enabled": "在 JavaScript 文件中启用或禁用编辑器的建议诊断。需要 TypeScript >= 2.8", + "typescript.suggestionActions.enabled": "在 TypeScript 文件中启用或禁用编辑器的建议诊断。需要 TypeScript >= 2.8" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/base/node/processes.i18n.json b/i18n/chs/src/vs/base/node/processes.i18n.json index 84aee0ac58..dbd4b558a0 100644 --- a/i18n/chs/src/vs/base/node/processes.i18n.json +++ b/i18n/chs/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "无法对 UNC 驱动器执行 shell 命令。" + "TaskRunner.UNC": "无法在 UNC 驱动器上执行 Shell 命令。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/base/node/zip.i18n.json b/i18n/chs/src/vs/base/node/zip.i18n.json index ff17c00bc1..d499d33124 100644 --- a/i18n/chs/src/vs/base/node/zip.i18n.json +++ b/i18n/chs/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "解压不完整。提取了 {0} / {1} 个项目", "notFound": "在 Zip 中找不到 {0}。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/chs/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index d513f542e3..7e6b14a8f6 100644 --- a/i18n/chs/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/chs/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "在 GitHub 中预览", "loadingData": "正在加载数据...", + "rateLimited": "超出 GitHub 查询限制。请稍候。", "similarIssues": "类似的问题", "open": "开放", "closed": "已关闭", - "noResults": "未找到结果", + "noSimilarIssues": "没有找到类似问题", "settingsSearchIssue": "设置搜索的问题", "bugReporter": "问题报告", - "performanceIssue": "性能问题", "featureRequest": "功能请求", + "performanceIssue": "性能问题", "stepsToReproduce": "重现步骤", "bugDescription": "请分享能稳定重现此问题的必要步骤,并包含实际和预期的结果。我们支持 GitHub 版的 Markdown。您将能在 GitHub 上预览时编辑这个问题并添加截图。", "performanceIssueDesciption": "这个性能问题是在什么时候发生的? 是在启动时,还是在一系列特定的操作之后? 我们支持 GitHub 版的 Markdown。您将能在 GitHub 上预览时编辑这个问题并添加截图。", diff --git a/i18n/chs/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/chs/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index 451c26222c..e0e39df949 100644 --- a/i18n/chs/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/chs/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "completeInEnglish": "请使用英文填写表单。", + "completeInEnglish": "请使用英文进行填写。", "issueTypeLabel": "这是一个", + "issueSourceLabel": "提交到", + "vscode": "Visual Studio Code", + "extension": "扩展", + "disableExtensionsLabelText": "请试着在{0}之后重现问题。如果此问题仅在扩展运行时才能重现,那么这可能是一个扩展的问题。", + "disableExtensions": "禁用所有扩展并重新加载窗口", + "chooseExtension": "扩展", "issueTitleLabel": "标题", "issueTitleRequired": "请输入标题。", "titleLengthValidation": "标题太长。", @@ -18,13 +24,6 @@ "extensions": "我的扩展", "searchedExtensions": "已搜索的扩展", "settingsSearchDetails": "设置搜索的详细信息", - "tryDisablingExtensions": "能否在禁用扩展后重现此问题?", - "yes": "是", - "no": "否", - "disableExtensionsLabelText": "尝试在{0}之后重现问题。", - "disableExtensions": "禁用所有扩展并重新加载窗口", - "showRunningExtensionsLabelText": "如果您怀疑这是扩展的问题,请{0}并进行报告。", - "showRunningExtensions": "查看所有运行中的扩展", "details": "请输入详细信息。", "loadingData": "正在加载数据..." } \ No newline at end of file diff --git a/i18n/chs/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/chs/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..fd812926a9 --- /dev/null +++ b/i18n/chs/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU %", + "memory": "内存 (MB)", + "pid": "PID", + "name": "名称", + "killProcess": "结束进程", + "forceKillProcess": "强制结束进程" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/code/electron-main/menus.i18n.json b/i18n/chs/src/vs/code/electron-main/menus.i18n.json index c2adb73a0b..86b6c05738 100644 --- a/i18n/chs/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/chs/src/vs/code/electron-main/menus.i18n.json @@ -42,7 +42,7 @@ "miExit": "退出(&&X)", "miOpenSettings": "设置(&&S)", "miOpenKeymap": "键盘快捷方式(&&K)", - "miOpenKeymapExtensions": "键映射扩展(&&K)", + "miOpenKeymapExtensions": "按键映射扩展(&&K)", "miOpenSnippets": "用户代码片段(&&S)", "miSelectColorTheme": "颜色主题(&&C)", "miSelectIconTheme": "文件图标主题(&&I)", @@ -122,8 +122,8 @@ "miFocusFirstGroup": "第一组(&&F)", "miFocusSecondGroup": "第二组(&&S)", "miFocusThirdGroup": "第三组(&&T)", - "miNextGroup": "下一个组(&&N)", - "miPreviousGroup": "上一个组(&&P)", + "miNextGroup": "下一组(&&N)", + "miPreviousGroup": "上一组(&&P)", "miSwitchGroup": "切换组(&&G)", "miGotoFile": "转到文件(&&F)...", "miGotoSymbolInFile": "转到文件中的符号(&&S)...", @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "条件断点(&&C)...", "miColumnBreakpoint": "列断点(&&O)", "miFunctionBreakpoint": "函数断点(&&F)...", + "miLogPoint": "记录点(&&L)...", "miNewBreakpoint": "新建断点(&&N)", "miEnableAllBreakpoints": "启用所有断点", "miDisableAllBreakpoints": "禁用所有断点(&&L)", @@ -161,6 +162,7 @@ "mMergeAllWindows": "合并所有窗口", "miToggleDevTools": "切换开发人员工具(&&T)", "miAccessibilityOptions": "辅助功能选项(&&O)", + "miOpenProcessExplorerer": "打开进程管理器(&&P)", "miReportIssue": "使用英文报告问题(&&I)", "miWelcome": "欢迎使用(&&W)", "miInteractivePlayground": "交互式演练场(&&I)", diff --git a/i18n/chs/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/chs/src/vs/editor/browser/widget/diffReview.i18n.json index a9f2e86537..a598740d07 100644 --- a/i18n/chs/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/chs/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "关闭", - "header": "第 {0} 个差异(共 {1} 个): 未修改 {2}, {3} 行,已修改 {4}, {5} 行", + "no_lines": "无内容", + "one_line": "1 行", + "more_lines": "{0} 行", + "header": "差异 {0},总共 {1}: 原始,{2},{3};改后,{4},{5}", "blankLine": "空白", "equalLine": "未修改 {0},已修改 {1}: {2}", "insertLine": "+ 已修改 {0}: {1}", diff --git a/i18n/chs/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/chs/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..c66c25ea99 --- /dev/null +++ b/i18n/chs/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "光标数量被限制为 {0}。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json index ccdb1d1496..acdc384835 100644 --- a/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "将行号显示为绝对行数。", "lineNumbers.relative": "将行号显示为与光标相隔的行数。", "lineNumbers.interval": "每 10 行显示一次行号。", - "lineNumbers": "控制行号的显示。可选值为 \"on\"、\"off\"、\"relative\" 和 \"interval\"。", + "lineNumbers": "控制行号的显示。", "rulers": "在一定数量的等宽字符后显示垂直标尺。输入多个值,显示多个标尺。若数组为空,则不绘制标尺。", "wordSeparators": "执行文字相关的导航或操作时将用作文字分隔符的字符", "tabSize": "一个制表符等于的空格数。该设置在 \"editor.detectIndentation\" 启用时根据文件内容可能会被覆盖。", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "控制编辑器是否可以滚动到最后一行之后", "smoothScrolling": "控制编辑器是否在滚动时使用动画", "minimap.enabled": "控制是否显示 minimap", - "minimap.side": "控制在哪一侧显示小地图。可选值为 \"right\" (右) 和 \"left\" (左)", - "minimap.showSlider": "控制是否自动隐藏小地图滑块。可选值为 \"always\" 和 \"mouseover\"", + "minimap.side": "控制在哪一侧显示小地图。", + "minimap.showSlider": "控制是否自动隐藏小地图滑块。", "minimap.renderCharacters": "呈现某行上的实际字符(与颜色块相反)", "minimap.maxColumn": "限制最小映射的宽度,尽量多地呈现特定数量的列", "find.seedSearchStringFromSelection": "控制是否将编辑器的选中内容作为搜索词填入到查找组件", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)", "multiCursorModifier.alt": "映射为 \"Alt\" (Windows 和 Linux) 或 \"Option\" (macOS)", "multiCursorModifier": "在通过鼠标添加多个光标时使用的修改键。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)。“转到定义”和“打开链接”功能所需的鼠标动作将会相应调整,不与多光标修改键冲突。", + "multiCursorMergeOverlapping": "当多个光标重叠时进行合并。", "quickSuggestions.strings": "在字符串内启用快速建议。", "quickSuggestions.comments": "在注释内启用快速建议。", "quickSuggestions.other": "在字符串和注释外启用快速建议。", @@ -57,7 +58,7 @@ "formatOnPaste": "控制编辑器是否应自动设置粘贴内容的格式。格式化程序必须可用并且能设置文档中某一范围的格式。", "autoIndent": "控制编辑器是否在用户键入、粘贴或移动行时自动调整缩进。语言的缩进规则必须可用。", "suggestOnTriggerCharacters": "控制键入触发器字符时是否应自动显示建议", - "acceptSuggestionOnEnter": "控制按“Enter”键是否像按“Tab”键一样接受建议。这能帮助避免“插入新行”和“接受建议”之间的歧义。值为“smart”时表示,仅当文字改变时,按“Enter”键才能接受建议", + "acceptSuggestionOnEnter": "控制按下 \"Enter\" 键是否像 \"Tab\" 键一样接受建议。这能减少“插入新行”和“接受建议”命令之间的歧义。若此项的值为 \"smart\",则仅在文字改变时,\"Enter\" 键才能接受建议", "acceptSuggestionOnCommitCharacter": "控制是否应在遇到提交字符时接受建议。例如,在 JavaScript 中,分号(\";\")可以为提交字符,可接受建议并键入该字符。", "snippetSuggestions.top": "在其他建议上方显示代码片段建议。", "snippetSuggestions.bottom": "在其他建议下方显示代码片段建议。", @@ -76,8 +77,8 @@ "occurrencesHighlight": "控制编辑器是否应该突出显示语义符号次数", "overviewRulerLanes": "控制可在概述标尺同一位置显示的效果数量", "overviewRulerBorder": "控制概述标尺周围是否要绘制边框。", - "cursorBlinking": "控制光标动画样式,可能的值为 \"blink\"、\"smooth\"、\"phase\"、\"expand\" 和 \"solid\"", - "mouseWheelZoom": "通过使用鼠标滚轮同时按住 Ctrl 可缩放编辑器的字体", + "cursorBlinking": "控制光标的动画样式。", + "mouseWheelZoom": "按住 Ctrl 键并滚动鼠标滚轮可缩放编辑器字体大小", "cursorStyle": "控制光标样式,接受的值为 \"block\"、\"block-outline\"、\"line\"、\"line-thin\" 、\"underline\" 和 \"underline-thin\"", "cursorWidth": "当 editor.cursorStyle 设置为 \"line\" 时控制光标的宽度。", "fontLigatures": "启用字体连字", @@ -86,8 +87,11 @@ "renderControlCharacters": "控制编辑器是否应呈现控制字符", "renderIndentGuides": "控制编辑器是否应呈现缩进参考线", "renderLineHighlight": "控制编辑器应如何呈现当前行突出显示,可能为“无”、“装订线”、“线”和“全部”。", - "codeLens": "控制编辑器是否显示 CodeLens", + "codeLens": "控制是否在编辑器中显示 CodeLens", "folding": "控制编辑器是否启用代码折叠功能", + "foldingStrategyAuto": "若语言特定的折叠策略可用,将直接使用;否则,将回退到基于缩进的折叠策略。", + "foldingStrategyIndentation": "始终使用基于缩进的折叠策略", + "foldingStrategy": "控制折叠范围的计算方式。\"auto\" 将使用语言特定的折叠策略 (若可用)。\"indentation\" 将强制使用基于缩进的折叠策略。", "showFoldingControls": "控制是否自动隐藏导航线上的折叠控件。", "matchBrackets": "当选择其中一项时,将突出显示匹配的括号。", "glyphMargin": "控制编辑器是否应呈现垂直字形边距。字形边距最常用于调试。", @@ -102,8 +106,12 @@ "links": "控制编辑器是否应检测链接并使它们可被点击", "colorDecorators": "控制编辑器是否显示内联颜色修饰器和颜色选取器。", "codeActions": "启用代码操作小灯泡提示", + "codeActionsOnSave.organizeImports": "是否在保存时整理 import 语句?", + "codeActionsOnSave": "在保存时运行的代码操作类型。", + "codeActionsOnSaveTimeout": "在保存时运行的代码操作的超时时间。", "selectionClipboard": "控制是否支持 Linux 主剪贴板。", "sideBySide": "控制 Diff 编辑器以并排或内联形式显示差异", "ignoreTrimWhitespace": "控制差异编辑器是否将对前导空格或尾随空格的更改显示为差异", + "largeFileOptimizations": "对大型文件进行特殊处理,禁用某些内存密集型功能。", "renderIndicators": "控制差异编辑器是否为已添加/删除的更改显示 +/- 指示符号" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json index 2d2c2d9db1..bde523e26e 100644 --- a/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "编辑器光标的背景色。可以自定义块型光标覆盖字符的颜色。", "editorWhitespaces": "编辑器中空白字符的颜色。", "editorIndentGuides": "编辑器缩进参考线的颜色。", + "editorActiveIndentGuide": "活动编辑器缩进参考线的颜色。", "editorLineNumbers": "编辑器行号的颜色。", "editorActiveLineNumber": "编辑器活动行号的颜色", + "deprecatedEditorActiveLineNumber": "\"Id\" 已被弃用,请改用 \"editorLineNumber.activeForeground\"。", "editorRuler": "编辑器标尺的颜色。", "editorCodeLensForeground": "编辑器 CodeLens 的前景色", "editorBracketMatchBackground": "匹配括号的背景色", @@ -28,7 +30,9 @@ "warningBorder": "编辑器中警告波浪线的边框颜色。", "infoForeground": "编辑器中信息波浪线的前景色。", "infoBorder": "编辑器中信息波浪线的边框颜色。", - "overviewRulerRangeHighlight": "概述范围突出显示的标尺标记颜色。", + "hintForeground": "编辑器中提示波浪线的前景色。", + "hintBorder": "编辑器中提示波浪线的边框颜色。", + "overviewRulerRangeHighlight": "概览标尺中高亮范围的标记颜色。颜色必须透明,使其不会挡住下方的其他元素。", "overviewRuleError": "概述错误的标尺标记颜色。", "overviewRuleWarning": "概述警告的标尺标记颜色。", "overviewRuleInfo": "概述信息的标尺标记颜色。" diff --git a/i18n/chs/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/chs/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..d034836e1c --- /dev/null +++ b/i18n/chs/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "显示修补程序({0})", + "quickFix": "显示修补程序", + "quickfix.trigger.label": "快速修复...", + "editor.action.quickFix.noneMessage": "没有可用的代码操作", + "refactor.label": "重构...", + "editor.action.refactor.noneMessage": "没有可用的重构操作", + "source.label": "源代码操作...", + "editor.action.source.noneMessage": "没有可用的源代码操作", + "organizeImports.label": "整理 import 语句", + "editor.action.organize.noneMessage": "没有可用的整理 import 语句操作" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/find/findController.i18n.json b/i18n/chs/src/vs/editor/contrib/find/findController.i18n.json index ed7b5bc015..e0efabcbc6 100644 --- a/i18n/chs/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "查找", + "startFindWithSelectionAction": "查找选定内容", "findNextMatchAction": "查找下一个", "findPreviousMatchAction": "查找上一个", "nextSelectionMatchFindAction": "查找下一个选择", diff --git a/i18n/chs/src/vs/editor/contrib/find/findWidget.i18n.json b/i18n/chs/src/vs/editor/contrib/find/findWidget.i18n.json index 76b534f388..bfd9e66f23 100644 --- a/i18n/chs/src/vs/editor/contrib/find/findWidget.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/find/findWidget.i18n.json @@ -18,6 +18,6 @@ "label.replaceAllButton": "全部替换", "label.toggleReplaceButton": "切换替换模式", "title.matchesCountLimit": "仅高亮了前 {0} 个结果,但所有查找操作均针对全文。", - "label.matchesLocation": "第 {0} 个(共 {1} 个)", + "label.matchesLocation": "{0} / {1}", "label.noResults": "无结果" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/chs/src/vs/editor/contrib/format/formatActions.i18n.json index 11896242f1..5b8eb5763f 100644 --- a/i18n/chs/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "第 {1} 行到第 {2} 行间进行了 {0} 次格式编辑", "no.provider": "当前没有安装“{0}”文件的格式化程序。", "formatDocument.label": "格式化文件", - "formatSelection.label": "格式化选定代码" + "no.documentprovider": "当前没有安装“{0}”文件的文档格式化程序。", + "formatSelection.label": "格式化选定代码", + "no.selectionprovider": "当前没有安装“{0}”文件的选定项格式化程序。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 97196c0735..823d67c3a7 100644 --- a/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "转到下一个问题 (错误、警告、信息)", - "markerAction.previous.label": "转到上一个问题 (错误、警告、信息)", - "editorMarkerNavigationError": "编辑器标记导航小组件错误颜色。", - "editorMarkerNavigationWarning": "编辑器标记导航小组件警告颜色。", - "editorMarkerNavigationInfo": "编辑器标记导航小组件信息颜色。", - "editorMarkerNavigationBackground": "编辑器标记导航小组件背景色。" + "markerAction.previous.label": "转到上一个问题 (错误、警告、信息)" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/chs/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..321c1e1198 --- /dev/null +++ b/i18n/chs/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "编辑器标记导航小组件错误颜色。", + "editorMarkerNavigationWarning": "编辑器标记导航小组件警告颜色。", + "editorMarkerNavigationInfo": "编辑器标记导航小组件信息颜色。", + "editorMarkerNavigationBackground": "编辑器标记导航小组件背景色。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/links/links.i18n.json b/i18n/chs/src/vs/editor/contrib/links/links.i18n.json index 617bf7a523..2d17f06b9f 100644 --- a/i18n/chs/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "按住 Ctrl 并单击可访问链接", "links.command.mac": "Cmd + 单击以执行命令", "links.command": "Ctrl + 单击以执行命令", + "links.navigate.al.mac": "按住 Option 并单击可访问链接", "links.navigate.al": "按住 Alt 并单击可访问链接", + "links.command.al.mac": "按住 Option 并单击可执行命令", "links.command.al": "Alt + 单击以执行命令", "invalid.url": "此链接格式不正确,无法打开: {0}", "missing.url": "此链接目标已丢失,无法打开。", diff --git a/i18n/chs/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/chs/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..7f7e56c013 --- /dev/null +++ b/i18n/chs/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "无法在只读编辑器中编辑" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/chs/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index e284f891e1..51927f1606 100644 --- a/i18n/chs/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "速览视图编辑器背景颜色。", "peekViewEditorGutterBackground": "速览视图编辑器中导航线的背景颜色。", "peekViewResultsMatchHighlight": "在速览视图结果列表中匹配突出显示颜色。", - "peekViewEditorMatchHighlight": "在速览视图编辑器中匹配突出显示颜色。" + "peekViewEditorMatchHighlight": "在速览视图编辑器中匹配突出显示颜色。", + "peekViewEditorMatchHighlightBorder": "在速览视图编辑器中匹配项的突出显示边框。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/chs/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..4729c70344 --- /dev/null +++ b/i18n/chs/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "星期日", + "Monday": "星期一", + "Tuesday": "星期二", + "Wednesday": "星期三", + "Thursday": "星期四", + "Friday": "星期五", + "Saturday": "星期六", + "SundayShort": "周日", + "MondayShort": "周一", + "TuesdayShort": "周二", + "WednesdayShort": "周三", + "ThursdayShort": "周四", + "FridayShort": "周五", + "SaturdayShort": "周六", + "January": "一月", + "February": "二月", + "March": "三月", + "April": "四月", + "May": "五月", + "June": "六月", + "July": "七月", + "August": "八月", + "September": "九月", + "October": "十月", + "November": "十一月", + "December": "十二月", + "JanuaryShort": "1月", + "FebruaryShort": "2月", + "MarchShort": "3月", + "AprilShort": "4月", + "MayShort": "5月", + "JuneShort": "6月", + "JulyShort": "7月", + "AugustShort": "8月", + "SeptemberShort": "9月", + "OctoberShort": "10月", + "NovemberShort": "11月", + "DecemberShort": "12月" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index a39a7850de..8bdc43c0b7 100644 --- a/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "符号在进行写入访问操作时的背景颜色,例如写入变量时。颜色必须透明,使其不会挡住下方的其他元素。", "wordHighlightBorder": "符号在进行读取访问操作时的边框颜色,例如读取变量。", "wordHighlightStrongBorder": "符号在进行写入访问操作时的边框颜色,例如写入变量。", - "overviewRulerWordHighlightForeground": "概述符号突出显示的标尺标记颜色。", - "overviewRulerWordHighlightStrongForeground": "概述写访问符号突出显示的标尺标记颜色。", + "overviewRulerWordHighlightForeground": "概览标尺中符号高亮的标记颜色。颜色必须透明,使其不会挡住下方的其他元素。", + "overviewRulerWordHighlightStrongForeground": "概览标尺中写入访问符号高亮的标记颜色。颜色必须透明,使其不会挡住下方的其他元素。", "wordHighlight.next.label": "转到下一个突出显示的符号", "wordHighlight.previous.label": "转到上一个突出显示的符号" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/chs/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..d31cf13c73 --- /dev/null +++ b/i18n/chs/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 个其他文件未显示", + "moreFiles": "...{0} 个其他文件未显示" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/chs/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..7667b94159 --- /dev/null +++ b/i18n/chs/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "取消" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/environment/node/argv.i18n.json b/i18n/chs/src/vs/platform/environment/node/argv.i18n.json index 873da47f51..e63ccb708a 100644 --- a/i18n/chs/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/chs/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "使用 --list-extension 时,显示已安装扩展的版本。", "installExtension": "安装扩展。", "uninstallExtension": "卸载扩展。", - "experimentalApis": "启用扩展程序实验性 api 功能。", + "experimentalApis": "为扩展启用实验性 API 功能。", "verbose": "打印详细输出(隐含 --wait 参数)。", "log": "使用的日志级别。默认值为 \"info\"。允许的值为 \"critical\" (关键)、\"error\" (错误)、\"warn\" (警告)、\"info\" (信息)、\"debug\" (调试)、\"trace\" (跟踪) 和 \"off\" (关闭)。", "status": "打印进程使用情况和诊断信息。", "performance": "通过启用 \"Developer: Startup Performance\" 命令开始。", "prof-startup": "启动期间运行 CPU 探查器", "disableExtensions": "禁用所有已安装的扩展。", - "inspect-extensions": "允许进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", - "inspect-brk-extensions": "允许在扩展主机在启动后暂停时进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", + "inspect-extensions": "允许调试和分析扩展。您可以在开发人员工具中找到连接 URI。", + "inspect-brk-extensions": "允许扩展宿主在启动后暂停时进行扩展的调试和分析。您可以在开发人员工具中找到连接 URI。", "disableGPU": "禁用 GPU 硬件加速。", "uploadLogs": "将当前会话的日志上传到安全端点。", "maxMemory": "单个窗口最大内存大小 (单位为 MB)。", diff --git a/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 2999f2563a..0e17b24b64 100644 --- a/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "扩展无效: package.json 不是 JSON 文件。", + "incompatible": "无法安装扩展“{0}”,它与 Code “{1}”不兼容。", "restartCode": "请先重启 Code 再重新安装 {0}。", "installingOutdatedExtension": "您已安装此扩展的新版程序。是否要使用旧版覆盖?", "override": "覆盖", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "安装依赖项时出错。{0}", "MarketPlaceDisabled": "商店未启用", "removeError": "删除扩展时出错: {0}。请重启 VS Code,然后重试。", - "Not Market place extension": "只能重新安装商店中的扩展", + "Not a Marketplace extension": "只能重新安装商店中的扩展", "notFoundCompatible": "无法安装“{0}”;没有可用的版本与 VS Code “{1}”兼容。", "malicious extension": "无法安装此扩展,它被报告存在问题。", "notFoundCompatibleDependency": "无法安装。找不到与 VS Code 当前版本 ({1}) 兼容的依赖扩展“{0}”。", "quitCode": "无法安装扩展。请在重启 VS Code 后重新安装。", "exitCode": "无法安装扩展。请在重启 VS Code 后重新安装。", - "uninstallDependeciesConfirmation": "要仅卸载“{0}”或者其依赖项也一起卸载?", - "uninstallOnly": "仅", - "uninstallAll": "全部", + "renameError": "将 {0} 重命名为 {1} 时发生未知错误", + "uninstallDependeciesConfirmation": "是仅卸载“{0}”还是与其依赖项一起卸载?", + "uninstallOnly": "仅此扩展", + "uninstallAll": "全部卸载", "uninstallConfirmation": "是否确定要卸载“{0}”?", "ok": "确定", "singleDependentError": "无法卸载扩展程序“{0}”。扩展程序“{1}”依赖于此。", diff --git a/i18n/chs/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/chs/src/vs/platform/extensions/node/extensionValidator.i18n.json index c4ae1449db..9231c79262 100644 --- a/i18n/chs/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/chs/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "无法分析 \"engines.vscode\" 值 {0}。例如请使用: ^0.10.0、^1.2.3、^0.11.0、^0.10.x 等。", + "versionSyntax": "无法解析 \"engines.vscode\" 的值 {0}。请改为如 ^1.22.0, ^1.22.x 等。", "versionSpecificity1": "\"engines.vscode\" ({0}) 中指定的版本不够具体。对于 1.0.0 之前的 vscode 版本,请至少定义主要和次要想要的版本。例如: ^0.10.0、0.10.x、0.11.0 等。", "versionSpecificity2": "\"engines.vscode\" ({0}) 中指定的版本不够具体。对于 1.0.0 之后的 vscode 版本,请至少定义主要想要的版本。例如: ^1.10.0、1.10.x、1.x.x、2.x.x 等。", "versionMismatch": "扩展与 Code {0} 不兼容。扩展需要: {1}。" diff --git a/i18n/chs/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/chs/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 2135ea3ae9..9d2a68887b 100644 --- a/i18n/chs/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/chs/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "{0} 安装似乎损坏。请重新安装。", "integrity.moreInformation": "详细信息", - "integrity.dontShowAgain": "不再显示", - "integrity.prompt": "{0} 安装似乎损坏。请重新安装。" + "integrity.dontShowAgain": "不再显示" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/chs/src/vs/platform/issue/electron-main/issueService.i18n.json index a303376415..2c518f204f 100644 --- a/i18n/chs/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/chs/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "问题报告程序" + "issueReporter": "问题报告程序", + "processExplorer": "进程管理器" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/list/browser/listService.i18n.json b/i18n/chs/src/vs/platform/list/browser/listService.i18n.json index 9f04dd6a88..c96dd85c96 100644 --- a/i18n/chs/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/chs/src/vs/platform/list/browser/listService.i18n.json @@ -9,8 +9,9 @@ "workbenchConfigurationTitle": "工作台", "multiSelectModifier.ctrlCmd": "映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)", "multiSelectModifier.alt": "映射为 \"Alt\" (Windows 和 Linux) 或 \"Option\" (macOS)", - "multiSelectModifier": "在通过鼠标多选树和列表条目时使用的修改键 (例如资资源管理器、打开的编辑器和源代码管理视图)。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)。“打开到侧边”功能所需的鼠标动作 (若可用) 将会相应调整,不与多选修改键冲突。", + "multiSelectModifier": "在通过鼠标多选树和列表条目时使用的修改键 (例如资资源管理器、打开的编辑器和源代码管理视图)。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)。“在侧边打开”功能所需的鼠标动作 (若可用) 将会相应调整,不与多选修改键冲突。", "openMode.singleClick": "在鼠标单击时打开项目。", "openMode.doubleClick": "在鼠标双击时打开项目。", - "openModeModifier": "控制如何在受支持的树和列表中使用鼠标来打开项目。设置为 \"singleClick\" 可单击打开项目,\"doubleClick\" 仅可双击打开项目。对于树中含子节点的节点,此设置将控制使用单击还是双击来展开他们。注意,某些不适用此项的树或列表可能会忽略此设置。" + "openModeModifier": "控制如何在受支持的树和列表中使用鼠标来打开项目。设置为 \"singleClick\" 可单击打开项目,\"doubleClick\" 仅可双击打开项目。对于树中含子节点的节点,此设置将控制使用单击还是双击来展开他们。注意,某些不适用此项的树或列表可能会忽略此设置。", + "horizontalScrolling setting": "控制工作台中的树控件是否支持水平滚动。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/markers/common/markers.i18n.json b/i18n/chs/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..3112dd48a9 --- /dev/null +++ b/i18n/chs/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "错误", + "sev.warning": "警告", + "sev.info": "信息" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json index 1c5888836f..499bcf441e 100644 --- a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "输入框中占位符的前景色。", "inputValidationInfoBackground": "输入验证结果为信息级别时的背景色。", "inputValidationInfoBorder": "严重性为信息时输入验证的边框颜色。", - "inputValidationWarningBackground": "输入验证结果为警告级别时的背景色。", + "inputValidationWarningBackground": "严重性为警告时输入验证的背景色。", "inputValidationWarningBorder": "严重性为警告时输入验证的边框颜色。", "inputValidationErrorBackground": "输入验证结果为错误级别时的背景色。", "inputValidationErrorBorder": "严重性为错误时输入验证的边框颜色。", @@ -93,6 +93,6 @@ "overviewRulerCurrentContentForeground": "内联合并冲突中当前版本区域的概览标尺前景色。", "overviewRulerIncomingContentForeground": "内联合并冲突中传入的版本区域的概览标尺前景色。", "overviewRulerCommonContentForeground": "内联合并冲突中共同祖先区域的概览标尺前景色。", - "overviewRulerFindMatchForeground": "概述查找匹配项的标尺标记颜色。", - "overviewRulerSelectionHighlightForeground": "概述选择突出显示的标尺标记颜色。" + "overviewRulerFindMatchForeground": "概览标尺中查找匹配项的标记颜色。颜色必须透明,使其不会挡住下方的其他元素。", + "overviewRulerSelectionHighlightForeground": "概览标尺中选择高亮的标记颜色。颜色必须透明,使其不会挡住下方的其他元素。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/chs/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..e28586d2eb --- /dev/null +++ b/i18n/chs/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "是否让 {0} 扩展打开以下 URL?" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..5f7e4407bb --- /dev/null +++ b/i18n/chs/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "用于标识容器的唯一 ID,视图能在容器内通过 \"view\" 参与点提供。", + "vscode.extension.contributes.views.containers.title": "人类可读的用于表示此容器的字符串", + "vscode.extension.contributes.views.containers.icon": "容器图标的路径。图标大小为 24x24,居中放置在 50x40 的方格内,其填充颜色为 \"rgb(215, 218, 224)\" 或 \"#d7dae0\"。所有图片格式均可用,推荐使用 SVG 格式。", + "vscode.extension.contributes.viewsContainers": "向编辑器提供视图容器", + "views.container.activitybar": "向活动栏提供视图容器", + "test": "测试", + "proposed": "\"viewsContainers\" 参与点仅在以开发模式运行时或附加命令行开关: --enable-proposed-api {1} 时可用", + "requirearray": "视图容器必须为数组", + "requireidstring": "属性“{0}”是必要属性,其类型必须是 \"string\"。仅支持字母、数字、\"_\" 和 \"-\"。", + "requirestring": "属性“{0}”是必要属性,其类型必须是 \"string\"", + "showViewlet": "显示 {0}", + "view": "查看" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index 42e641c625..8a68fe1f94 100644 --- a/i18n/chs/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/chs/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "人类可读的视图名称。将会被显示", "vscode.extension.contributes.view.when": "显示此视图必须为真的条件", "vscode.extension.contributes.views": "向编辑器提供视图", - "views.explorer": "资源管理器视图", - "views.debug": "调试视图", - "locationId.invalid": "“{0}”为无效视图位置", + "views.explorer": "向活动栏中的“资源管理器”容器提供视图", + "views.debug": "向活动栏中的“调试”容器提供视图", + "views.scm": "向活动栏中的“源代码管理”容器提供视图", + "views.test": "向活动栏中的“测试”容器提供视图", + "views.contributed": "在扩展提供的视图容器中提供视图。", + "ViewContainerDoesnotExist": "视图容器“{0}”不存在。所有注册到其中的视图将被添加到“资源管理器”中。", "duplicateView1": "无法在位置“{1}”注册多个 ID 同为“{0}”的视图。", "duplicateView2": "ID 为“{0}”的视图在位置“{1}”已被注册" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 2e60cbd73f..5995965464 100644 --- a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "在 {0}ms 后终止了保存时进行的格式设置", + "codeActionsOnSave.didTimeout": "在 {0}ms 后终止了 codeActionsOnSave ", + "timeout.onWillSave": "在 1750ms 后终止了 onWillSaveTextDocument 事件", "saveParticipants": "正在运行保存参与程序..." } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 491c2409e6..026ee0bdd0 100644 --- a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "webview 编辑器" + "errorMessage": "还原视图时出错: {0}" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/chs/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..07256b420b --- /dev/null +++ b/i18n/chs/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (扩展)" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index ce61fd1e08..b9d321e60f 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "聚焦于下一个组", "openToSide": "打开到侧边", "closeEditor": "关闭编辑器", + "closeOneEditor": "关闭", "revertAndCloseActiveEditor": "还原并关闭编辑器", "closeEditorsToTheLeft": "关闭左侧编辑器", "closeAllEditors": "关闭所有编辑器", diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index d4a5d65792..bd95948fc3 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "如果你没有使用屏幕阅读器,请将设置中的“editor.accessibilitySupport”改为“off”。", "disableTabMode": "禁用辅助功能模式", "gotoLine": "转到行", - "indentation": "缩进", + "selectIndentation": "选择缩进", "selectEncoding": "选择编码", "selectEOL": "选择行尾序列", "selectLanguageMode": "选择语言模式", diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index fc05d56f20..7e2c29f0a3 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} MB", "sizeGB": "{0} GB", "sizeTB": "{0} TB", - "largeImageError": "图像文件太大 (>1 MB),无法在编辑器中显示。", + "largeImageError": "图片太大,无法在编辑器中显示 ({0})。 ", "resourceOpenExternalButton": "使用外部程序打开图片?", - "nativeBinaryError": "因为此文件是二进制文件,或文件过大,或使用了不受支持的文本编码,将不会在编辑器中显示。", + "nativeFileTooLargeError": "文件太大,无法在编辑器中显示 ({0})。", + "nativeBinaryError": "此文件是二进制文件或使用了不支持的文本编码,无法在编辑器中显示。", + "openAsText": "是否仍要打开?", "zoom.action.fit.label": "整个图像", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index d3dc549f09..248cdd0ff5 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "关闭", "araLabelEditorActions": "编辑器操作" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index a4d805c767..b9a579c756 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "没有新通知", "notifications": "通知", "notificationsToolbar": "通知中心操作", "notificationsList": "通知列表" diff --git a/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..23748047f4 --- /dev/null +++ b/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (按 \"Enter\" 键确认或按 \"Esc\" 键取消)", + "inputModeEntry": "按 \"Enter\" 键确认或按 \"Esc\" 键取消", + "quickInput.countSelected": "已选 {0} 项", + "ok": "确定" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..a968ba2efa --- /dev/null +++ b/i18n/chs/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "在此输入可缩小结果范围。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json index 2230df37e8..5d52fa2ca9 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "打开最近的文件…", "quickOpenRecent": "快速打开最近的文件…", "reportIssueInEnglish": "使用英文报告问题", + "openProcessExplorer": "打开进程管理器", "reportPerformanceIssue": "报告性能问题", "keybindingsReference": "键盘快捷方式参考", "openDocumentationUrl": "文档", diff --git a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json index 76f8a69f21..6a7713cb22 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "窗口", "window.openFilesInNewWindow.on": "文件将在新窗口中打开", "window.openFilesInNewWindow.off": "文件将在该文件的文件夹打开的窗口中打开,或在上一个活动窗口中打开", - "window.openFilesInNewWindow.default": "文件将在该文件的文件夹打开的窗口中打开,或在上一个活动窗口中打开,除非通过平台或从查找程序(仅限 macOS)打开", - "openFilesInNewWindow": "控制是否应在新窗口中打开文件。\n- default: 文件将在该文件的文件夹打开的窗口中打开,或在上一个活动窗口中打开,除非该文件通过平台或从查找程序(仅限 macOS)打开\n- on: 文件将在新窗口中打开\n- off: 文件将在该文件的文件夹打开的窗口中打开,或在上一个活动窗口中打开\n注意,可能仍会存在忽略此设置的情况(例如当使用 -new-window 或 -reuse-window 命令行选项时)。", + "window.openFilesInNewWindow.defaultMac": "在不通过“程序坞”(Dock) 或“访达”(Finder) 打开的情况下,文件将在其所在文件夹的已有窗口中打开,或在上一个活动窗口中打开", + "window.openFilesInNewWindow.default": "除了从软件内部选择的文件 (如,从“文件”菜单选择),其他所有文件都将在新窗口中打开", + "openFilesInNewWindowMac": "控制是否在新窗口中打开文件。\n- default: 在不通过“程序坞”(Dock) 或“访达”(Finder) 打开的情况下,文件将在其所在文件夹的已有窗口中打开,或在上一个活动窗口中打开\n- on: 文件将在新窗口中打开\n- off: 文件将在其所在文件夹的已有窗口中打开,或在上一个活动窗口中打开\n注意,此设置可能会被忽略 (例如,在使用 -new-window 或 -reuse-window 命令行选项时)。", + "openFilesInNewWindow": "控制是否在新窗口中打开文件。\n- default: 除了从软件内部选择的文件 (如,从“文件”菜单选择),其他所有文件都将在新窗口中打开\n- on: 文件将在新窗口中打开\n- off: 文件将在其所在文件夹的已有窗口中打开,或在上一个活动窗口中打开\n注意,此设置可能会被忽略 (例如,在使用 -new-window 或 -reuse-window 命令行选项时)。", "window.openFoldersInNewWindow.on": "文件夹将在新窗口中打开", "window.openFoldersInNewWindow.off": "文件夹将替换上一个活动窗口", "window.openFoldersInNewWindow.default": "文件夹在新窗口中打开,除非从应用程序内选取一个文件夹(例如,通过“文件”菜单)", "openFoldersInNewWindow": "控制文件夹应在新窗口中打开还是替换上一活动窗口。\n- default: 文件夹将在新窗口中打开,除非文件是从应用程序内选取的(例如通过“文件”菜单)\n- on: 文件夹将在新窗口中打开\n- off: 文件夹将替换上一活动窗口\n注意,可能仍会存在忽略此设置的情况(例如当使用 -new-window 或 -reuse-window 命令行选项时)。", + "window.openWithoutArgumentsInNewWindow.on": "打开一个新的空窗口", + "window.openWithoutArgumentsInNewWindow.off": "聚焦于最后活动的运行实例", + "openWithoutArgumentsInNewWindow": "控制在另一实例无参启动时打开新的空窗口或是聚焦到最后运行的实例\n- on: 打开新的空窗口\n- off: 最后活动的运行实例将获得焦点\n注意,此设置可能会被忽略 (例如,在使用 -new-window 或 -reuse-window 命令行选项时)。", "window.reopenFolders.all": "重新打开所有窗口。", "window.reopenFolders.folders": "重新打开所有文件夹。空工作区将不会被恢复。", "window.reopenFolders.one": "重新打开上一个活动窗口。", @@ -58,7 +63,7 @@ "restoreWindows": "控制重启后重新打开窗口的方式。选择 \"none\" 则永远在启动时打开一个空工作区,\"one\" 则重新打开最后使用的窗口,\"folders\" 则重新打开所有含有文件夹的窗口,\"all\" 则重新打开上次会话的所有窗口。", "restoreFullscreen": "如果窗口已退出全屏模式,控制其是否应还原为全屏模式。", "zoomLevel": "调整窗口的缩放级别。原始大小是 0,每次递增(例如 1)或递减(例如 -1)表示放大或缩小 20%。也可以输入小数以便以更精细的粒度调整缩放级别。", - "title": "根据活动编辑器控制窗口标题。变量基于上下文进行替换:\n${activeEditorShort}: 文件名 (如 myFile.txt)\n${activeEditorMedium}: 相对于工作区文件夹的文件路径 (如 myFolder/myFile.txt)\n${activeEditorLong}: 文件的完整路径 (如 /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 文件所在工作区文件夹名称 (如 myFolder)\n${folderPath}: 文件所在工作区文件夹路径 (如 /Users/Development/myFolder)\n${rootName}: 工作区名称 (如 myFolder 或 myWorkspace)\n${rootPath}: 工作区路径 (如 /Users/Development/myWorkspace)\n${appName}: 如 VS Code\n${dirty}: 活动编辑器有更新时显示的更新指示器\n${separator}: 仅在被有值变量包围时显示的分隔符 (\" - \")", + "title": "根据活动编辑器控制窗口标题。变量基于上下文进行替换:\n${activeEditorShort}: 文件名 (如 myFile.txt)\n${activeEditorMedium}: 相对于工作区文件夹的文件路径 (如 myFolder/myFile.txt)\n${activeEditorLong}: 文件的完整路径 (如 /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 文件所在工作区文件夹名称 (如 myFolder)\n${folderPath}: 文件所在工作区文件夹路径 (如 /Users/Development/myFolder)\n${rootName}: 工作区名称 (如 myFolder 或 myWorkspace)\n${rootPath}: 工作区路径 (如 /Users/Development/myWorkspace)\n${appName}: 如 VS Code\n${dirty}: 活动编辑器有更新时显示的更新指示器\n${separator}: 仅在被有值变量或静态文本包围时显示的分隔符 (\" - \")", "window.newWindowDimensions.default": "在屏幕中心打开新窗口。", "window.newWindowDimensions.inherit": "以与上一个活动窗口相同的尺寸打开新窗口。", "window.newWindowDimensions.maximized": "打开最大化的新窗口。", @@ -70,10 +75,12 @@ "window.menuBarVisibility.toggle": "菜单隐藏,但可以通过 Alt 键显示。", "window.menuBarVisibility.hidden": "菜单始终隐藏。", "menuBarVisibility": "控制菜单栏的可见性。“切换”设置表示隐藏菜单栏,按一次 Alt 键则将显示此菜单栏。默认情况下,除非窗口为全屏,否则菜单栏可见。", - "enableMenuBarMnemonics": "如果启用,则可使用 Alt 快捷键打开主菜单。禁用助记键允许将这些 Alt 快捷键绑定到编辑器命令。", + "enableMenuBarMnemonics": "启用后,即可使用 Alt 快捷键打开主菜单。若禁用助记键,这些 Alt 快捷键将能绑定到编辑器命令。", "autoDetectHighContrast": "如果已启用,将自动更改为高对比度主题;如果 Windows 正在使用高对比度主题,则当离开 Windows 高对比度主题时会更改为深色主题。", "titleBarStyle": "调整窗口标题栏的外观。更改需要在完全重启后才能应用。", "window.nativeTabs": "\n启用macOS Sierra窗口选项卡。请注意,更改需要完全重新启动程序才能生效。如果配置此选项,本机选项卡将禁用自定义标题栏样式。", + "window.smoothScrollingWorkaround": "启用解决方案来修复还原最小化的 VS Code 窗口后平滑滚动消失的问题。这个滚动的卡顿问题出现在拥有精确式触控板的设备上,比如来自 Microsoft 的 Surface 设备(https://github.com/Microsoft/vscode/issues/13612)。如果启用这个解决方案,窗口布局可能会在从最小化状态中还原后有些许闪烁,其他方面则无大碍。", + "window.clickThroughInactive": "启用后,点击非活动窗口后将在激活窗口的同时触发光标之下的元素 (若可点击)。禁用后,点击非活动窗口仅能激活窗口,再次点击才能触发元素。", "zenModeConfigurationTitle": "Zen 模式", "zenMode.fullScreen": "控制打开 Zen Mode 是否也会将工作台置于全屏模式。", "zenMode.centerLayout": "控制是否在 Zen 模式中启用居中布局", diff --git a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json index 07da1c7f8d..dc7f641116 100644 --- a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json @@ -15,12 +15,12 @@ "auto_unknown": "编辑器被配置为使用平台 API 以检测是否附加了屏幕阅读器,但当前运行时不支持此功能。", "auto_on": "编辑器自动检测到已附加屏幕阅读器。", "auto_off": "编辑器被配置为自动检测是否附加了屏幕阅读器,当前未检测到。", - "configuredOn": "编辑器被配置为对屏幕阅读器的使用进行永久优化 — 你可以编辑设置中的“editor.accessibilitySupport”以改变此行为。", + "configuredOn": "已配置编辑器对屏幕阅读器进行永久优化 — 您可以更改 \"editor.accessibilitySupport\" 设置进行调整。", "configuredOff": "编辑器被配置为不对屏幕阅读器的使用进行优化。", "tabFocusModeOnMsg": "在当前编辑器中按 Tab 会将焦点移动到下一个可聚焦的元素。按 {0} 来切换此行为。", - "tabFocusModeOnMsgNoKb": "在当前编辑器中按 Tab 会将焦点移动到下一个可聚焦的元素。当前无法通过键绑定触发命令 {0}。", + "tabFocusModeOnMsgNoKb": "若在当前编辑器中按 Tab 键,将移动焦点到下一个可聚焦的元素。当前无法通过按键绑定触发命令 {0}。", "tabFocusModeOffMsg": "在当前编辑器中按 Tab 将插入制表符。按 {0} 来切换此行为。", - "tabFocusModeOffMsgNoKb": "在当前编辑器中按 Tab 会插入制表符。当前无法通过键绑定触发命令 {0}。", + "tabFocusModeOffMsgNoKb": "若在当前编辑器中按 Tab 键,将插入制表符。当前无法通过按键绑定触发命令 {0}。", "openDocMac": "按 Command+H 以打开浏览器窗口,其中包含更多有关 VS Code 辅助功能的信息。", "openDocWinLinux": "按 Ctrl+H 以打开浏览器窗口,其中包含更多有关 VS Code 辅助功能的信息。", "outroMsg": "你可以按 Esc 或 Shift+Esc 消除此工具提示并返回到编辑器。", diff --git a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/inspectKeybindings.i18n.json b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/inspectKeybindings.i18n.json index 850bdfb263..0f3ed8dea2 100644 --- a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/inspectKeybindings.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/inspectKeybindings.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "workbench.action.inspectKeyMap": "开发者: 检查键映射" + "workbench.action.inspectKeyMap": "开发者: 检查按键映射" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.i18n.json b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.i18n.json index de9ba271fa..fed0a8e036 100644 --- a/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.i18n.json @@ -8,6 +8,6 @@ ], "toggle.wordwrap": "查看: 切换自动换行", "wordWrap.notInDiffEditor": "不能在差异编辑器中切换自动换行。", - "unwrapMinified": "为此文件禁用折行", - "wrapMinified": "为此文件启用换行" + "unwrapMinified": "在此文件禁用折行", + "wrapMinified": "在此文件启用折行" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 1865968d54..890acbc214 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "编辑断点...", + "logPoint": "记录点", + "breakpoint": "断点", + "editBreakpoint": "编辑 {0}...", + "removeBreakpoint": "删除 {0}", "functionBreakpointsNotSupported": "此调试类型不支持函数断点", "functionBreakpointPlaceholder": "要断开的函数", "functionBreakPointInputAriaLabel": "键入函数断点", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "未验证的断点", "functionBreakpointUnsupported": "不受此调试类型支持的函数断点", "breakpointDirtydHover": "未验证的断点。对文件进行了修改,请重启调试会话。", + "logBreakpointUnsupported": "不受此调试类型支持的记录点", "conditionalBreakpointUnsupported": "不受此调试类型支持的条件断点", "hitBreakpointUnsupported": "命中不受此调试类型支持的条件断点" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 7b632936fc..f5e7e8a940 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "断开连接", "continueDebug": "继续", "pauseDebug": "暂停", + "terminateThread": "终止线程", "restartFrame": "重新启动框架", "removeBreakpoint": "删除断点", "removeAllBreakpoints": "删除所有断点", - "enableBreakpoint": "启用断点", - "disableBreakpoint": "禁用断点", "enableAllBreakpoints": "启用所有断点", "disableAllBreakpoints": "禁用所有断点", "activateBreakpoints": "激活断点", "deactivateBreakpoints": "停用断点", "reapplyAllBreakpoints": "重新应用所有断点", "addFunctionBreakpoint": "添加函数断点", - "addConditionalBreakpoint": "添加条件断点...", - "editConditionalBreakpoint": "编辑断点...", "setValue": "设置值", "addWatchExpression": "添加表达式", "editWatchExpression": "编辑表达式", diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 3bf22d1022..ab1e8acd57 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "调试: 切换断点", "conditionalBreakpointEditorAction": "调试: 添加条件断点...", + "logPointEditorAction": "调试: 添加记录点...", "runToCursor": "运行到光标处", "debugEvaluate": "调试: 求值", "debugAddToWatch": "调试: 添加到监视", diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/linkDetector.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/linkDetector.i18n.json index 7a4ac0a5ed..79ff90499a 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/linkDetector.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/linkDetector.i18n.json @@ -6,6 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "fileLinkMac": "点击以跟进(Cmd + 点击打开到侧边)", - "fileLink": "点击以跟进(Ctrl + 点击打开到侧边))" + "fileLinkMac": "单击打开 (按住 Cmd 键并单击在侧边打开)", + "fileLink": "单击打开 (按住 Ctrl 键并单击在侧边打开)" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..f13fb148e6 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "断点命中时记录的消息。{} 内的表达式将被替换。按 \"Enter\" 键确认,\"Esc\" 键取消。", + "breakpointWidgetHitCountPlaceholder": "在满足命中次数条件时中断。按 \"Enter\" 表示接受,\"Esc\" 表示取消。", + "breakpointWidgetExpressionPlaceholder": "在表达式计算结果为 true 时中断。按 \"Enter\" 表示接受,\"Esc\" 表示取消。", + "expression": "表达式", + "hitCount": "命中次数", + "logMessage": "记录消息" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 4ad61eed6d..4b5af2bc96 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "配置名称必须唯一。", "app.launch.json.compound.folder": "复合项所在的文件夹的名称。", "app.launch.json.compounds.configurations": "将作为此复合的一部分启动的配置名称。", - "debugNoType": "不可省略调试适配器“类型”,其类型必须是“字符串”。", + "debugNoType": "不可省略调试器的 \"type\" 属性,且其类型必须是 \"string\" 。", "selectDebug": "选择环境", "DebugConfig.failed": "无法在 \".vscode\" 文件夹({0})内创建 \"launch.json\" 文件。", "workspace": "工作区", diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index fcde23632e..a99b218685 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "记录点", + "breakpoint": "断点", + "removeBreakpoint": "删除 {0}", + "editBreakpoint": "编辑 {0}...", + "disableBreakpoint": "禁用 {0}", + "enableBreakpoint": "启用 {0}", "removeBreakpoints": "删除断点", "removeBreakpointOnColumn": "在列 {0} 上删除断点", "removeLineBreakpoint": "删除行断点", @@ -18,5 +24,13 @@ "enableBreakpoints": "在列 {0} 上启用断点", "enableBreakpointOnLine": "启用行断点", "addBreakpoint": "添加断点", + "addConditionalBreakpoint": "添加条件断点...", + "addLogPoint": "添加记录点...", + "breakpointHasCondition": "此{0}的{1}将在删除后丢失。请考虑仅禁用此{0}。", + "message": "消息", + "condition": "条件", + "removeLogPoint": "删除 {0}", + "disableLogPoint": "禁用 {0}", + "cancel": "取消", "addConfiguration": "添加配置..." } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 3496a373fc..8a0f328a39 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "显示错误", "noFolderWorkspaceDebugError": "无法调试活动文件。请确保它保存在磁盘上,并确保已为该文件类型安装了调试扩展。", "cancel": "取消", - "DebugTaskNotFound": "找不到 preLaunchTask“{0}”。", - "taskNotTracked": "无法跟踪 preLaunchTask “{0}”。" + "DebugTaskNotFound": "找不到任务“{0}”。", + "taskNotTracked": "无法跟踪任务“{0}”。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index ab3bec3b25..3a03b9d077 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "详细信息", - "unableToLaunchDebugAdapter": "无法从“{0}”启动调试适配器。", - "unableToLaunchDebugAdapterNoArgs": "无法启动调试适配器。", - "stoppingDebugAdapter": "{0}。正在停止调试适配器。", "debugAdapterCrash": "调试适配器进程已意外终止" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 57c28ff6f1..54eddc6e47 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "调试适配器可执行的“{0}”不存在。", "debugAdapterCannotDetermineExecutable": "无法确定调试适配器“{0}”的可执行文件。", - "launch.config.comment1": "使用 IntelliSense 了解相关属性。 ", - "launch.config.comment2": "悬停以查看现有属性的描述。", - "launch.config.comment3": "欲了解更多信息,请访问: {0}", - "debugType": "配置类型。", - "debugTypeNotRecognised": "无法识别此调试类型。确保已经安装并启用相应的调试扩展。", - "node2NotSupported": "不再支持 \"node2\",改用 \"node\",并将 \"protocol\" 属性设为 \"inspector\"。", - "debugName": "配置名称;在启动配置下拉菜单中显示。", - "debugRequest": "请求配置类型。可以是“启动”或“附加”。", - "debugServer": "仅用于调试扩展开发: 如果已指定端口,VS 代码会尝试连接到在服务器模式中运行的调试适配器", - "debugPrelaunchTask": "调试会话开始前要运行的任务。", - "debugWindowsConfiguration": "特定于 Windows 的启动配置属性。", - "debugOSXConfiguration": "特定于 OS X 的启动配置属性。", - "debugLinuxConfiguration": "特定于 Linux 的启动配置属性。", - "deprecatedVariables": "已弃用 \"env.\"、\"config.\" 和 \"command.\",改用 \"env:\"、\"config:\" 和 \"command:\"。" + "unableToLaunchDebugAdapter": "无法从“{0}”启动调试适配器。", + "unableToLaunchDebugAdapterNoArgs": "无法启动调试适配器。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..d94c69e8e7 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "使用 IntelliSense 了解相关属性。 ", + "launch.config.comment2": "悬停以查看现有属性的描述。", + "launch.config.comment3": "欲了解更多信息,请访问: {0}", + "debugType": "配置类型。", + "debugTypeNotRecognised": "无法识别此调试类型。确保已经安装并启用相应的调试扩展。", + "node2NotSupported": "不再支持 \"node2\",改用 \"node\",并将 \"protocol\" 属性设为 \"inspector\"。", + "debugName": "配置名称;在启动配置下拉菜单中显示。", + "debugRequest": "请求配置类型。可以是“启动”或“附加”。", + "debugServer": "仅用于调试扩展开发: 如果已指定端口,VS 代码会尝试连接到在服务器模式中运行的调试适配器", + "debugPrelaunchTask": "调试会话开始前要运行的任务。", + "debugPostDebugTask": "调试会话结束后运行的任务。", + "debugWindowsConfiguration": "特定于 Windows 的启动配置属性。", + "debugOSXConfiguration": "特定于 OS X 的启动配置属性。", + "debugLinuxConfiguration": "特定于 Linux 的启动配置属性。", + "deprecatedVariables": "已弃用 \"env.\"、\"config.\" 和 \"command.\",改用 \"env:\"、\"config:\" 和 \"command:\"。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..87183ec39c --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code 控制台", + "mac.terminal.script.failed": "脚本“{0}”失败,退出代码为 {1}", + "mac.terminal.type.not.supported": "不支持“{0}”", + "press.any.key": "按任意键继续...", + "linux.term.failed": "“{0}”失败,退出代码为 {1}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 07a89ca943..166181362a 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -50,7 +50,7 @@ "allExtensionsInstalled": "已安装根据工作区推荐的所有扩展", "installRecommendedExtension": "安装推荐的扩展", "extensionInstalled": "您已经安装过此推荐扩展", - "showRecommendedKeymapExtensionsShort": "键映射", + "showRecommendedKeymapExtensionsShort": "按键映射", "showLanguageExtensionsShort": "语言扩展", "showAzureExtensionsShort": "Azure 扩展", "OpenExtensionsFile.failed": "无法在 \".vscode\" 文件夹({0})内创建 \"extensions.json\" 文件。", @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "配置建议的扩展(工作区文件夹)", "malicious tooltip": "此扩展被报告存在问题。", "malicious": "恶意扩展", + "disabled": "已禁用", + "disabled globally": "已禁用", + "disabled workspace": "已在此工作区禁用", "disableAll": "禁用所有已安装的扩展", "disableAllWorkspace": "禁用此工作区的所有已安装的扩展", "enableAll": "启用所有扩展", diff --git a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..9b363a9078 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "扩展名", + "extension id": "扩展标识符", + "preview": "预览版", + "builtin": "内置", + "publisher": "发布服务器名称", + "install count": "安装计数", + "rating": "评级", + "repository": "存储库", + "license": "许可证", + "details": "详细信息", + "contributions": "发布内容", + "changelog": "更改日志", + "dependencies": "依赖项", + "noReadme": "无可用自述文件。", + "noChangelog": "无可用的更改日志。", + "noContributions": "没有发布内容", + "noDependencies": "没有依赖项", + "settings": "设置({0})", + "setting name": "名称", + "description": "描述", + "default": "默认", + "debuggers": "调试程序({0})", + "debugger name": "名称", + "debugger type": "类型", + "views": "视图 ({0})", + "view id": "ID", + "view name": "名称", + "view location": "位置", + "localizations": "本地化 ({0})", + "localizations language id": "语言 ID", + "localizations language name": "语言名称", + "localizations localized language name": "语言本地名称", + "colorThemes": "颜色主题 ({0})", + "iconThemes": "图标主题 ({0})", + "colors": "颜色 ({0})", + "colorId": "ID", + "defaultDark": "深色默认", + "defaultLight": "浅色默认", + "defaultHC": "高对比度默认", + "JSON Validation": "JSON 验证({0})", + "fileMatch": "匹配文件", + "schema": "结构", + "commands": "命令({0})", + "command name": "名称", + "keyboard shortcuts": "键盘快捷方式", + "menuContexts": "菜单上下文", + "languages": "语言({0})", + "language id": "ID", + "language name": "名称", + "file extensions": "文件扩展名", + "grammar": "语法", + "snippets": "代码片段" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index ce3f5753c0..7c0e25df29 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "neverShowAgain": "不再显示", - "searchMarketplace": "搜索应用商店", + "searchMarketplace": "搜索商店", "showLanguagePackExtensions": "商店中有可以将 VS Code 本地化为“{0}”语言的扩展。", "dynamicWorkspaceRecommendation": "您可能会对这个扩展感兴趣,它在 {0} 存储库的用户间流行。", "exeBasedRecommendation": "根据你安装的 {0},向你推荐此扩展。", @@ -15,8 +15,8 @@ "workspaceRecommendation": "当前工作区的用户推荐此扩展。", "reallyRecommended2": "建议对这种类型的文件使用“{0}”扩展。", "reallyRecommendedExtensionPack": "建议对这种类型的文件使用“{0}”扩展包。", - "showRecommendations": "显示建议", "install": "安装", + "showRecommendations": "显示建议", "showLanguageExtensions": "商店中有可以对 \".{0}\" 文件提供帮助的扩展。", "workspaceRecommended": "此工作区具有扩展建议。", "installAll": "全部安装", diff --git a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index c49c9b417a..5a7316d3e9 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -6,9 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "disableOtherKeymapsConfirmation": "禁用其他键映射 ({0}) 以避免键绑定之间的冲突?", + "disableOtherKeymapsConfirmation": "是否禁用其他按键映射扩展 ({0}),从而避免按键绑定之间的冲突?", "yes": "是", - "no": "否", - "betterMergeDisabled": "现已内置 Better Merge 扩展。此扩展已被安装并禁用,且能被卸载。", - "uninstall": "卸载" + "no": "否" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index d3d6491afd..418d6d5683 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -12,7 +12,9 @@ "recommendedExtensions": "推荐", "otherRecommendedExtensions": "其他推荐", "workspaceRecommendedExtensions": "工作区推荐", - "builtInExtensions": "内置", + "builtInExtensions": "功能", + "builtInThemesExtensions": "主题", + "builtInBasicsExtensions": "编程语言", "searchExtensions": "在商店中搜索扩展", "sort by installs": "排序依据: 安装计数", "sort by rating": "排序依据: 分级", diff --git a/i18n/chs/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index da60fe1e62..cd4305d89a 100644 --- a/i18n/chs/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "文本文件编辑器", "createFile": "创建文件", + "relaunchWithIncreasedMemoryLimit": "以 {0}MB 重启", + "configureMemoryLimit": "配置内存限制", "fileEditorWithInputAriaLabel": "{0}。文本文件编辑器。", "fileEditorAriaLabel": "文本文件编辑器。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 435aa04992..9b2a8fce41 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -17,7 +17,7 @@ "compareActiveWithSaved": "比较活动与已保存的文件", "closeEditor": "关闭编辑器", "view": "查看", - "openToSide": "打开到侧边", + "openToSide": "在侧边打开", "revealInWindows": "在资源管理器中显示", "revealInMac": "在 Finder 中显示", "openContainer": "打开所在的文件夹", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 0131cbc290..f2e95abe6d 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "复制", "pasteFile": "粘贴", "retry": "重试", + "renameWhenSourcePathIsParentOfTargetError": "请使用“新建文件夹”或“新建文件”命令来向已有文件夹添加子项", "newUntitledFile": "新的无标题文件", "createNewFile": "新建文件", "createNewFolder": "新建文件夹", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "你正在删除的文件夹有 {0} 个文件具有未保存的更改。是否继续?", "dirtyMessageFileDelete": "你正在删除的文件具有未保存的更改。是否继续?", "dirtyWarning": "如果不保存,更改将丢失。", - "confirmMoveTrashMessageMultiple": "是否确定要删除以下 {0} 个文件?", - "confirmMoveTrashMessageFolder": "是否确实要删除“{0}”及其内容?", - "confirmMoveTrashMessageFile": "是否确实要删除“{0}”?", "undoBin": "可以从回收站还原。", "undoTrash": "可以从废纸篓还原。", "doNotAskAgain": "不再询问", + "irreversible": "此操作不可逆!", + "binFailed": "无法删除到回收站。是否永久删除?", + "trashFailed": "无法删除到废纸篓。是否永久删除?", + "deletePermanentlyButtonLabel": "永久删除(&&D)", + "retryButtonLabel": "重试(&&R)", + "confirmMoveTrashMessageFilesAndDirectories": "是否确定要删除以下 {0} 个文件或文件夹 (包括其内容)?", + "confirmMoveTrashMessageMultipleDirectories": "是否确定要删除以下 {0} 个文件夹及其内容?", + "confirmMoveTrashMessageMultiple": "是否确定要删除以下 {0} 个文件?", + "confirmMoveTrashMessageFolder": "是否确实要删除“{0}”及其内容?", + "confirmMoveTrashMessageFile": "是否确实要删除“{0}”?", + "confirmDeleteMessageFilesAndDirectories": "是否确定要永久删除以下 {0} 个文件或文件夹 (包括其内容)?", + "confirmDeleteMessageMultipleDirectories": "是否确定要永久删除以下 {0} 个目录及其内容?", "confirmDeleteMessageMultiple": "是否确定要永久删除以下 {0} 个文件?", "confirmDeleteMessageFolder": "是否确定要永久删除“{0}”及其内容?", "confirmDeleteMessageFile": "是否确定要永久删除“{0}”?", - "irreversible": "此操作不可逆!", - "cancel": "取消", - "permDelete": "永久删除", - "importFiles": "导入文件", + "addFiles": "添加文件", "confirmOverwrite": "目标文件夹中已存在具有相同名称的文件或文件夹。是否要替换它?", "replaceButtonLabel": "替换(&&R)", "fileIsAncestor": "粘贴的项目是目标文件夹的上级", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "请先打开要在新窗口中打开的文件", "copyPath": "复制路径", "emptyFileNameError": "必须提供文件或文件夹名。", + "fileNameStartsWithSlashError": "文件或文件夹名称不能以斜线开头。", "fileNameExistsError": "此位置已存在文件或文件夹 **{0}**。请选择其他名称。", + "fileUsedAsFolderError": "**{0}** 是一个文件,不能含有子项。", "invalidFileNameError": "名称 **{0}** 作为文件或文件夹名无效。请选择其他名称。", "filePathTooLongError": "名称 **{0}** 导致路径太长。请选择更短的名称。", "compareWithClipboard": "比较活动文件与剪贴板", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index bc031ad48e..73f0316ec5 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -30,13 +30,15 @@ "autoSaveDelay": "控制在多少毫秒后自动保存更改过的文件。仅在“files.autoSave”设置为“{0}”时适用。", "watcherExclude": "配置文件路径的 glob 模式以从文件监视排除。模式必须在绝对路径上匹配(例如 ** 前缀或完整路径需正确匹配)。更改此设置需要重启。如果在启动时遇到 Code 消耗大量 CPU 时间,则可以排除大型文件夹以减少初始加载。", "hotExit.off": "禁用热退出。", - "hotExit.onExit": "应用程序关闭时将触发热退出。在 Windows/Linux 上关闭最后一个窗口或触发 workbench.action.quit 命令(命令托盘、键绑定、菜单)会引起应用程序关闭。下次启动时将还原所有已备份的窗口。", - "hotExit.onExitAndWindowClose": "应用程序关闭时将触发热退出。在 Windows/Linux 上关闭最后一个窗口、触发 workbench.action.quit 命令(命令托盘、键绑定、菜单)会引起应用程序关闭。对于任何有文件夹打开的窗口,则不论该窗口是否是最后一个窗口。下次启动时将还原所有未打开文件夹的窗口。若要还原打开有文件夹的窗口,请将“window.restoreWindows”设置为“all”。", + "hotExit.onExit": "应用程序关闭时将自动保留未保存内容 (热退出)。关闭的定义为,在 Windows/Linux 上关闭最后一个窗口或者在全平台触发 workbench.action.quit 命令 (命令托盘、键绑定、菜单)。下次启动时将还原所有已备份的窗口。", + "hotExit.onExitAndWindowClose": "应用程序关闭时将自动保留未保存内容 (热退出)。关闭的定义为,在 Windows/Linux 上关闭最后一个窗口,在全平台触发 workbench.action.quit 命令 (命令托盘、按键绑定、菜单),对于任何打开有文件夹的窗口,则不论该窗口是否是最后一个窗口。下次启动时将还原所有未打开文件夹的窗口。若要还原打开有文件夹的窗口,请将 \"window.restoreWindows\" 设置为 \"all\"。", "hotExit": "控制是否在会话间记住未保存的文件,以允许在退出编辑器时跳过保存提示。", "useExperimentalFileWatcher": "使用新的试验文件观察程序。", "defaultLanguage": "分配给新文件的默认语言模式。", + "maxMemoryForLargeFilesMB": "在打开大型文件时,控制 VS Code 可在重启后使用的内存。在命令行中指定“--max-memory=新的大小”参数可达到相同效果。", "editorConfigurationTitle": "编辑器", "formatOnSave": "保存时设置文件的格式。格式化程序必须可用,不能自动保存文件,并且不能关闭编辑器。", + "formatOnSaveTimeout": "在保存时格式化操作的超时时间。为 formatOnSave 命令指定时间限制 (单位: 毫秒)。运行超过设定时间的命令将被取消。", "explorerConfigurationTitle": "文件资源管理器", "openEditorsVisible": "在“打开的编辑器”窗格中显示的编辑器数量。", "autoReveal": "控制资源管理器是否应在打开文件时自动显示并选择它们。", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 3d8f7993f5..347e440204 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -6,14 +6,18 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "fileInputAriaLabel": "键入文件名。按 Enter 以确认或按 Esc 以取消。", - "constructedPath": "在 **{1}** 创建{0}", + "fileInputAriaLabel": "输入文件名。按 \"Enter\" 键确认或按 \"Esc\" 键取消。", + "createFileFromExplorerInfoMessage": "在 **{1}** 中创建文件 **{0}**", + "renameFileFromExplorerInfoMessage": "移动并重命名为 **{0}**", + "createFolderFromExplorerInfoMessage": "在 **{1}** 中创建文件夹 **{0}**", "filesExplorerViewerAriaLabel": "{0},文件资源管理器", "dropFolders": "你是否要将文件夹添加到工作区?", "dropFolder": "你是否要将文件夹添加到工作区?", "addFolders": "添加文件夹(&&A)", "addFolder": "添加文件夹(&&A)", + "confirmRootsMove": "是否确定要更改工作区中多个根文件夹的顺序?", "confirmMultiMove": "是否确定要移动以下 {0} 个文件?", + "confirmRootMove": "是否确定要更改工作区中根文件夹“{0}”的顺序?", "confirmMove": "是否确实要移动“{0}”?", "doNotAskAgain": "不再询问", "moveButtonLabel": "移动(&&M)", diff --git a/i18n/chs/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..f094961018 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "HTML 预览" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/chs/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..3cbb0b9c0c --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "编辑器输入无效。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..4602f03121 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "开发者" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/chs/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..bad27cc286 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "打开 Webview 开发工具", + "refreshWebviewLabel": "重新加载 Webview" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index 0d319d24d3..ae3ca17689 100644 --- a/i18n/chs/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,7 +6,11 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "JsonSchema.locale": "要使用的 UI 语言。", + "updateLocale": "是否将 VS Code 的界面语言更换为 {0} 并重新启动?", + "yes": "是", + "no": "否", + "neverAgain": "不再显示", + "JsonSchema.locale": "使用的界面语言。", "vscode.extension.contributes.localizations": "向编辑器提供本地化内容", "vscode.extension.contributes.localizations.languageId": "显示字符串翻译的目标语言 ID。", "vscode.extension.contributes.localizations.languageName": "语言的英文名称。", diff --git a/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..c767d56880 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "是否将 VS Code 的界面语言更换为 {0} 并重新启动?", + "yes": "是", + "no": "否", + "neverAgain": "不再显示", + "install language pack": "不久后,VS Code 将仅支持商店扩展形式的界面语言包。请安装“{0}”扩展以继续使用当前的界面语言。", + "install": "安装", + "more information": "更多信息...", + "JsonSchema.locale": "使用的界面语言。", + "vscode.extension.contributes.localizations": "向编辑器提供本地化内容", + "vscode.extension.contributes.localizations.languageId": "显示字符串翻译的目标语言 ID。", + "vscode.extension.contributes.localizations.languageName": "语言的英文名称。", + "vscode.extension.contributes.localizations.languageNameLocalized": "提供语言的名称。", + "vscode.extension.contributes.localizations.translations": "与语言关联的翻译的列表。", + "vscode.extension.contributes.localizations.translations.id": "使用此翻译的 VS Code 或扩展的 ID。VS Code 的 ID 总为 \"vscode\",扩展的 ID 的格式应为 \"publisherId.extensionName\"。", + "vscode.extension.contributes.localizations.translations.id.pattern": "翻译 VS Code 或者扩展,ID 分别应为 \"vscode\" 或格式为 \"publisherId.extensionName\"。", + "vscode.extension.contributes.localizations.translations.path": "包含语言翻译的文件的相对路径。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..3e746df31e --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "配置语言", + "displayLanguage": "定义 VSCode 的显示语言。", + "doc": "请参阅 {0},了解支持的语言列表。", + "restart": "更改此值需要重启 VSCode。", + "fail.createSettings": "无法创建“{0}”({1})。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..04a7e7edc8 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "复制", + "copyMessage": "复制消息" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..f53a9ecd18 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "总计 {0} 个问题" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..f4c0a38ab6 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "问题", + "tooltip.1": "此文件存在 1 个问题", + "tooltip.N": "此文件存在 {0} 个问题", + "markers.showOnFile": "显示关于文件与文件夹的错误与警告。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..a23959a4c1 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "禁用文件排除筛选器。", + "clearFilter": "清除筛选。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..30ef269d07 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "显示 {0} / {1}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..90e2b4ea2c --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "查看", + "problems.view.toggle.label": "切换问题 (错误、警告、信息) 视图", + "problems.view.focus.label": "聚焦于问题 (错误、警告、信息) 视图", + "problems.panel.configuration.title": "问题预览", + "problems.panel.configuration.autoreveal": "控制在打开文件时是否在问题视图中对其进行定位。", + "markers.panel.title.problems": "问题", + "markers.panel.aria.label.problems.tree": "按文件分组的问题", + "markers.panel.no.problems.build": "目前尚未在工作区检测到问题。", + "markers.panel.no.problems.filters": "在给定的筛选条件下,没有找到结果。", + "markers.panel.no.problems.file.exclusions": "由于启用了文件排除筛选器,所有问题均已隐藏。", + "markers.panel.action.useFilesExclude": "使用文件排除设置进行筛选", + "markers.panel.action.donotUseFilesExclude": "不使用文件排除设置", + "markers.panel.action.filter": "筛选器问题", + "markers.panel.filter.ariaLabel": "筛选器问题", + "markers.panel.filter.placeholder": "筛选。例: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "错误", + "markers.panel.filter.warnings": "警告", + "markers.panel.filter.infos": "信息", + "markers.panel.single.error.label": "1 个错误", + "markers.panel.multiple.errors.label": "{0} 个错误", + "markers.panel.single.warning.label": "1 条警告", + "markers.panel.multiple.warnings.label": "{0} 条警告", + "markers.panel.single.info.label": "1 条信息", + "markers.panel.multiple.infos.label": "{0} 条信息", + "markers.panel.single.unknown.label": "1 个未知", + "markers.panel.multiple.unknowns.label": "{0} 个未知", + "markers.panel.at.ln.col.number": "({0},{1})", + "problems.tree.aria.label.resource": "含有 {1} 问题的 {0}", + "problems.tree.aria.label.marker.relatedInformation": "此问题包含对 {0} 个位置的引用。", + "problems.tree.aria.label.error.marker": "{0} 生成的错误: {2} 行 {3} 列,{1}。{4}", + "problems.tree.aria.label.error.marker.nosource": "错误: {1} 行 {2} 列,{0}。{3}", + "problems.tree.aria.label.warning.marker": "{0} 生成的警告: {2} 行 {3} 列,{1}。{4}", + "problems.tree.aria.label.warning.marker.nosource": "警告: {1} 行 {2} 列,{0}。{3}", + "problems.tree.aria.label.info.marker": "{0} 生成的信息: {2} 行 {3} 列,{1}。{4}", + "problems.tree.aria.label.info.marker.nosource": "信息: {1} 行 {2} 列,{0}。{3}", + "problems.tree.aria.label.marker": "{0} 生成的问题: {2} 行 {3} 列,{1}。{4}", + "problems.tree.aria.label.marker.nosource": "问题: {1} 行 {2} 列,{0}。{3}", + "problems.tree.aria.label.relatedinfo.message": "{3} 的 {1} 行 {2} 列,{0}", + "errors.warnings.show.label": "显示错误和警告" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/chs/src/vs/workbench/parts/output/browser/outputActions.i18n.json index 0729aa091c..a05ea37fe5 100644 --- a/i18n/chs/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "切换输出", "clearOutput": "清除输出", "toggleOutputScrollLock": "切换输出 Scroll Lock", - "switchToOutput.label": "切换到输出" + "switchToOutput.label": "切换到输出", + "openInLogViewer": "打开日志文件" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 162412c6c6..31b11ac796 100644 --- a/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "输出", "logViewer": "日志查看器", "viewCategory": "查看", - "clearOutput.label": "清除输出" + "clearOutput.label": "清除输出", + "openActiveLogOutputFile": "查看: 打开活动日志输出文件" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/performance/electron-browser/startupProfiler.i18n.json b/i18n/chs/src/vs/workbench/parts/performance/electron-browser/startupProfiler.i18n.json index c9010274c1..e06856a025 100644 --- a/i18n/chs/src/vs/workbench/parts/performance/electron-browser/startupProfiler.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/performance/electron-browser/startupProfiler.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "prof.message": "已成功创建描述文件。", + "prof.message": "已成功创建分析文件。", "prof.detail": "请创建问题并手动附加以下文件:\n{0}", "prof.restartAndFileIssue": "创建问题并重启", "prof.restart": "重启", diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index af263600dd..532dc7fe13 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,33 +6,34 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "键盘快捷方式", - "SearchKeybindings.AriaLabel": "搜索键绑定", - "SearchKeybindings.Placeholder": "搜索键绑定", + "showDefaultKeybindings": "显示默认按键绑定", + "showUserKeybindings": "显示用户按键绑定", + "SearchKeybindings.AriaLabel": "搜索按键绑定", + "SearchKeybindings.Placeholder": "搜索按键绑定", "sortByPrecedene": "按优先级排序", "header-message": "高级自定义请打开和编辑", "keybindings-file-name": "keybindings.json", - "keybindingsLabel": "键绑定", - "changeLabel": "更改键绑定", - "addLabel": "添加键绑定", + "keybindingsLabel": "按键绑定", + "changeLabel": "更改按键绑定", + "addLabel": "添加按键绑定", "removeLabel": "删除键绑定", - "resetLabel": "重置键绑定", - "showSameKeybindings": "显示相同的键绑定", + "resetLabel": "重置按键绑定", + "showSameKeybindings": "显示相同的按键绑定", "copyLabel": "复制", "copyCommandLabel": "拷贝命令", - "error": "编辑键绑定时发生错误“{0}”。请打开 \"keybindings.json\" 文件并检查错误。", + "error": "编辑按键绑定时发生错误“{0}”。请打开 \"keybindings.json\" 文件并检查错误。", "command": "命令", - "keybinding": "键绑定", + "keybinding": "按键绑定", "source": "来源", "when": "何时", - "editKeybindingLabelWithKey": "更改键绑定{0}", + "editKeybindingLabelWithKey": "更改按键绑定 {0}", "editKeybindingLabel": "更改键绑定", - "addKeybindingLabelWithKey": "添加键绑定", + "addKeybindingLabelWithKey": "添加按键绑定 {0}", "addKeybindingLabel": "添加键绑定", "title": "{0} ({1})", "commandAriaLabel": "命令为 {0}。", - "keybindingAriaLabel": "键绑定为 {0}。", - "noKeybinding": "未分配键绑定。", + "keybindingAriaLabel": "按键绑定为 {0}。", + "noKeybinding": "没有绑定按键。", "sourceAriaLabel": "源为 {0}。", "whenAriaLabel": "时间为 {0}。", "noWhen": "没有时间上下文。" diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.i18n.json index 92a27daabc..762e48370e 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "defineKeybinding.start": "定义键绑定", + "defineKeybinding.start": "定义按键绑定", "defineKeybinding.kbLayoutErrorMessage": "在当前键盘布局下无法生成此组合键。", "defineKeybinding.kbLayoutLocalAndUSMessage": "在你的键盘布局上为 **{0}**(美国标准布局上为 **{1}**)。", "defineKeybinding.kbLayoutLocalMessage": "在你的键盘布局上为 **{0}**。" diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index e5adb55b94..0f0cdb0019 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "打开默认设置原始文档", + "openSettings": "打开设置", "openGlobalSettings": "打开用户设置", "openGlobalKeybindings": "打开键盘快捷方式", "openGlobalKeybindingsFile": "打开键盘快捷方式文件", diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 417be153e4..8d5b8bf3be 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "默认设置", "SearchSettingsWidget.AriaLabel": "搜索设置", "SearchSettingsWidget.Placeholder": "搜索设置", "noSettingsFound": "无结果", @@ -16,6 +15,8 @@ "nlpResult": "自然语言结果", "filterResult": "筛选结果", "defaultSettings": "默认设置", + "defaultUserSettings": "默认用户设置", + "defaultWorkspaceSettings": "默认工作区设置", "defaultFolderSettings": "默认文件夹设置", "defaultEditorReadonly": "在右侧编辑器中编辑以覆盖默认值。", "preferencesAriaLabel": "默认首选项。只读文本编辑器。" diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index cf911d4117..a2b6545cc9 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "显示扩展“{0}”", "editTtile": "编辑", "replaceDefaultValue": "在设置中替换", - "copyDefaultValue": "复制到设置", - "unsupportedPHPExecutablePathSetting": "此设置必须是“用户设置”。若要为工作区配置 PHP,请打开 PHP 文件并单击状态栏中的“PHP 路径”。", - "unsupportedWorkspaceSetting": "此设置必须是“用户设置”。", - "unsupportedWorkbenchSetting": "当前无法应用此设置。将在直接打开此文件夹时应用。", - "unsupportedWorkbenchSettingDevMode": "当前无法应用此设置。将你在注册时定义其作用域为 \"resource\",或是直接打开此文件夹时应用。" + "copyDefaultValue": "复制到设置" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.i18n.json index fc29a2e645..039655eea1 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.i18n.json @@ -7,6 +7,6 @@ "Do not edit this file. It is machine generated." ], "defaultPreferencesEditor": "默认首选项编辑器", - "keybindingsEditor": "键绑定编辑器", + "keybindingsEditor": "按键绑定编辑器", "preferences": "首选项" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json b/i18n/chs/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json index 2bdd666a3c..0caad51cba 100644 --- a/i18n/chs/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json @@ -9,8 +9,8 @@ "gotoLine": "转到行...", "gotoLineLabelEmptyWithLimit": "键入要导航到的介于 1 和 {0} 之间的行号", "gotoLineLabelEmpty": "键入要导航到的行号", - "gotoLineColumnLabel": "转到行 {0} 和字符 {1}", - "gotoLineLabel": "转至行 {0}", + "gotoLineColumnLabel": "转到第 {0} 行,第 {1} 列", + "gotoLineLabel": "转到第 {0} 行", "gotoLineHandlerAriaLabel": "键入要导航到的行号。", "cannotRunGotoLine": "首先打开文本文件以转到行" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 628a2aa033..5957a68271 100644 --- a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "安装其他源代码管理提供程序...", "no open repo": "没有活动的源代码管理提供程序。", "source control": "源代码管理", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "隐藏" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json index c8926f26e3..7d294181ec 100644 --- a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "显示上一个搜索排除模式", "nextSearchTerm": "显示下一个搜索词", "previousSearchTerm": "显示上一个搜索词", - "showSearchViewlet": "显示搜索", "findInFiles": "在文件中查找", "replaceInFiles": "在文件中替换", "RefreshAction.label": "刷新", diff --git a/i18n/chs/src/vs/workbench/parts/search/browser/searchView.i18n.json b/i18n/chs/src/vs/workbench/parts/search/browser/searchView.i18n.json index 1ba557747f..562901d243 100644 --- a/i18n/chs/src/vs/workbench/parts/search/browser/searchView.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/browser/searchView.i18n.json @@ -7,9 +7,9 @@ "Do not edit this file. It is machine generated." ], "moreSearch": "切换搜索详细信息", - "searchScope.includes": "要包含的文件", + "searchScope.includes": "包含的文件", "label.includes": "搜索包含模式", - "searchScope.excludes": "要排除的文件", + "searchScope.excludes": "排除的文件", "label.excludes": "搜索排除模式", "replaceAll.confirmation.title": "全部替换", "replaceAll.confirm.button": "替换(&&R)", diff --git a/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 19bd036911..e7e921aa68 100644 --- a/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "搜索", + "copyMatchLabel": "复制", + "copyPathLabel": "复制路径", + "copyAllLabel": "全部复制", + "clearSearchHistoryLabel": "清除搜索历史记录", + "toggleSearchViewPositionLabel": "切换搜索视图位置", "findInFolder": "在文件夹中查找...", "findInWorkspace": "在工作区中查找...", "showTriggerActions": "转到工作区中的符号...", "name": "搜索", - "search": "搜索", "showSearchViewl": "显示搜索", "view": "查看", "findInFiles": "在文件中查找", @@ -26,5 +31,5 @@ "search.followSymlinks": "控制是否在搜索中跟踪符号链接。", "search.smartCase": "若搜索词全为小写,则不区分大小写进行搜索,否则区分大小写进行搜索", "search.globalFindClipboard": "控制“搜索”视图是否读取或修改 macOS 的共享查找剪贴板", - "search.location": "预览: 控制搜索功能显示在侧边栏还是水平空间更大的面板区域。我们将在下个版本优化面板中搜索的水平布局,之后这将不再是一个预览功能。" + "search.location": "控制搜索功能显示在侧边栏还是水平空间更大的面板区域。我们将在下个版本中优化面板搜索的水平布局,此后,这将不再是一个预览功能。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index c0873e7113..2e2293dbb9 100644 --- a/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "帮助我们改善对 {0} 的支持", "takeShortSurvey": "参与小调查", "remindLater": "稍后提醒", - "neverAgain": "不再显示", - "helpUs": "帮助我们改善对 {0} 的支持" + "neverAgain": "不再显示" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 4cec6fd99f..9cfbe3e855 100644 --- a/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "您愿意参与一次简短的反馈调查吗?", "takeSurvey": "参与调查", "remindLater": "稍后提醒", - "neverAgain": "不再显示", - "surveyQuestion": "您愿意参与一次简短的反馈调查吗?" + "neverAgain": "不再显示" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 9cb8627001..fcedd5ee11 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "问题模式或者所提供或预定义问题模式的名称。如果已指定基准,则可以省略。", "ProblemMatcherSchema.base": "要使用的基问题匹配程序的名称。", "ProblemMatcherSchema.owner": "代码内问题的所有者。如果指定了基准,则可省略。如果省略,并且未指定基准,则默认值为“外部”。", + "ProblemMatcherSchema.source": "描述此诊断信息来源的人类可读字符串。如,\"typescript\" 或 \"super lint\"。", "ProblemMatcherSchema.severity": "捕获问题的默认严重性。如果模式未定义严重性的匹配组,则使用。", "ProblemMatcherSchema.applyTo": "控制文本文档上报告的问题是否仅应用于打开、关闭或所有文档。", "ProblemMatcherSchema.fileLocation": "定义应如何解释问题模式中报告的文件名。", diff --git a/i18n/chs/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index e3fe1a75d9..f14af1cae9 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "实际任务类型", + "TaskDefinition.description": "实际任务类型。请注意,以 \"$\" 开头的类型仅保留内部使用。", "TaskDefinition.properties": "任务类型的其他属性", "TaskTypeConfiguration.noType": "任务类型配置缺少必需的 \"taskType\" 属性", "TaskDefinitionExtPoint": "配置任务种类" diff --git a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 6b9cadadb5..78f08549fc 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "将任务分配为没有组", "JsonSchema.tasks.group": "定义此任务属于的执行组。它支持 \"build\" 以将其添加到生成组,也支持 \"test\" 以将其添加到测试组。", "JsonSchema.tasks.type": "定义任务是被作为进程运行还是在 shell 中作为命令运行。", + "JsonSchema.command.quotedString.value": "实际命令值", + "JsonSchema.tasks.quoting.escape": "使用 Shell 的转义字符来转义文本 (如,PowerShell 下的 ` 和 bash 下的 \\ )", + "JsonSchema.tasks.quoting.strong": "使用 Shell 的强引用字符来引用参数 (如,在 PowerShell 和 bash 下的 \" )。", + "JsonSchema.tasks.quoting.weak": "使用 Shell 的弱引用字符来引用参数 (如,在 PowerShell 和 bash 下的 ' )。", + "JsonSchema.command.quotesString.quote": "如何引用命令值。", + "JsonSchema.command": "要执行的命令。可以是外部程序或 shell 命令。", + "JsonSchema.args.quotedString.value": "实际参数值", + "JsonSchema.args.quotesString.quote": "如何引用参数值。", + "JsonSchema.tasks.args": "在调用此任务时传递给命令的参数。", "JsonSchema.tasks.label": "任务的用户界面标签", "JsonSchema.version": "配置的版本号。", "JsonSchema.tasks.identifier": "用于在 launch.json 或 dependsOn 子句中引用任务的用户定义标识符。", diff --git a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 11fe758513..59ac542b1f 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -8,9 +8,12 @@ ], "tasksCategory": "任务", "ConfigureTaskRunnerAction.label": "配置任务", + "totalErrors": "{0} 个错误", + "totalWarnings": "{0} 条警告", + "totalInfos": "{0} 条信息", "problems": "问题", "building": "正在生成...", - "manyMarkers": "99+", + "manyProblems": "1万+", "runningTasks": "显示运行中的任务", "tasks": "任务", "TaskSystem.noHotSwap": "在有活动任务运行时更换任务执行引擎需要重新加载窗口", @@ -28,8 +31,10 @@ "selectProblemMatcher": "选择针对何种错误和警告扫描任务输出", "customizeParseErrors": "当前任务配置存在错误。请先更正错误,再自定义任务。", "moreThanOneBuildTask": "当前 tasks.json 中定义了多个生成任务。正在执行第一个。\n", - "TaskSystem.activeSame.background": "任务 \"{0}\" 已激活并处于后台模式。若要终止任务,请选择“任务”菜单中的“终止任务...”。", - "TaskSystem.activeSame.noBackground": "任务 \"{0}\" 已处于活动状态。若要终止任务,请选择“任务”菜单中的“终止任务...”。", + "TaskSystem.activeSame.background": "任务“{0}”已激活,并且处于后台模式。", + "TaskSystem.activeSame.noBackground": "任务“{0}”已处于活动状态。", + "terminateTask": "终止任务", + "restartTask": "重启任务", "TaskSystem.active": "当前已有任务正在运行。请先终止它,然后再执行另一项任务。", "TaskSystem.restartFailed": "未能终止并重启任务 {0}", "TaskService.noConfiguration": "错误: {0} 任务检测没有提供拥有下列配置的任务:\n{1}\n将忽略此任务。\n", diff --git a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 07c5c42e3c..785aaacc18 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "任务 - {0}", "closeTerminal": "按任意键关闭终端。", "reuseTerminal": "终端将被任务重用,按任意键关闭。", - "TerminalTaskSystem": "无法对 UNC 驱动器执行 shell 命令。", + "TerminalTaskSystem": "无法使用 cmd.exe 在 UNC 驱动器上执行 Shell 命令。", "unkownProblemMatcher": "无法解析问题匹配程序 {0}。此匹配程序将被忽略" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/chs/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 7732bca1af..37cd61a268 100644 --- a/i18n/chs/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "警告: options.cwd 必须属于字符串类型。正在忽略值 {0}\n", + "ConfigurationParser.inValidArg": "错误: 命令参数必须是字符串或有效引用的字符串。提供的值为: {0}", "ConfigurationParser.noargs": "错误: 命令参数必须是字符串数组。提供的值为:\n{0}", "ConfigurationParser.noShell": "警告: 仅当在终端中执行任务时支持 shell 配置。", "ConfigurationParser.noName": "错误: 声明范围内的问题匹配程序必须具有名称:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "错误: 任务配置“{0}”缺失必要属性“{1}”。将忽略该任务。", "ConfigurationParser.notCustom": "错误: 任务未声明为自定义任务。将忽略配置。\n{0}\n", "ConfigurationParser.noTaskName": "错误: 任务必须提供 label 属性。将忽略该任务。\n{0}\n", - "taskConfiguration.shellArgs": "警告: 任务“{0}”是 shell 命令,而且其中一个参数可能含有未转义的空格。若要确保命令行引用正确,请将参数合并到该命令。", "taskConfiguration.noCommandOrDependsOn": "错误:任务“{0}”既不指定命令,也不指定 dependsOn 属性。将忽略该任务。其定义为:\n{1}", "taskConfiguration.noCommand": "错误: 任务“{0}”未定义命令。将忽略该任务。其定义为:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "任务版本 2.0.0 不支持全局操作系统特定任务。请将他们转换为含有操作系统特定命令的任务。受影响的任务有:\n{0}" diff --git a/i18n/chs/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..1c55c29463 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "终端的背景颜色,允许终端的颜色与面板不同。", + "terminal.foreground": "终端的前景颜色。", + "terminalCursor.foreground": "终端光标的前景色。", + "terminalCursor.background": "终端光标的背景色。允许自定义被 block 光标遮住的字符的颜色。", + "terminal.selectionBackground": "终端选中内容的背景颜色。", + "terminal.border": "分隔终端中拆分窗格的边框的颜色。默认值为 panel.border 的颜色", + "terminal.ansiColor": "终端中的 ANSI 颜色“{0}”。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index ee50460ad8..f7d3697384 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "选择当前工作目录新建终端", "workbench.action.terminal.newInActiveWorkspace": "新建集成终端 (活动工作区)", "workbench.action.terminal.split": "拆分终端", + "workbench.action.terminal.splitInActiveWorkspace": "拆分终端 (活动工作区)", "workbench.action.terminal.focusPreviousPane": "聚焦于上一个窗格", "workbench.action.terminal.focusNextPane": "聚焦于下一个窗格", "workbench.action.terminal.resizePaneLeft": "向左调整窗格大小", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "向上滚动(页)", "workbench.action.terminal.scrollToTop": "滚动到顶部", "workbench.action.terminal.clear": "清除", + "workbench.action.terminal.clearSelection": "清除选定内容", "workbench.action.terminal.allowWorkspaceShell": "允许配置工作区 Shell", "workbench.action.terminal.disallowWorkspaceShell": "禁止配置工作区 Shell", "workbench.action.terminal.rename": "重命名", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "隐藏查找小组件", "nextTerminalFindTerm": "显示下一个搜索结果", "previousTerminalFindTerm": "显示上一个搜索结果", - "quickOpenTerm": "切换活动终端" + "quickOpenTerm": "切换活动终端", + "workbench.action.terminal.scrollToPreviousCommand": "滚动到上一条命令", + "workbench.action.terminal.scrollToNextCommand": "滚动到下一条命令", + "workbench.action.terminal.selectToPreviousCommand": "选择上一条命令所有内容", + "workbench.action.terminal.selectToNextCommand": "选择下一条命令所有内容" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index e7ee311483..56f020fd3e 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "没有在终端中选择要复制的内容", "terminal.integrated.exitedWithCode": "通过退出代码 {0} 终止的终端进程", "terminal.integrated.waitOnExit": "按任意键以关闭终端", - "terminal.integrated.launchFailed": "终端进程命令“{0} {1}”无法启动 (退出代码: {2})" + "terminal.integrated.launchFailed": "终端进程命令“{0} {1}”无法启动 (退出代码: {2})", + "terminal.integrated.launchFailedExtHost": "无法启动终端进程 (退出代码: {0})" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 92099dc542..8d23d442d1 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "复制", + "split": "拆分", "paste": "粘贴", "selectAll": "全选", - "clear": "清除", - "split": "拆分" + "clear": "清除" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index a7fe73a1eb..d0ba16ab76 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "terminal.integrated.chooseWindowsShellInfo": "可通过选择“自定义”按钮来更改默认的终端 shell。", + "terminal.integrated.chooseWindowsShellInfo": "你可以按下“自定义”按钮并更换默认终端 Shell。", "customize": "自定义", "never again": "不再显示", "terminal.integrated.chooseWindowsShell": "选择首选的终端 shell,你可稍后在设置中进行更改", diff --git a/i18n/chs/src/vs/workbench/parts/themes/electron-browser/themes.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/themes/electron-browser/themes.contribution.i18n.json index dec17ae28a..f7e7b5144f 100644 --- a/i18n/chs/src/vs/workbench/parts/themes/electron-browser/themes.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/themes/electron-browser/themes.contribution.i18n.json @@ -11,7 +11,7 @@ "themes.category.dark": "深色主题", "themes.category.hc": "高对比度主题", "installColorThemes": "安装其他颜色主题...", - "themes.selectTheme": "选择颜色主题(按上下箭头键预览)", + "themes.selectTheme": "选择颜色主题 (按上下箭头键预览)", "selectIconTheme.label": "文件图标主题", "noIconThemeLabel": "无", "noIconThemeDesc": "禁用文件图标", diff --git a/i18n/chs/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 7085e9750e..a2e6a7e208 100644 --- a/i18n/chs/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "此工作区包含仅可在“用户设置”中配置的设置 ({0})。单击[这里]({1})了解更多信息。", "openWorkspaceSettings": "打开工作区设置", - "dontShowAgain": "不再显示", - "unsupportedWorkspaceSettings": "此工作区包含仅可在“用户设置”中配置的设置 ({0})。单击[这里]({1})了解更多信息。" + "dontShowAgain": "不再显示" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..7f37202986 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "发行说明: {0}", + "unassigned": "未分配" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 75d7ce4756..0020728737 100644 --- a/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "稍后", - "unassigned": "未分配", "releaseNotes": "发行说明", "showReleaseNotes": "显示发行说明", "read the release notes": "欢迎使用 {0} v{1}! 是否要阅读发布说明?", @@ -17,13 +15,14 @@ "updateIsReady": "有新的 {0} 的更新可用。", "noUpdatesAvailable": "当前没有可用的更新。", "ok": "确定", - "download now": "立即下载", "thereIsUpdateAvailable": "存在可用更新。", + "download now": "立即下载", + "later": "稍后", + "updateAvailable": "现有更新可用: {0} {1}", "installUpdate": "安装更新", - "updateAvailable": "存在可用更新: {0} {1}", "updateInstalling": "{0} {1} 正在后台安装,我们会在完成后通知您。", + "updateAvailableAfterRestart": "重新启动 {0} 即可应用最新更新。", "updateNow": "立即更新", - "updateAvailableAfterRestart": "{0} 将在重启后更新。", "commandPalette": "命令面板...", "settings": "设置", "keyboardShortcuts": "键盘快捷方式", diff --git a/i18n/chs/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..7e8fa2b4d6 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "打开 URL", + "developer": "开发者" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..2de51221fc --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "webview 编辑器", + "developer": "开发者" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..bad27cc286 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "打开 Webview 开发工具", + "refreshWebviewLabel": "重新加载 Webview" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/chs/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..4230b0cfc3 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "帮助改善 VS Code,允许 Microsoft 收集使用数据。请阅读我们的[隐私声明]({0})并了解如何[选择退出]({1})。", + "telemetryOptOut.optInNotice": "帮助改善 VS Code,允许 Microsoft 收集使用数据。请阅读我们的[隐私声明]({0})并了解如何[选择加入]({1})。", + "telemetryOptOut.readMore": "了解详细信息" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/chs/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index e9b126d812..081c46a508 100644 --- a/i18n/chs/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "管理扩展", "welcomeOverlay.problems": "查看错误和警告", "welcomeOverlay.commandPalette": "查找并运行所有命令", + "welcomeOverlay.notifications": "显示通知", "welcomeOverlay": "用户界面概览", "hideWelcomeOverlay": "隐藏界面概览", "help": "帮助" diff --git a/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 346c459f72..bd51a5623d 100644 --- a/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "工具和语言", "welcomePage.installExtensionPacksDescription": "安装对 {0} 和 {1} 的支持", "welcomePage.moreExtensions": "更多", - "welcomePage.installKeymapDescription": "安装键盘快捷方式", - "welcomePage.installKeymapExtension": "安装 {0} 和 {1} 的键盘快捷方式", + "welcomePage.installKeymapDescription": "设置和按键绑定", + "welcomePage.installKeymapExtension": "安装 {0} 和 {1} 的设置和快捷键", "welcomePage.others": "其他", "welcomePage.colorTheme": "颜色主题", "welcomePage.colorThemeDescription": "使编辑器和代码呈现你喜欢的外观", diff --git a/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.i18n.json b/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.i18n.json index d4d1650b15..c7a98ee382 100644 --- a/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.i18n.json @@ -28,9 +28,9 @@ "welcome.title": "欢迎使用", "welcomePage.openFolderWithPath": "打开路径为 {1} 的文件夹 {0}", "welcomePage.extensionListSeparator": "、", - "welcomePage.installKeymap": "安装 {0} 键映射", + "welcomePage.installKeymap": "安装 {0} 按键映射", "welcomePage.installExtensionPack": "安装对 {0} 的额外支持", - "welcomePage.installedKeymap": "已安装 {0} 键映射", + "welcomePage.installedKeymap": "已安装 {0} 按键映射", "welcomePage.installedExtensionPack": "已安装 {0} 支持", "ok": "确定", "details": "详细信息", diff --git a/i18n/chs/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json index cc4340c551..abcf75f374 100644 --- a/i18n/chs/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/chs/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "requirearray": "菜单项必须为一个数组", - "requirestring": "属性“{0}”是必要属性,其类型必须是 \"string\"", + "requirestring": "“{0}”是必要属性,其类型必须是 \"string\"", "optstring": "属性“{0}”可以省略,否则其类型必须是 \"string\"", "vscode.extension.contributes.menuItem.command": "要执行的命令的标识符。该命令必须在 \"commands\" 部分中声明", "vscode.extension.contributes.menuItem.alt": "要执行的替代命令的标识符。该命令必须在 ”commands\" 部分中声明", @@ -32,9 +32,9 @@ "requireStringOrObject": "属性“{0}”是必要属性,其类型必须是 \"string\" 或 \"object\"", "requirestrings": "属性“{0}”和“{1}”是必要属性,其类型必须是 \"string\"", "vscode.extension.contributes.commandType.command": "要执行的命令的标识符", - "vscode.extension.contributes.commandType.title": "在 UI 中依据其表示命令的标题", - "vscode.extension.contributes.commandType.category": "(可选)类别字符串按命令在 UI 中分组", - "vscode.extension.contributes.commandType.icon": "(可选)在 UI 中用来表示命令的图标。文件路径或者主题配置", + "vscode.extension.contributes.commandType.title": "在界面中显示的命令名称", + "vscode.extension.contributes.commandType.category": "(可选) 类别字符串,命令在界面中根据此项分组", + "vscode.extension.contributes.commandType.icon": "(可选) 在界面中显示的命令图标。可为文件路径或主题配置", "vscode.extension.contributes.commandType.icon.light": "使用浅色主题时的图标路径", "vscode.extension.contributes.commandType.icon.dark": "使用深色主题时的图标路径", "vscode.extension.contributes.commands": "对命令面板提供命令。", diff --git a/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index be326da2cd..2a9a723944 100644 --- a/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/chs/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -6,11 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "vscode.extension.contributes.configuration.title": "设置摘要。此标签将在设置文件中用作分隔注释。", + "vscode.extension.contributes.configuration.title": "设置项的介绍。这段文本将在设置文件中作为另外的注释。", "vscode.extension.contributes.configuration.properties": "配置属性的描述。", + "scope.application.description": "特定于应用的配置,仅可在“用户”设置中配置。", "scope.window.description": "特定于窗口的配置,可在“用户”或“工作区”设置中配置。", "scope.resource.description": "特定于资源的配置,可在“用户”、“工作区”或“文件夹”设置中配置。", - "scope.description": "配置适用的范围。可用范围有“窗口”和“资源”。", + "scope.description": "配置适用的范围。可用范围有 \"window\" (窗口) 和 \"resource\" (资源)。", "vscode.extension.contributes.defaultConfiguration": "按语言提供默认编辑器配置设置。", "vscode.extension.contributes.configuration": "用于配置字符串。", "invalid.title": "configuration.title 必须是字符串", diff --git a/i18n/chs/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/chs/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 1b2830aece..4f6e8fea49 100644 --- a/i18n/chs/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "打开设置", "saveAndRetry": "保存并重试", "errorUnknownKey": "没有注册配置 {1},因此无法写入 {0}。", + "errorInvalidWorkspaceConfigurationApplication": "无法将 {0} 写入“工作区设置”。此设置只能写于“用户设置”。", "errorInvalidFolderConfiguration": "{0} 不支持文件夹资源域,因此无法写入\"文件夹设置\"。", "errorInvalidUserTarget": "{0} 不支持全局域,因此无法写入\"用户设置\"。", "errorInvalidWorkspaceTarget": "{0} 不在多文件夹工作区环境下支持工作区作用域,因此无法写入“工作区设置”。", diff --git a/i18n/chs/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/chs/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..9654262900 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "此设置仅可应用于“用户设置”", + "unsupportedWindowSetting": "当前无法应用此设置。将在直接打开此文件夹时应用。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/chs/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..a6ae2efb80 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "canNotResolveWorkspaceFolderMultiRoot": "无法在多文件夹工作区中解析 \"${workspaceFolder}\"。使用 \":\" 和工作区文件夹名称来限定此变量的作用域。", + "canNotResolveWorkspaceFolder": "无法解析 \"${workspaceFolder}\"。请打开一个文件夹。", + "canNotResolveFolderBasenameMultiRoot": "无法在多文件夹工作区中解析 \"${workspaceFolderBasename}\"。使用 \":\" 和工作区文件夹名称来限定此变量的作用域。", + "canNotResolveFolderBasename": "无法解析 \"${workspaceFolderBasename}\"。请打开一个文件夹。", + "canNotResolveLineNumber": "无法解析 \"${lineNumber}\"。请打开一个编辑器。", + "canNotResolveSelectedText": "无法解析 \"${selectedText}\"。请打开一个编辑器。", + "canNotResolveFile": "无法解析 \"${file}\"。请打开一个编辑器。", + "canNotResolveRelativeFile": "无法解析 \"${relativeFile}\"。请打开一个编辑器。", + "canNotResolveFileDirname": "无法解析 \"${fileDirname}\"。请打开一个编辑器。", + "canNotResolveFileExtname": "无法解析 \"${fileExtname}\"。请打开一个编辑器。", + "canNotResolveFileBasename": "无法解析 \"${fileBasename}\"。请打开一个编辑器。", + "canNotResolveFileBasenameNoExtension": "无法解析 \"${fileBasenameNoExtension}\"。请打开一个编辑器。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/chs/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..9742dac3db --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "未给出环境变量名称,因此无法解析“{0}”。", + "configNotFound": "未能找到设置“{1}”,因此无法解析“{0}”。", + "configNoString": "“{1}”为结构类型值,因此无法解析“{0}”。", + "missingConfigName": "未给出设置名称,因此无法解析“{0}”。", + "noValueForCommand": "命令不含值,因此无法解析“{0}”。", + "canNotFindFolder": "找不到文件夹“{1}”,因此无法解析“{0}”。", + "canNotResolveWorkspaceFolderMultiRoot": "无法在多文件夹工作区中解析“{0}”。使用 \":\" 和工作区文件夹名称来限定此变量的作用域。", + "canNotResolveWorkspaceFolder": "无法解析“{0}”。请打开一个文件夹。", + "canNotResolveFile": "无法解析“{0}”。请打开一个编辑器。", + "canNotResolveLineNumber": "无法解析“{0}”。请确保已在活动编辑器中选择一行内容。", + "canNotResolveSelectedText": "无法解析“{0}”。请确保已在活动编辑器中选择一些文字。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/chs/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..e3294fd332 --- /dev/null +++ b/i18n/chs/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "是(&&Y)", + "cancelButton": "取消" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/chs/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 1a641704fc..274862511e 100644 --- a/i18n/chs/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/chs/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "引擎兼容性。", "vscode.extension.engines.vscode": "对于 VS Code 扩展,指定与其兼容的 VS Code 版本。不能为 *。 例如: ^0.10.5 表示最低兼容 VS Code 版本 0.10.5。", "vscode.extension.publisher": "VS Code 扩展的发布者。", "vscode.extension.displayName": "VS Code 库中使用的扩展的显示名称。", "vscode.extension.categories": "VS Code 库用于对扩展进行分类的类别。", + "vscode.extension.category.languages.deprecated": "请改用 \"Programming Languages\"", "vscode.extension.galleryBanner": "VS Code 商城使用的横幅。", "vscode.extension.galleryBanner.color": "VS Code 商城页标题上的横幅颜色。", "vscode.extension.galleryBanner.theme": "横幅文字的颜色主题。", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "在将要启动具有特定类型的调试会话 (且需要调用相应的 resolveDebugConfiguration 方法) 时发出的激活事件。", "vscode.extension.activationEvents.workspaceContains": "在打开至少包含一个匹配指定 glob 模式的文件的文件夹时发出的激活事件。", "vscode.extension.activationEvents.onView": "在指定视图被展开时发出的激活事件。", + "vscode.extension.activationEvents.onUri": "在打开系统范围内并指向此扩展的 URI 时发出的激活事件。", "vscode.extension.activationEvents.star": "在 VS Code 启动时发出的激活事件。为确保良好的最终用户体验,请仅在其他激活事件组合不适用于你的情况时,才在扩展中使用此事件。", "vscode.extension.badges": "显示在商店扩展页面侧边栏的徽章的数组", "vscode.extension.badges.url": "徽章图像 URL。", "vscode.extension.badges.href": "徽章链接。", "vscode.extension.badges.description": "徽章说明。", + "vscode.extension.markdown": "控制商店中使用的 Markdown 渲染引擎。可为 \"github\" (默认) 或 \"standard\" (标准)。", + "vscode.extension.qna": "控制市场中的“问与答”(Q&A)链接。设置为 \"marketplace\" 可启用市场的默认“问与答”页面。设置为其他字符串可指向自定义的“问与答”页面。设置为 \"false\" 可完全禁用“问与答”。", "vscode.extension.extensionDependencies": "其他扩展的依赖关系。扩展的标识符始终是 ${publisher}.${name}。例如: vscode.csharp。", "vscode.extension.scripts.prepublish": "包作为 VS Code 扩展发布前执行的脚本。", "vscode.extension.scripts.uninstall": "VS Code 扩展的卸载钩子。在扩展从 VS Code 卸载且 VS Code 重启 (关闭后开启) 后执行的脚本。仅支持 Node 脚本。", diff --git a/i18n/chs/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/chs/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index e7b36262a5..18a97b119d 100644 --- a/i18n/chs/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "已禁用所有扩展。", "extensionHostProcess.crash": "扩展宿主意外终止。", "extensionHostProcess.unresponsiveCrash": "扩展宿主因没有响应而被终止。", - "devTools": "开发人员工具", + "devTools": "打开开发人员工具", "restart": "重启扩展宿主", "overwritingExtension": "使用扩展程序 {1} 覆盖扩展程序 {0}。", "extensionUnderDevelopment": "正在 {0} 处加载开发扩展程序", diff --git a/i18n/chs/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/chs/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 836c755707..c026a10577 100644 --- a/i18n/chs/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -6,11 +6,24 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "缺少 Microsoft .NET Framework 4.5。请访问链接进行安装。", "installNet": "下载 .NET Framework 4.5", "neverShowAgain": "不再显示", - "netVersionError": "需要 Microsoft .NET Framework 4.5。请访问链接安装它。", + "enospcError": "{0} 无法监视这个大型工作区的文件变化。请访问说明链接解决此问题。", "learnMore": "说明", - "enospcError": "{0} 的文件句柄已用完。 请按照说明解决此问题。", + "fileInvalidPath": "无效的文件资源({0})", + "fileIsDirectoryError": "文件是目录", + "fileNotModifiedError": "自以下时间未修改的文件:", + "fileTooLargeForHeapError": "若要打开此大小的文件,需要重新启动 VS Code,并允许其使用更多内存", + "fileTooLargeError": "文件太大,无法打开", + "fileNotFoundError": "找不到文件({0})", + "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开", + "filePermission": "写入文件时权限被拒绝 ({0})", + "fileExists": "已存在要创建的文件 ({0})", + "fileModifiedError": "自以下时间已修改的文件:", + "fileReadOnlyError": "文件为只读文件", + "fileMoveConflict": "无法移动/复制。文件已存在于目标位置。", + "unableToMoveCopyError": "无法移动/复制。文件将替换其所在的文件夹。", "binFailed": "未能将“{0}”移动到回收站", "trashFailed": "未能将“{0}”移动到废纸篓" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index e7c2080932..e9201b69a5 100644 --- a/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "找不到文件({0})", "fileIsDirectoryError": "文件是目录", "fileNotModifiedError": "自以下时间未修改的文件:", - "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开" + "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开", + "err.create": "未能创建文件 {0}", + "fileMoveConflict": "无法移动/复制。文件已存在于目标位置。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json index bb1af9584c..2fd3855eb9 100644 --- a/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,7 @@ "fileInvalidPath": "无效的文件资源({0})", "fileIsDirectoryError": "文件是目录", "fileNotModifiedError": "自以下时间未修改的文件:", - "fileTooLargeForHeapError": "文件大小超过窗口内存限制,请尝试运行 code --max-memory=[新的大小]", + "fileTooLargeForHeapError": "文件大小超过默认内存限制。您可以使用更高的限制重新启动,当前限制为 {0}MB", "fileTooLargeError": "文件太大,无法打开", "fileNotFoundError": "找不到文件({0})", "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开", diff --git a/i18n/chs/src/vs/workbench/services/keybinding/common/keybindingEditing.i18n.json b/i18n/chs/src/vs/workbench/services/keybinding/common/keybindingEditing.i18n.json index 187c385989..33ae385a58 100644 --- a/i18n/chs/src/vs/workbench/services/keybinding/common/keybindingEditing.i18n.json +++ b/i18n/chs/src/vs/workbench/services/keybinding/common/keybindingEditing.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "errorKeybindingsFileDirty": "键绑定配置文件已变更,无法写入。请先保存此文件,然后重试。", - "parseErrors": "无法写入键绑定配置文件。请打开文件并更正错误或警告,然后重试。", - "errorInvalidConfiguration": "无法写入键绑定配置文件。文件内含有不是数组类型的对象。请打开文件进行清理,然后重试。", - "emptyKeybindingsHeader": "将键绑定放入此文件中以覆盖默认值" + "errorKeybindingsFileDirty": "按键绑定配置文件已变更,现在无法写入。请先保存此文件,然后重试。", + "parseErrors": "无法写入按键绑定配置文件。请打开文件并更正错误或警告,然后重试。", + "errorInvalidConfiguration": "无法写入按键绑定配置文件。文件内含有非数组类型对象。请打开文件进行清理,然后重试。", + "emptyKeybindingsHeader": "将按键绑定配置放入此文件中即可覆盖默认值" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index cd941f1db0..55945b287d 100644 --- a/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -7,18 +7,18 @@ "Do not edit this file. It is machine generated." ], "nonempty": "应为非空值。", - "requirestring": "属性“{0}”是必需的,其类型必须是“字符串”", - "optstring": "属性“{0}”可以省略,或者其类型必须是“字符串”", - "vscode.extension.contributes.keybindings.command": "要在触发键绑定时运行的命令的标识符。", + "requirestring": "“{0}”是必要属性,其类型必须是 \"string\" ", + "optstring": "属性“{0}”可以省略,否则其类型必须是 \"string\"", + "vscode.extension.contributes.keybindings.command": "触发按键绑定时运行的命令的标识符。", "vscode.extension.contributes.keybindings.key": "按键或按键序列。用加号分隔按键,用空格分隔序列。例如,Ctrl+O 和 Ctrl+L L(连续按键)。", "vscode.extension.contributes.keybindings.mac": "Mac 特定的键或键序列。", "vscode.extension.contributes.keybindings.linux": "Linux 特定的键或键序列。", "vscode.extension.contributes.keybindings.win": "Windows 特定的键或键序列。", "vscode.extension.contributes.keybindings.when": "键处于活动状态时的条件。", - "vscode.extension.contributes.keybindings": "用于键绑定。", + "vscode.extension.contributes.keybindings": "提供按键绑定。", "invalid.keybindings": "无效的“contributes.{0}”: {1}", "unboundCommands": "以下是其他可用命令:", - "keybindings.json.title": "键绑定配置", + "keybindings.json.title": "按键绑定配置", "keybindings.json.key": "键或键序列(用空格分隔)", "keybindings.json.command": "要执行的命令的名称", "keybindings.json.when": "键处于活动状态时的条件。", diff --git a/i18n/chs/src/vs/workbench/services/mode/common/workbenchModeService.i18n.json b/i18n/chs/src/vs/workbench/services/mode/common/workbenchModeService.i18n.json index 705b419bfb..c2e6e5941d 100644 --- a/i18n/chs/src/vs/workbench/services/mode/common/workbenchModeService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/mode/common/workbenchModeService.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "vscode.extension.contributes.languages": "有助于语言声明。", + "vscode.extension.contributes.languages": "提供语言声明。", "vscode.extension.contributes.languages.id": "语言 ID。", "vscode.extension.contributes.languages.aliases": "语言的别名。", "vscode.extension.contributes.languages.extensions": "与语言关联的文件扩展名。", diff --git a/i18n/chs/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/chs/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..2928c9a671 100644 --- a/i18n/chs/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/chs/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "取消" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 6421653745..3b13ecd9cd 100644 --- a/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -7,9 +7,10 @@ "Do not edit this file. It is machine generated." ], "vscode.extension.contributes.grammars": "贡献 textmate tokenizer。", - "vscode.extension.contributes.grammars.language": "此语法为其贡献了内容的语言标识符。", + "vscode.extension.contributes.grammars.language": "此语法对应语言的标识符。", "vscode.extension.contributes.grammars.scopeName": "tmLanguage 文件所用的 textmate 范围名称。", "vscode.extension.contributes.grammars.path": "tmLanguage 文件的路径。该路径是相对于扩展文件夹,通常以 \"./syntaxes/\" 开头。", "vscode.extension.contributes.grammars.embeddedLanguages": "如果此语法包含嵌入式语言,则为作用域名称到语言 ID 的映射。", + "vscode.extension.contributes.grammars.tokenTypes": "从作用域名到标记类型的映射。", "vscode.extension.contributes.grammars.injectTo": "此语法注入到的语言范围名称列表。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 5e0f845630..7002c29be7 100644 --- a/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/chs/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -6,11 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "invalid.language": "“contributes.{0}.language”中存在未知的语言。提供的值: {1}", - "invalid.scopeName": "“contributes.{0}.scopeName”中应为字符串。提供的值: {1}", + "invalid.language": "\"contributes.{0}.language\" 中包含未知语言。提供的值: {1}", + "invalid.scopeName": "\"contributes.{0}.scopeName\" 应为字符串。提供的值: {1}", "invalid.path.0": "“contributes.{0}.path”中应为字符串。提供的值: {1}", "invalid.injectTo": "\"contributes.{0}.injectTo\" 中的值无效。必须为语言范围名称数组。提供的值: {1}", "invalid.embeddedLanguages": "\"contributes.{0}.embeddedLanguages\" 中的值无效。必须为从作用域名称到语言的对象映射。提供的值: {1}", + "invalid.tokenTypes": "\"contributes.{0}.tokenTypes\" 的值无效。必须为从作用域名称到标记类型的对象映射。当前值: {1}", "invalid.path.1": "“contributes.{0}.path”({1})应包含在扩展的文件夹({2})内。这可能会使扩展不可移植。", "no-tm-grammar": "没有注册这种语言的 TM 语法。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json index dcded00f11..1f824d8346 100644 --- a/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/colorThemeStore.i18n.json @@ -8,7 +8,7 @@ ], "vscode.extension.contributes.themes": "请提供 TextMate 颜色主题。", "vscode.extension.contributes.themes.id": "用户设置中使用的图标主题的 ID。", - "vscode.extension.contributes.themes.label": "显示在 UI 中的颜色主题标签。", + "vscode.extension.contributes.themes.label": "颜色主题在界面中的显示名称。", "vscode.extension.contributes.themes.uiTheme": "用于定义编辑器周围颜色的基本主题: \"vs\" 是浅色主题,\"vs-dark\" 是深色主题。\"hc-black\" 是深色高对比度主题。", "vscode.extension.contributes.themes.path": "tmTheme 文件的路径。该路径相对于扩展文件夹,通常为 \"./themes/themeFile.tmTheme\"。", "reqarray": "扩展点“{0}”必须是一个数组。", diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json index 964d661413..61d59530a2 100644 --- a/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.i18n.json @@ -8,7 +8,7 @@ ], "vscode.extension.contributes.iconThemes": "提供文件图标主题。", "vscode.extension.contributes.iconThemes.id": "用户设置中使用的图标主题的 ID。", - "vscode.extension.contributes.iconThemes.label": "UI 中显示的图标主题的标签。", + "vscode.extension.contributes.iconThemes.label": "在界面中显示的图标主题名称 ", "vscode.extension.contributes.iconThemes.path": "图标主题定义文件的路径。该路径相对于扩展文件夹,通常是 \"./icons/awesome-icon-theme.json\"。", "reqarray": "扩展点“{0}”必须是一个数组。", "reqpath": "“contributes.{0}.path”中应为字符串。提供的值: {1}", diff --git a/i18n/cht/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/cht/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..8d5e76dfac --- /dev/null +++ b/i18n/cht/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS 語言伺服器", + "folding.start": "摺疊區域開始", + "folding.end": "摺疊區域結束" +} \ No newline at end of file diff --git a/i18n/cht/extensions/css-language-features/package.i18n.json b/i18n/cht/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..d40f448f34 --- /dev/null +++ b/i18n/cht/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS 語言功能", + "description": "為 CSS, LESS 和 SCSS 檔案提供豐富的語言支援 ", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "參數數目無效", + "css.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", + "css.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", + "css.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", + "css.lint.emptyRules.desc": "請勿使用空白規則集", + "css.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", + "css.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", + "css.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", + "css.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", + "css.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", + "css.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", + "css.lint.importStatement.desc": "匯入陳述式不會平行載入", + "css.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", + "css.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", + "css.lint.unknownProperties.desc": "未知的屬性。", + "css.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", + "css.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", + "css.lint.zeroUnits.desc": "零不需要任何單位", + "css.trace.server.desc": "追蹤 VS Code 與 CSS 語言伺服器之間的通訊。", + "css.validate.title": "控制 CSS 驗證與問題嚴重性。", + "css.validate.desc": "啟用或停用所有驗證", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "參數數目無效", + "less.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", + "less.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", + "less.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", + "less.lint.emptyRules.desc": "請勿使用空白規則集", + "less.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", + "less.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", + "less.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", + "less.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", + "less.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", + "less.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", + "less.lint.importStatement.desc": "匯入陳述式不會平行載入", + "less.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", + "less.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", + "less.lint.unknownProperties.desc": "未知的屬性。", + "less.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", + "less.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", + "less.lint.zeroUnits.desc": "零不需要任何單位", + "less.validate.title": "控制 LESS 驗證與問題嚴重性。", + "less.validate.desc": "啟用或停用所有驗證", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "參數數目無效", + "scss.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", + "scss.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", + "scss.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", + "scss.lint.emptyRules.desc": "請勿使用空白規則集", + "scss.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", + "scss.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", + "scss.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", + "scss.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", + "scss.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", + "scss.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", + "scss.lint.importStatement.desc": "匯入陳述式不會平行載入", + "scss.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", + "scss.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", + "scss.lint.unknownProperties.desc": "未知的屬性。", + "scss.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", + "scss.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", + "scss.lint.zeroUnits.desc": "零不需要任何單位", + "scss.validate.title": "控制 SCSS 驗證與問題嚴重性。", + "scss.validate.desc": "啟用或停用所有驗證", + "less.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", + "scss.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", + "css.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", + "css.colorDecorators.enable.deprecationMessage": "設定 `css.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。", + "scss.colorDecorators.enable.deprecationMessage": "設定 `scss.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。", + "less.colorDecorators.enable.deprecationMessage": "設定 `less.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/css/package.i18n.json b/i18n/cht/extensions/css/package.i18n.json index 3839e21895..ff1eb6e2f4 100644 --- a/i18n/cht/extensions/css/package.i18n.json +++ b/i18n/cht/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS 語言功能", - "description": "為 CSS, LESS 和 SCSS 檔案提供豐富的語言支援 ", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "參數數目無效", - "css.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", - "css.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", - "css.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", - "css.lint.emptyRules.desc": "請勿使用空白規則集", - "css.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", - "css.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", - "css.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", - "css.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", - "css.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", - "css.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", - "css.lint.importStatement.desc": "匯入陳述式不會平行載入", - "css.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", - "css.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", - "css.lint.unknownProperties.desc": "未知的屬性。", - "css.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", - "css.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", - "css.lint.zeroUnits.desc": "零不需要任何單位", - "css.trace.server.desc": "追蹤 VS Code 與 CSS 語言伺服器之間的通訊。", - "css.validate.title": "控制 CSS 驗證與問題嚴重性。", - "css.validate.desc": "啟用或停用所有驗證", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "參數數目無效", - "less.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", - "less.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", - "less.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", - "less.lint.emptyRules.desc": "請勿使用空白規則集", - "less.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", - "less.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", - "less.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", - "less.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", - "less.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", - "less.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", - "less.lint.importStatement.desc": "匯入陳述式不會平行載入", - "less.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", - "less.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", - "less.lint.unknownProperties.desc": "未知的屬性。", - "less.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", - "less.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", - "less.lint.zeroUnits.desc": "零不需要任何單位", - "less.validate.title": "控制 LESS 驗證與問題嚴重性。", - "less.validate.desc": "啟用或停用所有驗證", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "參數數目無效", - "scss.lint.boxModel.desc": "使用填補或框線時不要使用寬度或高度。", - "scss.lint.compatibleVendorPrefixes.desc": "在使用廠商專屬的前置詞時,請確定也包括其他所有的廠商特定屬性。", - "scss.lint.duplicateProperties.desc": "請勿使用重複的樣式定義", - "scss.lint.emptyRules.desc": "請勿使用空白規則集", - "scss.lint.float.desc": "避免使用 'float'。浮動會使 CSS 脆弱,在版面配置的任一層面改變時容易中斷。", - "scss.lint.fontFaceProperties.desc": "@font-face 規則必須定義 'src' 和 'font-family' 屬性", - "scss.lint.hexColorLength.desc": "十六進位色彩必須由三個或六個十六進位數字組成", - "scss.lint.idSelector.desc": "選取器不應包含 ID,因為這些規則與 HTML 結合過於緊密。", - "scss.lint.ieHack.desc": "只有在支援 IE7 及更舊的版本時才需要 IE Hack", - "scss.lint.important.desc": "避免使用 !important。這表示整個 CSS 的明確性皆失控,需要重構。", - "scss.lint.importStatement.desc": "匯入陳述式不會平行載入", - "scss.lint.propertyIgnoredDueToDisplay.desc": "屬性因顯示而忽略。例如,若為 'display: inline',則 width、height、margin-top、margin-bottom 以及 float 屬性就不會有任何作用。", - "scss.lint.universalSelector.desc": "已知通用選取器 (*) 速度緩慢", - "scss.lint.unknownProperties.desc": "未知的屬性。", - "scss.lint.unknownVendorSpecificProperties.desc": "未知的廠商特定屬性。", - "scss.lint.vendorPrefix.desc": "在使用廠商專屬的前置詞時,也包括標準屬性。", - "scss.lint.zeroUnits.desc": "零不需要任何單位", - "scss.validate.title": "控制 SCSS 驗證與問題嚴重性。", - "scss.validate.desc": "啟用或停用所有驗證", - "less.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", - "scss.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", - "css.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", - "css.colorDecorators.enable.deprecationMessage": "設定 `css.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。", - "scss.colorDecorators.enable.deprecationMessage": "設定 `scss.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。", - "less.colorDecorators.enable.deprecationMessage": "設定 `less.colorDecorators.enable` 已淘汰,改為 `editor.colorDecorators`。" + "displayName": "CSS 語言基礎知識", + "description": "為 CSS、LESS 與 SCSS 檔案提供語法醒目提示與括弧對應功能。" } \ No newline at end of file diff --git a/i18n/cht/extensions/emmet/package.i18n.json b/i18n/cht/extensions/emmet/package.i18n.json index 84231277aa..d879e36ec6 100644 --- a/i18n/cht/extensions/emmet/package.i18n.json +++ b/i18n/cht/extensions/emmet/package.i18n.json @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "在以 `-` 開頭的 Emmet 縮寫中使用時,會取得 'webkit' 廠商前綴的逗點分隔 CSS 屬性。設定為空白字串可避免總是取得 'webkit' 前綴。", "emmetPreferencesCssMozProperties": "在以 `-` 開頭的 Emmet 縮寫中使用時,會取得 'moz' 廠商前綴的逗點分隔 CSS 屬性。設定為空白字串可避免總是取得 'moz' 前綴。", "emmetPreferencesCssOProperties": "在以 `-` 開頭的 Emmet 縮寫中使用時,會取得 'o' 廠商前綴的逗點分隔 CSS 屬性。設定為空白字串可避免總是取得 'o' 前綴。", - "emmetPreferencesCssMsProperties": "在以 `-` 開頭的 Emmet 縮寫中使用時,會取得 'ms' 廠商前綴的逗點分隔 CSS 屬性。設定為空白字串可避免總是取得 'ms' 前綴。" + "emmetPreferencesCssMsProperties": "在以 `-` 開頭的 Emmet 縮寫中使用時,會取得 'ms' 廠商前綴的逗點分隔 CSS 屬性。設定為空白字串可避免總是取得 'ms' 前綴。", + "emmetPreferencesCssFuzzySearchMinScore": "模糊比對的縮寫應該達到最低分數(從 0 到 1)。較低數值可能產生錯誤的比對,較高的數值可能會降低可能的比對。", + "emmetOptimizeStylesheetParsing": "當設定為 false 時,將解析整個檔案以確定目前的位置是否適用於展開 Emmet 縮寫。當設定為 true 時,僅會解析 css/scss/less 檔案中目前位置周圍的內容。" } \ No newline at end of file diff --git a/i18n/cht/extensions/git/out/commands.i18n.json b/i18n/cht/extensions/git/out/commands.i18n.json index e5be201e39..f6af72bc7e 100644 --- a/i18n/cht/extensions/git/out/commands.i18n.json +++ b/i18n/cht/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) 建立新的分支", "repourl": "儲存庫 URL", "parent": "父目錄", - "cancel": "$ (同步 ~ 旋轉) 複製儲存庫.. 按一下以取消", - "cancel tooltip": "取消複製", - "cloning": "正在複製 Git 儲存庫...", + "cloning": "正在複製 git 存放庫 '{0}'...", "openrepo": "開啟儲存庫", "proposeopen": "要開啟複製的儲存庫嗎?", "init": "選擇工作區資料夾以初始化 git 儲存庫", @@ -75,7 +73,7 @@ "ok": "確定", "push with tags success": "已成功使用標籤推送。", "pick remote": "挑選要發行分支 '{0}' 的目標遠端:", - "sync is unpredictable": "此動作會將認可發送至 '{0}' 及從中提取認可。", + "sync is unpredictable": "此動作會推送認可至`{0}/{1}`並從中提取認可。", "never again": "確定,不要再顯示", "no remotes to publish": "您的儲存庫未設定要發行的遠端目標。", "no changes stash": "沒有變更可供隱藏。", diff --git a/i18n/cht/extensions/git/package.i18n.json b/i18n/cht/extensions/git/package.i18n.json index 2f5f2f87b3..217b8b25cf 100644 --- a/i18n/cht/extensions/git/package.i18n.json +++ b/i18n/cht/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "控制是否在Git變更列表中的檔名旁顯示“開啟檔案”的動作按鈕。", "config.inputValidation": "控制何時顯示認可訊息輸入驗證。", "config.detectSubmodules": "控制是否自動偵測 Git 子模組。", + "config.detectSubmodulesLimit": "控制 Git 子模組的偵測限制", "colors.modified": "修改資源的顏色。", "colors.deleted": "刪除資源的顏色", "colors.untracked": "未追蹤資源的顏色。", diff --git a/i18n/cht/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/cht/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..0c001145a7 --- /dev/null +++ b/i18n/cht/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML 語言伺服器", + "folding.start": "摺疊區域開始", + "folding.end": "摺疊區域結束" +} \ No newline at end of file diff --git a/i18n/cht/extensions/html-language-features/package.i18n.json b/i18n/cht/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..d83d91cc72 --- /dev/null +++ b/i18n/cht/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML 語言功能", + "description": "為 HTML、Razor 及 Handlebars 檔案提供豐富的語言支援。", + "html.format.enable.desc": "啟用/停用預設 HTML 格式器", + "html.format.wrapLineLength.desc": "每行的字元數上限 (0 = 停用)。", + "html.format.unformatted.desc": "不應重新格式化的逗號分隔標記清單。'null' 預設為 https://www.w3.org/TR/html5/dom.html#phrasing-content 中列出的所有標記。", + "html.format.contentUnformatted.desc": "逗點分隔的標記清單,其中內容的格式不應重新設定。'null' 預設為 'pre' 標記。", + "html.format.indentInnerHtml.desc": "縮排 <head> 及 <body> 區段。", + "html.format.preserveNewLines.desc": "是否應保留項目前方現有的分行符號。僅適用於項目前方,而不適用於標記內或文字。", + "html.format.maxPreserveNewLines.desc": "一個區塊要保留的最大分行符號數。使用 'null' 表示無限制。", + "html.format.indentHandlebars.desc": "格式化並縮排 {{#foo}} 及 {{/foo}}。", + "html.format.endWithNewline.desc": "以新行字元結尾。", + "html.format.extraLiners.desc": "前方應有額外新行字元的標記清單,須以逗號分隔。'null' 的預設值為 \"head, body, /html\"。", + "html.format.wrapAttributes.desc": "將屬性換行。", + "html.format.wrapAttributes.auto": "只在超過行的長度時將屬性換行。", + "html.format.wrapAttributes.force": "將第一個以外的每個屬性換行。", + "html.format.wrapAttributes.forcealign": "將第一個以外的每個屬性換行,並保持對齊。", + "html.format.wrapAttributes.forcemultiline": "將每個屬性換行。", + "html.suggest.angular1.desc": "設定內建 HTML 語言支援是否建議 Angular V1 標記和屬性。", + "html.suggest.ionic.desc": "設定內建 HTML 語言支援是否建議 Ionic 標記、屬性和值。", + "html.suggest.html5.desc": "設定內建 HTML 語言支援是否建議 HTML5 標記、屬性和值。", + "html.trace.server.desc": "追蹤 VS Code 與 HTML 語言伺服器之間的通訊。", + "html.validate.scripts": "設定內建 HTML 語言支援是否會驗證內嵌指定碼。", + "html.validate.styles": "設定內建 HTML 語言支援是否會驗證內嵌樣式。", + "html.autoClosingTags": "啟用/停用 HTML 標籤的自動關閉功能。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/html/package.i18n.json b/i18n/cht/extensions/html/package.i18n.json index 3c78d75b5e..eb9141c809 100644 --- a/i18n/cht/extensions/html/package.i18n.json +++ b/i18n/cht/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML 語言功能", - "description": "為 HTML、Razor 及 Handlebars 檔案提供豐富的語言支援。", - "html.format.enable.desc": "啟用/停用預設 HTML 格式器", - "html.format.wrapLineLength.desc": "每行的字元數上限 (0 = 停用)。", - "html.format.unformatted.desc": "不應重新格式化的逗號分隔標記清單。'null' 預設為 https://www.w3.org/TR/html5/dom.html#phrasing-content 中列出的所有標記。", - "html.format.contentUnformatted.desc": "逗點分隔的標記清單,其中內容的格式不應重新設定。'null' 預設為 'pre' 標記。", - "html.format.indentInnerHtml.desc": "縮排 <head> 及 <body> 區段。", - "html.format.preserveNewLines.desc": "是否應保留項目前方現有的分行符號。僅適用於項目前方,而不適用於標記內或文字。", - "html.format.maxPreserveNewLines.desc": "一個區塊要保留的最大分行符號數。使用 'null' 表示無限制。", - "html.format.indentHandlebars.desc": "格式化並縮排 {{#foo}} 及 {{/foo}}。", - "html.format.endWithNewline.desc": "以新行字元結尾。", - "html.format.extraLiners.desc": "前方應有額外新行字元的標記清單,須以逗號分隔。'null' 的預設值為 \"head, body, /html\"。", - "html.format.wrapAttributes.desc": "將屬性換行。", - "html.format.wrapAttributes.auto": "只在超過行的長度時將屬性換行。", - "html.format.wrapAttributes.force": "將第一個以外的每個屬性換行。", - "html.format.wrapAttributes.forcealign": "將第一個以外的每個屬性換行,並保持對齊。", - "html.format.wrapAttributes.forcemultiline": "將每個屬性換行。", - "html.suggest.angular1.desc": "設定內建 HTML 語言支援是否建議 Angular V1 標記和屬性。", - "html.suggest.ionic.desc": "設定內建 HTML 語言支援是否建議 Ionic 標記、屬性和值。", - "html.suggest.html5.desc": "設定內建 HTML 語言支援是否建議 HTML5 標記、屬性和值。", - "html.trace.server.desc": "追蹤 VS Code 與 HTML 語言伺服器之間的通訊。", - "html.validate.scripts": "設定內建 HTML 語言支援是否會驗證內嵌指定碼。", - "html.validate.styles": "設定內建 HTML 語言支援是否會驗證內嵌樣式。", - "html.experimental.syntaxFolding": "啟用/停用語法感知摺疊標記。", - "html.autoClosingTags": "啟用/停用 HTML 標籤的自動關閉功能。" + "displayName": "HTML 語言基礎知識", + "description": "為 HTML 檔案提供語法醒目提示、括弧對應與程式碼片段功能。" } \ No newline at end of file diff --git a/i18n/cht/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/cht/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..275d7ba3cb --- /dev/null +++ b/i18n/cht/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON 語言伺服器" +} \ No newline at end of file diff --git a/i18n/cht/extensions/json-language-features/package.i18n.json b/i18n/cht/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..15eaaf64ae --- /dev/null +++ b/i18n/cht/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON 語言功能", + "description": "為 JSON 檔案提供豐富的語言支援", + "json.schemas.desc": "在結構描述與目前專案的 JSON 檔案之間建立關聯", + "json.schemas.url.desc": "目前目錄中的結構描述 URL 或結構描述相對路徑", + "json.schemas.fileMatch.desc": "檔案模式陣列,在將 JSON 檔案解析成結構描述時的比對對象。", + "json.schemas.fileMatch.item.desc": "可包含 '*' 的檔案模式,在將 JSON 檔案解析成結構描述時的比對對象。", + "json.schemas.schema.desc": "指定 URL 的結構描述定義。只須提供結構描述以避免存取結構描述 URL。", + "json.format.enable.desc": "啟用/停用預設 JSON 格式器 (需要重新啟動)", + "json.tracing.desc": "追蹤 VS Code 與 JSON 語言伺服器之間的通訊。", + "json.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", + "json.colorDecorators.enable.deprecationMessage": "設定 `json.colorDecorators.enable` 已淘汰,將改為 `editor.colorDecorators`。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/json/package.i18n.json b/i18n/cht/extensions/json/package.i18n.json index 27192fc540..909f55cf27 100644 --- a/i18n/cht/extensions/json/package.i18n.json +++ b/i18n/cht/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON 語言功能", - "description": "為 JSON 檔案提供豐富的語言支援", - "json.schemas.desc": "在結構描述與目前專案的 JSON 檔案之間建立關聯", - "json.schemas.url.desc": "目前目錄中的結構描述 URL 或結構描述相對路徑", - "json.schemas.fileMatch.desc": "檔案模式陣列,在將 JSON 檔案解析成結構描述時的比對對象。", - "json.schemas.fileMatch.item.desc": "可包含 '*' 的檔案模式,在將 JSON 檔案解析成結構描述時的比對對象。", - "json.schemas.schema.desc": "指定 URL 的結構描述定義。只須提供結構描述以避免存取結構描述 URL。", - "json.format.enable.desc": "啟用/停用預設 JSON 格式器 (需要重新啟動)", - "json.tracing.desc": "追蹤 VS Code 與 JSON 語言伺服器之間的通訊。", - "json.colorDecorators.enable.desc": "啟用或停用彩色裝飾項目", - "json.colorDecorators.enable.deprecationMessage": "設定 `json.colorDecorators.enable` 已淘汰,將改為 `editor.colorDecorators`。", - "json.experimental.syntaxFolding": "啟用/停用語法感知折疊標記。" + "displayName": "JSON 語言基礎知識", + "description": "為 JSON 檔案提供語法醒目提示與括弧對應功能。" } \ No newline at end of file diff --git a/i18n/cht/extensions/markdown-basics/package.i18n.json b/i18n/cht/extensions/markdown-basics/package.i18n.json index 60c12fe7f5..c1f9350d04 100644 --- a/i18n/cht/extensions/markdown-basics/package.i18n.json +++ b/i18n/cht/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/cht/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/cht/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..2f489d0fef --- /dev/null +++ b/i18n/cht/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "無法載入 ‘markdown.style' 樣式:{0}" +} \ No newline at end of file diff --git a/i18n/cht/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/cht/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..74c6cf1816 --- /dev/null +++ b/i18n/cht/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[預覽] {0}", + "previewTitle": "預覽 [0]" +} \ No newline at end of file diff --git a/i18n/cht/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/cht/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..fe1f5c5a4e --- /dev/null +++ b/i18n/cht/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "此文件中的部分內容已停用", + "preview.securityMessage.title": "Markdown 預覽中已停用可能不安全或不安全的內容。請將 Markdown 預覽的安全性設定變更為允許不安全內容,或啟用指令碼", + "preview.securityMessage.label": "內容已停用安全性警告" +} \ No newline at end of file diff --git a/i18n/cht/extensions/markdown-language-features/out/security.i18n.json b/i18n/cht/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..6f41794bac --- /dev/null +++ b/i18n/cht/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "嚴謹", + "strict.description": "僅載入安全內容", + "insecureLocalContent.title": "允許不安全的本機內容", + "insecureLocalContent.description": "啟用從本機提供 http 載入內容", + "insecureContent.title": "允許不安全的內容", + "insecureContent.description": "啟用 http 載入內容", + "disable.title": "停用", + "disable.description": "允許所有內容與指令碼執行。不建議", + "moreInfo.title": "詳細資訊", + "enableSecurityWarning.title": "允許此工作區預覽安全性警告", + "disableSecurityWarning.title": "不允許此工作區預覽安全性警告", + "toggleSecurityWarning.description": "不影響內容安全性層級", + "preview.showPreviewSecuritySelector.title": "選擇此工作區 Markdown 預覽的安全性設定" +} \ No newline at end of file diff --git a/i18n/cht/extensions/markdown-language-features/package.i18n.json b/i18n/cht/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..d27fa896c2 --- /dev/null +++ b/i18n/cht/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown 語言功能", + "description": "為 Markdown 提供豐富的語言支援。", + "markdown.preview.breaks.desc": "設定在 Markdown 預覽中如何顯示分行符號。設為 'trure' 為每個新行建立<br>", + "markdown.preview.linkify": "啟用或停用在 Markdown 預覽中將類似 URL 的文字轉換為連結。", + "markdown.preview.doubleClickToSwitchToEditor.desc": "在 Markdown 預覽中按兩下會切換到編輯器。", + "markdown.preview.fontFamily.desc": "控制 Markdown 預覽中使用的字型家族。", + "markdown.preview.fontSize.desc": "控制 Markdown 預覽中使用的字型大小 (以像素為單位)。", + "markdown.preview.lineHeight.desc": "控制 Markdown 預覽中使用的行高。此數字相對於字型大小。", + "markdown.preview.markEditorSelection.desc": "在 Markdown 預覽中標記目前的編輯器選取範圍。", + "markdown.preview.scrollEditorWithPreview.desc": "在捲動 Markdown 預覽時更新編輯器的檢視。", + "markdown.preview.scrollPreviewWithEditor.desc": "在捲動 Markdown 編輯器時更新預覽的檢視。", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[已淘汰] 捲動 Markdown 預覽,以從編輯器顯示目前選取的程式行。", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "此設定已由 'markdown.preview.scrollPreviewWithEditor' 取代,不再具有任何效果。", + "markdown.preview.title": "開啟預覽", + "markdown.previewFrontMatter.dec": "設定 YAML 前端在 Markdown 預覽中呈現的方式。[隱藏] 會移除前端。否則,前端會視為 Markdown 內容。", + "markdown.previewSide.title": "在一側開啟預覽", + "markdown.showLockedPreviewToSide.title": "在側面開啟鎖定的預覽", + "markdown.showSource.title": "顯示來源", + "markdown.styles.dec": "可從 Markdown 預覽使用之 CSS 樣式表的 URL 或本機路徑清單。相對路徑是相對於在總管中開啟的資料夾來進行解釋。若沒有開啟資料夾,路徑則是相對於 Markdown 檔案的位置來進行解釋。所有 '\\' 都必須寫成 '\\\\'。", + "markdown.showPreviewSecuritySelector.title": "變更預覽的安全性設定", + "markdown.trace.desc": "允許 Markdown 延伸模組進行偵錯記錄。", + "markdown.preview.refresh.title": "重新整理預覽", + "markdown.preview.toggleLock.title": "切換預覽鎖定" +} \ No newline at end of file diff --git a/i18n/cht/extensions/markdown/out/features/preview.i18n.json b/i18n/cht/extensions/markdown/out/features/preview.i18n.json index 93ef07cf18..74c6cf1816 100644 --- a/i18n/cht/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/cht/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/cht/extensions/npm/out/npmView.i18n.json b/i18n/cht/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..0fcedab1eb --- /dev/null +++ b/i18n/cht/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "因為指令碼缺少節點偵錯選項 (例如 '--inspect-brk'),所以無法啟動 \"{0}\" 以進行偵錯。", + "npm.scriptInvalid": "找不到指令碼 \"{0}\"。請嘗試重新整理檢視。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/npm/out/tasks.i18n.json b/i18n/cht/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..f0e654540c --- /dev/null +++ b/i18n/cht/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Npm 工作刪除: 解析檔案 {0} 失敗" +} \ No newline at end of file diff --git a/i18n/cht/extensions/npm/package.i18n.json b/i18n/cht/extensions/npm/package.i18n.json index 8471b3529f..6a4c442541 100644 --- a/i18n/cht/extensions/npm/package.i18n.json +++ b/i18n/cht/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "以 `--silent` 選項執行 npm 命令。 ", "config.npm.packageManager": "用來執行指令碼的套件管理員。", "config.npm.exclude": "為應從自動指令碼偵測排除的資料夾設定 Glob 模式。", + "config.npm.enableScriptExplorer": "當工作區包含 'package.json' 檔案時,啟用 npm 指令碼的總管檢視。", "npm.parseError": "Npm 工作刪除: 解析檔案 {0} 失敗", "taskdef.script": "要自訂的 npm 指令碼。", - "taskdef.path": "提供指令碼之 package.json 檔案的資料夾路徑。可以省略。" + "taskdef.path": "提供指令碼之 package.json 檔案的資料夾路徑。可以省略。", + "view.name": "Npm 指令碼", + "command.refresh": "重新整理", + "command.run": "執行", + "command.debug": "偵錯", + "command.openScript": "開啟", + "npm.scriptInvalid": "找不到指令碼 '{0}'。請嘗試重新整理檢視。", + "npm.noDebugOptions": "因為指令碼缺少節點偵錯選項 (例如 '--inspect-brk'),所以無法啟動 '{0}' 以進行偵錯。" } \ No newline at end of file diff --git a/i18n/cht/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/cht/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..62153a9c2d --- /dev/null +++ b/i18n/cht/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "要允許 {0} (定義為工作區設定) 執行,以使用 lint 標記 PHP 檔案嗎?", + "php.yes": "允許", + "php.no": "不允許", + "wrongExecutable": "因為 {0} 不是有效的 PHP 可執行檔,所以無法驗證。您可以使用設定 'php.validate.executablePath' 設定 PHP 可執行檔。", + "noExecutable": "因為未設定任何 PHP 可執行檔,所以無法驗證。您可以使用 'php.validate.executablePath' 設定可執行檔。", + "unknownReason": "無法使用路徑 {0} 執行 PHP。原因不明。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/php-language-features/package.i18n.json b/i18n/cht/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..abe5dfe9ea --- /dev/null +++ b/i18n/cht/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "設定是否啟用內建 PHP 語言建議。此支援會建議 PHP 全域和變數。", + "configuration.validate.enable": "啟用/停用內建 PHP 驗證。", + "configuration.validate.executablePath": "指向 PHP 可執行檔。", + "configuration.validate.run": "是否在儲存或輸入時執行 linter。", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "禁止 PHP 驗證可執行檔 (定義為工作區設定)", + "displayName": "PHP 語言功能", + "description": "為 PHP 檔案提供豐富的語言支援。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/php/package.i18n.json b/i18n/cht/extensions/php/package.i18n.json index cff46f94e0..d6cdfe9a0f 100644 --- a/i18n/cht/extensions/php/package.i18n.json +++ b/i18n/cht/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "設定是否啟用內建 PHP 語言建議。此支援會建議 PHP 全域和變數。", - "configuration.validate.enable": "啟用/停用內建 PHP 驗證。", - "configuration.validate.executablePath": "指向 PHP 可執行檔。", - "configuration.validate.run": "是否在儲存或輸入時執行 linter。", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "禁止 PHP 驗證可執行檔 (定義為工作區設定)", - "displayName": "PHP 語言功能", - "description": "為 PHP 檔案提供 IntelliSense、Lint 支援及語言基礎知識。" + "displayName": "PHP 語言基礎知識", + "description": "為 PHP 檔案提供語法醒目提示與括弧對應功能。" } \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/commands.i18n.json b/i18n/cht/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..90f4f953b4 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "請在 VS Code 中開啟資料夾,以使用 TypeScript 或 JavaScript 專案", + "typescript.projectConfigUnsupportedFile": "無法判斷 TypeScript 或 JavaScript 專案。不支援的檔案類型", + "typescript.projectConfigCouldNotGetInfo": "無法判斷 TypeScript 或 JavaScript 專案", + "typescript.noTypeScriptProjectConfig": "檔案不屬於 TypeScript 專案。若要深入了解,請按一下[這裡]({0})。", + "typescript.noJavaScriptProjectConfig": "檔案不屬於 JavaScript 專案。若要深入了解,請按一下[這裡]({0})。", + "typescript.configureTsconfigQuickPick": "設定 tsconfig.json", + "typescript.configureJsconfigQuickPick": "設定 jsconfig.json" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..18117a677b --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "選擇要套用的程式碼動作", + "acquiringTypingsLabel": "正在擷取 typings...", + "acquiringTypingsDetail": "正在為 IntelliSense 擷取 typings 定義。", + "autoImportLabel": "自動從 {0} 匯入" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..7d901d9ed9 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "啟用 JavaScript 檔案的語意檢查。必須在檔案的最上面。", + "ts-nocheck": "停用 JavaScript 檔案的語意檢查。必須在檔案的最上面。", + "ts-ignore": "隱藏下一行@ts-check 的錯誤警告。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..16a3b7e5e5 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 個實作", + "manyImplementationLabel": "{0} 個實作", + "implementationsErrorLabel": "無法判斷實作數" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..2851c131ea --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc 註解" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..d3f0fb2186 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "組織匯入" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..85939cee97 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (檔案中修復全部)" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..4ae222d6a1 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 個參考", + "manyReferenceLabel": "{0} 個參考", + "referenceErrorLabel": "無法判斷參考" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..61ba5737e6 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "建置 - {0}", + "buildAndWatchTscLabel": "監看 - {0}" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/cht/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..54beeeb5b8 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "路徑 {0} 未指向有效的 tsserver 安裝。即將回復為配套的 TypeScript 版本。", + "serverCouldNotBeStarted": "無法啟動 TypeScript 語言伺服器。錯誤訊息為: {0}", + "typescript.openTsServerLog.notSupported": "TS 伺服器的記錄功能需要 TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "TS 伺服器記錄功能已關閉。請設定 `typescript.tsserver.log` 並重新啟動 TS 伺服器,以啟用記錄功能", + "typescript.openTsServerLog.enableAndReloadOption": "啟用記錄功能並重新啟動 TS 伺服器", + "typescript.openTsServerLog.noLogFile": "TS 伺服器尚未開始記錄。", + "openTsServerLog.openFileFailedFailed": "無法開啟 TS 伺服器記錄檔", + "serverDiedAfterStart": "TypeScript 語言服務在啟動後立即中止 5 次。服務將不會重新啟動。", + "serverDiedReportIssue": "回報問題", + "serverDied": "TypeScript 語言服務在過去 5 分鐘內意外中止 5 次。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..bb0bb1a4af --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "無效的版本" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..5d6e558a98 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "若要讓整個專案都能使用 JavaScript/TypeScript 語言功能,請排除內含許多檔案的資料夾,例如: {0}", + "hintExclude.generic": "若要讓整個專案都能使用 JavaScript/TypeScript 語言功能,請排除內含您未使用之來源檔案的大型資料夾。", + "large.label": "設定排除項目", + "hintExclude.tooltip": "若要讓整個專案都能使用 JavaScript/TypeScript 語言功能,請排除內含您未使用之來源檔案的大型資料夾。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..e80262263f --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "正在擷取資料以改善 TypeScript IntelliSense", + "typesInstallerInitializationFailed.title": "無法為 JavaScript 語言功能安裝 typings 檔案。請確認已安裝 NPM,或在使用者設定中設定 'typescript.npm'。若要深入了解,請按一下[這裡]({0})。", + "typesInstallerInitializationFailed.doNotCheckAgain": "不要再顯示" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..fdf7133b82 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "使用 VS Code 的版本", + "useWorkspaceVersionOption": "使用工作區版本", + "learnMore": "深入了解", + "selectTsVersion": "選取 JavaScript 與 TypeScript 功能使用的 TypeScript 版本" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/cht/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..8d374cb188 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "無法在此路徑載入 TypeScript 版本", + "noBundledServerFound": "其他應用程式已刪除了 VS Code 的 tsserver,例如行為不當的病毒偵測工具。請重新安裝 VS Code。" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript-language-features/package.i18n.json b/i18n/cht/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..c7a5d0d5e9 --- /dev/null +++ b/i18n/cht/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript 和 JavaScript 語言功能", + "description": "為 JavaScript 和 TypeScript 提供豐富的語言支援。", + "typescript.reloadProjects.title": "重新載入專案", + "javascript.reloadProjects.title": "重新載入專案", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "使用其參數簽章完成函式。", + "typescript.tsdk.desc": "指定資料夾路徑,其中包含要使用的 tsserver 和 lib*.d.ts 檔案。", + "typescript.disableAutomaticTypeAcquisition": "停用自動類型取得。需要 TypeScript >= 2.0.6。", + "typescript.tsserver.log": "允許 TS 伺服器記錄到檔案。此記錄可用來診斷 TS 伺服器問題。記錄可能包含檔案路徑、原始程式碼及您專案中可能具有敏感性的其他資訊。", + "typescript.tsserver.pluginPaths": "發現 TypeScript 語言服務外掛的其他路徑。需要 TypeScript >= 2.3.0。", + "typescript.tsserver.pluginPaths.item": "無論是絕對路徑或是相對路徑。相對路徑將會根據工作區資料夾進行解析。", + "typescript.tsserver.trace": "允許將訊息追蹤傳送到 TS 伺服器。此追蹤可用來診斷 TS 伺服器問題。追蹤可能包含檔案路徑、原始程式碼及您專案中可能具有敏感性的其他資訊。", + "typescript.validate.enable": "啟用/停用 TypeScript 驗證。", + "typescript.format.enable": "啟用/停用預設 TypeScript 格式器。", + "javascript.format.enable": "啟用/停用預設 JavaScript 格式器。", + "format.insertSpaceAfterCommaDelimiter": "定義逗號分隔符號後的空格處理。", + "format.insertSpaceAfterConstructor": "定義 constructor 關鍵字後空格處理。需要 TypeScript >= 2.3.0。", + "format.insertSpaceAfterSemicolonInForStatements": " 定義 for 陳述式內分號後的空格處理。", + "format.insertSpaceBeforeAndAfterBinaryOperators": "定義二元運算子後的空格處理。", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "定義控制流程陳述式內關鍵字後的空格處理方式。", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "定義匿名函式之函式關鍵字後的空格處理。", + "format.insertSpaceBeforeFunctionParenthesis": "定義如何處理函式引數括號之前的空格。TypeScript 必須 >= 2.1.5。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "定義左右非空白括弧間的空格處理。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "定義左右非空白括弧間的空格處理。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "定義左右非空白括弧間的空格處理。需要 TypeScript >= 2.3.0。", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "定義範本字串左右大括弧間的空格處理。需要 TypeScript >= 2.0.6。", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "定義 JSX 運算式左右大括弧間的空格處理。需要 TypeScript >= 2.0.6。", + "format.insertSpaceAfterTypeAssertion": "定義在 TypeScript 內類型宣告後空格處理。需要 TypeScript >= 2.4。", + "format.placeOpenBraceOnNewLineForFunctions": "定義是否將左大括弧放入函式的新行。", + "format.placeOpenBraceOnNewLineForControlBlocks": "定義是否將左大括弧放入控制區塊的新行。", + "javascript.validate.enable": "啟用/停用 JavaScript 驗證。", + "typescript.goToProjectConfig.title": "移至專案組態", + "javascript.goToProjectConfig.title": "移至專案組態", + "javascript.referencesCodeLens.enabled": "在JavaScript檔案啟用/停用 參考CodeLens ", + "typescript.referencesCodeLens.enabled": "在TypeScript檔案啟用/停用CodeLens參考。需要TypeScript>=2.0.6。", + "typescript.implementationsCodeLens.enabled": "啟用/停用實作 CodeLens。需要 TypeScript >= 2.2.0。", + "typescript.openTsServerLog.title": "開啟 TS 伺服器記錄", + "typescript.restartTsServer": "重新啟動TS伺服器", + "typescript.selectTypeScriptVersion.title": "選取 TypeScript 版本", + "typescript.reportStyleChecksAsWarnings": "使用警告顯示樣式檢查", + "jsDocCompletion.enabled": "啟用/停用自動 JSDoc 註解", + "javascript.implicitProjectConfig.checkJs": "啟用/停用 JavaScript 檔案的語意檢查。現有的 jsconfig.json 或 tsconfig.json 檔案會覆寫此設定。需要 TypeScript >=2.3.1。", + "typescript.npm": "指定用於自動類型取得的 NPM 可執行檔路徑。TypeScript 必須 >= 2.3.4.", + "typescript.check.npmIsInstalled": "檢查是否已安裝NPM用以取得自動類型擷取.", + "javascript.nameSuggestions": "從JavaScript推薦表檔案中啟用/停用包含唯一檔名", + "typescript.tsc.autoDetect": "控制自動偵測 tsc 任務。 'off' 停用此功能。 'build' 僅建立單次編譯任務。 'watch' 僅建立編譯並監看任務。 'on' 同時建立編譯及監看任務。預設值為 'on'。", + "typescript.problemMatchers.tsc.label": "TypeScript 問題", + "typescript.problemMatchers.tscWatch.label": " TypeScript 問題 (監看模式)", + "typescript.quickSuggestionsForPaths": "啟用/停用在輸入匯入路徑顯示即時建議。", + "typescript.locale": "設定報告 TypeScript 錯誤的語系。需要 TypeScript >= 2.6.0。預設值 'null' 則使用 VS Code 的語系來顯示 TypeScript 錯誤。", + "javascript.implicitProjectConfig.experimentalDecorators": "啟用/停用 JavaScript 檔案中非專案部分的 'experimentalDecorators'。現有的 jsconfig.json 或 tsconfig.json 檔案會覆寫此設定。需要 TypeScript >=2.3.1。", + "typescript.autoImportSuggestions.enabled": "啟用/停用 自動匯入建議。需要 TypeScript >=2.6.1", + "typescript.experimental.syntaxFolding": "啟用/停用語法感知摺疊標記。", + "taskDefinition.tsconfig.description": "定義 TS 組建的 tsconfig 檔案。", + "javascript.suggestionActions.enabled": "編輯器內啟用/停用 JavaScript 檔案建議診斷。需要 TypeScript >= 2.8", + "typescript.suggestionActions.enabled": "編輯器內啟用/停用 TypeScript 檔案建議診斷。需要 TypeScript >= 2.8" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/base/node/processes.i18n.json b/i18n/cht/src/vs/base/node/processes.i18n.json index 8a5687503c..ccee9332e3 100644 --- a/i18n/cht/src/vs/base/node/processes.i18n.json +++ b/i18n/cht/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "無法在 UNC 磁碟機上執行殼層命令。" + "TaskRunner.UNC": "無法在 UNC 磁碟機上執行 shell 命令。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/base/node/zip.i18n.json b/i18n/cht/src/vs/base/node/zip.i18n.json index 6158454378..a13062c166 100644 --- a/i18n/cht/src/vs/base/node/zip.i18n.json +++ b/i18n/cht/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "未完成。已擷取 {0} 個項目 (共 {1} 個)", "notFound": "在 ZIP 中找不到 {0}。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/cht/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 4b1716ee95..ffe1fad498 100644 --- a/i18n/cht/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/cht/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "在 GitHub 預覽", "loadingData": "正在載入資料...", + "rateLimited": "超出了 GitHub 查詢限制。請稍候。", "similarIssues": "相似的問題", "open": "開啟", "closed": "已關閉", - "noResults": "找不到結果", + "noSimilarIssues": "未發現相似的問題", "settingsSearchIssue": "設定值搜尋問題", "bugReporter": "臭蟲回報", - "performanceIssue": "效能問題", "featureRequest": "功能要求", + "performanceIssue": "效能問題", "stepsToReproduce": "重現的步驟", "bugDescription": "請共用必要步驟以確實複製問題。請包含實際與預期的結果。我們支援 GitHub 慣用的 Markdown 語言。當我們在 GitHub 進行預覽時,您仍可編輯問題和新增螢幕擷取畫面。", "performanceIssueDesciption": "效能問題的發生時間點為何? 問題是在啟動或經過一組特定動作後發生的? 我們支援 GitHub 慣用的 Markdown 語言。當我們在 GitHub 上進行預覽時,您仍可編輯問題和新增螢幕擷取畫面。", diff --git a/i18n/cht/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/cht/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index 021dfa083e..7983416d3d 100644 --- a/i18n/cht/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/cht/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "請用英語填寫這張表格。", "issueTypeLabel": "這是一個", + "issueSourceLabel": "檔案,位於", + "vscode": "Visual Studio Code", + "extension": "擴充功能", + "disableExtensionsLabelText": "嘗試在 {0} 之後重現問題。如果問題僅在使用中的擴充功能時重現,則可能是擴充功能的問題。", + "disableExtensions": "停用所有延伸模組並重新載入視窗", + "chooseExtension": "擴充功能", "issueTitleLabel": "標題", "issueTitleRequired": "請輸入標題。", "titleLengthValidation": "標題太長。", @@ -18,13 +24,6 @@ "extensions": "我的擴充功能", "searchedExtensions": "搜尋過的擴充功能", "settingsSearchDetails": "設定值搜尋詳細資料", - "tryDisablingExtensions": "是否在停用擴充功能後問題仍會發生?", - "yes": "是", - "no": "否", - "disableExtensionsLabelText": "請在 {0} 之後嘗試複製問題。", - "disableExtensions": "停用所有延伸模組並重新載入視窗", - "showRunningExtensionsLabelText": "如果您認為這是延伸模組問題,請 {0} 以回報延伸模組問題。", - "showRunningExtensions": "檢視所有執行中的延伸模組", "details": "請輸入詳細資料。", "loadingData": "正在載入資料..." } \ No newline at end of file diff --git a/i18n/cht/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/cht/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..00f7c8ffb1 --- /dev/null +++ b/i18n/cht/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU %", + "memory": "記憶體 (MB)", + "pid": "pid", + "name": "名稱", + "killProcess": "關閉處理序", + "forceKillProcess": "強制關閉處理序" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/code/electron-main/menus.i18n.json b/i18n/cht/src/vs/code/electron-main/menus.i18n.json index c0fb4442cb..ea090563a4 100644 --- a/i18n/cht/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/cht/src/vs/code/electron-main/menus.i18n.json @@ -113,7 +113,7 @@ "miZoomOut": "縮小(&&U)", "miZoomReset": "重設縮放(&&R)", "miBack": "上一步(&B)", - "miForward": "轉寄(&&F)", + "miForward": "下一頁(&&F)", "miNextEditor": "下一個編輯器(&&N)", "miPreviousEditor": "上一個編輯器(&&P)", "miNextEditorInGroup": "群組中下一個已使用的編輯器(&&N)", @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "條件式中斷點(&&C)...", "miColumnBreakpoint": "資料行中斷點(&&O)", "miFunctionBreakpoint": "函式中斷點(&&F}...", + "miLogPoint": "&&記錄點...", "miNewBreakpoint": "新增中斷點(&&N)", "miEnableAllBreakpoints": "啟用所有中斷點", "miDisableAllBreakpoints": "停用所有中斷點(&&L)", @@ -161,6 +162,7 @@ "mMergeAllWindows": "合併所有視窗", "miToggleDevTools": "切換開發人員工具(&&T)", "miAccessibilityOptions": "協助工具選項(&&O)", + "miOpenProcessExplorerer": "開啟處理序總管 (&&P)", "miReportIssue": "回報問題 (&&I)", "miWelcome": "歡迎使用(&&W)", "miInteractivePlayground": "Interactive Playground(&&I)", diff --git a/i18n/cht/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/cht/src/vs/editor/browser/widget/diffReview.i18n.json index a3f8e57713..1b40f08f45 100644 --- a/i18n/cht/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/cht/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "關閉", - "header": "差異 {0} / {1}: 原始 {2},{3} 行,修改後 {4},{5} 行", + "no_lines": "沒有任何行", + "one_line": "1 個行", + "more_lines": "{0} 個行", + "header": "{1} 的 {0} 不同: 原始為 {2},{3},修改後為 {4},{5}", "blankLine": "空白", "equalLine": "原始 {0},修改後{1}: {2", "insertLine": "+ 修改後 {0}: {1}", diff --git a/i18n/cht/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/cht/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..9ba9d8d6b8 --- /dev/null +++ b/i18n/cht/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "游標數已限制為 {0} 個。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json index 51a91eccd1..114d264012 100644 --- a/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "行號以絕對值顯示。", "lineNumbers.relative": "行號以目前游標的相對值顯示。", "lineNumbers.interval": "每 10 行顯示行號。", - "lineNumbers": "控制行號的顯示方式。允許的設定值為 'on'、 'off'、'relative' 及 'interval'", + "lineNumbers": "控制行號的顯示。", "rulers": "在特定的等寬字元數之後轉譯垂直尺規。有多個尺規就使用多個值。若陣列為空,則不繪製任何尺規。", "wordSeparators": "執行文字相關導覽或作業時將作為文字分隔符號的字元", "tabSize": "與 Tab 相等的空格數量。當 `editor.detectIndentation` 已開啟時,會根據檔案內容覆寫此設定。", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "控制編輯器是否會捲動到最後一行之後", "smoothScrolling": "控制編輯器是否會使用動畫捲動", "minimap.enabled": "控制是否會顯示迷你地圖", - "minimap.side": "控制要轉譯迷你地圖的方向。可能的值為 'right' 與 'left'", - "minimap.showSlider": "控制是否會自動隱藏迷你地圖滑桿。可能的值為 'always' 與 'mouseover'", + "minimap.side": "控制要在哪端呈現迷你地圖。", + "minimap.showSlider": "自動隱藏迷你地圖滑桿", "minimap.renderCharacters": "呈現行內的實際字元 (而不是彩色區塊)", "minimap.maxColumn": "限制迷你地圖的寬度,以呈現最多的資料行", "find.seedSearchStringFromSelection": "控制編譯器選取範圍是否預設為尋找工具的搜尋字串", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "對應 Windows 和 Linux 的 `Control` 與對應 macOS 的 `Command`", "multiCursorModifier.alt": "對應 Windows 和 Linux 的 `Alt` 與對應 macOS 的 `Option`", "multiCursorModifier": "用於新增多個滑鼠游標的修改。 `ctrlCmd` 會對應到 Windows 和 Linux 上的 `Control` 以及 macOS 上的 `Command`。 [移至定義] 及 [開啟連結] 滑鼠手勢將會適應以避免和 multicursor 修改衝突。", + "multiCursorMergeOverlapping": "在重疊時合併多個游標。", "quickSuggestions.strings": "允許在字串內顯示即時建議。", "quickSuggestions.comments": "允許在註解中顯示即時建議。", "quickSuggestions.other": "允許在字串與註解以外之處顯示即時建議。", @@ -76,7 +77,7 @@ "occurrencesHighlight": "控制編輯器是否應反白顯示出現的語意符號", "overviewRulerLanes": "控制可在概觀尺規中相同位置顯示的裝飾項目數", "overviewRulerBorder": "控制是否應在概觀尺規周圍繪製邊框。", - "cursorBlinking": "控制游標動畫樣式,可能的值為 'blink'、'smooth'、'phase'、'expand' 和 'solid'", + "cursorBlinking": "控制游標動畫樣式。", "mouseWheelZoom": "使用滑鼠滾輪並按住 Ctrl 時,縮放編輯器的字型", "cursorStyle": "控制游標樣式。接受的值為 'block'、'block-outline'、'line'、'line-thin'、'underline' 及 'underline-thin'", "cursorWidth": "控制游標寬度,當 editor.cursorStyle 設定為 'line' 時。", @@ -86,8 +87,11 @@ "renderControlCharacters": "控制編輯器是否應顯示控制字元", "renderIndentGuides": "控制編輯器是否應顯示縮排輔助線", "renderLineHighlight": "控制編輯器應如何轉譯目前反白的行,可能的值有 'none'、'gutter'、'line' 和 'all'。", - "codeLens": "控制編輯器是否顯示程式碼濾鏡", + "codeLens": "控制編輯器是否顯示 CodeLens", "folding": "控制編輯器是否已啟用程式碼摺疊功能", + "foldingStrategyAuto": "如果可行,請使用語言特定摺疊策略,否則請退回至縮排式策略。", + "foldingStrategyIndentation": "一律使用縮排式摺疊策略", + "foldingStrategy": "控制折疊範圍的計算方式。'auto' 會在可行的情況下挑選使用語言特定摺疊策略。'indentation' 則會強制使用縮排式摺疊策略。", "showFoldingControls": "自動隱藏摺疊控制向", "matchBrackets": "當選取某側的括號時,強調顯示另一側的配對括號。", "glyphMargin": "控制編輯器是否應轉譯垂直字符邊界。字符邊界最常用來進行偵錯。", @@ -102,8 +106,12 @@ "links": "控制編輯器是否應偵測連結且讓它可點擊", "colorDecorators": "控制編輯器是否應轉譯內嵌色彩裝飾項目與色彩選擇器。", "codeActions": "啟用程式動作燈泡提示", + "codeActionsOnSave.organizeImports": "要在儲存時執行組織匯入嗎?", + "codeActionsOnSave": "要在儲存時執行的程式碼動作種類。", + "codeActionsOnSaveTimeout": "儲存時執行的程式碼動作逾時。", "selectionClipboard": "控制是否應支援 Linux 主要剪貼簿。", "sideBySide": "控制 Diff 編輯器要並排或內嵌顯示差異", "ignoreTrimWhitespace": "控制 Diff 編輯器是否將開頭或尾端空白字元的變更顯示為差異", + "largeFileOptimizations": "針對大型檔案停用部分高記憶體需求功能的特殊處理方式。", "renderIndicators": "控制 Diff 編輯器是否要為新增的/移除的變更顯示 +/- 標記" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json index ecc3bba9f4..be0985019e 100644 --- a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,8 +14,10 @@ "editorCursorBackground": "編輯器游標的背景色彩。允許自訂區塊游標重疊的字元色彩。", "editorWhitespaces": "編輯器中空白字元的色彩。", "editorIndentGuides": "編輯器縮排輔助線的色彩。", + "editorActiveIndentGuide": "使用中編輯器縮排輔助線的色彩。", "editorLineNumbers": "編輯器行號的色彩。", "editorActiveLineNumber": "編輯器使用中行號的色彩 ", + "deprecatedEditorActiveLineNumber": "Id 已取代。請改用 'editorLineNumber.activeForeground' 。", "editorRuler": "編輯器尺規的色彩", "editorCodeLensForeground": "編輯器程式碼濾鏡的前景色彩", "editorBracketMatchBackground": "成對括號背景色彩", @@ -28,7 +30,9 @@ "warningBorder": "編輯器內警告提示線的邊框色彩.", "infoForeground": "編輯器內資訊提示線的前景色彩", "infoBorder": "編輯器內資訊提示線的邊框色彩", - "overviewRulerRangeHighlight": "範圍醒目提示的概觀尺規標記色彩。", + "hintForeground": "編輯器內提示訊息的提示線前景色彩", + "hintBorder": "編輯器內提示訊息的提示線邊框色彩", + "overviewRulerRangeHighlight": "概述反白範圍的尺規標記顏色。不能使用非透明的顏色來隱藏底層的樣式。", "overviewRuleError": "錯誤的概觀尺規標記色彩。", "overviewRuleWarning": "警示的概觀尺規標記色彩。", "overviewRuleInfo": "資訊的概觀尺規標記色彩。" diff --git a/i18n/cht/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/cht/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..aa47b7bc82 --- /dev/null +++ b/i18n/cht/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "顯示修正 ({0})", + "quickFix": "顯示修正", + "quickfix.trigger.label": "快速修復...", + "editor.action.quickFix.noneMessage": "沒有可用的程式碼操作", + "refactor.label": "重構...", + "editor.action.refactor.noneMessage": "沒有可用的重構", + "source.label": "來源動作...", + "editor.action.source.noneMessage": "沒有可用的來源動作", + "organizeImports.label": "組織匯入", + "editor.action.organize.noneMessage": "沒有任何可用的組織匯入動作" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/find/findController.i18n.json b/i18n/cht/src/vs/editor/contrib/find/findController.i18n.json index 6fea1b4355..ba61e1d453 100644 --- a/i18n/cht/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "尋找", + "startFindWithSelectionAction": "尋找選取項目", "findNextMatchAction": "尋找下一個", "findPreviousMatchAction": "尋找上一個", "nextSelectionMatchFindAction": "尋找下一個選取項目", diff --git a/i18n/cht/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/cht/src/vs/editor/contrib/format/formatActions.i18n.json index 15b53ec95a..725f95d449 100644 --- a/i18n/cht/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "在行 {1} 與行 {2} 之間編輯了 {0} 項格式", "no.provider": "尚無安裝適用於 '{0}' 檔案的格式器", "formatDocument.label": "將文件格式化", - "formatSelection.label": "將選取項目格式化" + "no.documentprovider": "未安裝 '{0}' 檔案的文件格式器。", + "formatSelection.label": "將選取項目格式化", + "no.selectionprovider": "未安裝 '{0}' 檔案的選擇格式器。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 285050b707..16f57c4919 100644 --- a/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "移至下一個問題 (錯誤, 警告, 資訊)", - "markerAction.previous.label": "移至上一個問題 (錯誤, 警告, 資訊)", - "editorMarkerNavigationError": "編輯器標記導覽小工具錯誤的色彩。", - "editorMarkerNavigationWarning": "編輯器標記導覽小工具警告的色彩。", - "editorMarkerNavigationInfo": "編輯器標記導覽小工具資訊的色彩", - "editorMarkerNavigationBackground": "編輯器標記導覽小工具的背景。" + "markerAction.previous.label": "移至上一個問題 (錯誤, 警告, 資訊)" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/cht/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..11b5e18ff6 --- /dev/null +++ b/i18n/cht/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "編輯器標記導覽小工具錯誤的色彩。", + "editorMarkerNavigationWarning": "編輯器標記導覽小工具警告的色彩。", + "editorMarkerNavigationInfo": "編輯器標記導覽小工具資訊的色彩", + "editorMarkerNavigationBackground": "編輯器標記導覽小工具的背景。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/links/links.i18n.json b/i18n/cht/src/vs/editor/contrib/links/links.i18n.json index ab6d3e2e78..376be6cd74 100644 --- a/i18n/cht/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "按住 Ctrl 並按一下滑鼠按鈕可連入連結", "links.command.mac": "按住 Cmd 並按一下滑鼠以執行命令", "links.command": "按住 Ctrl 並按一下滑鼠以執行命令", + "links.navigate.al.mac": "按住 Option 並按一下滑鼠按鈕以追蹤連結", "links.navigate.al": "按住Alt並點擊以追蹤連結", + "links.command.al.mac": "按住 Option 並按一下滑鼠以執行命令", "links.command.al": "按住 Alt 並按一下滑鼠以執行命令", "invalid.url": "因為此連結的格式不正確,所以無法開啟: {0}", "missing.url": "因為此連結目標遺失,所以無法開啟。", diff --git a/i18n/cht/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/cht/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..f6fa676ddd --- /dev/null +++ b/i18n/cht/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "無法在唯讀編輯器中編輯" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/cht/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index bff13aae3b..dbd4764fdb 100644 --- a/i18n/cht/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "預覽檢視編輯器的背景色彩。", "peekViewEditorGutterBackground": "預覽檢視編輯器邊框(含行號或字形圖示)的背景色彩。", "peekViewResultsMatchHighlight": "在預覽檢視編輯器中比對時的反白顯示色彩。", - "peekViewEditorMatchHighlight": "預覽檢視編輯器中比對時的反白顯示色彩。" + "peekViewEditorMatchHighlight": "預覽檢視編輯器中比對時的反白顯示色彩。", + "peekViewEditorMatchHighlightBorder": "在預覽檢視編輯器中比對時的反白顯示邊界。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/cht/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..54de5e0d2d --- /dev/null +++ b/i18n/cht/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "星期日", + "Monday": "星期一", + "Tuesday": "星期二", + "Wednesday": "星期三", + "Thursday": "星期四", + "Friday": "星期五", + "Saturday": "星期六", + "SundayShort": "週日", + "MondayShort": "週一", + "TuesdayShort": "週二", + "WednesdayShort": "週三", + "ThursdayShort": "週四", + "FridayShort": "週五", + "SaturdayShort": "週六", + "January": "1月", + "February": "2月", + "March": "3月", + "April": "4月", + "May": "5月", + "June": "6月", + "July": "7月", + "August": "8月", + "September": "9月", + "October": "10月", + "November": "11月", + "December": "12月", + "JanuaryShort": "1月", + "FebruaryShort": "2月", + "MarchShort": "3月", + "AprilShort": "4月", + "MayShort": "5月", + "JuneShort": "6月", + "JulyShort": "7月", + "AugustShort": "8月", + "SeptemberShort": "9月", + "OctoberShort": "10月", + "NovemberShort": "11月", + "DecemberShort": "12月" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 5538177f11..4ecccc9925 100644 --- a/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "寫入存取符號時的背景顏色,如寫入變數。不能使用非透明的顏色來隱藏底層的樣式。", "wordHighlightBorder": "讀取存取期間 (例如讀取變數時) 符號的邊框顏色。", "wordHighlightStrongBorder": "寫入存取期間 (例如寫入變數時) 符號的邊框顏色。 ", - "overviewRulerWordHighlightForeground": "符號醒目提示的概觀尺規標記色彩。", - "overviewRulerWordHighlightStrongForeground": "寫入權限符號醒目提示的概觀尺規標記色彩。", + "overviewRulerWordHighlightForeground": "概述反白符號的尺規標記顏色。不能使用非透明的顏色來隱藏底層的樣式。", + "overviewRulerWordHighlightStrongForeground": "概述反白寫入權限符號的尺規標記顏色。不能使用非透明的顏色來隱藏底層的樣式。", "wordHighlight.next.label": "移至下一個反白符號", "wordHighlight.previous.label": "移至上一個反白符號" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/cht/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..3b2a2f318b --- /dev/null +++ b/i18n/cht/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...另外 1 個檔案未顯示", + "moreFiles": "...另外 {0} 個檔案未顯示" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/cht/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..7667b94159 --- /dev/null +++ b/i18n/cht/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "取消" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/environment/node/argv.i18n.json b/i18n/cht/src/vs/platform/environment/node/argv.i18n.json index 31f5354ae0..1f5c084a5d 100644 --- a/i18n/cht/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/cht/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "使用 --list-extension 時,顯示安裝的擴充功能版本。", "installExtension": "安裝擴充功能。", "uninstallExtension": "解除安裝擴充功能。", - "experimentalApis": "為延伸模組啟用建議的 API 功能。", + "experimentalApis": "啟用延伸模組的建議 API 功能。", "verbose": "列印詳細資訊輸出 (表示 --wait)。", "log": "使用的日誌級別。預設為\"訊息\"。允許的值是 \"關鍵\"、\"錯誤\"、\"警告\"、\"訊息\"、\"偵錯\"、\"追蹤\"、\"關閉\"。", "status": "列印進程使用方式和診斷資訊。", "performance": "在已啟用 'Developer: Startup Performance' 命令的情況下開始。", "prof-startup": "啟動時執行 CPU 分析工具", "disableExtensions": "停用所有已安裝的擴充功能。", - "inspect-extensions": "允許對擴充功能進行除錯和分析。檢查開發工具的連接 uri。", - "inspect-brk-extensions": "允許對擴展主機在啟動後暫停擴充功能進行除錯和分析。檢查開發工具中的連接 uri。", + "inspect-extensions": "允許延伸模組的偵錯與分析。如需連線 URI,請查看開發人員工具。", + "inspect-brk-extensions": "允許對延伸主機在啟動後暫停擴充功能進行偵錯和分析。如需連線 URI,請查看開發人員工具。", "disableGPU": "停用 GPU 硬體加速。", "uploadLogs": "上傳目前的工作階段紀錄至安全的端點。", "maxMemory": "視窗的最大記憶體大小 (以 MB 為單位)。", diff --git a/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index b3ea596adb..e135a1089b 100644 --- a/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "擴充功能無效: package.json 不是 JSON 檔案。", + "incompatible": "因為延伸模組 '{0}' 與程式碼 '{1}' 不相容,所以無法安裝。", "restartCode": "請先重新啟動 Code,再重新安裝 {0}。", "installingOutdatedExtension": "已安裝此擴充功能的較新版本。是否要使用舊版本覆蓋此項?", "override": "覆寫", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "安裝相依套件時發生錯誤。{0}", "MarketPlaceDisabled": "未啟用市集", "removeError": "移除擴充功能: {0} 時發生錯誤。重新嘗試前請離開並再次啟動 VS Code。", - "Not Market place extension": "只有市集擴充功能可以重新安裝", + "Not a Marketplace extension": "只有市集擴充功能可以重新安裝", "notFoundCompatible": "無法安裝 '{0}';沒有任何與 VS Code 相容的可用版本 '{1}'。", "malicious extension": "因為有使用者回報該延伸模組有問題,所以無法安裝延伸模組。", "notFoundCompatibleDependency": "無法安裝,因為找不到相容於 VS Code 目前版本 '{1}' 的相依擴充功能 '{0}'。", "quitCode": "無法安裝擴充功能。重新安裝以前請重啟 VS Code。", "exitCode": "無法安裝擴充功能。重新安裝以前請離開並再次啟動 VS Code。", + "renameError": "將 {0} 重新命名為 {1} 時發生未知錯誤", "uninstallDependeciesConfirmation": "只要將 '{0}' 解除安裝,或要包含其相依性?", - "uninstallOnly": "只有", - "uninstallAll": "全部", + "uninstallOnly": "僅擴充功能", + "uninstallAll": "全部解除安裝", "uninstallConfirmation": "確定要將 '{0}' 解除安裝嗎?", "ok": "確定", "singleDependentError": "無法將延伸模組 '{0}' 解除安裝。其為延伸模組 '{1}' 的相依對象。", diff --git a/i18n/cht/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/cht/src/vs/platform/extensions/node/extensionValidator.i18n.json index bee11c7e18..6dea610799 100644 --- a/i18n/cht/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/cht/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "無法剖析 'engines.vscode` 值 {0}。例如,請使用:^0.10.0、^1.2.3、^0.11.0、^0.10.x 等。", + "versionSyntax": "無法解析 'engines.vscode` 值 {0}。請使用範例:^1.22.0, ^1.22.x, 等。", "versionSpecificity1": "在 `engines.vscode` ({0}) 中指定的版本不夠具體。對於 1.0.0 之前的 vscode 版本,請至少定義所需的主要和次要版本。 例如 ^0.10.0、0.10.x、0.11.0 等。", "versionSpecificity2": "在 `engines.vscode` ({0}) 中指定的版本不夠具體。對於 1.0.0 之後的 vscode 版本,請至少定義所需的主要和次要版本。 例如 ^1.10.0、1.10.x、1.x.x、2.x.x 等。", "versionMismatch": "擴充功能與 Code {0} 不相容。擴充功能需要: {1}。" diff --git a/i18n/cht/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/cht/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 1498481ab4..8fd524bcce 100644 --- a/i18n/cht/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/cht/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "您的 {0} 安裝似乎已損毀。請重新安裝。", "integrity.moreInformation": "詳細資訊", - "integrity.dontShowAgain": "不要再顯示", - "integrity.prompt": "您的 {0} 安裝似乎已損毀。請重新安裝。" + "integrity.dontShowAgain": "不要再顯示" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/cht/src/vs/platform/issue/electron-main/issueService.i18n.json index d7364c9e2c..771c06df62 100644 --- a/i18n/cht/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/cht/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "問題回報程式" + "issueReporter": "問題回報程式", + "processExplorer": "處理序總管" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/list/browser/listService.i18n.json b/i18n/cht/src/vs/platform/list/browser/listService.i18n.json index 41812d6970..5a072c5812 100644 --- a/i18n/cht/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/cht/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "透過滑鼠多選,用於在樹狀目錄與清單中新增項目的輔助按鍵 (例如在總管中開啟 [編輯器] 及 [SCM] 檢視)。在 Windows 及 Linux 上,`ctrlCmd` 對應 `Control`,在 macOS 上則對應 `Command`。[在側邊開啟] 滑鼠手勢 (若支援) 將會適應以避免和多選輔助按鍵衝突。", "openMode.singleClick": "以滑鼠按一下開啟項目。", "openMode.doubleClick": "以滑鼠按兩下開啟項目。", - "openModeModifier": "控制如何使用滑鼠在樹狀目錄與清單中開啟項目 (若有支援)。設為 `singleClick` 可以滑鼠按一下開啟物件,設為 `doubleClick` 則只能透過按兩下滑鼠開啟物件。對於樹狀目錄中具子系的父系而言,此設定會控制應以滑鼠按一下或按兩下展開父系。注意,某些樹狀目錄或清單若不適用此設定則會予以忽略。" + "openModeModifier": "控制如何使用滑鼠在樹狀目錄與清單中開啟項目 (若有支援)。設為 `singleClick` 可以滑鼠按一下開啟物件,設為 `doubleClick` 則只能透過按兩下滑鼠開啟物件。對於樹狀目錄中具子系的父系而言,此設定會控制應以滑鼠按一下或按兩下展開父系。注意,某些樹狀目錄或清單若不適用此設定則會予以忽略。", + "horizontalScrolling setting": "控制是否支援工作台中的水平滾動。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/markers/common/markers.i18n.json b/i18n/cht/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..cd4eb5c86c --- /dev/null +++ b/i18n/cht/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "錯誤", + "sev.warning": "警告", + "sev.info": "資訊" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json index 8531b24390..0f68abf509 100644 --- a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "文字輸入替代字符的前景顏色。", "inputValidationInfoBackground": "資訊嚴重性的輸入驗證背景色彩。", "inputValidationInfoBorder": "資訊嚴重性的輸入驗證邊界色彩。", - "inputValidationWarningBackground": "資訊警告的輸入驗證背景色彩。", + "inputValidationWarningBackground": "警告嚴重性的輸入驗證背景色彩。", "inputValidationWarningBorder": "警告嚴重性的輸入驗證邊界色彩。", "inputValidationErrorBackground": "錯誤嚴重性的輸入驗證背景色彩。", "inputValidationErrorBorder": "錯誤嚴重性的輸入驗證邊界色彩。", @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "選取時,內容相同之區域的框線色彩。", "editorFindMatch": "符合目前搜尋的色彩。", "findMatchHighlight": "符合搜尋條件的其他項目的顏色。不能使用非透明的顏色來隱藏底層的樣式。", - "findRangeHighlight": "為限制搜索的範圍著色。不能使用非透明的顏色來隱藏底層的樣式。", + "findRangeHighlight": "限制搜索的範圍色彩。不能使用非透明的色彩來隱藏基礎樣式。", "editorFindMatchBorder": "符合目前搜尋的框線色彩。", "findMatchHighlightBorder": "符合其他搜尋的框線色彩。", - "findRangeHighlightBorder": "限制搜尋範圍的邊框顏色。不能使用非透明的顏色來隱藏底層的樣式。", + "findRangeHighlightBorder": "限制搜尋範圍的邊框色彩。不能使用非透明的色彩來隱藏基礎樣式。", "hoverHighlight": "突顯懸停顯示的文字。不能使用非透明的顏色來隱藏底層的樣式。", "hoverBackground": "編輯器動態顯示的背景色彩。", "hoverBorder": "編輯器動態顯示的框線色彩。", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "傳入內嵌合併衝突中的深色標題背景。不能使用非透明的顏色來隱藏底層的樣式。", "mergeIncomingContentBackground": "傳入內嵌合併衝突中的內容背景。不能使用非透明的顏色來隱藏底層的樣式。", "mergeCommonHeaderBackground": "內嵌合併衝突中的共同始祖標題背景。不能使用非透明的顏色來隱藏底層的樣式。", - "mergeCommonContentBackground": "內嵌合併衝突中的共同始祖內容背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeCommonContentBackground": "內嵌合併衝突中的共同始祖內容背景。不能使用非透明的顏色來隱藏基礎樣式。", "mergeBorder": "內嵌合併衝突中標頭及分隔器的邊界色彩。", "overviewRulerCurrentContentForeground": "目前內嵌合併衝突的概觀尺規前景。", "overviewRulerIncomingContentForeground": "傳入內嵌合併衝突的概觀尺規前景。", "overviewRulerCommonContentForeground": "內嵌合併衝突中的共同上階概觀尺規前景。", - "overviewRulerFindMatchForeground": "尋找比對的概觀尺規標記色彩。", - "overviewRulerSelectionHighlightForeground": "選取項目醒目提示的概觀尺規標記色彩。" + "overviewRulerFindMatchForeground": "概述符合尋找條件的尺規標記顏色。不能使用非透明的顏色來隱藏底層的樣式。", + "overviewRulerSelectionHighlightForeground": "概述反白選擇的尺規標記顏色。不能使用非透明的顏色來隱藏底層的樣式。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/cht/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..71406e9116 --- /dev/null +++ b/i18n/cht/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "要允許 {0} 延伸模組開啟下列 URL 嗎?" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/cht/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..768c89868b --- /dev/null +++ b/i18n/cht/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "用於識別可透過使用 'views' 參與點參與檢視之容器的唯一識別碼", + "vscode.extension.contributes.views.containers.title": "用於轉譯容器的易讀字串", + "vscode.extension.contributes.views.containers.icon": "容器圖示的路徑。圖示為置於 50x40 正方形中央,且以 'rgb(215, 218, 224)' 或 '#d7dae0' 填滿顏色的 24x24 影像。雖然接受所有影像檔案類型,但建議使用 SVG 作為圖示格式。", + "vscode.extension.contributes.viewsContainers": "提供檢視容器給編輯者", + "views.container.activitybar": "提供檢視容器給活動列", + "test": "測試", + "proposed": "只有在 dev 不足,或使用下列命令列參數時才能使用 'viewsContainers' 參與: --enable-proposed-api {0}。", + "requirearray": "檢視容器必須為陣列", + "requireidstring": "屬性 ‵{0}` 為必要項且必須為類型 `string`。僅允許英數字元字母、'_'、'-'。", + "requirestring": "屬性 '{0}' 為強制項目且必須屬於 `string` 類型", + "showViewlet": "顯示 {0}", + "view": "檢視" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/cht/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index daf6bcabc8..58c3480e12 100644 --- a/i18n/cht/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/cht/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "使用人性化顯示名稱.", "vscode.extension.contributes.view.when": "必須為 true 以顯示此檢視的條件", "vscode.extension.contributes.views": "提供意見給編輯者", - "views.explorer": "檔案總管檢視", - "views.debug": "偵錯檢視", - "locationId.invalid": "`{0}`不是有效的識別位置", + "views.explorer": "提供檢視給活動列中的總管容器", + "views.debug": "提供檢視給活動列中的偵錯容器", + "views.scm": "提供檢視給活動列中的 SCM 容器", + "views.test": "提供檢視給活動列中的測試容器", + "views.contributed": "提供檢視給參與檢視容器", + "ViewContainerDoesnotExist": "檢視容器 '{0}' 不存在,且所有向其註冊的檢視都會新增至 'Explorer'。", "duplicateView1": "無法在位置 '{1}' 使用相同的識別碼 '{0}' 註冊多個檢視", "duplicateView2": "識別碼為 '{0}' 的檢視已在位置 '{1}' 註冊" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index a9f7a1f381..c639e41ab3 100644 --- a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "在 {0} 毫秒後儲存時中止格式", + "codeActionsOnSave.didTimeout": "在 {0} 毫秒後中止了 codeActionsOnSave", + "timeout.onWillSave": "在 1750 亳秒後中止 onWillSaveTextDocument 事件", "saveParticipants": "執行儲存參與者..." } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 0c243333d5..d4f84057ce 100644 --- a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "webview 編輯器" + "errorMessage": "還原 view:{0} 時發生錯誤" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/cht/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..950340ccaf --- /dev/null +++ b/i18n/cht/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (延伸模組)" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index fdd001a2f0..4fa4597d66 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "聚焦下一個群組", "openToSide": "開至側邊", "closeEditor": "關閉編輯器", + "closeOneEditor": "關閉", "revertAndCloseActiveEditor": "還原並關閉編輯器", "closeEditorsToTheLeft": "將編輯器關到左側", "closeAllEditors": "關閉所有編輯器", diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 3254e563bd..b505ac5006 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "若您不打算使用螢幕助讀程式,請將設定 `editor.accessibilitySupport` 變更為 \"off\"。", "disableTabMode": "停用協助工具模式", "gotoLine": "移至行", - "indentation": "縮排", + "selectIndentation": "選擇縮排", "selectEncoding": "選取編碼", "selectEOL": "選取行尾順序", "selectLanguageMode": "選取語言模式", diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 8574984a5a..95d4596319 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0}MB", "sizeGB": "{0}GB", "sizeTB": "{0}TB", - "largeImageError": "影像的檔案大小太大 (>1MB),無法在編輯器中顯示。", + "largeImageError": "因為影像太大,所以未在編輯器中顯示 ({0})。", "resourceOpenExternalButton": "要使用外部程式打開影像嗎?", - "nativeBinaryError": "檔案為二進位檔、非常大或使用不支援的文字編碼,因此將不會顯示於編輯器中。", + "nativeFileTooLargeError": "因為檔案太大,所以未在編輯器中顯示 ({0})。", + "nativeBinaryError": "因為檔案為二進位檔或使用了不支援的文字編碼,所以未在編輯器中顯示。", + "openAsText": "是否確定要開啟?", "zoom.action.fit.label": "整個影像", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index b3953b6671..738e3788ff 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "關閉", "araLabelEditorActions": "編輯器動作" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index f69bd5e06f..3c0dc76f18 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "尚無新通知", "notifications": "通知", "notificationsToolbar": "通知中心動作", "notificationsList": "通知列表" diff --git a/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..34f0faed81 --- /dev/null +++ b/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (按 'Enter' 鍵確認或按 'Esc' 鍵取消)", + "inputModeEntry": "按 'Enter' 鍵確認您的輸入或按 'Esc' 鍵取消", + "quickInput.countSelected": "已選擇 {0}", + "ok": "確定" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..28e300993c --- /dev/null +++ b/i18n/cht/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "輸入以縮小結果範圍。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json index db9a68652b..04680479ab 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "開啟最近使用的檔案...", "quickOpenRecent": "快速開啟最近使用的檔案...", "reportIssueInEnglish": "回報問題", + "openProcessExplorer": "開啟處理序總管", "reportPerformanceIssue": "回報效能問題", "keybindingsReference": "鍵盤快速鍵參考", "openDocumentationUrl": "文件", diff --git a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json index bd4578eed8..16c6d8fd46 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "視窗", "window.openFilesInNewWindow.on": "檔案會在新視窗中開啟", "window.openFilesInNewWindow.off": "檔案會在開啟了檔案資料夾的視窗,或在上一個使用中的視窗中開啟", - "window.openFilesInNewWindow.default": "除非從擴充座或 Finder 中開啟,否則檔案會在開啟了檔案資料夾的視窗,或在上一個使用中的視窗中開啟 (僅限 macOS)", - "openFilesInNewWindow": "控制檔案是否應在新視窗中開啟。\n- default: 檔案會在視窗中隨檔案的資料夾開啟或在上一個使用中視窗開啟,除非透過擴充座或從尋找工具開啟 (僅限 macOS)\n- on: 檔案會在新視窗開啟\n- off: 檔案會在視窗中隨檔案的資料夾開啟或在上一個使用中視窗開啟\n請注意,在某些情況下會略過此設定 (例如,使用了 -new-window 或 -reuse-window 命令列選項時)。", + "window.openFilesInNewWindow.defaultMac": "除非從擴充座或 Finder 中開啟,否則檔案會在開啟了檔案資料夾的視窗,或在上一個使用中的視窗中開啟", + "window.openFilesInNewWindow.default": "除非已從應用程式內挑選 (例如透過 [檔案] 功能表),否則檔案會在新視窗中開啟", + "openFilesInNewWindowMac": "控制檔案是否應在新視窗中開啟。\n- default: 檔案會在視窗中隨檔案的資料夾開啟或在上一個使用中視窗開啟,除非透過擴充座或從尋找工具開啟\n- on: 檔案會在新視窗開啟\n- off: 檔案會在視窗中隨檔案的資料夾開啟或在上一個使用中視窗開啟\n請注意,在某些情況下會略過此設定 (例如,使用了 -new-window 或 -reuse-window 命令列選項時)。", + "openFilesInNewWindow": "控制是否在新視窗中打開檔案。\n- default: 檔案會在新視窗中開啟,除非從應用程式中選擇 (例如透過 \"檔案\" 功能表)\n- on: 檔案會在新視窗中開啟\n- off: 檔案會在視窗中隨檔案的資料夾開啟或在上一個使用中視窗開啟\n請注意,在某些情況下會略過此設定 (例如,使用 the -new-window 或 -reuse-window 命令列選項時)。", "window.openFoldersInNewWindow.on": "資料夾會在新視窗中開啟", "window.openFoldersInNewWindow.off": "資料夾會取代上一個使用中的視窗", "window.openFoldersInNewWindow.default": "除非已從應用程式內挑選了資料夾 (例如透過 [檔案] 功能表),否則資料夾會在新視窗中開啟", "openFoldersInNewWindow": "控制資料夾應在新視窗中開啟或取代上一個使用中的視窗。\n- default: 除非已從應用程式內挑選資料夾 (例如,透過 [檔案] 功能表),否則會在新視窗開啟\n- on: 資料夾會在新視窗開啟\n- off: 資料夾會取代上一個使用中視窗\n請注意,在某些情況下會略過此設定 (例如,使用了 -new-window 或 -reuse-window 命令列選項時)。", + "window.openWithoutArgumentsInNewWindow.on": "開啟新空白視窗", + "window.openWithoutArgumentsInNewWindow.off": "聚焦在上一個正在運行的執行個體", + "openWithoutArgumentsInNewWindow": "控制不以引數啟動第二個執行個體時是否要開啟新的空白視窗,或是應聚焦於上一個執行的執行個體。\n- on: 開啟新的空白視窗\n- off: 上一個使用中的執行中執行個體將會受到聚焦\n請注意:仍可能發生忽略此設定的情形 (例如,在使用 -new-window 或 -reuse-window 命令列選項時)。", "window.reopenFolders.all": "重新開啟所有視窗。", "window.reopenFolders.folders": "重新開啟所有資料夾。空白工作區將不會還原。", "window.reopenFolders.one": "重新開啟上一個使用中的視窗。", @@ -58,7 +63,7 @@ "restoreWindows": "控制重新啟動後視窗重新開啟的方式。選取 [無] 一律以空白工作區開始、選取 [一] 從上一個編輯的視窗重新開啟、選取 [資料夾] 重新開啟所有資料夾曾經開啟的視窗,或選取 [全部] 重新開啟上一個工作階段的所有視窗。", "restoreFullscreen": "控制當視窗在全螢幕模式下結束後,下次是否仍以全螢幕模式開啟。", "zoomLevel": "調整視窗的縮放比例。原始大小為 0,而且每個向上增量 (例如 1) 或向下增量 (例如 -1) 代表放大或縮小 20%。您也可以輸入小數,更細微地調整縮放比例。", - "title": "依據使用中的編輯器控制視窗標題。變數會依據內容替換:\n${activeEditorShort}: 檔案名稱 (例如 myFile.txt)\n${activeEditorMedium}: 與工作區資料夾相關的檔案路徑 (例如 myFolder/myFile.txt)\n${activeEditorLong}: 完整的檔案路徑 (例如 /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 包含著資料夾之工作區資料夾的名稱 (例如 myFolder)\n${folderPath}: 包含著資料夾之工作區資料夾的檔案路徑 (例如 /Users/Development/myFolder)\n${rootName}: 工作區的名稱 (例如 myFolder 或 myWorkspace)\n${rootPath}: 工作區的檔案路徑 (例如 /Users/Development/myWorkspace)\n${appName}: 例如 VS Code\n${dirty}: 已變更指示 (若使用中編輯器已變更)\n${separator}: 僅在受具有值之變數括住時才顯示的條件式分隔符號 (\" - \")", + "title": "依據使用中的編輯器控制視窗標題。變數會依據內容替換:\n${activeEditorShort}: 檔案名稱 (例如 myFile.txt)\n${activeEditorMedium}: 與工作區資料夾相關的檔案路徑 (例如 myFolder/myFile.txt)\n${activeEditorLong}: 完整的檔案路徑 (例如 /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 包含著資料夾之工作區資料夾的名稱 (例如 myFolder)\n${folderPath}: 包含著資料夾之工作區資料夾的檔案路徑 (例如 /Users/Development/myFolder)\n${rootName}: 工作區的名稱 (例如 myFolder 或 myWorkspace)\n${rootPath}: 工作區的檔案路徑 (例如 /Users/Development/myWorkspace)\n${appName}: 例如 VS Code\n${dirty}: 已變更指示 (若使用中編輯器已變更)\n${separator}: 僅在受具有值或靜態文字之變數括住時才顯示的條件式分隔符號 (\" - \")", "window.newWindowDimensions.default": "在螢幕中央開啟新視窗。", "window.newWindowDimensions.inherit": "以相同於上一個使用中之視窗的維度開啟新視窗。", "window.newWindowDimensions.maximized": "開啟並最大化新視窗。", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "若啟用,如果 Windows 使用高對比佈景主題,就會自動變更為高對比佈景主題,切換掉 Windows 高對比佈景主題時則變更為深色佈景主題。", "titleBarStyle": "調整視窗標題列的外觀。變更需要完整重新啟動才會套用。", "window.nativeTabs": "啟用 macOS Sierra 視窗索引標籤。請注意需要完全重新啟動才能套用變更,並且完成設定後原始索引標籤將會停用自訂標題列樣式。", + "window.smoothScrollingWorkaround": "在還原最小化的 VS Code 視窗後,若捲動功能不再流暢,請啟用此因應措施。此因應措施適用於 Microsoft Surface 等具備精確軌跡板發生的捲動延遲問題 (https://github.com/Microsoft/vscode/issues/13612)。啟用此因應措施可能會在將視窗從最小化狀態還原後,導致版面稍微閃爍,但並不會造成任何傷害。", + "window.clickThroughInactive": "若已啟用,按一下非使用中的視窗將會啟動該視窗並觸發其下的元素 (如果可以案的話)。若已停用,按一下非使用中視窗的任一處則只會啟動該視窗,必須再按一下才會觸發元素。", "zenModeConfigurationTitle": "Zen Mode", "zenMode.fullScreen": "控制開啟 Zen Mode 是否也會將 Workbench 轉換為全螢幕模式。", "zenMode.centerLayout": "控制開啟 Zen Mode 是否也會置中配置。", diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 20119c6f4e..f530311b39 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "編輯中斷點...", + "logPoint": "記錄點", + "breakpoint": "中斷點", + "editBreakpoint": "編輯 {0}...", + "removeBreakpoint": "移除 {0}", "functionBreakpointsNotSupported": "此偵錯類型不支援函式中斷點", "functionBreakpointPlaceholder": "要中斷的函式", "functionBreakPointInputAriaLabel": "輸入函式中斷點", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "未驗證的中斷點", "functionBreakpointUnsupported": "此偵錯類型不支援函式中斷點", "breakpointDirtydHover": "未驗證的中斷點。檔案已修改,請重新啟動偵錯工作階段。", + "logBreakpointUnsupported": "此偵錯類型不支援記錄點", "conditionalBreakpointUnsupported": "此偵錯類型不支援的條件式中斷點", "hitBreakpointUnsupported": "此偵錯類型不支援點擊條件式中斷點" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 2d26e85949..db1f1ef117 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "中斷連接", "continueDebug": "繼續", "pauseDebug": "暫停", + "terminateThread": "終止執行緒", "restartFrame": "重新啟動框架", "removeBreakpoint": "移除中斷點", "removeAllBreakpoints": "移除所有中斷點", - "enableBreakpoint": "啟用中斷點", - "disableBreakpoint": "停用中斷點", "enableAllBreakpoints": "啟用所有中斷點", "disableAllBreakpoints": "停用所有中斷點", "activateBreakpoints": "啟動中斷點", "deactivateBreakpoints": "停用中斷點", "reapplyAllBreakpoints": "重新套用所有中斷點", "addFunctionBreakpoint": "加入函式中斷點", - "addConditionalBreakpoint": "新增條件中斷點...", - "editConditionalBreakpoint": "編輯中斷點...", "setValue": "設定值", "addWatchExpression": "加入運算式", "editWatchExpression": "編輯運算式", diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index ec38515957..851e8cb449 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "偵錯: 切換中斷點", "conditionalBreakpointEditorAction": "偵錯: 新增條件中斷點...", + "logPointEditorAction": "偵錯: 新增記錄點...", "runToCursor": "執行至游標處", "debugEvaluate": "偵錯: 評估", "debugAddToWatch": "偵錯: 加入監看", diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..9c6da9e6ef --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "當命中中斷點時向記錄傳送訊息。會以內插值取代 {} 中的運算式。按一下 'Enter' 接受,或是按 'esc' 取消。", + "breakpointWidgetHitCountPlaceholder": "符合叫用次數條件時中斷。按 'Enter' 鍵接受,按 'esc' 鍵取消。", + "breakpointWidgetExpressionPlaceholder": "在運算式評估為 true 時中斷。按 'Enter' 鍵接受,按 'esc' 鍵取消。", + "expression": "運算式", + "hitCount": "叫用次數", + "logMessage": "日誌訊息" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index e74ccd2361..54953a0ca1 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "請使用唯一的組態名稱。", "app.launch.json.compound.folder": "複合所在的資料夾名稱。", "app.launch.json.compounds.configurations": "將會作為此複合一部份而啟動之組態的名稱。", - "debugNoType": "偵錯配接器 'type' 不能省略且必須屬於 'string' 類型。", + "debugNoType": "偵錯器 'type' 無法省略,且必須為類型 'string'。", "selectDebug": "選取環境", "DebugConfig.failed": "無法在 '.vscode' 資料夾 ({0}) 中建立 'launch.json' 檔案。", "workspace": "工作區", diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 51f7c6d2f6..40dc883128 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "記錄點", + "breakpoint": "中斷點", + "removeBreakpoint": "移除 {0}", + "editBreakpoint": "編輯 {0}...", + "disableBreakpoint": "停用 {0}", + "enableBreakpoint": "啟用 {0}", "removeBreakpoints": "移除中斷點", "removeBreakpointOnColumn": "移除資料行 {0} 的中斷點", "removeLineBreakpoint": "移除行中斷點", @@ -18,5 +24,13 @@ "enableBreakpoints": "啟用資料行 {0} 的中斷點", "enableBreakpointOnLine": "啟用行中斷點", "addBreakpoint": "加入中斷點", + "addConditionalBreakpoint": "新增條件中斷點...", + "addLogPoint": "新增記錄點...", + "breakpointHasCondition": "此 {0} 具有會在移除時消失的 {1}。請考慮改為停用 {0}。", + "message": "訊息", + "condition": "條件", + "removeLogPoint": "移除 {0}", + "disableLogPoint": "停用 {0}", + "cancel": "取消", "addConfiguration": "新增組態..." } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index c1e1269008..9415d467d3 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "顯示錯誤", "noFolderWorkspaceDebugError": "無法對使用中的檔案偵錯。請確認檔案已儲存在磁碟上,而且您已經為該檔案類型安裝偵錯延伸模組。", "cancel": "取消", - "DebugTaskNotFound": "找不到 preLaunchTask '{0}'。", - "taskNotTracked": "無法追蹤 preLaunchTask '{0}'。" + "DebugTaskNotFound": "找不到工作 \"{0}\"。", + "taskNotTracked": "無法追蹤工作 '{0}'。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index 1e68d841a7..927ddaab15 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "詳細資訊", - "unableToLaunchDebugAdapter": "無法從 '{0}' 啟動偵錯配接器。", - "unableToLaunchDebugAdapterNoArgs": "無法啟動偵錯配接器。", - "stoppingDebugAdapter": "{0}。正在停止偵錯配接器。", "debugAdapterCrash": "偵錯配接器處理序已意外終止" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 41e1df2363..b5b6f085fb 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "偵錯配接器可執行檔 '{0}' 不存在。", "debugAdapterCannotDetermineExecutable": "無法判斷偵錯配接器 '{0}' 的可執行檔。", - "launch.config.comment1": "使用 IntelliSense 以得知可用的屬性。", - "launch.config.comment2": "暫留以檢視現有屬性的描述。", - "launch.config.comment3": "如需詳細資訊,請瀏覽: {0}", - "debugType": "組態的類型。", - "debugTypeNotRecognised": "無法辨識此偵錯類型.請確認已有安裝並啟用相對應的偵錯擴充功能.", - "node2NotSupported": "\"node2\" 已不再支援,請改用 \"node\",並將 \"protocol\" 屬性設為 \"inspector\"。", - "debugName": "組態的名稱; 出現在啟動組態下拉式功能表中。", - "debugRequest": "要求組態的類型。可以是 [啟動] 或 [附加]。", - "debugServer": "僅限偵錯延伸模組開發: 如果指定了連接埠,VS Code 會嘗試連線至以伺服器模式執行的偵錯配接器", - "debugPrelaunchTask": "偵錯工作階段啟動前要執行的工作。", - "debugWindowsConfiguration": "Windows 特定的啟動設定屬性。", - "debugOSXConfiguration": "OS X 特定的啟動設定屬性。", - "debugLinuxConfiguration": "Linux 特定的啟動設定屬性。", - "deprecatedVariables": "'env.'、'config.' 及 'command.' 已標示為即將淘汰,請改用 'env:'、'config:' 及 'command:'。" + "unableToLaunchDebugAdapter": "無法從 '{0}' 啟動偵錯配接器。", + "unableToLaunchDebugAdapterNoArgs": "無法啟動偵錯配接器。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..49c1a7df76 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "使用 IntelliSense 以得知可用的屬性。", + "launch.config.comment2": "暫留以檢視現有屬性的描述。", + "launch.config.comment3": "如需詳細資訊,請瀏覽: {0}", + "debugType": "組態的類型。", + "debugTypeNotRecognised": "無法辨識此偵錯類型.請確認已有安裝並啟用相對應的偵錯擴充功能.", + "node2NotSupported": "\"node2\" 已不再支援,請改用 \"node\",並將 \"protocol\" 屬性設為 \"inspector\"。", + "debugName": "組態的名稱; 出現在啟動組態下拉式功能表中。", + "debugRequest": "要求組態的類型。可以是 [啟動] 或 [附加]。", + "debugServer": "僅限偵錯延伸模組開發: 如果指定了連接埠,VS Code 會嘗試連線至以伺服器模式執行的偵錯配接器", + "debugPrelaunchTask": "偵錯工作階段啟動前要執行的工作。", + "debugPostDebugTask": "偵錯工作階段結束後要執行的工作。", + "debugWindowsConfiguration": "Windows 特定的啟動設定屬性。", + "debugOSXConfiguration": "OS X 特定的啟動設定屬性。", + "debugLinuxConfiguration": "Linux 特定的啟動設定屬性。", + "deprecatedVariables": "'env.'、'config.' 及 'command.' 已標示為即將淘汰,請改用 'env:'、'config:' 及 'command:'。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..afdfcfb0e9 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code 主控台", + "mac.terminal.script.failed": "指令碼 '{0}' 失敗,結束代碼為 {1}", + "mac.terminal.type.not.supported": "不支援 '{0}'", + "press.any.key": "請按任意鍵繼續...", + "linux.term.failed": "'{0}' 失敗,結束代碼為 {1}" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/emmet/electron-browser/emmet.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/emmet/electron-browser/emmet.contribution.i18n.json index 5b4d67c215..ed9f96b876 100644 --- a/i18n/cht/src/vs/workbench/parts/emmet/electron-browser/emmet.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/emmet/electron-browser/emmet.contribution.i18n.json @@ -6,9 +6,9 @@ { "emmetConfigurationTitle": "Emmet", "triggerExpansionOnTab": "啟用時,按下 TAB 即可展開 Emmet 縮寫。當 emmet.useNewemmet 設定為 true 時不適用。", - "emmetPreferences": "用以修改部分 Emmet 動作及解析程式之行為的喜好設定。emmet.useNewemmet 設定為 ture 時不適用。", + "emmetPreferences": "用以修改部分 Emmet 動作及解析程式之行為的喜好設定。emmet.useNewemmet 設定為 true 時不適用。", "emmetSyntaxProfiles": "為指定的語法定義設定檔,或透過特定規則使用自己的設定檔。", "emmetExclude": "不應展開 Emmet 縮寫的語言陣列。", "emmetExtensionsPath": "包含 Emmet 設定檔、片段及喜好設定的資料夾路徑。emmet.useNewEmmet 設定為 true 時僅會從延伸模組路徑接受設定檔。", "useNewEmmet": "試試所有 Emmet 功能的新 Emmet 模組 (最終會取代舊的單一 Emmet 程式庫)。" -} \ No newline at end of file +} diff --git a/i18n/cht/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 98a1abe8d3..54e403dbd1 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "設定建議的延伸模組 (工作區資料夾) ", "malicious tooltip": "這個延伸模組曾經被回報是有問題的。", "malicious": "惡意", + "disabled": "停用", + "disabled globally": "停用", + "disabled workspace": "在此工作區停用", "disableAll": "停用所有已安裝的延伸模組", "disableAllWorkspace": "停用此工作區的所有已安裝延伸模組", "enableAll": "啟用所有擴充功能", diff --git a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..1a8774452e --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "延伸模組名稱", + "extension id": "延伸模組識別碼", + "preview": "預覽", + "builtin": "內建", + "publisher": "發行者名稱", + "install count": "安裝計數", + "rating": "評等", + "repository": "儲存庫", + "license": "授權", + "details": "詳細資料", + "contributions": "貢獻", + "changelog": "變更記錄", + "dependencies": "相依性", + "noReadme": "沒有可用的讀我檔案。", + "noChangelog": "沒有可用的 Changelog。", + "noContributions": "沒有比重", + "noDependencies": "沒有相依性", + "settings": "設定 ({0})", + "setting name": "名稱", + "description": "描述", + "default": "預設", + "debuggers": "偵錯工具 ({0})", + "debugger name": "名稱", + "debugger type": "型別", + "views": "瀏覽次數 ({0})", + "view id": "識別碼", + "view name": "名稱", + "view location": "位置", + "localizations": "當地語系化 ({0})", + "localizations language id": "語言識別碼", + "localizations language name": "語言名稱", + "localizations localized language name": "語言名稱 (已當地語系化)", + "colorThemes": "色彩佈景主題 ({0})", + "iconThemes": "圖示佈景主題 ({0}) ", + "colors": "色彩 ({0})", + "colorId": "識別碼", + "defaultDark": "預設深色", + "defaultLight": "預設淺色", + "defaultHC": "預設高對比", + "JSON Validation": "JSON 驗證 ({0})", + "fileMatch": "檔案相符", + "schema": "結構描述", + "commands": "命令 ({0})", + "command name": "名稱", + "keyboard shortcuts": "鍵盤快速鍵(&&K)", + "menuContexts": "功能表內容", + "languages": "語言 ({0})", + "language id": "識別碼", + "language name": "名稱", + "file extensions": "副檔名", + "grammar": "文法", + "snippets": "程式碼片段" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index b7cf40a3ed..c002c5e474 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "根據目前工作區的使用者,建議您使用此延伸模組。", "reallyRecommended2": "建議對此檔案類型使用 '{0}' 延伸模組。", "reallyRecommendedExtensionPack": "建議對此檔案類型使用 '{0}' 延伸模組套件。", - "showRecommendations": "顯示建議", "install": "安裝", + "showRecommendations": "顯示建議", "showLanguageExtensions": "市集有 '.{0}' 個文件的擴充功能可以提供協助", "workspaceRecommended": "此工作區具有擴充功能建議。", "installAll": "全部安裝", diff --git a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index c0de814ef5..7d052a4fb3 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "要停用其他按鍵對應 ({0}),以避免按鍵繫結關係間的衝突嗎?", "yes": "是", - "no": "否", - "betterMergeDisabled": "目前已內建 Better Merge 延伸模組,安裝的延伸模組已停用並且可以移除。", - "uninstall": "解除安裝" + "no": "否" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index 10601b9eff..f4cf96d562 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -12,7 +12,9 @@ "recommendedExtensions": " 推薦項目", "otherRecommendedExtensions": "其他建議", "workspaceRecommendedExtensions": "工作區建議", - "builtInExtensions": "內建", + "builtInExtensions": "功能", + "builtInThemesExtensions": "主題", + "builtInBasicsExtensions": "程式語言", "searchExtensions": "在 Marketplace 中搜尋擴充功能", "sort by installs": "排序依據: 安裝計數", "sort by rating": "排序依據: 評等", diff --git a/i18n/cht/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 67f9024374..82ec7a591e 100644 --- a/i18n/cht/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "文字檔編輯器", "createFile": "建立檔案", + "relaunchWithIncreasedMemoryLimit": "以 {0} MB 重新啟動", + "configureMemoryLimit": "設定記憶體限制", "fileEditorWithInputAriaLabel": "{0}。文字檔編輯器。", "fileEditorAriaLabel": "文字檔編輯器。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index fde4b12436..dc1fea562c 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "複製", "pasteFile": "貼上", "retry": "重試", + "renameWhenSourcePathIsParentOfTargetError": "請使用 'New Folder' 或 'New File' 命令將子系新增至現有的資料夾", "newUntitledFile": "新增未命名檔案", "createNewFile": "新增檔案", "createNewFolder": "新增資料夾", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "您要刪除的資料夾中 {0} 個檔案有未儲存的變更。要繼續嗎?", "dirtyMessageFileDelete": "您要刪除的檔案有未儲存的變更。要繼續嗎?", "dirtyWarning": "如果您不儲存變更,這些變更將會遺失。", - "confirmMoveTrashMessageMultiple": "確定要刪除以下 {0} 個檔案嗎?", - "confirmMoveTrashMessageFolder": "您確定要刪除 '{0}' 及其內容嗎?", - "confirmMoveTrashMessageFile": "您確定要刪除 '{0}' 嗎?", "undoBin": "您可以從資源回收筒還原。", "undoTrash": "您可以從垃圾筒還原。", "doNotAskAgain": "不要再詢問我", + "irreversible": "此動作無法回復!", + "binFailed": "無法使用資源回收筒刪除。您要改為永久刪除嗎? ", + "trashFailed": "無法使用垃圾筒刪除。您要改為永久刪除嗎?", + "deletePermanentlyButtonLabel": "永久刪除(&&D)", + "retryButtonLabel": "重試(&&R)", + "confirmMoveTrashMessageFilesAndDirectories": "確定要刪除下列 {0} 個檔案/目錄及其內容嗎?", + "confirmMoveTrashMessageMultipleDirectories": "確定要刪除下列 {0} 個目錄及其內容嗎?", + "confirmMoveTrashMessageMultiple": "確定要刪除以下 {0} 個檔案嗎?", + "confirmMoveTrashMessageFolder": "您確定要刪除 '{0}' 及其內容嗎?", + "confirmMoveTrashMessageFile": "您確定要刪除 '{0}' 嗎?", + "confirmDeleteMessageFilesAndDirectories": "確定要永久刪除下列 {0} 個檔案/目錄及其內容嗎?", + "confirmDeleteMessageMultipleDirectories": "確定要永久刪除下列 {0} 個目錄及其內容嗎?", "confirmDeleteMessageMultiple": "確定要永久地刪除以下 {0} 個檔案嗎?", "confirmDeleteMessageFolder": "您確定要永久刪除 '{0}' 和其中的內容嗎?", "confirmDeleteMessageFile": "您確定要永久刪除 '{0}' 嗎?", - "irreversible": "此動作無法回復!", - "cancel": "取消", - "permDelete": "永久刪除", - "importFiles": "匯入檔案", + "addFiles": "新增檔案", "confirmOverwrite": "目的資料夾中已有同名的檔案或資料夾。要取代它嗎?", "replaceButtonLabel": "取代(&&R)", "fileIsAncestor": "要貼上的檔案是在目地資料夾的上層 ", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "先開啟檔案以在新視窗中開啟", "copyPath": "複製路徑", "emptyFileNameError": "必須提供檔案或資料夾名稱。", + "fileNameStartsWithSlashError": "檔案或資料夾名稱不得以斜線開頭。", "fileNameExistsError": "這個位置已存在檔案或資料夾 **{0}**。請選擇不同的名稱。", + "fileUsedAsFolderError": "**{0}** 是檔案且不得擁有任何子系。", "invalidFileNameError": "名稱 **{0}** 不能作為檔案或資料夾名稱。請選擇不同的名稱。", "filePathTooLongError": "名稱 **{0}** 導致路徑太長。請選擇較短的名稱。", "compareWithClipboard": "比較使用中的檔案和剪貼簿的檔案", diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index bc7d0d4db2..f7499c51bd 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "控制是否讓不同工作階段記住未儲存的檔案,並允許在結束編輯器時跳過儲存提示。", "useExperimentalFileWatcher": "使用新的實驗性檔案監看員。", "defaultLanguage": "指派給新檔案的預設語言模式。", + "maxMemoryForLargeFilesMB": "控制 VS Code 在重新啟動後常是開啟大型檔案時,可使用多少記憶體。在命令列上指定 --max-memory=NEWSIZE 也能達到相同效果。", "editorConfigurationTitle": "編輯器", "formatOnSave": "在儲存時設定檔案格式。格式器必須處於可用狀態、檔案不得自動儲存,且編輯器不得關機。", + "formatOnSaveTimeout": "儲存時格式化超時。指定 formatOnSave 命令的時間限制 (以毫秒為單位)。超過指定超時時間的命令將被取消。", "explorerConfigurationTitle": "檔案總管", "openEditorsVisible": "[開放式編輯器] 窗格中顯示的編輯器數目。", "autoReveal": "控制總管是否在開啟檔案時自動加以顯示及選取。", diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index f15546251e..6747870c99 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -7,13 +7,17 @@ "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "輸入檔案名稱。請按 Enter 鍵確認或按 Esc 鍵取消。", - "constructedPath": "在 **{1}** 建立 {0}", + "createFileFromExplorerInfoMessage": "在 **{1}** 中建立檔案 **{0}**", + "renameFileFromExplorerInfoMessage": "移至 **{0}** 並重新命名", + "createFolderFromExplorerInfoMessage": "在 **{1}** 中建立資料夾 **{0}**", "filesExplorerViewerAriaLabel": "{0},檔案總管", "dropFolders": "要在工作區新增資料夾嗎?", "dropFolder": "要在工作區新增資料夾嗎?", "addFolders": "新增資料夾(&A)", "addFolder": "新增資料夾(&A)", + "confirmRootsMove": "您確定要變更工作區中多個根資料夾的順序嗎?", "confirmMultiMove": "確定要移動以下 {0} 個文件嗎?", + "confirmRootMove": "您確定要變更工作區中根資料夾 '{0}' 的順序嗎? ", "confirmMove": "確定要移動 '{0}' 嗎?", "doNotAskAgain": "不要再詢問我", "moveButtonLabel": "移動(&&M)", diff --git a/i18n/cht/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..b4173cd7e5 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "HTML 預覽" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/cht/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..99f3827f91 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "編輯器輸入無效。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..8e9c4235dc --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "開發人員" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/cht/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..da7857bbdc --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "開啟 Webview Developer 工具", + "refreshWebviewLabel": "重新載入 Webviews" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index ac98537dc7..f24c91e3cc 100644 --- a/i18n/cht/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "您想要變更 VS Code 的 UI 語言為 {0} 並重新啟動嗎?", + "yes": "是", + "no": "否", + "neverAgain": "不要再顯示", "JsonSchema.locale": "要使用的 UI 語言。", "vscode.extension.contributes.localizations": "提供在地化服務給編輯者", "vscode.extension.contributes.localizations.languageId": "顯示已翻譯字串的語言 Id", diff --git a/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..080a6cc9f3 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "您想要變更 VS Code 的 UI 語言為 {0} 並重新啟動嗎?", + "yes": "是", + "no": "否", + "neverAgain": "不要再顯示", + "install language pack": "在不久之後,VS Code 將只支援格式為 Marketplace 延伸模組的語言套件。請安裝 '{0}' 延伸模組已繼續使用目前設定的語言。", + "install": "安裝", + "more information": "詳細資訊...", + "JsonSchema.locale": "要使用的 UI 語言。", + "vscode.extension.contributes.localizations": "提供在地化服務給編輯者", + "vscode.extension.contributes.localizations.languageId": "顯示已翻譯字串的語言 Id", + "vscode.extension.contributes.localizations.languageName": "語言名稱 (英文)。", + "vscode.extension.contributes.localizations.languageNameLocalized": "語言名稱 (提供的語言)。", + "vscode.extension.contributes.localizations.translations": "與該語言相關的翻譯列表。", + "vscode.extension.contributes.localizations.translations.id": "此翻譯提供之目標的 VS Code 或延伸模組識別碼。VS Code 的識別碼一律為 `vscode`,且延伸模組的格式應為 `publisherId.extensionName`。", + "vscode.extension.contributes.localizations.translations.id.pattern": "轉譯 VS 程式碼或延伸模組時,識別碼應分別使用 `vscode` 或 `publisherId.extensionName` 的格式。", + "vscode.extension.contributes.localizations.translations.path": "包含語言翻譯的檔案相對路徑。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..a5e6bfeb6f --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "設定語言", + "displayLanguage": "定義 VSCode 的顯示語言。", + "doc": "如需支援的語言清單,請參閱 {0}。", + "restart": "改變設定值後需要重新啟動 VSCode.", + "fail.createSettings": "無法建立 '{0}' ({1})。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..505303ab7e --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "複製", + "copyMessage": "複製訊息" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..9459b771c7 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "共 {0} 項問題" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..6a593deff2 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "問題", + "tooltip.1": "此檔案發生 1 個問題", + "tooltip.N": "此檔案發生 {0} 個問題", + "markers.showOnFile": "在檔案和資料夾上顯示錯誤和警告。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..cbdc55dae5 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "停用檔案排除篩選。", + "clearFilter": "清除篩選。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..44d1178263 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "顯示 {0} 個 (共 {1} 個)" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..45f0712eab --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "檢視", + "problems.view.toggle.label": "切換至問題(錯誤, 警告, 資訊)", + "problems.view.focus.label": "聚焦於問題(錯誤, 警告, 資訊)", + "problems.panel.configuration.title": "[問題] 檢視", + "problems.panel.configuration.autoreveal": "控制 [問題] 檢視是否應自動在開啟檔案時加以顯示", + "markers.panel.title.problems": "問題", + "markers.panel.aria.label.problems.tree": "依檔案分組的問題", + "markers.panel.no.problems.build": "目前在工作區中未偵測到任何問題。", + "markers.panel.no.problems.filters": "使用提供的篩選準則找不到任何結果。", + "markers.panel.no.problems.file.exclusions": "因為已啟用檔案排除篩選,所以所有問題皆已隱藏。", + "markers.panel.action.useFilesExclude": "使用檔案排除設定進行篩選", + "markers.panel.action.donotUseFilesExclude": "不使用檔案排除設定", + "markers.panel.action.filter": "篩選問題", + "markers.panel.filter.ariaLabel": "篩選問題", + "markers.panel.filter.placeholder": "篩選。例如: 文字、**/*.ts、!**/node_modules/**", + "markers.panel.filter.errors": "錯誤", + "markers.panel.filter.warnings": "警告", + "markers.panel.filter.infos": "資訊", + "markers.panel.single.error.label": "1 個錯誤", + "markers.panel.multiple.errors.label": "{0} 個錯誤", + "markers.panel.single.warning.label": "1 個警告", + "markers.panel.multiple.warnings.label": "{0} 個警告", + "markers.panel.single.info.label": "1 個資訊", + "markers.panel.multiple.infos.label": "{0} 個資訊", + "markers.panel.single.unknown.label": "1 個未知", + "markers.panel.multiple.unknowns.label": "{0} 個未知", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "發生 {1} 個問題的 {0}", + "problems.tree.aria.label.marker.relatedInformation": "此問題在 {0} 個位置有參考。", + "problems.tree.aria.label.error.marker": "{0} 產生的錯誤: 在行 {2} 與字元 {3} 的 {1}。{4} ", + "problems.tree.aria.label.error.marker.nosource": "錯誤: {0} 在行 {1} 和字元 {2}.{3}", + "problems.tree.aria.label.warning.marker": "{0} 產生的警告: 在行 {2} 與字元 {3} 的 {1}。{4} ", + "problems.tree.aria.label.warning.marker.nosource": "警告: 在行 {1} 與字元 {2} 的 {0}。{3}", + "problems.tree.aria.label.info.marker": "{0} 產生的資訊: 在行 {2} 與字元 {3} 的 {1}。{4}", + "problems.tree.aria.label.info.marker.nosource": "資訊: 在行 {1} 與字元 {2} 的 {0}。{3} ", + "problems.tree.aria.label.marker": "{0} 產生的問題: 在行 {2} 與字元 {3} 的 {1}。{4} ", + "problems.tree.aria.label.marker.nosource": "問題: 在行 {1} 與字元 {2} 的 {0}。{3} ", + "problems.tree.aria.label.relatedinfo.message": "在第 {1} 行的 {0},以及在 {3} 的 {2} 字元", + "errors.warnings.show.label": "顯示錯誤和警告" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/cht/src/vs/workbench/parts/output/browser/outputActions.i18n.json index f0cc8a6077..c4497e5abe 100644 --- a/i18n/cht/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "切換輸出", "clearOutput": "清除輸出", "toggleOutputScrollLock": "切換輸出 SCROLL LOCK", - "switchToOutput.label": "切換至輸出" + "switchToOutput.label": "切換至輸出", + "openInLogViewer": "開啟日誌檔案" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 5845ebb57a..8bc61f8584 100644 --- a/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "輸出", "logViewer": "紀錄檢視器", "viewCategory": "檢視", - "clearOutput.label": "清除輸出" + "clearOutput.label": "清除輸出", + "openActiveLogOutputFile": "檢視: 開啟活動日誌輸出檔案" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 14812c206a..3f4f4d6a5f 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "鍵盤快速鍵(&&K)", + "showDefaultKeybindings": "顯示預設按鍵繫結", + "showUserKeybindings": "顯示使用者按鍵繫結", "SearchKeybindings.AriaLabel": "搜尋按鍵繫結關係", "SearchKeybindings.Placeholder": "搜尋按鍵繫結關係", "sortByPrecedene": "依優先順序排序", diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 837eead4d3..44b87b90be 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "開啟原始預設設置", + "openSettings": "開啟設定", "openGlobalSettings": "開啟使用者設定", "openGlobalKeybindings": "開啟鍵盤快速鍵", "openGlobalKeybindingsFile": "開啟鍵盤快速鍵檔案", diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index ba34573fe5..ffcffb8d36 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "預設設定", "SearchSettingsWidget.AriaLabel": "搜尋設定", "SearchSettingsWidget.Placeholder": "搜尋設定", "noSettingsFound": "沒有結果", @@ -16,6 +15,8 @@ "nlpResult": "自然語言結果", "filterResult": "篩選結果", "defaultSettings": "預設設定", + "defaultUserSettings": "預設使用者設定", + "defaultWorkspaceSettings": "預設工作區設定", "defaultFolderSettings": "預設資料夾設定", "defaultEditorReadonly": "在右方編輯器中編輯以覆寫預設。", "preferencesAriaLabel": "預設喜好設定。唯讀文字編輯器。" diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 04d6da030b..aea8caa218 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "顯示擴充功能 \"{0}\"", "editTtile": "編輯", "replaceDefaultValue": "在設定中取代", - "copyDefaultValue": "複製到設定", - "unsupportedPHPExecutablePathSetting": "這項設定必須是使用者設定。若要設定工作區的 PHP,請開啟 PHP 檔案並按一下狀態列中的 [PHP 路徑]。", - "unsupportedWorkspaceSetting": "這項設定必須是使用者設定。", - "unsupportedWorkbenchSetting": "目前無法套用此設定。要在您直接開啟此資料夾時才會套用。", - "unsupportedWorkbenchSettingDevMode": "目前無法套用此設定。若您在註冊時將其範圍定義為「資源」,或您直接開啟此資料夾時,才會套用該設定。 " + "copyDefaultValue": "複製到設定" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index b1e781aa9b..00b23dcf8b 100644 --- a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "安裝額外SCM提供者...", "no open repo": "沒有使用中的原始檔控制提供者。", "source control": "原始檔控制", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "隱藏" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 70ec604a75..5e954b94f5 100644 --- a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "顯示上一個搜尋排除模式", "nextSearchTerm": "顯示下一個搜尋字詞", "previousSearchTerm": "顯示上一個搜尋字詞", - "showSearchViewlet": "顯示搜尋", "findInFiles": "在檔案中尋找", "replaceInFiles": "檔案中取代", "RefreshAction.label": "重新整理", diff --git a/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 765f19792f..55f7e2bb49 100644 --- a/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "搜尋", + "copyMatchLabel": "複製", + "copyPathLabel": "複製路徑", + "copyAllLabel": "全部複製", + "clearSearchHistoryLabel": "清除搜尋歷程記錄", + "toggleSearchViewPositionLabel": "切換搜尋檢視位置", "findInFolder": "在資料夾中尋找...", "findInWorkspace": "在工作區中尋找...", "showTriggerActions": "前往工作區中的符號...", "name": "搜尋", - "search": "搜尋", "showSearchViewl": "顯示搜尋", "view": "檢視", "findInFiles": "在檔案中尋找", @@ -26,5 +31,5 @@ "search.followSymlinks": "控制是否要在搜尋時遵循 symlink。", "search.smartCase": "如果搜尋式為全部小寫,則用不分大小寫的搜尋,否則用分大小寫的搜尋", "search.globalFindClipboard": "控制搜尋檢視是否應讀取或修改 macOS 上的共用尋找剪貼簿 (shared find clipboard)", - "search.location": "預覽: 控制搜尋會在資訊看板顯示為檢視,或在面板區域顯示為面板以取得更多水平空間。下個版本的面板搜尋將具有改善的水平版面配置,而此項目將不再處於預覽階段。" + "search.location": "控制搜尋是否在資訊看板會顯示為檢視,或為了更多水平空間,以面板方式在面板區域顯示。下個版本在面板上的搜尋將具有更好的水平版面配置,而此項目將不再處於預覽階段。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index d2b06d329c..94f6035ffc 100644 --- a/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "協助我們改善{0}", "takeShortSurvey": "填寫簡短調查問卷", "remindLater": "稍後再提醒我", - "neverAgain": "不要再顯示", - "helpUs": "協助我們改善{0}" + "neverAgain": "不要再顯示" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 5f4cd09f45..660697f2d0 100644 --- a/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "您願意填寫簡短的意見反應問卷嗎?", "takeSurvey": "填寫問卷", "remindLater": "稍後再提醒我", - "neverAgain": "不要再顯示", - "surveyQuestion": "您願意填寫簡短的意見反應問卷嗎?" + "neverAgain": "不要再顯示" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index add99411f3..45c2e69fe2 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "問題模式或所提供或預先定義之問題模式的名稱。如有指定基底,即可發出。", "ProblemMatcherSchema.base": "要使用之基底問題比對器的名稱。", "ProblemMatcherSchema.owner": "Code 內的問題擁有者。如果指定基底,則可以省略。如果省略且未指定基底,預設為 [外部]。", + "ProblemMatcherSchema.source": "可供人們閱讀的診斷描述來源,例如 'typescript' 或 'super lint'。", "ProblemMatcherSchema.severity": "擷取項目問題的預設嚴重性。如果模式未定義嚴重性的符合群組,就會加以使用。", "ProblemMatcherSchema.applyTo": "控制文字文件上所回報的問題僅會套用至開啟的文件、關閉的文件或所有文件。", "ProblemMatcherSchema.fileLocation": "定義問題模式中所回報檔案名稱的解譯方式。", diff --git a/i18n/cht/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 84024fcb36..30d38661a7 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "實際的工作類型", + "TaskDefinition.description": "實際工作類型。請注意以 '$' 作為開頭的類型皆為內部使用保留。", "TaskDefinition.properties": "工作類型的其他屬性", "TaskTypeConfiguration.noType": "工作類型組態遺失需要的 'taskType' 屬性", "TaskDefinitionExtPoint": "提供工作種類" diff --git a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 51544c209d..ba234c5974 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "指派工作到沒有群組", "JsonSchema.tasks.group": "定義工作屬於哪個執行群組。支援將 「組建」新增到組建群組,以及將「測試」新增到測試群組。", "JsonSchema.tasks.type": "定義工作在殼層中會作為處理序或命令來執行。", + "JsonSchema.command.quotedString.value": "實際命令值", + "JsonSchema.tasks.quoting.escape": "使用殼層逸出字元的逸出字元 (例如 ` under PowerShell 與 \\ under bash)。", + "JsonSchema.tasks.quoting.strong": "使用殼層的強式引號字元將引數括住 (例如 PowerShell 及 Bash 下的 \")。", + "JsonSchema.tasks.quoting.weak": "使用殼層的弱式引號字元將引數括住 (例如 PowerShell 及 Bash 下的 ')", + "JsonSchema.command.quotesString.quote": "如何引用命令值。", + "JsonSchema.command": "要執行的命令。可以是外部程式或殼層命令。", + "JsonSchema.args.quotedString.value": "實際參數值", + "JsonSchema.args.quotesString.quote": "如何引用參數值。", + "JsonSchema.tasks.args": "叫用此工作時,傳遞至命令的引數。", "JsonSchema.tasks.label": "工作的使用者介面標籤", "JsonSchema.version": "組態版本號碼", "JsonSchema.tasks.identifier": "用以參考在 launch.json 或 dependsOn 子句中工作的使用者定義識別碼。", diff --git a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index b765e552cb..a13d5229d2 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "工作", "ConfigureTaskRunnerAction.label": "設定工作", + "totalErrors": "{0} 個錯誤", + "totalWarnings": "{0} 個警告", + "totalInfos": "{0} 個資訊", "problems": "問題", "building": "建置中...", - "manyMarkers": "99+", + "manyProblems": "10K+", "runningTasks": "顯示執行中的工作", "tasks": "工作", "TaskSystem.noHotSwap": "必須重新載入視窗才可變更執行使用中工作的工作執行引擎", @@ -28,8 +31,10 @@ "selectProblemMatcher": "選取錯誤和警告的種類以掃描工作輸出", "customizeParseErrors": "當前的工作組態存在錯誤.請更正錯誤再執行工作.", "moreThanOneBuildTask": "定義了很多建置工作於tasks.json.執行第一個.", - "TaskSystem.activeSame.background": "工作 '{0}' 已在使用中並處於背景模式。若要予以終止,請使用 [Tasks] \\(工作\\) 功能表的 [Terminate Task...] \\(終止工作...\\)。", - "TaskSystem.activeSame.noBackground": "工作 '{0}' 已在使用中。若要予以終止,請使用 [Tasks] \\(工作\\) 功能表的 [Terminate Task...] \\(終止工作...\\)。", + "TaskSystem.activeSame.background": "工作 '{0}' 已在使用中並且處於背景模式。", + "TaskSystem.activeSame.noBackground": "工作 '{0}' 已在使用中。", + "terminateTask": "終止工作", + "restartTask": "重新啟動工作", "TaskSystem.active": "已有工作在執行。請先終止該工作,然後再執行其他工作。", "TaskSystem.restartFailed": "無法終止再重新啟動工作 {0}", "TaskService.noConfiguration": "錯誤: {0} 工作偵測未替下列組態提供工作:\n{1}\n將會忽略該工作。\n", diff --git a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 29badbfe08..42c0153d17 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "工作 - {0}", "closeTerminal": "按任意鍵關閉終端機。", "reuseTerminal": "工作將被重新啟用.按任意鍵關閉.", - "TerminalTaskSystem": "無法在 UNC 磁碟機上執行殼層命令。", + "TerminalTaskSystem": "無法使用 cmd.exe 在 UNC 磁碟機上執行 shell 命令。", "unkownProblemMatcher": "問題比對器 {0} 無法解析,比對器將予忽略。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/cht/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 479a4fdad3..d7ff08929d 100644 --- a/i18n/cht/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "警告: options.cwd 必須屬於字串類型。即將忽略值 {0}。", + "ConfigurationParser.inValidArg": "錯誤: 命令參數必須是字串或帶引號的字串。提供的值為:\n{0}", "ConfigurationParser.noargs": "錯誤: 命令引數必須是字串陣列。提供的值為:\n{0}", "ConfigurationParser.noShell": "警告: 只有在終端機中執行工作時才支援殼層組態。", "ConfigurationParser.noName": "錯誤: 宣告範圍中的問題比對器必須有名稱:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "錯誤: 工作組態 '{0}' 缺少要求的屬性 '{1}'。會略過工作組態。", "ConfigurationParser.notCustom": "錯誤: 未將工作宣告為自訂工作。將會忽略該組態。\n{0}\n", "ConfigurationParser.noTaskName": "錯誤: 一項工作必須提供標籤屬性。即將忽略此工作。\n{0}\n", - "taskConfiguration.shellArgs": "警告: 工作 '{0}' 是 shell 命令 ,其中一個引數可能有未逸出的空格。若要確保命令列正確引述,請將引數合併到命令中。", "taskConfiguration.noCommandOrDependsOn": "錯誤: 工作 '{0}' 未指定命令與 dependsOn 屬性。將會略過該工作。其定義為: \n{1}", "taskConfiguration.noCommand": "錯誤: 工作 '{0}' 未定義命令。即將略過該工作。其定義為:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "工作版本 2.0.0 不支援全域 OS 特定工作。請使用 OS 特定命令來轉換這些工作。受影響的工作為:\n{0}" diff --git a/i18n/cht/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..2657899133 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "終端機的背景色彩,允許終端機和面板的色彩不同。", + "terminal.foreground": "終端機的前景色彩。", + "terminalCursor.foreground": "終端機游標的前景色彩。", + "terminalCursor.background": "終端機游標的背景色彩。允許區塊游標重疊於自訂字元色彩。", + "terminal.selectionBackground": "終端機的選取項目背景色彩。", + "terminal.border": "在終端機內將窗格分割之邊界的色彩。預設為 panel.border。", + "terminal.ansiColor": "終端機中的 '{0}' ANSI 色彩。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 57d5d25857..6b90d7fb01 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "為新的終端機選擇目前的工作目錄", "workbench.action.terminal.newInActiveWorkspace": "建立新的整合式終端機 (於目前工作區)", "workbench.action.terminal.split": "分割終端機", + "workbench.action.terminal.splitInActiveWorkspace": "分割終端機 (於使用中的工作區)", "workbench.action.terminal.focusPreviousPane": "聚焦上一個窗格", "workbench.action.terminal.focusNextPane": "聚焦下一個窗格", "workbench.action.terminal.resizePaneLeft": "調整窗格左側", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "向上捲動 (頁)", "workbench.action.terminal.scrollToTop": "捲動至頂端", "workbench.action.terminal.clear": "清除", + "workbench.action.terminal.clearSelection": "清除選取項目", "workbench.action.terminal.allowWorkspaceShell": "允許工作區外觀配置", "workbench.action.terminal.disallowWorkspaceShell": "不允許工作區外觀設置", "workbench.action.terminal.rename": "重新命名", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "隱藏尋找小工具", "nextTerminalFindTerm": "顯示下一個尋找字詞", "previousTerminalFindTerm": "顯示上一個尋找字詞", - "quickOpenTerm": "切換使用中的終端機 " + "quickOpenTerm": "切換使用中的終端機 ", + "workbench.action.terminal.scrollToPreviousCommand": "捲動至上一個命令", + "workbench.action.terminal.scrollToNextCommand": "捲動至下一個命令", + "workbench.action.terminal.selectToPreviousCommand": "選取上一個命令", + "workbench.action.terminal.selectToNextCommand": "選取下一個命令" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index 87bac025ef..ee0ea8cbc8 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "終端機沒有任何選取項目可以複製", "terminal.integrated.exitedWithCode": "終端機處理序已終止,結束代碼為: {0}", "terminal.integrated.waitOnExit": "按任意鍵關閉終端機", - "terminal.integrated.launchFailed": "無法啟動終端機處理序命令 '{0}{1}' (結束代碼: {2})" + "terminal.integrated.launchFailed": "無法啟動終端機處理序命令 '{0}{1}' (結束代碼: {2})", + "terminal.integrated.launchFailedExtHost": "終端機處理序無法啟動 (結束代碼: {0})" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 0068a23e88..6b413d0615 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "複製", + "split": "分割", "paste": "貼上", "selectAll": "全選", - "clear": "清除", - "split": "分割" + "clear": "清除" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 35b3f7041f..f5b624d143 100644 --- a/i18n/cht/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "此工作區包含只能在 [使用者設定] 中進行的設定 ({0})。點擊 [這裡]({1}) 了解更多。", "openWorkspaceSettings": "開啟工作區設定", - "dontShowAgain": "不要再顯示", - "unsupportedWorkspaceSettings": "此工作區包含只能在 [使用者設定] 中進行的設定 ({0})。點擊 [這裡]({1}) 了解更多。" + "dontShowAgain": "不要再顯示" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..bc0754d2c3 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "版本資訊: {0}", + "unassigned": "未指派" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json index d66ec283cc..d6df33a190 100644 --- a/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "稍後", - "unassigned": "未指派", "releaseNotes": "版本資訊", "showReleaseNotes": "顯示版本資訊", "read the release notes": "歡迎使用 {0} v{1}! 您要閱讀版本資訊嗎?", @@ -17,13 +15,14 @@ "updateIsReady": "新的 {0} 更新已可用。", "noUpdatesAvailable": "目前沒有任何可用的更新。", "ok": "確定", - "download now": "立即下載", "thereIsUpdateAvailable": "已有更新可用。", + "download now": "立即下載", + "later": "稍後", + "updateAvailable": "已有可用的更新:{0} {1}", "installUpdate": "安裝更新", - "updateAvailable": "已有更新可用: {0} {1}", "updateInstalling": "{0} {1} 正在背景執行安裝,完成後我們會通知您。", + "updateAvailableAfterRestart": "重啟 {0} 以套用最新的更新。", "updateNow": "立即更新", - "updateAvailableAfterRestart": "{0} 重新啟動後將會更新。", "commandPalette": "命令選擇區...", "settings": "設定", "keyboardShortcuts": "鍵盤快速鍵(&&K)", diff --git a/i18n/cht/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..7eacd141c3 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "開啟 URL", + "developer": "開發人員" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..b50b4d83e7 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "webview 編輯器", + "developer": "開發人員" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..da7857bbdc --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "開啟 Webview Developer 工具", + "refreshWebviewLabel": "重新載入 Webviews" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/cht/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..c089b63f25 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "允許 Microsoft 收集使用率資料來協助改進 VS Code。閱讀我們的 [隱私權聲明] ({0}) 以及學習如何 [選擇退出] ({1})。", + "telemetryOptOut.optInNotice": "允許 Microsoft 收集使用率資料來協助改進 VS Code。閱讀我們的 [隱私權聲明] ({0}) 以及學習如何 [選擇參加] ({1})。", + "telemetryOptOut.readMore": "閱讀其他資訊" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/cht/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index e74671750d..543ff6ffb8 100644 --- a/i18n/cht/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "管理延伸模組", "welcomeOverlay.problems": "檢視錯誤和警告", "welcomeOverlay.commandPalette": "尋找及執行所有命令", + "welcomeOverlay.notifications": "顯示通知", "welcomeOverlay": "使用者介面概觀", "hideWelcomeOverlay": "隱藏介面概觀", "help": "說明" diff --git a/i18n/cht/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/cht/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 24d2b171cf..5f4a693c76 100644 --- a/i18n/cht/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "工具與語言", "welcomePage.installExtensionPacksDescription": "安裝{0}與{1}的支援功能。", "welcomePage.moreExtensions": "更多", - "welcomePage.installKeymapDescription": "安裝鍵盤快速鍵", - "welcomePage.installKeymapExtension": "安裝鍵盤快速鍵{0}與{1}", + "welcomePage.installKeymapDescription": "設定及按鍵對應", + "welcomePage.installKeymapExtension": "安裝 {0} 和 {1} 的設定及鍵盤快速鍵", "welcomePage.others": "其他", "welcomePage.colorTheme": "彩色佈景主題", "welcomePage.colorThemeDescription": "將編輯器及您的程式碼設定成您喜愛的外觀", diff --git a/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 9dad2e146d..5db5a4ce9d 100644 --- a/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/cht/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "設定的摘要。此標籤將會在設定檔中作為分隔註解使用。", "vscode.extension.contributes.configuration.properties": "組態屬性的描述。", + "scope.application.description": "應用程式特定設置,只能在使用者設定中進行設置。", "scope.window.description": "視窗特定組態,可在使用者或工作區設定中予以設定。", "scope.resource.description": "資源特定設定,可在使用者、工作區或資料夾設定中予以設定。", "scope.description": "組態適用的範圍。可用的範圍為「視窗」和「資源」。", diff --git a/i18n/cht/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/cht/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index d0b400cefe..ad89a0f030 100644 --- a/i18n/cht/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "開啟設定", "saveAndRetry": "儲存並重試", "errorUnknownKey": "因為 {1} 非已註冊的組態,所以無法寫入至 {0}。", + "errorInvalidWorkspaceConfigurationApplication": "無法寫入 {0} 至工作區設定。此設定只能寫入使用者設定中。", "errorInvalidFolderConfiguration": "因為 {0} 不支援資料夾資源範圍,所以無法寫入至資料夾設定。", "errorInvalidUserTarget": "因為 {0} 不支援全域範圍,所以無法寫入至使用者設定。", "errorInvalidWorkspaceTarget": "因為 {0} 不支援多資料夾工作區中使用工作區範圍,所以無法寫入工作區設定。", diff --git a/i18n/cht/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/cht/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..98e383c286 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "此設定只能在使用者設定中套用", + "unsupportedWindowSetting": "目前無法套用此設定。要在您直接開啟此資料夾時才會套用。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/cht/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/cht/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..a50b47db62 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "因為未指定任何環境變數名稱,所以無法解析 '{0}'。", + "configNotFound": "因為找不到設定 '{1}',所以無法解析 '{0}'。", + "configNoString": "因為 '{1}' 為結構化值,所以無法解析 '{0}'。", + "missingConfigName": "因為未指定任何設定名稱,所以無法解析 '{0}'。", + "noValueForCommand": "因為命令沒有任何值,所以無法解析 '{0}'。", + "canNotFindFolder": "無法解析 '{0}'。沒有該等資料夾 '{1}'。", + "canNotResolveWorkspaceFolderMultiRoot": "無法在多個資料夾工作區內解析 '{0}'。請使用 ':' 和工作區資料夾名稱定義此變數的範圍。", + "canNotResolveWorkspaceFolder": "無法解析 '{0}'。請開啟資料夾。", + "canNotResolveFile": "無法解析 '{0}'。請開啟編輯器。", + "canNotResolveLineNumber": "無法解析 '{0}'。請確認已在使用中編輯器中選取了行。", + "canNotResolveSelectedText": "無法解析 '{0}'。請確認在使用中編輯器內選取了部分文字。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/cht/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..e3294fd332 --- /dev/null +++ b/i18n/cht/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "是(&&Y)", + "cancelButton": "取消" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/cht/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index b77916d084..d1fb3b592c 100644 --- a/i18n/cht/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/cht/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "引擎相容性。", "vscode.extension.engines.vscode": "若是 VS Code 延伸模組,則指定與延伸模組相容的 VS Code 版本。不得為 *。例如: ^0.10.5 表示與最低 VS Code 版本 0.10.5 相容。", "vscode.extension.publisher": "VS Code 擴充功能的發行者。", "vscode.extension.displayName": "VS Code 資源庫中使用的擴充功能顯示名稱。", "vscode.extension.categories": "VS Code 資源庫用來將擴充功能歸類的分類。", + "vscode.extension.category.languages.deprecated": "使用 '程式語言' 代替", "vscode.extension.galleryBanner": "用於 VS Code Marketplace 的橫幅。", "vscode.extension.galleryBanner.color": "VS Code Marketplace 頁首的橫幅色彩。", "vscode.extension.galleryBanner.theme": "橫幅中使用的字型色彩佈景主題。", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "需要特定類型偵錯工作階段啟動來觸發啟動事件 (並且呼叫相對應 resolveDebugConfiguration 方法)", "vscode.extension.activationEvents.workspaceContains": "當開啟指定的文件夾包含glob模式匹配的文件時激發該事件", "vscode.extension.activationEvents.onView": "當指定的檢視被擴展時激發該事件", + "vscode.extension.activationEvents.onUri": "每當指向此延伸模組的全系統 URI 開啟時,都會發出啟動事件。", "vscode.extension.activationEvents.star": "當VS Code啟動時激發該事件,為了確保最好的使用者體驗,當您的擴充功能沒有其他組合作業時,請激活此事件.", "vscode.extension.badges": "要顯示於 Marketplace 擴充頁面資訊看板的徽章陣列。", "vscode.extension.badges.url": "徽章映像 URL。", "vscode.extension.badges.href": "徽章連結。", "vscode.extension.badges.description": "徽章描述。", + "vscode.extension.markdown": "控制使用市集中的 Markdown 轉譯引擎。可為 github (預設) 或標準。", + "vscode.extension.qna": "控制市集中 Q & A 的連結。設定為 marketplace 來啟用預設市集 Q & A 網站。設定字串以提供自訂的 Q & A 網站 URL。設定為 false 則禁用 Q & A。", "vscode.extension.extensionDependencies": "其它擴充功能的相依性。擴充功能的識別碼一律為 ${publisher}.${name}。例如: vscode.csharp。", "vscode.extension.scripts.prepublish": "在封裝作為 VS Code 擴充功能發行前所執行的指令碼。", "vscode.extension.scripts.uninstall": "VS Code 延伸模組的解除安裝勾點。當延伸模組完全從 VS Code 解除安裝時,會在延伸模組解除安裝並重新啟動 (關機並啟動) 時執行的程式碼。僅支援 Node 指令碼。", diff --git a/i18n/cht/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/cht/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 953e6f0a65..e359b3d27e 100644 --- a/i18n/cht/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "所有擴充功能已停用。", "extensionHostProcess.crash": "延伸主機意外終止。", "extensionHostProcess.unresponsiveCrash": "因為延伸主機沒有回應,所以意外終止。", - "devTools": "開發人員工具", + "devTools": "開啟開發人員工具", "restart": "重新啟動延伸主機", "overwritingExtension": "正在以 {1} 覆寫延伸模組 {0}。", "extensionUnderDevelopment": "正在載入位於 {0} 的開發延伸模組", diff --git a/i18n/cht/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/cht/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index f414b3a84f..fc04da73b9 100644 --- a/i18n/cht/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "需要 Microsoft .NET Framework 4.5。請連入此連結進行安裝。", "installNet": "下載 .NET Framework 4.5", "neverShowAgain": "不要再顯示", - "netVersionError": "需要 Microsoft .NET Framework 4.5。請連入此連結進行安裝。", + "enospcError": "{0} 無法監看此大型工作區中的檔案變更。請按照連結中的說明來解決此問題。", "learnMore": "說明", - "enospcError": "{0} 已超出檔案處理。請按照說明連結解決此問題。", + "fileInvalidPath": "檔案資源 ({0}) 無效", + "fileIsDirectoryError": "檔案是目錄", + "fileNotModifiedError": "未修改檔案的時間", + "fileTooLargeForHeapError": " 欲開啟此大小的檔案,需要重啟 VS Code,並且允許可使用更多記憶體", + "fileTooLargeError": "檔案太大無法開啟", + "fileNotFoundError": "找不到檔案 ({0})", + "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟", + "filePermission": "寫至檔案 ({0}) 的權限遭拒", + "fileExists": "要建立的檔案已存在 ({0})", + "fileModifiedError": "修改檔案的時間", + "fileReadOnlyError": "檔案為唯讀", + "fileMoveConflict": "無法移動/複製。目的地已存在檔案。", + "unableToMoveCopyError": "無法移動/複製。檔案會取代其所在的資料夾。", "binFailed": "無法將 '{0}' 移至資源回收筒", "trashFailed": "無法將 '{0}' 移動至垃圾" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 15c45aa918..09ee4d7e3e 100644 --- a/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "找不到檔案 ({0})", "fileIsDirectoryError": "檔案是目錄", "fileNotModifiedError": "未修改檔案的時間", - "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟" + "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟", + "err.create": "無法建立檔案 {0}", + "fileMoveConflict": "無法移動/複製。目的地已存在檔案。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json index be59345f38..a4e74cdbdc 100644 --- a/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,6 @@ "fileInvalidPath": "檔案資源 ({0}) 無效", "fileIsDirectoryError": "檔案是目錄", "fileNotModifiedError": "未修改檔案的時間", - "fileTooLargeForHeapError": "檔案大小超過視窗記憶體限制,請試執行 code --max-memory=NEWSIZE", "fileTooLargeError": "檔案太大無法開啟", "fileNotFoundError": "找不到檔案 ({0})", "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟", diff --git a/i18n/cht/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/cht/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..2928c9a671 100644 --- a/i18n/cht/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/cht/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "取消" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 7566c1ce48..bf33bc6af8 100644 --- a/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "tmLanguage 檔案所使用的 textmate 範圍名稱。", "vscode.extension.contributes.grammars.path": "tmLanguage 檔案的路徑。此路徑是擴充功能資料夾的相對路徑,而且一般會以 './syntaxes/' 開頭。", "vscode.extension.contributes.grammars.embeddedLanguages": "如果此文法包含內嵌語言,即為範圍名稱到語言識別碼的對應。", + "vscode.extension.contributes.grammars.tokenTypes": "範圍名稱到象徵類型的對應。", "vscode.extension.contributes.grammars.injectTo": "要插入此文法的語言範圍名稱清單。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 3f45401eb9..a196a455b7 100644 --- a/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/cht/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "'contributes.{0}.path' 中應有字串。提供的值: {1}", "invalid.injectTo": "`contributes.{0}.injectTo` 中的值無效。必須是語言範圍名稱的陣列。提供的值: {1}", "invalid.embeddedLanguages": "`contributes.{0}.embeddedLanguages` 中的值無效。必須是從範圍名稱到語言的物件對應。提供的值: {1}", + "invalid.tokenTypes": "`contributes.{0}.tokenTypes` 的值無效。必須是從範圍名稱到象徵類型的物件對應。提供的值: {1} ", "invalid.path.1": "擴充功能資料夾 ({2}) 應包含 'contributes.{0}.path' ({1})。這可能會導致擴充功能無法移植。", "no-tm-grammar": "此語言未註冊任何 TM 文法。" } \ No newline at end of file diff --git a/i18n/deu/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/deu/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..05ec8e7779 --- /dev/null +++ b/i18n/deu/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS-Sprachserver", + "folding.start": "Regionsanfang wird gefaltet", + "folding.end": "Regionsende wird gefaltet" +} \ No newline at end of file diff --git a/i18n/deu/extensions/css-language-features/package.i18n.json b/i18n/deu/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..6c525265ec --- /dev/null +++ b/i18n/deu/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für CSS-, LESS- und SCSS-Dateien.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", + "css.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", + "css.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", + "css.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", + "css.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", + "css.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", + "css.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", + "css.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", + "css.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", + "css.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", + "css.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", + "css.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", + "css.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", + "css.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", + "css.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", + "css.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", + "css.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", + "css.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", + "css.trace.server.desc": "Verfolgt die Kommunikation zwischen VS Code und dem CSS-Sprachserver.", + "css.validate.title": "Steuert die CSS-Validierung und Problemschweregrade.", + "css.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", + "less.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", + "less.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", + "less.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", + "less.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", + "less.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", + "less.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", + "less.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", + "less.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", + "less.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", + "less.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", + "less.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", + "less.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", + "less.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", + "less.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", + "less.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", + "less.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", + "less.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", + "less.validate.title": "Steuert die LESS-Validierung und Problemschweregrade.", + "less.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", + "scss.title": "SCSS (SASS)", + "scss.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", + "scss.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", + "scss.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", + "scss.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", + "scss.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", + "scss.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", + "scss.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", + "scss.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", + "scss.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", + "scss.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", + "scss.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", + "scss.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", + "scss.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", + "scss.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", + "scss.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", + "scss.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", + "scss.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", + "scss.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", + "scss.validate.title": "Steuert die SCSS-Überprüfung und Problemschweregrade.", + "scss.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", + "less.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", + "scss.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", + "css.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", + "css.colorDecorators.enable.deprecationMessage": "Die Einstellung \"css.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt.", + "scss.colorDecorators.enable.deprecationMessage": "Die Einstellung \"scss.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt.", + "less.colorDecorators.enable.deprecationMessage": "Die Einstellung \"less.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt." +} \ No newline at end of file diff --git a/i18n/deu/extensions/css/package.i18n.json b/i18n/deu/extensions/css/package.i18n.json index a6667b0e22..aed3443241 100644 --- a/i18n/deu/extensions/css/package.i18n.json +++ b/i18n/deu/extensions/css/package.i18n.json @@ -2,80 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS Sprachfeatures", - "description": "Bietet umfangreiche Sprachunterstützung für CSS-, LESS- und SCSS-Dateien.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", - "css.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", - "css.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", - "css.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", - "css.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", - "css.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", - "css.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", - "css.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", - "css.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", - "css.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", - "css.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", - "css.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", - "css.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", - "css.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", - "css.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", - "css.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", - "css.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", - "css.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", - "css.trace.server.desc": "Verfolgt die Kommunikation zwischen VS Code und dem CSS-Sprachserver.", - "css.validate.title": "Steuert die CSS-Validierung und Problemschweregrade.", - "css.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", - "less.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", - "less.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", - "less.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", - "less.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", - "less.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", - "less.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", - "less.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", - "less.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", - "less.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", - "less.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", - "less.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", - "less.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", - "less.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", - "less.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", - "less.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", - "less.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", - "less.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", - "less.validate.title": "Steuert die LESS-Validierung und Problemschweregrade.", - "less.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", - "scss.title": "SCSS (SASS)", - "scss.lint.argumentsInColorFunction.desc": "Ungültige Parameteranzahl.", - "scss.lint.boxModel.desc": "Verwenden Sie width oder height nicht beim Festlegen von padding oder border", - "scss.lint.compatibleVendorPrefixes.desc": "Stellen Sie beim Verwenden vom anbieterspezifischen Präfix sicher, dass alle anderen anbieterspezifischen Eigenschaften miteinbezogen werden", - "scss.lint.duplicateProperties.desc": "Keine doppelten Formatvorlagendefinitionen verwenden", - "scss.lint.emptyRules.desc": "Keine leeren Regelsätze verwenden", - "scss.lint.float.desc": "Die Verwendung von \"float\" vermeiden. float-Eigenschaften führen zu anfälligem CSS, das schnell nicht mehr funktioniert, wenn sich ein Aspekt des Layouts ändert.", - "scss.lint.fontFaceProperties.desc": "@font-face-Regel muss die Eigenschaften \"src\" und \"font-family\" definieren.", - "scss.lint.hexColorLength.desc": "Hexfarben müssen aus drei oder sechs Hexzahlen bestehen", - "scss.lint.idSelector.desc": "Selektoren sollten keine IDs enthalten, da diese Regeln zu eng mit HTML verknüpft sind.", - "scss.lint.ieHack.desc": "IE-Hacks sind nur für die Unterstützung von IE7 und älter erforderlich", - "scss.lint.important.desc": "Verwendung von „!important“ vermeiden. Damit wird angegeben, dass die Spezifität vom gesamten CSS außer Kontrolle geraten ist und umgestaltet werden muss.", - "scss.lint.importStatement.desc": "Importanweisungen können nicht parallel geladen werden.", - "scss.lint.propertyIgnoredDueToDisplay.desc": "Die Eigenschaft wird aufgrund der Anzeige ignoriert. Mit \"display: inline\" besitzen die width-, height-, margin-top-, margin-bottom- und float-Eigenschaften z. B. keine Auswirkung.", - "scss.lint.universalSelector.desc": "Es ist bekannt, dass der Universalselektor (*) langsam ist.", - "scss.lint.unknownProperties.desc": "Unbekannte Eigenschaft.", - "scss.lint.unknownVendorSpecificProperties.desc": "Unbekannte anbieterspezifische Eigenschaft.", - "scss.lint.vendorPrefix.desc": "Beim Verwenden von anbieterspezifischen Präfix auch die Standardeigenschaft miteinbeziehen", - "scss.lint.zeroUnits.desc": "Keine Einheit für Null erforderlich", - "scss.validate.title": "Steuert die SCSS-Überprüfung und Problemschweregrade.", - "scss.validate.desc": "Aktiviert oder deaktiviert alle Überprüfungen.", - "less.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", - "scss.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", - "css.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", - "css.colorDecorators.enable.deprecationMessage": "Die Einstellung \"css.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt.", - "scss.colorDecorators.enable.deprecationMessage": "Die Einstellung \"scss.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt.", - "less.colorDecorators.enable.deprecationMessage": "Die Einstellung \"less.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt." + "displayName": "CSS-Sprachgrundlagen", + "description": "Bietet Syntax-Highlighting und Bracket-Matching für CSS, LESS und SCSS Dateien." } \ No newline at end of file diff --git a/i18n/deu/extensions/emmet/package.i18n.json b/i18n/deu/extensions/emmet/package.i18n.json index 7aca2522ba..76a0f1cf2f 100644 --- a/i18n/deu/extensions/emmet/package.i18n.json +++ b/i18n/deu/extensions/emmet/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Pfad zu einem Ordner mit Emmet-Profilen und Ausschnitten.", "emmetShowExpandedAbbreviation": "Zeigt erweiterte Emmet-Abkürzungen als Vorschläge an.\nDie Option inMarkupAndStylesheetFilesOnly gilt für HTML, HAML, Jade, Slim, XML, XSL, CSS, SCSS, Sass, Less und Stylus.\nDie Option \"always\" gilt unabhängig vom Markup/CSS für alle Teile der Datei.", "emmetShowAbbreviationSuggestions": "Zeigt mögliche Emmet-Abkürzungen als Vorschläge an. Diese Option gilt nicht in Stylesheets oder wenn emmet.showExpandedAbbreviation auf \"never\" festgelegt ist.", - "emmetIncludeLanguages": "Aktivieren Sie Emmet-Abkürzungen in Sprachen, die nicht standardmäßig unterstützt werden. Fügen Sie hier ein Mapping zwischen der Sprache und der von Emmet unterstützten Sprache hinzu.\nBeispiel: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "Aktivieren Sie Emmet-Abkürzungen in Sprachen, die nicht standardmäßig unterstützt werden. Fügen Sie hier eine Zuordnung zwischen der Sprache und der von Emmet unterstützten Sprache hinzu.\nBeispiel: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "In Emmet-Ausschnitten zu verwendende Codeausschnitte", "emmetTriggerExpansionOnTab": "Wenn aktiviert, werden Emmet-Abkürzungen beim Drücken der TAB-Taste erweitert.", "emmetPreferences": "Einstellungen, die zum Ändern des Verhaltens einiger Aktionen und Konfliktlöser von Emmet verwendet werden.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Durch Trennzeichen getrennte CSS-Eigenschaften, die das \"webkit\"-Herstellerpräfix erhalten, wenn sie in einer Emmet-Abkürzung verwendet werden, die mit \"-\" beginnt. Legen Sie eine leere Zeichenfolge fest, um das \"webkit\"-Präfix immer zu vermeiden.", "emmetPreferencesCssMozProperties": "Durch Trennzeichen getrennte CSS-Eigenschaften, die das \"moz\"-Herstellerpräfix erhalten, wenn sie in einer Emmet-Abkürzung verwendet werden, die mit \"-\" beginnt. Legen Sie eine leere Zeichenfolge fest, um das \"moz\"-Präfix immer zu vermeiden.", "emmetPreferencesCssOProperties": "Durch Trennzeichen getrennte CSS-Eigenschaften, die das \"o\"-Herstellerpräfix erhalten, wenn sie in einer Emmet-Abkürzung verwendet werden, die mit \"-\" beginnt. Legen Sie eine leere Zeichenfolge fest, um das \"o\"-Präfix immer zu vermeiden.", - "emmetPreferencesCssMsProperties": "Durch Trennzeichen getrennte CSS-Eigenschaften, die das \"ms\"-Herstellerpräfix erhalten, wenn sie in einer Emmet-Abkürzung verwendet werden, die mit \"-\" beginnt. Legen Sie eine leere Zeichenfolge fest, um das \"ms\"-Präfix immer zu vermeiden." + "emmetPreferencesCssMsProperties": "Durch Trennzeichen getrennte CSS-Eigenschaften, die das \"ms\"-Herstellerpräfix erhalten, wenn sie in einer Emmet-Abkürzung verwendet werden, die mit \"-\" beginnt. Legen Sie eine leere Zeichenfolge fest, um das \"ms\"-Präfix immer zu vermeiden.", + "emmetPreferencesCssFuzzySearchMinScore": "Das Mindestergebnis (zwischen 0 und 1), das die Abkürzung mit Fuzzyübereinstimmung erreichen muss. Niedrigere Werte führen zu vielen falsch positiven Übereinstimmungen, höhere Werte verringern unter Umständen die möglichen Übereinstimmungen.", + "emmetOptimizeStylesheetParsing": "Bei der Einstellung FALSE wird die gesamte Datei analysiert, um zu bestimmten, ob die aktuelle Position zum Erweitern von Emmet-Abkürzungen gültig ist. Bei der Einstellung TRUE wird nur der Inhalt um die die aktuelle Position in CSS-/SCSS-/LESS-Dateien analysiert." } \ No newline at end of file diff --git a/i18n/deu/extensions/git/out/commands.i18n.json b/i18n/deu/extensions/git/out/commands.i18n.json index 752831ee37..dc0196a882 100644 --- a/i18n/deu/extensions/git/out/commands.i18n.json +++ b/i18n/deu/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Neuen Branch erstellen", "repourl": "Repository-URL", "parent": "Übergeordnetes Verzeichnis", - "cancel": "$(sync~spin) Repository wird geklont... Klicken Sie zum Abbrechen", - "cancel tooltip": "Klonen abbrechen", - "cloning": "Git-Repository wird geklont...", + "cloning": "Das Git-Repository \"{0}\" wird geklont …", "openrepo": "Repository öffnen", "proposeopen": "Möchten Sie das geklonte Repository öffnen?", "init": "Arbeitsbereichsordner auswählen, in dem das Git-Repository initialisiert wird", @@ -75,7 +73,7 @@ "ok": "OK", "push with tags success": "Push mit Tags erfolgreich ausgeführt.", "pick remote": "Remotespeicherort auswählen, an dem der Branch \"{0}\" veröffentlicht wird:", - "sync is unpredictable": "Mit dieser Aktion werden Commits per Push und Pull an und von \"{0}\" übertragen.", + "sync is unpredictable": "Mit dieser Aktion werden Commits per Push und Pull an und von \"{0}/{1}\" übertragen.", "never again": "OK, nicht mehr anzeigen", "no remotes to publish": "In Ihrem Repository wurden keine Remoteelemente für die Veröffentlichung konfiguriert.", "no changes stash": "Es sind keine Änderungen vorhanden, für die ein Stash ausgeführt werden kann.", diff --git a/i18n/deu/extensions/git/package.i18n.json b/i18n/deu/extensions/git/package.i18n.json index e98c75af3b..bb5e958587 100644 --- a/i18n/deu/extensions/git/package.i18n.json +++ b/i18n/deu/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Steuert, ob eine Inlineaktion zum Öffnen der Datei in der Ansicht \"Git-Änderungen\" angezeigt wird.", "config.inputValidation": "Steuert, wann die Commit-Meldung der Eingabevalidierung angezeigt wird.", "config.detectSubmodules": "Steuert, ob Git-Submodule automatisch erkannt werden.", + "config.detectSubmodulesLimit": "Steuert die Begrenzung der Git-Submodule.", "colors.modified": "Farbe für geänderte Ressourcen.", "colors.deleted": "Farbe für gelöschten Ressourcen.", "colors.untracked": "Farbe für nicht verfolgte Ressourcen.", diff --git a/i18n/deu/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/deu/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..6a6d902507 --- /dev/null +++ b/i18n/deu/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML-Sprachserver", + "folding.start": "Regionsanfang wird gefaltet", + "folding.end": "Regionsende wird gefaltet" +} \ No newline at end of file diff --git a/i18n/deu/extensions/html-language-features/package.i18n.json b/i18n/deu/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..a18d59eb26 --- /dev/null +++ b/i18n/deu/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML-Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für HTML-, Razor- und Handlebar-Dateien.", + "html.format.enable.desc": "Standard-HTML-Formatierer aktivieren/deaktivieren", + "html.format.wrapLineLength.desc": "Die maximale Anzahl von Zeichen pro Zeile (0 = deaktiviert).", + "html.format.unformatted.desc": "Die Liste der Tags (durch Kommas getrennt), die nicht erneut formatiert werden sollen. \"null\" bezieht sich standardmäßig auf alle Tags, die unter https://www.w3.org/TR/html5/dom.html#phrasing-content aufgeführt werden.", + "html.format.contentUnformatted.desc": "Liste der Tags (durch Trennzeichen getrennt), in der der Inhalt nicht neu formatiert werden muss. \"null\" entspricht standardmäßig dem Tag \"pre\".", + "html.format.indentInnerHtml.desc": "Nimmt einen Einzug für <head>- und <body>-Abschnitte vor.", + "html.format.preserveNewLines.desc": "Gibt an, ob vorhandene Zeilenumbrüche vor Elemente beibehalten werden sollen. Funktioniert nur vor Elementen, nicht in Tags oder für Text.", + "html.format.maxPreserveNewLines.desc": "Die maximale Anzahl von Zeilenumbrüchen, die in einem Block beibehalten werden soll. Verwenden Sie \"null\" für eine unbegrenzte Anzahl.", + "html.format.indentHandlebars.desc": "Formatiert {{#foo}} und {{/foo}} und nimmt einen Einzug vor.", + "html.format.endWithNewline.desc": "Endet mit einer neuen Zeile.", + "html.format.extraLiners.desc": "Die Liste der Tags (durch Kommas getrennt), vor denen eine zusätzliche neue Zeile eingefügt werden soll. \"null\" verwendet standardmäßig \"head, body, /HTML\".", + "html.format.wrapAttributes.desc": "Attribute umschließen.", + "html.format.wrapAttributes.auto": "Attribute nur dann umschließen, wenn die Zeilenlänge überschritten wird.", + "html.format.wrapAttributes.force": "Jedes Attribut mit Ausnahme des ersten umschließen.", + "html.format.wrapAttributes.forcealign": "Jedes Attribut mit Ausnahme des ersten umschließen und Ausrichtung beibehalten.", + "html.format.wrapAttributes.forcemultiline": "Jedes Attribut umschließen.", + "html.suggest.angular1.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung Angular V1-Tags und -Eigenschaften vorschlägt.", + "html.suggest.ionic.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung Ionic-Tags, -Eigenschaften und -Werte vorschlägt.", + "html.suggest.html5.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung HTML5-Tags, -Eigenschaften und -Werte vorschlägt.", + "html.trace.server.desc": "Verfolgt die Kommunikation zwischen VS Code und dem HTML-Sprachserver.", + "html.validate.scripts": "Konfiguriert, ob die integrierte HTML-Sprachunterstützung eingebettete Skripts unterstützt.", + "html.validate.styles": "Konfiguriert, ob die integrierte HTML-Sprachunterstützung eingebettete Skripts validiert.", + "html.autoClosingTags": "Automatisches Schließen von HTML-Tags aktivieren/deaktivieren." +} \ No newline at end of file diff --git a/i18n/deu/extensions/html/package.i18n.json b/i18n/deu/extensions/html/package.i18n.json index 99dfdf4169..9ce5789f79 100644 --- a/i18n/deu/extensions/html/package.i18n.json +++ b/i18n/deu/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML-Sprachfeatures", - "description": "Bietet umfangreiche Sprachunterstützung für HTML-, Razor- und Handlebar-Dateien.", - "html.format.enable.desc": "Standard-HTML-Formatierer aktivieren/deaktivieren", - "html.format.wrapLineLength.desc": "Die maximale Anzahl von Zeichen pro Zeile (0 = deaktiviert).", - "html.format.unformatted.desc": "Die Liste der Tags (durch Kommas getrennt), die nicht erneut formatiert werden sollen. \"null\" bezieht sich standardmäßig auf alle Tags, die unter https://www.w3.org/TR/html5/dom.html#phrasing-content aufgeführt werden.", - "html.format.contentUnformatted.desc": "Liste der Tags (durch Trennzeichen getrennt), in der der Inhalt nicht neu formatiert werden muss. \"null\" entspricht standardmäßig dem Tag \"pre\".", - "html.format.indentInnerHtml.desc": "Nimmt einen Einzug für <head>- und <body>-Abschnitte vor.", - "html.format.preserveNewLines.desc": "Gibt an, ob vorhandene Zeilenumbrüche vor Elemente beibehalten werden sollen. Funktioniert nur vor Elementen, nicht in Tags oder für Text.", - "html.format.maxPreserveNewLines.desc": "Die maximale Anzahl von Zeilenumbrüchen, die in einem Block beibehalten werden soll. Verwenden Sie \"null\" für eine unbegrenzte Anzahl.", - "html.format.indentHandlebars.desc": "Formatiert {{#foo}} und {{/foo}} und nimmt einen Einzug vor.", - "html.format.endWithNewline.desc": "Endet mit einer neuen Zeile.", - "html.format.extraLiners.desc": "Die Liste der Tags (durch Kommas getrennt), vor denen eine zusätzliche neue Zeile eingefügt werden soll. \"null\" verwendet standardmäßig \"head, body, /HTML\".", - "html.format.wrapAttributes.desc": "Attribute umschließen.", - "html.format.wrapAttributes.auto": "Attribute nur dann umschließen, wenn die Zeilenlänge überschritten wird.", - "html.format.wrapAttributes.force": "Jedes Attribut mit Ausnahme des ersten umschließen.", - "html.format.wrapAttributes.forcealign": "Jedes Attribut mit Ausnahme des ersten umschließen und Ausrichtung beibehalten.", - "html.format.wrapAttributes.forcemultiline": "Jedes Attribut umschließen.", - "html.suggest.angular1.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung Angular V1-Tags und -Eigenschaften vorschlägt.", - "html.suggest.ionic.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung Ionic-Tags, -Eigenschaften und -Werte vorschlägt.", - "html.suggest.html5.desc": "Konfiguriert, ob die integrierte HTML-Sprachuntersützung HTML5-Tags, -Eigenschaften und -Werte vorschlägt.", - "html.trace.server.desc": "Verfolgt die Kommunikation zwischen VS Code und dem HTML-Sprachserver.", - "html.validate.scripts": "Konfiguriert, ob die integrierte HTML-Sprachunterstützung eingebettete Skripts unterstützt.", - "html.validate.styles": "Konfiguriert, ob die integrierte HTML-Sprachunterstützung eingebettete Skripts validiert.", - "html.experimental.syntaxFolding": "Aktiviert bzw. deaktiviert syntaxabhängige Faltungsmarkierungen.", - "html.autoClosingTags": "Automatisches Schließen von HTML-Tags aktivieren/deaktivieren." + "displayName": "HTML-Sprachgrundlagen", + "description": "Bietet Syntaxhervorhebung, Klammernpaare und Ausschnitte in HTML-Dateien." } \ No newline at end of file diff --git a/i18n/deu/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/deu/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..fa24cd1104 --- /dev/null +++ b/i18n/deu/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON-Sprachserver" +} \ No newline at end of file diff --git a/i18n/deu/extensions/json-language-features/package.i18n.json b/i18n/deu/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..422563eeb7 --- /dev/null +++ b/i18n/deu/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON-Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für JSON-Dateien.", + "json.schemas.desc": "Schemas zu JSON-Dateien im aktuellen Projekt zuordnen", + "json.schemas.url.desc": "Eine URL zu einem Schema oder ein relativer Pfad zu einem Schema im aktuellen Verzeichnis", + "json.schemas.fileMatch.desc": "Ein Array von Dateimustern, mit dem beim Auflösen von JSON-Dateien zu Schemas ein Abgleich erfolgt.", + "json.schemas.fileMatch.item.desc": "Ein Dateimuster, das \"*\" enthalten kann, mit dem beim Auflösen von JSON-Dateien zu Schemas ein Abgleich erfolgt.", + "json.schemas.schema.desc": "Die Schemadefinition für die angegebene URL. Das Schema muss nur angegeben werden, um Zugriffe auf die Schema-URL zu vermeiden.", + "json.format.enable.desc": "Standard-JSON-Formatierer aktivieren/deaktivieren (Neustart erforderlich)", + "json.tracing.desc": "Verfolgt die Kommunikation zwischen VS Code und JSON-Sprachserver nach.", + "json.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", + "json.colorDecorators.enable.deprecationMessage": "Die Einstellung \"json.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt." +} \ No newline at end of file diff --git a/i18n/deu/extensions/json/package.i18n.json b/i18n/deu/extensions/json/package.i18n.json index 6c8abe1cb3..b9be795e73 100644 --- a/i18n/deu/extensions/json/package.i18n.json +++ b/i18n/deu/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON-Sprachfeatures", - "description": "Bietet umfangreiche Sprachunterstützung für JSON-Dateien.", - "json.schemas.desc": "Schemas zu JSON-Dateien im aktuellen Projekt zuordnen", - "json.schemas.url.desc": "Eine URL zu einem Schema oder ein relativer Pfad zu einem Schema im aktuellen Verzeichnis", - "json.schemas.fileMatch.desc": "Ein Array von Dateimustern, mit dem beim Auflösen von JSON-Dateien zu Schemas ein Abgleich erfolgt.", - "json.schemas.fileMatch.item.desc": "Ein Dateimuster, das \"*\" enthalten kann, mit dem beim Auflösen von JSON-Dateien zu Schemas ein Abgleich erfolgt.", - "json.schemas.schema.desc": "Die Schemadefinition für die angegebene URL. Das Schema muss nur angegeben werden, um Zugriffe auf die Schema-URL zu vermeiden.", - "json.format.enable.desc": "Standard-JSON-Formatierer aktivieren/deaktivieren (Neustart erforderlich)", - "json.tracing.desc": "Verfolgt die Kommunikation zwischen VS Code und JSON-Sprachserver nach.", - "json.colorDecorators.enable.desc": "Aktiviert oder deaktiviert Farb-Decorators", - "json.colorDecorators.enable.deprecationMessage": "Die Einstellung \"json.colorDecorators.enable\" ist veraltet und wurde durch \"editor.colorDecorators\" ersetzt.", - "json.experimental.syntaxFolding": "Aktiviert bzw. deaktiviert die syntaxabhängigen Faltungsmarkierungen." + "displayName": "JSON-Sprachgrundlagen", + "description": "Bietet Syntaxhervorhebung und Klammernpaare in JSON-Dateien." } \ No newline at end of file diff --git a/i18n/deu/extensions/markdown-basics/package.i18n.json b/i18n/deu/extensions/markdown-basics/package.i18n.json index b2d7d41efc..2cf88a1e68 100644 --- a/i18n/deu/extensions/markdown-basics/package.i18n.json +++ b/i18n/deu/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/deu/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/deu/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..fdc135e8be --- /dev/null +++ b/i18n/deu/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "'markdown.styles' konnte nicht geladen werden: {0}" +} \ No newline at end of file diff --git a/i18n/deu/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/deu/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..145213b7b2 --- /dev/null +++ b/i18n/deu/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Vorschau] {0}", + "previewTitle": "Vorschau von {0}" +} \ No newline at end of file diff --git a/i18n/deu/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/deu/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..1793456fe9 --- /dev/null +++ b/i18n/deu/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "In diesem Dokument wurden einige Inhalte deaktiviert.", + "preview.securityMessage.title": "Potenziell unsichere Inhalte wurden in der Markdown-Vorschau deaktiviert. Ändern Sie die Sicherheitseinstellung der Markdown-Vorschau, um unsichere Inhalte zuzulassen oder Skripts zu aktivieren.", + "preview.securityMessage.label": "Sicherheitswarnung – Inhalt deaktiviert" +} \ No newline at end of file diff --git a/i18n/deu/extensions/markdown-language-features/out/security.i18n.json b/i18n/deu/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..c59e06479c --- /dev/null +++ b/i18n/deu/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Strict", + "strict.description": "Nur sicheren Inhalt laden", + "insecureLocalContent.title": "Unsichere lokale Inhalte zulassen", + "insecureLocalContent.description": "Laden von Inhalten über HTTP von localhost aktivieren", + "insecureContent.title": "Unsicheren Inhalt zulassen", + "insecureContent.description": "Laden von Inhalten über HTTP aktivieren", + "disable.title": "Deaktivieren", + "disable.description": "Alle Inhalte und Skriptausführung zulassen. Nicht empfohlen.", + "moreInfo.title": "Weitere Informationen", + "enableSecurityWarning.title": "Vorschau von Sicherheitswarnungen in diesem Arbeitsbereich aktivieren", + "disableSecurityWarning.title": "Vorschau von Sicherheitswarnungen in diesem Arbeitsbereich deaktivieren ", + "toggleSecurityWarning.description": "Hat keinen Einfluss auf die Inhaltssicherheitsebene", + "preview.showPreviewSecuritySelector.title": "Sicherheitseinstellungen für die Markdown-Vorschau in diesem Arbeitsbereich auswählen" +} \ No newline at end of file diff --git a/i18n/deu/extensions/markdown-language-features/package.i18n.json b/i18n/deu/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..8a886edcb0 --- /dev/null +++ b/i18n/deu/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown-Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für Markdown.", + "markdown.preview.breaks.desc": "Legt fest, wie Zeilenumbrüche in der Markdown-Vorschau gerendert werden. Die Einstellung 'true' erzeugt ein <br> für jede neue Zeile.", + "markdown.preview.linkify": "Aktiviert oder deaktiviert die Konvertierung von URL-ähnlichem Text in Links in der Markdown-Vorschau.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Doppelklicken Sie in die Markdown-Vorschau, um zum Editor zu wechseln.", + "markdown.preview.fontFamily.desc": "Steuert die Schriftfamilie, die in der Markdownvorschau verwendet wird.", + "markdown.preview.fontSize.desc": "Steuert den Schriftgrad in Pixeln, der in der Markdownvorschau verwendet wird.", + "markdown.preview.lineHeight.desc": "Steuert die Zeilenhöhe, die in der Markdownvorschau verwendet wird. Diese Zahl ist relativ zum Schriftgrad.", + "markdown.preview.markEditorSelection.desc": "Markieren Sie die aktuelle Editor-Auswahl in der Markdown-Vorschau.", + "markdown.preview.scrollEditorWithPreview.desc": "Wenn für eine Markdown-Vorschau ein Bildlauf durchgeführt wird, die Ansicht des Editors aktualisieren.", + "markdown.preview.scrollPreviewWithEditor.desc": "Wenn für die Markdown-Vorschau ein Bildlauf durchgeführt wird, aktualisieren Sie die Ansicht der Vorschau.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Veraltet] Führt einen Bildlauf für die Markdown-Vorschau durch, um die aktuell ausgewählte Zeile im Editor anzuzeigen.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Diese Einstellung wurde durch \"markdown.preview.scrollPreviewWithEditor\" ersetzt und ist nicht mehr wirksam.", + "markdown.preview.title": "Vorschau öffnen", + "markdown.previewFrontMatter.dec": "Legt fest, wie die YAML-Titelei in der Markdownvorschau gerendert werden soll. Durch \"hide\" wird die Titelei entfernt. Andernfalls wird die Titelei wie Markdowninhalt verarbeitet.", + "markdown.previewSide.title": "Vorschau an der Seite öffnen", + "markdown.showLockedPreviewToSide.title": "Gesperrte Vorschau an der Seite öffnen", + "markdown.showSource.title": "Quelle anzeigen", + "markdown.styles.dec": "Eine Liste von URLs oder lokalen Pfaden zu CSS-Stylesheets aus der Markdownvorschau, die verwendet werden sollen. Relative Pfade werden relativ zu dem Ordner interpretiert, der im Explorer geöffnet ist. Wenn kein Ordner geöffnet ist, werden sie relativ zum Speicherort der Markdowndatei interpretiert. Alle '\\' müssen als '\\\\' geschrieben werden.", + "markdown.showPreviewSecuritySelector.title": "Sicherheitseinstellungen für Vorschau ändern", + "markdown.trace.desc": "Aktiviert die Debugprotokollierung für die Markdown-Erweiterung.", + "markdown.preview.refresh.title": "Vorschau aktualisieren", + "markdown.preview.toggleLock.title": "Vorschausperre umschalten" +} \ No newline at end of file diff --git a/i18n/deu/extensions/markdown/out/features/preview.i18n.json b/i18n/deu/extensions/markdown/out/features/preview.i18n.json index 4dc765627c..145213b7b2 100644 --- a/i18n/deu/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/deu/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/deu/extensions/npm/out/npmView.i18n.json b/i18n/deu/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..e56a09ae55 --- /dev/null +++ b/i18n/deu/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "\"{0}\" konnte nicht zum Debuggen gestartet werden, da die Skripte keine Node-Debugging-Option enthalten wie z. B. \"--inspect-brk\".", + "npm.scriptInvalid": "Das Skript \"{0}\" wurde nicht gefunden. Versuchen Sie, die Ansicht zu aktualisieren." +} \ No newline at end of file diff --git a/i18n/deu/extensions/npm/out/tasks.i18n.json b/i18n/deu/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..a918970a63 --- /dev/null +++ b/i18n/deu/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "NPM-Aufgabenerkennung: Fehler beim Analysieren der Datei {0}" +} \ No newline at end of file diff --git a/i18n/deu/extensions/npm/package.i18n.json b/i18n/deu/extensions/npm/package.i18n.json index 05d6dd4975..ba906568b8 100644 --- a/i18n/deu/extensions/npm/package.i18n.json +++ b/i18n/deu/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "npm-Befehle mit der Option \"--silent\" ausführen.", "config.npm.packageManager": "Der zu verwendende Paket-Manager, um Skripte auszuführen.", "config.npm.exclude": "Konfigurieren Sie Globmuster für Ordner, die von der automatischen Skripterkennung ausgeschlossen werden sollen.", + "config.npm.enableScriptExplorer": "Explorer-Ansicht für NPM-Skripte aktivieren, wenn der Arbeitsbereich die Datei \"package.json\" enthält.", "npm.parseError": "NPM-Aufgabenerkennung: Fehler beim Analysieren der Datei {0}", "taskdef.script": "Das anzupassende NPM-Skript.", - "taskdef.path": "Der Pfad zu dem Ordner der Datei vom Typ \"package.json\", die das Skript bereitstellt. Kann ausgelassen werden." + "taskdef.path": "Der Pfad zu dem Ordner der Datei vom Typ \"package.json\", die das Skript bereitstellt. Kann ausgelassen werden.", + "view.name": "NPM-Skripte", + "command.refresh": "Aktualisieren", + "command.run": "Ausführen", + "command.debug": "Debuggen", + "command.openScript": "Öffnen", + "npm.scriptInvalid": "Das Skript \"{0}\" wurde nicht gefunden. Versuchen Sie, die Ansicht zu aktualisieren.", + "npm.noDebugOptions": "\"{0}\" konnte nicht zum Debuggen gestartet werden, da die Skripte keine Node-Debugging-Option enthalten wie z. B. \"--inspect-brk\"." } \ No newline at end of file diff --git a/i18n/deu/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/deu/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..5805f86da6 --- /dev/null +++ b/i18n/deu/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Möchten Sie zulassen, dass {0} (als Arbeitsbereichseinstellung definiert) zum Bereinigen von PHP-Dateien ausgeführt wird?", + "php.yes": "Zulassen", + "php.no": "Nicht zulassen", + "wrongExecutable": "Eine Überprüfung ist nicht möglich, da {0} keine gültige ausführbare PHP-Datei ist. Verwenden Sie die Einstellung \"'php.validate.executablePath\", um die ausführbare PHP-Datei zu konfigurieren.", + "noExecutable": "Eine Überprüfung ist nicht möglich, da keine ausführbare PHP-Datei festgelegt ist. Verwenden Sie die Einstellung \"php.validate.executablePath\", um die ausführbare PHP-Datei zu konfigurieren.", + "unknownReason": "Fehler beim Ausführen von PHP mithilfe des Pfads \"{0}\". Die Ursache ist unbekannt." +} \ No newline at end of file diff --git a/i18n/deu/extensions/php-language-features/package.i18n.json b/i18n/deu/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..7124411caa --- /dev/null +++ b/i18n/deu/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Konfiguriert, ob die integrierten PHP-Sprachvorschläge aktiviert sind. Die Unterstützung schlägt globale und variable PHP-Elemente vor.", + "configuration.validate.enable": "Integrierte PHP-Überprüfung aktivieren/deaktivieren.", + "configuration.validate.executablePath": "Zeigt auf die ausführbare PHP-Datei.", + "configuration.validate.run": "Gibt an, ob der Linter beim Speichern oder bei der Eingabe ausgeführt wird.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "Ausführbare Datei für PHP-Überprüfung nicht zulassen (als Arbeitsbereicheinstellung definiert)", + "displayName": "PHP-Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für PHP-Dateien." +} \ No newline at end of file diff --git a/i18n/deu/extensions/php/package.i18n.json b/i18n/deu/extensions/php/package.i18n.json index e3c46ffdde..5c068410d3 100644 --- a/i18n/deu/extensions/php/package.i18n.json +++ b/i18n/deu/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Konfiguriert, ob die integrierten PHP-Sprachvorschläge aktiviert sind. Die Unterstützung schlägt globale und variable PHP-Elemente vor.", - "configuration.validate.enable": "Integrierte PHP-Überprüfung aktivieren/deaktivieren.", - "configuration.validate.executablePath": "Zeigt auf die ausführbare PHP-Datei.", - "configuration.validate.run": "Gibt an, ob der Linter beim Speichern oder bei der Eingabe ausgeführt wird.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "Ausführbare Datei für PHP-Überprüfung nicht zulassen (als Arbeitsbereicheinstellung definiert)", - "displayName": "PHP-Sprachfeatures", - "description": "Bietet IntelliSense, Bereinigen und Sprachgrundlagen für PHP-Dateien." + "displayName": "PHP-Sprachgrundlagen", + "description": "Bietet Syntaxhervorhebung und Klammernpaare für PHP-Dateien." } \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/commands.i18n.json b/i18n/deu/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..cdebacc88d --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Öffnen Sie einen Ordner in VS Code, um ein TypeScript- oder JavaScript-Projekt zu verwenden.", + "typescript.projectConfigUnsupportedFile": "TypeScript- oder JavaScript-Projekt konnte nicht ermittelt werden. Nicht unterstützter Dateityp.", + "typescript.projectConfigCouldNotGetInfo": "TypeScript- oder JavaScript-Projekt konnte nicht ermittelt werden.", + "typescript.noTypeScriptProjectConfig": "Datei ist nicht Teil eines TypeScript-Projekt. Klicken Sie [hier]({0}), um mehr zu erfahren.", + "typescript.noJavaScriptProjectConfig": "Datei ist nicht Teil eines JavaScript-Projekt. Klicken Sie [hier]({0}), um mehr zu erfahren.", + "typescript.configureTsconfigQuickPick": "tsconfig.json konfigurieren", + "typescript.configureJsconfigQuickPick": "jsconfig.json konfigurieren" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..c1be716a2f --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Anzuwendende Codeaktion auswählen", + "acquiringTypingsLabel": "Eingaben werden abgerufen...", + "acquiringTypingsDetail": "Eingabedefinitionen für IntelliSense werden abgerufen.", + "autoImportLabel": "Automatischer Import von {0}" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..ab837c60f3 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Aktiviert die Semantiküberprüfung in einer JavaScript-Datei. Muss sich oben in einer Datei befinden.", + "ts-nocheck": "Deaktiviert die Semantiküberprüfung in einer JavaScript-Datei. Muss sich oben in einer Datei befinden.", + "ts-ignore": "Unterdrückt @ts-check-Fehler in der nächsten Zeile einer Datei." +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..2dd478f859 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 Implementierung", + "manyImplementationLabel": "{0}-Implementierungen", + "implementationsErrorLabel": "Implementierungen konnten nicht bestimmt werden" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..e5e06fc03c --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc-Kommentar" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..9df063abf4 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Importe organisieren" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..e0e88f5e50 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Behebe alle in Datei)" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..73d84e6a38 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 Verweis", + "manyReferenceLabel": "{0} Verweise", + "referenceErrorLabel": "Verweise konnten nicht bestimmt werden" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..8d79b969df --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "Erstellen – {0}", + "buildAndWatchTscLabel": "Überwachen – {0}" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/deu/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..eb955bb9c0 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "Der Pfad \"{0}\" zeigt nicht auf eine gültige tsserver-Installation. Fallback auf gebündelte TypeScript-Version wird durchgeführt.", + "serverCouldNotBeStarted": "Der TypeScript-Sprachserver konnte nicht gestartet werden. Fehlermeldung: {0}", + "typescript.openTsServerLog.notSupported": "Die TS Server-Protokollierung erfordert TS 2.2.2+.", + "typescript.openTsServerLog.loggingNotEnabled": "Die TS Server-Protokollierung ist deaktiviert. Legen Sie \"typescript.tsserver.log\" fest, und laden Sie VS Code erneut, um die Protokollierung zu aktivieren.", + "typescript.openTsServerLog.enableAndReloadOption": "Aktiviert die Protokollierung und startet den TS-Server neu.", + "typescript.openTsServerLog.noLogFile": "TS Server hat noch nicht mit der Protokollierung begonnen.", + "openTsServerLog.openFileFailedFailed": "Die TS-Server-Protokolldatei konnte nicht geöffnet werden.", + "serverDiedAfterStart": "Der TypeScript-Sprachdienst wurde direkt nach seinem Start fünfmal beendet. Der Dienst wird nicht neu gestartet.", + "serverDiedReportIssue": "Problem melden", + "serverDied": "Der TypeScript-Sprachdienst wurde während der letzten fünf Minuten fünfmal unerwartet beendet." +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..e381d6d3b7 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "Ungültige Version" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..b36d5e0aec --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Um die JavaScript/TypeScript-Sprachfunktionen für das gesamte Projekt zu aktivieren, schließen Sie Ordner mit vielen Dateien aus. Beispiel: {0}", + "hintExclude.generic": "Um JavaScript/TypeScript-Sprachfunktionen für das gesamte Projekt zu aktivieren, schließen Sie große Ordner mit Quelldateien aus, an denen Sie nicht arbeiten.", + "large.label": "Auszuschließende Elemente konfigurieren", + "hintExclude.tooltip": "Um JavaScript/TypeScript-Sprachfunktionen für das gesamte Projekt zu aktivieren, schließen Sie große Ordner mit Quelldateien aus, an denen Sie nicht arbeiten." +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..797c586cb3 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Daten werden zum Optimieren von TypeScript IntelliSense abgerufen", + "typesInstallerInitializationFailed.title": "Typisierungsdateien für JavaScript-Sprachfunktionen konnten nicht installiert werden. Stellen Sie sicher, das NPM installiert ist, oder konfigurieren Sie \"typescript.npm\" in Ihren Benutzereinstellungen. Klicken Sie [hier]({0}), um mehr zu erfahren.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Nicht mehr anzeigen" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..9414ff7601 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Version von VS Code verwenden", + "useWorkspaceVersionOption": "Arbeitsbereichsversion verwenden", + "learnMore": "Weitere Informationen", + "selectTsVersion": "Wählen Sie die für die JavaScript- und TypeScript-Sprachfunktionen verwendete TypeScript-Version aus." +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/deu/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..4d94a01dc6 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Die TypeScript-Version konnte unter diesem Pfad nicht geladen werden.", + "noBundledServerFound": "Der tsserver von VS Code wurde von einer anderen Anwendung wie etwa einem fehlerhaften Tool zur Viruserkennung gelöscht. Führen Sie eine Neuinstallation von VS Code durch." +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript-language-features/package.i18n.json b/i18n/deu/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..8fa1df1b16 --- /dev/null +++ b/i18n/deu/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript- und JavaScript-Sprachfeatures", + "description": "Bietet umfangreiche Sprachunterstützung für JavaScript und TypeScript.", + "typescript.reloadProjects.title": "Projekt erneut laden", + "javascript.reloadProjects.title": "Projekt erneut laden", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Vervollständigen Sie Funktionen mit deren Parametersignatur.", + "typescript.tsdk.desc": "Gibt den Ordnerpfad mit den zu verwendenden tsserver- und lib*.d.ts-Dateien an.", + "typescript.disableAutomaticTypeAcquisition": "Deaktiviert die automatische Typerfassung. Erfordert TypeScript >= 2.0.6.", + "typescript.tsserver.log": "Aktiviert die Protokollierung des TS-Servers in eine Datei. Mithilfe der Protokolldatei lassen sich Probleme beim TS-Server diagnostizieren. Die Protokolldatei kann Dateipfade, Quellcode und weitere potenziell sensible Informationen aus Ihrem Projekt enthalten.", + "typescript.tsserver.pluginPaths": "Zusätzliche Pfade zum Suchen von Typescript Language Service-Plug-Ins. Erfordert TypeScript 2.3.0 oder höher. ", + "typescript.tsserver.pluginPaths.item": "Ein absoluter oder relativer Pfad. Ein relativer Pfad wird in Bezug auf die Arbeitsbereichsordner aufgelöst.", + "typescript.tsserver.trace": "Aktiviert die Ablaufverfolgung von an den TS-Server gesendeten Nachrichten. Mithilfe der Ablaufverfolgung lassen sich Probleme beim TS-Server diagnostizieren. Die Ablaufverfolgung kann Dateipfade, Quellcode und weitere potenziell sensible Informationen aus Ihrem Projekt enthalten.", + "typescript.validate.enable": "TypeScript-Überprüfung aktivieren/deaktivieren.", + "typescript.format.enable": "Standardmäßigen TypeScript-Formatierer aktivieren/deaktivieren.", + "javascript.format.enable": "Standardmäßigen JavaScript-Formatierer aktivieren/deaktivieren.", + "format.insertSpaceAfterCommaDelimiter": "Definiert die Verarbeitung von Leerzeichen nach einem Kommatrennzeichen.", + "format.insertSpaceAfterConstructor": "Definiert die Verarbeitung von Leerzeichen nach dem Konstruktor-Schlüsselwort. Erfordert TypeScript 2.3.0 oder höher.", + "format.insertSpaceAfterSemicolonInForStatements": " Definiert die Verarbeitung von Leerzeichen nach einem Semikolon in einer for-Anweisung.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Definiert die Verarbeitung von Leerzeichen nach einem binären Operator.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Definiert die Verarbeitung von Leerzeichen nach Schlüsselwörtern in einer Flusssteuerungsanweisung.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Definiert die Verarbeitung von Leerzeichen nach einem Funktionsschlüsselwort für anonyme Funktionen.", + "format.insertSpaceBeforeFunctionParenthesis": "Definiert die Verarbeitung von Leerzeichen vor Funktionsargumentklammern. Erfordert TypeScript >= 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Definiert die Verarbeitung von Leerzeichen nach öffnenden und vor schließenden nicht leeren runden Klammern.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Definiert die Verarbeitung von Leerzeichen nach öffnenden und vor schließenden nicht leeren eckigen Klammern.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Definiert die Verarbeitung von Leerzeichen nach öffnenden und vor schließenden nicht leeren geschweiften Klammern. Erfordert TypeScript 2.3.0 oder höher.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Definiert die Verarbeitung von Leerzeichen nach öffnenden und vor schließenden geschweiften Klammern für Vorlagenzeichenfolgen. Erfordert TypeScript >= 2.0.6.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Definiert die Verarbeitung von Leerzeichen nach öffnenden und vor schließenden geschweiften Klammern für JSX-Ausdrücke. Erfordert TypeScript >= 2.0.6.", + "format.insertSpaceAfterTypeAssertion": "Definiert die Verarbeitung von Leerzeichen nach Typassertionen in TypeScript. Erfordert TypeScript >= 2.4.", + "format.placeOpenBraceOnNewLineForFunctions": "Definiert, ob eine öffnende geschweifte Klammer für Funktionen in eine neue Zeile eingefügt wird.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Definiert, ob eine öffnende geschweifte Klammer für Kontrollblöcke in eine neue Zeile eingefügt wird.", + "javascript.validate.enable": "JavaScript-Überprüfung aktivieren/deaktivieren.", + "typescript.goToProjectConfig.title": "Zur Projektkonfiguration wechseln", + "javascript.goToProjectConfig.title": "Zur Projektkonfiguration wechseln", + "javascript.referencesCodeLens.enabled": "Aktiviert oder deaktiviert CodeLens-Verweise in JavaScript Dateien. Erfordert TypeScript 2.0.6 oder höher.", + "typescript.referencesCodeLens.enabled": "Aktiviert oder deaktiviert CodeLens-Verweise in TypeScript Dateien. Erfordert TypeScript 2.0.6 oder höher.", + "typescript.implementationsCodeLens.enabled": "Aktiviert oder deaktiviert CodeLens-Implementierungen. Erfordert TypeScript 2.2.0 oder höher.", + "typescript.openTsServerLog.title": "TS Server-Protokolldatei öffnen", + "typescript.restartTsServer": "TS Server neu starten", + "typescript.selectTypeScriptVersion.title": "TypeScript-Version wählen", + "typescript.reportStyleChecksAsWarnings": "Formatvorlagenprüfungen als Warnungen melden", + "jsDocCompletion.enabled": "Automatische JSDoc-Kommentare aktivieren/deaktivieren", + "javascript.implicitProjectConfig.checkJs": "Aktiviert/deaktiviert die Semantikprüfung bei JavaScript-Dateien. Diese Einstellung wird von vorhandenen \"jsconfig.json\"- oder \"tsconfig.json\"-Dateien außer Kraft gesetzt. Erfordert TypeScript 2.3.1 oder höher.", + "typescript.npm": "Gibt den Pfad zur ausführbaren NPM-Datei an, die für die automatische Typerfassung verwendet wird. Hierfür ist TypeScript 2.3.4 oder höher erforderlich.", + "typescript.check.npmIsInstalled": "Überprüfen Sie, ob NPM für die automatische Typerfassung installiert ist.", + "javascript.nameSuggestions": "Das Einbeziehen eindeutiger Namen von der Datei in der JavaScript-Vorschlagsliste aktivieren/deaktivieren.", + "typescript.tsc.autoDetect": "Steuert die automatische Erkennung von TSC-Aufgaben. \"Aus\" deaktiviert diese Funktion. \"Build\" erstellt nur Kompilierungsaufgaben mit einer Ausführung. \"Überwachen\" erstellt nur Kompilierungs- und Überwachungsaufgaben. \"Ein\" erstellt sowohl Build- als auch Überwachungsaufgaben. Der Standardwert ist \"Ein\".", + "typescript.problemMatchers.tsc.label": "TypeScript-Probleme", + "typescript.problemMatchers.tscWatch.label": "TypeScript-Probleme (Überwachungsmodus)", + "typescript.quickSuggestionsForPaths": "Aktiviert oder deaktiviert Schnellvorschläge, wenn Sie einen Importpfad ausschreiben.", + "typescript.locale": "Legt das zum Melden von TypeScript-Fehlern verwendete Gebietsschema fest. Erfordert TypeScript 2.6.0 oder höher. Der Standardwert \"null\" verwendet für TypeScript-Fehler das Gebietsschema von VS Code.", + "javascript.implicitProjectConfig.experimentalDecorators": "Aktiviert oder deaktiviert \"experimentalDecorators\" für JavaScript-Dateien, die nicht Teil eines Projekts sind. Vorhandene jsconfig.json- oder tsconfig.json-Dateien setzen diese Einstellung außer Kraft. Erfordert TypeScript 2.3.1 oder höher.", + "typescript.autoImportSuggestions.enabled": "Aktiviert oder deaktiviert Vorschläge für den automatischen Import. Erfordert TypeScript 2.6.1 oder höher.", + "typescript.experimental.syntaxFolding": "Aktiviert bzw. deaktiviert die syntaxabhängigen Faltungsmarkierungen.", + "taskDefinition.tsconfig.description": "Die \"tsconfig\"-Datei, die den TS-Build definiert.", + "javascript.suggestionActions.enabled": "Aktiviert/deaktiviert Vorschlagsdiagnosen für JavaScript-Dateien im Editor. Erfordert TypeScript 2.8 oder höher.", + "typescript.suggestionActions.enabled": "Aktiviert/deaktiviert Vorschlagsdiagnosen für TypeScript-Dateien im Editor. Erfordert TypeScript 2.8 oder höher." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/base/node/zip.i18n.json b/i18n/deu/src/vs/base/node/zip.i18n.json index f2b0c63687..a509943704 100644 --- a/i18n/deu/src/vs/base/node/zip.i18n.json +++ b/i18n/deu/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Unvollständig. {0} von {1} Einträgen wurden extrahiert", "notFound": "{0} wurde im ZIP nicht gefunden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/deu/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index a8d12c08e0..ee5978abf0 100644 --- a/i18n/deu/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/deu/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "Vorschau in GitHub", "loadingData": "Daten werden geladen …", + "rateLimited": "GitHub-Abfragebeschränkung überschritten. Bitte warten.", "similarIssues": "Ähnliche Probleme", "open": "Öffnen", "closed": "Geschlossen", - "noResults": "Es wurden keine Ergebnisse gefunden.", + "noSimilarIssues": "Keine ähnlichen Probleme gefunden", "settingsSearchIssue": "Fehler in Einstellungssuche ", "bugReporter": "Fehlerbericht", - "performanceIssue": "Leistungsproblem", "featureRequest": "Featureanforderung", + "performanceIssue": "Leistungsproblem", "stepsToReproduce": "Zu reproduzierende Schritte", "bugDescription": "Geben Sie an, welche Schritte ausgeführt werden müssen, um das Problem zuverlässig zu reproduzieren. Was sollte geschehen, und was ist stattdessen geschehen? Wir unterstützen GitHub Flavored Markdown. Sie können während der Vorschau in GitHub Ihr Problem bearbeiten und Screenshots hinzufügen.", "performanceIssueDesciption": "Wann ist dieses Leistungsproblem aufgetreten? Tritt es beispielsweise beim Start oder nach einer bestimmten Reihe von Aktionen auf? Wir unterstützen GitHub Flavored Markdown. Sie können während der Vorschau in GitHub Ihr Problem bearbeiten und Screenshots hinzufügen.", diff --git a/i18n/deu/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/deu/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index be8793d1e1..50c036699d 100644 --- a/i18n/deu/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/deu/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Füllen Sie das Formular auf Englisch aus.", "issueTypeLabel": "Dies ist", + "issueSourceLabel": "Datei auf", + "vscode": "Visual Studio Code", + "extension": "Eine Erweiterung", + "disableExtensionsLabelText": "Versuchen Sie, das Problem nach {0} zu reproduzieren. Wenn das Problem nur bei aktiven Erweiterungen reproduziert werden kann, besteht wahrscheinlich ein Problem bei einer Erweiterung.", + "disableExtensions": "Alle Erweiterungen werden deaktiviert, und das Fenster wird neu geladen", + "chooseExtension": "Erweiterung", "issueTitleLabel": "Titel", "issueTitleRequired": "Geben Sie einen Titel ein.", "titleLengthValidation": "Der Titel ist zu lang.", @@ -18,13 +24,6 @@ "extensions": "Eigene Erweiterungen", "searchedExtensions": "Gesuchte Erweiterungen", "settingsSearchDetails": "Details der Einstellungssuche", - "tryDisablingExtensions": "Kann das Problem reproduziert werden, wenn Erweiterungen deaktiviert sind?", - "yes": "Ja", - "no": "Nein", - "disableExtensionsLabelText": "Versuchen Sie, das Problem nach {0} zu reproduzieren.", - "disableExtensions": "Alle Erweiterungen werden deaktiviert, und das Fenster wird neu geladen", - "showRunningExtensionsLabelText": "Wenn Sie ein Erweiterungsproblem vermuten, melden Sie dieses Problem durch {0}.", - "showRunningExtensions": "Alle ausgeführten Erweiterungen anzeigen", "details": "Geben Sie Details ein.", "loadingData": "Daten werden geladen …" } \ No newline at end of file diff --git a/i18n/deu/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/deu/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..a692133c83 --- /dev/null +++ b/i18n/deu/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU (%)", + "memory": "Arbeitsspeicher (MB)", + "pid": "PID", + "name": "Name", + "killProcess": "Prozess beenden", + "forceKillProcess": "Beenden des Prozesses erzwingen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/code/electron-main/menus.i18n.json b/i18n/deu/src/vs/code/electron-main/menus.i18n.json index 6ba6269f8e..e71ea740d4 100644 --- a/i18n/deu/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/deu/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "&&Bedingter Haltepunkt...", "miColumnBreakpoint": "S&&paltenhaltepunkt", "miFunctionBreakpoint": "&&Funktionshaltepunkt...", + "miLogPoint": "&&Protokollpunkt …", "miNewBreakpoint": "&&Neuer Haltepunkt", "miEnableAllBreakpoints": "Alle Haltepunkte aktivieren", "miDisableAllBreakpoints": "A&&lle Haltepunkte deaktivieren", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Alle Fenster zusammenführen", "miToggleDevTools": "&&Entwicklertools umschalten", "miAccessibilityOptions": "&&Optionen für erleichterte Bedienung", + "miOpenProcessExplorerer": "&&Prozess-Explorer öffnen", "miReportIssue": "&&Problem melden", "miWelcome": "&&Willkommen", "miInteractivePlayground": "&&Interactive Spielwiese", diff --git a/i18n/deu/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/deu/src/vs/editor/browser/widget/diffReview.i18n.json index a2f121771e..021ca8a9d7 100644 --- a/i18n/deu/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/deu/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Schließen", - "header": "Unterschied von {0} zu {1}: Original {2}, {3} Zeilen, Geändert {4}, {5} Zeilen", + "no_lines": "keine Zeilen", + "one_line": "1 Zeile", + "more_lines": "{0} Zeilen", + "header": "Unterschied von {0} zu {1}: Original: {2}, {3}, geändert: {4}, {5}", "blankLine": "leer", "equalLine": "Original {0}, geändert {1}: {2}", "insertLine": "+ geändert {0}: {1}", diff --git a/i18n/deu/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/deu/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..ebc919fd7a --- /dev/null +++ b/i18n/deu/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "Die Anzahl der Cursors wurde auf {0} beschränkt." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json index 00a79638a3..05f4d5c9ce 100644 --- a/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "Zeilennummern werden als absolute Zahl dargestellt.", "lineNumbers.relative": "Zeilennummern werden als Abstand in Zeilen an Cursorposition dargestellt.", "lineNumbers.interval": "Zeilennummern werden alle 10 Zeilen dargestellt.", - "lineNumbers": "Steuert die Anzeige von Zeilennummern. Mögliche Werte sind \"on\", \"off\", \"relative\" und \"interval\".", + "lineNumbers": "Steuert die Anzeige von Zeilennummern.", "rulers": "Vertikale Linien nach einer bestimmten Anzahl von Monospace Zeichen zeichnen. Verwenden Sie mehrere Werte für mehrere Linien. Keine Linie wird gezeichnet, wenn das Array leer ist.", "wordSeparators": "Zeichen, die als Worttrennzeichen verwendet werden, wenn wortbezogene Navigationen oder Vorgänge ausgeführt werden.", "tabSize": "Die Anzahl der Leerzeichen, denen ein Tabstopp entspricht. Diese Einstellung wird basierend auf dem Inhalt der Datei überschrieben, wenn \"editor.detectIndentation\" aktiviert ist.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Legt fest, ob der Editor Bildläufe über die letzte Zeile hinaus ausführt.", "smoothScrolling": "Legt fest, ob der Editor Bildläufe animiert ausführt.", "minimap.enabled": "Steuert, ob die Minikarte angezeigt wird", - "minimap.side": "Steuert die Seite, wo die Minikarte gerendert wird. Mögliche Werte sind \"rechts\" und \"links\".", - "minimap.showSlider": "Steuert, ob der Minimap-Schieberegler automatisch ausgeblendet wird. Mögliche Werte sind \"always\" und \"mouseover\".", + "minimap.side": "Steuert die Seite, wo die Minikarte gerendert wird.", + "minimap.showSlider": "Steuert, ob der Minimap-Schieberegler automatisch ausgeblendet wird.", "minimap.renderCharacters": "Die tatsächlichen Zeichen in einer Zeile rendern (im Gegensatz zu Farbblöcken)", "minimap.maxColumn": "Breite der Minikarte beschränken, um höchstens eine bestimmte Anzahl von Spalten zu rendern", "find.seedSearchStringFromSelection": "Steuert, ob wir für die Suchzeichenfolge im Suchwidget aus der Editorauswahl ein Seeding ausführen.", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Ist unter Windows und Linux der Taste \"STRG\" und unter macOSX der Befehlstaste zugeordnet.", "multiCursorModifier.alt": "Ist unter Windows und Linux der Taste \"Alt\" und unter macOSX der Wahltaste zugeordnet. ", "multiCursorModifier": "Der Modifizierer, der zum Hinzufügen mehrerer Cursor mit der Maus verwendet wird. \"ctrlCmd\" wird unter Windows und Linux der Taste \"STRG\" und unter macOSX der Befehlstaste zugeordnet. Die Mausbewegungen \"Gehe zu Definition\" und \"Link öffnen\" werden so angepasst, dass kein Konflikt mit dem Multi-Cursor-Modifizierer entsteht.", + "multiCursorMergeOverlapping": "Mehrere Cursor zusammenführen, wenn sie sich überlappen.", "quickSuggestions.strings": "Schnellvorschläge innerhalb von Zeichenfolgen aktivieren.", "quickSuggestions.comments": "Schnellvorschläge innerhalb von Kommentaren aktivieren.", "quickSuggestions.other": "Schnellvorschläge außerhalb von Zeichenfolgen und Kommentaren aktivieren.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Steuert, ob der Editor das Vorkommen semantischer Symbole markieren soll.", "overviewRulerLanes": "Steuert die Anzahl von Dekorationen, die an derselben Position im Übersichtslineal angezeigt werden.", "overviewRulerBorder": "Steuert, ob um das Übersichtslineal ein Rahmen gezeichnet werden soll.", - "cursorBlinking": "Steuert den Cursoranimationsstil. Gültige Werte sind \"blink\", \"smooth\", \"phase\", \"expand\" und \"solid\".", + "cursorBlinking": "Steuert den Cursoranimationsstil.", "mouseWheelZoom": "Schriftart des Editors vergrößern, wenn das Mausrad verwendet und die STRG-TASTE gedrückt wird", "cursorStyle": "Steuert den Cursorstil. Gültige Werte sind \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" und \"underline-thin\".", "cursorWidth": "Steuert die Breite des Cursors, falls editor.cursorStyle auf \"line\" gestellt ist.", @@ -86,8 +87,11 @@ "renderControlCharacters": "Steuert, ob der Editor Steuerzeichen rendern soll.", "renderIndentGuides": "Steuert, ob der Editor Einzugsführungslinien rendern soll.", "renderLineHighlight": "Steuert, wie der Editor die aktuelle Zeilenhervorhebung rendern soll. Mögliche Werte sind \"none\", \"gutter\", \"line\" und \"all\".", - "codeLens": "Steuert, ob der Editor CodeLenses anzeigt.", + "codeLens": "Steuert, ob der Editor CodeLens anzeigt.", "folding": "Steuert, ob für den Editor Codefaltung aktiviert ist.", + "foldingStrategyAuto": "Falls vorhanden, eine sprachspezifische Strategie für das Codefaltung verwenden, ansonsten wird die einrückungsbasierte Strategie genutzt.", + "foldingStrategyIndentation": "Immer die einrückungsbasierte Strategie zur Codefaltung nutzen", + "foldingStrategy": "Steuert die Art und Weise, wie Faltungsbereiche berechnet werden. \"auto\" verwendet eine sprachspezifische Strategie für die Codefaltung, sofern verfügbar. \"indentation\" erzwingt eine einrückungsbasierte Strategie zur Codefaltung.", "showFoldingControls": "Steuert, ob die Falt-Steuerelemente an der Leiste automatisch ausgeblendet werden.", "matchBrackets": "Übereinstimmende Klammern hervorheben, wenn eine davon ausgewählt wird.", "glyphMargin": "Steuert, ob der Editor den vertikalen Glyphenrand rendert. Der Glyphenrand wird hauptsächlich zum Debuggen verwendet.", @@ -102,8 +106,12 @@ "links": "Steuert, ob der Editor Links erkennen und anklickbar machen soll", "colorDecorators": "Steuert, ob der Editor die Inline-Farbdecorators und die Farbauswahl rendern soll.", "codeActions": "Ermöglicht die Code-Aktion \"lightbulb\"", + "codeActionsOnSave.organizeImports": "Ein Organisieren der Importe beim Speichern ausführen?", + "codeActionsOnSave": "Arten von Codeaktionen, die beim Speichern ausgeführt werden sollen.", + "codeActionsOnSaveTimeout": "Timeout für Codeaktionen, die beim Speichern ausgeführt werden.", "selectionClipboard": "Steuert, ob die primäre Linux-Zwischenablage unterstützt werden soll.", "sideBySide": "Steuert, ob der Diff-Editor das Diff nebeneinander oder inline anzeigt.", "ignoreTrimWhitespace": "Steuert, ob der Diff-Editor Änderungen in führenden oder nachgestellten Leerzeichen als Diffs anzeigt.", + "largeFileOptimizations": "Spezielle Behandlung für große Dateien zum Deaktivieren bestimmter speicherintensiver Funktionen.", "renderIndicators": "Steuert, ob der Diff-Editor die Indikatoren \"+\" und \"-\" für hinzugefügte/entfernte Änderungen anzeigt." } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json index 03577ad7d7..12934235d5 100644 --- a/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "Hintergrundfarbe vom Editor-Cursor. Erlaubt die Anpassung der Farbe von einem Zeichen, welches von einem Block-Cursor überdeckt wird.", "editorWhitespaces": "Farbe der Leerzeichen im Editor.", "editorIndentGuides": "Farbe der Führungslinien für Einzüge im Editor.", + "editorActiveIndentGuide": "Farbe der Führungslinien für Einzüge im aktiven Editor.", "editorLineNumbers": "Zeilennummernfarbe im Editor.", "editorActiveLineNumber": "Zeilennummernfarbe der aktiven Editorzeile.", + "deprecatedEditorActiveLineNumber": "ID ist veraltet. Verwenden Sie stattdessen \"editorLineNumber.activeForeground\".", "editorRuler": "Farbe des Editor-Lineals.", "editorCodeLensForeground": "Vordergrundfarbe der CodeLens-Links im Editor", "editorBracketMatchBackground": "Hintergrundfarbe für zusammengehörige Klammern", @@ -28,7 +30,9 @@ "warningBorder": "Rahmenfarbe von Warnungsunterstreichungen im Editor.", "infoForeground": "Vordergrundfarbe von Informationsunterstreichungen im Editor.", "infoBorder": "Rahmenfarbe von Informationsunterstreichungen im Editor.", - "overviewRulerRangeHighlight": "Übersichtslineal-Markierungsfarbe für Bereichshervorhebungen.", + "hintForeground": "Vordergrundfarbe der Hinweisunterstreichungen im Editor.", + "hintBorder": "Rahmenfarbe der Hinweisunterstreichungen im Editor.", + "overviewRulerRangeHighlight": "Übersichtslineal-Markierungsfarbe für Bereichshervorhebungen. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "overviewRuleError": "Übersichtslineal-Markierungsfarbe für Fehler.", "overviewRuleWarning": "Übersichtslineal-Markierungsfarbe für Warnungen.", "overviewRuleInfo": "Übersichtslineal-Markierungsfarbe für Informationen." diff --git a/i18n/deu/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/deu/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..d3a255e112 --- /dev/null +++ b/i18n/deu/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Korrekturen anzeigen ({0})", + "quickFix": "Korrekturen anzeigen", + "quickfix.trigger.label": "Schnelle Problembehebung …", + "editor.action.quickFix.noneMessage": "Keine Code-Aktionen verfügbar", + "refactor.label": "Umgestalten...", + "editor.action.refactor.noneMessage": "Keine Refactorings verfügbar", + "source.label": "Quellaktion…", + "editor.action.source.noneMessage": "Keine Quellaktionen verfügbar", + "organizeImports.label": "Importe organisieren", + "editor.action.organize.noneMessage": "Keine Aktion zum Organisieren von Importen verfügbar" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/find/findController.i18n.json b/i18n/deu/src/vs/editor/contrib/find/findController.i18n.json index cdb3063abb..7a3b3761be 100644 --- a/i18n/deu/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Suchen", + "startFindWithSelectionAction": "Mit Auswahl suchen", "findNextMatchAction": "Nächstes Element suchen", "findPreviousMatchAction": "Vorheriges Element suchen", "nextSelectionMatchFindAction": "Nächste Auswahl suchen", diff --git a/i18n/deu/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/deu/src/vs/editor/contrib/format/formatActions.i18n.json index 9e6619a564..d0bb0368ca 100644 --- a/i18n/deu/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "{0} Formatierungen zwischen Zeilen {1} und {2} vorgenommen", "no.provider": "Es ist kein Formatierer für \"{0}\"-Dateien installiert. ", "formatDocument.label": "Dokument formatieren", - "formatSelection.label": "Auswahl formatieren" + "no.documentprovider": "Es ist kein Dokument-Formatierer für \"{0}\"-Dateien installiert.", + "formatSelection.label": "Auswahl formatieren", + "no.selectionprovider": "Es ist kein Auswahl-Formatierer für \"{0}\"-Dateien installiert. " } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 9f94b8d210..4a2b893362 100644 --- a/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Gehe zu nächstem Problem (Fehler, Warnung, Information)", - "markerAction.previous.label": "Gehe zu vorigem Problem (Fehler, Warnung, Information)", - "editorMarkerNavigationError": "Editormarkierung: Farbe bei Fehler des Navigationswidgets.", - "editorMarkerNavigationWarning": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", - "editorMarkerNavigationInfo": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", - "editorMarkerNavigationBackground": "Editormarkierung: Hintergrund des Navigationswidgets." + "markerAction.previous.label": "Gehe zu vorigem Problem (Fehler, Warnung, Information)" } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/deu/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..a710ee11dc --- /dev/null +++ b/i18n/deu/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Editormarkierung: Farbe bei Fehler des Navigationswidgets.", + "editorMarkerNavigationWarning": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", + "editorMarkerNavigationInfo": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", + "editorMarkerNavigationBackground": "Editormarkierung: Hintergrund des Navigationswidgets." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/links/links.i18n.json b/i18n/deu/src/vs/editor/contrib/links/links.i18n.json index 4e6f694beb..313f02b872 100644 --- a/i18n/deu/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "STRG + Mausklick zum Aufrufen des Links", "links.command.mac": "Cmd + Klick um Befehl auszuführen", "links.command": "Ctrl + Klick um Befehl auszuführen.", + "links.navigate.al.mac": "WAHLTASTE + Klicken, um Link zu folgen", "links.navigate.al": "ALT + Mausklick zum Aufrufen des Links", + "links.command.al.mac": "WAHLTASTE + Klicken, um Befehl auszuführen", "links.command.al": "Alt + Klick um Befehl auszuführen.", "invalid.url": "Fehler beim Öffnen dieses Links, weil er nicht wohlgeformt ist: {0}", "missing.url": "Fehler beim Öffnen dieses Links, weil das Ziel fehlt.", diff --git a/i18n/deu/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/deu/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..bd19b6b417 --- /dev/null +++ b/i18n/deu/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Ein Bearbeiten ist im schreibgeschützten Editor nicht möglich" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/deu/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 3182f6be25..f2e67c59a1 100644 --- a/i18n/deu/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Hintergrundfarbe des Peek-Editors.", "peekViewEditorGutterBackground": "Hintergrundfarbe der Leiste im Peek-Editor.", "peekViewResultsMatchHighlight": "Farbe für Übereinstimmungsmarkierungen in der Ergebnisliste der Peek-Ansicht.", - "peekViewEditorMatchHighlight": "Farbe für Übereinstimmungsmarkierungen im Peek-Editor." + "peekViewEditorMatchHighlight": "Farbe für Übereinstimmungsmarkierungen im Peek-Editor.", + "peekViewEditorMatchHighlightBorder": "Rahmen für Übereinstimmungsmarkierungen im Peek-Editor." } \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/deu/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..bc7ae23d39 --- /dev/null +++ b/i18n/deu/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Sonntag", + "Monday": "Montag", + "Tuesday": "Dienstag", + "Wednesday": "Mittwoch", + "Thursday": "Donnerstag", + "Friday": "Freitag", + "Saturday": "Samstag", + "SundayShort": "So", + "MondayShort": "Mo", + "TuesdayShort": "Di", + "WednesdayShort": "Mi", + "ThursdayShort": "Do", + "FridayShort": "Fr", + "SaturdayShort": "Sa", + "January": "Januar", + "February": "Februar", + "March": "März", + "April": "April", + "May": "Mai", + "June": "Juni", + "July": "Juli", + "August": "August", + "September": "September", + "October": "Oktober", + "November": "November", + "December": "Dezember", + "JanuaryShort": "Jan", + "FebruaryShort": "Feb", + "MarchShort": "Mar", + "AprilShort": "Apr", + "MayShort": "Mai", + "JuneShort": "Jun", + "JulyShort": "Jul", + "AugustShort": "Aug", + "SeptemberShort": "Sep", + "OctoberShort": "Okt", + "NovemberShort": "Nov", + "DecemberShort": "Dez" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index e8e912af3c..36ccd40ae3 100644 --- a/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Hintergrundfarbe eines Symbols bei Schreibzugriff, beispielsweise dem Schreiben einer Variable. Die Farbe muss durchsichtig sein, um nicht dahinterliegende Dekorationen zu verbergen.", "wordHighlightBorder": "Randfarbe eines Symbols beim Lesezugriff, wie etwa beim Lesen einer Variablen.", "wordHighlightStrongBorder": "Randfarbe eines Symbols beim Schreibzugriff, wie etwa beim Schreiben einer Variablen.", - "overviewRulerWordHighlightForeground": "Übersichtslineal-Markierungsfarbe für Symbolhervorhebungen.", - "overviewRulerWordHighlightStrongForeground": "Übersichtslineal-Markierungsfarbe für Schreibzugriffs-Symbolhervorhebungen.", + "overviewRulerWordHighlightForeground": "Übersichtslineal-Markierungsfarbe für Symbolhervorhebungen. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", + "overviewRulerWordHighlightStrongForeground": "Übersichtslineal-Markierungsfarbe für Schreibzugriffs-Symbolhervorhebungen. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "wordHighlight.next.label": "Gehe zur nächsten Symbolhervorhebungen", "wordHighlight.previous.label": "Gehe zur vorherigen Symbolhervorhebungen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/deu/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..86e0a5c422 --- /dev/null +++ b/i18n/deu/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 weitere Datei wird nicht angezeigt", + "moreFiles": "...{0} weitere Dateien werden nicht angezeigt" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/deu/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..73350e0c95 --- /dev/null +++ b/i18n/deu/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Abbrechen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/environment/node/argv.i18n.json b/i18n/deu/src/vs/platform/environment/node/argv.i18n.json index 531f559330..0caf4829c8 100644 --- a/i18n/deu/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/deu/src/vs/platform/environment/node/argv.i18n.json @@ -29,8 +29,8 @@ "performance": "Startet mit aktiviertem Befehl \"Developer: Startup Performance\".", "prof-startup": "CPU-Profiler beim Start ausführen", "disableExtensions": "Deaktiviert alle installierten Extensions.", - "inspect-extensions": "Erlaubt Debugging und Profiling für Erweiterungen. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", - "inspect-brk-extensions": "Erlaubt Debugging und Profiling für Erweiterungen, wobei der Erweiterungs-Host nach dem Starten pausiert wird. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", + "inspect-extensions": "Erlaubt Debuggen und Profilerstellung für Erweiterungen. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", + "inspect-brk-extensions": "Erlaubt Debuggen und Profilerstellung für Erweiterungen, wobei der Erweiterungs-Host nach dem Start angehalten wird. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", "disableGPU": "Deaktiviert die GPU-Hardwarebeschleunigung.", "uploadLogs": "Lädt die Logs der aktuellen Sitzung an einem sicheren Endpunkt hoch.", "maxMemory": "Maximale Speichergröße für ein Fenster (in Mbyte).", diff --git a/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 46f09e1ec9..f708991d81 100644 --- a/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Die Erweiterung ist ungültig: \"package.json\" ist keine JSON-Datei.", + "incompatible": "Die Erweiterung \"{0}\" kann nicht installiert werden, die sie nicht mit dem Code \"{1}\" kompatibel ist.", "restartCode": "Bitte starten Sie Code vor der Neuinstallation von {0} neu.", "installingOutdatedExtension": "Eine neuere Version dieser Erweiterung ist bereits installiert. Möchten Sie diese mit der älteren Version überschreiben?", "override": "Überschreiben", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Fehler während Installation der Abhängigkeiten. {0}", "MarketPlaceDisabled": "Marketplace ist nicht aktiviert.", "removeError": "Fehler beim Entfernen der Erweiterung: {0}. Bitte beenden Sie und starten Sie VS Code neu bevor Sie erneut versuchen die Erweiterung zu installieren.", - "Not Market place extension": "Nur Marktplatz-Erweiterungen können neu installiert werden", + "Not a Marketplace extension": "Nur Marktplatz-Erweiterungen können neu installiert werden", "notFoundCompatible": "'{0}' kann nicht installiert werden: Es gibt keine mit VS Code '{1}' kompatible Version.", "malicious extension": "Die Erweiterung kann nicht installiert werden, da sie als problematisch gemeldet wurde.", "notFoundCompatibleDependency": "Kann nicht installiert werden, da die abhängige Erweiterung '{0}', die mit der aktuellen VS Code Version '{1}' kompatibel ist, nicht gefunden werden kann. ", "quitCode": "Fehler bei der Installation der Erweiterung. Beenden und starten Sie VS Code vor der erneuten Installation neu.", "exitCode": "Fehler bei der Installation der Erweiterung. Beenden und starten Sie VS Code vor der erneuten Installation neu.", + "renameError": "Unbekannter Fehler beim Umbenennen von {0} in {1}", "uninstallDependeciesConfirmation": "Möchten Sie nur \"{0}\" oder auch die zugehörigen Abhängigkeiten deinstallieren?", - "uninstallOnly": "Nur", - "uninstallAll": "Alle", + "uninstallOnly": "Nur Erweiterung", + "uninstallAll": "Alle deinstallieren", "uninstallConfirmation": "Möchten Sie \"{0}\" deinstallieren?", "ok": "OK", "singleDependentError": "Die Erweiterung \"{0}\" kann nicht deinstalliert werden. Die Erweiterung \"{1}\" hängt von dieser Erweiterung ab.", diff --git a/i18n/deu/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/deu/src/vs/platform/extensions/node/extensionValidator.i18n.json index c517192487..56cad169e9 100644 --- a/i18n/deu/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/deu/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Der engines.vscode-Wert {0} konnte nicht analysiert werden. Verwenden Sie z. B. ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x usw.", + "versionSyntax": "`engines.vscode`-Wert {0} konnte nicht analysiert werden. Bitte z. B. folgende verwenden: ^1.22.0, ^1.22.x usw.", "versionSpecificity1": "Die in \"engines.vscode\" ({0}) angegebene Version ist nicht spezifisch genug. Definieren Sie für VS Code-Versionen vor Version 1.0.0 bitte mindestens die gewünschte Haupt- und Nebenversion, z. B. ^0.10.0, 0.10.x, 0.11.0 usw.", "versionSpecificity2": "Die in \"engines.vscode\" ({0}) angegebene Version ist nicht spezifisch genug. Definieren Sie für VS Code-Versionen nach Version 1.0.0 bitte mindestens die gewünschte Hauptversion, z. B. ^1.10.0, 1.10.x, 1.x.x, 2.x.x usw.", "versionMismatch": "Die Extension ist nicht mit dem Code {0} kompatibel. Die Extension erfordert {1}." diff --git a/i18n/deu/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/deu/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 1f877c6b04..e03a626236 100644 --- a/i18n/deu/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/deu/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "Ihre {0}-Installation ist offenbar beschädigt. Führen Sie eine Neuinstallation durch.", "integrity.moreInformation": "Weitere Informationen", - "integrity.dontShowAgain": "Nicht mehr anzeigen", - "integrity.prompt": "Ihre {0}-Installation ist offenbar beschädigt. Führen Sie eine Neuinstallation durch." + "integrity.dontShowAgain": "Nicht mehr anzeigen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/deu/src/vs/platform/issue/electron-main/issueService.i18n.json index e4b7e6f0b4..a91d2e65d8 100644 --- a/i18n/deu/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/deu/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Problembericht" + "issueReporter": "Problembericht", + "processExplorer": "Prozess-Explorer" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/list/browser/listService.i18n.json b/i18n/deu/src/vs/platform/list/browser/listService.i18n.json index 6479b5753d..3df21d28f5 100644 --- a/i18n/deu/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/deu/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Der Modifizierer zum Hinzufügen eines Elements in Bäumen und Listen zu einer Mehrfachauswahl mit der Maus (zum Beispiel im Explorer, in geöffneten Editoren und in der SCM-Ansicht). \"ctrlCmd\" wird unter Windows und Linux der Taste \"STRG\" und unter macOSX der Befehlstaste zugeordnet. Die Mausbewegung \"Seitlich öffnen\" wird – sofern unterstützt – so angepasst, dass kein Konflikt mit dem Modifizierer zur Mehrfachauswahl entsteht.", "openMode.singleClick": "Öffnet Elemente mit einem einzelnen Mausklick.", "openMode.doubleClick": "Öffnet Elemente mit einem doppelten Mausklick.", - "openModeModifier": "Steuert, wie Elemente in Bäumen und Listen mithilfe der Maus geöffnet werden (sofern unterstützt). Legen Sie \"singleClick\" fest, um Elemente mit einem einzelnen Mausklick zu öffnen, und \"doubleClick\", damit sie nur mit einem doppelten Mausklick geöffnet werden. Bei übergeordneten Elementen, deren untergeordnete Elemente sich in Bäumen befinden, steuert diese Einstellung, ob ein Einfachklick oder ein Doppelklick das übergeordnete Elemente erweitert. Beachten Sie, dass einige Bäume und Listen diese Einstellung ggf. ignorieren, wenn sie nicht zutrifft." + "openModeModifier": "Steuert, wie Elemente in Bäumen und Listen mithilfe der Maus geöffnet werden (sofern unterstützt). Legen Sie \"singleClick\" fest, um Elemente mit einem einzelnen Mausklick zu öffnen, und \"doubleClick\", damit sie nur mit einem doppelten Mausklick geöffnet werden. Bei übergeordneten Elementen, deren untergeordnete Elemente sich in Bäumen befinden, steuert diese Einstellung, ob ein Einfachklick oder ein Doppelklick das übergeordnete Elemente erweitert. Beachten Sie, dass einige Bäume und Listen diese Einstellung ggf. ignorieren, wenn sie nicht zutrifft.", + "horizontalScrolling setting": "Steuert, ob Bäume horizontales Scrollen in der Workbench unterstützen." } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/markers/common/markers.i18n.json b/i18n/deu/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..e5b40fe4a6 --- /dev/null +++ b/i18n/deu/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Fehler", + "sev.warning": "Warnung", + "sev.info": "Info" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json index 5b9490db19..b35ebab1bb 100644 --- a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "Input box - Vordergrundfarbe für Platzhalter-Text.", "inputValidationInfoBackground": "Hintergrundfarbe bei der Eingabevalidierung für den Schweregrad der Information.", "inputValidationInfoBorder": "Rahmenfarbe bei der Eingabevalidierung für den Schweregrad der Information.", - "inputValidationWarningBackground": "Hintergrundfarbe bei der Eingabevalidierung für eine Warnung zur Information.", + "inputValidationWarningBackground": "Hintergrundfarbe bei der Eingabevalidierung für den Schweregrad der Warnung.", "inputValidationWarningBorder": "Rahmenfarbe bei der Eingabevalidierung für den Schweregrad der Warnung.", "inputValidationErrorBackground": "Hintergrundfarbe bei der Eingabevalidierung für den Schweregrad des Fehlers.", "inputValidationErrorBorder": "Rahmenfarbe bei der Eingabevalidierung für den Schweregrad des Fehlers.", @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "Randfarbe für Bereiche, deren Inhalt der Auswahl entspricht.", "editorFindMatch": "Farbe des aktuellen Suchergebnisses.", "findMatchHighlight": "Farbe der anderen Suchergebnisse. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", - "findRangeHighlight": "Farbe des einschränkenden Suchbereichs. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "findRangeHighlight": "Farbe des Bereichs zur Einschränkung der Suche. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "editorFindMatchBorder": "Randfarbe des aktuellen Suchergebnisses.", "findMatchHighlightBorder": "Randfarbe der anderen Suchtreffer.", - "findRangeHighlightBorder": "Randfarbe des einschränkenden Suchbereichs. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "findRangeHighlightBorder": "Rahmenfarbe des Bereichs zur Einschränkung der Suche. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "hoverHighlight": "Hervorhebung eines Worts, unter dem ein Mauszeiger angezeigt wird. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "hoverBackground": "Background color of the editor hover.", "hoverBorder": "Rahmenfarbe des Editor-Mauszeigers.", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "Hintergrund für eingehende Kopfzeile in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "mergeIncomingContentBackground": "Hintergrund für eingehenden Inhalt in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "mergeCommonHeaderBackground": "Inhaltshintergrund des gemeinsamen übergeordneten Elements bei Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", - "mergeCommonContentBackground": "Inhaltshintergrund des gemeinsamen übergeordneten Elements bei Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "mergeCommonContentBackground": "Inhaltshintergrund des gemeinsamen übergeordneten Elements bei Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "mergeBorder": "Rahmenfarbe für Kopfzeilen und die Aufteilung in Inline-Mergingkonflikten.", "overviewRulerCurrentContentForeground": "Aktueller Übersichtslineal-Vordergrund für Inline-Mergingkonflikte.", "overviewRulerIncomingContentForeground": "Eingehender Übersichtslineal-Vordergrund für Inline-Mergingkonflikte. ", "overviewRulerCommonContentForeground": "Hintergrund des Übersichtslineals des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten.", - "overviewRulerFindMatchForeground": "Übersichtslineal-Markierungsfarbe für Suchübereinstimmungen.", - "overviewRulerSelectionHighlightForeground": "Übersichtslineal-Markierungsfarbe für Auswahlhervorhebungen." + "overviewRulerFindMatchForeground": "Übersichtslineal-Markierungsfarbe für Suchübereinstimmungen. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", + "overviewRulerSelectionHighlightForeground": "Übersichtslineal-Markierungsfarbe für Auswahlhervorhebungen. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen." } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/deu/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..3077316f15 --- /dev/null +++ b/i18n/deu/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "Soll die Erweiterung {0} die folgende URL öffnen?" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/windows/electron-main/windowsService.i18n.json b/i18n/deu/src/vs/platform/windows/electron-main/windowsService.i18n.json index 2dd3844ae3..fe22ac6b79 100644 --- a/i18n/deu/src/vs/platform/windows/electron-main/windowsService.i18n.json +++ b/i18n/deu/src/vs/platform/windows/electron-main/windowsService.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "aboutDetail": "\nVersion {0}\nCommit {1}\nDatum {2}\nShell {3}\nRenderer {4}\nNode {5}\nArchitektur {6}", + "aboutDetail": "Version {0}\nCommit {1}\nDatum {2}\nShell {3}\nRenderer {4}\nNode {5}\nArchitektur {6}", "okButton": "OK", "copy": "&&Kopieren" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/deu/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..d4fffac7aa --- /dev/null +++ b/i18n/deu/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "Eindeutige ID, die zum Bestimmen des Containers verwendet wird, in dem Ansichten mithilfe des Beitragspunkts \"views\" beigetragen werden können.", + "vscode.extension.contributes.views.containers.title": "Visuell lesbare Zeichenfolge zum Rendern des Containers", + "vscode.extension.contributes.views.containers.icon": "Pfad zum Containersymbol. Symbole sind 24x24 groß und zentriert in einem Rechteck (50x40), und ihre Füllfarbe ist \"rgb(215, 218, 224)\" oder \"#d7dae0\". SVG-Symbole werden empfohlen, es wird allerdings jeder Bilddateityp akzeptiert.", + "vscode.extension.contributes.viewsContainers": "Trägt Ansichtencontainer zum Editor bei", + "views.container.activitybar": "Trägt Ansichtencontainer zur Aktivitätsleiste bei", + "test": "Test", + "proposed": "Der Beitrag \"viewsContainers\" ist nur verfügbar, wenn er außerhalb der Entwicklung ausgeführt wird oder mithilfe des folgenden Befehlszeilenschalters: --enable-proposed-api {0}", + "requirearray": "Ansichtencontainer müssen ein Array sein", + "requireidstring": "Die Eigenschaft \"{0}\" ist erforderlich. Sie muss vom Typ \"string\" sein. Nur alphanumerische Buchstaben, \"_\", \"-\" sind zulässig.", + "requirestring": "Die Eigenschaft \"{0}\" ist erforderlich. Sie muss vom Typ \"string\" sein.", + "showViewlet": "{0} anzeigen", + "view": "Anzeigen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/deu/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index 52f4a50aa9..8400e13161 100644 --- a/i18n/deu/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/deu/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "Der visuell lesbare Name der Ansicht. Wird angezeigt", "vscode.extension.contributes.view.when": "Bedingung, die zum Anzeigen dieser Ansicht erfüllt sein muss", "vscode.extension.contributes.views": "Trägt Ansichten zum Editor bei.", - "views.explorer": "Explorer-Ansicht", - "views.debug": "Debugansicht", - "locationId.invalid": "{0}\" ist kein gültiger Ansichtenspeicherort", + "views.explorer": "Trägt Ansichten zum Explorer-Container in der Aktivitätsleiste bei", + "views.debug": "Trägt Ansichten zum Debugging-Container in der Aktivitätsleiste bei", + "views.scm": "Trägt Ansichten zum SCM-Container in der Aktivitätsleiste bei", + "views.test": "Trägt Ansichten zum Testcontainer in der Aktivitätsleiste bei", + "views.contributed": "Trägt Ansichten zum Container mit beigetragenen Ansichten bei", + "ViewContainerDoesnotExist": "Der Ansichtencontainer \"{0}\" ist nicht vorhanden, und alle für ihn registrierten Ansichten werden zu \"Explorer\" hinzugefügt.", "duplicateView1": "Mehrere Ansichten können nicht mit derselben ID \"{0}\" am Speicherort \"{1}\" registriert werden.", "duplicateView2": "Eine Ansicht mit der ID \"{0}\" ist am Speicherort \"{1}\" bereits registriert." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 6926e3cf17..b8d13fa0fe 100644 --- a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Formatieren beim Speichern nach {0} ms abgebrochen", + "codeActionsOnSave.didTimeout": "codeActionsOnSave nach {0} ms abgebrochen", + "timeout.onWillSave": "Bei onWillSaveTextDocument-Ereignis nach 1750 ms abgebrochen", "saveParticipants": "Speichern von Teilnehmern wird ausgeführt …" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index c76fd41114..522ad6a6e3 100644 --- a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "Webview-Editor" + "errorMessage": "Ein Fehler ist aufgetreten beim Wiederherstellen der Ansicht: {0}" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/deu/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..a933ea1e42 --- /dev/null +++ b/i18n/deu/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (Erweiterung)" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 58d4dc836d..7d9f86577d 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Fokus in nächster Gruppe", "openToSide": "Zur Seite öffnen", "closeEditor": "Editor schließen", + "closeOneEditor": "Schließen", "revertAndCloseActiveEditor": "Wiederherstellen und Editor schließen", "closeEditorsToTheLeft": "Editoren links schließen", "closeAllEditors": "Alle Editoren schließen", diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 8aa531b941..25ac631303 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Wenn Sie keine Sprachausgabe verwenden, ändern Sie die Einstellung \"editor.accessibilitySupport\" in \"Aus\".", "disableTabMode": "Barrierefreiheitsmodus deaktivieren", "gotoLine": "Gehe zu Zeile", - "indentation": "Einzug", + "selectIndentation": "Einzug auswählen", "selectEncoding": "Codierung auswählen", "selectEOL": "Zeilenendesequenz auswählen", "selectLanguageMode": "Sprachmodus auswählen", diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 3c38aa17e7..c2e2284501 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} MB", "sizeGB": "{0} GB", "sizeTB": "{0} TB", - "largeImageError": "Die Dateigröße des Bilds ist zu groß (über 1 MB), um im Editor angezeigt zu werden.", + "largeImageError": "Das Bild wird im Editor nicht angezeigt, weil es zu groß ist ({0}).", "resourceOpenExternalButton": "Bild mit externem Programm öffnen?", - "nativeBinaryError": "Die Datei wird nicht im Editor angezeigt, weil sie binär oder sehr groß ist oder eine nicht unterstützte Textcodierung verwendet.", + "nativeFileTooLargeError": "Die Datei wird im Editor nicht angezeigt, weil sie zu groß ist ({0}).", + "nativeBinaryError": "Die Datei wird im Editor nicht angezeigt, weil sie entweder binär ist oder eine nicht unterstützte Textcodierung verwendet.", + "openAsText": "Dennoch öffnen?", "zoom.action.fit.label": "Ganzes Bild", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 5e7388e59a..d33258419e 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Schließen", "araLabelEditorActions": "Editor-Aktionen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 02fbd8ec84..25fb0b63c3 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Keine neuen Benachrichtigungen", "notifications": "Benachrichtigungen", "notificationsToolbar": "Aktionen der Benachrichtigungszentrale", "notificationsList": "Benachrichtigungsliste" diff --git a/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..c40d49b3c7 --- /dev/null +++ b/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Drücken Sie die EINGABETASTE zur Bestätigung oder ESC, um den Vorgang abzubrechen.)", + "inputModeEntry": "Drücken Sie die EINGABETASTE, um Ihre Eingabe zu bestätigen, oder ESC, um den Vorgang abzubrechen.", + "quickInput.countSelected": "{0} ausgewählt", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..7eb6fe22c9 --- /dev/null +++ b/i18n/deu/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Nehmen Sie eine Eingabe vor, um die Ergebnisse einzugrenzen." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json index 6a3c25d74d..dd4f03bd19 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Zuletzt benutzt...", "quickOpenRecent": "Zuletzt benutzte schnell öffnen...", "reportIssueInEnglish": "Problem melden", + "openProcessExplorer": "Prozess-Explorer öffnen", "reportPerformanceIssue": "Leistungsproblem melden", "keybindingsReference": "Referenz für Tastenkombinationen", "openDocumentationUrl": "Dokumentation", diff --git a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json index 1c0ab61e61..659c13c5fa 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Fenster", "window.openFilesInNewWindow.on": "Dateien werden in einem neuen Fenster geöffnet.", "window.openFilesInNewWindow.off": "Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet.", - "window.openFilesInNewWindow.default": "Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet, sofern sie nicht über das Dock oder den Finder geöffnet werden (nur MacOS).", - "openFilesInNewWindow": "Steuert, ob Dateien in einem neuen Fenster oder im letzten aktiven Fenster geöffnet werden.\n- default: Die Dateien werden im letzten aktiven Fenster geöffnet, sofern sie nicht über das Dock oder den Finder geöffnet werden (nur macOS).\n- on: Die Dateien werden in einem neuen Fenster geöffnet.\n- off: Die Dateien werden im letzten aktiven Fenster geöffnet.\nIn einigen Fällen wird diese Einstellung unter Umständen ignoriert (z. B. bei der Befehlszeilenoption \"-new-window\" oder \"-reuse-window\").", + "window.openFilesInNewWindow.defaultMac": "Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet, sofern sie nicht über das Dock oder den Finder geöffnet werden.", + "window.openFilesInNewWindow.default": "Dateien werden in einem neuen Fenster geöffnet, sofern sie nicht innerhalb der Anwendung ausgewählt werden (z. B. über das Dateimenü).", + "openFilesInNewWindowMac": "Steuert, ob Dateien in einem neuen Fenster geöffnet werden.\n- default: Die Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet, sofern sie nicht über das Dock oder den Finder geöffnet werden.\n- on: Die Dateien werden in einem neuen Fenster geöffnet.\n- off: Die Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet.\nIn einigen Fällen wird diese Einstellung unter Umständen ignoriert (z. B. bei der Befehlszeilenoption \"-new-window\" oder \"-reuse-window\").", + "openFilesInNewWindow": "Steuert, ob Dateien in einem neuen Fenster geöffnet werden.\n- default: Die Dateien werden in einem neuen Fenster geöffnet, sofern sie nicht innerhalb der Anwendung ausgewählt werden (z. B. über das Dateimenü).\n- on: Die Dateien werden in einem neuen Fenster geöffnet.\n- off: Die Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet.\nIn einigen Fällen wird diese Einstellung unter Umständen ignoriert (z. B. bei der Befehlszeilenoption \"-new-window\" oder \"-reuse-window\").", "window.openFoldersInNewWindow.on": "Ordner werden in einem neuen Fenster geöffnet.", "window.openFoldersInNewWindow.off": "Ordner ersetzen das letzte aktive Fenster.", "window.openFoldersInNewWindow.default": "Ordner werden in einem neuen Fenster geöffnet, sofern kein Ordner innerhalb der Anwendung ausgewählt wird (z. B. über das Dateimenü).", "openFoldersInNewWindow": "Steuert, ob Ordner in einem neuen Fenster geöffnet werden oder das letzte aktive Fenster ersetzen.\n- default: Die Ordner werden in einem neuen Fenster geöffnet, sofern kein Ordner innerhalb der Anwendung ausgewählt wird (z. B. über das Dateimenü).\n- on: Die Ordner werden in einem neuen Fenster geöffnet.\n- off: Die Ordner ersetzen das letzte aktive Fenster.\nIn einigen Fällen wird diese Einstellung unter Umständen ignoriert (z. B. bei der Befehlszeilenoption \"-new-window\" oder \"-reuse-window\").", + "window.openWithoutArgumentsInNewWindow.on": "Neues leeres Fenster öffnen", + "window.openWithoutArgumentsInNewWindow.off": "Fokus auf die zuletzt aktive ausgeführte Instanz", + "openWithoutArgumentsInNewWindow": "Steuert, ob ein neues leeres Fenster geöffnet wird, wenn eine zweite Instanz ohne Argumente gestartet wird oder wenn für die zuletzt ausgeführt Instanz ein Fokus erforderlich ist.\n- on: Öffnet ein neues leeres Fenster.\n- off: Die zuletzt aktive ausgeführte Instanz erhält den Fokus.\nIn einigen Fällen wird diese Einstellung unter Umständen ignoriert (z. B. bei der Befehlszeilenoption \"-new-window\" oder \"-reuse-window\").", "window.reopenFolders.all": "Alle Fenster erneut öffnen.", "window.reopenFolders.folders": "Alle Ordner erneut öffnen. Leere Arbeitsbereiche werden nicht wiederhergestellt.", "window.reopenFolders.one": "Das letzte aktive Fenster erneut öffnen. ", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Ist diese Option aktiviert, erfolgt automatisch ein Wechsel zu einem Design mit hohem Kontrast, wenn Windows ein Design mit hohem Kontrast verwendet, und zu einem dunklen Design, wenn Sie für Windows kein Design mit hohem Kontrast mehr verwenden.", "titleBarStyle": "Passt das Aussehen der Titelleiste des Fensters an. Zum Anwenden der Änderungen ist ein vollständiger Neustart erforderlich.", "window.nativeTabs": "Aktiviert MacOS Sierra-Fensterregisterkarten. Beachten Sie, dass zum Übernehmen von Änderungen ein vollständiger Neustart erforderlich ist und durch ggf. konfigurierte native Registerkarten ein benutzerdefinierter Titelleistenstil deaktiviert wird.", + "window.smoothScrollingWorkaround": "Aktivieren Sie diese Problemumgehung, wenn der Bildlauf nach der Wiederherstellung eines minimierten VS Code-Fensters nicht mehr reibungslos funktioniert. Dies ist eine Problemumgehung für ein Problem (https://github.com/Microsoft/vscode/issues/13612), bei dem der Bildlauf auf Geräten mit präzisen Trackpads wie etwa den Surface-Geräten von Microsoft verzögert ist. Wenn Sie diese Problemumgehung aktivieren, flackert die Anzeige nach dem Wiederherstellen eines Fensters aus dem minimierten Zustand unter Umständen ein wenig, ansonsten treten jedoch keine Probleme auf.", + "window.clickThroughInactive": "Ist dies aktiviert, wird beim Klicken auf ein inaktives Fenster das Fenster aktiviert, und das Element unter der Maus wird ausgelöst, wenn es angeklickt werden kann. Wenn es deaktiviert ist, wird durch Klicken auf eine beliebige Stelle in einem inaktiven Fenster nur das Fenster aktiviert, und Sie müssen das Element zusätzlich anklicken.", "zenModeConfigurationTitle": "Zen-Modus", "zenMode.fullScreen": "Steuert, ob die Workbench durch das Aktivieren des Zen-Modus in den Vollbildmodus wechselt.", "zenMode.centerLayout": "Steuert, ob das Layout durch Aktivieren des Zen-Modus ebenfalls zentriert wird.", diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index f57afb2478..b4980d9051 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Haltepunkt bearbeiten...", + "logPoint": "Protokollpunkt", + "breakpoint": "Haltepunkt", + "editBreakpoint": "{0} bearbeiten …", + "removeBreakpoint": "{0} entfernen", "functionBreakpointsNotSupported": "Funktionshaltepunkte werden von diesem Debugtyp nicht unterstützt.", "functionBreakpointPlaceholder": "Funktion mit Haltepunkt", "functionBreakPointInputAriaLabel": "Geben Sie den Funktionshaltepunkt ein.", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Nicht überprüfter Haltepunkt", "functionBreakpointUnsupported": "Funktionshaltepunkte werden von diesem Debugtyp nicht unterstützt.", "breakpointDirtydHover": "Nicht überprüfter Haltepunkt. Die Datei wurde geändert. Bitte starten Sie die Debugsitzung neu.", + "logBreakpointUnsupported": "Protokollpunkte werden für diesen Debugtyp nicht unterstützt", "conditionalBreakpointUnsupported": "Bedingte Haltepunkte werden für diesen Debugtyp nicht unterstützt.", "hitBreakpointUnsupported": "Bedingte Trefferhaltepunkte werden für diesen Debugtyp nicht unterstützt." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 705cf13d6e..b190a00a18 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Trennen", "continueDebug": "Weiter", "pauseDebug": "Anhalten", + "terminateThread": "Thread beenden", "restartFrame": "Frame neu starten", "removeBreakpoint": "Haltepunkt entfernen", "removeAllBreakpoints": "Alle Haltepunkte entfernen", - "enableBreakpoint": "Haltepunkt aktivieren", - "disableBreakpoint": "Haltepunkt deaktivieren", "enableAllBreakpoints": "Alle Haltepunkte aktivieren", "disableAllBreakpoints": "Alle Haltepunkte deaktivieren", "activateBreakpoints": "Haltepunkte aktivieren", "deactivateBreakpoints": "Haltepunkte deaktivieren", "reapplyAllBreakpoints": "Alle Haltepunkte erneut anwenden", "addFunctionBreakpoint": "Funktionshaltepunkt hinzufügen", - "addConditionalBreakpoint": "Bedingten Haltepunkt hinzufügen...", - "editConditionalBreakpoint": "Haltepunkt bearbeiten...", "setValue": "Wert festlegen", "addWatchExpression": "Ausdruck hinzufügen", "editWatchExpression": "Ausdruck bearbeiten", diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 4178260600..938ba8aa98 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Debuggen: Haltepunkt umschalten", "conditionalBreakpointEditorAction": "Debuggen: Bedingten Haltepunkt hinzufügen...", + "logPointEditorAction": "Debuggen: Protokollpunkt hinzufügen …", "runToCursor": "Ausführen bis Cursor", "debugEvaluate": "Debuggen: Auswerten", "debugAddToWatch": "Debuggen: Zur Überwachung hinzufügen", diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..7cc2728b73 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "Zu protokollierende Nachricht, wenn der Haltepunkt erreicht wird. Ausdrücke innerhalb von {} werden interpoliert. Betätigen Sie die EINGABETASTE, um dies zu akzeptieren, oder ECS, um den Vorgang abzubrechen.", + "breakpointWidgetHitCountPlaceholder": "Unterbrechen, wenn die Bedingung für die Trefferanzahl erfüllt ist. EINGABETASTE zum Akzeptieren, ESC-TASTE zum Abbrechen.", + "breakpointWidgetExpressionPlaceholder": "Unterbrechen, wenn der Ausdruck als TRUE ausgewertet wird. EINGABETASTE zum Akzeptieren, ESC-TASTE zum Abbrechen.", + "expression": "Ausdruck", + "hitCount": "Trefferanzahl", + "logMessage": "Protokollmeldung" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 3d319121ce..49b0d91b1e 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Verwenden Sie eindeutige Konfigurationsnamen.", "app.launch.json.compound.folder": "Name des Ordners, in dem sich der Verbund befindet.", "app.launch.json.compounds.configurations": "Namen von Konfigurationen, die als Bestandteil dieses Verbunds gestartet werden.", - "debugNoType": "Der \"type\" des Debugadapters kann nicht ausgelassen werden und muss vom Typ \"string\" sein.", + "debugNoType": "Der Debugger \"type\" darf nicht ausgelassen werden und muss den Typ \"string\" aufweisen.", "selectDebug": "Umgebung auswählen", "DebugConfig.failed": "Die Datei \"launch.json\" kann nicht im Ordner \".vscode\" erstellt werden ({0}).", "workspace": "Arbeitsbereich", diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index f79cb35f59..3841294e91 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Protokollpunkt", + "breakpoint": "Haltepunkt", + "removeBreakpoint": "{0} entfernen", + "editBreakpoint": "{0} bearbeiten …", + "disableBreakpoint": "{0} deaktivieren", + "enableBreakpoint": "{0} aktivieren", "removeBreakpoints": "Haltepunkte entfernen", "removeBreakpointOnColumn": "Haltepunkt in Spalte {0} entfernen", "removeLineBreakpoint": "Zeilenhaltepunkt entfernen", @@ -18,5 +24,13 @@ "enableBreakpoints": "Haltepunkt in Spalte {0} aktivieren", "enableBreakpointOnLine": "Zeilenhaltepunkt aktivieren", "addBreakpoint": "Haltepunkt hinzufügen", + "addConditionalBreakpoint": "Bedingten Haltepunkt hinzufügen...", + "addLogPoint": "Protokollpunkt hinzufügen …", + "breakpointHasCondition": "Dieser {0} hat eine {1}, die beim Entfernen verloren geht. Deaktivieren Sie stattdessen ggf. den {0}.", + "message": "Nachricht", + "condition": "Bedingung", + "removeLogPoint": "{0} entfernen", + "disableLogPoint": "{0} deaktivieren", + "cancel": "Abbrechen", "addConfiguration": "Konfiguration hinzufügen..." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 70252dde41..27cb0addf6 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Fehler anzeigen", "noFolderWorkspaceDebugError": "Debuggen der aktiven Datei ist nicht möglich. Stellen Sie sicher, dass sie auf einem Datenträger gespeichert ist und dass Sie die Debugerweiterung für diesen Dateityp installiert haben.", "cancel": "Abbrechen", - "DebugTaskNotFound": "Der preLaunchTask \"{0}\" wurde nicht gefunden.", - "taskNotTracked": "Der preLaunchTask \"{0}\" kann nicht getrackt werden." + "DebugTaskNotFound": "Der Task \"{0}\" konnte nicht gefunden werden.", + "taskNotTracked": "Der Task \"{0}\" kann nicht nachverfolgt werden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index d990bd6850..e2fc59373b 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Weitere Informationen", - "unableToLaunchDebugAdapter": "Der Debugadapter kann nicht aus {0} gestartet werden.", - "unableToLaunchDebugAdapterNoArgs": "Debugadapter kann nicht gestartet werden.", - "stoppingDebugAdapter": "{0}. Der Debugadapter wird beendet.", "debugAdapterCrash": "Der Debugadapterprozess wurde unerwartet beendet." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index b848910f8a..cee36dc636 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "Die ausführbare Datei \"{0}\" des Debugadapters ist nicht vorhanden.", "debugAdapterCannotDetermineExecutable": "Die ausführbare Datei \"{0}\" des Debugadapters kann nicht bestimmt werden.", - "launch.config.comment1": "Verwendet IntelliSense zum Ermitteln möglicher Attribute.", - "launch.config.comment2": "Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.", - "launch.config.comment3": "Weitere Informationen finden Sie unter {0}", - "debugType": "Der Typ der Konfiguration.", - "debugTypeNotRecognised": "Dieser Debugging-Typ wurde nicht erkannt. Bitte installieren und aktivieren Sie die dazugehörige Debugging-Erweiterung.", - "node2NotSupported": "\"node2\" wird nicht mehr unterstützt, verwenden Sie stattdessen \"node\", und legen Sie das Attribut \"protocol\" auf \"inspector\" fest.", - "debugName": "Der Name der Konfiguration. Er wird im Dropdownmenü der Startkonfiguration angezeigt.", - "debugRequest": "Der Anforderungstyp der Konfiguration. Der Wert kann \"launch\" oder \"attach\" sein.", - "debugServer": "Nur für die Entwicklung von Debugerweiterungen: Wenn ein Port angegeben ist, versucht der VS-Code, eine Verbindung mit einem Debugadapter herzustellen, der im Servermodus ausgeführt wird.", - "debugPrelaunchTask": "Ein Task, der ausgeführt werden soll, bevor die Debugsitzung beginnt.", - "debugWindowsConfiguration": "Windows-spezifische Startkonfigurationsattribute.", - "debugOSXConfiguration": "OS X-spezifische Startkonfigurationsattribute.", - "debugLinuxConfiguration": "Linux-spezifische Startkonfigurationsattribute.", - "deprecatedVariables": "\"env.\", \"config.\" und \"command.\" sind veraltet, verwenden Sie stattdessen \"env:\", \"config:\" und \"command:\"." + "unableToLaunchDebugAdapter": "Der Debugadapter kann nicht aus {0} gestartet werden.", + "unableToLaunchDebugAdapterNoArgs": "Debugadapter kann nicht gestartet werden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..1bdbec328a --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Verwendet IntelliSense zum Ermitteln möglicher Attribute.", + "launch.config.comment2": "Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.", + "launch.config.comment3": "Weitere Informationen finden Sie unter {0}", + "debugType": "Der Typ der Konfiguration.", + "debugTypeNotRecognised": "Dieser Debugging-Typ wurde nicht erkannt. Bitte installieren und aktivieren Sie die dazugehörige Debugging-Erweiterung.", + "node2NotSupported": "\"node2\" wird nicht mehr unterstützt, verwenden Sie stattdessen \"node\", und legen Sie das Attribut \"protocol\" auf \"inspector\" fest.", + "debugName": "Der Name der Konfiguration. Er wird im Dropdownmenü der Startkonfiguration angezeigt.", + "debugRequest": "Der Anforderungstyp der Konfiguration. Der Wert kann \"launch\" oder \"attach\" sein.", + "debugServer": "Nur für die Entwicklung von Debugerweiterungen: Wenn ein Port angegeben ist, versucht der VS-Code, eine Verbindung mit einem Debugadapter herzustellen, der im Servermodus ausgeführt wird.", + "debugPrelaunchTask": "Ein Task, der ausgeführt werden soll, bevor die Debugsitzung beginnt.", + "debugPostDebugTask": "Ein Task, der ausgeführt werden soll, nachdem die Debugsitzung endet.", + "debugWindowsConfiguration": "Windows-spezifische Startkonfigurationsattribute.", + "debugOSXConfiguration": "OS X-spezifische Startkonfigurationsattribute.", + "debugLinuxConfiguration": "Linux-spezifische Startkonfigurationsattribute.", + "deprecatedVariables": "\"env.\", \"config.\" und \"command.\" sind veraltet, verwenden Sie stattdessen \"env:\", \"config:\" und \"command:\"." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..eb3d892064 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code-Konsole", + "mac.terminal.script.failed": "Fehler bei Skript \"{0}\" mit Exitcode {1}.", + "mac.terminal.type.not.supported": "\"{0}\" wird nicht unterstützt.", + "press.any.key": "Drücken Sie eine beliebige Taste, um fortzufahren...", + "linux.term.failed": "Fehler bei \"{0}\" mit Exitcode {1}." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index cba016efb3..9a4aa53b17 100644 --- a/i18n/deu/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,7 +58,10 @@ "configureWorkspaceFolderRecommendedExtensions": "Empfohlene Erweiterungen konfigurieren (Arbeitsbereichsordner)", "malicious tooltip": "Die Erweiterung wurde als problematisch gemeldet.", "malicious": "Böswillig", - "disableAll": "Alle installierten Erweiterungen löschen", + "disabled": "Deaktiviert", + "disabled globally": "Deaktiviert", + "disabled workspace": "Für diesen Arbeitsbereich deaktiviert", + "disableAll": "Alle installierten Erweiterungen deaktivieren", "disableAllWorkspace": "Alle installierten Erweiterungen für diesen Arbeitsbereich deaktivieren", "enableAll": "Alle Erweiterungen aktivieren", "enableAllWorkspace": "Alle Erweiterungen für diesen Arbeitsbereich aktivieren", diff --git a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..78913a24b2 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Erweiterungsname", + "extension id": "Erweiterungsbezeichner", + "preview": "Vorschau", + "builtin": "Integriert", + "publisher": "Name des Herausgebers", + "install count": "Installationsanzahl", + "rating": "Bewertung", + "repository": "Repository", + "license": "Lizenz", + "details": "Details", + "contributions": "Beiträge", + "changelog": "ChangeLog", + "dependencies": "Abhängigkeiten", + "noReadme": "Keine INFODATEI verfügbar.", + "noChangelog": "Es ist kein ChangeLog verfügbar.", + "noContributions": "Keine Beiträge", + "noDependencies": "Keine Abhängigkeiten", + "settings": "Einstellungen ({0})", + "setting name": "Name", + "description": "Beschreibung", + "default": "Standard", + "debuggers": "Debugger ({0})", + "debugger name": "Name", + "debugger type": "Typ", + "views": "Ansichten ({0})", + "view id": "ID", + "view name": "Name", + "view location": "Wo", + "localizations": "Lokalisierungen ({0})", + "localizations language id": "Sprach-ID", + "localizations language name": "Name der Sprache", + "localizations localized language name": "Name der Sprache (lokalisiert)", + "colorThemes": "Farbdesigns ({0})", + "iconThemes": "Symboldesigns ({0})", + "colors": "Farben ({0})", + "colorId": "ID", + "defaultDark": "Standard, dunkel", + "defaultLight": "Standard, hell", + "defaultHC": "Standard, hoher Kontrast", + "JSON Validation": "JSON-Validierung ({0})", + "fileMatch": "Dateiübereinstimmung", + "schema": "Schema", + "commands": "Befehle ({0})", + "command name": "Name", + "keyboard shortcuts": "Tastenkombinationen", + "menuContexts": "Menükontexte", + "languages": "Sprachen ({0})", + "language id": "ID", + "language name": "Name", + "file extensions": "Dateierweiterungen", + "grammar": "Grammatik", + "snippets": "Codeausschnitte" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 2ed8fad116..163437737c 100644 --- a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Diese Erweiterung wird von Benutzern des aktuellen Arbeitsbereichs empfohlen.", "reallyRecommended2": "Für diesen Dateityp wird die Erweiterung \"{0}\" empfohlen.", "reallyRecommendedExtensionPack": "Für diesen Dateityp wird das Erweiterungspaket \"{0}\" empfohlen.", - "showRecommendations": "Empfehlungen anzeigen", "install": "Installieren", + "showRecommendations": "Empfehlungen anzeigen", "showLanguageExtensions": "Der Marketplace enthält Erweiterungen, die bei \".{0}\"-Dateien behilflich sind.", "workspaceRecommended": "Für diesen Arbeitsbereich sind Erweiterungsempfehlungen verfügbar.", "installAll": "Alle installieren", diff --git a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index 9908990149..0381ac127e 100644 --- a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Deaktivere Tastenzuordnungen ({0}) um Konfilkte mit anderen zu vermeiden?", "yes": "Ja", - "no": "Nein", - "betterMergeDisabled": "Die \"Better Merge\" Erweiterung ist jetzt integriert, die alte Erweiterung wurde deaktiviert und kann deinstalliert werden.", - "uninstall": "Deinstallieren" + "no": "Nein" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index c475838ef1..7344b01b4a 100644 --- a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Empfohlen", "otherRecommendedExtensions": "Weitere Empfehlungen", "workspaceRecommendedExtensions": "Arbeitsbereich-Empfehlungen", - "builtInExtensions": "Integriert", + "builtInExtensions": "Features", + "builtInThemesExtensions": "Designs", + "builtInBasicsExtensions": "Programmiersprachen", "searchExtensions": "Nach Erweiterungen im Marketplace suchen", "sort by installs": "Sortieren nach: Installationsanzahl", "sort by rating": "Sortieren nach: Bewertung", diff --git a/i18n/deu/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/deu/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index f1eddbd55a..d0de3768d5 100644 --- a/i18n/deu/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Textdatei-Editor", "createFile": "Datei erstellen", + "relaunchWithIncreasedMemoryLimit": "Mit {0} MB neu starten", + "configureMemoryLimit": "Arbeitsspeicherbeschränkung konfigurieren", "fileEditorWithInputAriaLabel": "{0}. Textdatei-Editor.", "fileEditorAriaLabel": "Textdatei-Editor" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 9c51842b36..6c60d4a339 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Kopieren", "pasteFile": "Einfügen", "retry": "Wiederholen", + "renameWhenSourcePathIsParentOfTargetError": "Verwenden Sie den Befehl \"Neuer Ordner\" oder \"Neue Datei\", um untergeordnete Elemente zu einem vorhandenen Ordner hinzuzufügen", "newUntitledFile": "Neue unbenannte Datei", "createNewFile": "Neue Datei", "createNewFolder": "Neuer Ordner", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Sie löschen einen Ordner mit nicht gespeicherten Änderungen in {0} Dateien. Möchten Sie den Vorgang fortsetzen?", "dirtyMessageFileDelete": "Sie löschen eine Datei mit nicht gespeicherten Änderungen. Möchten Sie den Vorgang fortsetzen?", "dirtyWarning": "Ihre Änderungen gehen verloren, wenn Sie diese nicht speichern.", - "confirmMoveTrashMessageMultiple": "Möchten Sie die folgenden {0} Dateien löschen?", - "confirmMoveTrashMessageFolder": "Möchten Sie \"{0}\" samt Inhalt wirklich löschen?", - "confirmMoveTrashMessageFile": "Möchten Sie \"{0}\" wirklich löschen?", "undoBin": "Die Wiederherstellung kann aus dem Papierkorb erfolgen.", "undoTrash": "Die Wiederherstellung kann aus dem Papierkorb erfolgen.", "doNotAskAgain": "Nicht erneut fragen", + "irreversible": "Diese Aktion kann nicht rückgängig gemacht werden.", + "binFailed": "Fehler beim Löschen über den Papierkorb. Möchten Sie den Löschvorgang stattdessen dauerhaft ausführen?", + "trashFailed": "Fehler beim Löschen über den Papierkorb. Möchten Sie den Löschvorgang stattdessen dauerhaft ausführen?", + "deletePermanentlyButtonLabel": "En&&dgültig löschen", + "retryButtonLabel": "Wiede&&rholen", + "confirmMoveTrashMessageFilesAndDirectories": "Möchten Sie die folgenden {0} Dateien/Verzeichnisse und ihren Inhalt löschen?", + "confirmMoveTrashMessageMultipleDirectories": "Möchten Sie die folgenden {0} Verzeichnisse und ihren Inhalt löschen?", + "confirmMoveTrashMessageMultiple": "Möchten Sie die folgenden {0} Dateien löschen?", + "confirmMoveTrashMessageFolder": "Möchten Sie \"{0}\" samt Inhalt wirklich löschen?", + "confirmMoveTrashMessageFile": "Möchten Sie \"{0}\" wirklich löschen?", + "confirmDeleteMessageFilesAndDirectories": "Möchten Sie die folgenden {0} Dateien/Verzeichnisse und ihren Inhalt dauerhaft löschen?", + "confirmDeleteMessageMultipleDirectories": "Möchten Sie die folgenden {0} Verzeichnisse und ihren Inhalt dauerhaft löschen?", "confirmDeleteMessageMultiple": "Möchten Sie die folgenden {0} Dateien endgültig löschen?", "confirmDeleteMessageFolder": "Möchten Sie \"{0}\" samt Inhalt wirklich endgültig löschen?", "confirmDeleteMessageFile": "Möchten Sie \"{0}\" wirklich endgültig löschen?", - "irreversible": "Diese Aktion kann nicht rückgängig gemacht werden.", - "cancel": "Abbrechen", - "permDelete": "Endgültig löschen", - "importFiles": "Dateien importieren", + "addFiles": "Dateien hinzufügen", "confirmOverwrite": "Im Zielordner ist bereits eine Datei oder ein Ordner mit dem gleichen Namen vorhanden. Möchten Sie sie bzw. ihn ersetzen?", "replaceButtonLabel": "&&Ersetzen", "fileIsAncestor": "Die einzufügende Datei ist ein Vorgänger des Zielordners", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Datei zuerst öffnen, um sie in einem neuen Fenster zu öffnen", "copyPath": "Pfad kopieren", "emptyFileNameError": "Es muss ein Datei- oder Ordnername angegeben werden.", + "fileNameStartsWithSlashError": "Ein Datei- oder Ordnername darf nicht mit einem Schrägstrich beginnen.", "fileNameExistsError": "Eine Datei oder ein Ordner **{0}** ist an diesem Ort bereits vorhanden. Wählen Sie einen anderen Namen.", + "fileUsedAsFolderError": "**{0}** ist eine Datei und darf keine Nachfolger haben.", "invalidFileNameError": "Der Name **{0}** ist als Datei- oder Ordnername ungültig. Bitte wählen Sie einen anderen Namen aus.", "filePathTooLongError": "Der Name **{0}** führt zu einem Pfad, der zu lang ist. Wählen Sie einen kürzeren Namen.", "compareWithClipboard": "Aktive Datei mit Zwischenablage vergleichen", diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 1d3d8c2f6b..98c94564d8 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Steuert, ob nicht gespeicherten Dateien zwischen den Sitzungen beibehlten werden, die Aufforderung zum Speichern wird beim Beenden des Editors übersprungen.", "useExperimentalFileWatcher": "Verwenden Sie die neue experimentelle Dateiüberwachung.", "defaultLanguage": "Der Standardsprachmodus, der neuen Dateien zugewiesen wird.", + "maxMemoryForLargeFilesMB": "Steuert den für VS Code verfügbaren Arbeitsspeicher nach einem Neustart beim Versuch, große Dateien zu öffnen. Gleiche Auswirkung wie beim Festlegen von --max-memory=NEWSIZE in der Befehlszeile.", "editorConfigurationTitle": "Editor", "formatOnSave": "Hiermit wird eine Datei beim Speichern formatiert. Es muss ein Formatierer vorhanden sein, die Datei darf nicht automatisch gespeichert werden, und der Editor darf nicht geschlossen werden.", + "formatOnSaveTimeout": "Zeitüberschreitung beim Formatieren während des Speicherns. Legt eine Zeitbegrenzung in Millisekunden für formatOnSave-Befehle fest. Befehle, die länger dauern als die festgelegte Zeitüberschreitung, werden abgebrochen. ", "explorerConfigurationTitle": "Datei-Explorer", "openEditorsVisible": "Die Anzahl der Editoren, die im Bereich \"Geöffnete Editoren\" angezeigt werden.", "autoReveal": "Steuert, ob der Explorer Dateien beim Öffnen automatisch anzeigen und auswählen soll.", diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 133913e25f..89c8d9fa90 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -2,18 +2,22 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Geben Sie den Dateinamen ein. Drücken Sie zur Bestätigung die EINGABETASTE oder ESC, um den Vorgang abzubrechen.", - "constructedPath": "{0} in **{1}** erstellen", + "createFileFromExplorerInfoMessage": "Datei **{0}** in **{1}** erstellen", + "renameFileFromExplorerInfoMessage": "Verschieben und in **{0}** umbenennen", + "createFolderFromExplorerInfoMessage": "Ordner **{0}** in **{1}** erstellen", "filesExplorerViewerAriaLabel": "{0}, Datei-Explorer", "dropFolders": "Möchten Sie die Ordner zum Arbeitsbereich hinzufügen?", "dropFolder": "Möchten Sie den Ordner zum Arbeitsbereich hinzufügen?", "addFolders": "&&Ordner hinzufügen", "addFolder": "&&Ordner hinzufügen", + "confirmRootsMove": "Möchten Sie die Reihenfolge mehrerer Stammordner in Ihrem Arbeitsbereich ändern?", "confirmMultiMove": "Möchten Sie die folgenden {0} Dateien verschieben?", + "confirmRootMove": "Möchten Sie die Reihenfolge des Stammordners \"{0}\" in Ihrem Arbeitsbereich ändern?", "confirmMove": "Möchten Sie \"{0}\" wirklich verschieben?", "doNotAskAgain": "Nicht erneut fragen", "moveButtonLabel": "&&Verschieben", diff --git a/i18n/deu/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..755aaf46f8 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "HTML-Vorschau" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/deu/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..4a85781524 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Ungültige Editor-Eingabe." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..0c1f5497f1 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Entwickler" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/deu/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..1492a37abd --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview-Entwicklertools öffnen", + "refreshWebviewLabel": "Webviews erneut laden" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index f460a0cb8f..6503f29bb9 100644 --- a/i18n/deu/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Möchten Sie die Sprache der Benutzeroberfläche von VS Code in {0} ändern und einen Neustart durchführen?", + "yes": "Ja", + "no": "Nein", + "neverAgain": "Nicht mehr anzeigen", "JsonSchema.locale": "Die zu verwendende Sprache der Benutzeroberfläche.", "vscode.extension.contributes.localizations": "Trägt Lokalisierungen zum Editor bei", "vscode.extension.contributes.localizations.languageId": "ID der Sprache, in die Anzeigezeichenfolgen übersetzt werden.", diff --git a/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..d3b6302160 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Möchten Sie die Sprache der Benutzeroberfläche von VS Code in {0} ändern und einen Neustart durchführen?", + "yes": "Ja", + "no": "Nein", + "neverAgain": "Nicht mehr anzeigen", + "install language pack": "In naher Zukunft wird VS Code nur Sprachpakete in Form von Marketplace-Erweiterungen unterstützen. Installieren Sie die Erweiterung \"{0}\", damit Sie die derzeit konfigurierte Sprache weiter verwenden können.", + "install": "Installieren", + "more information": "Weitere Informationen …", + "JsonSchema.locale": "Die zu verwendende Sprache der Benutzeroberfläche.", + "vscode.extension.contributes.localizations": "Trägt Lokalisierungen zum Editor bei", + "vscode.extension.contributes.localizations.languageId": "ID der Sprache, in die Anzeigezeichenfolgen übersetzt werden.", + "vscode.extension.contributes.localizations.languageName": "Englischer Name der Sprache.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Name der Sprache in beigetragener Sprache.", + "vscode.extension.contributes.localizations.translations": "Liste der Übersetzungen, die der Sprache zugeordnet sind.", + "vscode.extension.contributes.localizations.translations.id": "ID von VS Code oder der Erweiterung, für die diese Übersetzung beigetragen wird. Die ID von VS Code ist immer \"vscode\", und die ID einer Erweiterung muss im Format \"publisherId.extensionName\" vorliegen.", + "vscode.extension.contributes.localizations.translations.id.pattern": "Die ID muss \"vscode\" sein oder im Format \"publisherId.extensionName\" vorliegen, um VS Code bzw. eine Erweiterung zu übersetzen.", + "vscode.extension.contributes.localizations.translations.path": "Ein relativer Pfad zu einer Datei mit Übersetzungen für die Sprache." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..ecb522366f --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Sprache konfigurieren", + "displayLanguage": "Definiert die Anzeigesprache von VSCode.", + "doc": "Unter {0} finden Sie eine Liste der unterstützten Sprachen.", + "restart": "Das Ändern dieses Wertes erfordert einen Neustart von VSCode.", + "fail.createSettings": "{0} ({1}) kann nicht erstellt werden." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..ed217d3a91 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Kopieren", + "copyMessage": "Nachricht kopieren" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..68d40f0924 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Insgesamt {0} Probleme" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..8a10d21818 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Probleme", + "tooltip.1": "1 Problem in dieser Datei", + "tooltip.N": "{0} Probleme in dieser Datei", + "markers.showOnFile": "Fehler & Warnungen auf Dateien und Ordnern anzeigen." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..44bcb5c161 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Dateiausschlussfilter deaktivieren.", + "clearFilter": "Filter löschen." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..74b775239c --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "Zeigt {0} von {1} an" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..68082d2d7b --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Anzeigen", + "problems.view.toggle.label": "Probleme umschalten (Fehler, Warnungen, Informationen)", + "problems.view.focus.label": "Probleme fokussieren (Fehler, Warnungen, Informationen)", + "problems.panel.configuration.title": "Ansicht \"Probleme\"", + "problems.panel.configuration.autoreveal": "Steuert, ob die Ansicht \"Probleme\" automatisch Dateien anzeigen sollte, wenn diese geöffnet werden.", + "markers.panel.title.problems": "Probleme", + "markers.panel.aria.label.problems.tree": "Probleme nach Dateien gruppiert", + "markers.panel.no.problems.build": "Es wurden bisher keine Probleme im Arbeitsbereich erkannt.", + "markers.panel.no.problems.filters": "Es wurden keine Ergebnisse mit den angegebenen Filterkriterien gefunden.", + "markers.panel.no.problems.file.exclusions": "Alle Probleme sind ausgeblendet, weil der Filter zum Ausschließen von Dateien aktiviert ist.", + "markers.panel.action.useFilesExclude": "Filtern mithilfe der Dateiausschlusseinstellungen", + "markers.panel.action.donotUseFilesExclude": "Dateiausschlusseinstellung nicht verwenden", + "markers.panel.action.filter": "Probleme filtern", + "markers.panel.filter.ariaLabel": "Probleme filtern", + "markers.panel.filter.placeholder": "Filter. Z. B.: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "Fehler", + "markers.panel.filter.warnings": "Warnungen", + "markers.panel.filter.infos": "Informationen", + "markers.panel.single.error.label": "1 Fehler", + "markers.panel.multiple.errors.label": "{0} Fehler", + "markers.panel.single.warning.label": "1 Warnung", + "markers.panel.multiple.warnings.label": "{0} Warnungen", + "markers.panel.single.info.label": "1 Information", + "markers.panel.multiple.infos.label": "{0}-Informationen", + "markers.panel.single.unknown.label": "1 Unbekannte", + "markers.panel.multiple.unknowns.label": "{0} Unbekannte", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} mit {1} Problemen", + "problems.tree.aria.label.marker.relatedInformation": "Dieses Problem verweist auf {0} Speicherorte.", + "problems.tree.aria.label.error.marker": "Von {0} generierter Fehler: {1} in Zeile {2} bei Zeichen {3}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Fehler: {0} in Zeile {1} bei Zeichen {2}.{3}", + "problems.tree.aria.label.warning.marker": "Von {0} generierte Warnung: {1} in Zeile {2} bei Zeichen {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Warnung: {0} in Zeile {1} bei Zeichen {2}.{3}", + "problems.tree.aria.label.info.marker": "Von {0} generierte Informationen: {1} in Zeile {2} bei Zeichen {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Informationen: {0} in Zeile {1} bei Zeichen {2}.{3}", + "problems.tree.aria.label.marker": "Von {0} generiertes Problem: {1} in Zeile {2} bei Zeichen {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Problem: {0} in Zeile {1} bei Zeichen {2}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{0} in Zeile {1} bei Zeichen {2} in {3}", + "errors.warnings.show.label": "Fehler und Warnungen anzeigen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/deu/src/vs/workbench/parts/output/browser/outputActions.i18n.json index c8aeb04fcb..c794e7a181 100644 --- a/i18n/deu/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Ausgabe umschalten", "clearOutput": "Ausgabe löschen", "toggleOutputScrollLock": "Ausgabe-Bildlaufsperre umschalten", - "switchToOutput.label": "Zur Ausgabe wechseln" + "switchToOutput.label": "Zur Ausgabe wechseln", + "openInLogViewer": "Protokolldatei öffnen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 7864adcdaa..5d0165d5bd 100644 --- a/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Ausgabe", "logViewer": "Protokollanzeige", "viewCategory": "Anzeigen", - "clearOutput.label": "Ausgabe löschen" + "clearOutput.label": "Ausgabe löschen", + "openActiveLogOutputFile": "Ansicht: Aktive Protokollausgabedatei öffnen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 286d94cb23..61cbbe2ab1 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Tastenkombinationen", + "showDefaultKeybindings": "Standard-Tastaturbelegungen anzeigen", + "showUserKeybindings": "Benutzer-Tastaturbelegungen anzeigen", "SearchKeybindings.AriaLabel": "Tastenzuordnungen suchen", "SearchKeybindings.Placeholder": "Tastenzuordnungen suchen", "sortByPrecedene": "Nach Priorität sortieren", diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 1514f25aac..19ff10a082 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Raw-Standardeinstellungen öffnen", + "openSettings": "Einstellungen öffnen", "openGlobalSettings": "Benutzereinstellungen öffnen", "openGlobalKeybindings": "Tastaturkurzbefehle öffnen", "openGlobalKeybindingsFile": "Datei mit Tastaturkurzbefehlen öffnen", diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index c110c8e105..dc635a6cc7 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Standardeinstellungen", "SearchSettingsWidget.AriaLabel": "Einstellungen suchen", "SearchSettingsWidget.Placeholder": "Einstellungen suchen", "noSettingsFound": "Keine Ergebnisse", @@ -16,6 +15,8 @@ "nlpResult": "Ergebnisse in natürlicher Sprache", "filterResult": "Gefilterte Ergebnisse", "defaultSettings": "Standardeinstellungen", + "defaultUserSettings": "Standardbenutzereinstellungen", + "defaultWorkspaceSettings": "Standard-Arbeitsbereichseinstellungen", "defaultFolderSettings": "Standardordnereinstellungen", "defaultEditorReadonly": "Nehmen Sie im Editor auf der rechten Seite Änderungen vor, um Standardwerte zu überschreiben.", "preferencesAriaLabel": "Standardeinstellungen. Schreibgeschützter Text-Editor." diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 721c9802b8..eab74406fe 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Erweiterung \"{0}\" anzeigen", "editTtile": "Bearbeiten", "replaceDefaultValue": "In Einstellungen ersetzen", - "copyDefaultValue": "In Einstellungen kopieren", - "unsupportedPHPExecutablePathSetting": "Diese Einstellung muss eine Benutzereinstellung sein. Öffnen Sie zum Konfigurieren von PHP für den Arbeitsbereich eine PHP-Datei, und klicken Sie in der Statusleiste auf \"PHP-Pfad\".", - "unsupportedWorkspaceSetting": "Diese Einstellung muss eine Benutzereinstellung sein.", - "unsupportedWorkbenchSetting": "Diese Einstellung kann jetzt nicht angewendet werden. Sie wird angewendet, wenn Sie den Ordner direkt öffnen.", - "unsupportedWorkbenchSettingDevMode": "Diese Einstellung kann jetzt nicht angewendet werden. Sie wird angewendet, wenn Sie ihren Bereich beim Registrieren als \"Ressource\" definieren oder den Ordner direkt öffnen." + "copyDefaultValue": "In Einstellungen kopieren" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index ccb05942e3..e03b2e39a0 100644 --- a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Installiere weiter SCM Provider...", "no open repo": "Es gibt keine aktiven Quellcodeanbieter.", "source control": "Quellcodeverwaltung", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Ausblenden" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json index cb9b85b884..12cb9f97eb 100644 --- a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Vorheriges Suchausschlussmuster anzeigen", "nextSearchTerm": "Nächsten Suchbegriff anzeigen", "previousSearchTerm": "Vorherigen Suchbegriff anzeigen", - "showSearchViewlet": "Suche anzeigen", "findInFiles": "In Dateien suchen", "replaceInFiles": "In Dateien ersetzen", "RefreshAction.label": "Aktualisieren", diff --git a/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 100721ddda..5ce5bde400 100644 --- a/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Suchen", + "copyMatchLabel": "Kopieren", + "copyPathLabel": "Pfad kopieren", + "copyAllLabel": "Alles kopieren", + "clearSearchHistoryLabel": "Suchverlauf löschen", + "toggleSearchViewPositionLabel": "Position der Suchansicht umschalten", "findInFolder": "In Ordner suchen...", "findInWorkspace": "In Arbeitsbereich suchen...", "showTriggerActions": "Zu Symbol im Arbeitsbereich wechseln...", "name": "Suchen", - "search": "Suchen", "showSearchViewl": "Suche anzeigen", "view": "Anzeigen", "findInFiles": "In Dateien suchen", @@ -26,5 +31,5 @@ "search.followSymlinks": "Steuert, ob Symlinks während der Suche gefolgt werden.", "search.smartCase": "Sucht ohne Berücksichtigung von Groß-/Kleinschreibung, wenn das Muster kleingeschrieben ist, andernfalls wird mit Berücksichtigung von Groß-/Kleinschreibung gesucht.", "search.globalFindClipboard": "Steuert, ob die Suchansicht die freigegebene Suchzwischenablage auf macOS lesen oder verändern soll", - "search.location": "Vorschau: Steuert, ob die Suche als Ansicht in der Seitenleiste oder als Bedienfeld im Bereich des Bedienfelds für horizontales Layout angezeigt wird. In der nächsten Version wird das horizontale Layout im Bedienfeld verbessert und dies keine Vorschau mehr sein." + "search.location": "Steuert, ob die Suche als Ansicht in der Seitenleiste oder als Bedienfeld im Bedienfeldbereich angezeigt wird, damit horizontal mehr Platz zur Verfügung steht. In der nächsten Version wird das horizontale Layout im Bedienfeld verbessert, und dies wird keine Vorschau mehr sein." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 69e96c5633..d50cab3384 100644 --- a/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Helfen Sie uns die Unterstützung für {0} zu verbessern", "takeShortSurvey": "An kurzer Umfrage teilnehmen", "remindLater": "Später erinnern", - "neverAgain": "Nicht mehr anzeigen", - "helpUs": "Helfen Sie uns die Unterstützung für {0} zu verbessern" + "neverAgain": "Nicht mehr anzeigen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 9124aad125..c01f532c4b 100644 --- a/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Wir würden uns freuen, wenn Sie an einer schnellen Umfrage teilnehmen.", "takeSurvey": "An Umfrage teilnehmen", "remindLater": "Später erinnern", - "neverAgain": "Nicht mehr anzeigen", - "surveyQuestion": "Wir würden uns freuen, wenn Sie an einer schnellen Umfrage teilnehmen." + "neverAgain": "Nicht mehr anzeigen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 622a7dc7b7..03cdb99ff4 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Ein Problemmuster oder der Name eines beigetragenen oder vordefinierten Problemmusters. Kann ausgelassen werden, wenn die Basis angegeben ist.", "ProblemMatcherSchema.base": "Der Name eines zu verwendenden Basisproblemabgleichers.", "ProblemMatcherSchema.owner": "Der Besitzer des Problems im Code. Kann ausgelassen werden, wenn \"base\" angegeben wird. Der Standardwert ist \"external\", wenn keine Angabe erfolgt und \"base\" nicht angegeben wird.", + "ProblemMatcherSchema.source": "Eine visuell lesbare Zeichenfolge, die die Quelle dieser Diagnose beschreibt, z. B. \"typescript\" oder \"super lint\".", "ProblemMatcherSchema.severity": "Der Standardschweregrad für Erfassungsprobleme. Dieser wird verwendet, wenn das Muster keine Übereinstimmungsgruppe für den Schweregrad definiert.", "ProblemMatcherSchema.applyTo": "Steuert, ob ein für ein Textdokument gemeldetes Problem nur auf geöffnete, geschlossene oder alle Dokumente angewendet wird.", "ProblemMatcherSchema.fileLocation": "Definiert, wie Dateinamen interpretiert werden sollen, die in einem Problemmuster gemeldet werden.", diff --git a/i18n/deu/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 34cadb883a..cedf63738b 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Der tatsächliche Aufgabentyp", + "TaskDefinition.description": "Der tatsächliche Aufgabentyp. Typen, die mit \"$\" beginnen, sind für den internen Gebrauch reserviert.", "TaskDefinition.properties": "Zusätzliche Eigenschaften des Aufgabentyps", "TaskTypeConfiguration.noType": "In der Konfiguration des Aufgabentyps fehlt die erforderliche taskType-Eigenschaft.", "TaskDefinitionExtPoint": "Trägt Aufgabenarten bei" diff --git a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index a9b501bcbb..7fbb2130f1 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "Weist die Aufgabe keiner Gruppe zu.", "JsonSchema.tasks.group": "Definiert die Ausführungsgruppe, zu der diese Aufgabe gehört. Zum Hinzufügen der Aufgabe zur Buildgruppe wird \"build\" unterstützt und zum Hinzufügen zur Testgruppe \"test\".", "JsonSchema.tasks.type": "Definiert, ob die Aufgabe als Prozess oder als Befehl innerhalb einer Shell ausgeführt wird.", + "JsonSchema.command.quotedString.value": "Der tatsächliche Sollwert", + "JsonSchema.tasks.quoting.escape": "Fügt mithilfe des Escapezeichens der Shell vor Zeichen Escapezeichen ein (z. B. `  bei PowerShell und \\ bei Bash).", + "JsonSchema.tasks.quoting.strong": "Setzt das Argument mithilfe des starken Anführungszeichens der Shell in Anführungszeichen (z. B. \" bei PowerShell und Bash).", + "JsonSchema.tasks.quoting.weak": "Setzt das Argument mithilfe des schwachen Anführungszeichens der Shell in Anführungszeichen (z. B. ' bei PowerShell und Bash).", + "JsonSchema.command.quotesString.quote": "In welche Anführungszeichen der Befehlswert gesetzt wird.", + "JsonSchema.command": "Der auszuführende Befehl. Es kann sich um ein externes Programm oder einen Shellbefehl handeln.", + "JsonSchema.args.quotedString.value": "Der tatsächliche Argumentwert", + "JsonSchema.args.quotesString.quote": "In welche Anführungszeichen der Argumentwert gesetzt wird.", + "JsonSchema.tasks.args": "Argumente, die an den Befehl übergeben werden, wenn diese Aufgabe aufgerufen wird.", "JsonSchema.tasks.label": "Die Bezeichnung der Aufgabe der Benutzerschnittstelle", "JsonSchema.version": "Die Versionsnummer der Konfiguration.", "JsonSchema.tasks.identifier": "Ein vom Benutzer definierter Bezeichner, mit dem in \"launch.json\" oder in einer dependsOn-Klausel auf die Aufgabe verwiesen wird.", diff --git a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index c81338170d..5e860baf0d 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "Aufgaben", "ConfigureTaskRunnerAction.label": "Aufgabe konfigurieren", + "totalErrors": "{0} Fehler", + "totalWarnings": "{0} Warnungen", + "totalInfos": "{0}-Informationen", "problems": "Probleme", "building": "Wird gebaut...", - "manyMarkers": "mehr als 99", + "manyProblems": "Über 10.000", "runningTasks": "Aktive Aufgaben anzeigen", "tasks": "Aufgaben", "TaskSystem.noHotSwap": "Zum Ändern des Aufgabenausführungsmoduls mit einem aktiven Task muss das Fenster erneut geladen werden.", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Fehler- und Warnungsarten auswählen, auf die die Aufgabenausgabe überprüft werden soll", "customizeParseErrors": "Die aktuelle Aufgabenkonfiguration weist Fehler auf. Beheben Sie die Fehler, bevor Sie eine Aufgabe anpassen.", "moreThanOneBuildTask": "In \"tasks.json\" sind mehrere Buildaufgaben definiert. Die erste wird ausgeführt.\n", - "TaskSystem.activeSame.background": "Die Aufgabe \"{0}\" ist bereits im Hintergrundmodus aktiv. Klicken Sie zum Beenden der Aufgabe im Menü \"Aufgaben\" auf \"Aufgabe beenden…\".", - "TaskSystem.activeSame.noBackground": "Die Aufgabe \"{0}\" ist bereits aktiv. Klicken Sie zum Beenden der Aufgabe im Menü \"Aufgaben\" auf \"Aufgabe beenden\".", + "TaskSystem.activeSame.background": "Die Aufgabe \"{0}\" ist bereits aktiv und befindet sich im Hintergrundmodus.", + "TaskSystem.activeSame.noBackground": "Die Aufgabe \"{0}\" ist bereits aktiv.", + "terminateTask": "Aufgabe beenden", + "restartTask": "Aufgabe neu starten", "TaskSystem.active": "Eine aktive Aufgabe wird bereits ausgeführt. Beenden Sie diese, bevor Sie eine andere Aufgabe ausführen.", "TaskSystem.restartFailed": "Fehler beim Beenden und Neustarten der Aufgabe \"{0}\".", "TaskService.noConfiguration": "Fehler: Die Aufgabenerkennung {0} hat für die folgende Konfiguration keine Aufgabe beigetragen:\n {1}\nDie Aufgabe wird ignoriert.\n", diff --git a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 677e0efd19..98f0b06649 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Aufgabe - {0}", "closeTerminal": "Betätigen Sie eine beliebige Taste, um das Terminal zu schließen.", "reuseTerminal": "Das Terminal wird von Aufgaben wiederverwendet, drücken Sie zum Schließen eine beliebige Taste.", - "TerminalTaskSystem": "Ein Shell-Befehl kann nicht auf einem UNC-Laufwerk ausgeführt werden.", + "TerminalTaskSystem": "Ein Shell-Befehl kann nicht mithilfe von cmd.exe auf einem UNC-Laufwerk ausgeführt werden.", "unkownProblemMatcher": "Der Problemabgleicher {0} kann nicht aufgelöst werden. Der Abgleicher wird ignoriert." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/deu/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 69d0e8992e..d3a6c80b9a 100644 --- a/i18n/deu/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Warnung: \"options.cwd\" muss vom Typ \"string\" sein. Der Wert {0} wird ignoriert.\n", + "ConfigurationParser.inValidArg": "Fehler: Befehlsargumente müssen Zeichenfolgen oder Zeichenfolgen in Anführungszeichen sein. Der angegebene Wert ist:\n{0}", "ConfigurationParser.noargs": "Fehler: Befehlsargumente müssen ein Array aus Zeichenfolgen sein. Angegebener Wert:\n{0}", "ConfigurationParser.noShell": "Warnung: Die Shell-Konfiguration wird nur beim Ausführen von Tasks im Terminal unterstützt.", "ConfigurationParser.noName": "Fehler: Der Problemabgleich im Deklarationsbereich muss einen Namen besitzen:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Fehler: Die Aufgabenkonfiguration \"{0}\" enthält die erforderlich Eigenschaft \"{1}\" nicht. Die Aufgabenkonfiguration wird ignoriert.", "ConfigurationParser.notCustom": "Fehler: Die Aufgabe ist nicht als benutzerdefinierte Aufgabe deklariert. Die Konfiguration wird ignoriert.\n{0}\n", "ConfigurationParser.noTaskName": "Fehler: Eine Aufgabe muss eine label-Eigenschaft angeben. Die Aufgabe wird ignoriert.\n{0}\n", - "taskConfiguration.shellArgs": "Warnung: Die Aufgabe \"{0}\" ist ein Shellbefehl, und eines seiner Argumente enthält Leerzeichen ohne Escapezeichen. Führen Sie Argumente im Befehl zusammen, um eine korrekte Angabe der Befehlszeile sicherzustellen.", "taskConfiguration.noCommandOrDependsOn": "Fehler: Aufgabe \"{0}\" definiert keinen Befehl bzw. keine depondsOn-Eigenschaft. Die Aufgabe wird ignoriert. Die Definition lautet:\n{1}", "taskConfiguration.noCommand": "Fehler: Aufgabe \"{0}\" definiert keinen Befehl. Die Aufgabe wird ignoriert. Die Definition lautet:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "Die Aufgabenversion 2.0.0 unterstützt globale betriebssystemspezifische Aufgaben nicht. Konvertieren Sie sie in eine Aufgabe mit einem betriebssystemspezifischen Befehl. Folgende Aufgaben sind hiervon betroffen:\n{0}" diff --git a/i18n/deu/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..84fc7fe0d6 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "Die Hintergrundfarbe des Terminals, dies ermöglicht eine unterschiedliche Färbung des Terminals im Panel.", + "terminal.foreground": "Die Vordergrundfarbe des Terminal.", + "terminalCursor.foreground": "Die Vordergrundfarbe des Terminalcursors.", + "terminalCursor.background": "Die Hintergrundfarbe des Terminalcursors. Ermöglicht das Anpassen der Farbe eines Zeichens, das von einem Blockcursor überdeckt wird.", + "terminal.selectionBackground": "Die Auswahlvordergrundfarbe des Terminals.", + "terminal.border": "Die Farbe des Rahmens, der Bereiche innerhalb des Terminals teilt. Der Standardwert ist panel.border.", + "terminal.ansiColor": "\"{0}\" ANSI-Farbe im Terminal" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 177ad3a732..dc99fa2383 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -20,7 +20,8 @@ "workbench.action.terminal.new.short": "Neues Terminal", "workbench.action.terminal.newWorkspacePlaceholder": "Aktuelles Arbeitsverzeichnis für neues Terminal auswählen", "workbench.action.terminal.newInActiveWorkspace": "Neues integriertes Terminal erstellen (in aktivem Arbeitsbereich)", - "workbench.action.terminal.split": "Details zu Sucheinstellungen", + "workbench.action.terminal.split": "Terminal verdoppeln", + "workbench.action.terminal.splitInActiveWorkspace": "Terminal teilen (in aktivem Arbeitsbereich)", "workbench.action.terminal.focusPreviousPane": "Fokus in vorherigem Bereich", "workbench.action.terminal.focusNextPane": "Fokus in nächstem Bereich", "workbench.action.terminal.resizePaneLeft": "Größe des linken Bereichs ändern", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "Nach oben scrollen (Seite)", "workbench.action.terminal.scrollToTop": "Bildlauf nach oben", "workbench.action.terminal.clear": "Löschen", + "workbench.action.terminal.clearSelection": "Auswahl löschen", "workbench.action.terminal.allowWorkspaceShell": "Shell-Konfiguration des Arbeitsbereichs zulassen", "workbench.action.terminal.disallowWorkspaceShell": "Verbiete Workspace Shell Konfiguration", "workbench.action.terminal.rename": "Umbenennen", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Widget zum Ausblenden der Suche", "nextTerminalFindTerm": "Nächsten Suchbegriff anzeigen", "previousTerminalFindTerm": "Vorherigen Suchbegriff anzeigen", - "quickOpenTerm": "Aktives Terminal wechseln" + "quickOpenTerm": "Aktives Terminal wechseln", + "workbench.action.terminal.scrollToPreviousCommand": "Zu vorherigem Befehl scrollen", + "workbench.action.terminal.scrollToNextCommand": "Zu nächstem Befehl scrollen", + "workbench.action.terminal.selectToPreviousCommand": "Auswählen bis zu vorherigem Befehl", + "workbench.action.terminal.selectToNextCommand": "Auswählen bis zu nächstem Befehl" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index 933fb5510f..c4511678dd 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "Das Terminal enthält keine Auswahl zum Kopieren.", "terminal.integrated.exitedWithCode": "Der Terminalprozess wurde mit folgendem Exitcode beendet: {0}", "terminal.integrated.waitOnExit": "Betätigen Sie eine beliebige Taste, um das Terminal zu schließen.", - "terminal.integrated.launchFailed": "Fehler beim Starten des Terminalprozessbefehls \"{0}{1}\" (Exitcode: {2})." + "terminal.integrated.launchFailed": "Fehler beim Starten des Terminalprozessbefehls \"{0}{1}\" (Exitcode: {2}).", + "terminal.integrated.launchFailedExtHost": "Der Terminalprozess konnte nicht gestartet werden (Exitcode: {0})" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 2f0d1e9aa3..7472ebf7b1 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copy": "Kopieren", + "split": "Teilen", "paste": "Einfügen", "selectAll": "Alles auswählen", "clear": "Löschen", diff --git a/i18n/deu/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index bd0406d499..263349083b 100644 --- a/i18n/deu/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Dieser Arbeitsbereich enthält Einstellungen, die nur in den Benutzereinstellungen festgelegt werden können ({0}). Klicken Sie [hier]({1}), um mehr zu erfahren.", "openWorkspaceSettings": "Arbeitsbereichseinstellungen öffnen", "dontShowAgain": "Nicht mehr anzeigen", "unsupportedWorkspaceSettings": "Dieser Arbeitsbereich enthält Einstellungen, die nur in den Benutzereinstellungen festgelegt werden können ({0}). Klicken Sie [hier]({1}), um mehr zu erfahren." diff --git a/i18n/deu/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/deu/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..e9c3a68337 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Anmerkungen zu dieser Version: {0}", + "unassigned": "Nicht zugewiesen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 0f473c53c8..7ad30b14c4 100644 --- a/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Später", - "unassigned": "Nicht zugewiesen", "releaseNotes": "Anmerkungen zu dieser Version", "showReleaseNotes": "Anmerkungen zu dieser Version anzeigen", "read the release notes": "Willkommen bei {0} v{1}! Möchten Sie die Hinweise zu dieser Version lesen?", @@ -17,13 +15,14 @@ "updateIsReady": "Neues {0}-Update verfügbar.", "noUpdatesAvailable": "Zurzeit sind keine Updates verfügbar.", "ok": "OK", - "download now": "Jetzt herunterladen", "thereIsUpdateAvailable": "Ein Update ist verfügbar.", - "installUpdate": "Update installieren", + "download now": "Jetzt herunterladen", + "later": "Später", "updateAvailable": "Ein Update ist verfügbar: {0} {1}", + "installUpdate": "Update installieren", "updateInstalling": "{0} {1} wird im Hintergrund installiert. Wir informieren Sie, wenn dies abgeschlossen ist.", + "updateAvailableAfterRestart": "Starten Sie {0} neu, um das neueste Update zu installieren.", "updateNow": "Jetzt aktualisieren", - "updateAvailableAfterRestart": "{0} wird nach dem Neustart aktualisiert.", "commandPalette": "Befehlspalette...", "settings": "Einstellungen", "keyboardShortcuts": "Tastenkombinationen", diff --git a/i18n/deu/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..d59e6ff3eb --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "URL öffnen", + "developer": "Entwickler" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..129a60d789 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "Webview-Editor", + "developer": "Entwickler" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..1492a37abd --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview-Entwicklertools öffnen", + "refreshWebviewLabel": "Webviews erneut laden" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/deu/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..343d4b1d7e --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Tragen Sie zur Verbesserung von VS Code bei, und lassen Sie zu, dass Microsoft Nutzungsdaten erfasst. Lesen Sie unsere [Datenschutzvereinbarung]({0}), und erfahren Sie, wie Sie dies [deaktivieren]({1}).", + "telemetryOptOut.optInNotice": "Tragen Sie zur Verbesserung von VS Code bei, und lassen Sie zu, dass Microsoft Nutzungsdaten erfasst. Lesen Sie unsere [Datenschutzvereinbarung]({0}), und erfahren Sie, wie Sie dies [aktivieren]({1}).", + "telemetryOptOut.readMore": "Weitere Informationen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/deu/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index c96c1d4d7e..8c0e5eb065 100644 --- a/i18n/deu/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Erweiterungen verwalten", "welcomeOverlay.problems": "Fehler und Warnungen anzeigen", "welcomeOverlay.commandPalette": "Alle Befehle suchen und ausführen", + "welcomeOverlay.notifications": "Benachrichtigungen anzeigen", "welcomeOverlay": "Benutzeroberflächenüberblick", "hideWelcomeOverlay": "Schnittstellenüberblick ausblenden", "help": "Hilfe" diff --git a/i18n/deu/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/deu/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 3fd68b96e3..c693d1cf95 100644 --- a/i18n/deu/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Tools und Sprachen", "welcomePage.installExtensionPacksDescription": "Unterstützung für {0} und {1} installieren", "welcomePage.moreExtensions": "mehr", - "welcomePage.installKeymapDescription": "Tastenkombinationen installieren", - "welcomePage.installKeymapExtension": "Installieren Sie die Tastenkombinationen von {0} und {1}.", + "welcomePage.installKeymapDescription": "Einstellungen und Tastenzuordnungen", + "welcomePage.installKeymapExtension": "Installieren Sie die Einstellungen und Tastenkombinationen von {0} und {1}", "welcomePage.others": "Andere", "welcomePage.colorTheme": "Farbdesign", "welcomePage.colorThemeDescription": "Passen Sie das Aussehen des Editors und Ihres Codes an Ihre Wünsche an.", diff --git a/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 4e3c8bc31c..19c52861ee 100644 --- a/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/deu/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Eine Zusammenfassung der Einstellungen. Diese Bezeichnung wird in der Einstellungsdatei als trennender Kommentar verwendet.", "vscode.extension.contributes.configuration.properties": "Die Beschreibung der Konfigurationseigenschaften.", + "scope.application.description": "Anwendungsspezifische Konfiguration, die nur in den Benutzereinstellungen konfiguriert werden kann.", "scope.window.description": "Fensterspezifische Konfiguration, die in den Benutzer- oder Arbeitsbereichseinstellungen konfiguriert werden kann.", "scope.resource.description": "Ressourcenspezifische Konfiguration, die in den Benutzer-, Arbeitsbereichs- oder Ordnereinstellungen konfiguriert werden kann.", "scope.description": "Bereich, in dem die Konfiguration gültig ist. Verfügbare Gültigkeitsbereiche sind \"window\" und \"resource\".", diff --git a/i18n/deu/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/deu/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 105a527acf..0c2db76a34 100644 --- a/i18n/deu/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Einstellungen öffnen", "saveAndRetry": "Speichern und wiederholen", "errorUnknownKey": "In {0} kann nicht geschrieben werden, weil {1} keine registrierte Konfiguration ist.", + "errorInvalidWorkspaceConfigurationApplication": "{0} kann nicht in die Arbeitsbereichseinstellungen geschrieben werden. Diese Einstellung kann nur in den Benutzereinstellungen geschrieben werden.", "errorInvalidFolderConfiguration": "In die Ordnereinstellungen kann nicht geschrieben werden, weil {0} den Gültigkeitsbereich für Ordnerressourcen nicht unterstützt.", "errorInvalidUserTarget": "In die Benutzereinstellungen kann nicht geschrieben werden, weil {0} den globalen Gültigkeitsbereich nicht unterstützt.", "errorInvalidWorkspaceTarget": "In die Arbeitsbereichseinstellungen kann nicht geschrieben werden, da {0} den Arbeitsbereichsumfang in einem Arbeitsbereich mit mehreren Ordnern nicht unterstützt.", diff --git a/i18n/deu/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/deu/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..0508efb20d --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Diese Einstellung kann nur in den Benutzereinstellungen angewendet werden", + "unsupportedWindowSetting": "Diese Einstellung kann jetzt nicht angewendet werden. Sie wird angewendet, wenn Sie den Ordner direkt öffnen." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/deu/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/deu/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..d691ed2871 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "\"{0}\" kann nicht aufgelöst werden, da kein Umgebungsvariablenname angegeben ist.", + "configNotFound": "\"{0}\" kann nicht aufgelöst werden, da die Einstellung \"{1}\" nicht gefunden wurde.", + "configNoString": "\"{0}\" kann nicht aufgelöst werden, da \"{1}\" ein strukturierter Wert ist.", + "missingConfigName": "\"{0}\" kann nicht aufgelöst werden, da kein Einstellungsname angegeben ist.", + "noValueForCommand": "\"{0}\" kann nicht aufgelöst werden, da der Befehl keinen Wert hat.", + "canNotFindFolder": "\"{0}\" kann nicht aufgelöst werden. Es ist kein Ordner \"{1}\" vorhanden.", + "canNotResolveWorkspaceFolderMultiRoot": "\"{0}\" kann nicht in einem Arbeitsbereich mit mehreren Ordnern aufgelöst werden. Legen Sie mithilfe von \":\" und einem Arbeitsbereichs-Ordnernamen einen Bereich für diese Variable fest.", + "canNotResolveWorkspaceFolder": "\"{0}\" kann nicht aufgelöst werden. Öffnen Sie einen Ordner.", + "canNotResolveFile": "\"{0}\" kann nicht aufgelöst werden. Öffnen Sie einen Editor.", + "canNotResolveLineNumber": "\"{0}\" kann nicht aufgelöst werden. Im aktiven Editor muss eine Zeile ausgewählt sein.", + "canNotResolveSelectedText": "\"{0}\" kann nicht aufgelöst werden. Im aktiven Editor muss Text ausgewählt sein." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/deu/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..4a29a1c902 --- /dev/null +++ b/i18n/deu/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Ja", + "cancelButton": "Abbrechen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/deu/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index acfe6907b5..b5b0321255 100644 --- a/i18n/deu/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/deu/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Modulkompatibilität.", "vscode.extension.engines.vscode": "Gibt für VS Code-Erweiterungen die VS Code-Version an, mit der die Erweiterung kompatibel ist. Darf nicht \"*\" sein. Beispiel: ^0.10.5 gibt die Kompatibilität mit mindestens VS Code-Version 0.10.5 an.", "vscode.extension.publisher": "Der Herausgeber der VS Code-Extension.", "vscode.extension.displayName": "Der Anzeigename für die Extension, der im VS Code-Katalog verwendet wird.", "vscode.extension.categories": "Die vom VS Code-Katalog zum Kategorisieren der Extension verwendeten Kategorien.", + "vscode.extension.category.languages.deprecated": "Stattdessen \"Programmiersprachen\" verwenden", "vscode.extension.galleryBanner": "Das in VS Code Marketplace verwendete Banner.", "vscode.extension.galleryBanner.color": "Die Bannerfarbe für die Kopfzeile der VS Code Marketplace-Seite.", "vscode.extension.galleryBanner.theme": "Das Farbdesign für die Schriftart, die im Banner verwendet wird.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Ein Aktivierungsereignis ausgegeben, wenn eine Debug-Sitzung mit dem spezifischen Typ gestartet wird (und eine entsprechende resolveDebugConfiguration-Methode aufgerufen werden muss).", "vscode.extension.activationEvents.workspaceContains": "Ein Aktivierungsereignis wird beim Öffnen eines Ordners ausgegeben, der mindestens eine Datei enthält, die mit dem angegebenen Globmuster übereinstimmt.", "vscode.extension.activationEvents.onView": "Ein Aktivierungsereignis wird beim Erweitern der angegebenen Ansicht ausgegeben.", + "vscode.extension.activationEvents.onUri": "Ein Aktivierungsereignis wird ausgegeben, wenn ein systemweiter URI, der auf diese Erweiterung ausgerichtet ist, geöffnet ist.", "vscode.extension.activationEvents.star": "Ein Aktivierungsereignis wird beim Start von VS Code ausgegeben. Damit für die Endbenutzer eine bestmögliche Benutzerfreundlichkeit sichergestellt ist, verwenden Sie dieses Aktivierungsereignis in Ihrer Erweiterung nur dann, wenn in Ihrem Anwendungsfall keine andere Kombination an Aktivierungsereignissen funktioniert.", "vscode.extension.badges": "Array aus Badges, die im Marketplace in der Seitenleiste auf der Seite mit den Erweiterungen angezeigt werden.", "vscode.extension.badges.url": "Die Bild-URL für den Badge.", "vscode.extension.badges.href": "Der Link für den Badge.", "vscode.extension.badges.description": "Eine Beschreibung für den Badge.", + "vscode.extension.markdown": "Steuert das im Marketplace verwendete Markdown-Renderingmodul. Entweder GitHub (Standardeinstellung) oder Standard", + "vscode.extension.qna": "Steuert den Q&A-Link im Marketplace. Auf Marketplace festlegen, um die standardmäßige Q&A-Marketplace-Site zu aktivieren. Auf eine Zeichenfolge festlegen, um die URL einer benutzerdefinierten Q&A-Site anzugeben. Auf FALSE festlegen, um Q&A komplett zu deaktivieren.", "vscode.extension.extensionDependencies": "Abhängigkeiten von anderen Erweiterungen. Der Bezeichner einer Erweiterung ist immer ${publisher}.${name}, beispielsweise \"vscode.csharp\".", "vscode.extension.scripts.prepublish": "Ein Skript, das ausgeführt wird, bevor das Paket als VS Code-Extension veröffentlicht wird.", "vscode.extension.scripts.uninstall": "Uninstall-Hook für VS Code-Erweiterung: Skript, das ausgeführt wird, wenn die Erweiterung vollständig aus VS Code deinstalliert wurde. Dies ist der Fall, wenn VS Code nach der Deinstallation der Erweiterung neu gestartet wurde (Herunterfahren und Starten). Nur Node-Skripts werden unterstützt. ", diff --git a/i18n/deu/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/deu/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 3831257f81..0f861722c9 100644 --- a/i18n/deu/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Alle Erweiterungen sind deaktiviert.", "extensionHostProcess.crash": "Der Erweiterungshost wurde unerwartet beendet.", "extensionHostProcess.unresponsiveCrash": "Der Erweiterungshost wurde beendet, weil er nicht reagiert hat.", - "devTools": "Entwicklertools", + "devTools": "Entwicklertools öffnen", "restart": "Erweiterungshost neu starten", "overwritingExtension": "Die Erweiterung \"{0}\" wird mit \"{1}\" überschrieben.", "extensionUnderDevelopment": "Die Entwicklungserweiterung unter \"{0}\" wird geladen.", diff --git a/i18n/deu/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/deu/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index d4b1b28826..846beeace7 100644 --- a/i18n/deu/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5 ist erforderlich. Klicken Sie auf den Link, um die Anwendung zu installieren.", "installNet": ".NET Framework 4.5 herunterladen", "neverShowAgain": "Nicht mehr anzeigen", - "netVersionError": "Microsoft .NET Framework 4.5 ist erforderlich. Klicken Sie auf den Link, um die Anwendung zu installieren.", + "enospcError": "{0} kann keine Dateiänderungen in diesem großen Workspace überwachen. Folgen Sie dem Anwendungslink, um das Problem zu beheben.", "learnMore": "Anweisungen", - "enospcError": "Keine Dateihandles mehr in {0} vorhanden. Folgen Sie dem Anwendungslink, um das Problem zu beheben.", + "fileInvalidPath": "Ungültige Dateiressource ({0})", + "fileIsDirectoryError": "Die Datei ist ein Verzeichnis", + "fileNotModifiedError": "Datei nicht geändert seit", + "fileTooLargeForHeapError": "Zum Öffnen einer Datei dieser Größe müssen Sie VS Code neu starten und die Verwendung von mehr Arbeitsspeicher zulassen", + "fileTooLargeError": "Die Datei ist zu groß, um sie zu öffnen.", + "fileNotFoundError": "Die Datei wurde nicht gefunden ({0}).", + "fileBinaryError": "Die Datei scheint eine Binärdatei zu sein und kann nicht als Text geöffnet werden.", + "filePermission": "Schreibzugriff auf Datei ({0}) verweigert", + "fileExists": "Die zu erstellende Datei ist bereits vorhanden ({0}). ", + "fileModifiedError": "Datei geändert seit", + "fileReadOnlyError": "Die Datei ist schreibgeschützt.", + "fileMoveConflict": "Verschieben/Kopieren kann nicht ausgeführt werden. Die Datei ist am Ziel bereits vorhanden.", + "unableToMoveCopyError": "Der Verschiebe-/Kopiervorgang kann nicht ausgeführt werden. Die Datei würde den Ordner ersetzen, in dem sie enthalten ist.", "binFailed": "Fehler beim Verschieben von \"{0}\" in den Papierkorb.", "trashFailed": "Fehler beim Verschieben von \"{0}\" in den Papierkorb." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 99d23343ab..8a5efc2fb7 100644 --- a/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Die Datei wurde nicht gefunden ({0}).", "fileIsDirectoryError": "Die Datei ist ein Verzeichnis", "fileNotModifiedError": "Datei nicht geändert seit", - "fileBinaryError": "Die Datei scheint eine Binärdatei zu sein und kann nicht als Text geöffnet werden." + "fileBinaryError": "Die Datei scheint eine Binärdatei zu sein und kann nicht als Text geöffnet werden.", + "err.create": "Fehler beim Erstellen der Datei {0}", + "fileMoveConflict": "Verschieben/Kopieren kann nicht ausgeführt werden. Die Datei ist am Ziel bereits vorhanden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/deu/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..afd4a61124 100644 --- a/i18n/deu/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/deu/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Abbrechen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 7f5b097fcc..634f028be2 100644 --- a/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Der TextMate-Bereichsname, der von der tmLanguage-Datei verwendet wird.", "vscode.extension.contributes.grammars.path": "Der Pfad der tmLanguage-Datei. Der Pfad ist relativ zum Extensionordner und beginnt normalerweise mit \". /syntaxes/\".", "vscode.extension.contributes.grammars.embeddedLanguages": "Eine Zuordnung zwischen Bereichsname und Sprach-ID, wenn diese Grammatik eingebettete Sprachen enthält.", + "vscode.extension.contributes.grammars.tokenTypes": "Eine Zuordnung von Bereichsnamen zu Tokentypen.", "vscode.extension.contributes.grammars.injectTo": "Die Liste der Sprachbereichsnamen, in die diese Grammatik injiziert wird." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 890d3762b3..f5190f658e 100644 --- a/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/deu/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "Expected string in `contributes.{0}.path`. Provided value: {1}", "invalid.injectTo": "Ungültiger Wert in \"contributes.{0}.injectTo\". Es muss sich um ein Array von Sprachbereichsnamen handeln. Bereitgestellter Wert: {1}", "invalid.embeddedLanguages": "Ungültiger Wert in \"contributes.{0}.embeddedLanguages\". Muss eine Objektzuordnung von Bereichsname zu Sprache sein. Angegebener Wert: {1}", + "invalid.tokenTypes": "Ungültiger Wert in \"contributes.{0}.tokenTypes\". Muss eine Objektzuordnung von Bereichsname zu Tokentyp sein. Angegebener Wert: {1}", "invalid.path.1": "Es wurde erwartet, dass \"contributes.{0}.path\" ({1}) im Ordner ({2}) der Erweiterung enthalten ist. Dies führt ggf. dazu, dass die Erweiterung nicht portierbar ist.", "no-tm-grammar": "Keine TM-Grammatik für diese Sprache registriert." } \ No newline at end of file diff --git a/i18n/esn/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/esn/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..0100d5fd5a --- /dev/null +++ b/i18n/esn/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "Servidor de lenguaje CSS", + "folding.start": "Inicio de la región plegable", + "folding.end": "Fin de la región plegable" +} \ No newline at end of file diff --git a/i18n/esn/extensions/css-language-features/package.i18n.json b/i18n/esn/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..91d31339c0 --- /dev/null +++ b/i18n/esn/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Características del lenguaje CSS", + "description": "Proporciona un potente soporte de lenguaje para archivos CSS, LESS y SCSS.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", + "css.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", + "css.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", + "css.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", + "css.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", + "css.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", + "css.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", + "css.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", + "css.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", + "css.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", + "css.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", + "css.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", + "css.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", + "css.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", + "css.lint.unknownProperties.desc": "Propiedad desconocida.", + "css.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", + "css.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", + "css.lint.zeroUnits.desc": "No se necesita una unidad para cero", + "css.trace.server.desc": "Hace un seguimiento de la comunicación entre VSCode y el servidor de lenguaje CSS.", + "css.validate.title": "Controla la validación de CSS y la gravedad de los problemas.", + "css.validate.desc": "Habilita o deshabilita todas las validaciones", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", + "less.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", + "less.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", + "less.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", + "less.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", + "less.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", + "less.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", + "less.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", + "less.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", + "less.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", + "less.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", + "less.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", + "less.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", + "less.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", + "less.lint.unknownProperties.desc": "Propiedad desconocida.", + "less.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", + "less.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", + "less.lint.zeroUnits.desc": "No se necesita una unidad para cero", + "less.validate.title": "Controla la validación de LESS y la gravedad de los problemas.", + "less.validate.desc": "Habilita o deshabilita todas las validaciones", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", + "scss.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", + "scss.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", + "scss.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", + "scss.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", + "scss.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", + "scss.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", + "scss.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", + "scss.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", + "scss.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", + "scss.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", + "scss.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", + "scss.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", + "scss.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", + "scss.lint.unknownProperties.desc": "Propiedad desconocida.", + "scss.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", + "scss.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", + "scss.lint.zeroUnits.desc": "No se necesita una unidad para cero", + "scss.validate.title": "Controla la validación de SCSS y la gravedad de los problemas.", + "scss.validate.desc": "Habilita o deshabilita todas las validaciones", + "less.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", + "scss.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", + "css.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", + "css.colorDecorators.enable.deprecationMessage": "El valor \"css.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\".", + "scss.colorDecorators.enable.deprecationMessage": "El valor \"scss.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\".", + "less.colorDecorators.enable.deprecationMessage": "El valor \"less.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\"." +} \ No newline at end of file diff --git a/i18n/esn/extensions/css/package.i18n.json b/i18n/esn/extensions/css/package.i18n.json index 285e792036..3d441a7650 100644 --- a/i18n/esn/extensions/css/package.i18n.json +++ b/i18n/esn/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Características del lenguaje CSS", - "description": "Proporciona un potente soporte de lenguaje para archivos CSS, LESS y SCSS.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", - "css.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", - "css.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", - "css.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", - "css.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", - "css.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", - "css.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", - "css.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", - "css.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", - "css.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", - "css.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", - "css.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", - "css.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", - "css.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", - "css.lint.unknownProperties.desc": "Propiedad desconocida.", - "css.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", - "css.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", - "css.lint.zeroUnits.desc": "No se necesita una unidad para cero", - "css.trace.server.desc": "Hace un seguimiento de la comunicación entre VSCode y el servidor de lenguaje CSS.", - "css.validate.title": "Controla la validación de CSS y la gravedad de los problemas.", - "css.validate.desc": "Habilita o deshabilita todas las validaciones", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", - "less.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", - "less.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", - "less.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", - "less.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", - "less.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", - "less.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", - "less.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", - "less.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", - "less.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", - "less.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", - "less.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", - "less.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", - "less.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", - "less.lint.unknownProperties.desc": "Propiedad desconocida.", - "less.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", - "less.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", - "less.lint.zeroUnits.desc": "No se necesita una unidad para cero", - "less.validate.title": "Controla la validación de LESS y la gravedad de los problemas.", - "less.validate.desc": "Habilita o deshabilita todas las validaciones", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Número de parámetros no válido", - "scss.lint.boxModel.desc": "No use ancho o alto con el relleno o los bordes.", - "scss.lint.compatibleVendorPrefixes.desc": "Cuando use un prefijo específico del proveedor, compruebe que también haya incluido el resto de propiedades específicas del proveedor.", - "scss.lint.duplicateProperties.desc": "No use definiciones de estilo duplicadas", - "scss.lint.emptyRules.desc": "No use conjuntos de reglas vacíos", - "scss.lint.float.desc": "Le recomendamos no usar 'float'. Los floats producen CSS frágiles, fáciles de corromper si cambia cualquier aspecto del diseño.", - "scss.lint.fontFaceProperties.desc": "La regla @font-face debe definir las propiedades \"src\" y \"font-family\"", - "scss.lint.hexColorLength.desc": "Los colores hexadecimales deben estar formados por tres o seis números hexadecimales.", - "scss.lint.idSelector.desc": "Los selectores no deben contener identificadores porque estas reglas están estrechamente ligadas a HTML.", - "scss.lint.ieHack.desc": "Las modificaciones de IE solo son necesarias cuando admiten IE7 y anteriores", - "scss.lint.important.desc": "Le recomendamos no usar !important. Esto indica que la especificidad de todo el CSS está fuera de control y que debe refactorizarse.", - "scss.lint.importStatement.desc": "Las instrucciones Import no se cargan en paralelo", - "scss.lint.propertyIgnoredDueToDisplay.desc": "La propiedad se ignora a causa de la pantalla. Por ejemplo, con 'display: inline', el ancho, el alto, el margen superior e inferior y las propiedades de float no tienen efecto.", - "scss.lint.universalSelector.desc": "Se sabe que el selector universal (*) es lento", - "scss.lint.unknownProperties.desc": "Propiedad desconocida.", - "scss.lint.unknownVendorSpecificProperties.desc": "Propiedad específica del proveedor desconocida.", - "scss.lint.vendorPrefix.desc": "Cuando use un prefijo específico del proveedor, incluya también la propiedad estándar.", - "scss.lint.zeroUnits.desc": "No se necesita una unidad para cero", - "scss.validate.title": "Controla la validación de SCSS y la gravedad de los problemas.", - "scss.validate.desc": "Habilita o deshabilita todas las validaciones", - "less.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", - "scss.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", - "css.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", - "css.colorDecorators.enable.deprecationMessage": "El valor \"css.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\".", - "scss.colorDecorators.enable.deprecationMessage": "El valor \"scss.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\".", - "less.colorDecorators.enable.deprecationMessage": "El valor \"less.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\"." + "displayName": "Básicos de CSS", + "description": "Proporciona resaltado de sintaxis y correspondencia de corchetes en archivos CSS, LESS y SCSS." } \ No newline at end of file diff --git a/i18n/esn/extensions/emmet/package.i18n.json b/i18n/esn/extensions/emmet/package.i18n.json index af803087d4..f3f241a7f9 100644 --- a/i18n/esn/extensions/emmet/package.i18n.json +++ b/i18n/esn/extensions/emmet/package.i18n.json @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Ruta de acceso a una carpeta que contiene los perfiles y fragmentos de Emmet.", "emmetShowExpandedAbbreviation": "Muestra abreviaciones Emmet expandidas como sugerencias. La opción \"inMarkupAndStylesheetFilesOnly\" se aplica a HTML, HAML, Jade, Slim, XML, XSL, CSS, SCSS, SASS, LESS y Stylus. La opción \"always\" se aplica a todas las partes del archivo, independientemente de que sea de marcado o CSS. ", "emmetShowAbbreviationSuggestions": "Muestra posibles abreviaciones Emmet como sugerencias. No se aplica a hojas de estilos ni cuando emmet.showExpandedAbbreviation está establecido en \"never\". ", - "emmetIncludeLanguages": "Habilita abreviaciones Emmet en lenguajes que no se admiten de forma predeterminada. Agregue una asignación aquí entre el lenguaje y el lenguaje que admite Emmet. Ejemplo: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"} ", + "emmetIncludeLanguages": "Habilite las abreviaturas de Emmet en idiomas que no sean compatibles de forma predeterminada. Añada una asignación aquí entre el idioma y el idioma admitido por Emmet.\n Ej.: { \"Vue-HTML \": \"HTML \", \"JavaScript \": \"javascriptreact \"}", "emmetVariables": "Variables para ser utilizadas en fragmentos de código de Emmet", "emmetTriggerExpansionOnTab": "Cuando se habilita, se expande la abreviación Emmet al presionar la tecla TAB. ", "emmetPreferences": "Preferencias usadas para modificar el comportamiento de algunas acciones y resoluciones de Emmet.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Propiedades CSS separadas por comas que obtienen el prefijo de proveedor 'webkit' cuando se utilizan en la abreviatura Emmet que comienza con '-'. Establecer en la cadena vacía para evitar siempre el prefijo 'webkit'.", "emmetPreferencesCssMozProperties": "Propiedades CSS separadas por comas que obtienen el prefijo de proveedor 'moz' cuando se utilizan en la abreviatura Emmet que comienza con '-'. Establecer en la cadena vacía para evitar siempre el prefijo 'moz'.", "emmetPreferencesCssOProperties": "Propiedades CSS separadas por comas que obtienen el prefijo de proveedor 'o' cuando se utilizan en la abreviatura Emmet que comienza con '-'. Establecer en la cadena vacía para evitar siempre el prefijo 'o'.", - "emmetPreferencesCssMsProperties": "Propiedades CSS separadas por comas que obtienen el prefijo de proveedor 'ms' cuando se utilizan en la abreviatura Emmet que comienza con '-'. Establecer en la cadena vacía para evitar siempre el prefijo 'ms'." + "emmetPreferencesCssMsProperties": "Propiedades CSS separadas por comas que obtienen el prefijo de proveedor 'ms' cuando se utilizan en la abreviatura Emmet que comienza con '-'. Establecer en la cadena vacía para evitar siempre el prefijo 'ms'.", + "emmetPreferencesCssFuzzySearchMinScore": "La mínima puntuación (de 0 a 1) que se debe alcanzar en la comparación difusa de abreviación. Los valores más bajos pueden producir muchos resultados falsos positivos, los valores más altos pueden reducir posibles coincidencias.", + "emmetOptimizeStylesheetParsing": "Cuando se establece en falso, se analiza el archivo entero para determinar si la posición actual es válida para la expansión de abreviaturas de Emmet. Cuando se establece en verdadero, sólo el contenido alrededor de la posición actual en archivos css, scss/less es analizado." } \ No newline at end of file diff --git a/i18n/esn/extensions/git/out/commands.i18n.json b/i18n/esn/extensions/git/out/commands.i18n.json index 171d165bc2..cfff5f12aa 100644 --- a/i18n/esn/extensions/git/out/commands.i18n.json +++ b/i18n/esn/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) crear nueva rama", "repourl": "URL del repositorio", "parent": "Directorio principal", - "cancel": "$(sync~spin) Clonando repositorio... Haga clic para cancelar", - "cancel tooltip": "Cancelar clonación", - "cloning": "Clonando el repositorio GIT...", + "cloning": "Clonación del repositorio git ' {0} '...", "openrepo": "Abrir repositorio", "proposeopen": "¿Desea abrir el repositorio clonado?", "init": "Seleccione una carpeta de área de trabajo en la que inicializar el repositorio de git", @@ -75,7 +73,7 @@ "ok": "Aceptar", "push with tags success": "Insertado con etiquetas correctamente.", "pick remote": "Seleccionar un elemento remoto para publicar la rama '{0}':", - "sync is unpredictable": "Esta acción insertará y extraerá confirmaciones en '{0}'.", + "sync is unpredictable": "Esta acción insertará e incorporará cambios en y desde '{0}/{1}'.", "never again": "No volver a mostrar ", "no remotes to publish": "El repositorio no tiene remotos configurados en los que publicar.", "no changes stash": "No existen cambios para el guardado provisional.", diff --git a/i18n/esn/extensions/git/package.i18n.json b/i18n/esn/extensions/git/package.i18n.json index baab098709..580bb12227 100644 --- a/i18n/esn/extensions/git/package.i18n.json +++ b/i18n/esn/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Controla si se debe mostrar una acción de archivo abierto en la vista de cambios en Git", "config.inputValidation": "Controla cuándo mostrar el mensaje de validación de entrada en el contador de entrada.", "config.detectSubmodules": "Controla si se detectan automáticamente los submódulos Git. ", + "config.detectSubmodulesLimit": "Controla el límite de submódulos de git detectados.", "colors.modified": "Color para recursos modificados.", "colors.deleted": "Color para los recursos eliminados.", "colors.untracked": "Color para los recursos a los que no se les hace seguimiento.", diff --git a/i18n/esn/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/esn/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..9900526f77 --- /dev/null +++ b/i18n/esn/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "Servidor de lenguaje HTML", + "folding.start": "Inicio de la región plegable", + "folding.end": "Fin de la región plegable" +} \ No newline at end of file diff --git a/i18n/esn/extensions/html-language-features/package.i18n.json b/i18n/esn/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..44cb8a8581 --- /dev/null +++ b/i18n/esn/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Características del lenguaje HTML", + "description": "Proporciona un potente soporte del lenguaje para archivos HTML, Razor y Handlebar.", + "html.format.enable.desc": "Habilitar o deshabilitar el formateador HTML predeterminado", + "html.format.wrapLineLength.desc": "Cantidad máxima de caracteres por línea (0 = deshabilitar).", + "html.format.unformatted.desc": "Lista de etiquetas, separadas por comas, a las que no se debe volver a aplicar formato. El valor predeterminado de \"null\" son todas las etiquetas mostradas en https://www.w3.org/TR/html5/dom.html#phrasing-content.", + "html.format.contentUnformatted.desc": "Lista de etiquetas, separadas por comas, en las que el contenido no debe volver a formatearse. \"null\" se establece de manera predeterminada en la etiqueta \"pre\".", + "html.format.indentInnerHtml.desc": "Aplicar sangría a las secciones <head> y <body>.", + "html.format.preserveNewLines.desc": "Indica si los saltos de línea existentes delante de los elementos deben conservarse. Solo funciona delante de los elementos, no dentro de las etiquetas o con texto.", + "html.format.maxPreserveNewLines.desc": "Número máximo de saltos de línea que deben conservarse en un fragmento. Use \"null\" para que el número sea ilimitado.", + "html.format.indentHandlebars.desc": "Formato y sangría {{#foo}} y {{/foo}}.", + "html.format.endWithNewline.desc": "Finalizar con una nueva línea.", + "html.format.extraLiners.desc": "Lista de etiquetas, separadas por comas, que deben tener una nueva línea adicional delante. \"null\" tiene como valores predeterminados \"head, body, /html\".", + "html.format.wrapAttributes.desc": "Ajustar atributos.", + "html.format.wrapAttributes.auto": "Ajustar atributos solo cuando se supera la longitud de la línea.", + "html.format.wrapAttributes.force": "Ajustar todos los atributos excepto el primero.", + "html.format.wrapAttributes.forcealign": "Ajustar todos los atributos excepto el primero y mantener la alineación.", + "html.format.wrapAttributes.forcemultiline": "Ajustar todos los atributos.", + "html.suggest.angular1.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas y propiedades de Angular V1.", + "html.suggest.ionic.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas, propiedades y valores de Ionic.", + "html.suggest.html5.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas, propiedades y valores de HTML5.", + "html.trace.server.desc": "Hace un seguimiento de la comunicación entre VSCode y el servidor de lenguaje HTML.", + "html.validate.scripts": "Configura si la compatibilidad con el lenguaje HTML incorporado valida los scripts insertados.", + "html.validate.styles": "Configura si la compatibilidad con el lenguaje HTML incorporado valida los estilos insertados.", + "html.autoClosingTags": "Habilita o deshabilita el cierre automático de las etiquetas HTML." +} \ No newline at end of file diff --git a/i18n/esn/extensions/html/package.i18n.json b/i18n/esn/extensions/html/package.i18n.json index 8e9548295a..ac148b80b0 100644 --- a/i18n/esn/extensions/html/package.i18n.json +++ b/i18n/esn/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Características del lenguaje HTML", - "description": "Proporciona un potente soporte del lenguaje para archivos HTML, Razor y Handlebar.", - "html.format.enable.desc": "Habilitar o deshabilitar el formateador HTML predeterminado", - "html.format.wrapLineLength.desc": "Cantidad máxima de caracteres por línea (0 = deshabilitar).", - "html.format.unformatted.desc": "Lista de etiquetas, separadas por comas, a las que no se debe volver a aplicar formato. El valor predeterminado de \"null\" son todas las etiquetas mostradas en https://www.w3.org/TR/html5/dom.html#phrasing-content.", - "html.format.contentUnformatted.desc": "Lista de etiquetas, separadas por comas, en las que el contenido no debe volver a formatearse. \"null\" se establece de manera predeterminada en la etiqueta \"pre\".", - "html.format.indentInnerHtml.desc": "Aplicar sangría a las secciones <head> y <body>.", - "html.format.preserveNewLines.desc": "Indica si los saltos de línea existentes delante de los elementos deben conservarse. Solo funciona delante de los elementos, no dentro de las etiquetas o con texto.", - "html.format.maxPreserveNewLines.desc": "Número máximo de saltos de línea que deben conservarse en un fragmento. Use \"null\" para que el número sea ilimitado.", - "html.format.indentHandlebars.desc": "Formato y sangría {{#foo}} y {{/foo}}.", - "html.format.endWithNewline.desc": "Finalizar con una nueva línea.", - "html.format.extraLiners.desc": "Lista de etiquetas, separadas por comas, que deben tener una nueva línea adicional delante. \"null\" tiene como valores predeterminados \"head, body, /html\".", - "html.format.wrapAttributes.desc": "Ajustar atributos.", - "html.format.wrapAttributes.auto": "Ajustar atributos solo cuando se supera la longitud de la línea.", - "html.format.wrapAttributes.force": "Ajustar todos los atributos excepto el primero.", - "html.format.wrapAttributes.forcealign": "Ajustar todos los atributos excepto el primero y mantener la alineación.", - "html.format.wrapAttributes.forcemultiline": "Ajustar todos los atributos.", - "html.suggest.angular1.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas y propiedades de Angular V1.", - "html.suggest.ionic.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas, propiedades y valores de Ionic.", - "html.suggest.html5.desc": "Configura si la compatibilidad con el lenguaje HTML integrada sugiere etiquetas, propiedades y valores de HTML5.", - "html.trace.server.desc": "Hace un seguimiento de la comunicación entre VSCode y el servidor de lenguaje HTML.", - "html.validate.scripts": "Configura si la compatibilidad con el lenguaje HTML incorporado valida los scripts insertados.", - "html.validate.styles": "Configura si la compatibilidad con el lenguaje HTML incorporado valida los estilos insertados.", - "html.experimental.syntaxFolding": "Habilita/deshabilita los marcadores de plegado sensibles a la sintaxis.", - "html.autoClosingTags": "Habilita o deshabilita el cierre automático de las etiquetas HTML." + "displayName": "Conceptos básicos de lenguaje HTML", + "description": "Proporciona resaltado de sintaxis, correspondencia de corchetes y fragmentos de código en archivos HTML." } \ No newline at end of file diff --git a/i18n/esn/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/esn/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..253bfb394d --- /dev/null +++ b/i18n/esn/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "Servidor de lenguaje JSON" +} \ No newline at end of file diff --git a/i18n/esn/extensions/json-language-features/package.i18n.json b/i18n/esn/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..d18d8b81bc --- /dev/null +++ b/i18n/esn/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Características del lenguaje JSON", + "description": "Proporciona un potente soporte de lenguaje para archivos JSON.", + "json.schemas.desc": "Asociar esquemas a archivos JSON en el proyecto actual", + "json.schemas.url.desc": "Una dirección URL a un esquema o una ruta de acceso relativa a un esquema en el directorio actual", + "json.schemas.fileMatch.desc": "Una matriz de patrones de archivo con los cuales coincidir cuando los archivos JSON se resuelvan en esquemas.", + "json.schemas.fileMatch.item.desc": "Un patrón de archivo que puede contener \"*\" con el cual coincidir cuando los archivos JSON se resuelvan en esquemas.", + "json.schemas.schema.desc": "La definición de esquema de la dirección URL determinada. Solo se necesita proporcionar el esquema para evitar los accesos a la dirección URL del esquema.", + "json.format.enable.desc": "Habilitar/deshabilitar formateador JSON predeterminado (requiere reiniciar)", + "json.tracing.desc": "Realiza el seguimiento de la comunicación entre VS Code y el servidor de lenguaje JSON.", + "json.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", + "json.colorDecorators.enable.deprecationMessage": "El valor \"json.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\"." +} \ No newline at end of file diff --git a/i18n/esn/extensions/json/package.i18n.json b/i18n/esn/extensions/json/package.i18n.json index 7223c9be42..e79d4e38be 100644 --- a/i18n/esn/extensions/json/package.i18n.json +++ b/i18n/esn/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Características del lenguaje JSON", - "description": "Proporciona un potente soporte de lenguaje para archivos JSON.", - "json.schemas.desc": "Asociar esquemas a archivos JSON en el proyecto actual", - "json.schemas.url.desc": "Una dirección URL a un esquema o una ruta de acceso relativa a un esquema en el directorio actual", - "json.schemas.fileMatch.desc": "Una matriz de patrones de archivo con los cuales coincidir cuando los archivos JSON se resuelvan en esquemas.", - "json.schemas.fileMatch.item.desc": "Un patrón de archivo que puede contener \"*\" con el cual coincidir cuando los archivos JSON se resuelvan en esquemas.", - "json.schemas.schema.desc": "La definición de esquema de la dirección URL determinada. Solo se necesita proporcionar el esquema para evitar los accesos a la dirección URL del esquema.", - "json.format.enable.desc": "Habilitar/deshabilitar formateador JSON predeterminado (requiere reiniciar)", - "json.tracing.desc": "Seguimiento de comunicación entre VS Code y el servidor de lenguaje JSON", - "json.colorDecorators.enable.desc": "Habilita o deshabilita decoradores de color", - "json.colorDecorators.enable.deprecationMessage": "El valor \"json.colorDecorators.enable\" está en desuso en favor de \"editor.colorDecorators\".", - "json.experimental.syntaxFolding": "Habilita/deshabilita los marcadores de plegado sensibles a la sintaxis." + "displayName": "Conceptos básicos de lenguaje JSON", + "description": "Proporciona resaltado de sintaxis y correspondencia de corchetes en archivos JSON." } \ No newline at end of file diff --git a/i18n/esn/extensions/markdown-basics/package.i18n.json b/i18n/esn/extensions/markdown-basics/package.i18n.json index 67a8fd6dbc..ae1623cce0 100644 --- a/i18n/esn/extensions/markdown-basics/package.i18n.json +++ b/i18n/esn/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/esn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/esn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..a97aa29723 --- /dev/null +++ b/i18n/esn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "No se pudo cargar 'markdown.styles': {0}" +} \ No newline at end of file diff --git a/i18n/esn/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/esn/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..0743f60083 --- /dev/null +++ b/i18n/esn/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Vista previa] {0}", + "previewTitle": "Vista Previa {0}" +} \ No newline at end of file diff --git a/i18n/esn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/esn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..ef0bed9244 --- /dev/null +++ b/i18n/esn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Se ha deshabilitado parte del contenido de este documento", + "preview.securityMessage.title": "Se ha deshabilitado el contenido potencialmente inseguro en la previsualización de Markdown. Para permitir el contenido inseguro o habilitar scripts cambie la configuración de la previsualización de Markdown", + "preview.securityMessage.label": "Alerta de seguridad de contenido deshabilitado" +} \ No newline at end of file diff --git a/i18n/esn/extensions/markdown-language-features/out/security.i18n.json b/i18n/esn/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..6d04884c96 --- /dev/null +++ b/i18n/esn/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Strict", + "strict.description": "Cargar solo el contenido seguro", + "insecureLocalContent.title": "Permitir contenido local inseguro ", + "insecureLocalContent.description": "Habilitar la carga del contenido sobre http desde localhost", + "insecureContent.title": "Permitir contenido no seguro", + "insecureContent.description": "Habilitar el contenido de carga sobre http", + "disable.title": "Deshabilitar", + "disable.description": "Permitir todo el contenido y la ejecución de scripts. No se recomienda.", + "moreInfo.title": "Más información", + "enableSecurityWarning.title": "Habilitar advertencias de seguridad de vista previa en este espacio de trabajo", + "disableSecurityWarning.title": "Deshabilitar advertencias de seguridad de vista previa en este espacio de trabajo", + "toggleSecurityWarning.description": "No afecta al nivel de seguridad de contenido", + "preview.showPreviewSecuritySelector.title": "Seleccione configuración de seguridad para las previsualizaciones de Markdown en esta área de trabajo" +} \ No newline at end of file diff --git a/i18n/esn/extensions/markdown-language-features/package.i18n.json b/i18n/esn/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..0e6d8a1f74 --- /dev/null +++ b/i18n/esn/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Características del lenguaje Markdown", + "description": "Proporciona un potente soporte de lenguaje para archivos Markdown.", + "markdown.preview.breaks.desc": "Establece cómo los saltos de línea son representados en la vista previa de markdown. Estableciendolo en 'true' crea un <br> para cada nueva línea.", + "markdown.preview.linkify": "Habilitar o deshabilitar la conversión de texto de tipo URL a enlaces en la vista previa de markdown.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Haga doble clic en la vista previa de Markdown para cambiar al editor.", + "markdown.preview.fontFamily.desc": "Controla la familia de la fuente utilizada en la previsualización del descuento.", + "markdown.preview.fontSize.desc": "Controla el tamaño de la fuente en píxeles utilizado en la previsualización del descuento.", + "markdown.preview.lineHeight.desc": "Controla la altura de línea utilizada en la previsualización del descuento. Este número es relativo al tamaño de la fuente.", + "markdown.preview.markEditorSelection.desc": "Marca la selección del editor actual en la vista previa de Markdown.", + "markdown.preview.scrollEditorWithPreview.desc": "Al desplazarse en la vista previa de Markdown, se actualiza la vista del editor.", + "markdown.preview.scrollPreviewWithEditor.desc": "Al desplazarse en el editor de Markdown, se actualiza la vista de la previsualización .", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Desestimado] Desplaza la vista previa de Markdown para revelar la línea del editor seleccionada actualmente.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Este valor se ha reemplazado por \"markdown.preview.scrollPreviewWithEditor\" y ya no tiene ningún efecto.", + "markdown.preview.title": "Abrir vista previa", + "markdown.previewFrontMatter.dec": "Establece cómo se debe representar el asunto de la parte delantera de YAML en la vista previa del descuento. 'hide' quita el asunto de la parte delantera. De lo contrario, el asunto de la parte delantera se trata como contenido del descuento.", + "markdown.previewSide.title": "Abrir vista previa en el lateral", + "markdown.showLockedPreviewToSide.title": "Abrir vista previa fija en el lateral", + "markdown.showSource.title": "Mostrar origen", + "markdown.styles.dec": "Una lista de direcciones URL o rutas de acceso locales a hojas de estilo CSS que utilizar desde la vista previa del descuento. Las tutas de acceso relativas se interpretan en relación con la carpeta abierta en el explorador. Si no hay ninguna carpeta abierta, se interpretan en relación con la ubicación del archivo del descuento. Todos los '\\' deben escribirse como '\\\\'.", + "markdown.showPreviewSecuritySelector.title": "Cambiar configuración de seguridad de vista previa", + "markdown.trace.desc": "Habilitar registro de depuración para las extensiones de Markdown. ", + "markdown.preview.refresh.title": "Actualizar vista previa", + "markdown.preview.toggleLock.title": "Cambiar fijación de la vista previa " +} \ No newline at end of file diff --git a/i18n/esn/extensions/markdown/out/features/preview.i18n.json b/i18n/esn/extensions/markdown/out/features/preview.i18n.json index 5f6910ae02..0743f60083 100644 --- a/i18n/esn/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/esn/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/esn/extensions/npm/out/npmView.i18n.json b/i18n/esn/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..5d96d5850a --- /dev/null +++ b/i18n/esn/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "No se pudo iniciar \"{0} \" para la depuración porque las secuencias de comandos carecen de una opción de depuración de nodo, por ejemplo \"--inspect-brk\".", + "npm.scriptInvalid": "No se pudo encontrar la secuencia de comandos \"{0}\". Trate de actualizar la vista." +} \ No newline at end of file diff --git a/i18n/esn/extensions/npm/out/tasks.i18n.json b/i18n/esn/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..888ecbd58c --- /dev/null +++ b/i18n/esn/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Detección de tareas de la NMP: error al analizar el archivo {0}" +} \ No newline at end of file diff --git a/i18n/esn/extensions/npm/package.i18n.json b/i18n/esn/extensions/npm/package.i18n.json index 9f7fca9777..4649fdc6be 100644 --- a/i18n/esn/extensions/npm/package.i18n.json +++ b/i18n/esn/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "Ejecutar comandos de npm con la opción '--silent'", "config.npm.packageManager": "El administrador de paquetes utilizado para ejecutar secuencias de comandos. ", "config.npm.exclude": "Configura patrones globales para carpetas que deben excluirse de la detección automática de scripts. ", + "config.npm.enableScriptExplorer": "Habilitar la vista del Explorador para los scripts de la NMP, cuando el espacio de trabajo contiene un archivo 'package.json'.", "npm.parseError": "Detección de tareas de nueva gestión pública: no se pudo analizar el archivo {0}", "taskdef.script": "Script npm que debe personalizarse.", - "taskdef.path": "Ruta de acceso a la carpeta del archivo package.json que proporciona el script. Se puede omitir." + "taskdef.path": "Ruta de acceso a la carpeta del archivo package.json que proporciona el script. Se puede omitir.", + "view.name": "Scripts Npm ", + "command.refresh": "Actualizar", + "command.run": "Ejecutar", + "command.debug": "Depurar", + "command.openScript": "Abrir", + "npm.scriptInvalid": "No se pudo encontrar el script '{0}'. Trate de actualizar la vista.", + "npm.noDebugOptions": "No se pudo iniciar ' {0} ' para la depuración porque las secuencias de comandos carecen de una opción de depuración de nodo, por ejemplo '--inspect-brk'." } \ No newline at end of file diff --git a/i18n/esn/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/esn/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..a204115941 --- /dev/null +++ b/i18n/esn/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "¿Permite la ejecución de {0} (definido como valor del área de trabajo) para detectar errores en archivos PHP?", + "php.yes": "Permitir", + "php.no": "No permitir", + "wrongExecutable": "No se puede validar porque {0} no es un ejecutable PHP válido. Use el ajuste \"php.validate.executablePath\" para configurar el ejecutable PHP.", + "noExecutable": "No se puede validar porque no hay ningún ejecutable PHP establecido. Use el ajuste \"php.validate.executablePath\" para configurar el ejecutable de PHP.", + "unknownReason": "No se pudo ejecutar el archivo PHP con la ruta de acceso: {0}. Se desconoce el motivo." +} \ No newline at end of file diff --git a/i18n/esn/extensions/php-language-features/package.i18n.json b/i18n/esn/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..0b5e90ed32 --- /dev/null +++ b/i18n/esn/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Configura si se habilitan las sugerencias del lenguaje PHP integradas. La asistencia sugiere variables y opciones globales de PHP.", + "configuration.validate.enable": "Habilita o deshabilita la validación integrada de PHP.", + "configuration.validate.executablePath": "Señala al ejecutable PHP.", + "configuration.validate.run": "Indica si linter se ejecuta al guardar o al escribir.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "No permitir el ejecutable de validación de PHP (como configuración de área de trabajo)", + "displayName": "Características del lenguaje PHP", + "description": "Proporciona un potente soporte de lenguaje para archivos PHP." +} \ No newline at end of file diff --git a/i18n/esn/extensions/php/package.i18n.json b/i18n/esn/extensions/php/package.i18n.json index 46f4b34c61..edf1d540da 100644 --- a/i18n/esn/extensions/php/package.i18n.json +++ b/i18n/esn/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Configura si se habilitan las sugerencias del lenguaje PHP integradas. La asistencia sugiere variables y opciones globales de PHP.", - "configuration.validate.enable": "Habilita o deshabilita la validación integrada de PHP.", - "configuration.validate.executablePath": "Señala al ejecutable PHP.", - "configuration.validate.run": "Indica si linter se ejecuta al guardar o al escribir.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "No permitir el ejecutable de validación de PHP (como configuración de área de trabajo)", - "displayName": "Características del lenguaje PHP", - "description": "Proporciona IntelliSense, linting y conceptos básicos del lenguaje para archivos de PHP." + "displayName": "Conceptos básicos del lenguaje PHP", + "description": "Proporciona resaltado de sintaxis y correspondencia de corchetes en archivos PHP." } \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/commands.i18n.json b/i18n/esn/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..0406f029ae --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Abra una carpeta en VS Code para usar un proyecto de TypeScript o JavaScript", + "typescript.projectConfigUnsupportedFile": "No se pudo determinar el proyecto de TypeScript o JavaScript. Tipo de archivo no compatible", + "typescript.projectConfigCouldNotGetInfo": "No se pudo determinar el proyecto de TypeScript o JavaScript", + "typescript.noTypeScriptProjectConfig": "El archivo no forma parte de un proyecto de TypeScript. Haga clic [aquí]({0}) para obtener más información.", + "typescript.noJavaScriptProjectConfig": "El archivo no forma parte de un proyecto de JavaScript. Haga clic [aquí]({0}) para obtener más información.", + "typescript.configureTsconfigQuickPick": "Configurar tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurar jsconfig.json" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..20f0523671 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Seleccione acción de código para aplicar", + "acquiringTypingsLabel": "Adquiriendo typings...", + "acquiringTypingsDetail": "Adquiriendo definiciones de typings para IntelliSense.", + "autoImportLabel": "Importar automáticamente desde {0}" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..c51828607c --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Habilita la verificación semántica en un archivo de JavaScript. Debe estar al principio del archivo.", + "ts-nocheck": "Deshabilita la verificación semántica en un archivo de JavaScript. Debe estar al principio del archivo.", + "ts-ignore": "Suprime los errores @ts-check en la siguiente línea de un archivo. " +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..5cab0f0f87 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 implementación", + "manyImplementationLabel": "{0} implementaciones", + "implementationsErrorLabel": "No se pueden determinar las implementaciones" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..7579ba46bb --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "Comentario de JSDoc" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..226cfad118 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Organizar las importaciones" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..a3699d251e --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Corregir todo en el archivo)" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..028c2af8de --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 referencia", + "manyReferenceLabel": "{0} referencias", + "referenceErrorLabel": "No se pudieron determinar las referencias" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..2737725617 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "construir - {0}", + "buildAndWatchTscLabel": "seguir - {0}" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/esn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..12d95cb707 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "La ruta de acceso {0} no apunta a una instalación válida de tsserver. Se usará la versión de TypeScript del paquete.", + "serverCouldNotBeStarted": "El servidor de lenguaje TypeScript no se pudo iniciar. El mensaje de error es: {0}", + "typescript.openTsServerLog.notSupported": "El registro del servidor de TS requiere TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "Los registros del servidor TS están desconectados. Establezca \"typescript.tsserver.log\" y reinicie el servidor TS para activar los registros.", + "typescript.openTsServerLog.enableAndReloadOption": "Habilite el registro y reinicie el servidor TS", + "typescript.openTsServerLog.noLogFile": "El servidor de TS no ha iniciado el registro.", + "openTsServerLog.openFileFailedFailed": "No se puede abrir el archivo de registro del servidor de TS", + "serverDiedAfterStart": "El servicio de lenguaje TypeScript finalizó de forma inesperada cinco veces después de haberse iniciado y no se reiniciará.", + "serverDiedReportIssue": "Notificar problema", + "serverDied": "El servicio de lenguaje Typescript finalizó de forma inesperada cinco veces en los últimos cinco minutos." +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..ea0f0a445e --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "versión inválida" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..6b1caf7be0 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Para habilitar las características de lenguaje de JavaScript/TypeScript en todo el proyecto, excluya las carpetas con muchos archivos, como: {0}", + "hintExclude.generic": "Para habilitar las características de idioma de JavaScript/TypeScript IntelliSense en todo el proyecto, excluya las carpetas de tamaño grande con archivos de origen en los que no trabaje.", + "large.label": "Configurar exclusiones", + "hintExclude.tooltip": "Para habilitar las características de idioma de JavaScript/TypeScript IntelliSense en todo el proyecto, excluya las carpetas de tamaño grande con archivos de origen en los que no trabaje." +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..290207978a --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Recuperando cambios en los datos para un mejor rendimiento de TypeScript IntelliSense", + "typesInstallerInitializationFailed.title": "No se pudieron instalar archivos de términos para las características de lenguaje de JavaScript. Asegúrese de que NPM está instalado o configure \"typescript.npm\" en la configuración de usuario. Haga clic [aquí]({0}) para obtener más información.", + "typesInstallerInitializationFailed.doNotCheckAgain": "No volver a mostrar" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..2cac579a21 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Utilizar la versión de VS Code", + "useWorkspaceVersionOption": "Usar versión del área de trabajo", + "learnMore": "Más información", + "selectTsVersion": "Seleccionar la versión de TypeScript usada para las características del lenguaje de JavaScript y TypeScript" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/esn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..2fa648a3e7 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "No se pudo cargar la versión de TypeScript en esta ruta", + "noBundledServerFound": "Otra aplicación (por ejemplo, una herramienta de detección de virus con un comportamiento erróneo) eliminó el tsserver de VSCode. Debe reinstalar el VS Code." +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript-language-features/package.i18n.json b/i18n/esn/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..4963282d83 --- /dev/null +++ b/i18n/esn/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Características del lenguaje JavaScript y TypeScript", + "description": "Proporciona soporte de lenguaje enriquecido para JavaScript y TypeScript.", + "typescript.reloadProjects.title": "Volver a cargar el proyecto", + "javascript.reloadProjects.title": "Volver a cargar el proyecto", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Complete las funciones con la signatura de parámetro.", + "typescript.tsdk.desc": "Especifica la ruta de acceso de carpeta que contiene los archivos lib*.d.ts y tsserver que se van a usar.", + "typescript.disableAutomaticTypeAcquisition": "Desactiva la adquisición automática de tipos. Requiere TypeScript >= 2.0.6.", + "typescript.tsserver.log": "votes Habilita los registros del servidor TS a un archivo. Este registro se puede utilizar para diagnosticar problemas en el servidor TS. Este registro puede contener rutas de acceso, código fuente y posiblemente otra información sensitiva acerca del proyecto.", + "typescript.tsserver.pluginPaths": "Rutas adicionales para descubrir plugins de servicio del lenguaje Typescript. Requiere TypeScript >= 2.3.0.", + "typescript.tsserver.pluginPaths.item": "Ruta relativa o absoluta. La ruta de acceso relativa se resolverá contra las carpetas del espacio de trabajo.", + "typescript.tsserver.trace": "Habilita el seguimiento de mensajes al servidor TS. Este seguimiento se puede utilizar para diagnosticar problemas en el servidor TS. Este seguimiento puede contener rutas de acceso, código fuente y posiblemente otra información sensitiva acerca del proyecto.", + "typescript.validate.enable": "Habilita o deshabilita la validación de TypeScript.", + "typescript.format.enable": "Habilita o deshabilita el formateador predeterminado de TypeScript.", + "javascript.format.enable": "Habilita o deshabilita el formateador predeterminado de JavaScript.", + "format.insertSpaceAfterCommaDelimiter": "Define el tratamiento del espacio después de un delimitador de coma.", + "format.insertSpaceAfterConstructor": "Define el manejo del espacio después de la palabra clave constructor. Requiere TypeScript >= 2.3.0", + "format.insertSpaceAfterSemicolonInForStatements": " Define el tratamiento del espacio después de punto y coma en una instrucción for.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Define el tratamiento del espacio después de un operador binario.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Define el tratamiento del espacio después de las palabras clave en una instrucción de flujo de control.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Define el tratamiento del espacio después de la palabra clave function para las funciones anónimas.", + "format.insertSpaceBeforeFunctionParenthesis": "Define el tratamiento del espacio delante de los paréntesis de los argumentos de las funciones. Requiere TypeScript >= 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Define el manejo del espacio después de abrir y antes de cerrar paréntesis no vacíos.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Define el manejo del espacio después de abrir y antes de cerrar los soportes no vacíos.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Define el manejo del espacio después de abrir y antes de cerrar llaves no vacías. Requiere TypeScript > = 2.3.0.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Define el tratamiento del espacio después de la llave de apertura y antes de la llave de cierre de cadenas de plantilla. Requiere TypeScript >= 2.0.6.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Define el tratamiento del espacio después de la llave de apertura y antes de la llave de cierre de las expresiones JSX. Requiere TypeScript >= 2.0.6.", + "format.insertSpaceAfterTypeAssertion": "Define el control del espacio después de las aserciones de tipos en TypeScript. Requiere TypeScript >= 2.4", + "format.placeOpenBraceOnNewLineForFunctions": "Define si una llave de apertura se incluye en una nueva línea para las funciones o no.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Define si una llave de apertura se incluye en una nueva línea para los bloques de control o no.", + "javascript.validate.enable": "Habilita o deshabilita la validación de JavaScript.", + "typescript.goToProjectConfig.title": "Ir a configuración del proyecto", + "javascript.goToProjectConfig.title": "Ir a configuración del proyecto", + "javascript.referencesCodeLens.enabled": "Habilitar/deshabilitar las referencias de CodeLens en los archivos de JavaScript.", + "typescript.referencesCodeLens.enabled": "Habilitar/deshabilitar las referencias de CodeLens en los archivos de TypeScript. Requiere TypeScript >= 2.0.6.", + "typescript.implementationsCodeLens.enabled": "Habilita o deshabilita implementaciones de CodeLens. Requiere TypeScript >= 2.2.0.", + "typescript.openTsServerLog.title": "Abrir registro del servidor de TS", + "typescript.restartTsServer": "Reiniciar servidor TS", + "typescript.selectTypeScriptVersion.title": "Seleccionar versión de TypeScript", + "typescript.reportStyleChecksAsWarnings": "Notificar comprobaciones de estilo como advertencias", + "jsDocCompletion.enabled": "Habilita o deshabilita comentarios automaticos de JSDoc", + "javascript.implicitProjectConfig.checkJs": "Habilita/deshabilita la comprobación semántica de los archivos JavaScript. Los archivos jsconfig.json o tsconfig.json reemplazan esta configuración. Se requiere TypeScript >=2.3.1.", + "typescript.npm": "Especifica la ruta de acceso al archivo ejecutable de NPM usada para la adquisición automática de tipos. Requiere TypeScript >= 2.3.4.", + "typescript.check.npmIsInstalled": "Compruebe si NPM está instalado para la adquisición automática de tipos.", + "javascript.nameSuggestions": "Habilitar/deshabilitar nombres únicos de la lista de sugerencias en los archivos de JavaScript. ", + "typescript.tsc.autoDetect": "Controla la auto detección de tareas del CAC. 'off' inhabilita esta función. 'build' crea una ejecución de compilación de tareas. 'watch' sólo crea compilación y 'watch tasks' 'on' crea tanto construir y ver tareas. Por defecto = 'on'. ", + "typescript.problemMatchers.tsc.label": "Problemas de TypeScript", + "typescript.problemMatchers.tscWatch.label": "Problemas de TypeScript (modo de inspección)", + "typescript.quickSuggestionsForPaths": "Activar o desactiva las sugerencias rápidas al escribir una ruta de importación.", + "typescript.locale": "Establece la configuración regional para reportar errores de TypeScript. Requiere TypeScript > = 2.6.0. Por defecto, utiliza el valor 'null' de VS Code para errores de TypeScript.", + "javascript.implicitProjectConfig.experimentalDecorators": "Activar/desactivar 'experimentalDecorators' para los archivos JavaScript que no son parte de un proyecto. Los archivos jsconfig.json o tsconfig.json reemplazan esta configuración. Requiere inicio > = 2.3.1. ", + "typescript.autoImportSuggestions.enabled": "Habilita o deshabilita sugerencias de importación automática.  Requiere TypeScript >= 2.6.1.", + "typescript.experimental.syntaxFolding": "Habilita/deshabilita los marcadores de plegado sensibles a la sintaxis.", + "taskDefinition.tsconfig.description": "Archivo tsconfig que define la compilación de TS.", + "javascript.suggestionActions.enabled": "Habilitar/deshabilitar sugerencias de diagnóstico para los archivos JavaScript en el editor. Requiere TypeScript > = 2.8 ", + "typescript.suggestionActions.enabled": "Habilitar/deshabilitar sugerencias de diagnóstico para los archivos JavaScript en el editor. Requiere TypeScript > = 2.8 " +} \ No newline at end of file diff --git a/i18n/esn/src/vs/base/node/processes.i18n.json b/i18n/esn/src/vs/base/node/processes.i18n.json index ebb3d65e4b..31902d0456 100644 --- a/i18n/esn/src/vs/base/node/processes.i18n.json +++ b/i18n/esn/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "No se puede ejecutar un comando shell en una unidad UNC." + "TaskRunner.UNC": "No se puede ejecutar un comando shell en una unidad UNC. " } \ No newline at end of file diff --git a/i18n/esn/src/vs/base/node/zip.i18n.json b/i18n/esn/src/vs/base/node/zip.i18n.json index c8b4719eb4..944c7bac4e 100644 --- a/i18n/esn/src/vs/base/node/zip.i18n.json +++ b/i18n/esn/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Incompleta. Extraído {0} de {1} entradas", "notFound": "{0} no se encontró dentro del archivo zip." } \ No newline at end of file diff --git a/i18n/esn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/esn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 86bf31800a..efeedf7059 100644 --- a/i18n/esn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/esn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "Visualizar en GitHub", "loadingData": "Cargando datos...", + "rateLimited": "Límite de consulta de GitHub excedido. Espera.", "similarIssues": "Problemas similares", "open": "Abrir", "closed": "Cerrado", - "noResults": "No se encontraron resultados", + "noSimilarIssues": "No hay problemas similares encontrados", "settingsSearchIssue": "Problema de búsqueda de configuración", "bugReporter": "Informe de errores", - "performanceIssue": "Problema de rendimiento", "featureRequest": "Solicitud de característica", + "performanceIssue": "Problema de rendimiento", "stepsToReproduce": "Pasos para reproducir", "bugDescription": "Indique los pasos necesarios para reproducir el problema. Debe incluir el resultado real y el resultado esperado. Admitimos Markdown al estilo de GitHub. Podrá editar el problema y agregar capturas de pantalla cuando veamos una vista previa en GitHub.", "performanceIssueDesciption": "¿Cuándo ocurrió este problema de rendimiento? ¿Se produce al inicio o después de realizar una serie específica de acciones? Admitimos Markdown al estilo de GitHub. Podrá editar el problema y agregar capturas de pantalla cuando veamos una vista previa en GitHub.", diff --git a/i18n/esn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/esn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index c5b244a052..ad772087dc 100644 --- a/i18n/esn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/esn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Por favor complete el formulario en inglés.", "issueTypeLabel": "Esto es un", + "issueSourceLabel": "Archivo en", + "vscode": "Visual Studio Code", + "extension": "Una extensión", + "disableExtensionsLabelText": "Intente reproducir el problema después de {0}. Si el problema sólo se reproduce cuando las extensiones están activas, puede que haya un problema con una extensión.", + "disableExtensions": "Deshabilitar todas las extensiones y volver a cargar la ventana", + "chooseExtension": "Extensión", "issueTitleLabel": "Título", "issueTitleRequired": "Por favor, introduzca un título.", "titleLengthValidation": "El título es demasiado largo.", @@ -18,13 +24,6 @@ "extensions": "Mis extensiones", "searchedExtensions": "Extensiones que se han buscado", "settingsSearchDetails": "Detalles de la búsqueda de configuración", - "tryDisablingExtensions": "¿Se reproduce el problema cuando están deshabilitadas las extensiones?", - "yes": "Sí", - "no": "No", - "disableExtensionsLabelText": "Intente reproducir el problema después de {0}.", - "disableExtensions": "Deshabilitar todas las extensiones y volver a cargar la ventana", - "showRunningExtensionsLabelText": "Si sospecha que se trata de un problema con una extensión, {0} para notificarlo.", - "showRunningExtensions": "Ver todas las extensiones que están en ejecución", "details": "Especifique los detalles.", "loadingData": "Cargando datos..." } \ No newline at end of file diff --git a/i18n/esn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/esn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..c10a769e35 --- /dev/null +++ b/i18n/esn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU %", + "memory": "Memoria (MB)", + "pid": "pid", + "name": "Nombre", + "killProcess": "Matar proceso", + "forceKillProcess": "Forzar matar proceso" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/code/electron-main/menus.i18n.json b/i18n/esn/src/vs/code/electron-main/menus.i18n.json index 4c1f571cd8..d32fd15625 100644 --- a/i18n/esn/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/esn/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "Punto de interrupción &&condicional...", "miColumnBreakpoint": "Punto de interrupción de c&&olumna", "miFunctionBreakpoint": "Punto de interrupción de &&función...", + "miLogPoint": "&& Logpoint...", "miNewBreakpoint": "&&Nuevo punto de interrupción", "miEnableAllBreakpoints": "Habilitar todos los puntos de interrupción", "miDisableAllBreakpoints": "&&Deshabilitar todos los puntos de interrupción", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Fusionar todas las ventanas", "miToggleDevTools": "&&Alternar herramientas de desarrollo", "miAccessibilityOptions": "&&Opciones de accesibilidad", + "miOpenProcessExplorerer": "Abrir Explorador de &&Procesos", "miReportIssue": "&&Notificar problema", "miWelcome": "&&Bienvenido", "miInteractivePlayground": "Área de juegos &&interactiva", diff --git a/i18n/esn/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/esn/src/vs/editor/browser/widget/diffReview.i18n.json index 3e31c98747..6e828fa375 100644 --- a/i18n/esn/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/esn/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Cerrar", - "header": "Diferencia {0} de {1}: original {2}, {3} líneas, modificado {4}, {5} líneas", + "no_lines": "sin líneas", + "one_line": "1 línea", + "more_lines": "{0} líneas", + "header": "Diferencia {0} de {1}: original {2}, {3}, modificado {4}, {5}", "blankLine": "vacío", "equalLine": "original {0}, modificado {1}: {2}", "insertLine": "+ modificado {0}: {1}", diff --git a/i18n/esn/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/esn/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..d60d995d48 --- /dev/null +++ b/i18n/esn/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "El número de cursores se ha limitado a {0}." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json index 94dc8d4ce5..541af19f49 100644 --- a/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "Los números de línea se muestran como un número absoluto.", "lineNumbers.relative": "Los números de línea se muestran como distancia en líneas a la posición del cursor.", "lineNumbers.interval": "Los números de línea se muestran cada 10 líneas.", - "lineNumbers": "Controla la visualización de números de línea. Los valores posibles son 'on', 'off', 'relative' e 'interval'.", + "lineNumbers": "Controla la visualización de números de línea.", "rulers": "Representar reglas verticales después de un cierto número de caracteres monoespacio. Usar multiples valores para multiples reglas. No se dibuja ninguna regla si la matriz esta vacía.", "wordSeparators": "Caracteres que se usarán como separadores de palabras al realizar operaciones o navegaciones relacionadas con palabras.", "tabSize": "El número de espacios a los que equivale una tabulación. Este valor se invalida según el contenido del archivo cuando `editor.detectIndentation` está activado.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Controla si el editor se seguirá desplazando después de la última línea", "smoothScrolling": "Controla si el editor se desplaza con una animación", "minimap.enabled": "Controla si se muestra el minimapa", - "minimap.side": "Controla el lado dónde rendir el minimapa. Los valores posibles son 'derecha' e 'izquierda'", - "minimap.showSlider": "Controla si se oculta automáticamente el control deslizante del minimapa. Los valores posibles son \"always\" y \"mouseover\".", + "minimap.side": "Controla el lado dónde rendir el minimapa.", + "minimap.showSlider": "Controla si el control deslizante del minimapa es ocultado automáticamente.", "minimap.renderCharacters": "Presentar los caracteres reales en una línea (por oposición a bloques de color)", "minimap.maxColumn": "Limitar el ancho del minimapa para presentar como mucho un número de columnas determinado", "find.seedSearchStringFromSelection": "Controla si se inicializa la cadena de búsqueda en Buscar widget en la selección del editor", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Se asigna a \"Control\" en Windows y Linux y a \"Comando\" en macOS.", "multiCursorModifier.alt": "Se asigna a \"Alt\" en Windows y Linux y a \"Opción\" en macOS.", "multiCursorModifier": "El modificador que se usará para agregar varios cursores con el mouse. \"ctrlCmd\" se asigna a \"Control\" en Windows y Linux y a \"Comando\" en macOS. Los gestos del mouse \"Ir a la definición\" y \"Abrir vínculo\" se adaptarán de modo que no entren en conflicto con el modificador multicurso", + "multiCursorMergeOverlapping": "Combinar varios cursores cuando se solapan.", "quickSuggestions.strings": "Habilita sugerencias rápidas en las cadenas.", "quickSuggestions.comments": "Habilita sugerencias rápidas en los comentarios.", "quickSuggestions.other": "Habilita sugerencias rápidas fuera de las cadenas y los comentarios.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Controla si el editor debe resaltar los símbolos semánticos.", "overviewRulerLanes": "Controla el número de decoraciones que pueden aparecer en la misma posición en la regla de visión general", "overviewRulerBorder": "Controla si debe dibujarse un borde alrededor de la regla de información general.", - "cursorBlinking": "Controlar el estilo de animación del cursor. Los valores posibles son \"blink\", \"smooth\", \"phase\", \"expand\" y \"solid\".", + "cursorBlinking": "Controlar el estilo de animación del cursor.", "mouseWheelZoom": "Ampliar la fuente del editor cuando se use la rueda del mouse mientras se presiona Ctrl", "cursorStyle": "Controla el estilo del cursor. Los valores aceptados son \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" y \"underline-thin\"", "cursorWidth": "Controla el ancho del cursor cuando editor.cursorStyle se establece a 'line'", @@ -86,8 +87,11 @@ "renderControlCharacters": "Controla si el editor debe representar caracteres de control", "renderIndentGuides": "Controla si el editor debe representar guías de sangría.", "renderLineHighlight": "Controla cómo el editor debe presentar el resaltado de línea. Las posibilidades son \"ninguno\", \"margen\", \"línea\" y \"todo\".", - "codeLens": "Controla si el editor muestra lentes de código", + "codeLens": "Controla si el editor muestra CodeLens", "folding": "Controla si el editor tiene habilitado el plegado de código.", + "foldingStrategyAuto": "Si está disponible, utilice una estrategia de plegado específica del idioma, de lo contrario volverá a la estrategia basada en sangría.", + "foldingStrategyIndentation": "Utilice siempre la estrategia de plegado basado en sangría.", + "foldingStrategy": "Controla la forma en que se calculan las gamas plegables. Las selecciones ' auto' utilizan una estrategia de plegado específica del idioma, si está disponible. 'Sangría' obliga a utilizar la estrategia de plegado con sangría.", "showFoldingControls": "Controla cuándo los controles de plegado del margen son ocultados automáticamente.", "matchBrackets": "Resaltar corchetes coincidentes cuando se seleccione uno de ellos.", "glyphMargin": "Controla si el editor debe representar el margen de glifo vertical. El margen de glifo se usa, principalmente, para depuración.", @@ -102,8 +106,12 @@ "links": "Controla si el editor debe detectar enlaces y hacerlos cliqueables", "colorDecorators": "Controla si el editor debe representar el Selector de colores y los elementos Decorator de color en línea.", "codeActions": "Permite que el foco de acción del código", + "codeActionsOnSave.organizeImports": "¿organizar importaciones en guardar?", + "codeActionsOnSave": "Tipos de acción de código que se ejecutarán en guardar.", + "codeActionsOnSaveTimeout": "Tiempo de espera para ejecutar acciones de código en guardar.", "selectionClipboard": "Controla si el portapapeles principal de Linux debe admitirse.", "sideBySide": "Controla si el editor de diferencias muestra las diferencias en paralelo o alineadas.", "ignoreTrimWhitespace": "Controla si el editor de diferencias muestra los cambios de espacio inicial o espacio final como diferencias.", + "largeFileOptimizations": "Manejo especial para archivos grandes para desactivar ciertas funciones de memoria intensiva.", "renderIndicators": "Controla si el editor de diff muestra indicadores +/- para cambios agregados/quitados" } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json index 08c91f17c5..5a2a61ef9c 100644 --- a/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,16 +6,18 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "lineHighlight": "Color de fondo del resaltado de línea en la posición del cursor.", + "lineHighlight": "Color de fondo para la línea resaltada en la posición del cursor.", "lineHighlightBorderBox": "Color de fondo del borde alrededor de la línea en la posición del cursor.", "rangeHighlight": "Color de fondo de los rangos resaltados, como por ejemplo las características de abrir rápidamente y encontrar. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "rangeHighlightBorder": "Color de fondo del borde alrededor de los intervalos resaltados.", "caret": "Color del cursor del editor.", - "editorCursorBackground": "Color de fondo del cursor de edición. Permite personalizar el color del carácter solapado por el bloque del cursor.", + "editorCursorBackground": "Color de fondo del cursor de edición. Permite personalizar el color del caracter solapado por el bloque del cursor.", "editorWhitespaces": "Color de los caracteres de espacio en blanco del editor.", "editorIndentGuides": "Color de las guías de sangría del editor.", + "editorActiveIndentGuide": "Color de las guías de sangría activas del editor.", "editorLineNumbers": "Color de números de línea del editor.", "editorActiveLineNumber": "Color del número de línea activa en el editor", + "deprecatedEditorActiveLineNumber": "ID es obsoleto. Usar en lugar 'editorLineNumber.activeForeground'. ", "editorRuler": "Color de las reglas del editor", "editorCodeLensForeground": "Color principal de lentes de código en el editor", "editorBracketMatchBackground": "Color de fondo tras corchetes coincidentes", @@ -28,7 +30,9 @@ "warningBorder": "Color de borde de squigglies de advertencia en el editor.", "infoForeground": "Color de primer plano de los subrayados ondulados informativos en el editor.", "infoBorder": "Color del borde de los subrayados ondulados informativos en el editor.", - "overviewRulerRangeHighlight": "Color de marcador de regla de información general para intervalos resaltados.", + "hintForeground": "Color de primer plano de pista squigglies en el editor.", + "hintBorder": "Color de borde de pista squigglies en el editor.", + "overviewRulerRangeHighlight": "Resumen de color de marcador para destacar rangos. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "overviewRuleError": "Color de marcador de regla de información general para errores. ", "overviewRuleWarning": "Color de marcador de regla de información general para advertencias.", "overviewRuleInfo": "Color de marcador de regla de información general para mensajes informativos. " diff --git a/i18n/esn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/esn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..121ba9263c --- /dev/null +++ b/i18n/esn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Mostrar correcciones ({0})", + "quickFix": "Mostrar correcciones", + "quickfix.trigger.label": "Solución rápida...", + "editor.action.quickFix.noneMessage": "No hay acciones de código disponibles", + "refactor.label": "Refactorizar...", + "editor.action.refactor.noneMessage": "No hay refactorizaciones disponibles", + "source.label": "Acción de la fuente...", + "editor.action.source.noneMessage": "No hay acciones de fuente disponibles", + "organizeImports.label": "Organizar Importaciones", + "editor.action.organize.noneMessage": "No hay acciones de importación disponibles" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/find/findController.i18n.json b/i18n/esn/src/vs/editor/contrib/find/findController.i18n.json index 082b6bed1a..f9ecd05224 100644 --- a/i18n/esn/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Buscar", + "startFindWithSelectionAction": "Buscar con selección", "findNextMatchAction": "Buscar siguiente", "findPreviousMatchAction": "Buscar anterior", "nextSelectionMatchFindAction": "Buscar selección siguiente", diff --git a/i18n/esn/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/esn/src/vs/editor/contrib/format/formatActions.i18n.json index 9b59d27899..549329852a 100644 --- a/i18n/esn/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "{0} ediciones de formato entre las líneas {1} y {2}", "no.provider": "No hay formateador para los archivos ' {0} ' instalados.", "formatDocument.label": "Dar formato al documento", - "formatSelection.label": "Dar formato a la selección" + "no.documentprovider": "No hay formateador de documentos para los archivos ' {0} ' instalados.", + "formatSelection.label": "Dar formato a la selección", + "no.selectionprovider": "No hay formateador de selección para los archivos ' {0} ' instalados." } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json index efc4df06ef..807eba3205 100644 --- a/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Ir al siguiente problema (Error, Advertencia, Información)", - "markerAction.previous.label": "Ir al problema anterior (Error, Advertencia, Información)", - "editorMarkerNavigationError": "Color de los errores del widget de navegación de marcadores del editor.", - "editorMarkerNavigationWarning": "Color de las advertencias del widget de navegación de marcadores del editor.", - "editorMarkerNavigationInfo": "Color del widget informativo marcador de navegación en el editor.", - "editorMarkerNavigationBackground": "Fondo del widget de navegación de marcadores del editor." + "markerAction.previous.label": "Ir al problema anterior (Error, Advertencia, Información)" } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/esn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..862620a88d --- /dev/null +++ b/i18n/esn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Color de los errores del widget de navegación de marcadores del editor.", + "editorMarkerNavigationWarning": "Color de las advertencias del widget de navegación de marcadores del editor.", + "editorMarkerNavigationInfo": "Color del widget informativo marcador de navegación en el editor.", + "editorMarkerNavigationBackground": "Fondo del widget de navegación de marcadores del editor." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/links/links.i18n.json b/i18n/esn/src/vs/editor/contrib/links/links.i18n.json index 7b3be6d4fa..52780dc765 100644 --- a/i18n/esn/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "Ctrl + clic para abrir el vínculo", "links.command.mac": "Cmd + click para ejecutar el comando", "links.command": "Ctrl + click para ejecutar el comando", + "links.navigate.al.mac": "Opción + clic para seguir el enlace", "links.navigate.al": "Alt + clic para seguir el vínculo", + "links.command.al.mac": "Opción + click para ejecutar el comando", "links.command.al": "Alt + clic para ejecutar el comando", "invalid.url": "No se pudo abrir este vínculo porque no tiene un formato correcto: {0}", "missing.url": "No se pudo abrir este vínculo porque falta el destino.", diff --git a/i18n/esn/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/esn/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..bc97e24608 --- /dev/null +++ b/i18n/esn/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "No se puede editar en editor de sólo lectura" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/esn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 50d1e27f74..9487af5841 100644 --- a/i18n/esn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Color de fondo del editor de vista de inspección.", "peekViewEditorGutterBackground": "Color de fondo del margen en el editor de vista de inspección.", "peekViewResultsMatchHighlight": "Buscar coincidencia con el color de resaltado de la lista de resultados de vista de inspección.", - "peekViewEditorMatchHighlight": "Buscar coincidencia del color de resultado del editor de vista de inspección." + "peekViewEditorMatchHighlight": "Buscar coincidencia del color de resultado del editor de vista de inspección.", + "peekViewEditorMatchHighlightBorder": "Hacer coincidir el borde resaltado en el editor de vista previa." } \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/esn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..22631072b4 --- /dev/null +++ b/i18n/esn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Domingo", + "Monday": "Lunes", + "Tuesday": "Martes", + "Wednesday": "Miércoles", + "Thursday": "Jueves", + "Friday": "Viernes", + "Saturday": "Sábado", + "SundayShort": "Dom", + "MondayShort": "Lun", + "TuesdayShort": "Mar", + "WednesdayShort": "Mié", + "ThursdayShort": "Jue", + "FridayShort": "Vie", + "SaturdayShort": "Sáb", + "January": "Enero", + "February": "Febrero", + "March": "Marzo", + "April": "Abril", + "May": "Mayo", + "June": "Junio", + "July": "Julio", + "August": "Agosto", + "September": "Septiembre", + "October": "Octubre", + "November": "Noviembre", + "December": "Diciembre", + "JanuaryShort": "Ene", + "FebruaryShort": "Feb", + "MarchShort": "Mar", + "AprilShort": "Abr", + "MayShort": "May", + "JuneShort": "Jun", + "JulyShort": "Jul", + "AugustShort": "Ago", + "SeptemberShort": "Sep", + "OctoberShort": "Oct", + "NovemberShort": "Noviembre", + "DecemberShort": "Dic" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 092859b090..38cc9535f4 100644 --- a/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Color de fondo de un símbolo durante el acceso de escritura, como escribir en una variable. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "wordHighlightBorder": "Color de fondo de un símbolo durante el acceso de lectura; por ejemplo, cuando se lee una variable.", "wordHighlightStrongBorder": "Color de fondo de un símbolo durante el acceso de escritura; por ejemplo, cuando se escribe una variable.", - "overviewRulerWordHighlightForeground": "Color de marcador de regla de información general para símbolos resaltados.", - "overviewRulerWordHighlightStrongForeground": "Color de marcador de regla de información general para símbolos de acceso de escritura resaltados. ", + "overviewRulerWordHighlightForeground": "Destaca el color del marcador para los puntos del símbolo. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "overviewRulerWordHighlightStrongForeground": "Destaca el color del marcador de acceso de escritura. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "wordHighlight.next.label": "Ir al siguiente símbolo destacado", "wordHighlight.previous.label": "Ir al símbolo destacado anterior" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/esn/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..cf1d1d7ad8 --- /dev/null +++ b/i18n/esn/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 archivo más que no se muestra", + "moreFiles": "...{0} archivos más que no se muestran" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/esn/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..4a277edc56 --- /dev/null +++ b/i18n/esn/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Cancelar" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/environment/node/argv.i18n.json b/i18n/esn/src/vs/platform/environment/node/argv.i18n.json index 96e69abf87..a6b10a3edb 100644 --- a/i18n/esn/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/esn/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "Muestra las versiones de las extensiones instaladas cuando se usa --list-extension.", "installExtension": "Instala una extensión.", "uninstallExtension": "Desinstala una extensión.", - "experimentalApis": "Habilita características de API propuestas para una extensión.", + "experimentalApis": "Permite las funciones de API propuestas para una extensión.", "verbose": "Imprima salidas detalladas (implica --wait).", "log": "Nivel de registro a utilizar. Por defecto es 'info'. Los valores permitidos son 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Imprimir el uso del proceso y la información de diagnóstico.", "performance": "Comience con el comando 'Developer: Startup Performance' habilitado.", "prof-startup": "Ejecutar generador de perfiles de CPU durante el inicio", "disableExtensions": "Deshabilite todas las extensiones instaladas.", - "inspect-extensions": "Permitir la depuración y el perfil de las extensiones. Revisar las herramientas de desarrollador para la conexión uri.", - "inspect-brk-extensions": "Permitir la depuración y el perfil de las extensiones con el host de la extensión pausado después del inicio. Revisar las herramientas de desarrollador para la conexión uri.", + "inspect-extensions": "Permite perfilar y depurar las extensiones. Revise las herramientas de desarrollador para la conexión URI.", + "inspect-brk-extensions": "Permite perfilar y depurar las extensiones con el host de la extensión pausado después de iniciar. Revise las herramientas de desarrollador para la conexión URI. ", "disableGPU": "Deshabilita la aceleración de hardware de GPU.", "uploadLogs": "Carga los registros de la sesión actual a un extremo.", "maxMemory": "Tamaño máximo de memoria para una ventana (en Mbytes).", diff --git a/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 44c945ef6a..5e55b7d238 100644 --- a/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Extensión no válida: package.json no es un archivo JSON.", + "incompatible": "No se puede instalar la extensión ' {0} ', ya que no es compatible con el código ' {1} '.", "restartCode": "Reinicie Code antes de volver a instalar {0}.", "installingOutdatedExtension": "Una versión más nueva de esta extensión ya está instalada. ¿Desea anular esto con la versión anterior?", "override": "Anular", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Error instalando dependencias. {0}", "MarketPlaceDisabled": "Marketplace no está habilitado", "removeError": "Error al quitar la extensión: {0}. Salga e inicie VS Code antes de intentarlo de nuevo.", - "Not Market place extension": "Solo se pueden reinstalar las extensiones de Marketplace", + "Not a Marketplace extension": "Sólo se pueden reinstalar Extensiones del Marketplace", "notFoundCompatible": "No se pueden instalar '{0}'; no hay ninguna versión disponible compatible con VS Code '{1}'. ", "malicious extension": "No se puede instalar la extensión ya que se informó que era problemático.", "notFoundCompatibleDependency": "No se puede instalar porque no se encuentra la extensión dependiente '{0}' compatible con la versión actual '{1}' del VS Code.", "quitCode": "No se puede instalar la extensión. Por favor, salga e inicie VS Code antes de reinstalarlo. ", "exitCode": "No se puede instalar la extensión. Por favor, salga e inicie VS Code antes de reinstalarlo. ", + "renameError": "Error desconocido al cambiar el nombre de {0} a {1}", "uninstallDependeciesConfirmation": "¿Quiere desinstalar solo '{0}' o también sus dependencias?", - "uninstallOnly": "Solo", - "uninstallAll": "Todo", + "uninstallOnly": "Sólo extensión", + "uninstallAll": "Desinstalar todo", "uninstallConfirmation": "¿Seguro que quiere desinstalar '{0}'?", "ok": "Aceptar", "singleDependentError": "No se puede desinstalar la extensión '{0}'. La extensión '{1}' depende de esta.", diff --git a/i18n/esn/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/esn/src/vs/platform/extensions/node/extensionValidator.i18n.json index 0f4be6cef1..7ca8580245 100644 --- a/i18n/esn/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/esn/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "No se pudo analizar el valor {0} de \"engines.vscode\". Por ejemplo, use: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x, etc.", + "versionSyntax": "No se pudo analizar el valor de ' engines.vscode ' {0}. Utilice, por ejemplo: ^ 1.22.0, ^ 1.22. x, etc.", "versionSpecificity1": "La versión indicada en \"engines.vscode\" ({0}) no es suficientemente específica. Para las versiones de vscode anteriores a la 1.0.0, defina como mínimo la versión principal y secundaria deseadas. Por ejemplo: ^0.10.0, 0.10.x, 0.11.0, etc.", "versionSpecificity2": "La versión indicada en \"engines.vscode\" ({0}) no es suficientemente específica. Para las versiones de vscode posteriores a la 1.0.0, defina como mínimo la versión principal deseada. Por ejemplo: ^1.10.0, 1.10.x, 1.x.x, 2.x.x, etc.", "versionMismatch": "La extensión no es compatible con {0} de Code y requiere: {1}." diff --git a/i18n/esn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/esn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 9e28db4a2e..5b34fd81a5 100644 --- a/i18n/esn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/esn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "La instalación de {0} parece estar dañada. Vuelva a instalar.", "integrity.moreInformation": "Más información", - "integrity.dontShowAgain": "No volver a mostrar", - "integrity.prompt": "La instalación de {0} parece estar dañada. Vuelva a instalar." + "integrity.dontShowAgain": "No volver a mostrar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/esn/src/vs/platform/issue/electron-main/issueService.i18n.json index 821afa8fd9..ba1f2ff8be 100644 --- a/i18n/esn/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/esn/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Reportero de tema" + "issueReporter": "Reportero de tema", + "processExplorer": "Process Explorer" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/list/browser/listService.i18n.json b/i18n/esn/src/vs/platform/list/browser/listService.i18n.json index c428698217..710a65032e 100644 --- a/i18n/esn/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/esn/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "El modificador que se usará para agregar un elemento en árboles y listas a una selección múltiple con el mouse (por ejemplo en el explorador, los editores abiertos y la vista SCM). ' ctrlCmd ' se asigna a ' control ' en Windows y Linux y a ' Command ' en macOS. Los gestos de ratón \"abrir a lado\", si se admiten, se adaptarán de tal manera que no estén en conflicto con el modificador multiselección.", "openMode.singleClick": "Abre elementos en solo clic de ratón.", "openMode.doubleClick": "Abre elementos en doble clic del ratón. ", - "openModeModifier": "Controla cómo abrir elementos en árboles y listas con el ratón (si está soportado). Establecer en ' singleClick ' para abrir elementos con un solo clic del ratón y ' DoubleClick ' para abrir sólo a través del doble clic del ratón. Para los elementos padres con hijos en los árboles, este ajuste controlará si un solo clic expande el padre o un doble clic. Tenga en cuenta que algunos árboles y listas pueden optar por ignorar esta configuración si no es aplicable" + "openModeModifier": "Controla cómo abrir elementos en árboles y listas con el ratón (si está soportado). Establecer en ' singleClick ' para abrir elementos con un solo clic del ratón y ' DoubleClick ' para abrir sólo a través del doble clic del ratón. Para los elementos padres con hijos en los árboles, este ajuste controlará si un solo clic expande el padre o un doble clic. Tenga en cuenta que algunos árboles y listas pueden optar por ignorar esta configuración si no es aplicable", + "horizontalScrolling setting": "Controla el esplazamiento horizontal de los árboles en la mesa de trabajo." } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/markers/common/markers.i18n.json b/i18n/esn/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..2229fecdaf --- /dev/null +++ b/i18n/esn/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Error", + "sev.warning": "Advertencia", + "sev.info": "Información" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json index 2dcc09e6a5..0c443073b8 100644 --- a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "Color de primer plano para el marcador de posición de texto", "inputValidationInfoBackground": "Color de fondo de validación de entrada para gravedad de información.", "inputValidationInfoBorder": "Color de borde de validación de entrada para gravedad de información.", - "inputValidationWarningBackground": "Color de fondo de validación de entrada para advertencia de información.", + "inputValidationWarningBackground": "Color de fondo de validación de entrada para gravedad de advertencia.", "inputValidationWarningBorder": "Color de borde de validación de entrada para gravedad de advertencia.", "inputValidationErrorBackground": "Color de fondo de validación de entrada para gravedad de error.", "inputValidationErrorBorder": "Color de borde de valdación de entrada para gravedad de error.", @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "Color de borde de las regiones con el mismo contenido que la selección.", "editorFindMatch": "Color de la coincidencia de búsqueda actual.", "findMatchHighlight": "Color de las otras coincidencias de búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", - "findRangeHighlight": "Colorea el rango limitando la búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "findRangeHighlight": "Color de la gama que limita la búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "editorFindMatchBorder": "Color de borde de la coincidencia de búsqueda actual.", "findMatchHighlightBorder": "Color de borde de otra búsqueda que coincide.", - "findRangeHighlightBorder": "Color de borde del rango limitando a la búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "findRangeHighlightBorder": "Color de borde de la gama que limita la búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "hoverHighlight": "Resalte debajo de la palabra para la cual se muestra un Hover. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "hoverBackground": "Color de fondo al mantener el puntero en el editor.", "hoverBorder": "Color del borde al mantener el puntero en el editor.", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "Fondo de encabezado entrante en conflictos de fusión en línea. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "mergeIncomingContentBackground": "Fondo de contenido entrante en conflictos de fusión en línea. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "mergeCommonHeaderBackground": "Fondo de encabezado de ancestro común en conflictos de fusión en línea. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", - "mergeCommonContentBackground": "Fondo de contenido de ancester común en conflictos de fusión en línea. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "mergeCommonContentBackground": "Fondo de contenido común de ancestro en conflictos de fusión en línea. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "mergeBorder": "Color del borde en los encabezados y el divisor en conflictos de combinación alineados.", "overviewRulerCurrentContentForeground": "Primer plano de la regla de visión general actual para conflictos de combinación alineados.", "overviewRulerIncomingContentForeground": "Primer plano de regla de visión general de entrada para conflictos de combinación alineados.", "overviewRulerCommonContentForeground": "Primer plano de la regla de visión general de ancestros comunes para conflictos de combinación alineados.", - "overviewRulerFindMatchForeground": "Color de marcador de regla de información general para coincidencias encontradas.", - "overviewRulerSelectionHighlightForeground": "Color de marcador de regla de información general para elementos seleccionados resaltados." + "overviewRulerFindMatchForeground": "Destaca el color del marcador de regla para las coincidencias de búsqueda. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "overviewRulerSelectionHighlightForeground": "Destaca el color del marcador de regla para los puntos de selección . El color no debe ser opaco para no ocultar las decoraciones subyacentes." } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/esn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..635a825e0a --- /dev/null +++ b/i18n/esn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "¿desea que la extensión {0} abra la siguiente URL?" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/esn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..90efea7a4b --- /dev/null +++ b/i18n/esn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "Identificador único utilizado para identificar el contenedor en el que se pueden aportar vistas mediante el punto de contribución \"vistas\"", + "vscode.extension.contributes.views.containers.title": "Cadena de texto en lenguaje natural usada para mostrar el contenedor. ", + "vscode.extension.contributes.views.containers.icon": "Ruta para el icono del contenedor. Los iconos son de 24x24 centrados en un cuadrado 50x40 y tienen un color de relleno de ' RGB (215, 218, 224) ' o ' #d7dae0 '. Se recomienda que los iconos estén en SVG, aunque se acepte cualquier tipo de archivo de imagen.", + "vscode.extension.contributes.viewsContainers": "Contribuye con vistas de contenedores al editor ", + "views.container.activitybar": "Contribuir vistas de contenedores a la barra de actividades", + "test": "Prueba", + "proposed": "la contribución ' viewsContainers ' sólo está disponible cuando se está ejecutando fuera de desarrollo con el siguiente modificador de línea de comandos: --enable-proposed-API {0}", + "requirearray": "contenedores de vistas deben ser una matriz", + "requireidstring": "la propiedad ' {0} ' es obligatoria y debe ser de tipo 'String'. Sólo se permiten letras alfanuméricas, ' _ ', '-'.", + "requirestring": "la propiedad `{0}` es obligatoria y debe ser de tipo \"string\"", + "showViewlet": "Mostrar {0}", + "view": "Ver" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/esn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index 428f30f245..930cf1f88b 100644 --- a/i18n/esn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/esn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -6,16 +6,19 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "requirearray": "views debe ser una mariz", + "requirearray": "Las vistas deben ser una matriz", "requirestring": "la propiedad `{0}` es obligatoria y debe ser de tipo \"string\"", "optstring": "la propiedad `{0}` se puede omitir o debe ser de tipo \"string\"", "vscode.extension.contributes.view.id": "Identificador de la vista. Úselo para registrar un proveedor de datos mediante la API \"vscode.window.registerTreeDataProviderForView\". También para desencadenar la activación de su extensión al registrar el evento \"onView:${id}\" en \"activationEvents\".", "vscode.extension.contributes.view.name": "Nombre de la vista en lenguaje natural. Será mostrado", "vscode.extension.contributes.view.when": "Condición que se debe cumplir para mostrar esta vista", "vscode.extension.contributes.views": "Aporta vistas al editor", - "views.explorer": "Vista del explorador", - "views.debug": "Vista de depuración", - "locationId.invalid": "`{0}` no es una ubicación de vista válida", + "views.explorer": "Aporta vistas al contenedor del explorador en la barra de actividades", + "views.debug": "Contribuye vistas al contenedor de depuración en la barra de actividades", + "views.scm": "Contribuye vistas al contenedor SCM en la barra de actividades", + "views.test": "Contribuye vistas al contenedor de pruebas en la barra de actividades", + "views.contributed": "Contribuye vistas al contenedor de vistas aportadas", + "ViewContainerDoesnotExist": "Contenedor de vistas ' {0} ' no existe y todas las vistas registradas se agregarán al 'Explorer'.", "duplicateView1": "No se pueden registrar múltiples vistas con el mismo identificador '{0}' en la ubicación '{1}'", "duplicateView2": "Una vista con el identificador '{0}' ya está registrada en la ubicación '{1}'" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index b30c3bee20..83011ff124 100644 --- a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Anular la aplicación de formato al guardar después de {0} ms", + "codeActionsOnSave.didTimeout": "codeActionsOnSave anulado después de {0} ms", + "timeout.onWillSave": "Se anuló onWillSaveTextDocument-event después de 1750 ms", "saveParticipants": "Ejecutando Guardar Participantes..." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index fee19de6b3..c697497936 100644 --- a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "Editor de vistas web" + "errorMessage": "Ha ocurrido un error mientras se restauraba la vista: {0}" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/esn/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..651918c67b --- /dev/null +++ b/i18n/esn/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (extensión)" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index b58870af01..84ba579e9f 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Enfocar el grupo siguiente", "openToSide": "Abrir en el lateral", "closeEditor": "Cerrar editor", + "closeOneEditor": "Cerrar", "revertAndCloseActiveEditor": "Revertir y cerrar el editor", "closeEditorsToTheLeft": "Cerrar los editores a la izquierda", "closeAllEditors": "Cerrar todos los editores", diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 58606f94d4..19342472fc 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Si no va a usar un lector de pantalla, cambie el valor de configuración \"editor.accessibilitySupport\" a \"desactivado\".", "disableTabMode": "Deshabilitar modo de accesibilidad", "gotoLine": "Ir a la línea", - "indentation": "Sangría", + "selectIndentation": "Seleccione la sangría", "selectEncoding": "Seleccionar Encoding", "selectEOL": "Seleccionar secuencia de fin de línea", "selectLanguageMode": "Seleccionar modo de lenguaje", diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index ff59ea4cb6..40e0fd6c64 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} MB", "sizeGB": "{0} GB", "sizeTB": "{0} TB", - "largeImageError": "El tamaño del archivo de la imagen es demasiado grande (> 1MB) para mostrarlo en el editor.", + "largeImageError": "La imagen no se muestra en el editor porque es demasiado grande ({0}). ", "resourceOpenExternalButton": "¿Abrir la imagen mediante un programa externo?", - "nativeBinaryError": "El archivo no se mostrará en el editor porque es binario, muy grande o usa una codificación de texto no compatible.", + "nativeFileTooLargeError": "El archivo no se muestra en el editor porque es demasiado grande ({0}). ", + "nativeBinaryError": "El archivo no se muestra en el editor porque es binario o utiliza una codificación de texto no soportada. ", + "openAsText": "¿Desea abrirlo de todas formas?", "zoom.action.fit.label": "Imagen completa", "imgMeta": "{0} x {1} {2}" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index a3df8c0d9d..ef4a8b2955 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Cerrar", "araLabelEditorActions": "Acciones del editor" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 93a44d6882..94aeba068e 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "No hay notificaciones nuevas", "notifications": "Notificaciones", "notificationsToolbar": "Acciones del centro de notificaciones", "notificationsList": "Lista de notificaciones" diff --git a/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..8a0f29393f --- /dev/null +++ b/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Presione \"Entrar\" para confirmar o \"Esc\" para cancelar)", + "inputModeEntry": "Presione \"Entrar\" para confirmar su entrada o \"Esc\" para cancelar", + "quickInput.countSelected": "{0} seleccionadas", + "ok": "Aceptar" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..c9120e6b4e --- /dev/null +++ b/i18n/esn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Escriba para restringir los resultados." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json index bb5e10e05a..b40547dd8b 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Abrir Reciente...", "quickOpenRecent": "Abrir Reciente Rapidamente...", "reportIssueInEnglish": "Notificar problema", + "openProcessExplorer": "Abrir Explorador de Procesos", "reportPerformanceIssue": "Notificar problema de rendimiento", "keybindingsReference": "Referencia de métodos abreviados de teclado", "openDocumentationUrl": "Documentación", diff --git a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json index 7c6134ea8a..7d0df8969b 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Ventana", "window.openFilesInNewWindow.on": "Los archivos se abrirán en una nueva ventana", "window.openFilesInNewWindow.off": "Los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa", - "window.openFilesInNewWindow.default": "Los archivos se abrirán en la ventana con la carpeta de los archivos abierta o en la última ventana activa a menos que se abran mediante el Dock o el Finder (solo macOS)", - "openFilesInNewWindow": "Controla si los archivos deben abrirse en una ventana nueva.\n- default: los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa, a menos que se abran mediante el Dock o desde el Finder (solo macOS)\n- on: los archivos se abrirán en una ventana nueva\n- off: los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa\nTenga en cuenta que aún puede haber casos en los que este parámetro se ignore (por ejemplo, al usar la opción de la línea de comandos -new-window o -reuse-window).", + "window.openFilesInNewWindow.defaultMac": "Los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa, a menos que se abran con Dock o desde Finder.", + "window.openFilesInNewWindow.default": "Los archivos se abrirán en una nueva ventana hasta que sean llamados dentro de la aplicación (ej.: via menú Archivo)", + "openFilesInNewWindowMac": "Controla si los archivos deben abrirse en una ventana nueva.\n- default: los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa, a menos que se abran con Dock o desde Finder.\n- on: los archivos se abrirán en una ventana nueva.\n- off: los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa.\nTenga en cuenta que puede haber casos en los que se omita esta configuración (por ejemplo, cuando se utilizan las opciones de la línea de comandos -new-window o -reuse-window). ", + "openFilesInNewWindow": "Controla si los archivos deben abrirse en una ventana nueva.\n- default: los archivos se abrirán en una ventana nueva a menos que se seleccionen desde la aplicación (por ejemplo, desde el menú Archivo).\n- on: los archivos se abrirán en una ventana nueva.\n- off: los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa.\nTenga en cuenta que puede haber casos en los que se omita esta configuración (por ejemplo, cuando se utilizan las opciones de la línea de comandos -new-window o -reuse-window).", "window.openFoldersInNewWindow.on": "Las carpetas se abrirán en una nueva ventana", "window.openFoldersInNewWindow.off": "Las carpetas reemplazarán la ventana activa más reciente", "window.openFoldersInNewWindow.default": "Las carpetas se abrirán en una nueva ventana a menos que se seleccione una carpeta desde la aplicación (p. ej. mediante el menú Archivo)", "openFoldersInNewWindow": "Controla si las carpetas deben abrirse en una ventana nueva o reemplazar la última ventana activa.\n- default: las carpetas se abrirán en una ventana nueva, a menos que se seleccione una carpeta desde la aplicación (por ejemplo, desde el menú Archivo)\n- on: las carpetas se abrirán en una ventana nueva\n- off: las carpetas reemplazarán la última ventana activa\nTenga en cuenta que aún puede haber casos en los que este parámetro se ignore (por ejemplo, al usar la opción de la línea de comandos -new-window o -reuse-window).", + "window.openWithoutArgumentsInNewWindow.on": "Abrir una nueva ventana vacía", + "window.openWithoutArgumentsInNewWindow.off": "Aplicar el foco a la última instancia en ejecución activa", + "openWithoutArgumentsInNewWindow": "Controla si debe abrirse una ventana nueva vacía cuando se inicia una segunda instancia sin argumentos o si la última instancia en ejecución debe obtener el foco.\n- on: se abre una ventana nueva vacía.\n- off: la última instancia en ejecución activa obtiene el foco.\nTenga en cuenta que puede haber casos en los que se omita esta configuración (por ejemplo, cuando se utilizan las opciones de la línea de comandos -new-window o -reuse-window).", "window.reopenFolders.all": "Reabrir todas las ventanas.", "window.reopenFolders.folders": "Reabrir todas las carpetas. Las áreas de trabajo vacías no se restaurarán.", "window.reopenFolders.one": "Reabrir la última ventana activa.", @@ -58,7 +63,7 @@ "restoreWindows": "Controla cómo se vuelven a abrir las ventanas tras un reinicio. Seleccione \"none\" para comenzar siempre con un área de trabajo vacía, \"one\" para volver a abrir la última ventana en la que trabajó, \"folders\" para volver a abrir todas las ventanas que tenían carpetas abiertas o \"all\" para volver a abrir todas las ventanas de la última sesión.", "restoreFullscreen": "Controla si una ventana se debe restaurar al modo de pantalla completa si se salió de ella en dicho modo.", "zoomLevel": "Ajuste el nivel de zoom de la ventana. El tamaño original es 0 y cada incremento (por ejemplo, 1) o disminución (por ejemplo, -1) representa una aplicación de zoom un 20 % más grande o más pequeño. También puede especificar decimales para ajustar el nivel de zoom con una granularidad más precisa.", - "title": "Controla el título de ventana basado en el editor activo. Las variables se sustituyen según el contexto: ${activeEditorShort}: el archivo nombre (e.g. miarchivo.txt) ${activeEditorMedium}: la ruta del archivo en relación con el área de trabajo carpeta (por ejemplo, myFolder/myFile.txt) ${activeEditorLong}: la ruta de acceso completa del archivo (p. ej. / Users/Development/myProject/myFolder/myFile.txt) ${nombre de carpeta}: nombre de la carpeta el archivo del espacio de trabajo está contenida en (e.g. myFolder) ${folderPath}: ruta del archivo de la carpeta el archivo del espacio de trabajo está contenida en (por ejemplo, /Users/Development/myFolder) {} $ rootName}: nombre de la área de trabajo (por ejemplo myFolder o myWorkspace) ${Ruta_raíz}: ruta del archivo del espacio de trabajo (por ejemplo, /Users/Development/myWorkspace) ${appName}: por ejemplo VS código ${sucio}: un indicador sucio si el editor activo es sucio ${separador}: condicional separador (\"-\") que sólo muestra cuando rodeada de variables con valores", + "title": "Controla el título de la ventana en función del editor activo. Las variables se reemplazan según el contexto:\n${activeEditorShort}: nombre del archivo (por ejemplo, miArchivo.txt).\n${activeEditorMedium}: ruta de acceso del archivo relativa a la carpeta del área de trabajo (por ejemplo, miCarpeta/miArchivo.txt).\n${activeEditorLong}: ruta de acceso completa del archivo (por ejemplo, /Usuarios/Desarrollo/miProyecto/miCarpeta/miArchivo.txt).\n${folderName}: nombre de la carpeta del área de trabajo que contiene el archivo (por ejemplo, miCarpeta).\n${folderPath}: ruta de acceso de la carpeta del área de trabajo que contiene el archivo (por ejemplo, /Usuarios/Desarrollo/miCarpeta).\n${rootName}: nombre del área de trabajo (por ejemplo, miCarpeta o miÁreaDeTrabajo).\n${rootPath}: ruta de acceso del área de trabajo (por ejemplo, /Usuarios/Desarrollo/miÁreaDeTrabajo).\n${appName}: nombre de la aplicación (por ejemplo, VS Code).\n${dirty}: indicador de modificaciones si se han realizado cambios en el editor activo.\n${separator}: separador condicional (\" - \") que solo se muestra cuando está rodeado de variables con valores o texto estático.", "window.newWindowDimensions.default": "Abrir las nuevas ventanas en el centro de la pantalla.", "window.newWindowDimensions.inherit": "Abrir las nuevas ventanas con la misma dimensión que la última activa.", "window.newWindowDimensions.maximized": "Abrir las nuevas ventanas maximizadas.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Si está habilitado, se cambiará automáticamente al tema de contraste alto si Windows utiliza un tema de contraste alto, y al tema oscuro si cambia desde un tema de contraste alto de Windows.", "titleBarStyle": "Ajuste la apariencia de la barra de título de la ventana. Se debe realizar un reinicio completo para aplicar los cambios.", "window.nativeTabs": "Habilita las fichas de ventana en macOS Sierra. Note que los cambios requieren que reinicie el equipo y las fichas nativas deshabilitan cualquier estilo personalizado que haya configurado.", + "window.smoothScrollingWorkaround": "Habilite esta solución alternativa si el desplazamiento deja de ser homogéneo después de restaurar una ventana de VS Code minimizada. Esta es una solución para un problema (https://github.com/Microsoft/vscode/issues/13612) en el que el desplazamiento comienza a sufrir interrupciones en dispositivos con panel táctil de precisión, como los dispositivos Surface de Microsoft. Al habilitar esta solución alternativa, puede parpadear ligeramente la distribución después de restaurar la ventana minimizada, pero no afecta a nada más.", + "window.clickThroughInactive": "Si está habilitado, haciendo clic en una ventana inactiva, activará dicha ventana y disparará el elemento bajo el cursor del ratón si éste es clicable. Si está deshabilitado, haciendo clic en cualquier lugar en una ventana inactiva, solo activará la misma y será necesario un segundo clic en el elemento. ", "zenModeConfigurationTitle": "Modo zen", "zenMode.fullScreen": "Controla si activar el modo Zen pone también el trabajo en modo de pantalla completa.", "zenMode.centerLayout": "Controla si al encender el Modo Zen también se centra el diseño.", diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 2e06121375..e9308047b4 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Editar punto de interrupción...", + "logPoint": "Logpoint", + "breakpoint": "Punto de interrupción", + "editBreakpoint": "Editar {0}...", + "removeBreakpoint": "Quitar {0}", "functionBreakpointsNotSupported": "Este tipo de depuración no admite puntos de interrupción en funciones", "functionBreakpointPlaceholder": "Función donde interrumpir", "functionBreakPointInputAriaLabel": "Escribir punto de interrupción de función", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Punto de interrupción no comprobado", "functionBreakpointUnsupported": "Este tipo de depuración no admite puntos de interrupción en funciones", "breakpointDirtydHover": "Punto de interrupción no comprobado. El archivo se ha modificado, reinicie la sesión de depuración.", + "logBreakpointUnsupported": "Logpoints no son compatible con este tipo de depuración", "conditionalBreakpointUnsupported": "Este tipo de depuración no es compatible con los puntos de interrupción condicionales.", "hitBreakpointUnsupported": "Este tipo de depuración no admite el uso de puntos de interrupción condicionales" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 0cb89d8a6c..7489251a59 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Desconectar", "continueDebug": "Continuar", "pauseDebug": "Pausar", + "terminateThread": "Terminar hilo de ejecución", "restartFrame": "Reiniciar marco", "removeBreakpoint": "Quitar punto de interrupción", "removeAllBreakpoints": "Quitar todos los puntos de interrupción", - "enableBreakpoint": "Habilitar punto de interrupción", - "disableBreakpoint": "Deshabilitar punto de interrupción", "enableAllBreakpoints": "Habilitar todos los puntos de interrupción", "disableAllBreakpoints": "Deshabilitar todos los puntos de interrupción", "activateBreakpoints": "Activar puntos de interrupción", "deactivateBreakpoints": "Desactivar puntos de interrupción", "reapplyAllBreakpoints": "Volver a aplicar todos los puntos de interrupción", "addFunctionBreakpoint": "Agregar punto de interrupción de función", - "addConditionalBreakpoint": "Agregar punto de interrupción condicional...", - "editConditionalBreakpoint": "Editar punto de interrupción...", "setValue": "Establecer valor", "addWatchExpression": "Agregar expresión", "editWatchExpression": "Editar expresión", diff --git a/i18n/esn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index fd4a113b22..8ba86168ee 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Depuración: Alternar punto de interrupción", "conditionalBreakpointEditorAction": "Depuración: agregar punto de interrupción condicional...", + "logPointEditorAction": "Depuración: Añadir Logpoint...", "runToCursor": "Ejecutar hasta el cursor", "debugEvaluate": "Depuración: Evaluar", "debugAddToWatch": "Depuración: Agregar a inspección", diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..b238709d15 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "Mensaje para registrar cuando se alcanza el punto de interrupción. Las expresiones entre {} son interpoladas. 'Enter' para aceptar, 'esc' para cancelar. ", + "breakpointWidgetHitCountPlaceholder": "Interrumpir cuando se alcance el número de llamadas. Presione \"ENTRAR\" para aceptar o \"Esc\" para cancelar.", + "breakpointWidgetExpressionPlaceholder": "Interrumpir cuando la expresión se evalúa como true. Presione \"ENTRAR\" para aceptar o \"Esc\" para cancelar.", + "expression": "Expresión", + "hitCount": "Número de llamadas", + "logMessage": "Mensaje de registro" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 855c925bd9..d5d1fc1967 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Por favor utilice nombres de configuración exclusivos.", "app.launch.json.compound.folder": "Nombre de la carpeta en la que se encuentra el compuesto.", "app.launch.json.compounds.configurations": "Nombres de las configuraciones que se iniciarán como parte de este elemento compuesto.", - "debugNoType": "El valor \"type\" del adaptador de depuración no se puede omitir y debe ser de tipo \"string\".", + "debugNoType": "El 'tipo' de depurador no se puede omitir y debe ser de tipo 'cadena'. ", "selectDebug": "Seleccionar entorno", "DebugConfig.failed": "No se puede crear el archivo \"launch.json\" dentro de la carpeta \".vscode\" ({0}).", "workspace": "espacio de trabajo", diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 1db435ccde..877d792dbe 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Logpoint", + "breakpoint": "Punto de interrupción", + "removeBreakpoint": "Quitar {0}", + "editBreakpoint": "Editar {0}...", + "disableBreakpoint": "Desactivar {0}", + "enableBreakpoint": "Activar {0}", "removeBreakpoints": "Quitar puntos de interrupción", "removeBreakpointOnColumn": "Quitar punto de interrupción en la columna {0}", "removeLineBreakpoint": "Quitar punto de interrupción de línea", @@ -18,5 +24,13 @@ "enableBreakpoints": "Habilitar punto de interrupción en la columna {0}", "enableBreakpointOnLine": "Habilitar punto de interrupción de línea", "addBreakpoint": "Agregar punto de interrupción", + "addConditionalBreakpoint": "Agregar punto de interrupción condicional...", + "addLogPoint": "Añadir Logpoint...", + "breakpointHasCondition": "Este {0} tiene una {1} que se perderá al quitarla. Considere la posibilidad de desactivar el {0} en su lugar.", + "message": "mensaje", + "condition": "condición", + "removeLogPoint": "Quitar {0}", + "disableLogPoint": "Desactivar {0}", + "cancel": "Cancelar", "addConfiguration": "Agregar configuración..." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 9dde2c4648..049fe87ca3 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Mostrar errores", "noFolderWorkspaceDebugError": "El archivo activo no se puede depurar. Compruebe que se ha guardado en el disco y que tiene una extensión de depuración instalada para ese tipo de archivo.", "cancel": "Cancelar", - "DebugTaskNotFound": "No se encontró el elemento preLaunchTask '{0}'.", - "taskNotTracked": "No se puede realizar un seguimiento de la tarea preLaunchTask '{0}'." + "DebugTaskNotFound": "No se pudo encontrar la tarea '{0}'.", + "taskNotTracked": "La tarea '{0}' no puede rastrearse." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index 7485b61212..2c9ad5ef75 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Más información", - "unableToLaunchDebugAdapter": "No se puede iniciar el adaptador de depuración desde '{0}'.", - "unableToLaunchDebugAdapterNoArgs": "No se puede iniciar el adaptador de depuración.", - "stoppingDebugAdapter": "{0}. Deteniendo el adaptador de depuración.", "debugAdapterCrash": "El proceso de adaptación del depurador finalizó inesperadamente" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 9b41b80acf..e7ae6ed577 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "El ejecutable del adaptador de depuración \"{0}\" no existe.", "debugAdapterCannotDetermineExecutable": "No se puede determinar el ejecutable para el adaptador de depuración \"{0}\".", - "launch.config.comment1": "Utilizar IntelliSense para aprender acerca de los posibles atributos.", - "launch.config.comment2": "Mantenga el puntero para ver las descripciones de los existentes atributos ", - "launch.config.comment3": "Para más información, visite: {0}", - "debugType": "Tipo de configuración.", - "debugTypeNotRecognised": "Este tipo de depuración no se reconoce. Compruebe que tiene instalada la correspondiente extensión de depuración y que está habilitada.", - "node2NotSupported": "\"node2\" ya no se admite; use \"node\" en su lugar y establezca el atributo \"protocol\" en \"inspector\".", - "debugName": "Nombre de la configuración. Aparece en el menú desplegable de la configuración de inicio.", - "debugRequest": "Tipo de solicitud de la configuración. Puede ser \"launch\" o \"attach\".", - "debugServer": "Solo para el desarrollo de extensiones de depuración: si se especifica un puerto, VS Code intenta conectarse a un adaptador de depuración que se ejecuta en modo servidor", - "debugPrelaunchTask": "Tarea que se va a ejecutar antes de iniciarse la sesión de depuración.", - "debugWindowsConfiguration": "Atributos de configuración de inicio específicos de Windows.", - "debugOSXConfiguration": "Atributos de configuración de inicio específicos de OS X.", - "debugLinuxConfiguration": "Atributos de configuración de inicio específicos de Linux.", - "deprecatedVariables": "\"env.\", \"config.\" y \"command.\" están en desuso, utilice en su lugar \"env:\", \"config:\" y \"command:\"." + "unableToLaunchDebugAdapter": "No se puede iniciar el adaptador de depuración desde '{0}'.", + "unableToLaunchDebugAdapterNoArgs": "No se puede iniciar el adaptador de depuración." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..b916d2192f --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Utilizar IntelliSense para aprender acerca de los posibles atributos.", + "launch.config.comment2": "Mantenga el puntero para ver las descripciones de los existentes atributos ", + "launch.config.comment3": "Para más información, visite: {0}", + "debugType": "Tipo de configuración.", + "debugTypeNotRecognised": "Este tipo de depuración no se reconoce. Compruebe que tiene instalada la correspondiente extensión de depuración y que está habilitada.", + "node2NotSupported": "\"node2\" ya no se admite; use \"node\" en su lugar y establezca el atributo \"protocol\" en \"inspector\".", + "debugName": "Nombre de la configuración. Aparece en el menú desplegable de la configuración de inicio.", + "debugRequest": "Tipo de solicitud de la configuración. Puede ser \"launch\" o \"attach\".", + "debugServer": "Solo para el desarrollo de extensiones de depuración: si se especifica un puerto, VS Code intenta conectarse a un adaptador de depuración que se ejecuta en modo servidor", + "debugPrelaunchTask": "Tarea que se va a ejecutar antes de iniciarse la sesión de depuración.", + "debugPostDebugTask": "Tarea que se ejecutará después de terminar la sesión de depuración.", + "debugWindowsConfiguration": "Atributos de configuración de inicio específicos de Windows.", + "debugOSXConfiguration": "Atributos de configuración de inicio específicos de OS X.", + "debugLinuxConfiguration": "Atributos de configuración de inicio específicos de Linux.", + "deprecatedVariables": "\"env.\", \"config.\" y \"command.\" están en desuso, utilice en su lugar \"env:\", \"config:\" y \"command:\"." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..ec6803b438 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "Consola de VS Code", + "mac.terminal.script.failed": "No se pudo ejecutar el script '{0}'. Código de salida: {1}.", + "mac.terminal.type.not.supported": "No se admite '{0}'", + "press.any.key": "Presione cualquier tecla para continuar...", + "linux.term.failed": "Error de '{0}' con el código de salida {1}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 8953fecceb..0dc460a55f 100644 --- a/i18n/esn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Configurar extensiones recomendadas (Carpeta del área de trabajo)", "malicious tooltip": "Se informó de que esta extensión era problemática.", "malicious": "Malintencionado", + "disabled": "Deshabilitado", + "disabled globally": "Deshabilitado", + "disabled workspace": "Deshabilitado para esta área de trabajo", "disableAll": "Deshabilitar todas las extensiones instaladas", "disableAllWorkspace": "Deshabilitar todas las extensiones instaladas para esta área de trabajo", "enableAll": "Habilitar todas las extensiones", diff --git a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..b632b359f0 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Nombre de la extensión", + "extension id": "Identificador de la extensión", + "preview": "Vista Previa", + "builtin": "Integrada", + "publisher": "Nombre del editor", + "install count": "Número de instalaciones", + "rating": "Clasificación", + "repository": "Repositorio", + "license": "Licencia", + "details": "Detalles", + "contributions": "Contribuciones", + "changelog": "Registro de cambios", + "dependencies": "Dependencias", + "noReadme": "No hay ningún archivo LÉAME disponible.", + "noChangelog": "No hay ningún objeto CHANGELOG disponible.", + "noContributions": "No hay contribuciones.", + "noDependencies": "No hay dependencias.", + "settings": "Configuración ({0})", + "setting name": "Nombre", + "description": "Descripción", + "default": "Predeterminado", + "debuggers": "Depuradores ({0})", + "debugger name": "Nombre", + "debugger type": "Tipo", + "views": "Vistas ({0})", + "view id": "Id.", + "view name": "Nombre", + "view location": "Donde", + "localizations": "Localizaciones ({0}) ", + "localizations language id": "ID. de idioma", + "localizations language name": "Nombre de idioma", + "localizations localized language name": "Nombre de idioma (localizado)", + "colorThemes": "Temas de color ({0})", + "iconThemes": "Temas de icono ({0})", + "colors": "Colores ({0})", + "colorId": "Id", + "defaultDark": "Oscuro por defecto", + "defaultLight": "Claro por defecto", + "defaultHC": "Contraste alto por defecto", + "JSON Validation": "Validación JSON ({0})", + "fileMatch": "Coincidencia de archivo", + "schema": "Esquema", + "commands": "Comandos ({0})", + "command name": "Nombre", + "keyboard shortcuts": "Métodos abreviados de teclado", + "menuContexts": "Contextos de menú", + "languages": "Lenguajes ({0})", + "language id": "Id.", + "language name": "Nombre", + "file extensions": "Extensiones de archivo", + "grammar": "Gramática", + "snippets": "Fragmentos" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index deda07fd39..622a09f888 100644 --- a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Esta extensión es recomendada por los usuarios del espacio de trabajo actual.", "reallyRecommended2": "La extension recomendada para este tipo de archivo es {0}", "reallyRecommendedExtensionPack": "Para este tipo de fichero, se recomienda el paquete de extensión '{0}'.", - "showRecommendations": "Mostrar recomendaciones", "install": "Instalar", + "showRecommendations": "Mostrar recomendaciones", "showLanguageExtensions": "El Marketplace tiene extensiones que pueden ayudar con '. {0} ' archivos ", "workspaceRecommended": "Esta área de trabajo tiene recomendaciones de extensión.", "installAll": "Instalar todo", diff --git a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index 3fd33c781f..312fe61562 100644 --- a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "¿Quiere deshabilitar otras asignaciones de teclas ({0}) para evitar conflictos entre enlaces de teclado?", "yes": "Sí", - "no": "No", - "betterMergeDisabled": "La extensión Mejor combinación está ahora integrada, la extensión instalada se deshabilitó y no se puede desinstalar.", - "uninstall": "Desinstalación" + "no": "No" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index 1c61c66d6f..a44cd55d9c 100644 --- a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Recomendado", "otherRecommendedExtensions": "Otras recomendaciones", "workspaceRecommendedExtensions": "Recomendaciones de espacio de trabajo", - "builtInExtensions": "Integrado", + "builtInExtensions": "Características", + "builtInThemesExtensions": "Temas", + "builtInBasicsExtensions": "Lenguajes de programación", "searchExtensions": "Buscar extensiones en Marketplace", "sort by installs": "Criterio de ordenación: Número de instalaciones", "sort by rating": "Criterio de ordenación: Clasificación", diff --git a/i18n/esn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/esn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index d571384a50..2ac605f5e1 100644 --- a/i18n/esn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Editor de archivos de texto", "createFile": "Crear archivo", + "relaunchWithIncreasedMemoryLimit": "Reiniciar con {0} MB", + "configureMemoryLimit": "Configurar el límite de memoria", "fileEditorWithInputAriaLabel": "{0}. Editor de archivos de texto.", "fileEditorAriaLabel": "Editor de archivos de texto." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 02105cb098..37a11ca875 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Copiar", "pasteFile": "Pegar", "retry": "Reintentar", + "renameWhenSourcePathIsParentOfTargetError": "Utilice el comando 'Nueva carpeta' o 'Nuevo archivo' para agregar elementos a una carpeta existente ", "newUntitledFile": "Nuevo archivo sin título", "createNewFile": "Nuevo archivo", "createNewFolder": "Nueva carpeta", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Va a eliminar una carpeta con cambios sin guardar en {0} archivos. ¿Desea continuar?", "dirtyMessageFileDelete": "Va a eliminar un archivo con cambios sin guardar. ¿Desea continuar?", "dirtyWarning": "Los cambios se perderán si no se guardan.", + "undoBin": "Se puede restaurar de la papelera de reciclaje.", + "undoTrash": "Se puede restaurar de la papelera.", + "doNotAskAgain": "No volver a preguntarme", + "irreversible": "Esta acción es irreversible.", + "binFailed": "Error al eliminar usando la papelera de reciclaje. ¿Desea eliminar de forma permanente en su lugar?", + "trashFailed": "No se pudo eliminar usando la papelera. ¿Desea eliminar de forma permanente?", + "deletePermanentlyButtonLabel": "&&Eliminar de forma permanente", + "retryButtonLabel": "&&Reintentar", + "confirmMoveTrashMessageFilesAndDirectories": "¿Está seguro que desea eliminar los siguientes archivos/directorios de {0} y su contenido?", + "confirmMoveTrashMessageMultipleDirectories": "¿Está seguro que desea eliminar los siguientes directorios de {0} y su contenido?", "confirmMoveTrashMessageMultiple": "¿Está seguro de que desea eliminar los siguientes archivos {0}?", "confirmMoveTrashMessageFolder": "¿Está seguro de que desea eliminar '{0}' y su contenido?", "confirmMoveTrashMessageFile": "¿Está seguro de que desea eliminar '{0}'?", - "undoBin": "Puede restaurar desde la papelera de reciclaje.", - "undoTrash": "Puede restaurar desde la papelera.", - "doNotAskAgain": "No volver a preguntarme", + "confirmDeleteMessageFilesAndDirectories": "¿Está seguro que desea eliminar permanentemente los archivos/directorios siguientes {0} y su contenido?", + "confirmDeleteMessageMultipleDirectories": "¿Está seguro que desea eliminar permanentemente los siguientes directorios de {0} y su contenido?", "confirmDeleteMessageMultiple": "¿Está seguro de que desea eliminar de forma permanente los siguientes archivos {0}?", "confirmDeleteMessageFolder": "¿Está seguro de que desea eliminar '{0}' y su contenido de forma permanente?", "confirmDeleteMessageFile": "¿Está seguro de que desea eliminar '{0}' de forma permanente?", - "irreversible": "Esta acción es irreversible.", - "cancel": "Cancelar", - "permDelete": "Eliminar permanentemente", - "importFiles": "Importar archivos", + "addFiles": "Agregar archivos", "confirmOverwrite": "Ya existe un archivo o carpeta con el mismo nombre en la carpeta de destino. ¿Quiere reemplazarlo?", "replaceButtonLabel": "&&Reemplazar", "fileIsAncestor": "El archivo que se va a pegar es un antecesor de la carpeta de destino", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Abrir un archivo antes para abrirlo en una nueva ventana", "copyPath": "Copiar ruta de acceso", "emptyFileNameError": "Debe especificarse un nombre de archivo o carpeta.", + "fileNameStartsWithSlashError": "El nombre de archivo o carpeta no puede comenzar con el carácter barra. ", "fileNameExistsError": "Ya existe el archivo o carpeta **{0}** en esta ubicación. Elija un nombre diferente.", + "fileUsedAsFolderError": "** {0} ** es un archivo y no puede tener elementos descendientes. ", "invalidFileNameError": "El nombre **{0}** no es válido para el archivo o la carpeta. Elija un nombre diferente.", "filePathTooLongError": "El nombre **{0}** da como resultado una ruta de acceso demasiado larga. Elija un nombre más corto.", "compareWithClipboard": "Comparar archivo activo con portapapeles", diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index bb13d7ef4c..47a4590b22 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Controla si los archivos no guardados se recuerdan entre las sesiones, lo que permite omitir el mensaje para guardar al salir del editor.", "useExperimentalFileWatcher": "Utilice el nuevo monitor de archivo experimental.", "defaultLanguage": "El modo de lenguaje predeterminado que se asigna a nuevos archivos.", + "maxMemoryForLargeFilesMB": "Controla la memoria disponible para VS Code después de reiniciar, cuando se intenta abrir archivos de gran tamaño. Afecta de la misma manera si se especifica --max-memory = NUEVOTAMAÑO en la línea de comandos. ", "editorConfigurationTitle": "Editor", "formatOnSave": "Formatea un archivo al guardarlo. Debe haber un formateador disponible, el archivo no debe guardarse automáticamente y el editor no debe estar cerrándose.", + "formatOnSaveTimeout": "Tiempo de espera de aplicación de formato al guardar. Especifica un límite de tiempo en milisegundos para los comandos formatOnSave. Los comandos que tarden más del tiempo de espera especificado se cancelarán.", "explorerConfigurationTitle": "Explorador de archivos", "openEditorsVisible": "Número de editores mostrados en el panel de editores abiertos.", "autoReveal": "Controla si el explorador debe mostrar y seleccionar automáticamente los archivos al abrirlos.", diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 8c3bb97439..d9af20c955 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -2,18 +2,22 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Escriba el nombre de archivo. Presione ENTRAR para confirmar o Esc para cancelar", - "constructedPath": "Crear {0} en **{1}**", + "createFileFromExplorerInfoMessage": "Crear archivo ** {0} ** en ** {1} **", + "renameFileFromExplorerInfoMessage": "Mover y renombrar a ** {0} **", + "createFolderFromExplorerInfoMessage": "Crear carpeta ** {0} ** en ** {1} **", "filesExplorerViewerAriaLabel": "{0}, Explorador de archivos", "dropFolders": "¿Quiere agregar las carpetas al área de trabajo?", "dropFolder": "¿Quiere agregar la carpeta al área de trabajo?", "addFolders": "&&Agregar carpetas", "addFolder": "&&Agregar carpeta", + "confirmRootsMove": "¿Está seguro de que quiere cambiar el orden de varias carpetas raíz en el área de trabajo?", "confirmMultiMove": "¿Está seguro de que desea mover los siguientes archivos {0}?", + "confirmRootMove": "¿Está seguro de que quiere cambiar el orden de la carpeta raíz \"{0}\" en el área de trabajo?", "confirmMove": "¿Está seguro de que desea mover '{0}'?", "doNotAskAgain": "No volver a preguntarme", "moveButtonLabel": "&&Mover", diff --git a/i18n/esn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..d73134b9c5 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Vista previa de HTML" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/esn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..1709fee8d0 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Entrada del editor no válida." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..7015229395 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Desarrollador" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/esn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..760d6b600c --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Abrir herramientas de desarrollo de vistas web", + "refreshWebviewLabel": "Recargar vistas web" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index f1b0a9cf80..494f385c78 100644 --- a/i18n/esn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "¿Desea cambiar el idioma de la interfaz de usuario de VS Code a {0} y reiniciar la aplicación?", + "yes": "Sí", + "no": "No", + "neverAgain": "No volver a mostrar", "JsonSchema.locale": "Idioma de la interfaz de usuario que debe usarse.", "vscode.extension.contributes.localizations": "Contribuye a la localización del editor", "vscode.extension.contributes.localizations.languageId": "Identificador del idioma en el que se traducen las cadenas de visualización.", diff --git a/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..2acd632d22 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "¿Desea cambiar el idioma de la interfaz de usuario de VS Code a {0} y reiniciar la aplicación?", + "yes": "Sí", + "no": "No", + "neverAgain": "No volver a mostrar", + "install language pack": "En un futuro próximo, VS Code sólo soportará paquetes de idiomas en forma de extensiones de Marketplace. Instale la extensión ' {0} ' para continuar utilizando el idioma configurado actualmente. ", + "install": "Instalar", + "more information": "Más información...", + "JsonSchema.locale": "Idioma de la interfaz de usuario que debe usarse.", + "vscode.extension.contributes.localizations": "Contribuye a la localización del editor", + "vscode.extension.contributes.localizations.languageId": "Identificador del idioma en el que se traducen las cadenas de visualización.", + "vscode.extension.contributes.localizations.languageName": "Nombre del idioma en Inglés.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Nombre de la lengua en el idioma contribuido.", + "vscode.extension.contributes.localizations.translations": "Lista de traducciones asociadas al idioma.", + "vscode.extension.contributes.localizations.translations.id": "ID de VS Code o extensión a la que se ha contribuido esta traducción. ID de código vs es siempre ' vscode ' y de extensión debe ser en formato ' publisherID. extensionName '.", + "vscode.extension.contributes.localizations.translations.id.pattern": "ID debe ser ' vscode ' o en formato ' publisherId.extensionName ' para traducer VS Code o una extensión respectivamente.", + "vscode.extension.contributes.localizations.translations.path": "Una ruta de acceso relativa a un archivo que contiene traducciones para el idioma." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..e5e5ab4cfb --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Configurar idioma", + "displayLanguage": "Define el lenguaje para mostrar de VSCode.", + "doc": "Consulte {0} para obtener una lista de idiomas compatibles.", + "restart": "Al cambiar el valor se requiere reiniciar VSCode.", + "fail.createSettings": "No se puede crear '{0}' ({1})." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..57024a086a --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Copiar", + "copyMessage": "Copiar mensaje" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..8323facb36 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Total {0} Problemas" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..5f229151f6 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Problemas", + "tooltip.1": "1 problema en este fichero", + "tooltip.N": "{0} problemas en este fichero", + "markers.showOnFile": "Mostrar Errores y Advertencias en la carpeta y ficheros." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..04f7dd0d77 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Desactivar filtro de exclusión de archivos.", + "clearFilter": "Borrar el filtro." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..cd0f382c88 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "Mostrando {0} de {1}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..90352e08b0 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Ver", + "problems.view.toggle.label": "Alternar problemas (errores, advertencias, información)", + "problems.view.focus.label": "Problemas de enfoque (errores, advertencias, información)", + "problems.panel.configuration.title": "Vista Problemas", + "problems.panel.configuration.autoreveal": "Controla si la vista Problemas debe revelar automáticamente los archivos cuando los abre", + "markers.panel.title.problems": "Problemas", + "markers.panel.aria.label.problems.tree": "Problemas agrupados por archivos", + "markers.panel.no.problems.build": "Hasta el momento, no se encontraron problemas en el área de trabajo.", + "markers.panel.no.problems.filters": "No se encontraron resultados con los criterios de filtro proporcionados.", + "markers.panel.no.problems.file.exclusions": "Todos los problemas se ocultan porque el filtro de exclusión de archivos está habilitado.", + "markers.panel.action.useFilesExclude": "Filtrar usando la configuración para excluir archivos", + "markers.panel.action.donotUseFilesExclude": "No utilice opción para excluir archivos", + "markers.panel.action.filter": "Filtrar problemas", + "markers.panel.filter.ariaLabel": "Filtrar problemas", + "markers.panel.filter.placeholder": "Filtro. Por ejemplo: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "errores", + "markers.panel.filter.warnings": "advertencias", + "markers.panel.filter.infos": "informaciones", + "markers.panel.single.error.label": "1 error", + "markers.panel.multiple.errors.label": "{0} errores", + "markers.panel.single.warning.label": "1 advertencia", + "markers.panel.multiple.warnings.label": "{0} advertencias", + "markers.panel.single.info.label": "1 información", + "markers.panel.multiple.infos.label": "{0} informaciones", + "markers.panel.single.unknown.label": "1 desconocido", + "markers.panel.multiple.unknowns.label": "{0} desconocidos", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} con {1} problemas", + "problems.tree.aria.label.marker.relatedInformation": " Este problema tiene referencias a ubicaciones de {0}.", + "problems.tree.aria.label.error.marker": "Error generado por {0}: {1} en la línea {2} y el carácter {3}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Error: {0} en la línea {1} y el carácter {2}.{3}", + "problems.tree.aria.label.warning.marker": "Advertencia generada por {0}: {1} en la línea {2} y el carácter {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Advertencia: {0} en la línea {1} y el carácter {2}.{3}", + "problems.tree.aria.label.info.marker": "Información generada por {0}: {1} en la línea {2} y el carácter {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Información: {0} en la línea {1} y el carácter {2}.{3}", + "problems.tree.aria.label.marker": "Problema generado por {0}: {1} en la línea {2} y el carácter {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Problema: {0} en la línea {1} y el carácter {2}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{0} en la línea {1} y el carácter {2} en {3}", + "errors.warnings.show.label": "Mostrar errores y advertencias" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/esn/src/vs/workbench/parts/output/browser/outputActions.i18n.json index fbf4cb4598..47d9b4ca83 100644 --- a/i18n/esn/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Alternar salida", "clearOutput": "Borrar salida", "toggleOutputScrollLock": "Alternar Bloq Despl salida", - "switchToOutput.label": "Cambiar a salida" + "switchToOutput.label": "Cambiar a salida", + "openInLogViewer": "Abrir archivo de registro" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index f725bb82e2..498c9940c9 100644 --- a/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Salida", "logViewer": "Visor de registros", "viewCategory": "Ver", - "clearOutput.label": "Borrar salida" + "clearOutput.label": "Borrar salida", + "openActiveLogOutputFile": "Ver: abrir el archivo de salida del registro activo" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 78ff09effe..8754c36d13 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Métodos abreviados de teclado", + "showDefaultKeybindings": "Mostrar enlaces de teclado predeterminados", + "showUserKeybindings": "Mostrar enlaces de teclado del usuario", "SearchKeybindings.AriaLabel": "Buscar enlaces de teclado", "SearchKeybindings.Placeholder": "Buscar enlaces de teclado", "sortByPrecedene": "Ordenar por procedimiento", diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index e83b387130..dd2ecf1e96 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Abrir Configuración Predeterminada Raw", + "openSettings": "Abrir configuración", "openGlobalSettings": "Abrir configuración de usuario", "openGlobalKeybindings": "Abrir métodos abreviados de teclado", "openGlobalKeybindingsFile": "Abrir el archivo de métodos abreviados de teclado", diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 2b6707ef3a..67704d94ef 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Configuración predeterminada", "SearchSettingsWidget.AriaLabel": "Buscar configuración", "SearchSettingsWidget.Placeholder": "Buscar configuración", "noSettingsFound": "Sin resultados", @@ -16,6 +15,8 @@ "nlpResult": "Resultados en lenguaje natural", "filterResult": "Resultados filtrados", "defaultSettings": "Configuración predeterminada", + "defaultUserSettings": "Configuración predeterminada de usuario", + "defaultWorkspaceSettings": "Configuración de espacio de trabajo predeterminado", "defaultFolderSettings": "Configuración de carpeta predeterminada", "defaultEditorReadonly": "Editar en el editor de lado de mano derecha para reemplazar valores predeterminados.", "preferencesAriaLabel": "Preferencias predeterminadas. Editor de texto de solo lectura." diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index dcddc1147c..649429c631 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Mostrar extensión \"{0}\"", "editTtile": "Editar", "replaceDefaultValue": "Reemplazar en Configuración", - "copyDefaultValue": "Copiar en Configuración", - "unsupportedPHPExecutablePathSetting": "Este valor debe estar en la configuración de usuario. Si quiere configurar PHP para el área de trabajo, abra un archivo PHP y haga clic en \"Ruta de acceso PHP\" en la barra de estado.", - "unsupportedWorkspaceSetting": "Este valor debe estar en Configuración de usuario.", - "unsupportedWorkbenchSetting": "Esta configuración no se puede aplicar ahora. Se aplicará al abrir esta carpeta directamente.", - "unsupportedWorkbenchSettingDevMode": "Esta configuración no se puede aplicar ahora. Se aplicará si se define su alcance como 'recurso' o al abrir esta carpeta directamente. " + "copyDefaultValue": "Copiar en Configuración" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index ce60d3014a..ffd23dfd8a 100644 --- a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Instalar proveedores adicionales de SCM...", "no open repo": "No hay proveedores de control de código fuente activos.", "source control": "Control de código fuente", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Ocultar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 39c6fb8f1b..c64f4ac2b7 100644 --- a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Mostrar búsqueda anterior de patrón exclude ", "nextSearchTerm": "Mostrar siguiente término de búsqueda", "previousSearchTerm": "Mostrar anterior término de búsqueda", - "showSearchViewlet": "Mostrar búsqueda", "findInFiles": "Buscar en archivos", "replaceInFiles": "Reemplazar en archivos", "RefreshAction.label": "Actualizar", diff --git a/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index b40640b7a8..99fee11481 100644 --- a/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Buscar", + "copyMatchLabel": "Copiar", + "copyPathLabel": "Copiar ruta de acceso", + "copyAllLabel": "Copiar todo", + "clearSearchHistoryLabel": "Borrar historial de búsqueda", + "toggleSearchViewPositionLabel": "Alternar la posición de vista de búsqueda", "findInFolder": "Buscar en carpeta...", "findInWorkspace": "Buscar en área de trabajo...", "showTriggerActions": "Ir al símbolo en el área de trabajo...", "name": "Buscar", - "search": "Buscar", "showSearchViewl": "Mostrar búsqueda", "view": "Ver", "findInFiles": "Buscar en archivos", @@ -26,5 +31,5 @@ "search.followSymlinks": "Controla si debe seguir enlaces simbólicos durante la búsqueda.", "search.smartCase": "Proporciona busquedas de mayúsculas y minúsculas si el patrón es todo en minúsculas, de lo contrario, busca en mayúsculas y minúsculas", "search.globalFindClipboard": "Controla si la vista de búsqueda debe leer o modificar el portapapeles de búsqueda compartido en macOS", - "search.location": "Vista previa: controla si se muestra la búsqueda como una vista en la barra lateral o como un panel en el área de paneles para tener más espacio horizontal. En la próxima versión, la búsqueda en panel tendrá una distribución horizontal mejorada y dejará de ser una vista previa." + "search.location": "Controla si la búsqueda se mostrará como una vista en la barra lateral o como un panel en el área del panel para un espacio más horizontal. La siguiente versión de la búsqueda en el panel tendrá un mejor diseño horizontal y esto ya no será una vista previa." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 06aeb38318..1a13c3c022 100644 --- a/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Ayúdenos a mejorar nuestro soporte para {0}", "takeShortSurvey": "Realizar una breve encuesta", "remindLater": "Recordármelo más tarde", - "neverAgain": "No volver a mostrar", - "helpUs": "Ayúdenos a mejorar nuestro soporte para {0}" + "neverAgain": "No volver a mostrar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index fe489ee2b2..66e9c5ce83 100644 --- a/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "¿Le importaría realizar una breve encuesta de opinión?", "takeSurvey": "Realizar encuesta", "remindLater": "Recordármelo más tarde", - "neverAgain": "No volver a mostrar", - "surveyQuestion": "¿Le importaría realizar una breve encuesta de opinión?" + "neverAgain": "No volver a mostrar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index c33f99445e..90bce3a809 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Patrón de problema o nombre de un patrón de problema que se ha aportado o predefinido. Se puede omitir si se especifica la base.", "ProblemMatcherSchema.base": "Nombre de un buscador de coincidencias de problemas base que se va a usar.", "ProblemMatcherSchema.owner": "Propietario del problema dentro de Code. Se puede omitir si se especifica \"base\". Si se omite y no se especifica \"base\", el valor predeterminado es \"external\".", + "ProblemMatcherSchema.source": "Una cadena legible que describe la fuente de este diagnóstico, por ejemplo 'Inicio' o 'super pelusa'.", "ProblemMatcherSchema.severity": "Gravedad predeterminada para los problemas de capturas. Se usa si el patrón no define un grupo de coincidencias para \"severity\".", "ProblemMatcherSchema.applyTo": "Controla si un problema notificado en un documento de texto se aplica solamente a los documentos abiertos, cerrados o a todos los documentos.", "ProblemMatcherSchema.fileLocation": "Define cómo deben interpretarse los nombres de archivo notificados en un patrón de problema.", diff --git a/i18n/esn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index be9e1ec7ea..bc60fb1ce6 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Tipo de tarea real", + "TaskDefinition.description": "Tenga en cuenta que los tipos que empiezan con ' $ ' están reservados para uso interno.", "TaskDefinition.properties": "Propiedades adicionales del tipo de tarea", "TaskTypeConfiguration.noType": "La configuración del tipo de tarea no tiene la propiedad \"taskType\" requerida.", "TaskDefinitionExtPoint": "Aporta tipos de tarea" diff --git a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 4de28ec3fc..bc81662c65 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "No asigna la tarea a ningún grupo", "JsonSchema.tasks.group": "Define a qué grupo de ejecución pertenece esta tarea. Admite \"compilación\" para agregarla al grupo de compilación y \"prueba\" para agregarla al grupo de prueba.", "JsonSchema.tasks.type": "Define si la tarea se ejecuta como un proceso o como un comando dentro de in shell. ", + "JsonSchema.command.quotedString.value": "El valor actual del comando", + "JsonSchema.tasks.quoting.escape": "Carácteres de escape usan el carácter de escape de la linea de comandos (ej.: ' en PowerShell y \\ en Bash)", + "JsonSchema.tasks.quoting.strong": "Cita el argumento usando el carácter de citación doble de la linea de comandos (ej.: \" en PowerShell y Bash) ", + "JsonSchema.tasks.quoting.weak": "Cita el argumento usando el carácter de citación simple de la linea de comandos (ej.: ' en PowerShell y Bash) ", + "JsonSchema.command.quotesString.quote": "Cómo el valor del comando debería ser citado", + "JsonSchema.command": "El comando que se va a ejecutar. Puede ser un programa externo o un comando shell.", + "JsonSchema.args.quotedString.value": "El valor actual del argumento", + "JsonSchema.args.quotesString.quote": "Cómo el valor del argumento debería ser citado ", + "JsonSchema.tasks.args": "Argumentos que se pasan al comando cuando se invoca esta tarea.", "JsonSchema.tasks.label": "Etiqueta de interfaz de usuario de la tarea", "JsonSchema.version": "El número de versión de la configuración.", "JsonSchema.tasks.identifier": "Un identificador definido por el usuario para hacer referencia a la tarea en launch.json o una cláusula dependsOn.", diff --git a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 96568f1193..7024547e7b 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "Tareas", "ConfigureTaskRunnerAction.label": "Configurar tarea", + "totalErrors": "{0} errores", + "totalWarnings": "{0} advertencias", + "totalInfos": "{0} informaciones", "problems": "Problemas", "building": "Compilando...", - "manyMarkers": "Más de 99", + "manyProblems": "+10Mil", "runningTasks": "Mostrar tareas en ejecución", "tasks": "Tareas", "TaskSystem.noHotSwap": "Cambiar el motor de ejecución de tareas con una tarea activa ejecutandose, requiere recargar la ventana", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Seleccione qué tipo de errores y advertencias deben buscarse durante el examen de la salida de la tarea", "customizeParseErrors": "La configuración actual de tareas contiene errores. Antes de personalizar una tarea, corrija los errores.", "moreThanOneBuildTask": "Hay muchas tareas de compilación definidas en el archivo tasks.json. Se ejecutará la primera.\n", - "TaskSystem.activeSame.background": "La tarea \"{0}\" ya está activa en segundo plano. Para terminarla, use la opción \"Terminar tarea\" del menú Tareas.", - "TaskSystem.activeSame.noBackground": "La tarea \"{0}\" ya está activa. Para terminarla, use la opción \"Terminar tarea\" del menú Tareas.", + "TaskSystem.activeSame.background": "La tarea '{0}' ya está activa y en segundo plano.", + "TaskSystem.activeSame.noBackground": "La tarea '{0}' ya está activa.", + "terminateTask": "Finalizar tarea", + "restartTask": "Reiniciar tarea", "TaskSystem.active": "Ya hay una tarea en ejecución. Finalícela antes de ejecutar otra tarea.", "TaskSystem.restartFailed": "No se pudo terminar y reiniciar la tarea {0}", "TaskService.noConfiguration": "Error: La detección de tarea {0} no encontró una tarea para la siguiente configuración:\n{1}\nLa tarea será omitida.\n", diff --git a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index efe4083574..cb8bd12b00 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Tarea - {0}", "closeTerminal": "Pulse cualquier tecla para cerrar el terminal", "reuseTerminal": "Las tareas reutilizarán el terminal, presione cualquier tecla para cerrarlo.", - "TerminalTaskSystem": "No se puede ejecutar un comando shell en una unidad UNC.", + "TerminalTaskSystem": "No se puede ejecutar un comando Shell en una unidad UNC mediante cmd.exe.", "unkownProblemMatcher": "No puede resolver el comprobador de problemas {0}. Será omitido." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/esn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index b1e5789fc9..3a198d4cbe 100644 --- a/i18n/esn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Advertencia: options.cwd debe ser de tipo cadena. Se ignora el valor {0}.", + "ConfigurationParser.inValidArg": "Error: el argumento del comando debe ser una cadena de texto o una cadena de texto citada. El valor provisto es: [0]", "ConfigurationParser.noargs": "Error: Los argumentos de comando deben ser una matriz de cadenas. El valor proporcionado es: {0}", "ConfigurationParser.noShell": "Advertencia: La configuración del shell solo se admite al ejecutar tareas en el terminal.", "ConfigurationParser.noName": "Error: El buscador de coincidencias de problemas del ámbito de declaración debe tener un nombre: {0}", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Error: la configuración de la tarea '{0}' no contiene la propiedad requerida '{1}'. Se omitirá la configuración de la tarea.", "ConfigurationParser.notCustom": "Error: Las tareas no se declaran como una tarea personalizada. La configuración se omitirá.\n{0}\n", "ConfigurationParser.noTaskName": "Error: Las tareas deben proporcionar una propiedad label. La tarea se ignorará.\n{0}\n", - "taskConfiguration.shellArgs": "Advertencia: La tarea '{0}' es un comando de shell y uno de sus argumentos podría tener espacios sin escape. Para asegurarse de que la línea de comandos se cite correctamente, fusione mediante combinación los argumentos en el comando.", "taskConfiguration.noCommandOrDependsOn": "Error: La tarea \"{0}\" no especifica un comando ni una propiedad dependsOn. La tarea se ignorará. Su definición es: \n{1}", "taskConfiguration.noCommand": "Error: La tarea \"{0}\" no define un comando. La tarea se ignorará. Su definición es: {1}", "TaskParse.noOsSpecificGlobalTasks": "La versión de tarea 2.0.0 no admite tareas específicas de SO globales. Conviértalas en una tarea con un comando específico de SO. Estas son las tareas afectadas:\n{0}" diff --git a/i18n/esn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..452c57e694 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "El color de fondo del terminal, esto permite colorear el terminal de forma diferente al panel.", + "terminal.foreground": "El color de primer plano del terminal.", + "terminalCursor.foreground": "Color de primer plano del cursor del terminal.", + "terminalCursor.background": "Color de fondo del cursor del terminal. Permite personalizar el color de un carácter solapado por un cursor de bloque.", + "terminal.selectionBackground": "Color de fondo de selección del terminal.", + "terminal.border": "Color del borde que separa paneles divididos en el terminal. El valor predeterminado es panel.border.", + "terminal.ansiColor": "color ANSI ' {0} ' en el terminal." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 8bee86605e..9861595bf7 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "Seleccione el directorio de trabajo actual para el nuevo terminal", "workbench.action.terminal.newInActiveWorkspace": "Crear nuevo terminal integrado (en el espacio de trabajo activo)", "workbench.action.terminal.split": "Dividir terminal", + "workbench.action.terminal.splitInActiveWorkspace": "Dividir Terminal (En el espacio de trabajo activo)", "workbench.action.terminal.focusPreviousPane": "Aplicar el foco al panel anterior", "workbench.action.terminal.focusNextPane": "Aplicar el foco al panel siguiente", "workbench.action.terminal.resizePaneLeft": "Cambiar el tamaño del panel por la izquierda", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "Desplazar hacia arriba (página)", "workbench.action.terminal.scrollToTop": "Desplazar al principio", "workbench.action.terminal.clear": "Borrar", + "workbench.action.terminal.clearSelection": "Borrar selección", "workbench.action.terminal.allowWorkspaceShell": "Permitir la configuración del área de trabajo Shell", "workbench.action.terminal.disallowWorkspaceShell": "No permitir la configuración del área de trabajo Shell", "workbench.action.terminal.rename": "Cambiar nombre", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Ocultar Encontrar Widget", "nextTerminalFindTerm": "Mostrar siguiente término de búsqueda", "previousTerminalFindTerm": "Mostrar término de búsqueda anterior", - "quickOpenTerm": "Cambiar terminal activo" + "quickOpenTerm": "Cambiar terminal activo", + "workbench.action.terminal.scrollToPreviousCommand": "Desplácese al comando anterior", + "workbench.action.terminal.scrollToNextCommand": "Desplácese al siguiente comando", + "workbench.action.terminal.selectToPreviousCommand": "Seleccionar hasta el comando anterior", + "workbench.action.terminal.selectToNextCommand": "Seleccionar hasta el comando siguiente" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index 06274dd050..e6b32d074f 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "El terminal no tiene ninguna selección para copiar", "terminal.integrated.exitedWithCode": "El proceso del terminal finalizó con el código de salida: {0}", "terminal.integrated.waitOnExit": "Presione cualquier tecla para cerrar el terminar", - "terminal.integrated.launchFailed": "No se pudo iniciar el comando de proceso del terminal \"{0}{1}\" (código de salida: {2})" + "terminal.integrated.launchFailed": "No se pudo iniciar el comando de proceso del terminal \"{0}{1}\" (código de salida: {2})", + "terminal.integrated.launchFailedExtHost": "El proceso terminal no pudo iniciarse (código de salida: {0})" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 79ddaacb02..8e64147ee8 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "Copiar", + "split": "Dividir", "paste": "Pegar", "selectAll": "Seleccionar todo", - "clear": "Borrar", - "split": "Dividir" + "clear": "Borrar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index d2f93e17ec..901823a3a1 100644 --- a/i18n/esn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Esta área de trabajo contiene valores de configuración que solo se pueden establecer en Configuración de usuario ({0}). Haga clic [aquí]({1}) para obtener más información.", "openWorkspaceSettings": "Abrir configuración del área de trabajo", "dontShowAgain": "No volver a mostrar", "unsupportedWorkspaceSettings": "Esta área de trabajo contiene valores de configuración que solo se pueden establecer en Configuración de usuario ({0}). Haga clic [aquí]({1}) para obtener más información." diff --git a/i18n/esn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/esn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..0378f2fc8d --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Notas de la versión: {0}", + "unassigned": "sin asignar" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/esn/src/vs/workbench/parts/update/electron-browser/update.i18n.json index d6f1fbeccf..2c980e5c8f 100644 --- a/i18n/esn/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Más tarde", - "unassigned": "sin asignar", "releaseNotes": "Notas de la versión", "showReleaseNotes": "Mostrar las notas de la versión", "read the release notes": "{0} v{1}. ¿Quiere leer las notas de la versión?", @@ -17,13 +15,14 @@ "updateIsReady": "Nueva actualización de {0} disponible.", "noUpdatesAvailable": "Actualmente, no hay actualizaciones disponibles.", "ok": "Aceptar", - "download now": "Descargar ahora", "thereIsUpdateAvailable": "Hay una actualización disponible.", - "installUpdate": "Instalar la actualización ", + "download now": "Descargar ahora", + "later": "Más tarde", "updateAvailable": "Hay una actualización disponible: {0} {1}", + "installUpdate": "Instalar la actualización ", "updateInstalling": "{0} {1} se está instalando en segundo plano, le avisaremos cuando sea completada", + "updateAvailableAfterRestart": "Reiniciar {0} para aplicar la última actualización.", "updateNow": "Actualizar ahora", - "updateAvailableAfterRestart": "{0} se actualizará después de reiniciarse.", "commandPalette": "Paleta de comandos...", "settings": "Configuración", "keyboardShortcuts": "Métodos abreviados de teclado", diff --git a/i18n/esn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..5ce816dbcb --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "Abrir URL", + "developer": "Desarrollador" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..cfb3d21c72 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "Editor de vistas web", + "developer": "Desarrollador" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..760d6b600c --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Abrir herramientas de desarrollo de vistas web", + "refreshWebviewLabel": "Recargar vistas web" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/esn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..41dc2fce9f --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Ayúdenos a mejorar VS Code permitiendo a Microsoft recopilar datos de uso. Lea nuestra [declaración de privacidad]({0}) y vea qué debe hacer para [no participar]({1}).", + "telemetryOptOut.optInNotice": "Ayúdenos a mejorar VS Code permitiendo a Microsoft recopilar datos de uso. Lea nuestra [declaración de privacidad]({0}) y vea qué debe hacer para [no participar]({1}).", + "telemetryOptOut.readMore": "Leer más" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/esn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index 1e81ab79d3..b88ffed015 100644 --- a/i18n/esn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Administrar extensiones", "welcomeOverlay.problems": "Ver errores y advertencias", "welcomeOverlay.commandPalette": "Buscar y ejecutar todos los comandos", + "welcomeOverlay.notifications": "Mostrar notificaciones", "welcomeOverlay": "Información general de la interfaz de usuario", "hideWelcomeOverlay": "Ocultar información general de la interfaz", "help": "Ayuda" diff --git a/i18n/esn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/esn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 7178fbf974..ab3c611d30 100644 --- a/i18n/esn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Herramientas y lenguajes", "welcomePage.installExtensionPacksDescription": "Instalar soporte para {0} y {1}", "welcomePage.moreExtensions": "más", - "welcomePage.installKeymapDescription": "Instalar los métodos abreviados de teclado", - "welcomePage.installKeymapExtension": "Instalar los métodos abreviados de teclado de {0} y {1}", + "welcomePage.installKeymapDescription": "Configuraciones y combinaciones de teclas", + "welcomePage.installKeymapExtension": "Instalar la configuración y los métodos abreviados de teclado de {0} y {1}", "welcomePage.others": "otros", "welcomePage.colorTheme": "Tema de color", "welcomePage.colorThemeDescription": "Modifique a su gusto la apariencia del editor y el código", diff --git a/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index c88af71ea9..7d6fc3a256 100644 --- a/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/esn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Resumen de la configuración. Esta etiqueta se usará en el archivo de configuración como comentario divisor.", "vscode.extension.contributes.configuration.properties": "Descripción de las propiedades de configuración.", + "scope.application.description": "Configuración específica de aplicación, que puede ser configurado en configuración de usuario.", "scope.window.description": "Configuración específica para ventanas, que se puede definir en la configuración de usuario o de área de trabajo.", "scope.resource.description": "Configuración específica para recursos, que se puede definir en la configuración de usuario, de área de trabajo o de carpeta.", "scope.description": "Ámbito donde es aplicable la configuración. Los ámbitos disponibles son \"window\" y \"resource\".", diff --git a/i18n/esn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/esn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 0b23b826ae..5cfc0aa87d 100644 --- a/i18n/esn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Abrir configuración", "saveAndRetry": "Guardar y reintentar", "errorUnknownKey": "No se puede escribir en {0} porque {1} no es una configuración registrada.", + "errorInvalidWorkspaceConfigurationApplication": "No se puede escribir {0} en configuración de área de trabajo. Esta opción puede escribirse solamente en configuración de usuario.", "errorInvalidFolderConfiguration": "No se puede escribir en Configuración de carpeta porque {0} no admite el ámbito del recurso de carpeta.", "errorInvalidUserTarget": "No se puede escribir en Configuración de usuario porque {0} no admite el ámbito global.", "errorInvalidWorkspaceTarget": "No se puede escribir a la configuración del espacio de trabajo porque {0} no soporta a un espacio de trabajo con multi carpetas.", diff --git a/i18n/esn/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/esn/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..53a465b71f --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Esta configuración puede aplicarse sólo en configuración de usuario", + "unsupportedWindowSetting": "Esta configuración no se puede aplicar ahora. Se aplicará al abrir esta carpeta directamente." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/esn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..0a5131780c --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "canNotResolveWorkspaceFolder": "'${workspaceFolder}' no puede ser resuelto. Por favor, abra una carpeta.", + "canNotResolveFolderBasename": "'${workspaceFolderBasename}' no puede ser resuelto. Por favor, abra una carpeta." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/esn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..36f359788c --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "'{0}' no puede resolverse porque no se asignó nombre de variable de entorno. ", + "configNotFound": "'{0}' puede no resolverse porque la configuración '{1}' no fué encontrada. ", + "configNoString": "'{0}' puede no resolverse porque '{1}' es un valor estructurado.", + "missingConfigName": "'{0}' no puede resolverse porque no tiene asignado un nombre de configuración . ", + "noValueForCommand": "{0} ' no se puede resolver porque el comando no tiene ningún valor.", + "canNotFindFolder": "' {0} ' no se puede resolver. No existe la carpeta ' {1} '.", + "canNotResolveWorkspaceFolderMultiRoot": "'{0}' no puede ser resuelto en un espacio de trabajo multicarpeta. Defina el alcance de esta variable utilizando ':' y un nombre de carpeta del espacio de trabajo. ", + "canNotResolveWorkspaceFolder": "'{0}' no puede ser resuelto. Por favor, abra una carpeta.", + "canNotResolveFile": "'{0}' no puede resolver. Por favor, abra un editor.", + "canNotResolveLineNumber": "' {0} ' no se puede resolver. Asegúrese de tener una línea seleccionada en el editor activo.", + "canNotResolveSelectedText": "' {0} ' no se puede resolver. Asegúrese de tener un texto seleccionado en el editor activo." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/esn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..f78002ce65 --- /dev/null +++ b/i18n/esn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Sí", + "cancelButton": "Cancelar" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/esn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index ac4ba0d686..863b2a88b8 100644 --- a/i18n/esn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/esn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Compatibilidad del motor.", "vscode.extension.engines.vscode": "Para las extensiones de VS Code, especifica la versión de VS Code con la que la extensión es compatible. No puede ser *. Por ejemplo: ^0.10.5 indica compatibilidad con una versión de VS Code mínima de 0.10.5.", "vscode.extension.publisher": "El publicador de la extensión VS Code.", "vscode.extension.displayName": "Nombre para mostrar de la extensión que se usa en la galería de VS Code.", "vscode.extension.categories": "Categorías que usa la galería de VS Code para clasificar la extensión.", + "vscode.extension.category.languages.deprecated": "Utilice 'Lenguajes de programación' en su lugar ", "vscode.extension.galleryBanner": "Banner usado en VS Code Marketplace.", "vscode.extension.galleryBanner.color": "Color del banner en el encabezado de página de VS Code Marketplace.", "vscode.extension.galleryBanner.theme": "Tema de color de la fuente que se usa en el banner.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Un evento de activación emitido cada vez que esté a punto de ser iniciada una sesión de depuración con el tipo específico (y se necesite llamar al método resolveDebugConfiguration correspondiente).", "vscode.extension.activationEvents.workspaceContains": "Un evento de activación emitido cada vez que se abre una carpeta que contiene al menos un archivo que coincide con el patrón global especificado.", "vscode.extension.activationEvents.onView": "Un evento de activación emitido cada vez que se expande la vista especificada.", + "vscode.extension.activationEvents.onUri": "Se emite un evento de activación siempre cuando se abre un identificador URI de todo el sistema dirigido hacia esta extensión.", "vscode.extension.activationEvents.star": "Un evento de activación emitido al inicio de VS Code. Para garantizar una buena experiencia para el usuario final, use este evento de activación en su extensión solo cuando no le sirva ninguna otra combinación de eventos de activación en su caso.", "vscode.extension.badges": "Matriz de distintivos que se muestran en la barra lateral de la página de extensiones de Marketplace.", "vscode.extension.badges.url": "URL de la imagen del distintivo.", "vscode.extension.badges.href": "Vínculo del distintivo.", "vscode.extension.badges.description": "Descripción del distintivo.", + "vscode.extension.markdown": "Controla el motor de renderizado de Markdown utilizado en el Marketplace. Github (por defecto) o estándar.", + "vscode.extension.qna": "Controla el enlace Q&A en el Marketplace. Establézcalo a marketplace para habilitar el sitio web Q&A de Marketplace. Establézcalo a una cadena para proporcionar la dirección URL de un sitio web Q&A personalizado. Establézcalo en falso para deshabilitar el Q&A totalmente. ", "vscode.extension.extensionDependencies": "Dependencias a otras extensiones. El identificador de una extensión siempre es ${publisher}.${name}. Por ejemplo: vscode.csharp.", "vscode.extension.scripts.prepublish": "Script que se ejecuta antes de publicar el paquete como extensión VS Code.", "vscode.extension.scripts.uninstall": "Enlace de desinstalación para la extensión de VS Code. Script que se ejecuta cuando la extensión se ha desinstalado por completo de VS Code, que es cuando VS Code se reinicia (se cierra y se inicia) después de haberse desinstalado la extensión. Solo se admiten scripts de Node.", diff --git a/i18n/esn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/esn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 3a69b5c0ad..eadbe2502f 100644 --- a/i18n/esn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Todas las extensiones están deshabilitadas.", "extensionHostProcess.crash": "El host de extensiones finalizó inesperadamente.", "extensionHostProcess.unresponsiveCrash": "Se terminó el host de extensiones porque no respondía.", - "devTools": "Herramientas de desarrollo", + "devTools": "Herramientas de desarrollo abiertas", "restart": "Reiniciar el host de extensiones", "overwritingExtension": "Sobrescribiendo la extensión {0} con {1}.", "extensionUnderDevelopment": "Cargando la extensión de desarrollo en {0}", diff --git a/i18n/esn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/esn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index cac6f98472..36c012260a 100644 --- a/i18n/esn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Requiere Microsoft .NET Framework 4.5. Siga el vínculo para instalarlo.", "installNet": "Descargar .NET Framework 4.5", "neverShowAgain": "No volver a mostrar", - "netVersionError": "Requiere Microsoft .NET Framework 4.5. Siga el vínculo para instalarlo.", + "enospcError": "{0} es incapaz de observar los cambios de los archivos en este espacio de trabajo tan grande. Por favor siga las instrucciones en el link para resolver este problema.", "learnMore": "Instrucciones", - "enospcError": "{0} está a punto de agotar los identificadores de archivo. Por favor siga el enlace de instrucciones para resolver este problema.", + "fileInvalidPath": "Recurso de archivo no válido ({0})", + "fileIsDirectoryError": "El archivo es un directorio", + "fileNotModifiedError": "Archivo no modificado desde", + "fileTooLargeForHeapError": "Para abrir un archivo de este tamaño, es necesario reiniciar VS Code y permitirle utilizar más memoria", + "fileTooLargeError": "Archivo demasiado grande para abrirlo", + "fileNotFoundError": "Archivo no encontrado ({0})", + "fileBinaryError": "El archivo parece ser binario y no se puede abrir como texto", + "filePermission": "Permiso denegado al escribir en el archivo ({0})", + "fileExists": "El archivo a crear ya existe ({0})", + "fileModifiedError": "Archivo Modificado Desde", + "fileReadOnlyError": "El archivo es de solo lectura", + "fileMoveConflict": "No se puede mover o copiar. El archivo ya existe en la ubicación de destino. ", + "unableToMoveCopyError": "No se puede mover o copiar. El archivo reemplazaría a la carpeta que lo contiene.", "binFailed": "No se pudo mover \"{0}\" a la papelera de reciclaje", "trashFailed": "No se pudo mover '{0}' a la papelera" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index a527ee3d78..e20141624d 100644 --- a/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Archivo no encontrado ({0})", "fileIsDirectoryError": "El archivo es un directorio", "fileNotModifiedError": "Archivo no modificado desde", - "fileBinaryError": "El archivo parece ser binario y no se puede abrir como texto" + "fileBinaryError": "El archivo parece ser binario y no se puede abrir como texto", + "err.create": "No se pudo crear el archivo {0}", + "fileMoveConflict": "No se puede mover o copiar. El archivo ya existe en la ubicación de destino. " } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/esn/src/vs/workbench/services/progress/browser/progressService2.i18n.json index 7da6218aa9..e5812ea732 100644 --- a/i18n/esn/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/esn/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1} ", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Cancelar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 078095db28..4886d7b9ac 100644 --- a/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Nombre del ámbito de TextMate que usa el archivo tmLanguage.", "vscode.extension.contributes.grammars.path": "Ruta de acceso del archivo tmLanguage. La ruta es relativa a la carpeta de extensión y normalmente empieza por \"./syntaxes/\".", "vscode.extension.contributes.grammars.embeddedLanguages": "Asignación de un nombre de ámbito al identificador de lenguaje si esta gramática contiene lenguajes incrustados.", + "vscode.extension.contributes.grammars.tokenTypes": "Asignación de nombre de ámbito a tipos de token.", "vscode.extension.contributes.grammars.injectTo": "Lista de nombres de ámbito de lenguaje al que se inyecta esta gramática." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 0e26acb50f..b38093323d 100644 --- a/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/esn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "Se esperaba una cadena en \"contributes.{0}.path\". Valor proporcionado: {1}", "invalid.injectTo": "Valor no válido en `contributes.{0}.injectTo`. Debe ser una matriz de nombres de ámbito de lenguaje. Valor proporcionado: {1}", "invalid.embeddedLanguages": "Valor no válido en \"contributes.{0}.embeddedLanguages\". Debe ser una asignación de objeto del nombre del ámbito al lenguaje. Valor proporcionado: {1}", + "invalid.tokenTypes": "Valor no válido en \"contributes.{0}.tokenTypes\". Debe ser una asignación de objeto del nombre del ámbito al tipo de token. Valor proporcionado: {1}", "invalid.path.1": "Se esperaba que \"contributes.{0}.path\" ({1}) se incluyera en la carpeta de la extensión ({2}). Esto puede hacer que la extensión no sea portátil.", "no-tm-grammar": "No hay ninguna gramática de TM registrada para este lenguaje." } \ No newline at end of file diff --git a/i18n/fra/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/fra/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..56a7e4e867 --- /dev/null +++ b/i18n/fra/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "Serveur de langage CSS", + "folding.start": "Début de la région repliable", + "folding.end": "Fin de la région repliable" +} \ No newline at end of file diff --git a/i18n/fra/extensions/css-language-features/package.i18n.json b/i18n/fra/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..8ce650a48c --- /dev/null +++ b/i18n/fra/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Fonctionnalités de langage CSS", + "description": "Fournit une prise en charge riche de langage pour les fichiers CSS, LESS et SCSS", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", + "css.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", + "css.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", + "css.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", + "css.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", + "css.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", + "css.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", + "css.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", + "css.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", + "css.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", + "css.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", + "css.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", + "css.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", + "css.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", + "css.lint.unknownProperties.desc": "Propriété inconnue.", + "css.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", + "css.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", + "css.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", + "css.trace.server.desc": "Trace la communication entre VS Code et le serveur de langage CSS.", + "css.validate.title": "Contrôle la validation CSS et la gravité des problèmes.", + "css.validate.desc": "Active ou désactive toutes les validations", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", + "less.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", + "less.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", + "less.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", + "less.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", + "less.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", + "less.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", + "less.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", + "less.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", + "less.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", + "less.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", + "less.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", + "less.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", + "less.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", + "less.lint.unknownProperties.desc": "Propriété inconnue.", + "less.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", + "less.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", + "less.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", + "less.validate.title": "Contrôle la validation LESS et la gravité des problèmes.", + "less.validate.desc": "Active ou désactive toutes les validations", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", + "scss.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", + "scss.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", + "scss.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", + "scss.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", + "scss.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", + "scss.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", + "scss.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", + "scss.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", + "scss.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", + "scss.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", + "scss.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", + "scss.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", + "scss.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", + "scss.lint.unknownProperties.desc": "Propriété inconnue.", + "scss.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", + "scss.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", + "scss.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", + "scss.validate.title": "Contrôle la validation SCSS et la gravité des problèmes.", + "scss.validate.desc": "Active ou désactive toutes les validations", + "less.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", + "scss.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", + "css.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", + "css.colorDecorators.enable.deprecationMessage": "Le paramètre 'css.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'.", + "scss.colorDecorators.enable.deprecationMessage": "Le paramètre 'scss.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'.", + "less.colorDecorators.enable.deprecationMessage": "Le paramètre 'less.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'." +} \ No newline at end of file diff --git a/i18n/fra/extensions/css/package.i18n.json b/i18n/fra/extensions/css/package.i18n.json index 33b37cb487..46288c0f4a 100644 --- a/i18n/fra/extensions/css/package.i18n.json +++ b/i18n/fra/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Fonctionnalités de langage CSS", - "description": "Fournit une prise en charge riche de langage pour les fichiers CSS, LESS et SCSS", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", - "css.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", - "css.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", - "css.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", - "css.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", - "css.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", - "css.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", - "css.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", - "css.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", - "css.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", - "css.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", - "css.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", - "css.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", - "css.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", - "css.lint.unknownProperties.desc": "Propriété inconnue.", - "css.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", - "css.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", - "css.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", - "css.trace.server.desc": "Trace la communication entre VS Code et le serveur de langage CSS.", - "css.validate.title": "Contrôle la validation CSS et la gravité des problèmes.", - "css.validate.desc": "Active ou désactive toutes les validations", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", - "less.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", - "less.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", - "less.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", - "less.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", - "less.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", - "less.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", - "less.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", - "less.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", - "less.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", - "less.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", - "less.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", - "less.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", - "less.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", - "less.lint.unknownProperties.desc": "Propriété inconnue.", - "less.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", - "less.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", - "less.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", - "less.validate.title": "Contrôle la validation LESS et la gravité des problèmes.", - "less.validate.desc": "Active ou désactive toutes les validations", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Nombre de paramètres non valide", - "scss.lint.boxModel.desc": "Ne pas utiliser la largeur ou la hauteur avec une marge intérieure ou une bordure", - "scss.lint.compatibleVendorPrefixes.desc": "Lors de l'utilisation d'un préfixe spécifique à un fabricant, toujours inclure également toutes les propriétés spécifiques au fabricant", - "scss.lint.duplicateProperties.desc": "Ne pas utiliser de définitions de style en double", - "scss.lint.emptyRules.desc": "Ne pas utiliser d'ensembles de règles vides", - "scss.lint.float.desc": "N'utilisez pas 'float'. Les éléments Float peuvent fragiliser le code CSS qui est ainsi plus vulnérable si un aspect de la disposition change.", - "scss.lint.fontFaceProperties.desc": "la règle @font-face doit définir les propriétés 'src' et 'font-family'", - "scss.lint.hexColorLength.desc": "Les couleurs Hex doivent contenir trois ou six chiffres hex", - "scss.lint.idSelector.desc": "Les sélecteurs ne doivent pas contenir d'ID, car ces règles sont trop fortement couplées au code HTML.", - "scss.lint.ieHack.desc": "Les hacks IE ne sont nécessaires que si IE7 et versions antérieures sont pris en charge", - "scss.lint.important.desc": "N'utilisez pas !important. Cela indique que la spécificité de l'intégralité du code CSS est incorrecte et qu'il doit être refactorisé.", - "scss.lint.importStatement.desc": "Les instructions d'importation ne sont pas chargées en parallèle", - "scss.lint.propertyIgnoredDueToDisplay.desc": "Propriété ignorée en raison de l'affichage. Par exemple, avec 'display: inline', les propriétés width, height, margin-top, margin-bottom et float sont sans effet", - "scss.lint.universalSelector.desc": "Le sélecteur universel (*) est connu pour sa lenteur", - "scss.lint.unknownProperties.desc": "Propriété inconnue.", - "scss.lint.unknownVendorSpecificProperties.desc": "Propriété spécifique à un fournisseur inconnue.", - "scss.lint.vendorPrefix.desc": "Lors de l'utilisation d'un préfixe spécifique à un fournisseur, ajouter également la propriété standard", - "scss.lint.zeroUnits.desc": "Aucune unité nécessaire pour zéro", - "scss.validate.title": "Contrôle la validation SCSS et la gravité des problèmes.", - "scss.validate.desc": "Active ou désactive toutes les validations", - "less.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", - "scss.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", - "css.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", - "css.colorDecorators.enable.deprecationMessage": "Le paramètre 'css.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'.", - "scss.colorDecorators.enable.deprecationMessage": "Le paramètre 'scss.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'.", - "less.colorDecorators.enable.deprecationMessage": "Le paramètre 'less.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'." + "displayName": "Bases du langage CSS", + "description": "Fournit la coloration syntaxique et la correspondance des parenthèses dans les fichiers CSS, LESS et SCSS." } \ No newline at end of file diff --git a/i18n/fra/extensions/emmet/package.i18n.json b/i18n/fra/extensions/emmet/package.i18n.json index 9c1e6ff3d1..6dfb09a4b7 100644 --- a/i18n/fra/extensions/emmet/package.i18n.json +++ b/i18n/fra/extensions/emmet/package.i18n.json @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Chemin d’accès au dossier contenant les profils Emmet et les extraits.", "emmetShowExpandedAbbreviation": "Affiche les abréviations Emmet développées sous forme de suggestions.\nL’option \"inMarkupAndStylesheetFilesOnly\" s’applique à haml, jade, slim, xml, xsl, css, html, scss, sass, less et stylus.\nL’option\"always\" s’applique à toutes les parties du fichier indépendamment du balisage/css.", "emmetShowAbbreviationSuggestions": "Affiche les abréviations Emmet possibles sous forme de suggestions. Non applicable dans les feuilles de style ou lorsque emmet.showExpandedAbbreviation est défini à \"never\".", - "emmetIncludeLanguages": "Activer les abréviations Emmet dans les langages qui ne sont pas pris en charge par défaut. Ajouter ici un mappage entre le langage et le langage Emmet pris en charge.\n Par exemple : {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "Activer les abréviations Emmet dans les langages qui ne sont pas pris en charge par défaut. Ajoutez un mappage ici entre la langue et le langage supporté par emmet.\n Par exemple : {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "Variables à utiliser dans les extraits de Emmet", "emmetTriggerExpansionOnTab": "Lorsqu’activé, les abréviations Emmet sont développées lorsque vous appuyez sur TAB.", "emmetPreferences": "Préférences utilisées pour modifier le comportement de certaines actions et résolveurs d'Emmet.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Les propriétés css séparées par des virgules qui ont un préfixe 'webkit' vendor lorsqu’elles sont utilisées dans une abréviation emmet qui commence par '-'. Mettre une chaîne vide pour éviter le préfixe 'webkit'.", "emmetPreferencesCssMozProperties": "Les propriétés css séparées par des virgules qui ont un préfixe 'moz' vendor lorsqu’elles sont utilisées dans une abréviation emmet qui commence par '-'. Mettre une chaîne vide pour éviter le préfixe 'moz'.", "emmetPreferencesCssOProperties": "Les propriétés css séparées par des virgules qui ont un préfixe 'o' vendor lorsqu’elles sont utilisées dans une abréviation emmet qui commence par '-'. Mettre une chaîne vide pour éviter le préfixe 'o'.", - "emmetPreferencesCssMsProperties": "Les propriétés css séparées par des virgules qui ont un préfixe 'ms' vendor lorsqu’elles sont utilisées dans une abréviation emmet qui commence par '-'. Mettre une chaîne vide pour éviter le préfixe 'ms'." + "emmetPreferencesCssMsProperties": "Les propriétés css séparées par des virgules qui ont un préfixe 'ms' vendor lorsqu’elles sont utilisées dans une abréviation emmet qui commence par '-'. Mettre une chaîne vide pour éviter le préfixe 'ms'.", + "emmetPreferencesCssFuzzySearchMinScore": "La note minimale (de 0 à 1) que la correspondance de l'abréviation (fuzzy-matched) devrait atteindre. Des valeurs plus faibles peuvent produire de nombreuses correspondances de faux-positifs, des valeurs plus élevées peuvent réduire les correspondances possibles.", + "emmetOptimizeStylesheetParsing": "Si défini à false, la fichier entier est analysé pour déterminer si la position courante est valide pour l’expansion des abréviations Emmet. Si défini à true, seul le contenu autour de la position actuelle dans les fichiers css/scss/less est analysé." } \ No newline at end of file diff --git a/i18n/fra/extensions/git/out/commands.i18n.json b/i18n/fra/extensions/git/out/commands.i18n.json index dbcaf03544..6a7204c50a 100644 --- a/i18n/fra/extensions/git/out/commands.i18n.json +++ b/i18n/fra/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Créer nouvelle branche", "repourl": "URL du dépôt", "parent": "Répertoire parent", - "cancel": "$(sync~spin) Clonage du dépôt... Cliquer pour annuler", - "cancel tooltip": "Annuler le clonage", - "cloning": "Clonage du dépôt git...", + "cloning": "Clonage du dépôt Git '{0}'...", "openrepo": "Ouvrir le dépôt", "proposeopen": "Voulez-vous ouvrir le dépôt cloné ?", "init": "Choisir le dossier d’espace de travail dans lequel initialiser le dépôt git", @@ -75,7 +73,7 @@ "ok": "OK", "push with tags success": "Envoyé (push) avec des balises.", "pick remote": "Choisissez un dépôt distant où publier la branche '{0}' :", - "sync is unpredictable": "Cette action effectue un transfert (Push) et un tirage (Pull) des validations à destination et en provenance de '{0}'.", + "sync is unpredictable": "Cette action va effectuer un transfert (Push) et une récupération (Pull) des commits à destination et en provenance de '{0}/{1}'.", "never again": "OK, Ne plus afficher", "no remotes to publish": "Votre dépôt n'a aucun dépôt distant configuré pour une publication.", "no changes stash": "Aucune modification à remiser (stash).", diff --git a/i18n/fra/extensions/git/package.i18n.json b/i18n/fra/extensions/git/package.i18n.json index fdb68628e7..c6002051f9 100644 --- a/i18n/fra/extensions/git/package.i18n.json +++ b/i18n/fra/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Contrôle s’il faut afficher une action Ouvrir le fichier dans l’affichage des modifications de Git.", "config.inputValidation": "Contrôle quand afficher la validation de la saisie du message de commit.", "config.detectSubmodules": "Contrôle s’il faut détecter automatiquement les sous-modules git.", + "config.detectSubmodulesLimit": "Contrôle la limite de sous-modules git détectés.", "colors.modified": "Couleur pour les ressources modifiées.", "colors.deleted": "Couleur pour les ressources supprimées.", "colors.untracked": "Couleur pour les ressources non tracées.", diff --git a/i18n/fra/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/fra/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..9d334931d1 --- /dev/null +++ b/i18n/fra/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "Serveur de langage HTML", + "folding.start": "Début de la région repliable", + "folding.end": "Fin de la région repliable" +} \ No newline at end of file diff --git a/i18n/fra/extensions/html-language-features/package.i18n.json b/i18n/fra/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..d94c280aaa --- /dev/null +++ b/i18n/fra/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Fonctionnalités de langage HTML", + "description": "Fournit une prise en charge riche de langage pour HTML, Razor et les fichiers Handlebar.", + "html.format.enable.desc": "Activer/désactiver le formateur HTML par défaut.", + "html.format.wrapLineLength.desc": "Nombre maximal de caractères par ligne (0 = désactiver).", + "html.format.unformatted.desc": "Liste des balises, séparées par des virgules, qui ne doivent pas être remises en forme. 'null' correspond par défaut à toutes les balises répertoriées à l'adresse https://www.w3.org/TR/html5/dom.html#phrasing-content.", + "html.format.contentUnformatted.desc": "Liste des balises, séparées par des virgules, dont le contenu ne doit pas être remis en forme. 'null' correspond par défaut à toutes les balises 'pre'.", + "html.format.indentInnerHtml.desc": "Mettez en retrait les sections <head> et <body>.", + "html.format.preserveNewLines.desc": "Spécifie si les sauts de ligne existants qui précèdent les éléments doivent être conservés. Fonctionne uniquement devant les éléments, pas dans les balises, ni pour du texte.", + "html.format.maxPreserveNewLines.desc": "Nombre maximal de sauts de ligne à conserver dans un bloc. Utilisez 'null' pour indiquer une valeur illimitée.", + "html.format.indentHandlebars.desc": "Mettez en forme et en retrait {{#foo}}, ainsi que {{/foo}}.", + "html.format.endWithNewline.desc": "Finissez par un caractère de nouvelle ligne.", + "html.format.extraLiners.desc": "Liste de balises, séparées par une virgule, qui doivent être précédées d'une nouvelle ligne. 'null' prend par défaut la valeur \"head, body, /html\".", + "html.format.wrapAttributes.desc": "Retour à la ligne des attributs.", + "html.format.wrapAttributes.auto": "Retour automatique à la ligne des attributs uniquement en cas de dépassement de la longueur de la ligne.", + "html.format.wrapAttributes.force": "Retour automatique à la ligne de chaque attribut, sauf le premier.", + "html.format.wrapAttributes.forcealign": "Retour automatique à la ligne de chaque attribut, sauf le premier, avec maintien de l'alignement.", + "html.format.wrapAttributes.forcemultiline": "Retour automatique à la ligne de chaque attribut.", + "html.suggest.angular1.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises et propriétés Angular V1.", + "html.suggest.ionic.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises, des propriétés et des valeurs Ionic.", + "html.suggest.html5.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises, des propriétés et des valeurs HTML5.", + "html.trace.server.desc": "Trace la communication entre VS Code et le serveur de langage HTML.", + "html.validate.scripts": "Configure la validation des scripts incorporés par la prise en charge du langage HTML intégré.", + "html.validate.styles": "Configure la validation des styles incorporés par la prise en charge du langage HTML intégré.", + "html.autoClosingTags": "Activez/désactivez la fermeture automatique des balises HTML." +} \ No newline at end of file diff --git a/i18n/fra/extensions/html/package.i18n.json b/i18n/fra/extensions/html/package.i18n.json index f20d3d1575..e2a03b6fd5 100644 --- a/i18n/fra/extensions/html/package.i18n.json +++ b/i18n/fra/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Fonctionnalités de langage HTML", - "description": "Fournit une prise en charge riche de langage pour HTML, Razor et les fichiers Handlebar.", - "html.format.enable.desc": "Activer/désactiver le formateur HTML par défaut.", - "html.format.wrapLineLength.desc": "Nombre maximal de caractères par ligne (0 = désactiver).", - "html.format.unformatted.desc": "Liste des balises, séparées par des virgules, qui ne doivent pas être remises en forme. 'null' correspond par défaut à toutes les balises répertoriées à l'adresse https://www.w3.org/TR/html5/dom.html#phrasing-content.", - "html.format.contentUnformatted.desc": "Liste des balises, séparées par des virgules, dont le contenu ne doit pas être remis en forme. 'null' correspond par défaut à toutes les balises 'pre'.", - "html.format.indentInnerHtml.desc": "Mettez en retrait les sections <head> et <body>.", - "html.format.preserveNewLines.desc": "Spécifie si les sauts de ligne existants qui précèdent les éléments doivent être conservés. Fonctionne uniquement devant les éléments, pas dans les balises, ni pour du texte.", - "html.format.maxPreserveNewLines.desc": "Nombre maximal de sauts de ligne à conserver dans un bloc. Utilisez 'null' pour indiquer une valeur illimitée.", - "html.format.indentHandlebars.desc": "Mettez en forme et en retrait {{#foo}}, ainsi que {{/foo}}.", - "html.format.endWithNewline.desc": "Finissez par un caractère de nouvelle ligne.", - "html.format.extraLiners.desc": "Liste de balises, séparées par une virgule, qui doivent être précédées d'une nouvelle ligne. 'null' prend par défaut la valeur \"head, body, /html\".", - "html.format.wrapAttributes.desc": "Retour à la ligne des attributs.", - "html.format.wrapAttributes.auto": "Retour automatique à la ligne des attributs uniquement en cas de dépassement de la longueur de la ligne.", - "html.format.wrapAttributes.force": "Retour automatique à la ligne de chaque attribut, sauf le premier.", - "html.format.wrapAttributes.forcealign": "Retour automatique à la ligne de chaque attribut, sauf le premier, avec maintien de l'alignement.", - "html.format.wrapAttributes.forcemultiline": "Retour automatique à la ligne de chaque attribut.", - "html.suggest.angular1.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises et propriétés Angular V1.", - "html.suggest.ionic.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises, des propriétés et des valeurs Ionic.", - "html.suggest.html5.desc": "Permet de configurer la prise en charge intégrée du langage HTML pour suggérer des balises, des propriétés et des valeurs HTML5.", - "html.trace.server.desc": "Trace la communication entre VS Code et le serveur de langage HTML.", - "html.validate.scripts": "Configure la validation des scripts incorporés par la prise en charge du langage HTML intégré.", - "html.validate.styles": "Configure la validation des styles incorporés par la prise en charge du langage HTML intégré.", - "html.experimental.syntaxFolding": "Active/désactive les marqueurs de réduction en fonction de la syntaxe.", - "html.autoClosingTags": "Activez/désactivez la fermeture automatique des balises HTML." + "displayName": "Notions de base du langage HTML", + "description": "Fournit la coloration syntaxique, la correspondance des balises d'ouverture et de fermeture et des extraits de code dans les fichiers HTML." } \ No newline at end of file diff --git a/i18n/fra/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/fra/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..bd80392eb0 --- /dev/null +++ b/i18n/fra/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "Serveur de langage JSON" +} \ No newline at end of file diff --git a/i18n/fra/extensions/json-language-features/package.i18n.json b/i18n/fra/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..9b182858ce --- /dev/null +++ b/i18n/fra/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Fonctionnalités de langage JSON", + "description": "Fournit une prise en charge de langage pour les fichiers JSON", + "json.schemas.desc": "Associer les schémas aux fichiers JSON dans le projet actif", + "json.schemas.url.desc": "URL de schéma ou chemin relatif d'un schéma dans le répertoire actif", + "json.schemas.fileMatch.desc": "Tableau de modèles de fichiers pour la recherche de correspondances durant la résolution de fichiers JSON en schémas.", + "json.schemas.fileMatch.item.desc": "Modèle de fichier pouvant contenir '*' pour la recherche de correspondances durant la résolution de fichiers JSON en schémas.", + "json.schemas.schema.desc": "Définition de schéma pour l'URL indiquée. Le schéma doit être fourni uniquement pour éviter les accès à l'URL du schéma.", + "json.format.enable.desc": "Activer/désactiver le formateur JSON par défaut (nécessite un redémarrage)", + "json.tracing.desc": "Trace la communication entre VS Code et le serveur de langage JSON.", + "json.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", + "json.colorDecorators.enable.deprecationMessage": "Le paramètre 'json.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'." +} \ No newline at end of file diff --git a/i18n/fra/extensions/json/package.i18n.json b/i18n/fra/extensions/json/package.i18n.json index d21e00e6f6..cce12b474a 100644 --- a/i18n/fra/extensions/json/package.i18n.json +++ b/i18n/fra/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Fonctionnalités de langage JSON", - "description": "Fournit une prise en charge de langage pour les fichiers JSON", - "json.schemas.desc": "Associer les schémas aux fichiers JSON dans le projet actif", - "json.schemas.url.desc": "URL de schéma ou chemin relatif d'un schéma dans le répertoire actif", - "json.schemas.fileMatch.desc": "Tableau de modèles de fichiers pour la recherche de correspondances durant la résolution de fichiers JSON en schémas.", - "json.schemas.fileMatch.item.desc": "Modèle de fichier pouvant contenir '*' pour la recherche de correspondances durant la résolution de fichiers JSON en schémas.", - "json.schemas.schema.desc": "Définition de schéma pour l'URL indiquée. Le schéma doit être fourni uniquement pour éviter les accès à l'URL du schéma.", - "json.format.enable.desc": "Activer/désactiver le formateur JSON par défaut (nécessite un redémarrage)", - "json.tracing.desc": "Trace la communication entre VS Code et le serveur de langage JSON.", - "json.colorDecorators.enable.desc": "Active ou désactive les éléments décoratifs de couleurs", - "json.colorDecorators.enable.deprecationMessage": "Le paramètre 'json.colorDecorators.enable' a été déprécié en faveur de 'editor.colorDecorators'.", - "json.experimental.syntaxFolding": "Active/désactive les marqueurs de réduction en fonction de la syntaxe." + "displayName": "Bases du langage JSON", + "description": "Fournit la coloration syntaxique et la correspondance des parenthèses dans les fichiers JSON." } \ No newline at end of file diff --git a/i18n/fra/extensions/markdown-basics/package.i18n.json b/i18n/fra/extensions/markdown-basics/package.i18n.json index 9613c9e793..cc2cb10952 100644 --- a/i18n/fra/extensions/markdown-basics/package.i18n.json +++ b/i18n/fra/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/fra/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/fra/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..69d5cb1c1f --- /dev/null +++ b/i18n/fra/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "Impossible de charger 'markdown.styles' : {0}" +} \ No newline at end of file diff --git a/i18n/fra/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/fra/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..9e9f654e2f --- /dev/null +++ b/i18n/fra/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Aperçu] {0}", + "previewTitle": "Prévisualiser {0}" +} \ No newline at end of file diff --git a/i18n/fra/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/fra/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..38a6bf3c24 --- /dev/null +++ b/i18n/fra/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Du contenu a été désactivé dans ce document", + "preview.securityMessage.title": "Le contenu potentiellement dangereux ou précaire a été désactivé dans l’aperçu du format markdown. Modifier le paramètre de sécurité Aperçu Markdown afin d’autoriser les contenus non sécurisés ou activer les scripts", + "preview.securityMessage.label": "Avertissement de sécurité de contenu désactivé" +} \ No newline at end of file diff --git a/i18n/fra/extensions/markdown-language-features/out/security.i18n.json b/i18n/fra/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..a6eb76789a --- /dev/null +++ b/i18n/fra/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Strict", + "strict.description": "Charger uniquement le contenu sécurisé.", + "insecureLocalContent.title": "Autoriser le contenu local non sécurisé", + "insecureLocalContent.description": "Activer le chargement de contenu http servi par localhost", + "insecureContent.title": "Autoriser le contenu non sécurisé", + "insecureContent.description": "Activer le chargement de contenu sur http", + "disable.title": "Désactiver", + "disable.description": "Autorisez tout le contenu et l’exécution des scripts. Non recommandé", + "moreInfo.title": "Informations", + "enableSecurityWarning.title": "Activer l'aperçu d'avertissements de sécurité pour cet espace de travail", + "disableSecurityWarning.title": "Désactiver l'aperçu d'avertissements de sécurité pour cet espace de travail", + "toggleSecurityWarning.description": "N'affecte pas le niveau de sécurité de contenu", + "preview.showPreviewSecuritySelector.title": "Sélectionner les paramètres de sécurité pour les aperçus Markdown dans cet espace de travail" +} \ No newline at end of file diff --git a/i18n/fra/extensions/markdown-language-features/package.i18n.json b/i18n/fra/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..f5aede8507 --- /dev/null +++ b/i18n/fra/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Fonctionnalités de langage Markdown", + "description": "Fournit une prise en charge riche de langage pour Markdown", + "markdown.preview.breaks.desc": "Définit l'affichage des sauts de ligne dans l'aperçu Markdown. Si la valeur est 'true', crée un <br> pour chaque nouvelle ligne.", + "markdown.preview.linkify": "Activez ou désactivez la conversion de texte de type URL en liens dans l’aperçu Markdown.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Double-cliquez dans l'aperçu Markdown pour passer à l'éditeur.", + "markdown.preview.fontFamily.desc": "Contrôle la famille de polices utilisée dans l'aperçu Markdown.", + "markdown.preview.fontSize.desc": "Contrôle la taille de police en pixels utilisée dans l'aperçu Markdown.", + "markdown.preview.lineHeight.desc": "Contrôle la hauteur de ligne utilisée dans l'aperçu Markdown. Ce nombre est relatif à la taille de police.", + "markdown.preview.markEditorSelection.desc": "Permet de marquer la sélection actuelle de l'éditeur dans l'aperçu Markdown.", + "markdown.preview.scrollEditorWithPreview.desc": "Lors du défilement de l'aperçu markdown, actualiser l’affichage de l’éditeur.", + "markdown.preview.scrollPreviewWithEditor.desc": "Lors du défilement d’un éditeur markdow, actualiser l’affichage de l’aperçu.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Déprécié] Fait défiler l'aperçu Markdown pour révéler la ligne actuellement sélectionnée dans l'éditeur.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Ce paramètre a été remplacé par 'markdown.preview.scrollPreviewWithEditor' et n'a plus aucun effet.", + "markdown.preview.title": "Ouvrir l'aperçu", + "markdown.previewFrontMatter.dec": "Définit comment les pages liminaires YAML doivent être affichées dans l'aperçu Markdown. L'option 'hide' supprime les pages liminaires. Sinon, elles sont traitées comme du contenu Markdown.", + "markdown.previewSide.title": "Ouvrir l'aperçu sur le côté", + "markdown.showLockedPreviewToSide.title": "Ouvrir l'aperçu verrrouillé sur le côté", + "markdown.showSource.title": "Afficher la source", + "markdown.styles.dec": "Liste d'URL ou de chemins locaux de feuilles de style CSS à utiliser dans l'aperçu Markdown. Les chemins relatifs sont interprétés par rapport au dossier ouvert dans l'explorateur. S'il n'y a aucun dossier ouvert, ils sont interprétés par rapport à l'emplacement du fichier Markdown. Tous les signes '\\' doivent être écrits sous la forme '\\\\'.", + "markdown.showPreviewSecuritySelector.title": "Changer les paramètres de sécurité de l'aperçu", + "markdown.trace.desc": "Active la journalisation du débogage pour l'extension Markdown.", + "markdown.preview.refresh.title": "Actualiser l'aperçu", + "markdown.preview.toggleLock.title": "Activer/désactiver le verrouillage de l'aperçu" +} \ No newline at end of file diff --git a/i18n/fra/extensions/markdown/out/features/preview.i18n.json b/i18n/fra/extensions/markdown/out/features/preview.i18n.json index d22af9c6b9..9e9f654e2f 100644 --- a/i18n/fra/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/fra/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/fra/extensions/npm/out/npmView.i18n.json b/i18n/fra/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..164e1b51e3 --- /dev/null +++ b/i18n/fra/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "Impossible de lancer \"{0}\" pour le débogage, car les scripts n'ont pas d'option de débogage de nœud, par exemple, \"--inspect-brk\".", + "npm.scriptInvalid": "Script \"{0}\" introuvable. Essayez d'actualiser la vue." +} \ No newline at end of file diff --git a/i18n/fra/extensions/npm/out/tasks.i18n.json b/i18n/fra/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..18fa5992ad --- /dev/null +++ b/i18n/fra/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Détection de tâche Npm : impossible d’analyser le fichier {0}" +} \ No newline at end of file diff --git a/i18n/fra/extensions/npm/package.i18n.json b/i18n/fra/extensions/npm/package.i18n.json index 6c575d42fa..b85f2981ff 100644 --- a/i18n/fra/extensions/npm/package.i18n.json +++ b/i18n/fra/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "Exécutez les commandes npm avec l'option `--silent`.", "config.npm.packageManager": "Le gestionnaire de paquets utilisé pour exécuter des scripts.", "config.npm.exclude": "Configurer les profils glob pour les dossiers qui doivent être exclus de la détection de script automatique.", + "config.npm.enableScriptExplorer": "Activez une vue Explorateur pour les scripts npm quand l'espace de travail contient un fichier 'package.json'.", "npm.parseError": "Détection de tâche Npm : impossible d’analyser le fichier {0}", "taskdef.script": "Le script npm à personnaliser.", - "taskdef.path": "Le chemin d’accès au dossier du fichier package.json qui fournit le script. Peut être oublié." + "taskdef.path": "Le chemin d’accès au dossier du fichier package.json qui fournit le script. Peut être oublié.", + "view.name": "Scripts npm", + "command.refresh": "Actualiser", + "command.run": "Exécuter", + "command.debug": "Déboguer", + "command.openScript": "Ouvrir", + "npm.scriptInvalid": "Script '{0}' introuvable. Essayez d'actualiser la vue.", + "npm.noDebugOptions": "Impossible de lancer '{0}' pour le débogage, car les scripts n'ont pas d'option de débogage de nœud, par exemple, '--inspect-brk'." } \ No newline at end of file diff --git a/i18n/fra/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/fra/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..b20a0679e6 --- /dev/null +++ b/i18n/fra/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Autorisez-vous l'exécution de {0} (défini en tant que paramètre d'espace de travail) pour effectuer une validation lint sur les fichiers PHP ?", + "php.yes": "Autoriser", + "php.no": "Interdire", + "wrongExecutable": "Impossible d'effectuer la validation, car {0} n'est pas un exécutable PHP valide. Utilisez le paramètre 'php.validate.executablePath' pour configurer l'exécutable PHP.", + "noExecutable": "Impossible d'effectuer la validation, car aucun exécutable PHP n'est défini. Utilisez le paramètre 'php.validate.executablePath' pour configurer l'exécutable PHP.", + "unknownReason": "Échec de l'exécution de php avec le chemin : {0}. Raison inconnue." +} \ No newline at end of file diff --git a/i18n/fra/extensions/php-language-features/package.i18n.json b/i18n/fra/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..6070999895 --- /dev/null +++ b/i18n/fra/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Configure l'activation ou la désactivation des suggestions de langage PHP intégrées. La fonctionnalité de prise en charge suggère les variables globales et les variables de session PHP.", + "configuration.validate.enable": "Activez/désactivez la validation PHP intégrée.", + "configuration.validate.executablePath": "Pointe vers l'exécutable PHP.", + "configuration.validate.run": "Spécifie si linter est exécuté au moment de l'enregistrement ou de la saisie.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "Interdire l'exécutable de validation PHP (défini comme paramètre d'espace de travail)", + "displayName": "Fonctionnalités de langage PHP", + "description": "Fournit une prise en charge de langage riche pour les fichiers PHP." +} \ No newline at end of file diff --git a/i18n/fra/extensions/php/package.i18n.json b/i18n/fra/extensions/php/package.i18n.json index ff6f1381f9..2b1f86c123 100644 --- a/i18n/fra/extensions/php/package.i18n.json +++ b/i18n/fra/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Configure l'activation ou la désactivation des suggestions de langage PHP intégrées. La fonctionnalité de prise en charge suggère les variables globales et les variables de session PHP.", - "configuration.validate.enable": "Activez/désactivez la validation PHP intégrée.", - "configuration.validate.executablePath": "Pointe vers l'exécutable PHP.", - "configuration.validate.run": "Spécifie si linter est exécuté au moment de l'enregistrement ou de la saisie.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "Interdire l'exécutable de validation PHP (défini comme paramètre d'espace de travail)", - "displayName": "Fonctionnalités du langage PHP", - "description": "Fournit IntelliSense, le linting et les concepts de base de langage pour les fichiers PHP." + "displayName": "Bases du langage PHP", + "description": "Fournit la coloration syntaxique et la correspondance des parenthèses dans les fichiers PHP." } \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/commands.i18n.json b/i18n/fra/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..1738a01dc8 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Ouvrez un dossier dans VS Code pour utiliser un projet TypeScript ou JavaScript", + "typescript.projectConfigUnsupportedFile": "Impossible de déterminer le projet TypeScript ou JavaScript. Type de fichier non pris en charge", + "typescript.projectConfigCouldNotGetInfo": "Impossible de déterminer le projet TypeScript ou JavaScript", + "typescript.noTypeScriptProjectConfig": "Le fichier ne fait pas partie d'un projet TypeScript. Cliquer [ici]({0}) pour en savoir plus.", + "typescript.noJavaScriptProjectConfig": "Le fichier ne fait pas partie d'un projet JavaScript. Cliquer [ici]({0}) pour en savoir plus.", + "typescript.configureTsconfigQuickPick": "Configurer tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurer jsconfig.json" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..a9b06927dc --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Sélectionner l'action de code à appliquer", + "acquiringTypingsLabel": "Acquisition des typings...", + "acquiringTypingsDetail": "Acquisition des définitions typings pour IntelliSense.", + "autoImportLabel": "Importation automatique depuis {0}" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..8096453313 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Active la vérification sémantique dans un fichier JavaScript. Doit se trouver au début d'un fichier.", + "ts-nocheck": "Désactive la vérification sémantique dans un fichier JavaScript. Doit se trouver au début d'un fichier.", + "ts-ignore": "Supprime les erreurs @ts-check sur la ligne suivante d'un fichier." +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..2e7856eb1b --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 implémentation", + "manyImplementationLabel": "{0} implémentations", + "implementationsErrorLabel": "Impossible de déterminer les implémentations" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..7915d99dbd --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "Commentaire JSDoc" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..064e933aa6 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Organiser les Imports" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..f10b35e9e5 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Corriger tout dans le fichier)" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..927ba6cdb7 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 référence", + "manyReferenceLabel": "{0} références", + "referenceErrorLabel": "Impossible de déterminer les références" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..451f7029ba --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "build - {0}", + "buildAndWatchTscLabel": "watch - {0}" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/fra/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..f31ff437ec --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "Le chemin {0} ne pointe pas vers une installation tsserver valide. Utilisation par défaut de la version TypeScript groupée.", + "serverCouldNotBeStarted": "Impossible de démarrer le serveur de langage TypeScript. Message d'erreur : {0}", + "typescript.openTsServerLog.notSupported": "La journalisation du serveur TS nécessite TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "La journalisation du serveur TS est désactivée. Définissez 'typescript.tsserver.log' et redémarrez le serveur TS pour activer la journalisation", + "typescript.openTsServerLog.enableAndReloadOption": "Activer la journalisation et redémarrer le serveur TS", + "typescript.openTsServerLog.noLogFile": "Le serveur TS n'a pas démarré la journalisation.", + "openTsServerLog.openFileFailedFailed": "Impossible d'ouvrir le fichier journal du serveur TS", + "serverDiedAfterStart": "Le service de langage TypeScript s'est subitement arrêté 5 fois juste après avoir démarré. Il n'y aura pas d'autres redémarrages.", + "serverDiedReportIssue": "Signaler un problème", + "serverDied": "Le service de langage TypeScript s'est subitement arrêté 5 fois au cours des 5 dernières minutes." +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..61ed0b6012 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "version non valide" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..b39c51e947 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Pour activer les fonctionnalités de langage JavaScript/TypeScript à l'échelle du projet, excluez les dossiers contenant de nombreux fichiers, par exemple : {0}", + "hintExclude.generic": "Pour activer les fonctionnalités de langage JavaScript/TypeScript à l'échelle du projet, excluez les dossiers volumineux contenant des fichiers sources inutilisés.", + "large.label": "Configurer les exclusions", + "hintExclude.tooltip": "Pour activer les fonctionnalités de langage JavaScript/TypeScript à l'échelle du projet, excluez les dossiers volumineux contenant des fichiers sources inutilisés." +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..108ea8e9d3 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Récupération (fetch) des données pour l'amélioration de TypeScript IntelliSense", + "typesInstallerInitializationFailed.title": "Impossible d'installer des fichiers de typages pour les fonctionnalités de langage JavaScript. Vérifiez que NPM est installé ou configurez 'typescript.npm' dans vos paramètres utilisateur. Cliquer [ici]({0}) pour en savoir plus.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Ne plus afficher" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..c6da9b3843 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Utiliser la version de VS Code", + "useWorkspaceVersionOption": "Utiliser la version de l'espace de travail", + "learnMore": "En savoir plus", + "selectTsVersion": "Sélectionner la version TypeScript utilisée pour les fonctionnalités de langage JavaScript et TypeScript" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/fra/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..5c32ecfe10 --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Impossible de charger la version TypeScript dans ce chemin", + "noBundledServerFound": "Le tsserver de VSCode a été supprimé par une autre application, par exemple, un outil de détection de virus mal configuré. Réinstallez VS Code." +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript-language-features/package.i18n.json b/i18n/fra/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..a84454b66c --- /dev/null +++ b/i18n/fra/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Fonctionnalités de langage TypeScript et JavaScript", + "description": "Fournit une prise en charge riche de langage pour JavaScript et TypeScript.", + "typescript.reloadProjects.title": "Recharger le projet", + "javascript.reloadProjects.title": "Recharger le projet", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Fonctions complètes avec leur signature de paramètre.", + "typescript.tsdk.desc": "Spécifie le chemin de dossier contenant les fichiers tsserver et lib*.d.ts à utiliser.", + "typescript.disableAutomaticTypeAcquisition": "Désactive l'acquisition de type automatique. Nécessite TypeScript >= 2.0.6.", + "typescript.tsserver.log": "Active la journalisation du serveur TS dans un fichier. Ce journal peut être utilisé pour diagnostiquer les problèmes du serveur TS. Il peut contenir des chemins de fichier, du code source et d'autres informations potentiellement sensibles de votre projet.", + "typescript.tsserver.pluginPaths": "Chemins d’accès supplémentaires pour découvrir les plugins de Service de langage Typescript. Nécessite TypeScript > = 2.3.0.", + "typescript.tsserver.pluginPaths.item": "Un chemin absolu ou un chemin relatif. Le chemin d’accès relatif sera résolu en fonction des dossiers de l’espace de travail.", + "typescript.tsserver.trace": "Active le traçage des messages envoyés au serveur TS. Cette trace peut être utilisée pour diagnostiquer les problèmes du serveur TS. Elle peut contenir des chemins de fichier, du code source et d'autres informations potentiellement sensibles de votre projet.", + "typescript.validate.enable": "Activez/désactivez la validation TypeScript.", + "typescript.format.enable": "Activez/désactivez le formateur TypeScript par défaut.", + "javascript.format.enable": "Activez/désactivez le formateur JavaScript par défaut.", + "format.insertSpaceAfterCommaDelimiter": "Définit le traitement des espaces après une virgule de délimitation.", + "format.insertSpaceAfterConstructor": "Définit le traitement des espaces après le mot clé constructor. Nécessite TypeScript >= 2.3.0.", + "format.insertSpaceAfterSemicolonInForStatements": " Définit le traitement des espaces après un point-virgule dans une instruction for.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Définit le traitement des espaces après un opérateur binaire.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Définit la gestion des espaces après les mots clés dans une instruction de flux de contrôle.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Définit le traitement des espaces après le mot clé function pour les fonctions anonymes.", + "format.insertSpaceBeforeFunctionParenthesis": "Définit la gestion des espaces avant les parenthèses des arguments d'une fonction. Nécessite TypeScript >= 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Définit l’espace après ouverture et avant la fermeture de parenthèses non vides.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Définit l’espace après ouverture et avant la fermeture de crochets non vides.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Définit l’espace après ouverture et avant la fermeture d'accolades non vides. Nécessite le TypeScript >= 2.3.0.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Définit la gestion de l'espace après l'ouverture et avant la fermeture des accolades de la chaîne de modèle. Nécessite TypeScript >= 2.0.6.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Définit la gestion de l'espace après l'ouverture et avant la fermeture des accolades de l'expression JSX. Nécessite TypeScript >= 2.0.6.", + "format.insertSpaceAfterTypeAssertion": "Définit le traitement des espaces après les assertions de type dans TypeScript. Nécessite TypeScript >= 2.4.", + "format.placeOpenBraceOnNewLineForFunctions": "Définit si une accolade ouvrante dans une fonction est placée ou non sur une nouvelle ligne.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Définit si une accolade ouvrante dans un bloc de contrôle est placée ou non sur une nouvelle ligne.", + "javascript.validate.enable": "Activez/désactivez la validation JavaScript.", + "typescript.goToProjectConfig.title": "Accéder à la configuration du projet", + "javascript.goToProjectConfig.title": "Accéder à la configuration du projet", + "javascript.referencesCodeLens.enabled": "Activez/désactivez les références CodeLens dans les fichiers JavaScript.", + "typescript.referencesCodeLens.enabled": "Activez/désactivez les références CodeLens dans les fichiers TypeScript. Nécessite TypeScript >= 2.0.6.", + "typescript.implementationsCodeLens.enabled": "Activer/désactiver CodeLens dans les implémentations. Nécessite TypeScript >= 2.2.0.", + "typescript.openTsServerLog.title": "Ouvrir le journal du serveur TS", + "typescript.restartTsServer": "Redémarrer le serveur TS", + "typescript.selectTypeScriptVersion.title": "Sélectionner la version de TypeScript", + "typescript.reportStyleChecksAsWarnings": "Rapporter les vérifications de style comme des avertissements", + "jsDocCompletion.enabled": "Activer/désactiver les commentaires JSDoc automatiques", + "javascript.implicitProjectConfig.checkJs": "Activer/désactiver la vérification sémantique des fichiers JavaScript. Les fichiers jsconfig.json ou tsconfig.json existants remplacent ce paramètre. Nécessite TypeScript >=2.3.1.", + "typescript.npm": "Spécifie le chemin de l'exécutable NPM utilisé pour l'acquisition de type automatique. Nécessite TypeScript >= 2.3.4.", + "typescript.check.npmIsInstalled": "Vérifie si NPM est installé pour l'acquisition de type automatique.", + "javascript.nameSuggestions": "Activez/désactivez l'inclusion de noms uniques à partir du fichier dans les listes de suggestions JavaScript.", + "typescript.tsc.autoDetect": "Contrôle la détection automatique des tâches tsc. 'off' désactive cette fonctionnalité. 'build' crée uniquement des tâches de compilation à exécution unique. 'watch' crée uniquement des tâches de compilation et de watch. 'on' crée les deux les tâches build et watch. La valeur par défaut est 'on'.", + "typescript.problemMatchers.tsc.label": "Problèmes liés à TypeScript", + "typescript.problemMatchers.tscWatch.label": "Problèmes liés à TypeScript (mode espion)", + "typescript.quickSuggestionsForPaths": "Activer/désactiver les suggestions rapides lorsque vous saisissez un chemin d’import.", + "typescript.locale": "Définit les paramètres locaux utilisés pour signaler les erreurs TypeScript . Nécessite TypeScript >= 2.6.0. Par défaut 'null' utilise les paramètres locaux de VS Code pour les erreurs TypeScript.", + "javascript.implicitProjectConfig.experimentalDecorators": "Activer/désactiver 'experimentalDecorators' pour les fichiers JavaScript qui ne font pas partie d'un projet. Les fichiers jsconfig.json ou tsconfig.json existants remplacent ce paramètre. Nécessite TypeScript >=2.3.1.", + "typescript.autoImportSuggestions.enabled": "Activer/désactiver les suggestions d'import automatiques. Nécessite TypeScript >= 2.6.1.", + "typescript.experimental.syntaxFolding": "Active/désactive les marqueurs de réduction en fonction de la syntaxe.", + "taskDefinition.tsconfig.description": "Fichier tsconfig qui définit la build TS.", + "javascript.suggestionActions.enabled": "Activer/désactiver le diagnostic de suggestion des fichiers JavaScript dans l’éditeur. Nécessite TypeScript > = 2.8", + "typescript.suggestionActions.enabled": "Activer/désactiver les diagnostics de suggestion pour les fichiers TypeScript dans l’éditeur de texte. Nécessite TypeScript > = 2.8." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/base/node/processes.i18n.json b/i18n/fra/src/vs/base/node/processes.i18n.json index 5cc1e691e5..bf26eba5b2 100644 --- a/i18n/fra/src/vs/base/node/processes.i18n.json +++ b/i18n/fra/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "Impossible d'exécuter une commande d'interpréteur de commandes sur un lecteur UNC." + "TaskRunner.UNC": "Impossible d’exécuter une commande shell sur un lecteur UNC." } \ No newline at end of file diff --git a/i18n/fra/src/vs/base/node/zip.i18n.json b/i18n/fra/src/vs/base/node/zip.i18n.json index 11465d3066..4aa157cd51 100644 --- a/i18n/fra/src/vs/base/node/zip.i18n.json +++ b/i18n/fra/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Incomplète. {0} sur {1} entrées extraites", "notFound": "{0} introuvable dans le zip." } \ No newline at end of file diff --git a/i18n/fra/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/fra/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index fb412e3629..4c54af6f18 100644 --- a/i18n/fra/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/fra/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "Prévisualiser sur GitHub", "loadingData": "Chargement des données en cours...", + "rateLimited": "Limite de requête GitHub dépassée. Veuillez patienter.", "similarIssues": "Problèmes similaires", "open": "Ouvrir", "closed": "Fermé", - "noResults": "Résultats introuvables", + "noSimilarIssues": "Aucun problème similaire trouvé", "settingsSearchIssue": "Problème de paramètres de recherche", "bugReporter": "Rapporteur de bogue", - "performanceIssue": "Problème de performance", "featureRequest": "Demande de fonctionnalité", + "performanceIssue": "Problème de performance", "stepsToReproduce": "Étapes à reproduire", "bugDescription": "Partagez les étapes nécessaires pour reproduire fidèlement le problème. Veuillez inclure les résultats réels et prévus. Nous prenons en charge la syntaxe GitHub Markdown. Vous pourrez éditer votre problème et ajouter des captures d'écran lorsque nous le prévisualiserons sur GitHub.", "performanceIssueDesciption": "Quand ce problème de performance s'est-il produit ? Se produit-il au démarrage ou après une série d'actions spécifiques ? Nous prenons en charge la syntaxe Markdown de GitHub. Vous pourrez éditer votre problème et ajouter des captures d'écran lorsque nous le prévisualiserons sur GitHub.", diff --git a/i18n/fra/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/fra/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index f5fd62234a..f18659a614 100644 --- a/i18n/fra/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/fra/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Veuillez remplir le formulaire en anglais.", "issueTypeLabel": "Ceci est un ", + "issueSourceLabel": "Fichier sur", + "vscode": "Visual Studio Code", + "extension": "Une Extension", + "disableExtensionsLabelText": "Essayez de reproduire le problème après {0}. Si le problème se reproduit uniquement lorsque les extensions sont actives, c’est probablement un problème avec une extension.", + "disableExtensions": "en désactivant toutes les extensions et en rechargeant la fenêtre", + "chooseExtension": "Extension", "issueTitleLabel": "Titre", "issueTitleRequired": "Veuillez s’il vous plaît entrer un titre.", "titleLengthValidation": "Le titre est trop long.", @@ -18,13 +24,6 @@ "extensions": "Mes Extensions", "searchedExtensions": "Extensions recherchées", "settingsSearchDetails": "Détails de paramètres de recherche", - "tryDisablingExtensions": "Le problème est-il reproductible lorsque les extensions sont désactivées?", - "yes": "Oui", - "no": "Non", - "disableExtensionsLabelText": "Essayez de reproduire le problème après {0}.", - "disableExtensions": "en désactivant toutes les extensions et en rechargeant la fenêtre", - "showRunningExtensionsLabelText": "Si vous pensez que c'est un problème d'extension, {0} pour reporter le problème de l'extension.", - "showRunningExtensions": "Afficher toutes les extensions en cours d'exécution", "details": "Veuillez saisir les détails ", "loadingData": "Chargement des données..." } \ No newline at end of file diff --git a/i18n/fra/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/fra/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..9eedc8116f --- /dev/null +++ b/i18n/fra/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "% PROCESSEUR", + "memory": "Mémoire (Mo)", + "pid": "pid", + "name": "Nom", + "killProcess": "Tuer le processus", + "forceKillProcess": "Forcer la suppression du processus" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/code/electron-main/menus.i18n.json b/i18n/fra/src/vs/code/electron-main/menus.i18n.json index ff18044743..bb8cc03e54 100644 --- a/i18n/fra/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/fra/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "Point d'arrêt &&conditionnel...", "miColumnBreakpoint": "P&&oint d'arrêt de la colonne", "miFunctionBreakpoint": "Point d'arrêt sur &&fonction...", + "miLogPoint": "&&Point de journalisation...", "miNewBreakpoint": "&&Nouveau point d'arrêt", "miEnableAllBreakpoints": "Activer tous les points d'arrêt", "miDisableAllBreakpoints": "Désacti&&ver tous les points d'arrêt", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Fusionner toutes les fenêtres", "miToggleDevTools": "Activer/désactiver les ou&&tils de développement", "miAccessibilityOptions": "&&Options d'accessibilité", + "miOpenProcessExplorerer": "Ouvrir l'Explorateur de &&Processus", "miReportIssue": "Signaler un problème", "miWelcome": "&&Bienvenue", "miInteractivePlayground": "Terrain de jeu &&interactif", diff --git a/i18n/fra/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/fra/src/vs/editor/browser/widget/diffReview.i18n.json index bc2bf2e666..b85a26c3a7 100644 --- a/i18n/fra/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/fra/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Fermer", - "header": "Différence {0} sur {1} : {2} d'origine, {3} lignes, {4} modifiées, {5} lignes", + "no_lines": "aucune ligne", + "one_line": "1 ligne", + "more_lines": "{0} lignes", + "header": "Différence {0} sur {1} : original {2}, {3}, modifié {4}, {5}", "blankLine": "vide", "equalLine": "{0} d'origine, {1} modifiées : {2}", "insertLine": "+ {0} modifiées : {1}", diff --git a/i18n/fra/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/fra/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..973f68f522 --- /dev/null +++ b/i18n/fra/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "Le nombre de curseurs a été limité à {0}." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json index 9a40c9f6e2..0d6073bf2c 100644 --- a/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "Les numéros de ligne sont affichés en nombre absolu.", "lineNumbers.relative": "Les numéros de ligne sont affichés sous la forme de distance en lignes à la position du curseur.", "lineNumbers.interval": "Les numéros de ligne sont affichés toutes les 10 lignes.", - "lineNumbers": "Contrôle l’affichage des numéros de ligne. Les valeurs possibles sont 'on', 'off', 'relative' et 'interval'.", + "lineNumbers": "Contrôle l’affichage des numéros de ligne.", "rulers": "Afficher les règles verticales après un certain nombre de caractères à espacement fixe. Utiliser plusieurs valeurs pour plusieurs règles. Aucune règle n'est dessinée si le tableau est vide", "wordSeparators": "Caractères utilisés comme séparateurs de mots durant la navigation ou les opérations basées sur les mots", "tabSize": "Le nombre d'espaces correspondant à une tabulation. Ce paramètre est remplacé en fonction du contenu du fichier quand 'editor.detectIndentation' est activé.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Contrôle si l'éditeur défile au-delà de la dernière ligne", "smoothScrolling": "Contrôle si l'éditeur défilera en utilisant une animation", "minimap.enabled": "Contrôle si la minicarte est affichée", - "minimap.side": "Contrôle le côté où afficher la minicarte. Les valeurs possibles sont 'right' et 'left'", - "minimap.showSlider": "Contrôle si le curseur de la minicarte est automatiquement masqué. Les valeurs possibles sont 'always' et 'mouseover'", + "minimap.side": "Contrôle le côté où afficher la minicarte.", + "minimap.showSlider": "Contrôle si le curseur de la minicarte est automatiquement masqué", "minimap.renderCharacters": "Afficher les caractères réels sur une ligne (par opposition aux blocs de couleurs)", "minimap.maxColumn": "Limiter la largeur de la minicarte pour afficher au maximum un certain nombre de colonnes", "find.seedSearchStringFromSelection": "Contrôle si nous remplissons la chaîne à rechercher dans le Widget Recherche à partir de la sélection de l'éditeur", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans macOS.", "multiCursorModifier.alt": "Mappe vers 'Alt' dans Windows et Linux, et vers 'Option' dans macOS.", "multiCursorModifier": "Le modificateur à utiliser pour ajouter plusieurs curseurs avec la souris. 'ctrlCmd' mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans macOS. Les mouvements de souris Accéder à la définition et Ouvrir le lien s'adaptent pour ne pas entrer en conflit avec le modificateur multicurseur.", + "multiCursorMergeOverlapping": "Fusionnez plusieurs curseurs quand ils se chevauchent.", "quickSuggestions.strings": "Activez les suggestions rapides dans les chaînes.", "quickSuggestions.comments": "Activez les suggestions rapides dans les commentaires.", "quickSuggestions.other": "Activez les suggestions rapides en dehors des chaînes et des commentaires.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Contrôle si l'éditeur doit mettre en surbrillance les occurrences de symboles sémantiques", "overviewRulerLanes": "Contrôle le nombre d'ornements pouvant s'afficher à la même position dans la règle d'aperçu", "overviewRulerBorder": "Contrôle si une bordure doit être dessinée autour de la règle d'aperçu.", - "cursorBlinking": "Contrôle le style d'animation du curseur. Valeurs possibles : 'blink', 'smooth', 'phase', 'expand' et 'solid'", + "cursorBlinking": "Contrôler le style d’animation du curseur.", "mouseWheelZoom": "Agrandir ou réduire la police de l'éditeur quand l'utilisateur fait tourner la roulette de la souris tout en maintenant la touche Ctrl enfoncée", "cursorStyle": "Contrôle le style du curseur. Les valeurs acceptées sont 'block', 'block-outline', 'line', 'line-thin', 'underline' et 'underline-thin'", "cursorWidth": "Contrôle la largeur du curseur quand editor.cursorStyle est à 'line'", @@ -86,8 +87,11 @@ "renderControlCharacters": "Contrôle si l'éditeur doit afficher les caractères de contrôle", "renderIndentGuides": "Contrôle si l'éditeur doit afficher les repères de mise en retrait", "renderLineHighlight": "Contrôle la façon dont l'éditeur doit afficher la surbrillance de la ligne active. Les différentes possibilités sont 'none', 'gutter', 'line' et 'all'.", - "codeLens": "Contrôle si l'éditeur affiche les indicateurs CodeLens", + "codeLens": "Contrôle si l’éditeur affiche CodeLens", "folding": "Contrôle si le pliage de code est activé dans l'éditeur", + "foldingStrategyAuto": "Si disponible, utilisez une stratégie de présentation langage-spécifique, sinon la stratégie d'indentation s'applique.", + "foldingStrategyIndentation": "Utilisez toujours l'indentation basée sur la stratégie de présentation", + "foldingStrategy": "Contrôle la façon dont les repliages sont calculées. 'auto' utilise une stratégie repliage spécifique au langage, si disponible. 'indentation' force à ce que la stratégie de repliage basée sur l'indentation soit utilisée.", "showFoldingControls": "Définit si les contrôles de réduction sur la bordure sont cachés automatiquement", "matchBrackets": "Met en surbrillance les crochets correspondants quand l'un d'eux est sélectionné.", "glyphMargin": "Contrôle si l'éditeur doit afficher la marge de glyphes verticale. La marge de glyphes sert principalement au débogage.", @@ -102,8 +106,12 @@ "links": "Contrôle si l'éditeur doit détecter les liens et les rendre cliquables", "colorDecorators": "Contrôle si l'éditeur doit afficher les éléments décoratifs de couleurs inline et le sélecteur de couleurs.", "codeActions": "Active l'ampoule d'action de code", + "codeActionsOnSave.organizeImports": "Exécuter organiser les importations lors de l'enregistrement ?", + "codeActionsOnSave": "Types d'action de code à exécuter à l'enregistrement.", + "codeActionsOnSaveTimeout": "Délai d'attente pour les actions de code exécutées lors de l'enregistrement.", "selectionClipboard": "Contrôle si le presse-papiers primaire Linux doit être pris en charge.", "sideBySide": "Contrôle si l'éditeur de différences affiche les différences en mode côte à côte ou inline", "ignoreTrimWhitespace": "Contrôle si l'éditeur de différences affiche les changements liés aux espaces blancs de début ou de fin comme des différences", + "largeFileOptimizations": "Traitement spécial des fichiers volumineux pour désactiver certaines fonctionnalités utilisant beaucoup de mémoire.", "renderIndicators": "Contrôle si l'éditeur de différences affiche les indicateurs +/- pour les modifications ajoutées/supprimées" } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json index cb7e2c2864..0803b85863 100644 --- a/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "La couleur de fond du curseur de l'éditeur. Permet de personnaliser la couleur d'un caractère survolé par un curseur de bloc.", "editorWhitespaces": "Couleur des espaces blancs dans l'éditeur.", "editorIndentGuides": "Couleur des repères de retrait de l'éditeur.", + "editorActiveIndentGuide": "Couleur des guides d'indentation de l'éditeur actif", "editorLineNumbers": "Couleur des numéros de ligne de l'éditeur.", "editorActiveLineNumber": "Couleur des numéros de lignes actives de l'éditeur", + "deprecatedEditorActiveLineNumber": "Id est obsolète. Utilisez à la place 'editorLineNumber.activeForeground'. ", "editorRuler": "Couleur des règles de l'éditeur", "editorCodeLensForeground": "Couleur pour les indicateurs CodeLens", "editorBracketMatchBackground": "Couleur d'arrière-plan pour les accolades associées", @@ -28,7 +30,9 @@ "warningBorder": "Couleur de bordure de la ligne ondulée marquant les avertissements dans l'éditeur.", "infoForeground": "Couleur de premier plan de la ligne ondulée marquant les informations dans l'éditeur.", "infoBorder": "Couleur de bordure de la ligne ondulée marquant les informations dans l'éditeur.", - "overviewRulerRangeHighlight": "Couleur du marqueur de la règle d'aperçu pour la mise en évidence de plage.", + "hintForeground": "Couleur de premier plan de la ligne ondulée d'indication dans l'éditeur.", + "hintBorder": "Couleur de bordure de la ligne ondulée d'indication dans l'éditeur.", + "overviewRulerRangeHighlight": "Couleur du marqueur de la règle d'aperçu pour des plages mises en surbrillance. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous.", "overviewRuleError": "Couleur du marqueur de la règle d'aperçu pour les erreurs.", "overviewRuleWarning": "Couleur du marqueur de la règle d'aperçu pour les avertissements.", "overviewRuleInfo": "Couleur du marqueur de la règle d'aperçu pour les informations." diff --git a/i18n/fra/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/fra/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..f04b6d1316 --- /dev/null +++ b/i18n/fra/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Afficher les correctifs ({0})", + "quickFix": "Afficher les correctifs", + "quickfix.trigger.label": "Correction rapide...", + "editor.action.quickFix.noneMessage": "Aucune action de code disponible", + "refactor.label": "Remanier...", + "editor.action.refactor.noneMessage": "Aucune refactorisation disponible", + "source.label": "Action de la source", + "editor.action.source.noneMessage": "Aucune action n'est disponible", + "organizeImports.label": "Organiser les Imports", + "editor.action.organize.noneMessage": "Aucune action organiser les imports disponible" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/find/findController.i18n.json b/i18n/fra/src/vs/editor/contrib/find/findController.i18n.json index e5d9eba6eb..8a56c99849 100644 --- a/i18n/fra/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Rechercher", + "startFindWithSelectionAction": "Trouver avec la sélection", "findNextMatchAction": "Rechercher suivant", "findPreviousMatchAction": "Rechercher précédent", "nextSelectionMatchFindAction": "Sélection suivante", diff --git a/i18n/fra/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/fra/src/vs/editor/contrib/format/formatActions.i18n.json index a306a0bec7..96a470bdc6 100644 --- a/i18n/fra/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "{0} modifications de format effectuées entre les lignes {1} et {2}", "no.provider": "Il n’y a aucun formateur installé pour les fichiers '{0}'.", "formatDocument.label": "Mettre en forme le document", - "formatSelection.label": "Mettre en forme la sélection" + "no.documentprovider": "Il n’y a aucun formateur de document installé pour les fichiers '{0}'.", + "formatSelection.label": "Mettre en forme la sélection", + "no.selectionprovider": "Il n’y a aucun formateur de sélection installé pour les fichiers '{0}'." } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 664f234cae..57419ec313 100644 --- a/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Aller au problème suivant (Erreur, Avertissement, Info)", - "markerAction.previous.label": "Aller au problème précédent (Erreur, Avertissement, Info)", - "editorMarkerNavigationError": "Couleur d'erreur du widget de navigation dans les marqueurs de l'éditeur.", - "editorMarkerNavigationWarning": "Couleur d'avertissement du widget de navigation dans les marqueurs de l'éditeur.", - "editorMarkerNavigationInfo": "Couleur d’information du widget de navigation du marqueur de l'éditeur.", - "editorMarkerNavigationBackground": "Arrière-plan du widget de navigation dans les marqueurs de l'éditeur." + "markerAction.previous.label": "Aller au problème précédent (Erreur, Avertissement, Info)" } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/fra/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..9d9cfafff3 --- /dev/null +++ b/i18n/fra/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Couleur d'erreur du widget de navigation dans les marqueurs de l'éditeur.", + "editorMarkerNavigationWarning": "Couleur d'avertissement du widget de navigation dans les marqueurs de l'éditeur.", + "editorMarkerNavigationInfo": "Couleur d’information du widget de navigation du marqueur de l'éditeur.", + "editorMarkerNavigationBackground": "Arrière-plan du widget de navigation dans les marqueurs de l'éditeur." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/links/links.i18n.json b/i18n/fra/src/vs/editor/contrib/links/links.i18n.json index fedf7d63e1..f4f2199736 100644 --- a/i18n/fra/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "Ctrl + clic pour suivre le lien", "links.command.mac": "Cmd + clic pour exécuter la commande", "links.command": "Ctrl + clic pour exécuter la commande", + "links.navigate.al.mac": "Option + clic pour suivre le lien", "links.navigate.al": "Alt + clic pour suivre le lien", + "links.command.al.mac": "Option + clic pour exécuter la commande", "links.command.al": "Alt + clic pour exécuter la commande", "invalid.url": "Échec de l'ouverture de ce lien, car il n'est pas bien formé : {0}", "missing.url": "Échec de l'ouverture de ce lien, car sa cible est manquante.", diff --git a/i18n/fra/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/fra/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..8f37ab47ec --- /dev/null +++ b/i18n/fra/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Impossible de modifier dans l’éditeur en lecture seule" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/fra/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 13c37d1e3e..153e791b1e 100644 --- a/i18n/fra/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Couleur d'arrière-plan de l'éditeur d'affichage d'aperçu.", "peekViewEditorGutterBackground": "Couleur d'arrière-plan de la bordure de l'éditeur d'affichage d'aperçu.", "peekViewResultsMatchHighlight": "Couleur de mise en surbrillance d'une correspondance dans la liste des résultats de l'affichage d'aperçu.", - "peekViewEditorMatchHighlight": "Couleur de mise en surbrillance d'une correspondance dans l'éditeur de l'affichage d'aperçu." + "peekViewEditorMatchHighlight": "Couleur de mise en surbrillance d'une correspondance dans l'éditeur de l'affichage d'aperçu.", + "peekViewEditorMatchHighlightBorder": "Bordure de mise en surbrillance d'une correspondance dans l'éditeur de l'affichage d'aperçu." } \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/fra/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..5b27a515c9 --- /dev/null +++ b/i18n/fra/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Dimanche", + "Monday": "Lundi", + "Tuesday": "Mardi", + "Wednesday": "Mercredi", + "Thursday": "Jeudi", + "Friday": "Vendredi", + "Saturday": "Samedi", + "SundayShort": "Dim", + "MondayShort": "Lun", + "TuesdayShort": "Mar", + "WednesdayShort": "Mer", + "ThursdayShort": "Jeu", + "FridayShort": "Ven", + "SaturdayShort": "Sam", + "January": "Janvier", + "February": "Février", + "March": "Mars", + "April": "Avril", + "May": "Mai", + "June": "Juin", + "July": "Juillet", + "August": "Août", + "September": "Septembre", + "October": "Octobre", + "November": "Novembre", + "December": "Décembre", + "JanuaryShort": "Jan", + "FebruaryShort": "Fév", + "MarchShort": "Mar", + "AprilShort": "Avr", + "MayShort": "Mai", + "JuneShort": "Jun", + "JulyShort": "Jul", + "AugustShort": "Aoû", + "SeptemberShort": "Sep", + "OctoberShort": "Oct", + "NovemberShort": "Nov", + "DecemberShort": "Déc" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 4659ff38bf..aeccdb60ce 100644 --- a/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Couleur d'arrière-plan d'un symbole durant l'accès en écriture, par exemple l'écriture dans une variable. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", "wordHighlightBorder": "Couleur de bordure d'un symbole durant l'accès en lecture, par exemple la lecture d'une variable.", "wordHighlightStrongBorder": "Couleur de bordure d'un symbole durant l'accès en écriture, par exemple l'écriture dans une variable.", - "overviewRulerWordHighlightForeground": "Couleur du marqueur de la règle d'aperçu pour la mise en évidence de symbole.", - "overviewRulerWordHighlightStrongForeground": "Couleur du marqueur de la règle d'aperçu la mise en évidence de symbole d’accès en écriture.", + "overviewRulerWordHighlightForeground": "Couleur du marqueur de la règle d'aperçu pour les mises en surbrillance de symbole. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous.", + "overviewRulerWordHighlightStrongForeground": "Couleur du marqueur de la règle d'aperçu pour les mises en surbrillance de symbole d'accès en écriture. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous.", "wordHighlight.next.label": "Aller à la prochaine mise en évidence de symbole", "wordHighlight.previous.label": "Aller à la mise en évidence de symbole précédente" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/fra/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..40bf02755c --- /dev/null +++ b/i18n/fra/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 fichier supplémentaire non affiché", + "moreFiles": "...{0} fichiers supplémentaires non affichés" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/fra/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..2f086ccc7a --- /dev/null +++ b/i18n/fra/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Annuler" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/environment/node/argv.i18n.json b/i18n/fra/src/vs/platform/environment/node/argv.i18n.json index 293e40fe31..0e80c9ad22 100644 --- a/i18n/fra/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/fra/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "Affichez les versions des extensions installées, quand --list-extension est utilisé.", "installExtension": "Installe une extension.", "uninstallExtension": "Désinstalle une extension.", - "experimentalApis": "Active les fonctionnalités d'API proposées pour une extension.", + "experimentalApis": "Active les fonctionnalités de l’API proposées pour une extension.", "verbose": "Affichez la sortie détaillée (implique --wait).", "log": "Niveau de journalisation à utiliser. La valeur par défaut est 'info'. Les valeurs autorisées sont 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off.", "status": "Imprimer l'utilisation de processus et l'information des diagnostics.", "performance": "Démarrez avec la commande 'Développeur : performance de démarrage' activée.", "prof-startup": "Exécuter le profileur d'UC au démarrage", "disableExtensions": "Désactivez toutes les extensions installées.", - "inspect-extensions": "Autorise le débogage et le profilage des extensions. Vérifier les outils de développements pour l'uri de connexion.", - "inspect-brk-extensions": "Autorise le débogage et le profilage des extensions avec l'hôte d'extensions en pause après le démarrage. Vérifier les outils de développement pour l'uri de connexion.", + "inspect-extensions": "Permettre le débogage et le profilage d’extensions. Vérifier les outils de développement pour l'URI de connexion.", + "inspect-brk-extensions": "Permettre le débogage et le profilage d’extensions avec l’hôte de l’extension étant suspendu après le démarrage. Vérifier les outils de développement pour l'URI de connexion.", "disableGPU": "Désactivez l'accélération matérielle du GPU.", "uploadLogs": "Upload les logs depuis la session actuelle vers le endpoint sécurisé.", "maxMemory": "Taille mémoire maximale pour une fenêtre (En Megaoctêts)", diff --git a/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index d021614186..a975f63332 100644 --- a/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Extension non valide : package.json n'est pas un fichier JSON.", + "incompatible": "Impossible d’installer l’Extension '{0}' car elle n’est pas compatible avec VS Code '{1}'.", "restartCode": "Redémarrez Code avant de réinstaller {0}.", "installingOutdatedExtension": "Une version plus récente de cette extension est déjà installée. Voulez-vous remplacer celle-ci avec l'ancienne version ?", "override": "Remplacer", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Erreur lors de l'installation des dépendances. {0}", "MarketPlaceDisabled": "Le marketplace n’est pas activé", "removeError": "Erreur lors de la suppression de l’extension : {0}. Veuillez quitter et relancer VS Code avant de réessayer.", - "Not Market place extension": "Seules les Extensions de Marketplace peuvent être réinstallées", + "Not a Marketplace extension": "Seules les Extensions de Marketplace peuvent être réinstallées", "notFoundCompatible": "Impossible d’installer '{0}'; Il n’y a pas de version disponible compatible avec VS Code '{1}'.", "malicious extension": "Impossible d’installer l'extension car elle a été signalée comme problématique.", "notFoundCompatibleDependency": "Installation impossible car l'extension dépendante '{0}' compatible avec la version actuelle '{1}' de VS Code est introuvable.", "quitCode": "Impossible d’installer l’extension. Veuillez s’il vous plaît quitter et redémarrer VS Code avant de le réinstaller.", "exitCode": "Impossible d’installer l’extension. Veuillez s’il vous plaît sortir et redémarrer VS Code avant de le réinstaller.", + "renameError": "Erreur inconnue en renommant {0} en {1}", "uninstallDependeciesConfirmation": "Voulez-vous désinstaller uniquement '{0}' ou également ses dépendances ?", - "uninstallOnly": "Uniquement", - "uninstallAll": "Tout", + "uninstallOnly": "Extension uniquement", + "uninstallAll": "Tout désinstaller", "uninstallConfirmation": "Voulez-vous vraiment désinstaller '{0}' ?", "ok": "OK", "singleDependentError": "Impossible de désinstaller l'extension '{0}'. L'extension '{1}' en dépend.", diff --git a/i18n/fra/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/fra/src/vs/platform/extensions/node/extensionValidator.i18n.json index c987c61783..9f5831d299 100644 --- a/i18n/fra/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/fra/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Impossible d'analyser la valeur {0} de 'engines.vscode'. Utilisez, par exemple, ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x, etc.", + "versionSyntax": "Impossible d'analyser la valeur {0} de `engines.vscode`. Veuillez utiliser, par exemple : ^1.22.0, ^1.22.x, ...", "versionSpecificity1": "La version spécifiée dans 'engines.vscode' ({0}) n'est pas assez précise. Pour les versions de vscode antérieures à 1.0.0, définissez au minimum les versions majeure et mineure souhaitées. Par exemple : ^0.10.0, 0.10.x, 0.11.0, etc.", "versionSpecificity2": "La version spécifiée dans 'engines.vscode' ({0}) n'est pas assez précise. Pour les versions de vscode ultérieures à 1.0.0, définissez au minimum la version majeure souhaitée. Par exemple : ^1.10.0, 1.10.x, 1.x.x, 2.x.x, etc.", "versionMismatch": "L'extension n'est pas compatible avec le code {0}. L'extension nécessite {1}." diff --git a/i18n/fra/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/fra/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index c818d6d8fb..1d0612bea1 100644 --- a/i18n/fra/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/fra/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "Votre installation de {0} semble être endommagée. Effectuez une réinstallation.", "integrity.moreInformation": "Informations", - "integrity.dontShowAgain": "Ne plus afficher", - "integrity.prompt": "Votre installation de {0} semble être endommagée. Effectuez une réinstallation." + "integrity.dontShowAgain": "Ne plus afficher" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/fra/src/vs/platform/issue/electron-main/issueService.i18n.json index 042dae6893..34631426da 100644 --- a/i18n/fra/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/fra/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Rapporteur du problème" + "issueReporter": "Rapporteur du problème", + "processExplorer": "Explorateur de processus" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/list/browser/listService.i18n.json b/i18n/fra/src/vs/platform/list/browser/listService.i18n.json index 85cefabeaf..d1d4574d62 100644 --- a/i18n/fra/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/fra/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Le modificateur à utiliser pour ajouter un élément à une multi-sélection avec la souris (par exemple dans l’Explorateur, des éditeurs ouverts et scm view). 'ctrlCmd' mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans macOS. Les mouvements de souris 'Ouvrir sur le côté', si supportés, s'adaptent pour ne pas entrer en conflit avec le modificateur multiselect.", "openMode.singleClick": "Ouvre les éléments sur un simple clic de souris.", "openMode.doubleClick": "Ouvre les éléments sur un double clic de souris.", - "openModeModifier": "Contrôle l’ouverture des éléments dans les arbres et listes à l’aide de la souris (si pris en charge). Mettre la valeur `singleClick` pour ouvrir des éléments avec un simple clic de souris et `doubleClick` pour ouvrir uniquement via un double-clic de souris. Pour les parents ayant des enfants dans les arbres, ce paramètre contrôle si un simple clic développe le parent ou un double-clic. Notez que certains arbres et listes peuvent choisir d’ignorer ce paramètre, si ce n’est pas applicable. " + "openModeModifier": "Contrôle l’ouverture des éléments dans les arbres et listes à l’aide de la souris (si pris en charge). Mettre la valeur `singleClick` pour ouvrir des éléments avec un simple clic de souris et `doubleClick` pour ouvrir uniquement via un double-clic de souris. Pour les parents ayant des enfants dans les arbres, ce paramètre contrôle si un simple clic développe le parent ou un double-clic. Notez que certains arbres et listes peuvent choisir d’ignorer ce paramètre, si ce n’est pas applicable. ", + "horizontalScrolling setting": "Contrôle si les arborescences prennent en charge le défilement horizontal dans le plan de travail." } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/markers/common/markers.i18n.json b/i18n/fra/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..634b6c772a --- /dev/null +++ b/i18n/fra/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Erreur", + "sev.warning": "Avertissement", + "sev.info": "Informations" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json index 5198484b51..7f4a2385ad 100644 --- a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "Couleur de premier plan de la zone d'entrée pour le texte d'espace réservé.", "inputValidationInfoBackground": "Couleur d'arrière-plan de la validation d'entrée pour la gravité des informations.", "inputValidationInfoBorder": "Couleur de bordure de la validation d'entrée pour la gravité des informations.", - "inputValidationWarningBackground": "Couleur d'arrière-plan de la validation d'entrée pour l'avertissement sur les informations.", + "inputValidationWarningBackground": "Couleur d'arrière-plan de la validation d'entrée pour la gravité de l'avertissement.", "inputValidationWarningBorder": "Couleur de bordure de la validation d'entrée pour la gravité de l'avertissement.", "inputValidationErrorBackground": "Couleur d'arrière-plan de la validation d'entrée pour la gravité de l'erreur.", "inputValidationErrorBorder": "Couleur de bordure de la validation d'entrée pour la gravité de l'erreur. ", @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "Couleur de bordure des régions dont le contenu est identique à la sélection.", "editorFindMatch": "Couleur du résultat de recherche actif.", "findMatchHighlight": "Couleur des autres résultats de recherche correspondants. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", - "findRangeHighlight": "Couleur de la plage limitant la recherche. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "findRangeHighlight": "Couleur de la plage limitant la recherche. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", "editorFindMatchBorder": "Couleur de bordure du résultat de recherche actif.", "findMatchHighlightBorder": "Couleur de bordure des autres résultats de recherche.", - "findRangeHighlightBorder": "La couleur de bordure définit l'étendue de la recherche. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous. ", + "findRangeHighlightBorder": "Couleur de la bordure limitant la recherche. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes. ", "hoverHighlight": "Mettre en surbrillance ci-dessous le mot pour lequel un survol est affiché. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "hoverBackground": "Couleur d'arrière-plan du pointage de l'éditeur.", "hoverBorder": "Couleur de bordure du pointage de l'éditeur.", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "Arrière-plan de l'en-tête qui arrive dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "mergeIncomingContentBackground": "Arrière-plan du contenu qui arrive dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "mergeCommonHeaderBackground": "Arrière-plan de l'en-tête de l'ancêtre commun dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", - "mergeCommonContentBackground": "Arrière-plan du contenu de l'ancêtre commun dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeCommonContentBackground": "Arrière-plan du contenu de l'ancêtre commun dans les conflits de fusion inline. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", "mergeBorder": "Couleur de bordure des en-têtes et du séparateur dans les conflits de fusion inline.", "overviewRulerCurrentContentForeground": "Premier plan de la règle d'aperçu actuelle pour les conflits de fusion inline.", "overviewRulerIncomingContentForeground": "Premier plan de la règle d'aperçu entrante pour les conflits de fusion inline.", "overviewRulerCommonContentForeground": "Arrière-plan de la règle d'aperçu de l'ancêtre commun dans les conflits de fusion inline.", - "overviewRulerFindMatchForeground": "Couleur du marqueur de la règle d'aperçu pour rechercher des correspondances.", - "overviewRulerSelectionHighlightForeground": "Couleur du marqueur de la règle d'aperçu pour la mise en évidence de la sélection." + "overviewRulerFindMatchForeground": "Couleur du marqueur de la règle d'aperçu pour les correspondances trouvées. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous.", + "overviewRulerSelectionHighlightForeground": "Couleur du marqueur de la règle d'aperçu pour les mises en surbrillance de sélection. La couleur doit ne pas être opaque pour ne pas masquer les décorations du dessous." } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/fra/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..b610699043 --- /dev/null +++ b/i18n/fra/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "Vous voulez laisser l'extension {0} ouvrir l'URL suivante ?" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/fra/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..698e3a6abb --- /dev/null +++ b/i18n/fra/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "Identificateur unique utilisé pour identifier le conteneur dans lequel les vues peuvent être contribuées en utilisant le point de contribution 'views'.", + "vscode.extension.contributes.views.containers.title": "Chaîne lisible par un humain permettant d'afficher le conteneur", + "vscode.extension.contributes.views.containers.icon": "Chemin de l'icône du conteneur. Les icônes ont une taille de 24x24 centrée dans un rectangle de 50x40, et leur couleur de remplissage est 'rgb(215, 218, 224)' ou '#d7dae0'. Les icônes doivent être de préférence au format SVG, mais tous les types de fichier image sont acceptés.", + "vscode.extension.contributes.viewsContainers": "Contribue aux conteneurs de vues vers l’éditeur", + "views.container.activitybar": "Les conteneurs visuels contribuent à la barre d'activité", + "test": "Test", + "proposed": "La contribution 'viewsContainers' est disponible uniquement pour l'exécution en dehors de dev ou avec le commutateur de ligne de commande suivant : --enable-proposed-api {0}", + "requirearray": "les conteneurs de vues doivent être un tableau", + "requireidstring": "La propriété '{0}' est obligatoire et doit être de type 'string'. Sont autorisés uniquement les caractères alphanumériques, '_', '-'.", + "requirestring": "la propriété '{0}' est obligatoire et doit être de type 'string'", + "showViewlet": "Afficher {0}", + "view": "Affichage" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/fra/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index cab3a278ef..f97d84a533 100644 --- a/i18n/fra/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/fra/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "Nom de la vue, contrôlable de visu. Affiché", "vscode.extension.contributes.view.when": "Condition qui doit être vraie pour afficher cette vue", "vscode.extension.contributes.views": "Ajoute des vues à l'éditeur", - "views.explorer": "Mode Explorateur", - "views.debug": "Debug View", - "locationId.invalid": "'{0}' n'est pas un emplacement de vue valide", + "views.explorer": "Les vues dans le conteneur \"Explorer\" contribuent à la barre d'activité", + "views.debug": "Les vues dans le conteneur de débogage contribuent à la barre d'activité", + "views.scm": "Les vues dans le conteneur \"SCM\" contribuent à la barre d'activité", + "views.test": "Fournit des vues du conteneur de test dans la barre d'activités", + "views.contributed": "Les vues contribuent au conteneur de vues contributives", + "ViewContainerDoesnotExist": "Le conteneur de vues '{0}' n'existe pas et toutes les vues inscrites dans ce conteneur sont ajoutées à l''Explorateur'.", "duplicateView1": "Impossible d’enregistrer des vues multiples avec le même id '{0}'» dans l’emplacement '{1}'", "duplicateView2": "Une vue avec l’id `{0}` est déjà enregistrée à l’emplacement `{1}`" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 210fd3a010..2e03576f1a 100644 --- a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Format avorté lors de l'enregistrement après {0} ms", + "codeActionsOnSave.didTimeout": "codeActionsOnSave abandonné au bout de {0} ms", + "timeout.onWillSave": "OnWillSaveTextDocument-event avorté après 1750 ms", "saveParticipants": "Exécution de la sauvegarde des participants..." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..5f508cf00b --- /dev/null +++ b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0} : {1}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index b5c9a1f44d..3c73881181 100644 --- a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "éditeur webview" + "errorMessage": "Une erreur s’est produite lors de restauration de a vue : {0}" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/fra/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..ba3f301458 --- /dev/null +++ b/i18n/fra/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (Extension)" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index fb14f10dc5..ab82c41bb3 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Focus sur le groupe suivant", "openToSide": "Ouvrir sur le côté", "closeEditor": "Fermer l'éditeur", + "closeOneEditor": "Fermer", "revertAndCloseActiveEditor": "Restaurer et fermer l'éditeur", "closeEditorsToTheLeft": "Fermer les éditeurs situés à gauche", "closeAllEditors": "Fermer tous les éditeurs", diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index d94e3ed853..ae4d467c9a 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Si vous n'utilisez pas de lecteur d'écran, définissez le paramètre 'editor.accessibilitySupport' sur \"désactivé\".", "disableTabMode": "Désactiver le mode d'accessibilité", "gotoLine": "Atteindre la ligne", - "indentation": "Retrait", + "selectIndentation": "Sélectionner le retrait", "selectEncoding": "Sélectionner l'encodage", "selectEOL": "Sélectionner la séquence de fin de ligne", "selectLanguageMode": "Sélectionner le mode de langage", diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 72cfab923e..206aecbb1a 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} Mo", "sizeGB": "{0} Go", "sizeTB": "{0} To", - "largeImageError": "La taille du fichier de l’image est trop grande (> à 1Mo) pour afficher dans l’éditeur.", + "largeImageError": "L’image n’est pas affichée dans l’éditeur parce qu’elle est trop grande ({0}).", "resourceOpenExternalButton": " Ouvrir l'image en utilisant un programme externe ?", - "nativeBinaryError": "Impossible d'afficher le fichier dans l'éditeur : soit il est binaire, soit il est très volumineux, soit il utilise un encodage de texte non pris en charge.", + "nativeFileTooLargeError": "Le fichier n’est pas affiché dans l’éditeur, parce qu’il est trop volumineux ({0}).", + "nativeBinaryError": "Le fichier n’est pas affiché dans l’éditeur parce que c’est un fichier binaire ou qu'il utilise un encodage de texte non pris en charge.", + "openAsText": "Vous voulez l'ouvrir quand même ?", "zoom.action.fit.label": "Toute l’Image", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index ee9f5dc0f7..105472a8e6 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Fermer", "araLabelEditorActions": "Actions de l'éditeur" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index c82a9d79c8..86977fb8b9 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Aucune nouvelle notification", "notifications": "Notifications", "notificationsToolbar": "Actions du centre de notifications", "notificationsList": "Liste des notifications" diff --git a/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..161084b3be --- /dev/null +++ b/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Appuyez sur 'Entrée' pour confirmer ou sur 'Échap' pour annuler)", + "inputModeEntry": "Appuyez sur 'Entrée' pour confirmer votre saisie, ou sur 'Échap' pour l'annuler", + "quickInput.countSelected": "{0} Sélectionnés", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..e961aa1b88 --- /dev/null +++ b/i18n/fra/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Taper pour affiner les résultats." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json index f69ffcda7b..3f2e911cee 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Ouvrir les éléments récents...", "quickOpenRecent": "Ouverture rapide des éléments récents...", "reportIssueInEnglish": "Signaler un problème", + "openProcessExplorer": "Ouvrir l'explorateur de processus", "reportPerformanceIssue": "Signaler un problème de performance", "keybindingsReference": "Référence des raccourcis clavier", "openDocumentationUrl": "Documentation", diff --git a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json index d5ad16a412..a08c437859 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Fenêtre", "window.openFilesInNewWindow.on": "Les fichiers s'ouvrent dans une nouvelle fenêtre", "window.openFilesInNewWindow.off": "Les fichiers s'ouvrent dans la fenêtre du dossier conteneur ouvert ou dans la dernière fenêtre active", - "window.openFilesInNewWindow.default": "Les fichiers s'ouvrent dans la fenêtre du dossier conteneur ouvert ou dans la dernière fenêtre active, sauf s'ils sont ouverts via le Dock ou depuis le Finder (macOS uniquement)", - "openFilesInNewWindow": "Contrôle si les fichiers doivent s'ouvrir dans une nouvelle fenêtre.\n- default : les fichiers s'ouvrent dans la fenêtre du dossier conteneur ouvert ou dans la dernière fenêtre active, sauf s'ils sont ouverts via le Dock ou depuis le Finder (macOS uniquement)\n- on : les fichiers s'ouvrent dans une nouvelle fenêtre\n- off : les fichiers s'ouvrent dans la fenêtre du dossier conteneur ouvert ou dans la dernière fenêtre active\nNotez que dans certains cas, ce paramètre est ignoré (par exemple, quand vous utilisez l'option de ligne de commande -new-window ou -reuse-window).", + "window.openFilesInNewWindow.defaultMac": "Les fichiers s'ouvriront dans la fenêtre avec le dossier des fichiers ouvert ou la dernière fenêtre active, à moins qu'ils ne soient ouverts via le Dock ou depuis Finder.", + "window.openFilesInNewWindow.default": "Les fichiers s'ouvriront dans une nouvelle fenêtre, à moins qu'ils ne soient sélectionnés dans l'application (par ex. via le menu Fichier)", + "openFilesInNewWindowMac": "Contrôle si les fichiers doivent s'ouvrir dans une nouvelle fenêtre.\n- default : les fichiers s'ouvriront dans la fenêtre avec le dossier des fichiers ouvert ou la dernière fenêtre active à moins qu'ils ne soient ouverts via le Dock ou depuis le Finder\n- on : les fichiers s'ouvriront dans une nouvelle fenêtre\n- off : les fichiers s'ouvriront dans la fenêtre avec le dossier des fichiers ouvert ou la dernière fenêtre active\nNotez qu'il peut encore y avoir des cas où ce paramètre est ignoré (par exemple lorsque vous utilisez l'option de ligne de commande -new-window ou -reuse-window).", + "openFilesInNewWindow": "Contrôle si les fichiers doivent s'ouvrir dans une nouvelle fenêtre.\n- default : les fichiers s'ouvriront dans une nouvelle fenêtre à moins qu'ils ne soient sélectionnés dans l'application (par ex. via le menu Fichier)\n- on : les fichiers s'ouvriront dans une nouvelle fenêtre\n- off : les fichiers s'ouvriront dans la fenêtre avec le dossier des fichiers ouvert ou la dernière fenêtre active\nNotez qu'il peut encore y avoir des cas où ce paramètre est ignoré (par exemple lorsque vous utilisez l'option de ligne de commande -new-window ou -reuse-window).", "window.openFoldersInNewWindow.on": "Les dossiers s'ouvrent dans une nouvelle fenêtre", "window.openFoldersInNewWindow.off": "Les dossiers remplacent la dernière fenêtre active", "window.openFoldersInNewWindow.default": "Les dossiers s'ouvrent dans une nouvelle fenêtre, sauf si un dossier est sélectionné depuis l'application (par exemple, via le menu Fichier)", "openFoldersInNewWindow": "Contrôle si les dossiers doivent s'ouvrir dans une nouvelle fenêtre ou remplacer la dernière fenêtre active.\n- default : les dossiers s'ouvrent dans une nouvelle fenêtre, sauf si un dossier est sélectionné depuis l'application (par exemple, via le menu Fichier)\n- on : les dossiers s'ouvrent dans une nouvelle fenêtre\n- off : les dossiers remplacent la dernière fenêtre active\nNotez que dans certains cas, ce paramètre est ignoré (par exemple, quand vous utilisez l'option de ligne de commande -new-window ou -reuse-window).", + "window.openWithoutArgumentsInNewWindow.on": "Ouvrir une nouvelle fenêtre vide", + "window.openWithoutArgumentsInNewWindow.off": "Mettre le focus sur la dernière instance active du terminal", + "openWithoutArgumentsInNewWindow": "Contrôle si une nouvelle fenêtre vide doit s’ouvrir lors du démarrage d’une seconde instance sans argument, ou si la dernière instance en cours d’exécution doit obtenir le focus.\n- on : ouvrir une nouvelle fenêtre vide\n- off : la dernière instance en cours d’exécution active obtiendra le focus\nNote qu’il peut encore exister des cas où ce paramètre est ignoré (par exemple lorsque vous utilisez l'option de ligne de commande -new-window ou -reuse-window).", "window.reopenFolders.all": "Rouvre toutes les fenêtres.", "window.reopenFolders.folders": "Rouvrir tous les dossiers. Les espaces de travail vides ne seront pas restaurées.", "window.reopenFolders.one": "Rouvre la dernière fenêtre active.", @@ -58,7 +63,7 @@ "restoreWindows": "Contrôle comment les fenêtres seront rouvertes après un redémarrage. Sélectionner 'none' pour toujours démarrer avec un espace de travail vide, 'one' pour rouvrir la dernière fenêtre avec laquelle vous avez travaillé, 'folders' pour rouvrir toutes les fenêtres qui avaient des dossiers ouverts ou 'all' pour rouvrir toutes les fenêtres de votre dernière session.", "restoreFullscreen": "Contrôle si une fenêtre doit être restaurée en mode plein écran si elle a été fermée dans ce mode.", "zoomLevel": "Modifiez le niveau de zoom de la fenêtre. La taille d'origine est 0. Chaque incrément supérieur (exemple : 1) ou inférieur (exemple : -1) représente un zoom 20 % plus gros ou plus petit. Vous pouvez également entrer des décimales pour changer le niveau de zoom avec une granularité plus fine.", - "title": "Contrôle le titre de la fenêtre en fonction sur l’éditeur actif. Les variables sont remplacés selon le contexte : ${activeEditorShort} : le nom du fichier (ex: monFichier.txt) ${activeEditorMedium} : le chemin d’accès au fichier par rapport au dossier de l’espace de travail (ex: monDossier/monFichier.txt) ${activeEditorLong} : le chemin d’accès complet du fichier (par exemple / Users/Developpement/monDossier/monFichier.txt) ${folderName} : nom du dossier de l’espace de travail auquel le fichier appartient (ex: mondossier) ${folderPath} : chemin d’accès du dossier de l'espace de travail auquel le fichier appartient (ex: /Users/Developpement/monDossier) {$ rootName} : nom de l’espace de travail (:. monDossier ou monEspaceDeTravail) ${rootPath} : chemin d’accès de l’espace de travail (ex: /Users/Developpement/monEspaceDeTravail) ${appName} : ex. VS Code ${dirty} : un indicateur si l’éditeur actif est modifié ${separator} : un séparateur conditionnel (\" - \") qui ne s'affiche que quand ils sont entourés par des variables avec des valeurs", + "title": "Contrôle le titre de la fenêtre basé sur l’éditeur actif. Les variables sont remplacées selon le contexte : \n${activeEditorShort} : le nom de fichier (p. ex. monfichier.txt)\n${activeEditorMedium} : le chemin d’accès du fichier par rapport au dossier de l’espace de travail (par exemple, myFolder/myFile.txt) \n${activeEditorLong} : le chemin d’accès complet du fichier (par exemple / Users/Development/myProject/myFolder/myFile.txt) \n${folderName} : le nom du dossier de l'espace de travail dans lequel le fichier est contenu (p. ex. mondossier) \n${folderPath} : le chemin d’accès au dossier de l'espace de travail dans lequel le fichier est contenu (par exemple /Users/Development/myFolder) \n{$ rootName} : le nom de l’espace de travail (p. ex. myFolder ou myWorkspace) \n${rootPath} : le chemin d’accès de l’espace de travail (par exemple, /Users/Development/myWorkspace) \n${appName} : p. ex. VS Code\n${dirty} : un indicateur si l’éditeur actif est modifié\n${separator} : un séparateur conditionnel (\" - \") qui ne s'affiche que quand ils sont entourés par des variables avec des valeurs ou du texte statique", "window.newWindowDimensions.default": "Permet d'ouvrir les nouvelles fenêtres au centre de l'écran.", "window.newWindowDimensions.inherit": "Permet d'ouvrir les nouvelles fenêtres avec la même dimension que la dernière fenêtre active.", "window.newWindowDimensions.maximized": "Permet d'ouvrir les nouvelles fenêtres de manière agrandie.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Si cette option est activée, le thème à contraste élevé est automatiquement choisi quand Windows utilise un thème à contraste élevé. À l'inverse, le thème sombre est automatiquement choisi quand Windows n'utilise plus le thème à contraste élevé.", "titleBarStyle": "Ajustez l'apparence de la barre de titre de la fenêtre. Vous devez effectuer un redémarrage complet pour que les changements soient appliqués.", "window.nativeTabs": "Active les onglets macOS Sierra. Notez que vous devez redémarrer l'ordinateur pour appliquer les modifications et que les onglets natifs désactivent tout style de barre de titre personnalisé configuré, le cas échéant.", + "window.smoothScrollingWorkaround": "Activez cette solution de contournement si le défilement n’est plus lissé après la restauration d’une fenêtre de VS Code réduite. Il s’agit d’une solution de contournement pour un problème (https://github.com/Microsoft/vscode/issues/13612) où le défilement commence à laguer sur les périphériques dotés de pavés de précision comme les appareils Surface de Microsoft. Activer cette solution de contournement peut provoquer un peu de scintillement de mise en page après la restauration de la fenêtre depuis l’état minimisé mais est sans danger.", + "window.clickThroughInactive": "Si activée, cliquer sur une fenêtre inactive activera la fenêtre et déclenchera l’élément sous la souris, si elle est cliquable. Si désactivé, cliquer n’importe où sur une fenêtre inactive va seulement l'activer et un second clic sur l’élément sera nécessaire.", "zenModeConfigurationTitle": "Mode Zen", "zenMode.fullScreen": "Contrôle si l'activation de Zen Mode met également le banc d'essai en mode plein écran.", "zenMode.centerLayout": "Contrôle si l'activation du mode Zen centre également la disposition.", diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index aaafb7bb8b..44d5d6033e 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Modifier un point d'arrêt...", + "logPoint": "Point de journalisation", + "breakpoint": "Point d'arrêt", + "editBreakpoint": "Modifier {0}...", + "removeBreakpoint": "Supprimer {0}", "functionBreakpointsNotSupported": "Les points d'arrêt de fonction ne sont pas pris en charge par ce type de débogage", "functionBreakpointPlaceholder": "Fonction où effectuer un point d'arrêt", "functionBreakPointInputAriaLabel": "Point d'arrêt sur fonction de type", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Point d'arrêt non vérifié", "functionBreakpointUnsupported": "Les points d'arrêt de fonction ne sont pas pris en charge par ce type de débogage", "breakpointDirtydHover": "Point d'arrêt non vérifié. Fichier modifié. Redémarrez la session de débogage.", + "logBreakpointUnsupported": "Les points de journalisation ne sont pas pris en charge par ce type de débogage", "conditionalBreakpointUnsupported": "Les points d'arrêt conditionnels ne sont pas pris en charge par ce type de débogage", "hitBreakpointUnsupported": "Les points d'arrêt conditionnels ne sont pas pris en charge par ce type de débogage" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index d1b69a30cb..dcc964fe80 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Déconnecter", "continueDebug": "Continuer", "pauseDebug": "Suspendre", + "terminateThread": "Terminer le thread", "restartFrame": "Redémarrer le frame", "removeBreakpoint": "Supprimer un point d'arrêt", "removeAllBreakpoints": "Supprimer tous les points d'arrêt", - "enableBreakpoint": "Activer le point d'arrêt", - "disableBreakpoint": "Désactiver le point d'arrêt", "enableAllBreakpoints": "Activer tous les points d'arrêt", "disableAllBreakpoints": "Désactiver tous les points d'arrêt", "activateBreakpoints": "Activer les points d'arrêt", "deactivateBreakpoints": "Désactiver les points d'arrêt", "reapplyAllBreakpoints": "Réappliquer tous les points d'arrêt", "addFunctionBreakpoint": "Ajouter un point d'arrêt sur fonction", - "addConditionalBreakpoint": "Ajouter un point d'arrêt conditionnel...", - "editConditionalBreakpoint": "Modifier un point d'arrêt...", "setValue": "Définir la valeur", "addWatchExpression": "Ajouter une expression", "editWatchExpression": "Modifier l'expression", diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index a2d1d5d40e..a12b1b805b 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Déboguer : activer/désactiver un point d'arrêt", "conditionalBreakpointEditorAction": "Déboguer : ajouter un point d'arrêt conditionnel...", + "logPointEditorAction": "Débogage : Ajouter un point de journalisation...", "runToCursor": "Exécuter jusqu'au curseur", "debugEvaluate": "Déboguer : évaluer", "debugAddToWatch": "Déboguer : ajouter à la fenêtre Espion", diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..44f7ce035b --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "Message à loguer lorsque le point d’arrêt est atteint. Les expressions entre {} sont interpolées. 'Entrée' pour accepter,'Echap' pour annuler.", + "breakpointWidgetHitCountPlaceholder": "Arrêt quand le nombre d'accès est atteint. 'Entrée' pour accepter ou 'Échap' pour annuler.", + "breakpointWidgetExpressionPlaceholder": "Arrêt quand l'expression prend la valeur true. 'Entrée' pour accepter ou 'Échap' pour annuler.", + "expression": "Expression", + "hitCount": "Nombre d'accès", + "logMessage": "Message de log" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index fae84ee045..9edc18d1ab 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Veuillez utiliser des noms de configuration uniques.", "app.launch.json.compound.folder": "Nom du dossier dans lequel le composé se trouve.", "app.launch.json.compounds.configurations": "Noms des configurations qui sont lancées dans le cadre de ce composé.", - "debugNoType": "Le 'type' de l'adaptateur de débogage ne peut pas être omis. Il doit s'agir du type 'string'.", + "debugNoType": "Le 'type' de débogueur ne peut pas être omis et doit être de type 'string'.", "selectDebug": "Sélectionner l'environnement", "DebugConfig.failed": "Impossible de créer le fichier 'launch.json' dans le dossier '.vscode' ({0}).", "workspace": "espace de travail", diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index acb73d8018..c0d36ce732 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Point de journalisation", + "breakpoint": "Point d'arrêt", + "removeBreakpoint": "Supprimer {0}", + "editBreakpoint": "Modifier {0}...", + "disableBreakpoint": "Désactiver {0}", + "enableBreakpoint": "Activer {0}", "removeBreakpoints": "Supprimer les points d'arrêt", "removeBreakpointOnColumn": "Supprimer le point d'arrêt de la colonne {0}", "removeLineBreakpoint": "Supprimer le point d'arrêt de la ligne", @@ -18,5 +24,13 @@ "enableBreakpoints": "Activer le point d'arrêt de la colonne {0}", "enableBreakpointOnLine": "Activer le point d'arrêt de la ligne", "addBreakpoint": "Ajouter un point d'arrêt", + "addConditionalBreakpoint": "Ajouter un point d'arrêt conditionnel...", + "addLogPoint": "Ajouter un point de journalisation...", + "breakpointHasCondition": "Ce {0} a un {1} qui sera perdu en cas de suppression. Désactivez le {0} à la place.", + "message": "message", + "condition": "condition", + "removeLogPoint": "Supprimer {0}", + "disableLogPoint": "Désactiver {0}", + "cancel": "Annuler", "addConfiguration": "Ajouter une configuration..." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 12e37fffab..35c5c45f01 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Afficher les erreurs", "noFolderWorkspaceDebugError": "Impossible de déboguer le fichier actif. Vérifiez qu'il est enregistré sur le disque et qu'une extension de débogage est installée pour ce type de fichier.", "cancel": "Annuler", - "DebugTaskNotFound": "preLaunchTask '{0}' introuvable.", - "taskNotTracked": "La tâche de prélancement '{0}' n'a pas pu être tracée." + "DebugTaskNotFound": "Tâche '{0}' introuvable.", + "taskNotTracked": "La tâche '{0}' ne peut pas être tracée." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index bb2eb9b570..b8b3ea21a0 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Informations", - "unableToLaunchDebugAdapter": "Impossible de lancer l'adaptateur de débogage à partir de '{0}'.", - "unableToLaunchDebugAdapterNoArgs": "Impossible de lancer l'adaptateur de débogage.", - "stoppingDebugAdapter": "{0}. Arrêt de l'adaptateur de débogage.", "debugAdapterCrash": "Le processus de l'adaptateur de débogage s'est terminé de manière inattendue" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 0d7a8d178c..10434c3b2a 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "L'exécutable d'adaptateur de débogage '{0}' n'existe pas.", "debugAdapterCannotDetermineExecutable": "Impossible de déterminer l'exécutable pour l'adaptateur de débogage '{0}'.", - "launch.config.comment1": "Utilisez IntelliSense pour en savoir plus sur les attributs possibles.", - "launch.config.comment2": "Pointez pour afficher la description des attributs existants.", - "launch.config.comment3": "Pour plus d'informations, visitez : {0}", - "debugType": "Type de configuration.", - "debugTypeNotRecognised": "Le type de débogage n'est pas reconnu. Vérifiez que vous avez installé l'extension de débogage correspondante et qu'elle est activée.", - "node2NotSupported": "\"node2\" n'est plus pris en charge. Utilisez \"node\" à la place, et affectez la valeur \"inspector\" à l'attribut \"protocol\".", - "debugName": "Le nom de la configuration s'affiche dans le menu déroulant de la configuration de lancement.", - "debugRequest": "Type de requête de configuration. Il peut s'agir de \"launch\" ou \"attach\".", - "debugServer": "Pour le développement d'une extension de débogage uniquement : si un port est spécifié, VS Code tente de se connecter à un adaptateur de débogage s'exécutant en mode serveur", - "debugPrelaunchTask": "Tâche à exécuter avant le démarrage de la session de débogage.", - "debugWindowsConfiguration": "Attributs de configuration de lancement spécifiques à Windows.", - "debugOSXConfiguration": "Attributs de configuration de lancement spécifiques à OS X.", - "debugLinuxConfiguration": "Attributs de configuration de lancement spécifiques à Linux.", - "deprecatedVariables": "env.', 'config.' et 'command.' sont déconseillés. Utilisez 'env:', 'config:' et 'command:' à la place." + "unableToLaunchDebugAdapter": "Impossible de lancer l'adaptateur de débogage à partir de '{0}'.", + "unableToLaunchDebugAdapterNoArgs": "Impossible de lancer l'adaptateur de débogage." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..6d5a247318 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Utilisez IntelliSense pour en savoir plus sur les attributs possibles.", + "launch.config.comment2": "Pointez pour afficher la description des attributs existants.", + "launch.config.comment3": "Pour plus d'informations, visitez : {0}", + "debugType": "Type de configuration.", + "debugTypeNotRecognised": "Le type de débogage n'est pas reconnu. Vérifiez que vous avez installé l'extension de débogage correspondante et qu'elle est activée.", + "node2NotSupported": "\"node2\" n'est plus pris en charge. Utilisez \"node\" à la place, et affectez la valeur \"inspector\" à l'attribut \"protocol\".", + "debugName": "Le nom de la configuration s'affiche dans le menu déroulant de la configuration de lancement.", + "debugRequest": "Type de requête de configuration. Il peut s'agir de \"launch\" ou \"attach\".", + "debugServer": "Pour le développement d'une extension de débogage uniquement : si un port est spécifié, VS Code tente de se connecter à un adaptateur de débogage s'exécutant en mode serveur", + "debugPrelaunchTask": "Tâche à exécuter avant le démarrage de la session de débogage.", + "debugPostDebugTask": "Tâche à exécuter après que le débogage se termine.", + "debugWindowsConfiguration": "Attributs de configuration de lancement spécifiques à Windows.", + "debugOSXConfiguration": "Attributs de configuration de lancement spécifiques à OS X.", + "debugLinuxConfiguration": "Attributs de configuration de lancement spécifiques à Linux.", + "deprecatedVariables": "env.', 'config.' et 'command.' sont déconseillés. Utilisez 'env:', 'config:' et 'command:' à la place." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..d7245a4f2e --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "Console VS Code", + "mac.terminal.script.failed": "Échec du script '{0}'. Code de sortie : {1}", + "mac.terminal.type.not.supported": "'{0}' non pris en charge", + "press.any.key": "Appuyez sur une touche pour continuer...", + "linux.term.failed": "Échec de '{0}'. Code de sortie : {1}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 0bdffeb19d..5acd91da63 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Configurer les extensions recommandées (Dossier d'espace de travail)", "malicious tooltip": "Cette extension a été signalée comme problématique.", "malicious": "Malveillant", + "disabled": "Désactivé", + "disabled globally": "Désactivé", + "disabled workspace": "Désactivé pour cet espace de travail", "disableAll": "Désactiver toutes les extensions installées", "disableAllWorkspace": "Désactiver toutes les extensions installées pour cet espace de travail", "enableAll": "Activer toutes les extension", diff --git a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..ecc9b7ee90 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Nom de l'extension", + "extension id": "Identificateur d'extension", + "preview": "Aperçu", + "builtin": "Intégrée", + "publisher": "Nom de l'éditeur", + "install count": "Nombre d'installations", + "rating": "Évaluation", + "repository": "Dépôt", + "license": "Licence", + "details": "Détails", + "contributions": "Contributions", + "changelog": "Journal des modifications", + "dependencies": "Dépendances", + "noReadme": "Aucun fichier README disponible.", + "noChangelog": "Aucun Changelog disponible.", + "noContributions": "Aucune contribution", + "noDependencies": "Aucune dépendance", + "settings": "Paramètres ({0})", + "setting name": "Nom", + "description": "Description", + "default": "Par défaut", + "debuggers": "Débogueurs ({0})", + "debugger name": "Nom", + "debugger type": "Type", + "views": "Vues ({0})", + "view id": "ID", + "view name": "Nom", + "view location": "Emplacement", + "localizations": "Localisations ({0})", + "localizations language id": "Id de langue", + "localizations language name": "Nom de la langue", + "localizations localized language name": "Nom de la langue (localisé)", + "colorThemes": "Thèmes de couleurs ({0})", + "iconThemes": "Thèmes d’icônes ({0})", + "colors": "Couleurs ({0})", + "colorId": "Id", + "defaultDark": "Défaut pour le thème sombre", + "defaultLight": "Défaut pour le thème clair", + "defaultHC": "Défaut pour le thème de contraste élevé", + "JSON Validation": "Validation JSON ({0})", + "fileMatch": "Correspondance de fichier", + "schema": "Schéma", + "commands": "Commandes ({0})", + "command name": "Nom", + "keyboard shortcuts": "Raccourcis clavier", + "menuContexts": "Contextes de menu", + "languages": "Langages ({0})", + "language id": "ID", + "language name": "Nom", + "file extensions": "Extensions de fichier", + "grammar": "Grammaire", + "snippets": "Extraits" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 4b7ba68cf0..4149f9c33d 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Cette extension est recommandée par les utilisateurs de l’espace de travail actuel.", "reallyRecommended2": "L'extension '{0}' est recommandée pour ce type de fichier.", "reallyRecommendedExtensionPack": "Le pack d’extensions '{0}' est recommandé pour ce type de fichier.", - "showRecommendations": "Afficher les recommandations", "install": "Installer", + "showRecommendations": "Afficher les recommandations", "showLanguageExtensions": "Le Marketplace a des extensions qui peuvent aider avec les fichiers '.{0}'", "workspaceRecommended": "Cet espace de travail a des recommandations d'extension.", "installAll": "Tout installer", diff --git a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index 5c6030249b..b77f1c9ee6 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Désactiver les autres mappages de touches ({0}) pour éviter les conflits de combinaisons de touches ?", "yes": "Oui", - "no": "Non", - "betterMergeDisabled": "L'extension Better Merge est désormais intégrée, l'extension installée est désactivée et peut être désinstallée.", - "uninstall": "Désinstaller" + "no": "Non" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index f59a45a15d..f395ede0a0 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Recommandées", "otherRecommendedExtensions": "Autres recommandations", "workspaceRecommendedExtensions": "Recommandations de l’espace de travail", - "builtInExtensions": "Intégrée", + "builtInExtensions": "Fonctionnalités", + "builtInThemesExtensions": "Thèmes", + "builtInBasicsExtensions": "Langages de programmation", "searchExtensions": "Rechercher des extensions dans Marketplace", "sort by installs": "Trier par : nombre d'installations", "sort by rating": "Trier par : évaluation", diff --git a/i18n/fra/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 0563efeec1..8e18035f13 100644 --- a/i18n/fra/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Éditeur de fichier texte", "createFile": "Créer un fichier", + "relaunchWithIncreasedMemoryLimit": "Redémarrer avec {0} Mo", + "configureMemoryLimit": "Configurer la limite de mémoire", "fileEditorWithInputAriaLabel": "{0}. Éditeur de fichier texte.", "fileEditorAriaLabel": "Éditeur de fichier texte." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index edfa993f15..6c595644a6 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Copier", "pasteFile": "Coller", "retry": "Réessayer", + "renameWhenSourcePathIsParentOfTargetError": "Veuillez utiliser la commande 'Nouveau dossier' ou 'Nouveau fichier\" pour ajouter des enfants à un dossier existant", "newUntitledFile": "Nouveau fichier sans titre", "createNewFile": "Nouveau fichier", "createNewFolder": "Nouveau dossier", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Vous supprimez un dossier contenant {0} fichiers dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyMessageFileDelete": "Vous supprimez un fichier dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyWarning": "Vous perdrez vos modifications, si vous ne les enregistrez pas.", + "undoBin": "Vous pouvez restaurer à partir de la Corbeille.", + "undoTrash": "Vous pouvez restaurer à partir de la Poubelle.", + "doNotAskAgain": "Ne plus me demander", + "irreversible": "Cette action est irréversible !", + "binFailed": "Impossible de supprimer en utilisant la corbeille. Voulez-vous supprimer définitivement à la place ?", + "trashFailed": "Impossible de supprimer en utilisant la corbeille. Voulez-vous supprimer définitivement à la place?", + "deletePermanentlyButtonLabel": "Supprimer &&définitivement", + "retryButtonLabel": "&&Réessayer", + "confirmMoveTrashMessageFilesAndDirectories": "Voulez-vous vraiment supprimer les {0} fichiers/répertoires suivants et leur contenu ?", + "confirmMoveTrashMessageMultipleDirectories": "Voulez-vous vraiment supprimer les {0} répertoires suivants et leur contenu ?", "confirmMoveTrashMessageMultiple": "Êtes-vous sûr de vouloir supprimer les fichiers {0} suivants ?", "confirmMoveTrashMessageFolder": "Voulez-vous vraiment supprimer '{0}' et son contenu ?", "confirmMoveTrashMessageFile": "Voulez-vous vraiment supprimer '{0}' ?", - "undoBin": "Vous pouvez effectuer une restauration à partir de la Corbeille.", - "undoTrash": "Vous pouvez effectuer une restauration à partir de la Poubelle.", - "doNotAskAgain": "Ne plus me demander", + "confirmDeleteMessageFilesAndDirectories": "Voulez-vous vraiment supprimer définitivement les {0} fichiers/répertoires suivants et leur contenu ?", + "confirmDeleteMessageMultipleDirectories": "Voulez-vous vraiment supprimer définitivement les {0} répertoires suivants et leur contenu ?", "confirmDeleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer définitivement les fichiers {0} suivants ?", "confirmDeleteMessageFolder": "Voulez-vous vraiment supprimer définitivement '{0}' et son contenu ?", "confirmDeleteMessageFile": "Voulez-vous vraiment supprimer définitivement '{0}' ?", - "irreversible": "Cette action est irréversible !", - "cancel": "Annuler", - "permDelete": "Supprimer définitivement", - "importFiles": "Importer des fichiers", + "addFiles": "Ajouter des fichiers", "confirmOverwrite": "Un fichier ou dossier portant le même nom existe déjà dans le dossier de destination. Voulez-vous le remplacer ?", "replaceButtonLabel": "&&Remplacer", "fileIsAncestor": "Le fichier à copier est un ancêtre du dossier de destination", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Ouvrir d'abord un fichier à ouvrir dans une nouvelle fenêtre", "copyPath": "Copier le chemin", "emptyFileNameError": "Un nom de fichier ou de dossier doit être fourni.", + "fileNameStartsWithSlashError": "Un nom de fichier ou de dossier ne peut commencer par une barre oblique.", "fileNameExistsError": "Un fichier ou dossier **{0}** existe déjà à cet emplacement. Choisissez un autre nom.", + "fileUsedAsFolderError": "**{0}** est un fichier et ne peut pas avoir de descendant.", "invalidFileNameError": "Le nom **{0}** est non valide en tant que nom de fichier ou de dossier. Choisissez un autre nom.", "filePathTooLongError": "Le nom **{0}** correspond à un chemin d'accès trop long. Choisissez un nom plus court.", "compareWithClipboard": "Compare le fichier actif avec le presse-papiers", diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index cfe548dcd8..5b2177e90b 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Contrôle si les fichiers non enregistrés sont mémorisés entre les sessions, ce qui permet d'ignorer la demande d'enregistrement à la sortie de l'éditeur.", "useExperimentalFileWatcher": "Utilisez le nouvel observateur de fichiers expérimental.", "defaultLanguage": "Mode de langage par défaut affecté aux nouveaux fichiers.", + "maxMemoryForLargeFilesMB": "Contrôle la mémoire disponible pour VS Code après redémarrage en essayant d’ouvrir les fichiers volumineux. Cela a le même effet que de spécifier --max-memory=NEWSIZE sur la ligne de commande.", "editorConfigurationTitle": "Éditeur", "formatOnSave": "Met en forme un fichier au moment de l'enregistrement. Un formateur doit être disponible, le fichier ne doit pas être enregistré automatiquement, et l'éditeur ne doit pas être en cours d'arrêt.", + "formatOnSaveTimeout": "Délai d’attente pour formater lors de l'enregistrement. Spécifie le délai en millisecondes pour les commandes formatOnSave. Les commandes prenant plus de temps que le délai d’attente spécifié seront annulées.", "explorerConfigurationTitle": "Explorateur de fichiers", "openEditorsVisible": "Nombre d'éditeurs affichés dans le volet Éditeurs ouverts.", "autoReveal": "Contrôle si l'Explorateur doit automatiquement afficher et sélectionner les fichiers à l'ouverture.", diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index f3824c2e1c..0f05e6b801 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -7,13 +7,17 @@ "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Tapez le nom du fichier. Appuyez sur Entrée pour confirmer ou sur Échap pour annuler.", - "constructedPath": "Créer {0} dans **{1}**", + "createFileFromExplorerInfoMessage": "Créer le fichier **{0}** à **{1}**", + "renameFileFromExplorerInfoMessage": "Déplacer et renommer en **{0}**", + "createFolderFromExplorerInfoMessage": "Créer le dossier **{0}** en **{1}**", "filesExplorerViewerAriaLabel": "{0}, Explorateur de fichiers", "dropFolders": "Voulez-vous ajouter les dossiers à l’espace de travail ?", "dropFolder": "Voulez-vous ajouter le dossier à l’espace de travail ?", "addFolders": "&&Ajouter les dossiers", "addFolder": "&&Ajouter le dossier", + "confirmRootsMove": "Êtes-vous sûr de vouloir modifier l’ordre de plusieurs dossiers de la racine dans votre espace de travail ?", "confirmMultiMove": "Êtes-vous sûr de vouloir déplacer les fichiers '{0}' suivants ?", + "confirmRootMove": "Êtes-vous sûr de vouloir modifier l’ordre de dossier racine '{0}' dans votre espace de travail ?", "confirmMove": "Êtes-vous certain de vouloir déplacer '{0}' ?", "doNotAskAgain": "Ne plus me demander", "moveButtonLabel": "&&Déplacer", diff --git a/i18n/fra/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..2af49cbd74 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Aperçu HTML" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/fra/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..eaf9eb82e4 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Entrée d'éditeur non valide." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..dfefdfa0bf --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Développeur" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/fra/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..09dc435705 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Ouvrir les outils de développement Webview", + "refreshWebviewLabel": "Recharger les Webviews" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index 7a5ad5d6d3..79690054ff 100644 --- a/i18n/fra/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Souhaitez-vous changer la langue de l’interface de VS Code en {0} et redémarrer ?", + "yes": "Oui", + "no": "Non", + "neverAgain": "Ne plus afficher", "JsonSchema.locale": "Langue d'interface utilisateur (IU) à utiliser.", "vscode.extension.contributes.localizations": "Contribuer aux localisations de l’éditeur", "vscode.extension.contributes.localizations.languageId": "Id de la langue dans laquelle les chaînes d’affichage sont traduites.", diff --git a/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..7a8e6c2de0 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Souhaitez-vous changer la langue de l’interface de VS Code en {0} et redémarrer ?", + "yes": "Oui", + "no": "Non", + "neverAgain": "Ne plus afficher", + "install language pack": "Prochainement, VS Code prendra en charge uniquement les modules linguistiques sous forme d'extensions Marketplace. Installez l'extension '{0}' pour continuer à utiliser la langue actuellement configurée.", + "install": "Installer", + "more information": "Plus d'informations...", + "JsonSchema.locale": "Langue d'interface utilisateur (IU) à utiliser.", + "vscode.extension.contributes.localizations": "Contribuer aux localisations de l’éditeur", + "vscode.extension.contributes.localizations.languageId": "Id de la langue dans laquelle les chaînes d’affichage sont traduites.", + "vscode.extension.contributes.localizations.languageName": "Nom de la langue en anglais.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Nom de la langue dans la langue contribuée.", + "vscode.extension.contributes.localizations.translations": "Liste des traductions associées à la langue.", + "vscode.extension.contributes.localizations.translations.id": "Id de VS Code ou Extension pour lesquels cette traduction contribue. L'Id de VS Code est toujours `vscode` et d’extension doit être au format `publisherId.extensionName`.", + "vscode.extension.contributes.localizations.translations.id.pattern": "L’Id doit être `vscode` ou au format `publisherId.extensionName` pour traduire respectivement VS code ou une extension.", + "vscode.extension.contributes.localizations.translations.path": "Un chemin relatif vers un fichier contenant les traductions du langage." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..5144212e71 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Configurer la langue", + "displayLanguage": "Définit le langage affiché par VSCode.", + "doc": "Consultez {0} pour connaître la liste des langues prises en charge.", + "restart": "Le changement de la valeur nécessite le redémarrage de VS Code.", + "fail.createSettings": "Impossible de créer '{0}' ({1})." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..a615adefb9 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Copier", + "copyMessage": "Copier le Message" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..6540dc70d5 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Total de {0} problèmes" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..37f685827c --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Problèmes", + "tooltip.1": "1 problème dans ce fichier", + "tooltip.N": "{0} problèmes dans ce fichier", + "markers.showOnFile": "Afficher les erreurs & les avertissements sur les fichiers et dossiers." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..cd138c0c0a --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Désactivez le filtre d'exclusion de fichiers.", + "clearFilter": "Effacer le filtre." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..60ed699807 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "Affichage de {0} de {1}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..0c1cb04ba6 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Affichage", + "problems.view.toggle.label": "Activer/désactiver les problèmes (Erreurs, Avertissements, Infos)", + "problems.view.focus.label": " Focus sur les problèmes (Erreurs, Avertissements, Infos)", + "problems.panel.configuration.title": "Affichage des problèmes", + "problems.panel.configuration.autoreveal": "Contrôle si l'affichage des problèmes doit automatiquement montrer les fichiers quand il les ouvre", + "markers.panel.title.problems": "Problèmes", + "markers.panel.aria.label.problems.tree": "Problèmes regroupés par fichiers", + "markers.panel.no.problems.build": "Aucun problème n'a été détecté dans l'espace de travail jusqu'à présent.", + "markers.panel.no.problems.filters": "Aucun résultat trouvé avec les critères de filtre fourni.", + "markers.panel.no.problems.file.exclusions": "Tous les problèmes sont cachés parce que le filtre d’exclusion de fichiers est activé.", + "markers.panel.action.useFilesExclude": "Filtrer en utilisant le paramètre d’exclusion de fichiers", + "markers.panel.action.donotUseFilesExclude": "Ne pas utiliser le paramètre d’exclusion de fichiers", + "markers.panel.action.filter": "Filtrer les problèmes", + "markers.panel.filter.ariaLabel": "Filtrer les problèmes", + "markers.panel.filter.placeholder": "Filtre. Par exemple : texte, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "erreurs", + "markers.panel.filter.warnings": "avertissements", + "markers.panel.filter.infos": "infos", + "markers.panel.single.error.label": "1 erreur", + "markers.panel.multiple.errors.label": "{0} erreurs", + "markers.panel.single.warning.label": "1 avertissement", + "markers.panel.multiple.warnings.label": "{0} avertissements", + "markers.panel.single.info.label": "1 info", + "markers.panel.multiple.infos.label": "{0} infos", + "markers.panel.single.unknown.label": "1 inconnu", + "markers.panel.multiple.unknowns.label": "{0} inconnus", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} avec {1} problèmes", + "problems.tree.aria.label.marker.relatedInformation": " Ce problème a des références à {0} emplacements.", + "problems.tree.aria.label.error.marker": "Erreur générée par {0} : {1} à la ligne {2} et au caractère {3}. {4}", + "problems.tree.aria.label.error.marker.nosource": "Erreur : {0} à la ligne {1} et au caractère {2}.{3}", + "problems.tree.aria.label.warning.marker": "Avertissement généré par {0} : {1} à la ligne {2} et au caractère {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Avertissement : {0} à la ligne {1} et au caractère {2}.{3}", + "problems.tree.aria.label.info.marker": "Information générée par {0} : {1} à la ligne {2} et au caractère {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Information : {0} à la ligne {1} et au caractère {2}.{3}", + "problems.tree.aria.label.marker": "Problème généré par {0} : {1} à la ligne {2} et au caractère {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Problème : {0} à la ligne {1} et au caractère {2}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{0} à la ligne {1} et caractère {2} dans {3}", + "errors.warnings.show.label": "Afficher les erreurs et les avertissements" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/fra/src/vs/workbench/parts/output/browser/outputActions.i18n.json index ee2be321c1..ce3643c4be 100644 --- a/i18n/fra/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Activer/désactiver la sortie", "clearOutput": "Effacer la sortie", "toggleOutputScrollLock": "Activer/désactiver l'arrêt du défilement de la sortie", - "switchToOutput.label": "Passer à la sortie" + "switchToOutput.label": "Passer à la sortie", + "openInLogViewer": "Ouvrir le fichier de log" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 36519d451b..6b2ea563ec 100644 --- a/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Sortie", "logViewer": "Visualiseur de journal", "viewCategory": "Affichage", - "clearOutput.label": "Effacer la sortie" + "clearOutput.label": "Effacer la sortie", + "openActiveLogOutputFile": "Affichage: Ouvrir le fichier de log de sortie actif" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index dba588d8bf..8b4bdfb9bb 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Raccourcis clavier", + "showDefaultKeybindings": "Afficher les raccourcis clavier par défaut", + "showUserKeybindings": "Afficher les raccourcis clavier utilisateur", "SearchKeybindings.AriaLabel": "Rechercher dans les combinaisons de touches", "SearchKeybindings.Placeholder": "Rechercher dans les combinaisons de touches", "sortByPrecedene": "Trier par priorité", diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 66f604cca7..286bb69c00 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Ouvrir les paramètres bruts par défaut", + "openSettings": "Ouvrir les paramètres", "openGlobalSettings": "Ouvrir les paramètres utilisateur", "openGlobalKeybindings": "Ouvrir les raccourcis clavier", "openGlobalKeybindingsFile": "Ouvrir le fichier des raccourcis clavier", diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index b07f5ba553..f1a441939f 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Paramètres par défaut", "SearchSettingsWidget.AriaLabel": "Paramètres de recherche", "SearchSettingsWidget.Placeholder": "Paramètres de recherche", "noSettingsFound": "Aucun résultat", @@ -16,6 +15,8 @@ "nlpResult": "Résultats en langage naturel", "filterResult": "Résultats filtrés", "defaultSettings": "Paramètres par défaut", + "defaultUserSettings": "Paramètres utilisateur par défaut", + "defaultWorkspaceSettings": "Paramètres de l'espace de travail par défaut", "defaultFolderSettings": "Paramètres de dossier par défaut", "defaultEditorReadonly": "Modifier dans l’éditeur du côté droit pour substituer les valeurs par défaut.", "preferencesAriaLabel": "Préférences par défaut. Éditeur de texte en lecture seule." diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 96d76a8189..b0cf43e245 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Afficher l’Extension \"{0}\"", "editTtile": "Modifier", "replaceDefaultValue": "Remplacer dans les paramètres", - "copyDefaultValue": "Copier dans Paramètres", - "unsupportedPHPExecutablePathSetting": "Ce paramètre doit être un paramètre utilisateur. Pour configurer PHP pour l'espace de travail, ouvrez un fichier PHP, puis cliquez sur 'Chemin PHP' dans la barre d'état.", - "unsupportedWorkspaceSetting": "Ce paramètre doit être un paramètre utilisateur.", - "unsupportedWorkbenchSetting": "Ce paramètre ne peut pas être appliqué maintenant. Il est appliqué quand vous ouvrez ce dossier directement.", - "unsupportedWorkbenchSettingDevMode": "Ce paramètre ne peut pas s’appliquer maintenant. Il s’appliquera si vous définissez la portée à 'ressource' lors de son inscription, ou lorsque vous ouvrez ce dossier directement." + "copyDefaultValue": "Copier dans Paramètres" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 048774c124..3177d737e3 100644 --- a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Installer des fournisseurs SCM supplémentaires...", "no open repo": "Il n’y a aucun fournisseur de contrôle de code source actif.", "source control": "Contrôle de code source", - "viewletTitle": "{0} : {1}" + "viewletTitle": "{0} : {1}", + "hideView": "Masquer" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 9baa974a2e..af07c4f443 100644 --- a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Afficher le précédent Exclude Pattern de recherche", "nextSearchTerm": "Afficher le terme de recherche suivant", "previousSearchTerm": "Afficher le terme de recherche précédent", - "showSearchViewlet": "Afficher la zone de recherche", "findInFiles": "Chercher dans les fichiers", "replaceInFiles": "Remplacer dans les fichiers", "RefreshAction.label": "Actualiser", diff --git a/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 1b161a03da..7cb5620c5e 100644 --- a/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Rechercher", + "copyMatchLabel": "Copier", + "copyPathLabel": "Copier le chemin", + "copyAllLabel": "Copier tout", + "clearSearchHistoryLabel": "Effacer l'historique de recherche", + "toggleSearchViewPositionLabel": "Basculer la position de la vue de Recherche", "findInFolder": "Rechercher dans le dossier...", "findInWorkspace": "Trouver dans l’espace de travail...", "showTriggerActions": "Atteindre le symbole dans l'espace de travail...", "name": "Rechercher", - "search": "Rechercher", "showSearchViewl": "Afficher la zone de recherche", "view": "Affichage", "findInFiles": "Chercher dans les fichiers", @@ -26,5 +31,5 @@ "search.followSymlinks": "Contrôle s'il faut suivre les symlinks pendant la recherche.", "search.smartCase": "Recherches de manière non case-sensitive si le modèle est entièrement en minuscules, dans le cas contraire, recherche de manière case-sensitive", "search.globalFindClipboard": "Contrôle si la vue de recherche doit lire ou modifier le presse-papiers partagé sur macOS", - "search.location": "Aperçu : contrôle si la recherche est affichée comme une vue dans la barre latérale ou comme un panneau dans la zone correspondante pour libérer de l'espace horizontal. La prochaine version de la recherche dans le panneau prévoit une amélioration de la disposition horizontale qui ne sera plus un aperçu." + "search.location": "Contrôle si la recherche s’affichera comme une vue dans la barre latérale ou comme un panneau dans la zone de panneau pour plus d'espace horizontal. La prochaine version de la Recherche dans le panneau aura une meilleure présentation horizontale et cela ne sera plus une preview." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 4d36cabd2b..389b75b351 100644 --- a/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Aidez-nous à améliorer le support de {0}", "takeShortSurvey": "Répondre à une enquête rapide", "remindLater": "Me le rappeler plus tard", - "neverAgain": "Ne plus afficher", - "helpUs": "Aidez-nous à améliorer le support de {0}" + "neverAgain": "Ne plus afficher" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index b63eedb828..3897b86ea5 100644 --- a/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Acceptez-vous de répondre à une enquête rapide ?", "takeSurvey": "Répondre à l'enquête", "remindLater": "Me le rappeler plus tard", - "neverAgain": "Ne plus afficher", - "surveyQuestion": "Acceptez-vous de répondre à une enquête rapide ?" + "neverAgain": "Ne plus afficher" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 57009dd190..39ed92c194 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Modèle de problème ou bien nom d'un modèle de problème faisant l'objet d'une contribution ou prédéfini. Peut être omis si base est spécifié.", "ProblemMatcherSchema.base": "Nom d'un détecteur de problèmes de correspondance de base à utiliser.", "ProblemMatcherSchema.owner": "Propriétaire du problème dans Code. Peut être omis si base est spécifié. Prend la valeur 'external' par défaut en cas d'omission et si base n'est pas spécifié.", + "ProblemMatcherSchema.source": "Une chaîne lisible par humain qui décrit la source de ce diagnostic, par exemple 'typescript' ou 'super lint'.", "ProblemMatcherSchema.severity": "Gravité par défaut des problèmes de capture. Est utilisé si le modèle ne définit aucun groupe de correspondance pour la gravité.", "ProblemMatcherSchema.applyTo": "Contrôle si un problème signalé pour un document texte s'applique uniquement aux documents ouverts ou fermés, ou bien à l'ensemble des documents.", "ProblemMatcherSchema.fileLocation": "Définit la façon dont les noms de fichiers signalés dans un modèle de problème doivent être interprétés.", diff --git a/i18n/fra/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index ad84ecf37f..8c83d64ad5 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Type de tâche réel", + "TaskDefinition.description": "Type de tâche réel. Notez que les types commençant par '$' sont réservés à un usage interne.", "TaskDefinition.properties": "Propriétés supplémentaires du type de tâche", "TaskTypeConfiguration.noType": "La propriété 'taskType' obligatoire est manquante dans la configuration du type de tâche", "TaskDefinitionExtPoint": "Ajoute des types de tâche" diff --git a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index cc0a35fc51..fee1afc17e 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "N'assigne la tâche à aucun groupe", "JsonSchema.tasks.group": "Définit le groupe d'exécution auquel la tâche appartient. Prend en charge \"build\" pour l'ajouter au groupe de génération et \"test\" pour l'ajouter au groupe de test.", "JsonSchema.tasks.type": "Définit si la tâche est exécutée comme un processus ou comme une commande à l’intérieur d’un shell.", + "JsonSchema.command.quotedString.value": "La valeur réelle de la commande", + "JsonSchema.tasks.quoting.escape": "Echappe les caractères à l’aide du caractère d’échappement du shell (par exemple: ` sous PowerShell et \\ sous bash).", + "JsonSchema.tasks.quoting.strong": "Entoure l’argument en utilisant le caractère guillemet du shell (par exemple: \" sous PowerShell et bash).", + "JsonSchema.tasks.quoting.weak": "Entoure l’argument en utilisant le caractère apostrophe du shell (par exemple: ' sous PowerShell et bash).", + "JsonSchema.command.quotesString.quote": "Comment la valeur de la commande devrait être donnée.", + "JsonSchema.command": "Commande à exécuter. Il peut s'agir d'un programme externe ou d'une commande d'interpréteur de commandes.", + "JsonSchema.args.quotedString.value": "La valeur réelle de l’argument", + "JsonSchema.args.quotesString.quote": "Comment la valeur de l’argument devrait être donnée.", + "JsonSchema.tasks.args": "Arguments passés à la commande quand cette tâche est appelée.", "JsonSchema.tasks.label": "L'étiquette de l’interface utilisateur de la tâche", "JsonSchema.version": "Numéro de version de la configuration.", "JsonSchema.tasks.identifier": "Identificateur défini par l'utilisateur pour référencer la tâche dans launch.json ou une clause dependsOn.", diff --git a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 7362cf1eee..4019a12c5b 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -8,9 +8,12 @@ ], "tasksCategory": "Tâches", "ConfigureTaskRunnerAction.label": "Configurer une tâche", + "totalErrors": "{0} erreurs", + "totalWarnings": "{0} avertissements", + "totalInfos": "{0} infos", "problems": "Problèmes", "building": "Génération...", - "manyMarkers": "99", + "manyProblems": "10K+", "runningTasks": "Afficher les tâches en cours d'exécution", "tasks": "Tâches", "TaskSystem.noHotSwap": "Changer le moteur d’exécution de tâches avec une tâche active en cours d’exécution nécessite de recharger la fenêtre", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Sélectionner pour quel type d’erreurs et d’avertissements analyser la sortie de la tâche", "customizeParseErrors": "La configuration de tâche actuelle contient des erreurs. Corrigez-les avant de personnaliser une tâche. ", "moreThanOneBuildTask": "De nombreuses tâches de génération sont définies dans le fichier tasks.json. Exécution de la première.\n", - "TaskSystem.activeSame.background": "La tâche '{0}' est déjà active et en mode arrière-plan. Pour la terminer, utiliser `Terminer la Tâche...` dans le menu Tâches.", - "TaskSystem.activeSame.noBackground": "La tâche '{0}' est déjà active. Pour la terminer, utiliser `Terminer la Tâche...` dans le menu Tâches.", + "TaskSystem.activeSame.background": "La tâche '{0}\" est déjà active et en mode arrière-plan.", + "TaskSystem.activeSame.noBackground": "La tâche '{0}' est déjà active.", + "terminateTask": "Terminer la tâche", + "restartTask": "Redémarrer la tâche", "TaskSystem.active": "Une tâche est déjà en cours d'exécution. Terminez-la avant d'exécuter une autre tâche.", "TaskSystem.restartFailed": "Échec de la fin de l'exécution de la tâche {0}", "TaskService.noConfiguration": "Erreur : La détection de la tâche {0} n’a pas contribué à une tâche pour la configuration suivante : {1}, la tâche sera ignorée.\n", diff --git a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index fd142eb5ee..cbf0245e75 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Tâche - {0}", "closeTerminal": "Appuyez sur n’importe quelle touche pour fermer le terminal.", "reuseTerminal": "Le terminal sera réutilisé par les tâches, appuyez sur une touche pour le fermer.", - "TerminalTaskSystem": "Impossible d'exécuter une commande d'interpréteur de commandes sur un lecteur UNC.", + "TerminalTaskSystem": "Impossible d'exécuter une commande d'interpréteur de commandes sur un lecteur UNC à l'aide de cmd.exe.", "unkownProblemMatcher": "Impossible de résoudre le détecteur de problèmes {0}. Le détecteur est ignoré" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/fra/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 1f9c5f7aff..745a85ce89 100644 --- a/i18n/fra/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Warning: options.cwd must be of type string. Ignoring value {0}\n", + "ConfigurationParser.inValidArg": "Erreur : l'argument de commande doit être une chaîne ou une chaîne entre apostrophes. La valeur fournie est : \n{0}", "ConfigurationParser.noargs": "Erreur : les arguments de commande doivent correspondre à un tableau de chaînes. La valeur fournie est :\n{0}", "ConfigurationParser.noShell": "Avertissement : La configuration de l'interpréteur de commandes n'est prise en charge que durant l'exécution des tâches dans le terminal.", "ConfigurationParser.noName": "Erreur : le détecteur de problèmes de correspondance dans la portée de déclaration doit avoir un nom :\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Erreur : la configuration de la tâche '{0}' a besoin de la propriété '{1}'. La configuration de la tâche sera ignorée.", "ConfigurationParser.notCustom": "Erreur : la tâche n'est pas déclarée comme une tâche personnalisée. La configuration est ignorée.\n{0}\n", "ConfigurationParser.noTaskName": "Erreur : un tâche doit fournir une propriété label. La tâche va être ignorée.\n{0}\n", - "taskConfiguration.shellArgs": "Avertissement : la tâche '{0}' est une commande shell et un de ses arguments peut avoir des espaces non échappés. Afin d’assurer un échappement correct des guillemets dans la ligne de commande, veuillez fusionner les arguments dans la commande.", "taskConfiguration.noCommandOrDependsOn": "Erreur : La tâche '{0}' ne spécifie ni une commande, ni une propriété dependsOn. La tâche est ignorée. Sa définition est :\n{1}", "taskConfiguration.noCommand": "Erreur : La tâche '{0}' ne définit aucune commande. La tâche va être ignorée. Sa définition est :\n{1}", "TaskParse.noOsSpecificGlobalTasks": "Task Version 2.0.0 ne supporte pas les tâches spécifiques globales du système d'exploitation. Convertissez-les en une tâche en une commande spécifique du système d'exploitation. Les tâches concernées sont : {0}" diff --git a/i18n/fra/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..e89604d819 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "Couleur d'arrière-plan du terminal, permet d'appliquer au terminal une couleur différente de celle du panneau.", + "terminal.foreground": "Couleur de premier plan du terminal.", + "terminalCursor.foreground": "La couleur de premier plan du curseur du terminal.", + "terminalCursor.background": "La couleur d’arrière-plan du curseur terminal. Permet de personnaliser la couleur d’un caractère recouvert par un curseur de bloc.", + "terminal.selectionBackground": "La couleur d’arrière-plan de sélection du terminal.", + "terminal.border": "Couleur de bordure qui sépare les volets de fractionnement dans le terminal. La valeur par défaut est panel.border.", + "terminal.ansiColor": "Couleur ansi '{0}' dans le terminal." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 3f84e8eb7a..6b0c31c403 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "Sélectionner le répertoire de travail actuel pour le nouveau terminal", "workbench.action.terminal.newInActiveWorkspace": "Créer un nouveau Terminal intégré (dans l'espace de travail actif)", "workbench.action.terminal.split": "Diviser le terminal", + "workbench.action.terminal.splitInActiveWorkspace": "Diviser le Terminal (dans l'espace de travail actif)", "workbench.action.terminal.focusPreviousPane": "Focus sur le panneau précédent", "workbench.action.terminal.focusNextPane": "Focus sur le panneau suivant", "workbench.action.terminal.resizePaneLeft": "Redimensionner le panneau vers la gauche", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "Faire défiler vers le haut (page)", "workbench.action.terminal.scrollToTop": "Faire défiler jusqu'en haut", "workbench.action.terminal.clear": "Effacer", + "workbench.action.terminal.clearSelection": "Effacer la sélection", "workbench.action.terminal.allowWorkspaceShell": "Autoriser la configuration de l'interpréteur de commandes de l'espace de travail", "workbench.action.terminal.disallowWorkspaceShell": "Interdire la configuration de l'interpréteur de commandes de l'espace de travail", "workbench.action.terminal.rename": "Renommer", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Masquer le widget de recherche", "nextTerminalFindTerm": "Afficher le terme de recherche suivant", "previousTerminalFindTerm": "Afficher le terme de recherche précédent", - "quickOpenTerm": "Changer de terminal actif" + "quickOpenTerm": "Changer de terminal actif", + "workbench.action.terminal.scrollToPreviousCommand": "Faire défiler jusqu'à la commande précédente", + "workbench.action.terminal.scrollToNextCommand": "Faire défiler jusqu'à la prochaine commande", + "workbench.action.terminal.selectToPreviousCommand": "Sélectionnez pour la commande précédente", + "workbench.action.terminal.selectToNextCommand": "Sélectionnez pour la commande suivante" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index e85c85aa5f..25c572920e 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "Le terminal n'a aucune sélection à copier", "terminal.integrated.exitedWithCode": "Le processus du terminal s'est achevé avec le code de sortie {0}", "terminal.integrated.waitOnExit": "Appuyez sur une touche pour fermer le terminal", - "terminal.integrated.launchFailed": "Échec du lancement de la commande de traitement du terminal '{0}{1}' (code de sortie : {2})" + "terminal.integrated.launchFailed": "Échec du lancement de la commande de traitement du terminal '{0}{1}' (code de sortie : {2})", + "terminal.integrated.launchFailedExtHost": "Impossible de démarrer le processus du terminal (code de sortie : {0})" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index eca89b2430..9f916b323f 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "Copier", + "split": "Diviser", "paste": "Coller", "selectAll": "Tout Sélectionner", - "clear": "Effacer", - "split": "Diviser" + "clear": "Effacer" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 1e8e95ff0d..8d57e3f50f 100644 --- a/i18n/fra/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Cet espace de travail contient des paramètres qui ne peuvent être définis que dans les paramètres utilisateur ({0}). Cliquez [ici]({1}) pour en savoir plus.", "openWorkspaceSettings": "Ouvrir les paramètres d'espace de travail", - "dontShowAgain": "Ne plus afficher", - "unsupportedWorkspaceSettings": "Cet espace de travail contient des paramètres qui ne peuvent être définis que dans les paramètres utilisateur ({0}). Cliquez [ici]({1}) pour en savoir plus." + "dontShowAgain": "Ne plus afficher" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..68cda1a5f0 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Notes de publication : {0}", + "unassigned": "non assigné" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 7fe8f1b377..1c0f5e94e4 100644 --- a/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Plus tard", - "unassigned": "non assigné", "releaseNotes": "Notes de publication", "showReleaseNotes": "Afficher les notes de publication", "read the release notes": "Bienvenue dans {0} v{1} ! Voulez-vous lire les notes de publication ?", @@ -17,13 +15,14 @@ "updateIsReady": "Nouvelle mise à jour de {0} disponible.", "noUpdatesAvailable": "Aucune mise à jour n'est disponible actuellement.", "ok": "OK", - "download now": "Télécharger maintenant", "thereIsUpdateAvailable": "Une mise à jour est disponible.", - "installUpdate": "Installer la mise à jour", + "download now": "Télécharger maintenant", + "later": "Plus tard", "updateAvailable": "Il y a une mise à jour disponible : {0} {1}", + "installUpdate": "Installer la mise à jour", "updateInstalling": "{0} {1} est en train d'être installé en arrière-plan, nous vous ferons savoir quand c’est fini.", + "updateAvailableAfterRestart": "Redémarrer {0} pour appliquer la dernière mise à jour.", "updateNow": "Mettre à jour maintenant", - "updateAvailableAfterRestart": "{0} sera mis à jour après avoir redémarré.", "commandPalette": "Palette de commandes...", "settings": "Paramètres", "keyboardShortcuts": "Raccourcis clavier", diff --git a/i18n/fra/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..de2f45279f --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "Ouvrir le lien", + "developer": "Développeur" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..da5ba7cccb --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "éditeur webview", + "developer": "Développeur" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..09dc435705 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Ouvrir les outils de développement Webview", + "refreshWebviewLabel": "Recharger les Webviews" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/fra/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..f34ed7abe6 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Aidez-nous à améliorer VS Code en permettant à Microsoft de recueillir des données d’utilisation. Lisez notre [déclaration sur la vie privée]({0}) et apprenez comment [se désengager]({1}).", + "telemetryOptOut.optInNotice": "Aidez-nous à améliorer VS Code en permettant à Microsoft de recueillir des données d’utilisation. Lisez notre [déclaration sur la vie privée]({0}) et apprenez comment [se désengager]({1}).", + "telemetryOptOut.readMore": "Lire la suite" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/fra/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index f435184d20..63b1c5d06a 100644 --- a/i18n/fra/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Gérer les extensions", "welcomeOverlay.problems": "Afficher les erreurs et avertissements", "welcomeOverlay.commandPalette": "Rechercher et exécuter toutes les commandes", + "welcomeOverlay.notifications": "Afficher les notifications", "welcomeOverlay": "Vue d'ensemble de l'interface utilisateur", "hideWelcomeOverlay": "Masquer la vue d'ensemble de l'interface", "help": "Aide" diff --git a/i18n/fra/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/fra/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 149ec49be0..3507268e12 100644 --- a/i18n/fra/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Outils et langages", "welcomePage.installExtensionPacksDescription": "Installer un support pour {0} et {1}", "welcomePage.moreExtensions": "plus", - "welcomePage.installKeymapDescription": "Installer les raccourcis clavier", - "welcomePage.installKeymapExtension": "Installer les raccourcis clavier de {0} et {1}", + "welcomePage.installKeymapDescription": "Paramètres et combinaisons de touches", + "welcomePage.installKeymapExtension": "Installer les paramètres et les raccourcis clavier de {0} et {1}", "welcomePage.others": "autres", "welcomePage.colorTheme": "Thème de couleur", "welcomePage.colorThemeDescription": "Personnalisez l'apparence de l'éditeur et de votre code", diff --git a/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 9b508357a2..3b05950f1a 100644 --- a/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/fra/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Résumé des paramètres. Cette étiquette va être utilisée dans le fichier de paramètres en tant que commentaire de séparation.", "vscode.extension.contributes.configuration.properties": "Description des propriétés de configuration.", + "scope.application.description": "Configuration spécifique de l'application, qui peut être configurée uniquement dans les paramètres utilisateur.", "scope.window.description": "Configuration spécifique de la fenêtre, qui peut être configurée dans les paramètres utilisateur ou de l'espace de travail.", "scope.resource.description": "Configuration spécifique de la ressource, qui peut être configurée dans les paramètres utilisateur, de l'espace de travail ou du dossier.", "scope.description": "Portée dans laquelle la configuration s’applique. Les portées disponibles sont `window` et `resource`.", diff --git a/i18n/fra/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/fra/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 69c2a4c69a..be89cee605 100644 --- a/i18n/fra/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Ouvrir les paramètres", "saveAndRetry": "Enregistrer et Réessayer", "errorUnknownKey": "Impossible d’écrire dans {0} car {1} n’est pas une configuration recommandée.", + "errorInvalidWorkspaceConfigurationApplication": "Impossible d’écrire {0} dans paramètres de l’espace de travail. Ce paramètre peut être écrit uniquement dans les paramètres de l’utilisateur.", "errorInvalidFolderConfiguration": "Impossible d’écrire dans les paramètres de dossier parce que {0} ne supporte pas la portée de ressource de dossier.", "errorInvalidUserTarget": "Impossible d’écrire dans les paramètres utilisateur parce que {0} ne supporte pas de portée globale.", "errorInvalidWorkspaceTarget": "Impossible d’écrire dans les paramètres de l’espace de travail car {0} ne supporte pas de portée d’espace de travail dans un espace de travail multi dossiers.", diff --git a/i18n/fra/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/fra/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..c28d44842a --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Ce paramètre ne peut être appliqué que dans les paramètres utilisateur", + "unsupportedWindowSetting": "Ce paramètre ne peut pas être appliqué maintenant. Il est appliqué quand vous ouvrez ce dossier directement." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/fra/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..e5809c2c66 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "canNotResolveWorkspaceFolderMultiRoot": "'${workspaceFolder}' ne peut pas être résolu dans un espace de travail de dossiers multiples. Gérer la portée de cette variable en utilisant ':' et un nom de dossier d’espace de travail.", + "canNotResolveWorkspaceFolder": "'${workspaceFolder}' ne peut pas être résolu. Veuillez ouvrir un dossier.", + "canNotResolveFolderBasenameMultiRoot": "'${workspaceFolderBasename}' ne peut pas être résolu dans un espace de travail de dossiers multiples. Gérer la portée de cette variable en utilisant ':' et un nom de dossier d’espace de travail.", + "canNotResolveFolderBasename": "'${workspaceFolderBasename}' ne peut pas être résolu. Veuillez ouvrir un dossier.", + "canNotResolveLineNumber": "'${lineNumber}' ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveSelectedText": "'${selectedText}' ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveFile": "${file} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveRelativeFile": "${relativeFile} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveFileDirname": "${fileDirname} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveFileExtname": "${fileExtname} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveFileBasename": "${fileBasename} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur.", + "canNotResolveFileBasenameNoExtension": "${fileBasenameNoExtension} ne peut pas être résolu. Veuillez s’il vous plaît ouvrir un éditeur." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/fra/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..26aac19855 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "'{0}' ne peut pas être résolu car aucun nom de variable d’environnement n’est donné.", + "configNotFound": "'{0}' ne peut pas être résolu car le paramètre '{1}' est introuvable.", + "configNoString": "'{0}' ne peut pas être résolu car '{1}' est une valeur structurée.", + "missingConfigName": "'{0}' ne peut pas être résolu car aucun nom de paramètre n'est donné.", + "noValueForCommand": "Impossible de résoudre '{0}', car la commande n'a pas de valeur.", + "canNotFindFolder": "'{0}' ne peut pas être résolu. Aucun dossier '{1}'.", + "canNotResolveWorkspaceFolderMultiRoot": "'{0}' ne peut pas être résolu dans un espace de travail de dossiers multiples. Gérer la portée cette variable en utilisant ':' et un nom de dossier d’espace de travail.", + "canNotResolveWorkspaceFolder": "'{0}' ne peut pas être résolu. Veuillez ouvrir un dossier.", + "canNotResolveFile": "'{0}' ne peut pas être résolu. Veuillez ouvrir un éditeur.", + "canNotResolveLineNumber": "'{0}' ne peut pas être résolu. Assurez-vous d’avoir une ligne sélectionnée dans l’éditeur actif.", + "canNotResolveSelectedText": "'{0}' ne peut pas être résolu. Assurez-vous que vous avez du texte sélectionné dans l’éditeur actif." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/fra/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..ad189dada9 --- /dev/null +++ b/i18n/fra/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Oui", + "cancelButton": "Annuler" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/fra/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index ba8510e3e1..d368558993 100644 --- a/i18n/fra/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/fra/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Compatibilité de moteur.", "vscode.extension.engines.vscode": "Pour les extensions VS Code, spécifie la version de VS Code avec laquelle l'extension est compatible. Ne peut pas être *. Exemple : ^0.10.5 indique une compatibilité avec la version minimale 0.10.5 de VS Code.", "vscode.extension.publisher": "Éditeur de l'extension VS Code.", "vscode.extension.displayName": "Nom d'affichage de l'extension utilisée dans la galerie VS Code.", "vscode.extension.categories": "Catégories utilisées par la galerie VS Code pour catégoriser l'extension.", + "vscode.extension.category.languages.deprecated": "Utiliser 'Langages de programmation' à la place", "vscode.extension.galleryBanner": "Bannière utilisée dans le marketplace VS Code.", "vscode.extension.galleryBanner.color": "Couleur de la bannière de l'en-tête de page du marketplace VS Code.", "vscode.extension.galleryBanner.theme": "Thème de couleur de la police utilisée dans la bannière.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Événement d'activation envoyé quand une session de débogage du type spécifié est sur le point d’être lancée (et une méthode resolveDebugConfiguration correspondante doit être appelée).", "vscode.extension.activationEvents.workspaceContains": "Événement d'activation envoyé quand un dossier ouvert contient au moins un fichier correspondant au modèle glob spécifié.", "vscode.extension.activationEvents.onView": "Événement d'activation envoyé quand la vue spécifiée est développée.", + "vscode.extension.activationEvents.onUri": "Événement d'activation envoyé quand un URI système dirigé vers cette extension est ouvert.", "vscode.extension.activationEvents.star": "Événement d'activation envoyé au démarrage de VS Code. Pour garantir la qualité de l'expérience utilisateur, utilisez cet événement d'activation dans votre extension uniquement quand aucune autre combinaison d'événements d'activation ne fonctionne dans votre cas d'utilisation.", "vscode.extension.badges": "Ensemble de badges à afficher dans la barre latérale de la page d'extensions de Marketplace.", "vscode.extension.badges.url": "URL de l'image du badge.", "vscode.extension.badges.href": "Lien du badge.", "vscode.extension.badges.description": "Description du badge.", + "vscode.extension.markdown": "Contrôle le moteur de rendu de Markdown utilisé sur le marché. Github (par défaut) ou standard.", + "vscode.extension.qna": "Contrôle le lien Q&A sur le marché. Mettre à marketplace pour activer le site de Q&A du Marketplace par défaut. Mettre une chaîne pour fournir l’URL d’un site personnalisé de Q&A. Mettre à false pour désactiver complètement les Q&A.", "vscode.extension.extensionDependencies": "Dépendances envers d'autres extensions. L'identificateur d'une extension est toujours ${publisher}.${name}. Exemple : vscode.csharp.", "vscode.extension.scripts.prepublish": "Le script exécuté avant le package est publié en tant qu'extension VS Code.", "vscode.extension.scripts.uninstall": "Désinstallez le crochet pour l'extension VS Code. Script exécuté quand l'extension est complètement désinstallée dans VS Code et au redémarrage de VS Code (arrêt, puis démarrage). Seuls les scripts Node sont pris en charge.", diff --git a/i18n/fra/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/fra/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 0c2e69290b..81bb41578d 100644 --- a/i18n/fra/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Toutes les extensions sont désactivées.", "extensionHostProcess.crash": "L'hôte d’extension s'est arrêté de manière inattendue.", "extensionHostProcess.unresponsiveCrash": "L'hôte d'extension s'est arrêté, car il ne répondait pas.", - "devTools": "Outils de développement", + "devTools": "Ouvrir les outils de développement", "restart": "Redémarrer l’hôte d'extension", "overwritingExtension": "Remplacement de l'extension {0} par {1}.", "extensionUnderDevelopment": "Chargement de l'extension de développement sur {0}", diff --git a/i18n/fra/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/fra/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 4e5bf5c5f7..bd1e816363 100644 --- a/i18n/fra/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5 est obligatoire. Suivez le lien pour l'installer.", "installNet": "Télécharger .NET Framework 4.5", "neverShowAgain": "Ne plus afficher", - "netVersionError": "Microsoft .NET Framework 4.5 est obligatoire. Suivez le lien pour l'installer.", + "enospcError": "{0} n’est pas en mesure de surveiller les modifications de fichiers dans ce grand espace de travail. Veuillez suivre le lien d'instructions pour résoudre ce problème.", "learnMore": "Instructions", - "enospcError": "{0} est à court de mémoire pour les fichiers. Veuillez suivre le lien avec les instructions pour résoudre ce problème.", + "fileInvalidPath": "Ressource de fichier non valide ({0})", + "fileIsDirectoryError": "Le fichier est un répertoire", + "fileNotModifiedError": "Fichier non modifié depuis", + "fileTooLargeForHeapError": "Pour ouvrir un fichier de cette taille, vous devez redémarrer VS Code et lui permettre d’utiliser plus de mémoire", + "fileTooLargeError": "Fichier trop volumineux pour être ouvert", + "fileNotFoundError": "Fichier introuvable ({0})", + "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte", + "filePermission": "Autorisation refusée en écrivant dans le fichier ({0})", + "fileExists": "Le fichier à créer existe déjà ({0})", + "fileModifiedError": "Fichier modifié depuis", + "fileReadOnlyError": "Fichier en lecture seule", + "fileMoveConflict": "Déplacement/copie impossible. Le fichier existe déjà dans la destination.", + "unableToMoveCopyError": "Impossible de déplacer/copier. Le fichier remplace le dossier qui le contient.", "binFailed": "Échec du déplacement de '{0}' vers la corbeille", "trashFailed": "Échec du déplacement de '{0}' vers la corbeille" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 069db57fc4..ca83618f2f 100644 --- a/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Fichier introuvable ({0})", "fileIsDirectoryError": "Le fichier est un répertoire", "fileNotModifiedError": "Fichier non modifié depuis", - "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte" + "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte", + "err.create": "Impossible de créer le fichier {0}", + "fileMoveConflict": "Déplacement/copie impossible. Le fichier existe déjà dans la destination." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json index 06d2c12f7f..7d6937255c 100644 --- a/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,6 @@ "fileInvalidPath": "Ressource de fichier non valide ({0})", "fileIsDirectoryError": "Le fichier est un répertoire", "fileNotModifiedError": "Fichier non modifié depuis", - "fileTooLargeForHeapError": "La taille du ficher dépasse la limite de mémoire, veuillez essayer d'exécuter code --max-memory=NEWSIZE", "fileTooLargeError": "Fichier trop volumineux pour être ouvert", "fileNotFoundError": "Fichier introuvable ({0})", "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte", diff --git a/i18n/fra/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/fra/src/vs/workbench/services/progress/browser/progressService2.i18n.json index cb9dc6da3b..5a31cdd999 100644 --- a/i18n/fra/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/fra/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0} : {1}" + "progress.title": "{0} : {1}", + "cancel": "Annuler" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index c8b66e5f19..026ab52e5e 100644 --- a/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Nom de portée TextMate utilisé par le fichier tmLanguage.", "vscode.extension.contributes.grammars.path": "Chemin du fichier tmLanguage. Le chemin est relatif au dossier d'extensions et commence généralement par './syntaxes/'.", "vscode.extension.contributes.grammars.embeddedLanguages": "Mappage du nom de portée à l'ID de langage si cette grammaire contient des langages incorporés.", + "vscode.extension.contributes.grammars.tokenTypes": "Un mappage entre un nom d'étendue et des types de token.", "vscode.extension.contributes.grammars.injectTo": "Liste de noms des portées de langage auxquelles cette grammaire est injectée." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 10730e67a6..231f70c984 100644 --- a/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/fra/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "Chaîne attendue dans 'contributes.{0}.path'. Valeur fournie : {1}", "invalid.injectTo": "Valeur non valide dans 'contributes.{0}.injectTo'. Il doit s'agir d'un tableau de noms de portées de langage. Valeur fournie : {1}", "invalid.embeddedLanguages": "Valeur non valide dans 'contributes.{0}.embeddedLanguages'. Il doit s'agir d'un mappage d'objets entre le nom de portée et le langage. Valeur fournie : {1}", + "invalid.tokenTypes": "Valeur non valide dans 'contribue.{0}.tokenTypes'. Il doit s'agir d'un mappage d’objets entre un nom d’étendue et un type de jeton. Valeur fournie : {1}", "invalid.path.1": "'contributes.{0}.path' ({1}) est censé être inclus dans le dossier ({2}) de l'extension. Cela risque de rendre l'extension non portable.", "no-tm-grammar": "Aucune grammaire TM n'est inscrite pour ce langage." } \ No newline at end of file diff --git a/i18n/hun/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/hun/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..762d665d83 --- /dev/null +++ b/i18n/hun/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS nyelvi szerver", + "folding.start": "Összecsukható tartomány kezdete", + "folding.end": "Összecsukható tartomány vége" +} \ No newline at end of file diff --git a/i18n/hun/extensions/css-language-features/package.i18n.json b/i18n/hun/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..aadc8f5c6f --- /dev/null +++ b/i18n/hun/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás CSS-, LESS- és SCSS-fájlokhoz.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", + "css.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", + "css.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", + "css.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", + "css.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", + "css.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", + "css.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", + "css.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", + "css.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", + "css.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", + "css.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", + "css.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", + "css.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", + "css.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", + "css.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", + "css.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", + "css.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", + "css.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", + "css.trace.server.desc": "A VS Code és a CSS nyelvi szerver közötti kommunikáció naplózása.", + "css.validate.title": "Meghatározza a CSS-validáció működését és a problémák súlyosságát.", + "css.validate.desc": "Összes validálás engedélyezése vagy letiltása", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", + "less.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", + "less.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", + "less.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", + "less.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", + "less.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", + "less.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", + "less.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", + "less.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", + "less.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", + "less.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", + "less.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", + "less.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", + "less.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", + "less.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", + "less.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", + "less.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", + "less.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", + "less.validate.title": "Meghatározza a LESS-validáció működését és a problémák súlyosságát.", + "less.validate.desc": "Összes validálás engedélyezése vagy letiltása", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", + "scss.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", + "scss.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", + "scss.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", + "scss.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", + "scss.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", + "scss.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", + "scss.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", + "scss.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", + "scss.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", + "scss.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", + "scss.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", + "scss.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", + "scss.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", + "scss.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", + "scss.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", + "scss.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", + "scss.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", + "scss.validate.title": "Meghatározza az SCSS-validáció működését és a problémák súlyosságát.", + "scss.validate.desc": "Összes validálás engedélyezése vagy letiltása", + "less.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", + "scss.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", + "css.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", + "css.colorDecorators.enable.deprecationMessage": "Az `css.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt.", + "scss.colorDecorators.enable.deprecationMessage": "Az `scss.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt.", + "less.colorDecorators.enable.deprecationMessage": "A `less.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt." +} \ No newline at end of file diff --git a/i18n/hun/extensions/css/package.i18n.json b/i18n/hun/extensions/css/package.i18n.json index 67257bd8a5..a7af29e361 100644 --- a/i18n/hun/extensions/css/package.i18n.json +++ b/i18n/hun/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS nyelvi funkciók", - "description": "Széleskörű nyelvi támogatás CSS-, LESS- és SCSS-fájlokhoz.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", - "css.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", - "css.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", - "css.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", - "css.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", - "css.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", - "css.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", - "css.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", - "css.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", - "css.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", - "css.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", - "css.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", - "css.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", - "css.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", - "css.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", - "css.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", - "css.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", - "css.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", - "css.trace.server.desc": "A VS Code és a CSS nyelvi szerver közötti kommunikáció naplózása.", - "css.validate.title": "Meghatározza a CSS-validáció működését és a problémák súlyosságát.", - "css.validate.desc": "Összes validálás engedélyezése vagy letiltása", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", - "less.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", - "less.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", - "less.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", - "less.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", - "less.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", - "less.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", - "less.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", - "less.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", - "less.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", - "less.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", - "less.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", - "less.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", - "less.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", - "less.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", - "less.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", - "less.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", - "less.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", - "less.validate.title": "Meghatározza a LESS-validáció működését és a problémák súlyosságát.", - "less.validate.desc": "Összes validálás engedélyezése vagy letiltása", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Nem megfelelő számú paraméter", - "scss.lint.boxModel.desc": "A width és a height tulajdonság kerülése a padding és a border tulajdonság használata esetén", - "scss.lint.compatibleVendorPrefixes.desc": "Gyártóspecifikus előtag használata esetén minden más gyártóspecifikus tulajdonságot is meg kell adni", - "scss.lint.duplicateProperties.desc": "Duplikált stílusdefiníciók kerülése", - "scss.lint.emptyRules.desc": "Üres szabályhalmazok kerülése", - "scss.lint.float.desc": "A float tulajdonságérték kerülése, mivel könnyen váratlan eredményt idézhet elő az elrendezés változásakor.", - "scss.lint.fontFaceProperties.desc": "A @font-face szabályokban az src és a font-family tulajdonságot is definiálni kell", - "scss.lint.hexColorLength.desc": "A hexadecimális formában megadott színeknek három vagy hat hexadecimális számjegyből kell állniuk", - "scss.lint.idSelector.desc": "A szelektorok nem tartalmazhatnak azonosítókat, mivel az ilyen szabályok túl szorosan kötődnek a HTML-hez.", - "scss.lint.ieHack.desc": "Az IE hangolása csak az IE7 vagy régebbi verziók támogatása esetén szükséges", - "scss.lint.important.desc": "Az !important attribútum mellőzése. Az attribútum jelenléte arra utal, hogy a CSS-struktúra átláthatatlanná vált, és refaktorálásra szorul.", - "scss.lint.importStatement.desc": "Ne töltődjenek párhuzamosan az importálási utasítások", - "scss.lint.propertyIgnoredDueToDisplay.desc": "A megjelenítési mód miatt a megjelenítőkomponensek nem fogják figyelembe venni a tulajdonságot. Ha például a display tulajdonság értéke inline, akkor a megjelenítők figyelmen kívül hagyják a width, a height, a margin-top, a margin-bottom és a float tulajdonságot.", - "scss.lint.universalSelector.desc": "Az univerzális szelektor (*) lassú működést eredményez", - "scss.lint.unknownProperties.desc": "Ismeretlen tulajdonság.", - "scss.lint.unknownVendorSpecificProperties.desc": "Ismeretlen gyártóspecifikus tulajdonság.", - "scss.lint.vendorPrefix.desc": "Gyártóspecifikus előtagok használata esetén az adott tulajdonság szabványos változatát is meg kell adni", - "scss.lint.zeroUnits.desc": "A 0 értékhez nem szükséges mértékegység", - "scss.validate.title": "Meghatározza az SCSS-validáció működését és a problémák súlyosságát.", - "scss.validate.desc": "Összes validálás engedélyezése vagy letiltása", - "less.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", - "scss.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", - "css.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", - "css.colorDecorators.enable.deprecationMessage": "Az `css.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt.", - "scss.colorDecorators.enable.deprecationMessage": "Az `scss.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt.", - "less.colorDecorators.enable.deprecationMessage": "A `less.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt." + "displayName": "CSS nyelvi alapok", + "description": "Szintaktikai kiemelést szolgáltat, valamint kezeli az összetartozó zárójeleket a CSS-, LESS- és SCSS-fájlokban." } \ No newline at end of file diff --git a/i18n/hun/extensions/emmet/package.i18n.json b/i18n/hun/extensions/emmet/package.i18n.json index 2cbe530b05..a02b4a28ce 100644 --- a/i18n/hun/extensions/emmet/package.i18n.json +++ b/i18n/hun/extensions/emmet/package.i18n.json @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "CSS-tulajdonságok vesszővel ellátott listája, melyek 'webkit' gyártói előtagot kapnak azoknál az Emmet-rövidtéseknél, melyek `-` karakterrel kezdődnek. Állítsa üres szövegre, ha soha nem szeretne 'webkit' előtagot használni.", "emmetPreferencesCssMozProperties": "CSS-tulajdonságok vesszővel ellátott listája, melyek 'moz' gyártói előtagot kapnak azoknál az Emmet-rövidtéseknél, melyek `-` karakterrel kezdődnek. Állítsa üres szövegre, ha soha nem szeretne 'moz' előtagot használni.", "emmetPreferencesCssOProperties": "CSS-tulajdonságok vesszővel ellátott listája, melyek 'o' gyártói előtagot kapnak azoknál az Emmet-rövidtéseknél, melyek `-` karakterrel kezdődnek. Állítsa üres szövegre, ha soha nem szeretne 'o' előtagot használni.", - "emmetPreferencesCssMsProperties": "CSS-tulajdonságok vesszővel ellátott listája, melyek 'ms' gyártói előtagot kapnak azoknál az Emmet-rövidtéseknél, melyek `-` karakterrel kezdődnek. Állítsa üres szövegre, ha soha nem szeretne 'ms' előtagot használni." + "emmetPreferencesCssMsProperties": "CSS-tulajdonságok vesszővel ellátott listája, melyek 'ms' gyártói előtagot kapnak azoknál az Emmet-rövidtéseknél, melyek `-` karakterrel kezdődnek. Állítsa üres szövegre, ha soha nem szeretne 'ms' előtagot használni.", + "emmetPreferencesCssFuzzySearchMinScore": "A minimális pontszám (0-tól 1-ig), amit egy fuzzy keresési találatnak el kell érnie. Az alacsonyabb értékek álpozitív találatokat eredményezhetnek, míg a magasabb értékek szűkítik a lehetséges találatok számát.", + "emmetOptimizeStylesheetParsing": "Ha az értéke false, az egész fájl fel lesz dolgozva annak meghatározásához, hogy az aktuális pozíció ércényes-e Emmet-rövidítések kibontásához. Ha az értéke true, csak az aktuális pozíció körüli tartalom lesz feldolgozva a CSS/SCSS/LESS-fájlokban." } \ No newline at end of file diff --git a/i18n/hun/extensions/git/out/commands.i18n.json b/i18n/hun/extensions/git/out/commands.i18n.json index a0878a84e2..3e7a779ae0 100644 --- a/i18n/hun/extensions/git/out/commands.i18n.json +++ b/i18n/hun/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Új ág létrehozása", "repourl": "Forráskódtár URL-címe", "parent": "Szülőkönyvtár", - "cancel": "$(sync~spin) Forráskódtár klónozása... Kattintson ide a megszakításhoz", - "cancel tooltip": "Klónozás megszakítása", - "cloning": "Git-forráskódtár klónozása...", + "cloning": "'{0}' git forráskódtár klónozása...", "openrepo": "Forráskódtár megnyitása", "proposeopen": "Szeretné megnyitni a klónozott forráskódtárat?", "init": "Válasszon munkaterületi mappát a Git-forráskódtár inicializálásához!", @@ -75,7 +73,7 @@ "ok": "OK", "push with tags success": "A címkékkel együtt történő pusholás sikeresen befejeződött.", "pick remote": "Válassza ki a távoli szervert, ahová publikálni szeretné a(z) '{0}' ágat:", - "sync is unpredictable": "Ez a művelet pusholja és pullozza a commitokat a következő helyről: '{0}'.", + "sync is unpredictable": "Ez a művelet pusholja és pullozza a commitokat a következő helyről: '{0}/{1}'.", "never again": "Rendben, ne jelenjen meg újra", "no remotes to publish": "A forráskódtárhoz nincsenek távoli szerverek konfigurálva, ahová publikálni lehetne.", "no changes stash": "Nincs elrakandó módosítás.", diff --git a/i18n/hun/extensions/git/package.i18n.json b/i18n/hun/extensions/git/package.i18n.json index 6fd7a29810..84ba1c3bc5 100644 --- a/i18n/hun/extensions/git/package.i18n.json +++ b/i18n/hun/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Meghatározza, hogy megjelenjen-e a sorok között egy 'Fájl megnyitása' művelet a git változások nézetén.", "config.inputValidation": "Meghatározza, hogy mikor jelenjen meg a beadási üzenet validálása.", "config.detectSubmodules": "Meghatározza, hogy automatikusan fel legyenek-e derítve a git almodulok.", + "config.detectSubmodulesLimit": "Korlátozza a felderített git almodulok számát.", "colors.modified": "A módosított erőforrások színe.", "colors.deleted": "A törölt erőforrások színe.", "colors.untracked": "A nem követett erőforrások színe.", diff --git a/i18n/hun/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/hun/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..8b705a9740 --- /dev/null +++ b/i18n/hun/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML nyelvi szerver", + "folding.start": "Összecsukható tartomány kezdete", + "folding.end": "Összecsukható tartomány vége" +} \ No newline at end of file diff --git a/i18n/hun/extensions/html-language-features/package.i18n.json b/i18n/hun/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..c4e070a679 --- /dev/null +++ b/i18n/hun/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás HTML-, Razor- és Handlebar-fájlokhoz.", + "html.format.enable.desc": "Alapértelmezett HTML-formázó engedélyezése vagy letiltása.", + "html.format.wrapLineLength.desc": "Maximális karakterszám soronként (0 = letiltás)", + "html.format.unformatted.desc": "Azon elemek vesszővel elválasztott listája, melyek ne legyenek újraformázva. 'null' érték esetén a https://www.w3.org/TR/html5/dom.html#phrasing-content oldalon listázott elemek lesznek használva.", + "html.format.contentUnformatted.desc": "Azon elemek vesszővel elválasztott listája, melyek ne legyenek újraformázva. 'null' érték esetén a 'pre' tag lesz használva.", + "html.format.indentInnerHtml.desc": "<head>- és <body>-szakaszok indentálása.", + "html.format.preserveNewLines.desc": "Az elemek előtt lévő sortörések meg legyenek-e hagyva. Csak elemek előtt működik, elemek belsejében vagy szövegben nem.", + "html.format.maxPreserveNewLines.desc": "Az egymás után megőrzött sortörések maximális száma. Ha nem szeretné korlátozni, használja a 'null' értéket!", + "html.format.indentHandlebars.desc": "{{#foo}} és {{/foo}} formázása és indentálása.", + "html.format.endWithNewline.desc": "Lezárás új sorral.", + "html.format.extraLiners.desc": "Azon elemek veszővel elválasztott listája, amelyek előtt lennie kell egy extra új sornak. 'null' érték esetén a \"head,body,/html\" érték van használva.", + "html.format.wrapAttributes.desc": "Attribútumok tördelése.", + "html.format.wrapAttributes.auto": "Az attribútumok csak akkor vannak tördelve, ha a sorhossz túl lett lépve.", + "html.format.wrapAttributes.force": "Minden egyes attribútum tördelve van, kivéve az elsőt.", + "html.format.wrapAttributes.forcealign": "Minden egyes attribútum tördelve van, kivéve az elsőt, és igazítva vannak.", + "html.format.wrapAttributes.forcemultiline": "Minden egyes attribútum tördelve van.", + "html.suggest.angular1.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e Angular V1 elemeket és tulajdonságokat.", + "html.suggest.ionic.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e Ionic elemeket, tulajdonságokat és értékeket.", + "html.suggest.html5.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e HTML5-ös elemeket, tulajdonságokat és értékeket.", + "html.trace.server.desc": "A VS Code és a HTML nyelvi szerver közötti kommunikáció naplózása.", + "html.validate.scripts": "Meghatározza, hogy a beépített HTML nyelvi támogatás validálja-e a beágyazott parancsafájlokat.", + "html.validate.styles": "Meghatározza, hogy a beépített HTML nyelvi támogatás validálja-e a beágyazott stílusfájlokat.", + "html.autoClosingTags": "HTML-elemek automatikus lezárásának engedélyezése vagy tetiltása." +} \ No newline at end of file diff --git a/i18n/hun/extensions/html/package.i18n.json b/i18n/hun/extensions/html/package.i18n.json index 444e54099a..b47841424c 100644 --- a/i18n/hun/extensions/html/package.i18n.json +++ b/i18n/hun/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML nyelvi funkciók", - "description": "Széleskörű nyelvi támogatás HTML-, Razor- és Handlebar-fájlokhoz.", - "html.format.enable.desc": "Alapértelmezett HTML-formázó engedélyezése vagy letiltása.", - "html.format.wrapLineLength.desc": "Maximális karakterszám soronként (0 = letiltás)", - "html.format.unformatted.desc": "Azon elemek vesszővel elválasztott listája, melyek ne legyenek újraformázva. 'null' érték esetén a https://www.w3.org/TR/html5/dom.html#phrasing-content oldalon listázott elemek lesznek használva.", - "html.format.contentUnformatted.desc": "Azon elemek vesszővel elválasztott listája, melyek ne legyenek újraformázva. 'null' érték esetén a 'pre' tag lesz használva.", - "html.format.indentInnerHtml.desc": "<head>- és <body>-szakaszok indentálása.", - "html.format.preserveNewLines.desc": "Az elemek előtt lévő sortörések meg legyenek-e hagyva. Csak elemek előtt működik, elemek belsejében vagy szövegben nem.", - "html.format.maxPreserveNewLines.desc": "Az egymás után megőrzött sortörések maximális száma. Ha nem szeretné korlátozni, használja a 'null' értéket!", - "html.format.indentHandlebars.desc": "{{#foo}} és {{/foo}} formázása és indentálása.", - "html.format.endWithNewline.desc": "Lezárás új sorral.", - "html.format.extraLiners.desc": "Azon elemek veszővel elválasztott listája, amelyek előtt lennie kell egy extra új sornak. 'null' érték esetén a \"head,body,/html\" érték van használva.", - "html.format.wrapAttributes.desc": "Attribútumok tördelése.", - "html.format.wrapAttributes.auto": "Az attribútumok csak akkor vannak tördelve, ha a sorhossz túl lett lépve.", - "html.format.wrapAttributes.force": "Minden egyes attribútum tördelve van, kivéve az elsőt.", - "html.format.wrapAttributes.forcealign": "Minden egyes attribútum tördelve van, kivéve az elsőt, és igazítva vannak.", - "html.format.wrapAttributes.forcemultiline": "Minden egyes attribútum tördelve van.", - "html.suggest.angular1.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e Angular V1 elemeket és tulajdonságokat.", - "html.suggest.ionic.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e Ionic elemeket, tulajdonságokat és értékeket.", - "html.suggest.html5.desc": "Meghatározza, hogy a beépített HTML nyelvi támogatás ajánl-e HTML5-ös elemeket, tulajdonságokat és értékeket.", - "html.trace.server.desc": "A VS Code és a HTML nyelvi szerver közötti kommunikáció naplózása.", - "html.validate.scripts": "Meghatározza, hogy a beépített HTML nyelvi támogatás validálja-e a beágyazott parancsafájlokat.", - "html.validate.styles": "Meghatározza, hogy a beépített HTML nyelvi támogatás validálja-e a beágyazott stílusfájlokat.", - "html.experimental.syntaxFolding": "Szintaxisalapú becsukható kódrészletek engedélyezése vagy letiltása.", - "html.autoClosingTags": "HTML-elemek automatikus lezárásának engedélyezése vagy tetiltása." + "displayName": "HTML nyelvi alapok", + "description": "Szintaktikai kiemelést, összetartozó zárójelek kezelését és kódtöredékeket szolgáltat a HTML-fájlokhoz." } \ No newline at end of file diff --git a/i18n/hun/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/hun/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..7651ab518e --- /dev/null +++ b/i18n/hun/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON nyelvi szerver" +} \ No newline at end of file diff --git a/i18n/hun/extensions/json-language-features/package.i18n.json b/i18n/hun/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..ddfd0e82d1 --- /dev/null +++ b/i18n/hun/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás JSON-fájlokhoz.", + "json.schemas.desc": "Sémák hozzárendelése JSON-fájlokhoz a jelenlegi projektben", + "json.schemas.url.desc": "Egy séma URL-címe vagy egy séma relatív elérési útja az aktuális könyvtárban", + "json.schemas.fileMatch.desc": "Fájlminták tömbje, amely a JSON-fájlok sémákhoz való rendelésénél van használva.", + "json.schemas.fileMatch.item.desc": "Fájlminták tömbje, amely a JSON-fájlok sémákhoz való rendelésénél van használva. Tartalmazhat '*'-ot.", + "json.schemas.schema.desc": "Az adott URL-cím sémadefiníciója. A sémát csak a séma URL-címéhez való fölösleges lekérdezések megakadályozása érdekében kell megadni.", + "json.format.enable.desc": "Alapértelmezett JSON-formázó engedélyezése vagy letiltása (újraindítást igényel)", + "json.tracing.desc": "A VS Code és a JSON nyelvi szerver közötti kommunikáció naplózása.", + "json.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", + "json.colorDecorators.enable.deprecationMessage": "A `json.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt." +} \ No newline at end of file diff --git a/i18n/hun/extensions/json/package.i18n.json b/i18n/hun/extensions/json/package.i18n.json index 2f0cdf7c4a..55ffac6d3d 100644 --- a/i18n/hun/extensions/json/package.i18n.json +++ b/i18n/hun/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON nyelvi funkciók", - "description": "Széleskörű nyelvi támogatás JSON-fájlokhoz.", - "json.schemas.desc": "Sémák hozzárendelése JSON-fájlokhoz a jelenlegi projektben", - "json.schemas.url.desc": "Egy séma URL-címe vagy egy séma relatív elérési útja az aktuális könyvtárban", - "json.schemas.fileMatch.desc": "Fájlminták tömbje, amely a JSON-fájlok sémákhoz való rendelésénél van használva.", - "json.schemas.fileMatch.item.desc": "Fájlminták tömbje, amely a JSON-fájlok sémákhoz való rendelésénél van használva. Tartalmazhat '*'-ot.", - "json.schemas.schema.desc": "Az adott URL-cím sémadefiníciója. A sémát csak a séma URL-címéhez való fölösleges lekérdezések megakadályozása érdekében kell megadni.", - "json.format.enable.desc": "Alapértelmezett JSON-formázó engedélyezése vagy letiltása (újraindítást igényel)", - "json.tracing.desc": "A VS Code és a JSON nyelvi szerver közötti kommunikáció naplózása.", - "json.colorDecorators.enable.desc": "Színdekorátorok engedélyezése vagy letiltása", - "json.colorDecorators.enable.deprecationMessage": "A `json.colorDecorators.enable` beállítás elavult az `editor.colorDecorators` bevezetése miatt.", - "json.experimental.syntaxFolding": "Szintaxisalapú becsukható kódrészletek engedélyezése vagy letiltása." + "displayName": "JSON nyelvi alapok", + "description": "Szintaktikai kiemelést szolgáltat, valamint kezeli az összetartozó zárójeleket a JSON-fájlokban." } \ No newline at end of file diff --git a/i18n/hun/extensions/markdown-basics/package.i18n.json b/i18n/hun/extensions/markdown-basics/package.i18n.json index de5c5fc134..25f466b5c0 100644 --- a/i18n/hun/extensions/markdown-basics/package.i18n.json +++ b/i18n/hun/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/hun/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/hun/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..9eab0fec46 --- /dev/null +++ b/i18n/hun/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "A 'markdown.styles' nem tölthető be: {0}" +} \ No newline at end of file diff --git a/i18n/hun/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/hun/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..a7a0c88748 --- /dev/null +++ b/i18n/hun/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Előnézet] {0}", + "previewTitle": "{0} előnézete" +} \ No newline at end of file diff --git a/i18n/hun/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/hun/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..0a920063d6 --- /dev/null +++ b/i18n/hun/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "A tartalom egy része le van tiltva az aktuális dokumentumban", + "preview.securityMessage.title": "Potencionálisan veszélyes vagy nem biztonságos tartalom lett letiltva a markdown-előnézetben. Módosítsa a markdown-előnézet biztonsági beállításait a nem biztonságos tartalmak vagy parancsfájlok engedélyezéséhez!", + "preview.securityMessage.label": "Biztonsági figyelmeztetés: tartalom le van tiltva" +} \ No newline at end of file diff --git a/i18n/hun/extensions/markdown-language-features/out/security.i18n.json b/i18n/hun/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..926e1ff93f --- /dev/null +++ b/i18n/hun/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Szigorú", + "strict.description": "Csak biztonságos tartalmak betöltése", + "insecureLocalContent.title": "Nem biztonságos helyi tartalom engedélyezése", + "insecureLocalContent.description": "Tartalom betöltésének engedélyezése HTTP-n keresztül localhostról.", + "insecureContent.title": "Nem biztonságos tartalom engedélyezése", + "insecureContent.description": "Tartalom betöltésének engedélyezése HTTP-n keresztül.", + "disable.title": "Letiltás", + "disable.description": "Minden tartalom és parancsfájl futtatásának engedélyezése. Nem ajánlott.", + "moreInfo.title": "További információ", + "enableSecurityWarning.title": "Előnézettel kapcsolatos biztonsági figyelmeztetések engedélyezése ezen a munkaterületen", + "disableSecurityWarning.title": "Előnézettel kapcsolatos biztonsági figyelmeztetések letiltása ezen a munkaterületen", + "toggleSecurityWarning.description": "Nem befolyásolja a tartalom biztonsági szintjét", + "preview.showPreviewSecuritySelector.title": "Válassza ki a munkaterület Markdown-előnézeteinek biztonsági beállítását!" +} \ No newline at end of file diff --git a/i18n/hun/extensions/markdown-language-features/package.i18n.json b/i18n/hun/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..5e8a854122 --- /dev/null +++ b/i18n/hun/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás Markdown-fájlokhoz.", + "markdown.preview.breaks.desc": "Meghatározza, hogy a sortörések hogyan vannak megjelenítve a markdown-előnézetben. Ha az értéke 'true', akkor minden egyes újsor esetén <br> jön létre.", + "markdown.preview.linkify": "URL-szerű szövegek hivatkozássá alakításának engedélyezése vagy letiltása a markdown-előnézetben.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Kattintson duplán a markdown-előnézetre a szerkesztőre való átváltáshoz.", + "markdown.preview.fontFamily.desc": "Meghatározza a markdown-előnézeten használt betűkészletet.", + "markdown.preview.fontSize.desc": "Meghatározza a markdown-előnézet betűméretét, pixelekben.", + "markdown.preview.lineHeight.desc": "Meghatározza a markdown-előnézeten használt sormagasságot. Az érték relatív a betűmérethez képest.", + "markdown.preview.markEditorSelection.desc": "Az aktuális kijelölés megjelölése a markdown-előnézeten", + "markdown.preview.scrollEditorWithPreview.desc": "Amikor a markdown-előnézetet görgetik, a szerkesztőnézet is aktualizálódik", + "markdown.preview.scrollPreviewWithEditor.desc": "Amikor a markdown-szerkesztőnézetet görgetik, az előnézet is aktualizálódik.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Elavult] A markdown-előnézetet úgy görgeti, hogy látni lehessen az aktuálisan kijelölt sort.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Ezt a beállítást leváltotta a 'markdown.preview.scrollPreviewWithEditor' beállítás, és már nincs hatása.", + "markdown.preview.title": "Előnézet megnyitása", + "markdown.previewFrontMatter.dec": "Meghatározza, hogy a YAML konfiguráció (front matter) hogyan legyen megjelenítve a markdown-előnézetben. A 'hide' elrejti a konfigurációt, minden más esetben a front matter markdown-tartalomként van kezelve.", + "markdown.previewSide.title": "Előnézet megnyitása oldalt", + "markdown.showLockedPreviewToSide.title": "Rögzített előnézet megnyitása oldalt", + "markdown.showSource.title": "Forrás megjelenítése", + "markdown.styles.dec": "CSS-stíluslapok URL-címeinek vagy helyi elérési útjainak listája, amelyek a markdown-előnézeten használva vannak. A relatív elérési utak az intézőben megnyitott mappához képest vannak relatívan értelmezve. Ha nincs mappa megnyitva, akkor a markdown-fájl elréséi útjához képest. Minden '\\' karaktert '\\\\' formában kell megadni.", + "markdown.showPreviewSecuritySelector.title": "Az előnézet biztonsági beállításainak módosítása", + "markdown.trace.desc": "Hibakeresési napló engedélyezése a markdown kiterjesztésben.", + "markdown.preview.refresh.title": "Előnézet frissítése", + "markdown.preview.toggleLock.title": "Előnézet rögzítésének be- és kikapcsolása" +} \ No newline at end of file diff --git a/i18n/hun/extensions/markdown/out/features/preview.i18n.json b/i18n/hun/extensions/markdown/out/features/preview.i18n.json index fd75fd37f2..a7a0c88748 100644 --- a/i18n/hun/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/hun/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/hun/extensions/npm/out/npmView.i18n.json b/i18n/hun/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..90269483e9 --- /dev/null +++ b/i18n/hun/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "A(z) „{0}” nem indítható el hibakereséshez, mert a parancsból hiányzik a node hibakeresési kapcsoló, pl. az „--inspect-brk”.", + "npm.scriptInvalid": "A(z) „{0}” parancs nem található. Frissítse a nézetet!" +} \ No newline at end of file diff --git a/i18n/hun/extensions/npm/out/tasks.i18n.json b/i18n/hun/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..7c22848110 --- /dev/null +++ b/i18n/hun/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Npm-feladatok felderítése: nem sikerült beolvasni a következő fájlt: {0}" +} \ No newline at end of file diff --git a/i18n/hun/extensions/npm/package.i18n.json b/i18n/hun/extensions/npm/package.i18n.json index 7c4caee296..79cbd9c9f8 100644 --- a/i18n/hun/extensions/npm/package.i18n.json +++ b/i18n/hun/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "Az npm-parancsok a '--silent' kapcsolóval fussanak.", "config.npm.packageManager": "A parancsfájlok futtatásához használt csomagkezelő.", "config.npm.exclude": "Azokat a mappákat leíró globális minta, amelyek ne legyenek vizsgálva az automatikus parancsfájlkeresés közben.", + "config.npm.enableScriptExplorer": "Npm-parancsnézet hozzáadása a Fájlkezelőhöz, ha van „package.json”-fál a munkaterületen.", "npm.parseError": "Npm-feladatok felderítése: nem sikerült beolvasni a következő fájlt: {0}", "taskdef.script": "A testreszabott npm parancsfájl.", - "taskdef.path": "Azon mappa elérési útja, amely a parancsfájlt szolgáltató package.json fájlt tartalmazza. Elhagyható." + "taskdef.path": "Azon mappa elérési útja, amely a parancsfájlt szolgáltató package.json fájlt tartalmazza. Elhagyható.", + "view.name": "Npm-parancsok", + "command.refresh": "Frissítés", + "command.run": "Futtatás", + "command.debug": "Hibakeresés", + "command.openScript": "Megnyitás", + "npm.scriptInvalid": "A(z) „{0}” parancs nem található. Frissítse a nézetet!", + "npm.noDebugOptions": "A(z) „{0}” nem indítható el hibakereséshez, mert a parancsból hiányzik a node hibakeresési kapcsoló, pl. az „--inspect-brk”." } \ No newline at end of file diff --git a/i18n/hun/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/hun/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..d4851192c1 --- /dev/null +++ b/i18n/hun/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Engedélyezi a(z) {0} (munkaterületi beállításként megadott) végrehajtását a PHP-fájlok linteléséhez?", + "php.yes": "Engedélyezés", + "php.no": "Tiltás", + "wrongExecutable": "A validáció nem sikerült, mivel a(z) {0} nem egy érvényes php végrehajtható fájl. Használja a 'php.validate.executablePath' beállítást a PHP végrehajtható fájl konfigurálásához!", + "noExecutable": "A validáció nem sikerült, mivel nincs beállítva PHP végrehajtható fájl. Használja a 'php.validate.executablePath' beállítást a PHP végrehajtható fájl konfigurálásához!", + "unknownReason": "Nem sikerült futtatni a PHP-t a következő elérési út használatával: {0}. Az ok ismeretlen." +} \ No newline at end of file diff --git a/i18n/hun/extensions/php-language-features/package.i18n.json b/i18n/hun/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..1d6ca7197b --- /dev/null +++ b/i18n/hun/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Meghatározza, hogy a beépített PHP nyelvi támogatás ajánl-e PHP globálisokat és változókat.", + "configuration.validate.enable": "Beépített PHP-validáció engedélyezése vagy letiltása", + "configuration.validate.executablePath": "A PHP végrehajtható fájljának elérési útja.", + "configuration.validate.run": "A linter mentéskor vagy gépeléskor fut-e.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "PHP-validációs végrehajtható fájl letiltása (munkaterületi beállításként megadva)", + "displayName": "PHP nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás PHP-fájlokhoz." +} \ No newline at end of file diff --git a/i18n/hun/extensions/php/package.i18n.json b/i18n/hun/extensions/php/package.i18n.json index 0ee9c74cf3..7a75a0d1d2 100644 --- a/i18n/hun/extensions/php/package.i18n.json +++ b/i18n/hun/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Meghatározza, hogy a beépített PHP nyelvi támogatás ajánl-e PHP globálisokat és változókat.", - "configuration.validate.enable": "Beépített PHP-validáció engedélyezése vagy letiltása", - "configuration.validate.executablePath": "A PHP végrehajtható fájljának elérési útja.", - "configuration.validate.run": "A linter mentéskor vagy gépeléskor fut-e.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "PHP-validációs végrehajtható fájl letiltása (munkaterületi beállításként megadva)", - "displayName": "PHP nyelvi funkciók", - "description": "IntelliSense-t, lintelést és alapvető nyelvi funkciókat szolgáltat a PHP-fájlokban." + "displayName": "PHP nyelvi alapok", + "description": "Szintaktikai kiemelést szolgáltat, valamint kezeli az összetartozó zárójeleket a PHP-fájlokban." } \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/commands.i18n.json b/i18n/hun/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..2d667c1016 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Nyisson meg egy mappát a VS Code-ban typescriptes vagy javascriptes projekt használatához!", + "typescript.projectConfigUnsupportedFile": "Nem sikerült meghatározni a TypeScript- vagy JavaScript-projektet. Nem támogatott fájltípus", + "typescript.projectConfigCouldNotGetInfo": "Nem sikerült meghatározni a TypeScript- vagy JavaScript-projektet", + "typescript.noTypeScriptProjectConfig": "A fájl nem egy TypeScript-projekt része. További információkat [ide]({0}) kattintva tudhat meg.", + "typescript.noJavaScriptProjectConfig": "A fájl nem egy JavaScript-projekt része. További információkat [ide]({0}) kattintva tudhat meg.", + "typescript.configureTsconfigQuickPick": "tsconfig.json konfigurálása", + "typescript.configureJsconfigQuickPick": "jsconfig.json konfigurálása" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..30437c7682 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Válasszon végrehajtandó kódműveletet!", + "acquiringTypingsLabel": "Típusdefiníciók letöltése...", + "acquiringTypingsDetail": "Típusdefiníciók letöltése az IntelliSense-hez.", + "autoImportLabel": "Automatikus importálás a következő helyről: {0}" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..c7d2746fdb --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Engedélyezi a JavaScript-fájlok szemantikai ellenőrzését. A fájl tetején kell szerepelnie.", + "ts-nocheck": "Letiltja a JavaScript-fájlok szemantikai ellenőrzését. A fájl tetején kell szerepelnie.", + "ts-ignore": "Elfedi a fájl következő sorában található @ts-check-hibákat." +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..7207bf3b21 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 implementáció", + "manyImplementationLabel": "{0} implementáció", + "implementationsErrorLabel": "Nem sikerült meghatározni az implementációkat" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..d6bb7d7c26 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc-megjegyzés" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..4573e2028b --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Importálások rendezése" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..e76bf145ef --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (összes javítása a fájlban)" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..ac0763b55e --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 referencia", + "manyReferenceLabel": "{0} referencia", + "referenceErrorLabel": "Nem sikerült meghatározni a referenciákat" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..d7ad58409e --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "buildelés – {0}", + "buildAndWatchTscLabel": "figyelés – {0}" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/hun/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..5c3b49a603 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "A(z) {0} elérési út nem egy érvényes tsserver-telepítésre mutat. A beépített TypeScript-verzió lesz használva.", + "serverCouldNotBeStarted": "Nem sikerült elindítani a TypeScript nyelvi szervert. Hibaüzenet: {0}", + "typescript.openTsServerLog.notSupported": "A TS-szerver naplózáshoz TS 2.2.2+ szükséges", + "typescript.openTsServerLog.loggingNotEnabled": "A TS-szervernaplózás ki van kapcsolva. Állítsa be a `typescript.tsserver.log` beállítást, majd indítsa újra a TS-szervert a naplózás engedélyezéséhez!", + "typescript.openTsServerLog.enableAndReloadOption": "Naplózás engedélyezése és TS-szerver újraindítása", + "typescript.openTsServerLog.noLogFile": "A TS-szerver nem kezdett el naplózni", + "openTsServerLog.openFileFailedFailed": "A TS-szervernapló nem nyitható meg", + "serverDiedAfterStart": "A TypeScript nyelvi szolgáltatás öt alkalommal omlott össze rögtön azután, hogy el lett indítva. A szolgáltatás nem lesz újraindítva.", + "serverDiedReportIssue": "Probléma jelentése", + "serverDied": "A TypeScript nyelvi szolgáltatás öt alkalommal omlott össze az elmúlt öt percben." +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..93f5c9220f --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "érvénytelen verzió" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..3e5d8de4e0 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "A JavaScript/TypeScript funkciók teljes projektre való engedélyezéséhez zárja ki a sok fájlt tartalmazó mappákat. Például: {0}", + "hintExclude.generic": "A JavaScript/TypeScript funkciók teljes projektre való engedélyezéséhez zárja ki azokat a mappákat, amelyben olyan forrásfájlok találhatók, melyen nem dolgozik. ", + "large.label": "Kivételek konfigurálása", + "hintExclude.tooltip": "A JavaScript/TypeScript funkciók teljes projektre való engedélyezéséhez zárja ki azokat a mappákat, amelyben olyan forrásfájlok találhatók, melyen nem dolgozik. " +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..4e9549aeb0 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Adatok lekérése a jobb typescriptes IntelliSense-hez", + "typesInstallerInitializationFailed.title": "Nem sikerült telepíteni a típusdefiníciós fájlokat a javascriptes nyelvi funkciókhoz. Győződjön meg róla, hogy az NPM telepítve van vagy módosítsa a 'typescript.npm' beállítás értékét a felhasználói beállításokban. További információkat [ide]({0}) kattintva tudhat meg.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Ne jelenítse meg újra" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..919b167831 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "A VSCode verziójának használata", + "useWorkspaceVersionOption": "A munkaterület verziójának használata", + "learnMore": "További információ", + "selectTsVersion": "Válassza ki a javascriptes és typescriptes nyelvi funkciókhoz használt TypeScript-verziót" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/hun/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..4e8b25cde5 --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Nem sikerült meghatározni a TypeScript-verziót ezen az elérési úton", + "noBundledServerFound": "A VSCode beépített tsserverét törölte egy másik alkalmazás, például egy hibásan viselkedő víruskereső eszköz. Telepítse újra a VSCode-ot!" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript-language-features/package.i18n.json b/i18n/hun/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..5ffa7df24e --- /dev/null +++ b/i18n/hun/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript és JavaScript nyelvi funkciók", + "description": "Széleskörű nyelvi támogatás JavaScripthez és TypeScripthez.", + "typescript.reloadProjects.title": "Projekt újratöltése", + "javascript.reloadProjects.title": "Projekt újratöltése", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Függvények kiegészítése paraméterdefiníciójukkal.", + "typescript.tsdk.desc": "A tsservert és a lib*.d.ts fájlokat tartalmazó mappa elérési útja.", + "typescript.disableAutomaticTypeAcquisition": "Automatikus típusdefiníció-letöltés letiltása. Legalább 2.0.6-os TypeScriptet igényel.", + "typescript.tsserver.log": "Engedélyezi a TS-szerver naplózását egy fájlba. Ez a napló a TS-szerverrel kapcsolatos problémák diagnosztizálására használható. A napló tartalmazhat elérési utakat, forráskódot és más potenciálisan érzékeny, projekttel kapcsolatos adatot.", + "typescript.tsserver.pluginPaths": "További felderített elérési utak, amelyek TypeScript nyelvi szerver beépülőket tartalmaznak. TypeScript >=2.3.0-t igényel.", + "typescript.tsserver.pluginPaths.item": "Abszolút vagy relatív elérési út. A relatív elérési utak a munkaterületi mappákhoz relatívan lesznek feloldva.", + "typescript.tsserver.trace": "Engedélyezi a TS-szervernek küldött üzenetek naplózását. Ez a napló a TS-szerverrel kapcsolatos problémák diagnosztizálására használható. A napló tartalmazhat elérési utakat, forráskódot és más potenciálisan érzékeny, projekttel kapcsolatos adatot. ", + "typescript.validate.enable": "TypeScript-validálás engedélyezése vagy letiltása.", + "typescript.format.enable": "Alapértelmezett TypeScript-formázó engedélyezése vagy letiltása.", + "javascript.format.enable": "Alapértelmezett JavaScript-formázó engedélyezése vagy letiltása.", + "format.insertSpaceAfterCommaDelimiter": "Meghatározza a szóközök kezelését vessző elválasztókarakter után.", + "format.insertSpaceAfterConstructor": "Meghatározza a szóközök kezelését a constructor kulcsszó után. TypeScript >= 2.3.0-t igényel.", + "format.insertSpaceAfterSemicolonInForStatements": "Meghatározza a szóközök kezelését pontosvessző után a for ciklusban.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Meghatározza a szóközök kezelését bináris operátorok után.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Meghatározza a szóközök kezelését vezérlési szerkezetek kulcsszavai után.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Meghatározza a szóközök kezelését a névtelen függvényekben található function kulcsszó után.", + "format.insertSpaceBeforeFunctionParenthesis": "Meghatározza a szóközök kezelését a függvényargumentumokat tartalmazó zárójel előtt. TypeScript >= 2.1.5-öt igényel.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Meghatározza a szóközök kezelését nem üres zárójelek nyitása után és zárása előtt.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Meghatározza a szóközök kezelését nem üres szögletes zárójelek nyitása után és zárása előtt.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Meghatározza a szóközök kezelését nem üres kapcsos zárójelek nyitása után és zárása előtt. TypeScript >= 2.3.0-t igényel.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Meghatározza a szóközök kezelését a sablonkarakterláncok (template stringek) kapcsos zárójeleinek nyitása után és zárása előtt. TypeScript >= 2.0.6-ot igényel.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Meghatározza a szóközök kezelését JSX-kifejezések kapcsos zárójeleinek nyitása után és zárása előtt. TypeScript >= 2.0.6-ot igényel.", + "format.insertSpaceAfterTypeAssertion": "Meghatározza a szóközök kezelését a típuskényszerítések utn. TypeScript >= 2.4-t igényel.", + "format.placeOpenBraceOnNewLineForFunctions": "Meghatározza, hogy a függvények nyitó kapcsos zárójelei új sorba kerüljenek-e vagy sem.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Meghatározza, hogy a vezérlőblokkok nyitó kapcsos zárójelei új sorba kerüljenek-e vagy sem.", + "javascript.validate.enable": "JavaScript-validálás engedélyezése vagy letiltása.", + "typescript.goToProjectConfig.title": "Projektkonfiguráció megkeresése", + "javascript.goToProjectConfig.title": "Projektkonfiguráció megkeresése", + "javascript.referencesCodeLens.enabled": "Referencia kódlencsék engedélyezése vagy letiltása a JavaScript-fájlokban.", + "typescript.referencesCodeLens.enabled": "Referencia kódlencsék engedélyezése vagy letiltása a TypeScript-fájlokban. TypeScript >= 2.0.6-ot igényel.", + "typescript.implementationsCodeLens.enabled": "Implementációs kódlencsék engedélyezése vagy letiltása. TypeScript >= 2.2.0-t igényel.", + "typescript.openTsServerLog.title": "TS-szervernapló megnyitása", + "typescript.restartTsServer": "TS-szerver újraindítása", + "typescript.selectTypeScriptVersion.title": "TypeScript-verzió kiválasztása", + "typescript.reportStyleChecksAsWarnings": "Stílusellenőrzés során talált esetek figyelmeztetésként legyenek jelentve", + "jsDocCompletion.enabled": "Automatikus JSDoc-megjegyzések engedélyezése vagy letiltása", + "javascript.implicitProjectConfig.checkJs": "JavaScript-fájlok szemantikai ellenőrzésének engedélyezése vagy letiltása. A meglévő jsconfig.json vagy tsconfig.json fájlok felülírják ezt a beállítást. TypeScript >= 2.3.1-et igényel.", + "typescript.npm": "Az automatikus típusdefiníció-letöltéshez használt NPM végrehajtható fájl elérési útja. TypeScript 2.3.4-et igényel.", + "typescript.check.npmIsInstalled": "Ellenőrizze, hogy az NPM telepítve van-e az automatikus típusdefiníció-letöltéshez.", + "javascript.nameSuggestions": "Egyedi nevek listázásának engedélyezése a javascriptes javaslati listákban.", + "typescript.tsc.autoDetect": "Meghatározza a tsc-s feladatok automatikus felderítésének működését. 'off' érték esetén a funkció ki van kapcsolva. 'build' esetén egyszer lefutó, fordítást végző feladatok jönnek létre. 'watch' esetén csak fordítást és figyelést végző feladatok jönnek létre. 'on' esetén buildelési és figyelési feladatok is keletkeznek. Az alapértelmezett érték: 'on'.", + "typescript.problemMatchers.tsc.label": "TypeScript-problémák", + "typescript.problemMatchers.tscWatch.label": "TypeScript-problémák (figyelő módban)", + "typescript.quickSuggestionsForPaths": "Kiegészítési javaslatok engedélyezése importált elérési utak beírásakor.", + "typescript.locale": "Meghatározza a TypeScript-hibák jelentésénél használt lokalizációt. TypeScript >= 2.6.0-t igényel. Az alapértelmezett 'null' érték esetén a VS Code-ban beállított nyelven jelennek meg a TypeScript-hibák.", + "javascript.implicitProjectConfig.experimentalDecorators": " 'experimentalDecorators' beállítás engedélyezése azon JavaScript-fájlok esetében, amelyek nem részei a projektnek. A meglévő jsconfig.json vagy tsconfig.json fájlok felülírják ezt a beállítást. TypeScript >= 2.3.1-et igényel.", + "typescript.autoImportSuggestions.enabled": "Automatikus importálási ajánlatok engedélyezése vagy letiltása. TypeScript >= 2.6.1-t igényel.", + "typescript.experimental.syntaxFolding": "Szintaxisalapú becsukható kódrészletek engedélyezése vagy letiltása.", + "taskDefinition.tsconfig.description": "A tsconfig-fájl, ami meghatározza a TS-buildet.", + "javascript.suggestionActions.enabled": "Ajánlásokat tartalmazó diagnosztikák engedélyezése vagy letiltása a JavaScript-fájlokban. TypeScript >= 2.8-at igényel.", + "typescript.suggestionActions.enabled": "Ajánlásokat tartalmazó diagnosztikák engedélyezése vagy letiltása a TypeScript-fájlokban. TypeScript >= 2.8-at igényel." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/base/browser/ui/findinput/findInputCheckboxes.i18n.json b/i18n/hun/src/vs/base/browser/ui/findinput/findInputCheckboxes.i18n.json index e3e0559747..93770ead65 100644 --- a/i18n/hun/src/vs/base/browser/ui/findinput/findInputCheckboxes.i18n.json +++ b/i18n/hun/src/vs/base/browser/ui/findinput/findInputCheckboxes.i18n.json @@ -7,6 +7,6 @@ "Do not edit this file. It is machine generated." ], "caseDescription": "Kis- és nagybetűk megkülönböztetése", - "wordsDescription": "Csak teljes szavas egyezés", + "wordsDescription": "Teljes szavas egyezés vizsgálata", "regexDescription": "Reguláris kifejezés használata" } \ No newline at end of file diff --git a/i18n/hun/src/vs/base/common/errorMessage.i18n.json b/i18n/hun/src/vs/base/common/errorMessage.i18n.json index 74a2a9148a..968c566fff 100644 --- a/i18n/hun/src/vs/base/common/errorMessage.i18n.json +++ b/i18n/hun/src/vs/base/common/errorMessage.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "stackTrace.format": "{0}: {1}", - "error.defaultMessage": "Ismeretlen hiba történt. Részletek a naplóban.", + "error.defaultMessage": "Ismeretlen hiba történt. Részleteket a naplóban találhat.", "nodeExceptionMessage": "Rendszerhiba történt ({0})", "error.moreErrors": "{0} (összesen {1} hiba)" } \ No newline at end of file diff --git a/i18n/hun/src/vs/base/common/jsonErrorMessages.i18n.json b/i18n/hun/src/vs/base/common/jsonErrorMessages.i18n.json index 384a2b8a63..e270f83740 100644 --- a/i18n/hun/src/vs/base/common/jsonErrorMessages.i18n.json +++ b/i18n/hun/src/vs/base/common/jsonErrorMessages.i18n.json @@ -9,10 +9,10 @@ "error.invalidSymbol": "Érvénytelen szimbólum", "error.invalidNumberFormat": "Érvénytelen számformátum.", "error.propertyNameExpected": "Hiányzó tulajdonságnév", - "error.valueExpected": "Hiányzó érték.", - "error.colonExpected": "Hiányzó kettőspont.", + "error.valueExpected": "Hiányzó érték", + "error.colonExpected": "Hiányzó kettőspont", "error.commaExpected": "Hiányzó vessző", "error.closeBraceExpected": "Hiányzó záró kapcsos zárójel", "error.closeBracketExpected": "Hiányzó záró szögletes zárójel", - "error.endOfFileExpected": "Itt fájlvége jelnek kellene szerepelnie." + "error.endOfFileExpected": "Hiányzó fájlvégjel" } \ No newline at end of file diff --git a/i18n/hun/src/vs/base/node/processes.i18n.json b/i18n/hun/src/vs/base/node/processes.i18n.json index 7d180d1b36..404cc66a95 100644 --- a/i18n/hun/src/vs/base/node/processes.i18n.json +++ b/i18n/hun/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "Rendszerparancsok UNC-meghajtókon nem hajthatók végre." + "TaskRunner.UNC": "Rendszerparancsok nem hajthatók végre UNC-meghajtókon." } \ No newline at end of file diff --git a/i18n/hun/src/vs/base/node/zip.i18n.json b/i18n/hun/src/vs/base/node/zip.i18n.json index 6f349ae150..5ef62026cd 100644 --- a/i18n/hun/src/vs/base/node/zip.i18n.json +++ b/i18n/hun/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Hiányos. {0} bejegyzés feldolgozva a(z) {0} bejegyzésből.", "notFound": "{0} nem található a zipen belül." } \ No newline at end of file diff --git a/i18n/hun/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/hun/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 22969de2d8..7eed9a3ddf 100644 --- a/i18n/hun/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/hun/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "Előnézet GitHubon", "loadingData": "Adatok betöltése...", + "rateLimited": "GitHub lekérdezési korlát túllépve. Kérem, várjon!", "similarIssues": "Hasonló problémák", "open": "Megnyitás", "closed": "Bezárva", - "noResults": "Nincs találat", + "noSimilarIssues": "Nincs hasonló probléma", "settingsSearchIssue": "Hiba a beállítások keresőjében", "bugReporter": "hibát", - "performanceIssue": "teljesítményproblémát", "featureRequest": "funkcióigényt", + "performanceIssue": "teljesítményproblémát", "stepsToReproduce": "A probléma előidézésének lépései", "bugDescription": "Ossza meg a probléma megbízható előidézéséhez szükséges részleteket! Írja le a valós és az elvárt működést! A mezőben GitHub-stílusú markdown használható. A hibajelentés szerkeszthető lesz és képernyőfotók is csatolhatók a githubos előnézetnél.", "performanceIssueDesciption": "Mikor fordult elő ez a teljesítménybeli probléma? Például előfordul indulásnál vagy végre kell hajtani bizonyos műveleteket? A mezőben GitHub-stílusú markdown használható. A hibajelentés szerkeszthető lesz és képernyőfotók is csatolhatók a githubos előnézetnél.", diff --git a/i18n/hun/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/hun/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index b943a7e421..886cb41d49 100644 --- a/i18n/hun/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/hun/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Kérjük, hogy angolul töltse ki az űrlapot!", "issueTypeLabel": "Ez egy", + "issueSourceLabel": "Komponens", + "vscode": "Visual Studio Code", + "extension": "Egy kiegészítő", + "disableExtensionsLabelText": "Próbálja meg előidézni a hibát {0}! Ha a hiba csak aktív kiegészítőkkel idézhető elő, akkor nagy valószínűséggel a kiegészítőben van a hiba.", + "disableExtensions": "az összes kiegészítő letiltása és az ablak újratöltése után", + "chooseExtension": "Kiegészítő", "issueTitleLabel": "Cím", "issueTitleRequired": "Kérjük, adja meg a címet!", "titleLengthValidation": "A cím túl hosszú.", @@ -18,13 +24,6 @@ "extensions": "Kiegészítők", "searchedExtensions": "Keresett kiegészítők", "settingsSearchDetails": "Beállításokban való keresés részletei", - "tryDisablingExtensions": "A probléma letiltott kiegészítőkkel is előidézhető?", - "yes": "Igen", - "no": "Nem", - "disableExtensionsLabelText": "Próbálja meg előidézni a hibát {0}!", - "disableExtensions": "az összes kiegészítő letiltása és az ablak újratöltése után", - "showRunningExtensionsLabelText": "Ha azt gyanítja, hogy a hiba egy kiegészítőben van, {0} a kiegészítővel kapcsolatos hiba jelentéséhez!", - "showRunningExtensions": "tekintse meg a futó kiegészítők listáját", "details": "Írja le a részleteket!", "loadingData": "Adatok betöltése..." } \ No newline at end of file diff --git a/i18n/hun/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/hun/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..27c0f1d3fc --- /dev/null +++ b/i18n/hun/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "Processzor %", + "memory": "Memória (MB)", + "pid": "folyamatazonosító", + "name": "Név", + "killProcess": "Folyamat leállítása", + "forceKillProcess": "Folyamat kényszerített leállítása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/code/electron-main/menus.i18n.json b/i18n/hun/src/vs/code/electron-main/menus.i18n.json index c9ca504d8b..61e879b21f 100644 --- a/i18n/hun/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/hun/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "Feltételes törés&&pont", "miColumnBreakpoint": "Töréspont &&oszlopnál", "miFunctionBreakpoint": "Töréspont&&funkció...", + "miLogPoint": "Nap&&lózási pont...", "miNewBreakpoint": "Ú&&j töréspont", "miEnableAllBreakpoints": "Összes töréspont engedélyezése", "miDisableAllBreakpoints": "Összes töréspont leti&<ása", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Összes ablak összeolvasztása", "miToggleDevTools": "&&Fejlesztői eszközök be- és kikapcsolása", "miAccessibilityOptions": "&&Kisegítő lehetőségek", + "miOpenProcessExplorerer": "&&Feladatkezelő megnyitása", "miReportIssue": "H&&iba jelentése", "miWelcome": "Üdvözlő&&oldal", "miInteractivePlayground": "&&Interaktív játszótér", diff --git a/i18n/hun/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/hun/src/vs/editor/browser/widget/diffReview.i18n.json index 1701c5e028..0bee706964 100644 --- a/i18n/hun/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/hun/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Bezárás", - "header": "{0}. eltérés, összesen: {1}. Eredeti: {2}., {3}. sorok, módosított: {4}., {5}. sorok", + "no_lines": "nincsenek sorok", + "one_line": "1 sor", + "more_lines": "{0} sor", + "header": "{0}. eltérés, összesen: {1}. Eredeti: {2}, {3}, módosított: {4}, {5}", "blankLine": "üres", "equalLine": "eredeti {0}., módosított {1}.: {2}", "insertLine": "+ módosított {0}.: {1}", diff --git a/i18n/hun/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/hun/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..6e1b7fcb7c --- /dev/null +++ b/i18n/hun/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "A kurzorok száma legfeljebb {0} lehet." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json index 0629915291..030c8e5246 100644 --- a/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "editorConfigurationTitle": "Szerkesztőablak", - "fontFamily": "Ez a beállítás a betűkészletet határozza meg.", + "fontFamily": "Meghatározza a betűkészletet.", "fontWeight": "Meghatározza a betűvastagságot.", "fontSize": "Meghatározza a betű méretét, pixelekben.", "lineHeight": "Meghatározza a sormagasságot. A 0 érték használata esetén a sormagasság a fontSize értékéből van számolva.", @@ -16,7 +16,7 @@ "lineNumbers.on": "A sorszámok abszolút értékként jelennek meg.", "lineNumbers.relative": "A sorszámok a kurzortól való távolságuk alapján jelennek meg.", "lineNumbers.interval": "A sorszámok minden 10. sorban jelennek meg.", - "lineNumbers": "Meghatározza a sorszámok megjelenését. A lehetséges értékek: 'on', 'off', 'relative' és 'interval'.", + "lineNumbers": "Meghatározza a sorszámok megjelenítési módját.", "rulers": "Függőleges vonalzók kirajzolása bizonyos számú fix szélességű karakter után. Több vonalzó használatához adjon meg több értéket. Nincs kirajzolva semmi, ha a tömb üres.", "wordSeparators": "Azon karakterek listája, amelyek szóelválasztónak vannak tekintve szavakkal kapcsolatos navigáció vagy műveletek során.", "tabSize": "Egy tabulátor hány szóköznek felel meg. Ez a beállítás felülírásra kerül a fájl tartalma alapján, ha az `editor.detectIndentation` beállítás aktív.", @@ -24,12 +24,12 @@ "insertSpaces": "Szóközök beszúrása a tabulátor billentyű lenyomása esetén. Ez a beállítás felülíródik a fájl tartalma alapján, ha az `editor.detectIndentation` beállítás aktív.", "insertSpaces.errorMessage": "A várt érték 'boolean' típusú. Megjegyzés: az \"auto\" értéket az 'editor.detectIndentation' beállítás helyettesíti.", "detectIndentation": "Fájl megnyitásakor az `editor.tabSize` és az `editor.insertSpaces` értéke a fájl tartalma alapján lesz meghatározva.", - "roundedSelection": "Itt adható meg, hogy a kijelölt elemek sarkai lekerekítettek legyenek-e", + "roundedSelection": "Meghatározza, hogy a kijelölések sarkai le legyenek-e kerekítve.", "scrollBeyondLastLine": "Meghatározza, hogy a szerkesztőablak görgethető-e az utolsó sor után.", "smoothScrolling": "Meghatározza, hogy a szerkesztőablak animálva van-e görgetve.", "minimap.enabled": "Meghatározza, hogy megjelenjen-e a kódtérkép.", - "minimap.side": "Meghatározza, hogy melyik oldalon jelenjen meg a kódtérkép. Lehetséges értékek: 'right' és 'left'.", - "minimap.showSlider": "Meghatározza, hogy automatikusan el legyen-e rejtve a kódtérképes görgetősáv. Lehetséges értékek: 'always' és 'mouseover'.", + "minimap.side": "Meghatározza, hogy melyik oldalon jelenjen meg a kódtérkép.", + "minimap.showSlider": "Meghatározza, hogy automatikusan el legyen-e rejtve a kódtérképes görgetősáv.", "minimap.renderCharacters": "Meghatározza, hogy a tényleges karakterek legyenek-e megjelenítve (színes téglalapok helyett)", "minimap.maxColumn": "Meghatározza, hogy a kódtérképen legfeljebb hány oszlop legyen kirajzolva.", "find.seedSearchStringFromSelection": "Meghatározza, hogy a keresés modulba automatikusan bekerüljön-e a szerkesztőablakban kiválasztott szöveg.", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti.", "multiCursorModifier.alt": "Windows és Linux alatt az `Alt`, macOS alatt az `Option` billentyűt jelenti.", "multiCursorModifier": "Több kurzor hozzáadásához használt módosítóbillentyű. A `ctrlCmd` Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti. A Definíció megkeresése és Hivatkozás megnyitása egérgesztusok automatikusan úgy lesznek beállítva, hogy ne ütközzenek a többkurzorhoz tartozó módosítóval.", + "multiCursorMergeOverlapping": "Több kurzor összeolvasztása, ha azok fedik egymást.", "quickSuggestions.strings": "Kiegészítési javaslatok engedélyezése karakterláncokban (stringekben)", "quickSuggestions.comments": "Kiegészítési javaslatok engedélyezése megjegyzésekben", "quickSuggestions.other": "Kiegészítési javaslatok engedélyezése karakterláncokon (stringeken) és megjegyzéseken kívül", @@ -56,7 +57,7 @@ "formatOnType": "Meghatározza, hogy a szerkesztő automatikusan formázza-e a sort a gépelés után", "formatOnPaste": "Meghatározza, hogy a szerkesztő automatikusan formázza-e a beillesztett tartalmat. Ehhez szükség van egy formázóra, illetve a formázónak tudnia kell a dokumentum egy részét formázni.", "autoIndent": "Meghatározza, hogy a szerkesztőablak automatikusan állítsa-e az indentálást miközben a felhasználó gépel, beilleszt vagy mozgatja a sorokat. Az adott nyelv indentálási szabályainak rendelkezésre kell állnia.", - "suggestOnTriggerCharacters": "Itt adható meg, hogy eseményindító karakterek beírásakor automatikusan megjelenjenek-e a javaslatok", + "suggestOnTriggerCharacters": "Meghatározza, hogy eseménykiváltó karakterek beírásakor automatikusan megjelenjenek-e a javaslatok", "acceptSuggestionOnEnter": "Meghatározza, hogy a javaslatok az 'Enter' gomb leütésére is el legyenek fogadva a 'Tab' mellett. Segít feloldani a bizonytalanságot az új sorok beillesztése és a javaslatok elfogadása között. A 'smart' érték azt jelenti, hogy csak akkor fogadja el a javaslatot az Enter leütése esetén, ha az módosítja a szöveget.", "acceptSuggestionOnCommitCharacter": "Meghatározza, hogy a javaslaok a zárókarakterek leütésére is el legyenek fogadva. A JavaScriptben például a pontosvessző (';') számít zárókarakternek, leütésére a javaslat elfogadásra kerül és beillesztődik az adott karakter. ", "snippetSuggestions.top": "A javasolt kódrészletek a többi javaslat előtt jelenjenek meg.", @@ -72,11 +73,11 @@ "suggestSelection": "Meghatározza, mely javaslat van előre kiválasztva a javaslatok listájából.", "suggestFontSize": "Az ajánlásokat tartalmazó modul betűmérete", "suggestLineHeight": "Az ajánlásokat tartalmazó modul sormagassága", - "selectionHighlight": "Itt adható meg, hogy a szerkesztő kiemelje-e a kijelöléshez hasonló találatokat", + "selectionHighlight": "Meghatározza, hogy a szerkesztőablakban ki legyenek-e emelve a kijelöléshez hasonló találatok", "occurrencesHighlight": "Meghatározza, hogy a szerkesztőablakban ki legyenek-e emelve a szimbólum szemantikailag hozzá tartozó előfordulásai.", "overviewRulerLanes": "Meghatározza, hogy hány dekoráció jelenhet meg azonos pozícióban az áttekintő sávon.", "overviewRulerBorder": "Meghatározza, hogy legyen-e kerete az áttekintő sávnak.", - "cursorBlinking": "Meghatározza a kurzor animációjának stílusát. Lehetséges értékek: 'blink', 'smooth', 'phase', 'expand' vagy 'solid'", + "cursorBlinking": "Meghatározza a kurzor animációjának stílusát.", "mouseWheelZoom": "A szerkesztőablak betűtípusának nagyítása vagy kicsinyítése az egérgörgő Ctrl lenyomása mellett történő használata esetén", "cursorStyle": "Meghatározza a kurzor stílusát. Lehetséges értékek: 'block', 'block-outline', 'line', 'line-thin', 'underline' vagy 'underline-thin'", "cursorWidth": "Meghatározza a kurzor szélességét, ha az editor.cursorStyle értéke 'line'.", @@ -86,8 +87,11 @@ "renderControlCharacters": "Meghatározza, hogy a szerkesztőablakban ki legyenek-e rajzolva a vezérlőkarakterek.", "renderIndentGuides": "Meghatározza, hogy a szerkesztőablakban ki legyenek-e rajzolva az indentálási segédvonalak.", "renderLineHighlight": "Meghatározza, hogy a szerkesztőablakban hogyan legyen kirajzolva az aktuális sor kiemelése. Lehetséges értékek: 'none', 'gutter', 'line', vagy 'all'.", - "codeLens": "Meghatározza, hogy megjelenjenek-e a kódlencsék", + "codeLens": "Meghatározza, hogy megjelenjenek-e a kódlencsék a szerkesztőablakban.", "folding": "Meghatározza, hogy engedélyezve van-e a kódrészletek bezárása a szerkesztőablakban.", + "foldingStrategyAuto": "Nyelvspecifikus kódrész-bezárási stratégia használata, ha az rendelkezésre áll. Ha nem, akkor tartalékmegoldásként az indentálásalapú kódrész-bezárási stratégia használata.", + "foldingStrategyIndentation": "A kódrészek bezárása mindig az indentálásalapú kódrész-bezárási stratégia alapján történjen.", + "foldingStrategy": "Meghatározza, hogyan vannak meghatározva a bezárható kódrészek. Az 'auto' esetén a nyelvspecifikus kódbezárási stratégia van használva, ha az rendelkezésre áll. Az 'indentation' esetén minden esetben az indentálásalapú bezárási stratégia van használva.", "showFoldingControls": "Meghatározza, hogy a kódrészletek bezárásához tartozó vezérlőelemek automatikusan el legyenek-e rejtve.", "matchBrackets": "Zárójel kiválasztása esetén a hozzátartozó zárójel kiemelése.", "glyphMargin": "Meghatározza, hogy legyen-e vertikális szimbólummargó a szerkesztőablakban. A szimbólummargó elsősorban hibakeresésnél van használva.", @@ -102,8 +106,12 @@ "links": "Meghatározza, hogy a szerkesztőablak érzékelje-e a hivatkozásokat, és kattinthatóvá tegye-e őket.", "colorDecorators": "Meghatározza, hogy a szerkesztőablakban ki legyenek-e rajzolva a színdekorátorok és színválasztók.", "codeActions": "Engedélyezi a kódműveletek végrehajtásához használható villanykörtét", + "codeActionsOnSave.organizeImports": "Importálások rendezése mentés során", + "codeActionsOnSave": "A mentés során futtatott kódműveletek.", + "codeActionsOnSaveTimeout": "A mentés során futtatott kódműveletek futási időkorlátja.", "selectionClipboard": "Meghatározza-e, hogy támogatva van-e az elsődleges vágólap Linux alatt", "sideBySide": "Meghatározza, hogy a differenciaszerkesztő ablakban egymás mellett vagy a sorban jelenjenek meg az eltérések", "ignoreTrimWhitespace": "Meghatározza, hogy a differenciaszerkesztő ablakban megjelenjenek-e a sor elején vagy végén a szóközökben talált különbségek", + "largeFileOptimizations": "Nagy fájlok megnyitása esetén néhány, sok memóriát használó funkció letiltása.", "renderIndicators": "Meghatározza, hogy a differenciaszerkesztő ablakban megjelenjenek-e a +/- jelzők az hozzáadott/eltávolított változásoknál" } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/common/controller/cursor.i18n.json b/i18n/hun/src/vs/editor/common/controller/cursor.i18n.json index faf3ea9d6f..4522950b0c 100644 --- a/i18n/hun/src/vs/editor/common/controller/cursor.i18n.json +++ b/i18n/hun/src/vs/editor/common/controller/cursor.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "corrupt.commands": "Váratlan kivétel egy parancs végrehajtása során." + "corrupt.commands": "Váratlan kivétel történt a parancs végrehajtása közben." } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json index 79dc794f28..cfc03a81c0 100644 --- a/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "A szerkesztőablak kurzorának háttérszíne. Lehetővé teszik az olyan karakterek színének módosítását, amelyek fölött egy blokk-típusú kurzor áll.", "editorWhitespaces": "A szerkesztőablakban található szóköz karakterek színe.", "editorIndentGuides": "A szerkesztőablak segédvonalainak színe.", + "editorActiveIndentGuide": "Az aktív szerkesztőablak segédvonalainak színe.", "editorLineNumbers": "A szerkesztőablak sorszámainak színe.", "editorActiveLineNumber": "A szerkesztőablak aktív sorához tartozó sorszám színe.", + "deprecatedEditorActiveLineNumber": "Az Id elavult. Használja helyette az 'editorLineNumber.activeForeground' beállítást!", "editorRuler": "A szerkesztőablak sávjainak színe.", "editorCodeLensForeground": "A szerkesztőablakban található kódlencsék előtérszíne", "editorBracketMatchBackground": "Hozzátartozó zárójelek háttérszíne", @@ -28,7 +30,9 @@ "warningBorder": "A figyelmeztetéseket jelző hullámvonal keretszíne a szerkesztőablakban.", "infoForeground": "Az információkat jelző hullámvonal előtérszíne a szerkesztőablakban.", "infoBorder": "Az információkat jelző hullámvonal keretszíne a szerkesztőablakban. ", - "overviewRulerRangeHighlight": "A kiemelt tartományokat jelölő jelzések színe az áttekintősávon.", + "hintForeground": "Az utalásokat jelző hullámvonal előtérszíne a szerkesztőablakban.", + "hintBorder": "Az utalásokat jelző hullámvonal keretszíne a szerkesztőablakban.", + "overviewRulerRangeHighlight": "A kiemelt területeket jelölő jelzések színe az áttekintősávon. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "overviewRuleError": "A hibákat jelölő jelzések színe az áttekintősávon.", "overviewRuleWarning": "A figyelmeztetéseket jelölő jelzések színe az áttekintősávon.", "overviewRuleInfo": "Az információkat jelölő jelzések színe az áttekintősávon." diff --git a/i18n/hun/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/hun/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..5132aa7d40 --- /dev/null +++ b/i18n/hun/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Javítások megjelenítése ({0})", + "quickFix": "Javítások megjelenítése", + "quickfix.trigger.label": "Gyorsjavítás...", + "editor.action.quickFix.noneMessage": "Nem áll rendelkezésre kódművelet", + "refactor.label": "Refaktorálás...", + "editor.action.refactor.noneMessage": "Nem áll rendelkezésre refaktorálási lehetőség", + "source.label": "Forrásművelet...", + "editor.action.source.noneMessage": "Nem áll rendelkezésre forrásművelet", + "organizeImports.label": "Importálások rendezése", + "editor.action.organize.noneMessage": "Nem áll rendelkezésre importálások rendezésére szolgáló művelet" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/find/findController.i18n.json b/i18n/hun/src/vs/editor/contrib/find/findController.i18n.json index 35debd937b..d7b02fe930 100644 --- a/i18n/hun/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Keresés", + "startFindWithSelectionAction": "Keresés kijelöléssel", "findNextMatchAction": "Következő találat", "findPreviousMatchAction": "Előző találat", "nextSelectionMatchFindAction": "Következő kijelölés", diff --git a/i18n/hun/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/hun/src/vs/editor/contrib/format/formatActions.i18n.json index cd6828e2eb..0b48def52d 100644 --- a/i18n/hun/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "{0} formázást végzett a(z) {1}. és {2}. sorok között", "no.provider": "Nincs formázó telepítve a(z) '{0}' típusú fájlokhoz.", "formatDocument.label": "Dokumentum formázása", - "formatSelection.label": "Kijelölt tartalom formázása" + "no.documentprovider": "Nincs dokumentumformázó telepítve a(z) '{0}' típusú fájlokhoz.", + "formatSelection.label": "Kijelölt tartalom formázása", + "no.selectionprovider": "Nincs kijelölésformázó telepítve a(z) '{0}' típusú fájlokhoz." } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 2e890525ef..6a568875bd 100644 --- a/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Következő probléma (hiba, figyelmeztetés, információ)", - "markerAction.previous.label": "Előző probléma (hiba, figyelmeztetés, információ)", - "editorMarkerNavigationError": "A szerkesztőablak jelzőnavigációs moduljának színe hiba esetén.", - "editorMarkerNavigationWarning": "A szerkesztőablak jelzőnavigációs moduljának színe figyelmeztetés esetén.", - "editorMarkerNavigationInfo": "A szerkesztőablak jelzőnavigációs moduljának színe információ esetén.", - "editorMarkerNavigationBackground": "A szerkesztőablak jelzőnavigációs moduljának háttérszíne." + "markerAction.previous.label": "Előző probléma (hiba, figyelmeztetés, információ)" } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/hun/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..60534d6d43 --- /dev/null +++ b/i18n/hun/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "A szerkesztőablak jelzőnavigációs moduljának színe hiba esetén.", + "editorMarkerNavigationWarning": "A szerkesztőablak jelzőnavigációs moduljának színe figyelmeztetés esetén.", + "editorMarkerNavigationInfo": "A szerkesztőablak jelzőnavigációs moduljának színe információ esetén.", + "editorMarkerNavigationBackground": "A szerkesztőablak jelzőnavigációs moduljának háttérszíne." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/links/links.i18n.json b/i18n/hun/src/vs/editor/contrib/links/links.i18n.json index afe2094238..c694b25123 100644 --- a/i18n/hun/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/links/links.i18n.json @@ -6,11 +6,13 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "links.navigate.mac": "Hivatkozott oldal megnyitása Cmd + kattintás paranccsal", + "links.navigate.mac": "Hivatkozás megnyitása Ctrl + kattintás paranccsal", "links.navigate": "Hivatkozott oldal megnyitása Ctrl + kattintás paranccsal", "links.command.mac": "Cmd + kattintás a parancs végrehajtásához", "links.command": "Ctrl + kattintás a parancs végrehajtásához", + "links.navigate.al.mac": "Hivatkozás megnyitása az Option + kattintás paranccsal", "links.navigate.al": "Hivatkozás megnyitása Alt + kattintás paranccsal", + "links.command.al.mac": "Option + kattintás a parancs végrehajtásához", "links.command.al": "Alt + kattintás a parancs végrehajtásához", "invalid.url": "A hivatkozást nem sikerült megnyitni, mert nem jól formázott: {0}", "missing.url": "A hivatkozást nem sikerült megnyitni, hiányzik a célja.", diff --git a/i18n/hun/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/hun/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..4b62af37a2 --- /dev/null +++ b/i18n/hun/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Nem lehet szerkeszteni egy csak olvasható szerkesztőablakban" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/hun/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index d1c87b75ff..a168907a7c 100644 --- a/i18n/hun/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "A betekintőablak szerkesztőablakának háttérszíne.", "peekViewEditorGutterBackground": "A betekintőablak szerkesztőablakában található margó háttérszíne.", "peekViewResultsMatchHighlight": "Kiemelt keresési eredmények színe a betekintőablak eredménylistájában.", - "peekViewEditorMatchHighlight": "Kiemelt keresési eredmények színe a betekintőablak szerkesztőablakában." + "peekViewEditorMatchHighlight": "Kiemelt keresési eredmények színe a betekintőablak szerkesztőablakában.", + "peekViewEditorMatchHighlightBorder": "Kiemelt keresési eredmények keretszíne a betekintőablak szerkesztőablakában." } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/hun/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..57dd858270 --- /dev/null +++ b/i18n/hun/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "vasárnap", + "Monday": "hétfő", + "Tuesday": "kedd", + "Wednesday": "szerda", + "Thursday": "csütörtök", + "Friday": "péntek", + "Saturday": "szombat", + "SundayShort": "vas", + "MondayShort": "hét", + "TuesdayShort": "kedd", + "WednesdayShort": "sze", + "ThursdayShort": "csüt", + "FridayShort": "pén", + "SaturdayShort": "szo", + "January": "január", + "February": "február", + "March": "március", + "April": "április", + "May": "május", + "June": "június", + "July": "július", + "August": "augusztus", + "September": "szeptember", + "October": "október", + "November": "november", + "December": "december", + "JanuaryShort": "jan", + "FebruaryShort": "feb", + "MarchShort": "márc", + "AprilShort": "ápr", + "MayShort": "máj", + "JuneShort": "jún", + "JulyShort": "júl", + "AugustShort": "aug", + "SeptemberShort": "szept", + "OctoberShort": "okt", + "NovemberShort": "nov", + "DecemberShort": "dec" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 407d8750db..1c77483f75 100644 --- a/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Szimbólumok háttérszíne írási hozzáférés, például változó írása esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "wordHighlightBorder": "Szimbólumok háttérszíne olvasási hozzáférés, például változó olvasása esetén.", "wordHighlightStrongBorder": "Szimbólumok háttérszíne írási hozzáférés, például változó írása esetén.", - "overviewRulerWordHighlightForeground": "A kiemelt szimbólumokat jelölő jelzések színe az áttekintősávon.", - "overviewRulerWordHighlightStrongForeground": "A kiemelt, írási hozzáférésű szimbólumokat jelölő jelzések színe az áttekintősávon.", + "overviewRulerWordHighlightForeground": "A kiemelt szimbólumokat jelölő jelzések színe az áttekintősávon. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "overviewRulerWordHighlightStrongForeground": "Az írási hozzáféréssel rendelkező szimbólumokat jelölő jelzések színe az áttekintősávon. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "wordHighlight.next.label": "Ugrás a következő kiemelt szimbólumhoz", "wordHighlight.previous.label": "Ugrás az előző kiemelt szimbólumhoz" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/hun/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..43e1fb7070 --- /dev/null +++ b/i18n/hun/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 további fájl nincs megjelenítve", + "moreFiles": "...{0} további fájl nincs megjelenítve" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/hun/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..d1d33322cd --- /dev/null +++ b/i18n/hun/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Mégse" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/environment/node/argv.i18n.json b/i18n/hun/src/vs/platform/environment/node/argv.i18n.json index 221fa561e8..e40b4edd0e 100644 --- a/i18n/hun/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/hun/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "Telepített kiegészítők verziójának megjelenítése a --list-extension kapcsoló használata esetén.", "installExtension": "Kiegészítő telepítése.", "uninstallExtension": "Kiegészítő eltávolítása.", - "experimentalApis": "Tervezett API-funkciók engedélyezése egy kiegészítő számára.", + "experimentalApis": "Tervezett API-funkciók engedélyezése a kiegészítők számára.", "verbose": "Részletes kimenet kiírása (magába foglalja a --wait kapcsolót)", "log": "A naplózott események szintje.Az 'info' az alapértelmezett értéke. Lehetséges értékek: 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Folyamatok erőforrás-használati és diagnosztikai adatinak kiíratása.", "performance": "Indítás a 'Developer: Startup Performance' parancs engedélyezésével.", "prof-startup": "Processzorhasználat profilozása induláskor", "disableExtensions": "Összes telepített kiegészítő letiltása.", - "inspect-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz.", - "inspect-brk-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben, úgy, hogy a kiegészítő gazdafolyamata szüneteltetve lesz az indítás után. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz. ", + "inspect-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben. A csatlakozási URI-t a fejlesztői eszközöknél találja meg.", + "inspect-brk-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben, úgy, hogy a kiegészítő gazdafolyamata szüneteltetve lesz az indítás után. A csatlakozási URI-t a fejlesztői eszközöknél találja meg.", "disableGPU": "Hardveres gyorsítás letiltása.", "uploadLogs": "Az aktuális munkamenet naplóinak feltöltése egy biztonságos végpontra.", "maxMemory": "Egy ablak maximális memóriamérete (megabájtban).", diff --git a/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index d51f478f61..2c206b7274 100644 --- a/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "A kiegészítő érvénytelen: a package.json nem egy JSON-fájl.", + "incompatible": "A(z) '{0}' kiegészítő nem telepíthető, mivel nem kompatibilis a Code '{1}' verziójával.", "restartCode": "Indítsa újra a Code-ot a(z) {0} újratelepítése előtt.", "installingOutdatedExtension": "A kiegészítő egy újabb verziója már telepítve van. Szeretné felülírni a régebbi verzióval?", "override": "Felülírás", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Hiba a függőségek telepítése közben. {0}", "MarketPlaceDisabled": "A piactér nincs engedélyezve", "removeError": "Hiba történt a kiegészítő eltávolítása közben: {0}. Lépjen ki és indítsa el a VS Code-ot mielőtt újrapróbálná!", - "Not Market place extension": "Csak a piactérről származó kiegészítőket lehet újratelepíteni", + "Not a Marketplace extension": "Csak a piactérről származó kiegészítőket lehet újratelepíteni", "notFoundCompatible": "A(z) '{0}' nem telepíthető: nincs a VS Code '{1}' verziójával kompatibilis változat.", "malicious extension": "A kiegészítő nem telepíthető, mert jelentették, hogy problémás.", "notFoundCompatibleDependency": "A telepítés nem sikerült, mert a(z) '{0}' kiegészítő függőség VS Code '{1}' verziójával kompatibilis változata nem található. ", "quitCode": "A kiegészítő telepítése nem sikerült. Lépjen ki és indítsa el a VS Code-ot az újratelepítés előtt!", "exitCode": "A kiegészítő telepítése nem sikerült. Lépjen ki és indítsa el a VS Code-ot az újratelepítés előtt!", + "renameError": "Ismeretlen hiba történt a(z) {0} {1} névre való átnevezése közben", "uninstallDependeciesConfirmation": "Csak a(z) '{0}' kiegészítőt szeretné eltávolítani vagy annak függőségeit is?", - "uninstallOnly": "Csak ezt", - "uninstallAll": "Mindent", + "uninstallOnly": "Csak a kiegészítőt", + "uninstallAll": "Az összes eltávolítása", "uninstallConfirmation": "Biztosan szeretné eltávolítani a(z) '{0}' kiegészítőt?", "ok": "OK", "singleDependentError": "Nem sikerült eltávolítani a(z) '{0}' kiegészítőt: a(z) '{1}' kiegészítő függ tőle.", diff --git a/i18n/hun/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/hun/src/vs/platform/extensions/node/extensionValidator.i18n.json index 2755341ef3..161c3de96e 100644 --- a/i18n/hun/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/hun/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Nem sikerült feldolgozni az `engines.vscode` beállítás értékét ({0}). Használja például a következők egyikét: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x stb.", + "versionSyntax": "Nem sikerült feldolgozni az `engines.vscode` beállítás értékét ({0}). Használja például a következők egyikét: ^1.22.0, ^1.22.x stb.", "versionSpecificity1": "Az `engines.vscode` beállításban megadott érték ({0}) nem elég konkrét. A vscode 1.0.0 előtti verzióihoz legalább a kívánt fő- és alverziót is meg kell adni. Pl.: ^0.10.0, 0.10.x, 0.11.0 stb.", "versionSpecificity2": "Az `engines.vscode` beállításban megadott érték ({0}) nem elég konkrét. A vscode 1.0.0 utáni verzióihoz legalább a kívánt főverziót meg kell adni. Pl.: ^1.10.0, 1.10.x, 1.x.x, 2.x.x stb.", "versionMismatch": "A kiegészítő nem kompatibilis a Code {0} verziójával. A következő szükséges hozzá: {1}." diff --git a/i18n/hun/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/hun/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index e2f9b9c9fa..9e03e7a885 100644 --- a/i18n/hun/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/hun/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "A feltelepített {0} hibásnak tűnik. Telepítse újra!", "integrity.moreInformation": "További információ", - "integrity.dontShowAgain": "Ne jelenítse meg újra", - "integrity.prompt": "A feltelepített {0} hibásnak tűnik. Telepítse újra!" + "integrity.dontShowAgain": "Ne jelenítse meg újra" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/hun/src/vs/platform/issue/electron-main/issueService.i18n.json index 2e6142ba24..a558ed2272 100644 --- a/i18n/hun/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/hun/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Hibajelentő" + "issueReporter": "Hibajelentő", + "processExplorer": "Feladatkezelő" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/keybinding/common/abstractKeybindingService.i18n.json b/i18n/hun/src/vs/platform/keybinding/common/abstractKeybindingService.i18n.json index 495a53b7d9..b57a9aedd6 100644 --- a/i18n/hun/src/vs/platform/keybinding/common/abstractKeybindingService.i18n.json +++ b/i18n/hun/src/vs/platform/keybinding/common/abstractKeybindingService.i18n.json @@ -6,6 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "first.chord": "Lenyomta a következőt: ({0}). Várakozás a kombináció második billentyűjére...", + "first.chord": "Lenyomott billentyű: ({0}) Várakozás a kombináció második billentyűjére...", "missing.chord": "A(z) ({0}, {1}) billentyűkombináció nem egy parancs." } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/list/browser/listService.i18n.json b/i18n/hun/src/vs/platform/list/browser/listService.i18n.json index 2b7799c64a..dcb62dc211 100644 --- a/i18n/hun/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/hun/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Több elem kijelölése esetén újabb elem hozzáadásához használt módosítóbillentyű a fanézetekben és listákban (például a fájlkezelőben, a megnyitott szerkesztőablakok listájában és a verziókezelő rendszer nézeten). A `ctrlCmd` Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti. A 'Megnyitás oldalt\" egérgesztusok – ha támogatva vannak – automatikusan úgy lesznek beállítva, hogy ne ütközzenek a több elem kijelöléséhez tartozó módosító billentyűvel.", "openMode.singleClick": "Elemek megnyitása egyetlen kattintásra.", "openMode.doubleClick": "Elemek megnyitása dupla kattintásra.", - "openModeModifier": "Meghatározza, hogyan nyíljanak meg az elemek a fanézetekben és listákban egér használata esetén (ha támogatott). `singleClick` esetén egyetlen kattintásra megnyílnak az elemek, míg `doubleClick` esetén dupla kattintás szükséges. Fanézeteknél meghatározza, hogy a szülőelemek egyetlen vagy dupla kattintásra nyílnak ki. Megjegyzés: néhány fanézet és lista figyelmen kívül hagyja ezt a beállítást ott, ahol ez nem alkalmazható. " + "openModeModifier": "Meghatározza, hogyan nyíljanak meg az elemek a fanézetekben és listákban egér használata esetén (ha támogatott). `singleClick` esetén egyetlen kattintásra megnyílnak az elemek, míg `doubleClick` esetén dupla kattintás szükséges. Fanézeteknél meghatározza, hogy a szülőelemek egyetlen vagy dupla kattintásra nyílnak ki. Megjegyzés: néhány fanézet és lista figyelmen kívül hagyja ezt a beállítást ott, ahol ez nem alkalmazható. ", + "horizontalScrolling setting": "Meghatározza, hogy a fák támogatják-e a vízszintes görgetést a munkaterületen." } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/markers/common/markers.i18n.json b/i18n/hun/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..ba6e96532e --- /dev/null +++ b/i18n/hun/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Hiba", + "sev.warning": "Figyelmeztetés", + "sev.info": "Információ" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json index 6b45855f11..8338f95df0 100644 --- a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -93,6 +93,6 @@ "overviewRulerCurrentContentForeground": "A helyi tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.", "overviewRulerIncomingContentForeground": "A beérkező tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.", "overviewRulerCommonContentForeground": "A közös ős tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén. ", - "overviewRulerFindMatchForeground": "A keresési találatokat jelölő jelzések színe az áttekintősávon.", - "overviewRulerSelectionHighlightForeground": "A kiemelt kijelöléseket jelölő jelzések színe az áttekintősávon." + "overviewRulerFindMatchForeground": "A keresési találatokat jelölő jelzések színe az áttekintősávon. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "overviewRulerSelectionHighlightForeground": "A kijelölt területeket jelölő jelzések színe az áttekintősávon. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat." } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/hun/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..f6bafd3286 --- /dev/null +++ b/i18n/hun/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "Szeretné engedélyezni a(z) {0} kiegészítő számára a következő URL-cím megnyitását?" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/windows/electron-main/windowsService.i18n.json b/i18n/hun/src/vs/platform/windows/electron-main/windowsService.i18n.json index 4d8cdce308..6c56153302 100644 --- a/i18n/hun/src/vs/platform/windows/electron-main/windowsService.i18n.json +++ b/i18n/hun/src/vs/platform/windows/electron-main/windowsService.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "aboutDetail": "Verzió: {0}\nCommit: {1}\nDátum: {2}\nShell: {3}\nRendelő: {4}\nNode: {5}\nArchitektúra: {6}", + "aboutDetail": "\nVerzió: {0}\nCommit: {1}\nDátum: {2}\nShell: {3}\nRenderelő: {4}\nNode: {5}\nArchitektúra: {6}", "okButton": "OK", "copy": "&&Másolás" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/hun/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..215c70faf9 --- /dev/null +++ b/i18n/hun/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "A gyűjtemény egyedi azonosítója, mellyel nézetek rendelhetők hozzá a 'views' értékeivel.", + "vscode.extension.contributes.views.containers.title": "A gyűjtemény megjelenítésénél használt, emberek számára szánt neve", + "vscode.extension.contributes.views.containers.icon": "A gyűjtemény ikonjának elérési útja. Az ikonok 24x24 pixel méretűek, és középre vannak igazítva egy 50x40-es téglalapban. A kitöltési színük 'rgb(215, 218, 224)' vagy '#d7dae0'. Ajánlott az SVG-formátum használata, de bármely képfájltípus elfogadott.", + "vscode.extension.contributes.viewsContainers": "Nézetgyűjteményeket szolgáltat a szerkesztőhöz", + "views.container.activitybar": "Nézetgyűjteményeket szolgáltat a tevékenységsávra", + "test": "Teszt", + "proposed": "A 'viewsContainers' csak a fejlesztői változatban vagy az --enable-proposed-api {1} kapcsoló használata esetén érhető el.", + "requirearray": "a nézetgyűjteményeket tömbként kell megadni", + "requireidstring": "a(z) `{0}` tulajdonság kötelező és `string` típusúnak kell lennie. Csak alfanumerikus karaktereket, alulvonást és kötőjelet tartalmazhat.", + "requirestring": "a(z) `{0}` tulajdonság kötelező és `string` típusúnak kell lennie", + "showViewlet": "{0} megjelenítése", + "view": "Nézet" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/hun/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index c62b2128ff..a7b44a55c5 100644 --- a/i18n/hun/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/hun/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -10,12 +10,15 @@ "requirestring": "a(z) `{0}` tulajdonság kötelező és `string` típusúnak kell lennie", "optstring": "a(z) `{0}` tulajdonság elhagyható vagy `string` típusúnak kell lennie", "vscode.extension.contributes.view.id": "A nézet azonosítója. Ez használható az adatszolgáltató regisztrálásához a `vscode.window.registerTreeDataProviderForView` API-n keresztül. Ezen túl a kiegészítő aktiválásához regisztrálni kell az `onView:${id}` eseményt az `activationEvents`-nél.", - "vscode.extension.contributes.view.name": "A nézet emberek számára olvasható neve. Meg fog jelenni", + "vscode.extension.contributes.view.name": "A nézet emberek számára szánt neve. Megjelenik a felületen.", "vscode.extension.contributes.view.when": "A nézet megjelenítésének feltétele", "vscode.extension.contributes.views": "Nézeteket szolgáltat a szerkesztőhöz", - "views.explorer": "Fájlkezelő-nézet", - "views.debug": "Hibakeresési nézet", - "locationId.invalid": "A(z) `{0}` nem érvényes nézethelyszín", + "views.explorer": "Nézeteket szolgáltat a tevékenységsávon található Fájlkezelő gyűjteményhez.", + "views.debug": "Nézeteket szolgáltat a tevékenységsávon található Hibakeresés gyűjteményhez.", + "views.scm": "Nézeteket szolgáltat a tevékenységsávon található Verziókezelő rendszer gyűjteményhez.", + "views.test": "Nézeteket szolgáltat a tevékenységsávon található Teszt gyűjteményhez.", + "views.contributed": "Nézeteket szolgáltat a szolgáltatott nézetek gyűjteményhez.", + "ViewContainerDoesnotExist": "Nem létezik '{0}' azonosítójú nézetgyűjtemény, és az összes oda regisztrált nézet a Fájlkezelőhöz lesz hozzáadva.", "duplicateView1": "Nem regisztrálható több nézet `{0}` azonosítóval a következő helyen: `{1}`", "duplicateView2": "Már van `{0}` azonosítójú nézet regisztrálva a következő helyen: `{1}`" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index d6218e83d1..82ef2a8589 100644 --- a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Mentéskor végzett formázás megszakítva {0}ms után", + "codeActionsOnSave.didTimeout": "codeActionsOnSave megszakítva {0}ms után", + "timeout.onWillSave": "OnWillSaveTextDocument-esemény megszakítva 1750ms után", "saveParticipants": "Mentési események futtatása..." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index a29500b22b..05b6f4a9d9 100644 --- a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "webview-szerkesztő" + "errorMessage": "Hiba történt a nézet visszaállítása közben: {0}" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/hun/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..c073dbed80 --- /dev/null +++ b/i18n/hun/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (kiegészítő)" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 42a544fa5c..a55e2ef422 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Váltás a következő csoportra", "openToSide": "Megnyitás oldalt", "closeEditor": "Szerkesztőablak bezárása", + "closeOneEditor": "Bezárás", "revertAndCloseActiveEditor": "Visszaállítás és szerkesztőablak bezárása", "closeEditorsToTheLeft": "Balra lévő szerkesztőablakok bezárása", "closeAllEditors": "Összes szerkesztőablak bezárása", diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 93a2ded79e..17a1a32799 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Ha nem használ képernyőolvasót, állítsa az `editor.accessibilitySupport` értékét \"off\"-ra.", "disableTabMode": "Kisegítő mód letiltása", "gotoLine": "Sor megkeresése", - "indentation": "Indentálás", + "selectIndentation": "Indentálás kiválasztása", "selectEncoding": "Kódolás kiválasztása", "selectEOL": "Sorvégjel kiválasztása", "selectLanguageMode": "Nyelvmód kiválasztása", diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index acbf3364df..2f930acfd5 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} MB", "sizeGB": "{0} GB", "sizeTB": "{0} TB", - "largeImageError": "A képfájl mérete túl nagy (>1 MB) a szerkesztőben való megjelenítéshez.", + "largeImageError": "A kép nincs megjelenítve, mert túl nagy ({0}).", "resourceOpenExternalButton": "Kép megnyitása külső program használatával?", - "nativeBinaryError": "A fájl nem jeleníthető meg a szerkesztőben, mert bináris adatokat tartalmaz, túl nagy vagy nem támogatott szövegkódolást használ.", + "nativeFileTooLargeError": "A fájl nem jeleníthető meg a szerkesztőben, mert túl nagy ({0}).", + "nativeBinaryError": "A fájl nem jeleníthető meg a szerkesztőben, mert bináris adatokat tartalmaz vagy nem támogatott szövegkódolást használ.", + "openAsText": "Mégis meg szeretné nyitni?", "zoom.action.fit.label": "Teljes kép", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 4b2a143061..bffd7d2025 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Bezárás", "araLabelEditorActions": "Szerkesztőablak-műveletek" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 67e38cc1fa..fccdcadbf2 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Nincs új értesítés", "notifications": "Értesítések", "notificationsToolbar": "Értesítésiközpont-műveletek", "notificationsList": "Értesítések listája" diff --git a/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..614736ffe7 --- /dev/null +++ b/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Nyomjon 'Enter'-t a megerősítéshez vagy 'Escape'-et a megszakításhoz)", + "inputModeEntry": "Nyomjon 'Enter'-t a megerősítéshez vagy 'Escape'-et a megszakításhoz", + "quickInput.countSelected": "{0} kiválasztva", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..f402e9c2fe --- /dev/null +++ b/i18n/hun/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Kezdjen el gépelni a találati lista szűkítéséhez!" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json index d1c046d20d..cd27394d28 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Legutóbbi megnyitása...", "quickOpenRecent": "Legutóbbi gyors megnyitása...", "reportIssueInEnglish": "Probléma jelentése", + "openProcessExplorer": "Feladatkezelő megnyitása", "reportPerformanceIssue": "Teljesítményproblémák jelentése", "keybindingsReference": "Billentyűparancs-referencia", "openDocumentationUrl": "Dokumentáció", diff --git a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json index 39dc5d9bf4..bf6e9dc4c0 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Ablak", "window.openFilesInNewWindow.on": "A fájlok új ablakban nyílnak meg", "window.openFilesInNewWindow.off": "A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban", - "window.openFilesInNewWindow.default": "A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban, kivéve, ha a dokkról vagy a Finderből lettek megnyitva (csak macOS-en)", - "openFilesInNewWindow": "Meghatározza, hogy a fájlok új ablakban legyenek-e megnyitva.\n- default: A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban, kivéve, ha a dokkról vagy a Finderből lettek megnyitva (csak macOS-en)\n- on: A fájlok új ablakban nyílnak meg.\n- off: A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban\nMegjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva (pl. a -new-window vagy a -reuse-window parancssori beállítás használata esetén).", + "window.openFilesInNewWindow.defaultMac": "A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban, kivéve, ha a dokkról vagy a Finderből lettek megnyitva", + "window.openFilesInNewWindow.default": "A fájlok új ablakban nyílnak meg, kivéve akkor, ha az alkalmazáson belül lettek kiválasztva (pl. a Fájl menüből)", + "openFilesInNewWindowMac": "Meghatározza, hogy a fájlok új ablakban legyenek-e megnyitva.\n- default: A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban, kivéve, ha a dokkról vagy a Finderből lettek megnyitva\n- on: A fájlok új ablakban nyílnak meg.\n- off: A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban\nMegjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva (pl. a -new-window vagy a -reuse-window parancssori beállítás használata esetén).", + "openFilesInNewWindow": "Meghatározza, hogy a fájlok új ablakban legyenek-e megnyitva.\n- default: A fájlok új ablakban nyílnak meg, kivéve akkor, ha az alkalmazáson belül lettek kiválasztva (pl. a Fájl menüből).\n- on: A fájlok új ablakban nyílnak meg.\n- off: A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban\nMegjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva (pl. a -new-window vagy a -reuse-window parancssori beállítás használata esetén).", "window.openFoldersInNewWindow.on": "A mappák új ablakban nyílnak meg", "window.openFoldersInNewWindow.off": "A mappák lecserélik a legutoljára aktív ablakot", "window.openFoldersInNewWindow.default": "A mappák új ablakban nyílnak meg, kivéve akkor, ha a mappát az alkalmazáson belül lett kiválasztva (pl. a Fájl menüből)", "openFoldersInNewWindow": "Meghatározza, hogy a mappák új ablakban legyenek-e megnyitva.\n- alapértelmezett: A mappák új ablakban nyílnak meg, kivéve akkor, ha a mappát az alkalmazáson belül lett kiválasztva (pl. a Fájl menüből)\n- on: A mappák új ablakban nyílnak meg\n- off: A mappák lecserélik a legutoljára aktív ablakot\nMegjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva (pl. a -new-window vagy a -reuse-window parancssori beállítás használata esetén).", + "window.openWithoutArgumentsInNewWindow.on": "Új, üres ablak megnyitása", + "window.openWithoutArgumentsInNewWindow.off": "Váltás a legutóbb aktív, futó példányra", + "openWithoutArgumentsInNewWindow": "Meghatározza, hogy egy új, üres ablak nyíljon-e meg, ha egy új példány indul paraméterek nélkül, vagy váltson a legutóbb aktív, futó példányra.\n- on: Új, üres ablak megnyitása.\n- off: váltás a legutóbb aktív, futó példányra\nMegjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva (pl. a -new-window vagy a -reuse-window parancssori beállítás használata esetén).", "window.reopenFolders.all": "Összes ablak újranyitása.", "window.reopenFolders.folders": "Összes mappa újranyitása. Az üres munkaterületek nem lesznek helyreállítva.", "window.reopenFolders.one": "A legutóbbi aktív ablak újranyitása.", @@ -58,7 +63,7 @@ "restoreWindows": "Meghatározza, hogy újraindítás után hogyan vannak ismét megnyitva az ablakok. A 'none' választása esetén mindig üres munkaterület indul, 'one' esetén a legutóbb használt ablak nyílik meg újra, a 'folders' megnyitja az összes megnyitott mappát, míg az 'all' újranyitja az összes ablakot az előző munkamenetből.", "restoreFullscreen": "Meghatározza, hogy az ablak teljesképernyős módban nyíljon-e meg, ha kilépéskor teljes képernyős módban volt.", "zoomLevel": "Meghatározza az ablak nagyítási szintjét. Az eredei méret 0, és minden egyes plusz (pl. 1) vagy mínusz (pl. -1) 20%-kal nagyobb vagy kisebb nagyítási szintet jelent. Tizedestört megadása esetén a nagyítási szint finomabban állítható.", - "title": "Meghatározza az ablak címét az aktív szerkesztőablak alapján. A változók a környezet alapján vannak behelyettesítve:\n${activeEditorShort}: a fájl neve (pl. myFile.txt)\n${activeEditorMedium}: a fájl relatív elérési útja a munkaterület mappájához képest (pl. myFolder/myFile.txt)\n${activeEditorLong}: a fájl teljes elérési útja (pl. /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: azon munkaterületi mappa a neve, amelyben a fájl található (pl. myFolder)\n${folderPath}: azon munkaterületi mappa elérési útja, amelyben a fájl található (pl. /Users/Development/myFolder)\n${rootName}: a munkaterület neve (pl. myFolder vagy myWorkspace)\n${rootPath}: a munkaterület elérési útja (pl. /Users/Development/myWorkspace)\n${appName}: pl. VS Code\n${dirty}: módosításjelző, ami jelzi, ha az aktív szerkesztőablak tartalma módosítva lett\n${separator}: feltételes elválasztó (\" - \"), ami akkor jelenik meg, ha olyan változókkal van körülvéve, amelyeknek van értéke", + "title": "Meghatározza az ablak címét az aktív szerkesztőablak alapján. A változók a környezet alapján vannak behelyettesítve:\n${activeEditorShort}: az aktív fájl neve (pl. myFile.txt)\n${activeEditorMedium}: a fájl relatív elérési útja a munkaterület mappájához képest (pl. myFolder/myFile.txt)\n${activeEditorLong}: a fájl teljes elérési útja (pl. /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: azon munkaterületi mappa a neve, amelyben a fájl található (pl. myFolder)\n${folderPath}: azon munkaterületi mappa elérési útja, amelyben a fájl található (pl. /Users/Development/myFolder)\n${rootName}: a munkaterület neve (pl. myFolder vagy myWorkspace)\n${rootPath}: a munkaterület elérési útja (pl. /Users/Development/myWorkspace)\n${appName}: pl. VS Code\n${dirty}: módosításjelző, ami jelzi, ha az aktív szerkesztőablak tartalma módosítva lett\n${separator}: feltételes elválasztó (\" - \"), ami akkor jelenik meg, ha statikus szöveggek vagy olyan változókkal van körülvéve, amelyeknek van értéke\n", "window.newWindowDimensions.default": "Az új ablakok a képernyő közepén nyílnak meg.", "window.newWindowDimensions.inherit": "Az új ablakok ugyanolyan méretben és ugyanazon a helyen jelennek meg, mint a legutoljára aktív ablak.", "window.newWindowDimensions.maximized": "Az új ablakok teljes méretben nyílnak meg.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Ha engedélyezve van, az alkalmazás automatikusan átvált a nagy kontrasztos témára, ha a WIndows a nagy kontrasztos témát használ, és a sötét témára, ha a Windows átvált a nagy kontrasztos témáról.", "titleBarStyle": "Módosítja az ablak címsorának megjelenését. A változtatás teljes újraindítást igényel.", "window.nativeTabs": "Engedélyezi a macOS Sierra ablakfüleket. Megjegyzés: a változtatás teljes újraindítást igényel, és a natív fülek letiltják az egyedi címsorstílust, ha azok be vannak konfigurálva.", + "window.smoothScrollingWorkaround": "Akkor engedélyezze ezt a kerülőmegoldást, ha a görgetés nem egyenletes egy kis méretre rakott VS Code-ablak helyreállítása után. Ez egy kerülőmegoldás arra a problémára (https://github.com/Microsoft/vscode/issues/13612), amely a trackpadokkal rendelkező eszközöket érinti, például a Microsoft Surface készülékeit. A kerülőmegoldás engedélyezése a felület elrendezésének ugrálásával járhat az ablak kis méretből való helyreállítása után, de egyébként nem okoz más problémát.", + "window.clickThroughInactive": "Ha engedélyezve van, akkor egy inaktív ablakra való kattintás aktiválja az ablakot, valamint kattintási esemény keletkezik az egér alatt lévő elemen is, ha az kattintható. Ha le van tiltva, akkor az inaktív ablakra való kattintás csak az ablak aktiválását eredményezi, és egy újabb kattintás szükséges az elemen.", "zenModeConfigurationTitle": "Zen-mód", "zenMode.fullScreen": "Meghatározza, hogy zen-módban a munakterület teljes képernyős módba vált-e.", "zenMode.centerLayout": "Meghatározza, hogy zen-módban középre igazított elrendezés van-e.", diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index cf644f6276..fe7ad6918b 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Töréspont szerkesztése...", + "logPoint": "Naplózási pont", + "breakpoint": "Töréspont", + "editBreakpoint": "{0} szerkesztése...", + "removeBreakpoint": "{0} eltávolítása", "functionBreakpointsNotSupported": "Ez a hibakereső nem támogatja a függvénytöréspontokat", "functionBreakpointPlaceholder": "A függvény, amin meg kell állni", "functionBreakPointInputAriaLabel": "Adja meg a függvénytöréspontot", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Nem megerősített töréspont", "functionBreakpointUnsupported": "Ez a hibakereső nem támogatja a függvénytöréspontokat", "breakpointDirtydHover": "Nem megerősített töréspont. A fájl módosult, indítsa újra a hibakeresési munkamenetet.", + "logBreakpointUnsupported": "Ez a hibakereső nem támogatja a naplózási pontokat", "conditionalBreakpointUnsupported": "Ez a hibakereső nem támogatja a feltételes töréspontokat", "hitBreakpointUnsupported": "Ez a hibakereső nem támogatja az érintési feltételes töréspontokat" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 06418edd2e..69d784bbd3 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Kapcsolat bontása", "continueDebug": "Folytatás", "pauseDebug": "Szüneteltetés", + "terminateThread": "Szál megszüntetése", "restartFrame": "Keret újraindítása", "removeBreakpoint": "Töréspont eltávolítása", "removeAllBreakpoints": "Összes töréspont eltávolítása", - "enableBreakpoint": "Töréspont engedélyezése", - "disableBreakpoint": "Töréspont letiltása", "enableAllBreakpoints": "Összes töréspont engedélyezése", "disableAllBreakpoints": "Összes töréspont letiltása", "activateBreakpoints": "Töréspontok aktiválása", "deactivateBreakpoints": "Töréspontok deaktiválása", "reapplyAllBreakpoints": "Töréspontok felvétele ismét", "addFunctionBreakpoint": "Függvénytöréspont hozzáadása", - "addConditionalBreakpoint": "Feltételes töréspont hozzáadása...", - "editConditionalBreakpoint": "Töréspont szerkesztése...", "setValue": "Érték beállítása", "addWatchExpression": "Kifejezés hozzáadása", "editWatchExpression": "Kifejezés szerkesztése", diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 923bdcbdde..51c172cb0e 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Hibakeresés: Töréspont be- és kikapcsolása", "conditionalBreakpointEditorAction": "Hibakeresés: Feltételes töréspont...", + "logPointEditorAction": "Hibakeresés: Naplózási pont hozzáadása...", "runToCursor": "Futtatás a kurzorig", "debugEvaluate": "Hibakeresés: Kiértékelés", "debugAddToWatch": "Hibakeresés: Hozzáadás a figyelőlistához", diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..b6de2b1518 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "A töréspont érintése esetén naplózandó üzenet. A {} karakterek közötti kifejezések interpolálva lesznek. 'Enter' a megerősítéshez vagy 'Escape' a megszakításhoz.", + "breakpointWidgetHitCountPlaceholder": "Futás megállítása, ha adott alkalommal érintve lett. 'Enter' a megerősítéshez vagy 'Escape' a megszakításhoz.", + "breakpointWidgetExpressionPlaceholder": "Futás megállítása, ha a kifejezés értéke igazra értékelődik ki. 'Enter' a megerősítéshez vagy 'Escape' a megszakításhoz.", + "expression": "Kifejezés", + "hitCount": "Érintések száma", + "logMessage": "Üzenet naplózása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index c89cc33512..c859982a0f 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Használjon egyedi konfigurációs neveket!", "app.launch.json.compound.folder": "A mappa neve, ahol az összetett konfiguráció található.", "app.launch.json.compounds.configurations": "Azon konfigurációk neve, melyek elindulnak ezen kombináció részeként.", - "debugNoType": "A hibakeresési illesztő 'type' tulajdonsága kötelező, és 'string' típusúnak kell lennie.", + "debugNoType": "A hibakereső 'type' tulajdonsága kötelező, és 'string' típusúnak kell lennie.", "selectDebug": "Környezet kiválasztása", "DebugConfig.failed": "Nem sikerült létrehozni a 'launch.json' fájlt a '.vscode' mappánan ({0}).", "workspace": "munkaterület", diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 66682d20da..4fbade7183 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Naplózási pont", + "breakpoint": "Töréspont", + "removeBreakpoint": "{0} eltávolítása", + "editBreakpoint": "{0} szerkesztése...", + "disableBreakpoint": "{0} letiltása", + "enableBreakpoint": "{0} engedélyezése", "removeBreakpoints": "Töréspontok eltávolítása", "removeBreakpointOnColumn": "{0}. oszlopban található töréspont eltávolítása", "removeLineBreakpoint": "Sorra vonatkozó töréspont eltávolítása", @@ -18,5 +24,13 @@ "enableBreakpoints": "{0}. oszlopban található töréspont engedélyezése", "enableBreakpointOnLine": "Sorszintű töréspont engedélyezése", "addBreakpoint": "Töréspont hozzáadása", + "addConditionalBreakpoint": "Feltételes töréspont hozzáadása...", + "addLogPoint": "Naplózási pont hozzáadása...", + "breakpointHasCondition": "Ez a(z) {0} {1} rendelkezik, ami elvész az eltávolítás során. Fontolja meg a(z) {0} letiltását!", + "message": "üzenettel", + "condition": "feltétellel", + "removeLogPoint": "{0} eltávolítása", + "disableLogPoint": "{0} letiltása", + "cancel": "Mégse", "addConfiguration": "Konfiguráció hozzáadása..." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 2c720d7f7c..eca8a151f1 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Hibák megjelenítése", "noFolderWorkspaceDebugError": "Az aktív fájlon nem lehet hibakeresést végezni. Bizonyosodjon meg róla, hogy el van mentve a lemezre, és hogy az adott fájltípushoz telepítve van a megfelelő hibakeresési kiegészítő.", "cancel": "Mégse", - "DebugTaskNotFound": "A(z) '{0}' preLaunchTask nem található.", - "taskNotTracked": "A(z) ${0} preLaunchTaskot nem lehet követni." + "DebugTaskNotFound": "A(z) '{0}' feladat nem található.", + "taskNotTracked": "A(z) '{0}' feladatot nem lehet követni." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index dac7ef73bd..13d762d55f 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "További információ", - "unableToLaunchDebugAdapter": "Nem sikerült elindítani a hibakeresési illesztőt a következő helyről: '{0}'.", - "unableToLaunchDebugAdapterNoArgs": "Nem sikerült elindítani a hibakeresési illesztőt.", - "stoppingDebugAdapter": "{0}. Hibakeresési illesztő leállítása.", "debugAdapterCrash": "A hibakeresési illesztő folyamata váratlanul leállt" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 1770c367a1..3e403e0c92 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "A hibakeresési illesztő futtatható állománya ('{0}') nem létezik.", "debugAdapterCannotDetermineExecutable": "Nem határozható meg a(z) '{0}' hibakeresési illesztő futtatható állománya.", - "launch.config.comment1": "IntelliSense használata a lehetséges attribútumok listázásához", - "launch.config.comment2": "Húzza fölé az egeret a létező attribútumok leírásának megtekintéséhez!", - "launch.config.comment3": "További információért látogassa meg a következőt: {0}", - "debugType": "A konfiguráció típusa.", - "debugTypeNotRecognised": "Ez a hibakeresési típus nem ismert. Bizonyosodjon meg róla, hogy telepítve és engedélyezve van a megfelelő hibakeresési kiegészítő.", - "node2NotSupported": "A \"node2\" már nem támogatott. Használja helyette a \"node\"-ot, és állítsa a \"protocol\" attribútum értékét \"inspector\"-ra.", - "debugName": "A konfiguráció neve. Az indítási konfiguráció lenyíló menüjében jelenik meg.", - "debugRequest": "A konfiguráció kérési típusa. Lehet \"launch\" vagy \"attach\".", - "debugServer": "Csak hibakeresési kiegészítők fejlesztéséhez: ha a port meg van adva, akkor a VS Code egy szerver módban futó hibakeresési illesztőhöz próbál meg csatlakozni.", - "debugPrelaunchTask": "A hibakeresési folyamat előtt futtatandó feladat.", - "debugWindowsConfiguration": "Windows-specifikus indítási konfigurációs attribútumok.", - "debugOSXConfiguration": "OS X-specifikus indítási konfigurációs attribútumok.", - "debugLinuxConfiguration": "Linux-specifikus indítási konfigurációs attribútumok.", - "deprecatedVariables": "Az 'env.', 'config.' és 'command.' tujdonságok elavultak, használja helyette az 'env:', 'config:' és 'command:' tulajdonságokat." + "unableToLaunchDebugAdapter": "Nem sikerült elindítani a hibakeresési illesztőt a következő helyről: '{0}'.", + "unableToLaunchDebugAdapterNoArgs": "Nem sikerült elindítani a hibakeresési illesztőt." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..b50ef5b76d --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "IntelliSense használata a lehetséges attribútumok listázásához", + "launch.config.comment2": "Húzza fölé az egeret a létező attribútumok leírásának megtekintéséhez!", + "launch.config.comment3": "További információért látogassa meg a következőt: {0}", + "debugType": "A konfiguráció típusa.", + "debugTypeNotRecognised": "Ez a hibakeresési típus nem ismert. Bizonyosodjon meg róla, hogy telepítve és engedélyezve van a megfelelő hibakeresési kiegészítő.", + "node2NotSupported": "A \"node2\" már nem támogatott. Használja helyette a \"node\"-ot, és állítsa a \"protocol\" attribútum értékét \"inspector\"-ra.", + "debugName": "A konfiguráció neve. Az indítási konfiguráció lenyíló menüjében jelenik meg.", + "debugRequest": "A konfiguráció kérési típusa. Lehet \"launch\" vagy \"attach\".", + "debugServer": "Csak hibakeresési kiegészítők fejlesztéséhez: ha a port meg van adva, akkor a VS Code egy szerver módban futó hibakeresési illesztőhöz próbál meg csatlakozni.", + "debugPrelaunchTask": "A hibakeresési folyamat előtt futtatandó feladat.", + "debugPostDebugTask": "A hibakeresési folyamat vége után futtatandó feladat.", + "debugWindowsConfiguration": "Windows-specifikus indítási konfigurációs attribútumok.", + "debugOSXConfiguration": "OS X-specifikus indítási konfigurációs attribútumok.", + "debugLinuxConfiguration": "Linux-specifikus indítási konfigurációs attribútumok.", + "deprecatedVariables": "Az 'env.', 'config.' és 'command.' tujdonságok elavultak, használja helyette az 'env:', 'config:' és 'command:' tulajdonságokat." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..63c2dd4d54 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code-konzol", + "mac.terminal.script.failed": "A(z) '{0}' parancsfájl a következő hibakóddal lépett ki: {1}", + "mac.terminal.type.not.supported": "A(z) '{0}' nem támogatott", + "press.any.key": "A folytatáshoz nyomjon meg egy billentyűt...", + "linux.term.failed": "A(z) '{0}' a következő hibakóddal lépett ki: {1}" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index a531a62534..a18c062362 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Ajánlott kiegészítők konfigurálása (munkaterület-mappára vonatkozóan)", "malicious tooltip": "A kiegészítőt korábban problémásnak jelezték.", "malicious": "Rosszindulatú", + "disabled": "Letiltva", + "disabled globally": "Letiltva", + "disabled workspace": "Letiltva ezen a munkaterületen", "disableAll": "Összes telepített kiegészítő letiltása", "disableAllWorkspace": "Összes telepített kiegészítő letiltása a munkaterületre vonatkozóan", "enableAll": "Összes kiegészítő engedélyezése", diff --git a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..70f8aa798f --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Kiegészítő neve", + "extension id": "Kiegészítő azonosítója", + "preview": "Betekintő", + "builtin": "Beépített", + "publisher": "Kiadó neve", + "install count": "Telepítések száma", + "rating": "Értékelés", + "repository": "Forráskódtár", + "license": "Licenc", + "details": "Részletek", + "contributions": "Szolgáltatások", + "changelog": "Változtatási napló", + "dependencies": "Függőségek", + "noReadme": "Leírás nem található.", + "noChangelog": "Változtatási napló nem található.", + "noContributions": "Nincsenek szolgáltatások", + "noDependencies": "Nincsenek függőségek", + "settings": "Beállítások ({0})", + "setting name": "Név", + "description": "Leírás", + "default": "Alapértelmezett", + "debuggers": "Hibakeresők ({0})", + "debugger name": "Név", + "debugger type": "Típus", + "views": "Nézetek ({0})", + "view id": "Azonosító", + "view name": "Név", + "view location": "Hol?", + "localizations": "Lokalizációk ({0})", + "localizations language id": "Nyelv azonosítója", + "localizations language name": "Nyelv neve", + "localizations localized language name": "Nyelv neve (lokalizálva)", + "colorThemes": "Színtémák ({0})", + "iconThemes": "Ikontémák ({0})", + "colors": "Színek ({0})", + "colorId": "Azonosító", + "defaultDark": "Alapértelmezett sötét", + "defaultLight": "Alapértelmezett világos", + "defaultHC": "Alapértelmezett nagy kontrasztú", + "JSON Validation": "JSON-validációk ({0})", + "fileMatch": "Fájlegyezés", + "schema": "Séma", + "commands": "Parancsok ({0})", + "command name": "Név", + "keyboard shortcuts": "Billentyűparancsok", + "menuContexts": "Helyi menük", + "languages": "Nyelvek ({0})", + "language id": "Azonosító", + "language name": "Név", + "file extensions": "Fájlkiterjesztések", + "grammar": "Nyelvtan", + "snippets": "Kódtöredékek" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index a91a6e95fe..b399013642 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -8,15 +8,15 @@ ], "neverShowAgain": "Ne jelenítse meg újra", "searchMarketplace": "Keresés a piactéren", - "showLanguagePackExtensions": "A piactéren található olyan kiegészítő, ami lefordítja a(z) '.{0}' VS Code-ot '{0}' nyelvre", + "showLanguagePackExtensions": "A piactéren található olyan kiegészítő, ami lefordítja a VS Code-ot '{0}' nyelvre", "dynamicWorkspaceRecommendation": "Ez a kiegészítő lehet, hogy érdekelni fogja, mert népszerű a(z) {0} forráskódtár felhasználói körében.", "exeBasedRecommendation": "Ez a kiegészítő azért ajánlott, mert a következő telepítve van: {0}.", "fileBasedRecommendation": "Ez a kiegészítő a közelmúltban megnyitott fájlok alapján ajánlott.", "workspaceRecommendation": "Ez a kiegészítő az aktuális munkaterület felhasználói által ajánlott.", "reallyRecommended2": "Ehhez a fájltípushoz a(z) '{0}' kiegészítő ajánlott.", "reallyRecommendedExtensionPack": "Ehhez a fájltípushoz a(z) '{0}' kiegészítőcsomag ajánlott.", - "showRecommendations": "Ajánlatok megjelenítése", "install": "Telepítés", + "showRecommendations": "Ajánlatok megjelenítése", "showLanguageExtensions": "A piactéren található olyan kiegészítő, ami segíthet a(z) '.{0}' fájloknál", "workspaceRecommended": "A munkaterülethez vannak javasolt kiegészítők", "installAll": "Összes telepítése", diff --git a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index 05c523e85e..1026880da8 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Letiltja a többi billentyűkonfigurációt ({0}) a billentyűparancsok közötti konfliktusok megelőzése érdekében?", "yes": "Igen", - "no": "Nem", - "betterMergeDisabled": "A Better Merge kiegészítő most már be van építve. A telepített kiegészítő le lett tiltva és eltávolítható.", - "uninstall": "Eltávolítás" + "no": "Nem" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index be44805602..9ef43ba7e5 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -12,7 +12,9 @@ "recommendedExtensions": "Ajánlott", "otherRecommendedExtensions": "További ajánlatok", "workspaceRecommendedExtensions": "Ajánlott a munkaterülethez", - "builtInExtensions": "Beépített", + "builtInExtensions": "Funkciók", + "builtInThemesExtensions": "Témák", + "builtInBasicsExtensions": "Programozási nyelvek", "searchExtensions": "Kiegészítők keresése a piactéren", "sort by installs": "Rendezés a telepítések száma szerint", "sort by rating": "Rendezés értékelés szerint", diff --git a/i18n/hun/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index e806b3281d..ed735f3713 100644 --- a/i18n/hun/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Szövegfájlszerkesztő", "createFile": "Fájl létrehozása", + "relaunchWithIncreasedMemoryLimit": "Újraindítás {0} MB-tal", + "configureMemoryLimit": "Memóriakorlát beállítása", "fileEditorWithInputAriaLabel": "{0}. Szövegfájlszerkesztő.", "fileEditorAriaLabel": "Szövegfájlszerkesztő" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 72867c8d4a..77357bf5a2 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Másolás", "pasteFile": "Beillesztés", "retry": "Újrapróbálkozás", + "renameWhenSourcePathIsParentOfTargetError": "Létező mappában az „Új mappa” vagy „Új fájl” parancsokkal hozhat lére új elemeket.", "newUntitledFile": "Új, névtelen fájl", "createNewFile": "Új fájl", "createNewFolder": "Új mappa", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Törölni készül egy olyan mappát, melyben {0} nem mentett változtatásokat tartalmazó fájl van. Folytatja?", "dirtyMessageFileDelete": "Törölni készül egy olyan fájlt, amely nem mentett változtatásokat tartalmaz. Folytatja?", "dirtyWarning": "A módosítások elvesznek, ha nem menti őket.", - "confirmMoveTrashMessageMultiple": "Törli a következő {0} fájlt?", - "confirmMoveTrashMessageFolder": "Törli a(z) '{0}' nevű mappát és a teljes tartalmát?", - "confirmMoveTrashMessageFile": "Törli a(z) '{0}' nevű fájlt?", "undoBin": "Helyreállíthatja a lomtárból.", "undoTrash": "Helyreállíthatja a kukából.", "doNotAskAgain": "Ne kérdezze meg újra", + "irreversible": "A művelet nem vonható vissza!", + "binFailed": "Nem sikerült törölni a lomtár használatával. Szeretné helyette véglegesen törölni?", + "trashFailed": "Nem sikerült törölni a kuka használatával. Szeretné helyette véglegesen törölni?", + "deletePermanentlyButtonLabel": "&&Törlés véglegesen", + "retryButtonLabel": "Új&&rapróbálkozás", + "confirmMoveTrashMessageFilesAndDirectories": "Törli a következő {0} fájlt vagy könyvtárat a teljes tartalmával együtt?", + "confirmMoveTrashMessageMultipleDirectories": "Törli a következő {0} könyvtárat a teljes tartalmával együtt?", + "confirmMoveTrashMessageMultiple": "Törli a következő {0} fájlt?", + "confirmMoveTrashMessageFolder": "Törli a(z) '{0}' nevű mappát és a teljes tartalmát?", + "confirmMoveTrashMessageFile": "Törli a(z) '{0}' nevű fájlt?", + "confirmDeleteMessageFilesAndDirectories": "Véglegesen törli a következő {0} fájlt vagy könyvtárat a teljes tartalmával együtt?", + "confirmDeleteMessageMultipleDirectories": "Véglegesen törli a következő {0} könyvtárat a teljes tartalmával együtt?", "confirmDeleteMessageMultiple": "Véglegesen törli a következő {0} fájlt?", "confirmDeleteMessageFolder": "Törli a(z) '{0}' nevű mappát és annak teljes tartalmát? ", "confirmDeleteMessageFile": "Véglegesen törli a(z) '{0}' nevű fájlt?", - "irreversible": "A művelet nem vonható vissza!", - "cancel": "Mégse", - "permDelete": "Végleges törlés", - "importFiles": "Fájlok importálása", + "addFiles": "Fájlok hozzáadása", "confirmOverwrite": "A célmappában már van ilyen nevű mappa vagy fájl. Le szeretné cserélni?", "replaceButtonLabel": "&&Csere", "fileIsAncestor": "A beillesztendő fájl a célmappa szülője", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Fájl új ablakban történő megnyitásához először nyisson meg egy fájlt", "copyPath": "Elérési út másolása", "emptyFileNameError": "Meg kell adni egy fájl vagy mappa nevét.", + "fileNameStartsWithSlashError": "A fájlok és mappák neve nem kezdődhet perjellel.", "fileNameExistsError": "Már létezik **{0}** nevű fájl vagy mappa ezen a helyszínen. Adjon meg egy másik nevet!", + "fileUsedAsFolderError": "A(z) **{0}** egy fájl, és nem rendelkezhet alelemekkel.", "invalidFileNameError": "A(z) **{0}** név nem érvényes fájl- vagy mappanév. Adjon meg egy másik nevet!", "filePathTooLongError": "A(z) **{0}** név egy olyan elérési utat eredményez, ami túl hosszú. Adjon meg egy másik nevet!", "compareWithClipboard": "Aktív fájl összehasonlítása a vágólap tartalmával", diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 29943643be..0c671b7b81 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Meghatározza, hogy a nem mentett fájlokra emlékezzen-e az alkalmazás a munkamenetek között, így ki lehet hagyni a mentéssel kapcsolatos felugró ablakokat kilépésnél.", "useExperimentalFileWatcher": "Új, kísérleti fájlfigyelő használata.", "defaultLanguage": "Az új fájlokhoz alapértelmezetten hozzárendelt nyelv.", + "maxMemoryForLargeFilesMB": "Meghatározza a VS Code számára elérhető memória mennyiségét újraindítás után, nagy fájlok megnyitása esetén. Hatása ugyanaz, mint a --max-memory=ÚJMÉRET kapcsoló megadása parancssorból való indítás esetén.", "editorConfigurationTitle": "Szerkesztőablak", "formatOnSave": "Fájlok formázása mentéskor. Az adott nyelvhez rendelkezésre kell állni formázónak, nem lehet beállítva automatikus mentés, és a szerkesztő nem állhat éppen lefelé.", + "formatOnSaveTimeout": "Időkorlát mentéskor végzett formázások esetén. Meghatároz egy időkorlátot ezredmásodpercben a formatOnSave-parancsok számára. Az ennél hosszabb ideig tartó parancsok meg lesznek szakítva.", "explorerConfigurationTitle": "Fájlkezelő", "openEditorsVisible": "A megnyitott szerkesztőablakok panelen megjelenített szerkesztőablakok száma.", "autoReveal": "Meghatározza, hogy a fájlkezelőben automatikusan fel legyenek fedve és ki legyenek jelölve a fájlok, amikor megnyitják őket.", diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 66e3d4f231..d6b9c1e3bb 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -7,13 +7,17 @@ "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Adja meg a fájl nevét. Nyomjon 'Enter'-t a megerősítéshez vagy 'Escape'-et a megszakításhoz.", - "constructedPath": "{0} létrehozása a következő helyen: **{1}**", + "createFileFromExplorerInfoMessage": "**{0}** fájl létrehozva a következő helyen: **{1}**", + "renameFileFromExplorerInfoMessage": "Áthelyezés és átnevezés a következőre: **{0}**", + "createFolderFromExplorerInfoMessage": "**{0}** mappa létrehozása a következő helyen: **{1}**", "filesExplorerViewerAriaLabel": "{0}, Fájlkezelő", "dropFolders": "Szeretné hozzáadni a mappákat a munkaterülethez?", "dropFolder": "Szeretné hozzáadni a mappát a munkaterülethez?", "addFolders": "Mappák hozzá&&adása", "addFolder": "Mappa hozzá&&adása", + "confirmRootsMove": "Szeretné módosítani több gyökérmappa sorrendjét a munkaterületen belül?", "confirmMultiMove": "Át szeretné helyezni a következő {0} fájlt?", + "confirmRootMove": "Szeretné módosítani a(z) '{0}' gyökérmappa sorrendjét a munkaterületen belül?", "confirmMove": "Át szeretné helyezni a(z) '{0}' nevű fájlt?", "doNotAskAgain": "Ne kérdezze meg újra", "moveButtonLabel": "&&Áthelyezés", diff --git a/i18n/hun/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..c2a0ca800e --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "HTML-előnézet" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/hun/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..d5c321fd60 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Érvénytelen bemenet a szerkesztőablakból." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..6f1887b847 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Fejlesztői" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/hun/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..89f213109c --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview-fejlesztőeszközök megnyitása", + "refreshWebviewLabel": "Webview-k újratöltése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index c5c9b1ee12..6a0fe09247 100644 --- a/i18n/hun/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Szeretné a VS Code felületét {0} nyelvűre állítani és újraindítani az alkalmazást?", + "yes": "Igen", + "no": "Nem", + "neverAgain": "Ne jelenítse meg újra", "JsonSchema.locale": "A felhasználói felületen használt nyelv.", "vscode.extension.contributes.localizations": "Lokalizációkat szolgáltat a szerkesztőhöz", "vscode.extension.contributes.localizations.languageId": "Annak a nyelvnek az azonosítója, amelyre a megjelenített szövegek fordítva vannak.", diff --git a/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..fbc4f5faee --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Szeretné a VS Code felületét {0} nyelvűre állítani és újraindítani az alkalmazást?", + "yes": "Igen", + "no": "Nem", + "neverAgain": "Ne jelenítse meg újra", + "install": "Telepítés", + "more information": "További információ...", + "JsonSchema.locale": "A felhasználói felületen használt nyelv.", + "vscode.extension.contributes.localizations": "Lokalizációkat szolgáltat a szerkesztőhöz", + "vscode.extension.contributes.localizations.languageId": "Annak a nyelvnek az azonosítója, amelyre a megjelenített szövegek fordítva vannak.", + "vscode.extension.contributes.localizations.languageName": "A nyelv neve angolul.", + "vscode.extension.contributes.localizations.languageNameLocalized": "A nyelv neve a szolgáltatott nyelven.", + "vscode.extension.contributes.localizations.translations": "A nyelvhez rendelt fordítások listája.", + "vscode.extension.contributes.localizations.translations.id": "Azonosító, ami a VS Code-ra vagy arra a kiegészítőre hivatkozik, amihez a fordítás szolgáltatva van. A VS Code azonosítója mindig `vscode`, kiegészítők esetén pedig a `publisherId.extensionName` formátumban kell megadni.", + "vscode.extension.contributes.localizations.translations.id.pattern": "Az id értéke VS Code fordítása esetében `vscode`, egy kiegészítő esetében pedig `publisherId.extensionName` formátumú lehet.", + "vscode.extension.contributes.localizations.translations.path": "A nyelvhez tartozó fordításokat tartalmazó fájl relatív elérési útja." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..8181e5ce9e --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Nyelv beállítása", + "displayLanguage": "Meghatározza a VSCode felületének nyelvét.", + "doc": "Az elérhető nyelvek listája a következő címen tekinthető meg: {0}", + "restart": "Az érték módosítása után újra kell indítani a VSCode-ot.", + "fail.createSettings": "Nem sikerült a(z) '{0}' létrehozás ({1})." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..08d7b8601c --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Másolás", + "copyMessage": "Üzenet másolása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..9cc6717e0d --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Összesen {0} probléma" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..e26c8c27c9 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Problémák", + "tooltip.1": "A fájlban 1 probléma található", + "tooltip.N": "A fájlban {0} probléma található", + "markers.showOnFile": "Fájlokban és mappákban található hibák és figyelmeztetések megjelenítése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..b058dcf407 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Fájlkizárási beállítások kikapcsolása", + "clearFilter": "Szűrő törlése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..9b95cf1be7 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "{0} megjelenítve (összesen: {1})" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..e2f7dbb8ae --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Nézet", + "problems.view.toggle.label": "Problémák be- és kikapcsolása (hiba, figyelmeztetés, információ)", + "problems.view.focus.label": "Váltás a problémákra (hiba, figyelmeztetés, információ)", + "problems.panel.configuration.title": "Problémák-nézet", + "problems.panel.configuration.autoreveal": "Meghatározza, hogy a problémák nézet automatikusan felfedje-e a fájlokat, amikor megnyitja őket.", + "markers.panel.title.problems": "Problémák", + "markers.panel.aria.label.problems.tree": "Problémák fájlonként csoportosítva", + "markers.panel.no.problems.build": "A munkaterületen eddig egyetlen hiba sem lett érzékelve.", + "markers.panel.no.problems.filters": "A megadott szűrőfeltételeknek egyetlen elem sem felel meg.", + "markers.panel.no.problems.file.exclusions": "Az összes probléma el van rejtve, mert a fájlkizárási szűrő engedélyezve van.", + "markers.panel.action.useFilesExclude": "Fájlkizárási beállítások használata", + "markers.panel.action.donotUseFilesExclude": " Ne legyenek használva a fájlkizárási beállítások", + "markers.panel.action.filter": "Problémák szűrése", + "markers.panel.filter.ariaLabel": "Problémák szűrése", + "markers.panel.filter.placeholder": "Szűrő, pl.: szöveg, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "hibák", + "markers.panel.filter.warnings": "figyelmeztetések", + "markers.panel.filter.infos": "információk", + "markers.panel.single.error.label": "1 hiba", + "markers.panel.multiple.errors.label": "{0} hiba", + "markers.panel.single.warning.label": "1 figyelmeztetés", + "markers.panel.multiple.warnings.label": "{0} figyelmeztetés", + "markers.panel.single.info.label": "1 információ", + "markers.panel.multiple.infos.label": "{0} információ", + "markers.panel.single.unknown.label": "1 ismeretlen", + "markers.panel.multiple.unknowns.label": "{0} ismeretlen", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} {1} problémával", + "problems.tree.aria.label.marker.relatedInformation": "Ez a probléma {0} helyre hivatkozik.", + "problems.tree.aria.label.error.marker": "{0} által generált hiba: {1}, sor: {2}, oszlop: {3}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Hiba: {0}, sor: {1}, oszlop: {2}.{3}", + "problems.tree.aria.label.warning.marker": "{0} által generált figyelmeztetés: {1}, sor: {2}, oszlop: {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Figyelmeztetés: {0}, sor: {1}, oszlop: {2}.{3}", + "problems.tree.aria.label.info.marker": "{0} által generált információ: {1}, sor: {2}, oszlop: {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Információ: {0}, sor: {1}, oszlop: {2}.{3}", + "problems.tree.aria.label.marker": "{0} által generált probléma: {1}, sor: {2}, oszlop: {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Probléma: {0}, sor: {1}, oszlop: {2}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{0}, sor: {1}, oszlop: {2}, a következő helyen: {3}", + "errors.warnings.show.label": "Hibák és figyelmezetések megjelenítése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/hun/src/vs/workbench/parts/output/browser/outputActions.i18n.json index 7f027f2e3e..0aaecfe64d 100644 --- a/i18n/hun/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Kimenet be- és kikapcsolása", "clearOutput": "Kimenet törlése", "toggleOutputScrollLock": "Kimenet görgetési zárának be- és kikapcsolása", - "switchToOutput.label": "Váltás a kimenetre" + "switchToOutput.label": "Váltás a kimenetre", + "openInLogViewer": "Naplófájl megnyitása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 6945a11eaa..5f3eb4a941 100644 --- a/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Kimenet", "logViewer": "Naplófájl-megjelenítő", "viewCategory": "Nézet", - "clearOutput.label": "Kimenet törlése" + "clearOutput.label": "Kimenet törlése", + "openActiveLogOutputFile": "Nézet: Aktív napló kimeneti fájljának megnyitása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 994e662994..9492b545f0 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Billentyűparancsok", + "showDefaultKeybindings": "Alapértelmezett billentyűparancsok megjelenítése", + "showUserKeybindings": "Felhasználói billentyűparancsok megjelenítése", "SearchKeybindings.AriaLabel": "Billentyűparancsok keresése", "SearchKeybindings.Placeholder": "Billentyűparancsok keresése", "sortByPrecedene": "Rendezés precedencia szerint", diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 6648b46170..e1ac486072 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Nyers alapértelmezett beállítások megnyitása", + "openSettings": "Beállítások megnyitása", "openGlobalSettings": "Felhasználói beállítások megnyitása", "openGlobalKeybindings": "Billentyűparancsok megnyitása", "openGlobalKeybindingsFile": "Billentyűparancsfájl megnyitása", diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index fbded0ae9a..f3c8a253e9 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Alapértelmezett beállítások", "SearchSettingsWidget.AriaLabel": "Beállítások keresése", "SearchSettingsWidget.Placeholder": "Beállítások keresése", "noSettingsFound": "Nincs eredmény", @@ -16,6 +15,8 @@ "nlpResult": "Természetes nyelvi keresés eredményei", "filterResult": "Szűrt találatok", "defaultSettings": "Alapértelmezett beállítások", + "defaultUserSettings": "Alapértelmezett felhasználói beállítások", + "defaultWorkspaceSettings": "Alapértelmezett munkaterületi beállítások", "defaultFolderSettings": "Alapértelmezett mappabeállítások", "defaultEditorReadonly": "A jobb oldalon lévő szerkesztőablak tartalmának módosításával írhatja felül az alapértelmezett beállításokat.", "preferencesAriaLabel": "Az alapértelmezett beállítások. Írásvédett szerkesztőablak." diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index c7095560ef..6d971ed2db 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "\"{0}\" kiegészítő megjelenítése", "editTtile": "Szerkesztés", "replaceDefaultValue": "Csere a beállításokban", - "copyDefaultValue": "Másolás a beállításokba", - "unsupportedPHPExecutablePathSetting": "Ez a beállítás csak a felhasználói beállításokban szerepelhet. A PHP munkaterülethez történő konfigurálásához nyisson meg egy PHP-fájlt, majd kattintson a PHP-elérési útra az állapotsoron!", - "unsupportedWorkspaceSetting": "Ez a beállítás csak a felhasználói beállításokban szerepelhet.", - "unsupportedWorkbenchSetting": "Ez a beállítás jelenleg nem alkalmazható. Akkor van használatban, ha közvetlenül nyitja meg ezt a mappát.", - "unsupportedWorkbenchSettingDevMode": "Ez a beállítás jelenleg nem alkalmazható. Akkor van használatban, ha a hatóköre 'resource'-ként van megadva a regisztráció során vagy közvetlenül nyitja meg ezt a mappát." + "copyDefaultValue": "Másolás a beállításokba" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json b/i18n/hun/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json index f9a5073399..be342667db 100644 --- a/i18n/hun/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "gotoLine": "Sor megkeresése...", - "gotoLineLabelEmptyWithLimit": "A keresett sor 1 és {0} közötti sorszáma", - "gotoLineLabelEmpty": "A keresett sor száma", + "gotoLineLabelEmptyWithLimit": "Adja meg a keresett sor számát 1 és {0} között!", + "gotoLineLabelEmpty": "Adja meg a keresett sor számát!", "gotoLineColumnLabel": "Ugrás a(z) {0}. sor {1}. oszlopára", "gotoLineLabel": "Sor megkeresése {0}", "gotoLineHandlerAriaLabel": "Adja meg a keresett sor számát!", diff --git a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 1ef246cb98..620271b1d4 100644 --- a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "További verziókezelő rendszerek telepítése...", "no open repo": "Nincs aktív verziókezelő rendszer.", "source control": "Verziókezelő rendszer", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Elrejtés" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 2efd044e45..b85c223ebb 100644 --- a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Előző kizáró keresési minta megjelenítése", "nextSearchTerm": "Következő keresőkifejezés megjelenítése", "previousSearchTerm": "Előző keresőkifejezés megjelenítése", - "showSearchViewlet": "Keresés megjelenítése", "findInFiles": "Keresés a fájlokban", "replaceInFiles": "Csere a fájlokban", "RefreshAction.label": "Frissítés", diff --git a/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 6aff638867..d9c23b4c9e 100644 --- a/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,22 +2,27 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Keresés", + "copyMatchLabel": "Másolás", + "copyPathLabel": "Elérési út másolása", + "copyAllLabel": "Összes másolása", + "clearSearchHistoryLabel": "Keresési előzmények törlése", + "toggleSearchViewPositionLabel": "Keresőnézet helyzetének váltása", "findInFolder": "Keresés mappában...", "findInWorkspace": "Keresés a munkaterületen...", "showTriggerActions": "Szimbólum megkeresése a munkaterületen...", "name": "Keresés", - "search": "Keresés", "showSearchViewl": "Keresés megjelenítése", "view": "Nézet", "findInFiles": "Keresés a fájlokban", "openAnythingHandlerDescription": "Fájl megkeresése", "openSymbolDescriptionNormal": "Szimbólum megkeresése a munkaterületen", "searchConfigurationTitle": "Keresés", - "exclude": "Globális minták konfigurálása fájlok és mappák keresésből való kizárásához. Örökli az összes globális mintát a fliex.exclude beállításból.", + "exclude": "Fájlok és mappák keresésből való kizárására szolgáló globális minták. Örökli az összes globális mintát a fliex.exclude beállításból.", "exclude.boolean": "A globális minta, amire illesztve lesznek a fájlok elérési útjai. A minta engedélyezéséhez vagy letiltásához állítsa igaz vagy hamis értékre.", "exclude.when": "További ellenőrzés elvégzése az illeszkedő fájlok testvérein. Az illeszkedő fájl nevéhez használja a $(basename) változót!", "useRipgrep": "Meghatározza, hogy a szövegben és fájlokban való kereséshez a ripgrep van-e használva.", @@ -26,5 +31,5 @@ "search.followSymlinks": "Meghatározza, hogy keresés során követve legyenek-e a szimbolikus linkek.", "search.smartCase": "Figyelmen kívül hagyja a kis- és nagybetűket, ha a minta csak kisbetűkből áll, ellenkező esetben kis- és nagybetűérzékenyen keres", "search.globalFindClipboard": "Meghatározza, hogy a keresőmodul olvassa és módosítsa-e a megosztott keresési vágólapot macOS-en.", - "search.location": "Előzetes funkció: meghatározza, hogy a keresés az oldalsávon jelenik meg vagy egy panelként a panelterületen, mely utóbbi esetén több hely van vízszintesen. A következő kiadásban a panel megjelenése optimalizálva lesz a vízszintes megjelenítéshez, és a funkció nem lesz előzetes." + "search.location": "Meghatározza, hogy a keresés az oldalsávon jelenik meg vagy egy panelként a panelterületen, mely utóbbi esetén több hely van vízszintesen. A következő kiadásban a panel megjelenése optimalizálva lesz a vízszintes megjelenítéshez, és a funkció nem lesz előzetes." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 241eef0c42..4fb8b809e4 100644 --- a/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Segítsen javítani a {0}-támogatásunkat", "takeShortSurvey": "Rövid felmérés kitöltése", "remindLater": "Emlékeztessen később", - "neverAgain": "Ne jelenítse meg újra", - "helpUs": "Segítsen javítani a {0}-támogatásunkat" + "neverAgain": "Ne jelenítse meg újra" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 1402b8f422..2cef771fe6 100644 --- a/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Lenne kedve egy gyors elégedettségi felméréshez?", "takeSurvey": "Felmérés kitöltése", "remindLater": "Emlékeztessen később", - "neverAgain": "Ne jelenítse meg újra", - "surveyQuestion": "Lenne kedve egy gyors elégedettségi felméréshez?" + "neverAgain": "Ne jelenítse meg újra" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 1a69b728cf..c0a0fc7b31 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Egy problémaminta vagy egy szolgáltatott vagy elődefiniált problémaminta neve. Elhagyható, ha az alapként használandó minta meg van adva.", "ProblemMatcherSchema.base": "A alapként használni kívánt problémaillesztő neve.", "ProblemMatcherSchema.owner": "A probléma tulajdonosa a Code-on belül. Elhagyható, ha az alapként használt minta meg van adva. Alapértelmezett értéke 'external', ha nem létezik és az alapként használt minta nincs meghatározva.", + "ProblemMatcherSchema.source": "A diagnosztika forrásának emberek számára szánt leírása, pl. 'typescript' vagy 'super lint'.", "ProblemMatcherSchema.severity": "Az elkapott problémák alapértelmezett súlyossága. Ez az érték van használva, ha a minta nem definiál illesztési csoportot a súlyossághoz.", "ProblemMatcherSchema.applyTo": "Meghatározza, hogy a szöveges dokumentumhoz jelentett probléma megnyitott, bezárt vagy minden dokumentumra legyen alkalmazva.", "ProblemMatcherSchema.fileLocation": "Meghatározza, hogy a problémamintában talált fájlnevek hogyan legyenek értelmezve.", diff --git a/i18n/hun/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 19d5d90558..cab1d82464 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "A feladat konkrét típusa", + "TaskDefinition.description": "A feladat tényleges típusa. Megjegyzés: a „$” karakterrel kezdődő feladattípusok belső használatra vannak fenntartva.", "TaskDefinition.properties": "A feladattípus további tulajdonságai", "TaskTypeConfiguration.noType": "A feladattípus-konfigurációból hiányzik a kötelező 'taskType' tulajdonság", "TaskDefinitionExtPoint": "Feladattípusokat szolgáltat" diff --git a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 16ae4e112e..f098beb323 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "A feladatot egyetlen csoporthoz sem rendeli", "JsonSchema.tasks.group": "Meghatározza a feladat végrehajtási csoportját. A \"build\" esetén a buildelési csoportba, a \"test\" esetén a tesztelési csoportba kerül bele a feladat.", "JsonSchema.tasks.type": "Meghatározza, hogy a feladat folyamatként van-e végrehajtva vagy egy parancsként a shellben.", + "JsonSchema.command.quotedString.value": "A parancs tényleges értéke", + "JsonSchema.tasks.quoting.escape": "A karaktereket a shell saját feloldókarakterével oldja fel (pl. PowerShell alatt a `, míg bash alatt a \\ karakterrel).", + "JsonSchema.tasks.quoting.strong": "Az argumentumot a shell erős idézőjel-karakterével veszi körül (pl. PowerShell és bash alatt a \" karakterrel). ", + "JsonSchema.tasks.quoting.weak": "Az argumentumot a shell erős idézőjel-karakterével veszi körül (pl. PowerShell és bash alatt a ' karakterrel). ", + "JsonSchema.command.quotesString.quote": "Hogyan legyen idézőjelezve a parancs értéke.", + "JsonSchema.command": "A végrehajtandó parancs. Lehet egy külső parancs vagy egy rendszerparancs.", + "JsonSchema.args.quotedString.value": "Az argumentum tényleges értéke", + "JsonSchema.args.quotesString.quote": "Hogyan legyen idézőjelezve az argumentum értéke.", + "JsonSchema.tasks.args": "A parancs meghívásakor átadott argumentumok.", "JsonSchema.tasks.label": "A feladat felhasználói felületen megjelenő neve", "JsonSchema.version": "A konfiguráció verziószáma", "JsonSchema.tasks.identifier": "A feladat felhasználó által definiált azonosítója, amivel hivatkozni lehet a feladatra a lauch.json-ban vagy egy dependsOn-utasításban.", diff --git a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index a117e38ddf..ba393fa7d5 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -8,9 +8,12 @@ ], "tasksCategory": "Feladatok", "ConfigureTaskRunnerAction.label": "Feladat beállítása", + "totalErrors": "{0} hiba", + "totalWarnings": "{0} figyelmeztetés", + "totalInfos": "{0} információ", "problems": "Problémák", "building": "Buildelés...", - "manyMarkers": "99+", + "manyProblems": "10k+", "runningTasks": "Futó feladatok megjelenítése", "tasks": "Feladatok", "TaskSystem.noHotSwap": "A feladatvégrehajtó motor megváltoztatása egy futó, aktív feladat esetén az ablak újraindítását igényli.", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Válassza ki, milyen típusú hibák és figyelmeztetések legyenek keresve a feladat kimenetében!", "customizeParseErrors": "A jelenlegi feladatkonfigurációban hibák vannak. Feladat egyedivé tétele előtt javítsa a hibákat!", "moreThanOneBuildTask": "Túl sok buildelési feladat van definiálva a tasks.json-ban. Az első lesz végrehajtva.\n", - "TaskSystem.activeSame.background": "A(z) '{0}' feladat már aktív és a háttérben fut. A feladat befejezéséhez használja az 'Feladat megszakítása...' parancsot a Feladatok menüből!", - "TaskSystem.activeSame.noBackground": "A(z) '{0}' feladat már aktív. A feladat befejezéséhez használja 'Feladat megszakítása' parancsot a Feladatok menüből!", + "TaskSystem.activeSame.background": "A(z) '{0}' azonosítójú feladat már aktiválva van és a háttérben fut.", + "TaskSystem.activeSame.noBackground": "A(z) '{0}' azonosítójú feladat már aktiválva van.", + "terminateTask": "Feladat megszakítása", + "restartTask": "Feladat újraindítása", "TaskSystem.active": "Már fut egy feladat. Szakítsa meg, mielőtt egy másik feladatot futtatna.", "TaskSystem.restartFailed": "Nem sikerült a(z) {0} feladat befejezése és újraindítása.", "TaskService.noConfiguration": "Hiba: a(z) {0} feladatok felderítése nem szolgáltatott feladatot a következő konfigurációhoz:\n{1}\nA feladat figyelmen kívül lesz hagyva.\n", diff --git a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 53815265fe..ac12f205e1 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Feladat – {0}", "closeTerminal": "A folytatáshoz nyomjon meg egy billentyűt.", "reuseTerminal": "A terminál újra lesz hasznosítva a feladatok által. Nyomjon meg egy billentyűt a bezáráshoz.", - "TerminalTaskSystem": "Rendszerparancsok nem hajthatók végre UNC-meghajtókon.", + "TerminalTaskSystem": "Rendszerparancsok nem hajthatók végre UNC-meghajtókon a cmd.exe használata esetén.", "unkownProblemMatcher": "A(z) {0} problémaillesztő nem található. Az illesztő figyelmen kívül lesz hagyva." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/hun/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 372cc8f41c..f9c57c827a 100644 --- a/i18n/hun/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Figyelmeztetés: az options.cwd értékének string típusúnak kell lennie. A következő érték figyelmen kívül van hagyva: {0}.", + "ConfigurationParser.inValidArg": "Hiba: a parancssori argumentum egy string vagy egy idézőjeles string lehet. A megadott érték:\n{0}", "ConfigurationParser.noargs": "Hiba: a parancssori argumentumokat string típusú tömbként kell megadni. A megadott érték:\n{0}", "ConfigurationParser.noShell": "Figyelmeztetés: a shellkonfiguráció csak akkor támogatott, ha a feladat a terminálban van végrehajtva.", "ConfigurationParser.noName": "Hiba: a deklarációs hatókörben lévő problémailleszőnek kötelező nevet adni:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Hiba: a(z) '{0}' feladatkonfigurációból hiányzik a kötelező '{1}' tulajdonság. A feladatkonfiguráció figyelmen kívül lesz hagyva.", "ConfigurationParser.notCustom": "Hiba: a feladat nem egyedi feladatként van definiálva. A konfiguráció figyelmen kívül lesz hagyva.\n{0}\n", "ConfigurationParser.noTaskName": "Hiba: a feladatnak rendelkeznie kell adni taskName tulajdonsággal. A feladat figyelmen kívül lesz hagyva.\n{0}\n", - "taskConfiguration.shellArgs": "Figyelmeztetés: a(z) '{0}' feladat egy rendszerparancs, és az argumentumok egyikében escape-elés nélküli szóköz található. A megfelelő idézőjelezés érdekében olvassza bele az argumentumokat a parancsba.", "taskConfiguration.noCommandOrDependsOn": "Hiba: a(z) '{0}' feladat nem ad meg parancsot, és nem definiálja a dependsOn tulajdonságot sem. A feladat figyelmen kívül lesz hagyva. A definíciója:\n{1}", "taskConfiguration.noCommand": "Hiba: a(z) '{0}' feladathoz nincs definiálva a parancs. A feladat figyelmen kívül lesz hagyva. A definíciója:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "A feladatok 2.0.0-s verziója nem támogatja a globális, operációs rendszer-specifikus feladatokat. Alakítsa át őket operációs rendszer-specifikus parancsot tartalmazó feladattá. Az érintett feladatok:\n{0}" diff --git a/i18n/hun/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..e68d779116 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "A terminál háttérszíne. Ez lehetővé teszi a terminál paneltől eltérő színezését.", + "terminal.foreground": "A terminál előtérszíne.", + "terminalCursor.foreground": "A terminál kurzorának előtérszíne.", + "terminalCursor.background": "A terminál kurzorának háttérszíne. Lehetővé teszik az olyan karakterek színének módosítását, amelyek fölött egy blokk-típusú kurzor áll.", + "terminal.selectionBackground": "A terminálban kijelölt tartalom háttérszíne.", + "terminal.border": "A terminálokat elválasztó keret színe. Alapértelmezett értéke megegyezik a panel.border értékével.", + "terminal.ansiColor": "'{0}' ANSI-szín a terminálban." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index ff59b669ee..e7e3af2a8e 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -28,7 +28,7 @@ "terminal.integrated.setLocaleVariables": "Meghatározza, hogy a lokálváltozók be vannak-e állítva a terminál indításánál. Alapértelmezett értéke igaz OS X-en, hamis más platformokon.", "terminal.integrated.rightClickBehavior": "Meghatározza, hogy a terminál hogyan reagál a jobb kattintásra. Lehetséges értékek: 'default', 'copyPaste' és 'selectWord'. 'default' esetén megjelenik a helyi menü, 'copyPaste' esetén másolja a kijelölt szöveget, ha van, egyébként beilleszt, 'selectWord' esetén pedig kijelöli a kurzor alatti szót és megjeleníti a helyi menüt.", "terminal.integrated.cwd": "Explicit elérési út, ahol a terminál indítva lesz. Ez a shellfolyamat munkakönyvtára (cwd) lesz. Ez a beállítás nagyon hasznos olyan munkaterületeken, ahol a gyökérkönyvtár nem felel meg munkakönyvtárnak.", - "terminal.integrated.confirmOnExit": "Meghatározza, hogy megerősítést kér-e az alkalamzás, ha van aktív terminál-munkafolyamat.", + "terminal.integrated.confirmOnExit": "Az alkalmazás kérjen-e megerősítést kilépéskor, ha van aktív terminál-munkafolyamat.", "terminal.integrated.enableBell": "Meghatározza, hogy engedélyezve van-e a csengő a terminálba.", "terminal.integrated.commandsToSkipShell": "Olyan parancsazonosítók listája, melyek nem lesznek elküldve a shellnek, és ehelyett mindig a Code kezeli le őket. Ez lehetővé teszi, hogy az olyan billentyűparancsok, melyeket normál esetben a shell dolgozna fel, ugyanúgy működjenek, mint mikor a terminálon nincs fókusz. Például ilyen a gyorsmegnyitás indításához használt Ctrl+P.", "terminal.integrated.env.osx": "A VS Code folyamatához hozzáadott környezeti változókat tartalmazó objektum, amit az OS X-es terminál használ.", diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 2a7eb681b9..96b8edc4ec 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "Az aktuális munkakönyvtár kiválasztása az új terminálhoz", "workbench.action.terminal.newInActiveWorkspace": "Új integrált terminál létrehozása (az aktív munkaterületen)", "workbench.action.terminal.split": "Terminál kettéosztása", + "workbench.action.terminal.splitInActiveWorkspace": "Terminál kettéosztása (az aktív munkaterületen)", "workbench.action.terminal.focusPreviousPane": "Váltás az előző panelra", "workbench.action.terminal.focusNextPane": "Ugrás a következő panelra", "workbench.action.terminal.resizePaneLeft": "Méret növelése balra", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "G9rgetés felfelé (oldalanként)", "workbench.action.terminal.scrollToTop": "Görgetés a tetejére", "workbench.action.terminal.clear": "Törlés", + "workbench.action.terminal.clearSelection": "Kijelölés megszüntetése", "workbench.action.terminal.allowWorkspaceShell": "Munkaterületspecifikus shellkonfiguráció engedélyezése", "workbench.action.terminal.disallowWorkspaceShell": "Munkaterületspecifikus shellkonfiguráció letiltása", "workbench.action.terminal.rename": "Átnevezés", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Keresőmodul elrejtése", "nextTerminalFindTerm": "Következő keresési kifejezés megjelenítése", "previousTerminalFindTerm": "Előző keresési kifejezés megjelenítése", - "quickOpenTerm": "Aktív terminál váltása" + "quickOpenTerm": "Aktív terminál váltása", + "workbench.action.terminal.scrollToPreviousCommand": "Görgetés az előző parancshoz", + "workbench.action.terminal.scrollToNextCommand": "Görgetés a következő parancshoz", + "workbench.action.terminal.selectToPreviousCommand": "Előző parancs kiválasztása", + "workbench.action.terminal.selectToNextCommand": "Következő parancs kiválasztása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index 64160127b4..4ad98c231e 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "A terminálban nincs semmi kijelölve a másoláshoz", "terminal.integrated.exitedWithCode": "A terminálfolyamat a következő kilépési kóddal állt le: {0}", "terminal.integrated.waitOnExit": "A folytatáshoz nyomjon meg egy billentyűt...", - "terminal.integrated.launchFailed": "A(z) '{0}{1}' terminálfolyamat-parancsot nem sikerült elindítani (kilépési kód: {2})" + "terminal.integrated.launchFailed": "A(z) '{0}{1}' terminálfolyamat-parancsot nem sikerült elindítani (kilépési kód: {2})", + "terminal.integrated.launchFailedExtHost": "A terminálfolyamat nem tudott elindulni (kilépési kód: {0})" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json index d43e93ec18..39bd7a36f5 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.i18n.json @@ -7,6 +7,6 @@ "Do not edit this file. It is machine generated." ], "terminalLinkHandler.followLinkAlt": "Hivatkozás megnyitása Alt + kattintás paranccsal", - "terminalLinkHandler.followLinkCmd": "Hivatkozott oldal megnyitása Cmd + kattintás paranccsal", + "terminalLinkHandler.followLinkCmd": "Hivatkozás megnyitása Cmd + kattintás paranccsal", "terminalLinkHandler.followLinkCtrl": "Hivatkozott oldal megnyitása Ctrl + kattintás paranccsal" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 8e0f93b53c..5d7d55ef4c 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "Másolás", + "split": "Kettéosztás", "paste": "Beillesztés", "selectAll": "Összes kijelölése", - "clear": "Törlés", - "split": "Kettéosztás" + "clear": "Törlés" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index a50f89d239..7feda6f68a 100644 --- a/i18n/hun/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "A munkaterület olyan beállításokat tartalmaz, amelyeket csak a felhasználói beállításoknál lehet megadni (({0}). További információhoz kattintson [ide]({1})!", "openWorkspaceSettings": "Munkaterület beállításainak megnyitása", - "dontShowAgain": "Ne jelenítse meg újra", - "unsupportedWorkspaceSettings": "A munkaterület olyan beállításokat tartalmaz, amelyeket csak a felhasználói beállításoknál lehet megadni (({0}). További információhoz kattintson [ide]({1})!" + "dontShowAgain": "Ne jelenítse meg újra" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..d682cbdfb4 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Kiadási jegyzék: {0}", + "unassigned": "nincs hozzárendelve" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 58d73a6469..ee15963391 100644 --- a/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Később", - "unassigned": "nincs hozzárendelve", "releaseNotes": "Kiadási jegyzék", "showReleaseNotes": "Kiadási jegyzék megjelenítése", "read the release notes": "Üdvözöljük a {0} v{1} verziójában. Szeretné megtekinteni a kiadási jegyzéket?", @@ -17,13 +15,14 @@ "updateIsReady": "Új {0}-frissítés érhető el.", "noUpdatesAvailable": "Jelenleg nincs elérhető frissítés.", "ok": "OK", - "download now": "Letöltés most", "thereIsUpdateAvailable": "Van elérhető frissítés.", - "installUpdate": "Frissítés telepítése", + "download now": "Letöltés most", + "later": "Később", "updateAvailable": "Frissítés érhető el: {0} {1}", + "installUpdate": "Frissítés telepítése", "updateInstalling": "{0} {1} a háttérben települ. Jelzünk, ha elkészült.", + "updateAvailableAfterRestart": "A {0} újraindításával telepíthető a legújabb frissítés.", "updateNow": "Frissítés most", - "updateAvailableAfterRestart": "A {0} frissül az újraindítás után.", "commandPalette": "Parancskatalógus...", "settings": "Beállítások", "keyboardShortcuts": "Billentyűparancsok", diff --git a/i18n/hun/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..4fc157d384 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "URL megnyitása", + "developer": "Fejlesztői" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..d027e8f442 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "webview-szerkesztő", + "developer": "Fejlesztői" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..89f213109c --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview-fejlesztőeszközök megnyitása", + "refreshWebviewLabel": "Webview-k újratöltése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/hun/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..37523ae01c --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Segítsen a VS Code tökéletesítésében azzal, hogy engedélyezi a Microsoft számára a használati adatok gyűjtését! Olvasssa el az [adatvédelmi nyilatkozatot]({0}), és tudja meg, hogyan [kapcsolhatja ki]({1}) ezt a funkciót.", + "telemetryOptOut.optInNotice": "Segítsen a VS Code tökéletesítésében azzal, hogy engedélyezi a Microsoft számára a használati adatok gyűjtését! Olvasssa el az [adatvédelmi nyilatkozatot]({0}), és tudja meg, hogyan [kapcsolhatja be]({1}) ezt a funkciót.", + "telemetryOptOut.readMore": "További információk" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/hun/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index b7fb937db3..6c0d4fe9dd 100644 --- a/i18n/hun/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Kiterjesztések kezelése", "welcomeOverlay.problems": "Hibák és figyelmeztetések megtekintése", "welcomeOverlay.commandPalette": "Összes parancs megkeresése és futtatása", + "welcomeOverlay.notifications": "Értesítések megjelenítése", "welcomeOverlay": "Felhasználói felület áttekintése", "hideWelcomeOverlay": "Felület áttekintésének elrejtése", "help": "Segítség" diff --git a/i18n/hun/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/hun/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 5f9fa71419..3e4cb51138 100644 --- a/i18n/hun/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Eszközök és nyelvek", "welcomePage.installExtensionPacksDescription": "{0} és {1} fejlesztőkörnyezetek telepítése ", "welcomePage.moreExtensions": "további", - "welcomePage.installKeymapDescription": "Billentyűparancsok telepítése", - "welcomePage.installKeymapExtension": "{0} és {1} billentyűparancsok telepítése ", + "welcomePage.installKeymapDescription": "Beállítások és billentyűkombinációk", + "welcomePage.installKeymapExtension": "{0} és {1} billentyűparancsok és beállítások telepítése ", "welcomePage.others": "további", "welcomePage.colorTheme": "Színtéma", "welcomePage.colorThemeDescription": "Alakítsa át szeretett szerkesztőjét úgy, ahogyan szeretné!", diff --git a/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 5454fc4c27..adfea92d29 100644 --- a/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/hun/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "A beállítások összefoglaló leírása. Ez a címke jelenik meg a beállítások fájlban egy különálló megjegyzésként.", "vscode.extension.contributes.configuration.properties": "A konfigurációs tulajdonságok leírása.", + "scope.application.description": "Alkalmazásspecifikus beállítás, ami csak a felhasználói beállításokban konfigurálható.", "scope.window.description": "Ablakspecifikus beállítás, ami konfigurálható a felhasználói vagy munkaterületi beállításokban.", "scope.resource.description": "Erőforrásspecifikus beállítás, ami beállítható a felhasználói, munkaterületi és mappaszintű beállításokban.", "scope.description": "A hatókör, amire a beállítás vonatkozik. Az elérhető hatókörök: `window` és `resource`.", diff --git a/i18n/hun/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/hun/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 7f76784fd3..a3641310e2 100644 --- a/i18n/hun/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Beállítások megnyitása", "saveAndRetry": "Mentés és újrapróbálkozás", "errorUnknownKey": "Nem sikerült írni a következőbe: {0}. A(z) {1} nem regisztrált beállítás.", + "errorInvalidWorkspaceConfigurationApplication": "Nem sikerült írni a munkaterület beállításaiba, mert ez a beállítás csak a felhasználói beállításokban használható. ", "errorInvalidFolderConfiguration": "Nem sikerült írni a mappa beállításaiba, mert a(z) {0} nem támogatott mappa típusú erőforrások hatókörében.", "errorInvalidUserTarget": "Nem sikerült írni a felhasználói beállításokba, mert a(z) {0} nem támogatott globális hatókörben.", "errorInvalidWorkspaceTarget": "Nem sikerült írni a munkaterület beállításaiba, mert a(z) {0} nem támogatott munkaterületi hatókörben egy több mappát tartalmazó munkaterületen.", diff --git a/i18n/hun/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/hun/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..e25641ff79 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Ez a beállítás csak a felhasználói beállításokban szerepelhet.", + "unsupportedWindowSetting": "Ez a beállítás jelenleg nem alkalmazható. Akkor van használatban, ha közvetlenül nyitja meg ezt a mappát." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/hun/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..4eade970e4 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "canNotResolveWorkspaceFolder": "A '${workspaceFolder}' értékét nem lehet feloldani. Nyisson meg egy mappát!", + "canNotResolveFolderBasename": "A '${workspaceFolderBasename}' értékét nem lehet feloldani. Nyisson meg egy mappát!" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/hun/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..978a6d116b --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "A(z) '{0}' értékét nem lehet feloldani, mert nincs megadva a környezeti változó neve.", + "configNotFound": "A(z) '{0}' értékét nem lehet feloldani, mert a(z) '{1}' beállítás nem található.", + "configNoString": "A(z) '{0}' értékét nem lehet feloldani, mert a(z) '{1}' strukturált értékkel rendelkezik.", + "missingConfigName": "A(z) '{0}' értékét nem lehet feloldani, mert nincs megadva a beállítás neve.", + "noValueForCommand": "A(z) '{0}' értékét nem lehet feloldani, mert a parancsnak nincs értéke.", + "canNotFindFolder": "A(z) '{0}' értékét nem lehet feloldani, mert nincs '{1}' nevű mappa.", + "canNotResolveWorkspaceFolderMultiRoot": "Az) '{0}' értékét nem lehet feloldani egy többmappás munkaterületen. Pontosítsa a változó hatókörét a : karakterrel és a mappa nevének megadásával!", + "canNotResolveWorkspaceFolder": "A(z) '{0}' értékét nem lehet feloldani. Nyisson meg egy mappát!", + "canNotResolveFile": "A(z) '{0}' értékét nem lehet feloldani. Nyisson meg egy szerkesztőablakot!", + "canNotResolveLineNumber": "A(z) '{0}' értékét nem lehet feloldani. Jelöljön ki egy sort az aktív szerkesztőablakban!", + "canNotResolveSelectedText": "A(z) '{0}' értékét nem lehet feloldani. Jelöljön ki szöveget az aktív szerkesztőablakban!" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/hun/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..a1522b0bc3 --- /dev/null +++ b/i18n/hun/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Igen", + "cancelButton": "Mégse" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/hun/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 14d2073ea6..9ec0b71822 100644 --- a/i18n/hun/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/hun/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Motorkompatibilitás.", "vscode.extension.engines.vscode": "VS Code kiegészítőkhöz. Meghatározza azt a VS Code-verziót, amivel a kiegészítő kompatibilis. Nem lehet *. Például a ^0.10.5 a VS Code minimum 0.10.5-ös verziójával való kompatibilitást jelzi.", "vscode.extension.publisher": "A VS Code-kiegészítő kiadója.", "vscode.extension.displayName": "A kiegészítő VS Code galériában megjelenített neve.", "vscode.extension.categories": "A VS Code-galériában való kategorizálásra használt kategóriák.", + "vscode.extension.category.languages.deprecated": "Használja helyette a „programozási nyelveket”!", "vscode.extension.galleryBanner": "A VS Code piactéren használt szalagcím.", "vscode.extension.galleryBanner.color": "A VS Code piactéren használt szalagcím színe.", "vscode.extension.galleryBanner.theme": "A szalagcímben használt betűtípus színsémája.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Aktiváló esemény, ami akkor fut, ha a megadott típusú hibakeresési munkamenetnek el kell indulnia (és a megfelelő resolveDebugConfiguration metódusokat meg kell hívni).", "vscode.extension.activationEvents.workspaceContains": "Aktiváló esemény, ami akkor fut le, ha egy olyan mappa kerül megnyitásra, amiben legalább egy olyan fájl van, amely illeszkedik a megadott globális mintára.", "vscode.extension.activationEvents.onView": "Aktiváló esemény, ami akkor fut le, amikor a megadott nézetet kiterjesztik.", + "vscode.extension.activationEvents.onUri": "Aktiváló esemény, ami akkor fut le, amikor megnyílik egy URI, ami ehhez a kiegészítőhöz van irányítva.", "vscode.extension.activationEvents.star": "Aktiváló esemény, ami a VS Code indításakor fut le. A jó felhasználói élmény érdekében csak akkor használja ezt az eseményt, ha más aktiváló események nem alkalmasak az adott kiegészítő esetében.", "vscode.extension.badges": "A kiegészítő piactéren található oldalának oldalsávjában megjelenő jelvények listája.", "vscode.extension.badges.url": "A jelvény kép URL-je.", "vscode.extension.badges.href": "A jelvény hivatkozása.", "vscode.extension.badges.description": "A jelvény leírása.", + "vscode.extension.markdown": "Meghatározza a piactéren a markdown-tartalom megjelenítéséhez használt motort.", + "vscode.extension.qna": "Meghatározza a piactéren található „Kérdések és válaszok” (Q&A) hivatkozást. „marketplace” érték esetén a piactér alapértelmezett kérdések és válaszok oldala van engedélyezve. Egyéb szöveges tartalom esetén egy saját URL-lel rendelkező „kérdések és válaszok”-oldal adható meg! False érték esetén a „kérdések és válaszok”-oldal ki van kapcsolva.", "vscode.extension.extensionDependencies": "Más kiegészítők, melyek függőségei ennek a kiegészítőnek. A kiegészítők azonosítója mindig ${publisher}.${name} formájú. Például: vscode.csharp.", "vscode.extension.scripts.prepublish": "A VS Code kiegészítő publikálása előtt végrehajtott parancsfájl.", "vscode.extension.scripts.uninstall": "Eltávolítási illesztőpont VS Code kiegészítők számára. Parancsfájl, ami a VS Code újraindítása (leállása és elindítása) esetén fut le a kiegészítő teljes eltávolítása után. Csak Node-parancsfájlok használhatók.", diff --git a/i18n/hun/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/hun/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 35211938d1..b58594ae5e 100644 --- a/i18n/hun/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Az összes kiegészítő le van tiltva.", "extensionHostProcess.crash": "A kiegészítő gazdafolyamata váratlanul leállt.", "extensionHostProcess.unresponsiveCrash": "A kiegészítő gazdafolyamata le lett állítva, mert nem válaszolt.", - "devTools": "Fejlesztői eszközök", + "devTools": "Fejlesztői eszközök megnyitása", "restart": "Kiegészítő gazdafolyamatának újraindítása", "overwritingExtension": "A(z) {0} kiegészítő felülírása a következővel: {1}.", "extensionUnderDevelopment": "A(z) {0} elérési úton található fejlesztői kiegészítő betöltése", diff --git a/i18n/hun/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/hun/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 419a30cc60..84820d599b 100644 --- a/i18n/hun/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -6,11 +6,24 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "A működéshez Microsoft .NET-keretrendszer 4.5 szükséges. A telepítéshez kövesse az alábbi hivatkozást!", "installNet": ".NET Framework 4.5 letöltése", "neverShowAgain": "Ne jelenítse meg újra", - "netVersionError": "A működéshez Microsoft .NET-keretrendszer 4.5 szükséges. A telepítéshez kövesse az alábbi hivatkozást!", + "enospcError": "A {0} nem tudja figyelni a fájlváltozásokat egy ilyen nagy munkaterületen. Kövesse az utasításokat az alábbi hivatkozáson a probléma megoldásához!", "learnMore": "Utasítások", - "enospcError": "A {0} kezd kifogyni a fájlleírókból. Kövesse az utasításokat az alábbi hivatkozáson a probléma megoldásához!", + "fileInvalidPath": "Érvénytelen fájlerőforrás ({0})", + "fileIsDirectoryError": "A fájl egy könyvtár", + "fileNotModifiedError": "A fájl azóta nem módosult", + "fileTooLargeForHeapError": "Egy ekkora fájl megnyitásához újra kell indítania a VS Code-ot, és engedélyeznie kell, hogy több memóriát használhasson.", + "fileTooLargeError": "A fájl túl nagy a megnyitáshoz", + "fileNotFoundError": "Fájl nem található ({0})", + "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként", + "filePermission": "Engedély megtagadva a fájl írására ({0})", + "fileExists": "A létrehozandó fájl már létezik ({0})", + "fileModifiedError": "A fájl azóta módosult", + "fileReadOnlyError": "A fájl csak olvasható", + "fileMoveConflict": "Nem lehet áthelyezni vagy másolni. A fájl már létezik a célhelyen.", + "unableToMoveCopyError": "Nem lehet áthelyezni vagy másolni. A fájl felülírná a mappát, amiben található.", "binFailed": "A következő fájlt nem sikerült a lomtárba helyezni: '{0}'", "trashFailed": "A(z) {0} kukába helyezése nem sikerült" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index c2d2782199..751f673906 100644 --- a/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Fájl nem található ({0})", "fileIsDirectoryError": "A fájl egy könyvtár", "fileNotModifiedError": "A fájl azóta nem módosult", - "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként" + "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként", + "err.create": "Nem sikerült létrehozni a(z) {0} nevű fájlt", + "fileMoveConflict": "Nem lehet áthelyezni vagy másolni. A fájl már létezik a célhelyen." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json index 942007243d..e9a181b9b3 100644 --- a/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,7 @@ "fileInvalidPath": "Érvénytelen fájlerőforrás ({0})", "fileIsDirectoryError": "A fájl egy könyvtár", "fileNotModifiedError": "A fájl azóta nem módosult", - "fileTooLargeForHeapError": "A fájlméret nagyobb, mint az ablak memóriakorlátja. Próbálja meg a következő parancsot futtatni: code --max-memory=<ÚJ MÉRET>", + "fileTooLargeForHeapError": "A fájlméret túllépi az alapértelmezett memóriakorlátot. A jelenlegi beállítás szerint az alkalmazás újraindul {0}MB-os korláttal.", "fileTooLargeError": "A fájl túl nagy a megnyitáshoz", "fileNotFoundError": "Fájl nem található ({0})", "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként", diff --git a/i18n/hun/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/hun/src/vs/workbench/services/progress/browser/progressService2.i18n.json index 7557bf18aa..8b044f5543 100644 --- a/i18n/hun/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/hun/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} – {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Mégse" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 72975b30f2..ce816c471c 100644 --- a/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -10,6 +10,7 @@ "vscode.extension.contributes.grammars.language": "Annak a nyelvnek az azonosítója, amely számára szolgáltatva van ez a szintaxis.", "vscode.extension.contributes.grammars.scopeName": "A tmLanguage-fájl által használt TextMate-hatókör neve.", "vscode.extension.contributes.grammars.path": "A tmLanguage-fájl elérési útja. Az elérési út relatív a kiegészítő mappájához képest, és általában './syntaxes/'-zal kezdődik.", - "vscode.extension.contributes.grammars.embeddedLanguages": "Hatókörnév-nyelvazonosító kulcs-érték párokat tartalmazó objektum, ha a nyelvtan tartalmaz beágyazott nyelveket.", + "vscode.extension.contributes.grammars.embeddedLanguages": "Hatókörnevek leképezése nyelvazonosítókra, ha a nyelvtan tartalmaz beágyazott nyelveket.", + "vscode.extension.contributes.grammars.tokenTypes": "Hatókörnevek leképezése tokentípusokra.", "vscode.extension.contributes.grammars.injectTo": "Azon nyelvi hatókörök nevei, ahová be lesz ágyazva ez a nyelvtan." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 48305e482e..e51801f26c 100644 --- a/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/hun/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "Hiányzó karakterlánc a `contributes.{0}.path`-ban. A megadott érték: {1}", "invalid.injectTo": "A `contributes.{0}.injectTo` értéke érvénytelen. Az értéke egy tömb lehet, ami nyelvhatókörök neveit tartalmazza. A megadott érték: {1}", "invalid.embeddedLanguages": "A `contributes.{0}.embeddedLanguages` értéke érvénytelen. Az értéke egy hatókörnév-nyelv kulcs-érték párokat tartalmazó objektum lehet. A megadott érték: {1}", + "invalid.tokenTypes": "A `contributes.{0}.tokenTypes` értéke érvénytelen. Az értéke egy hatókörnév-tokentípus kulcs-érték párokat tartalmazó objektum lehet. A megadott érték: {1}", "invalid.path.1": "A `contributes.{0}.path` ({1}) nem a kiegészítő mappáján belül található ({2}). Emiatt előfordulhat, hogy a kiegészítő nem lesz hordozható.", "no-tm-grammar": "Nincs TM Grammar regisztrálva ehhez a nyelvhez." } \ No newline at end of file diff --git a/i18n/ita/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/ita/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..4976649690 --- /dev/null +++ b/i18n/ita/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "Server di linguaggio CSS", + "folding.start": "Inizio di una regione riducibile", + "folding.end": "Fine di una regione riducibile" +} \ No newline at end of file diff --git a/i18n/ita/extensions/css-language-features/package.i18n.json b/i18n/ita/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..35517becb5 --- /dev/null +++ b/i18n/ita/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Funzionalità del linguaggio CSS", + "description": "Offre un supporto avanzato per i file CSS, LESS e SCSS", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", + "css.lint.boxModel.desc": "Non usare width o height con padding o border", + "css.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", + "css.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", + "css.lint.emptyRules.desc": "Non usare set di regole vuoti", + "css.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", + "css.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", + "css.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", + "css.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", + "css.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", + "css.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", + "css.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", + "css.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", + "css.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", + "css.lint.unknownProperties.desc": "Proprietà sconosciuta.", + "css.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", + "css.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", + "css.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", + "css.trace.server.desc": "Traccia la comunicazione tra VS Code e il server del linguaggio CSS.", + "css.validate.title": "Controlla la convalida CSS e le gravità dei problemi.", + "css.validate.desc": "Abilita o disabilita tutte le convalide", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", + "less.lint.boxModel.desc": "Non usare width o height con padding o border", + "less.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", + "less.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", + "less.lint.emptyRules.desc": "Non usare set di regole vuoti", + "less.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", + "less.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", + "less.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", + "less.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", + "less.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", + "less.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", + "less.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", + "less.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", + "less.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", + "less.lint.unknownProperties.desc": "Proprietà sconosciuta.", + "less.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", + "less.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", + "less.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", + "less.validate.title": "Controlla la convalida LESS e le gravità dei problemi.", + "less.validate.desc": "Abilita o disabilita tutte le convalide", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", + "scss.lint.boxModel.desc": "Non usare width o height con padding o border", + "scss.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", + "scss.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", + "scss.lint.emptyRules.desc": "Non usare set di regole vuoti", + "scss.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", + "scss.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", + "scss.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", + "scss.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", + "scss.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", + "scss.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", + "scss.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", + "scss.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", + "scss.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", + "scss.lint.unknownProperties.desc": "Proprietà sconosciuta.", + "scss.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", + "scss.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", + "scss.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", + "scss.validate.title": "Controlla la convalida SCSS e le gravità dei problemi.", + "scss.validate.desc": "Abilita o disabilita tutte le convalide", + "less.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", + "scss.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", + "css.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", + "css.colorDecorators.enable.deprecationMessage": "L'impostazione `css.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`.", + "scss.colorDecorators.enable.deprecationMessage": "L'impostazione `scss.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`.", + "less.colorDecorators.enable.deprecationMessage": "L'impostazione `less.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`." +} \ No newline at end of file diff --git a/i18n/ita/extensions/css/package.i18n.json b/i18n/ita/extensions/css/package.i18n.json index 50dc622c92..5f1a325b6d 100644 --- a/i18n/ita/extensions/css/package.i18n.json +++ b/i18n/ita/extensions/css/package.i18n.json @@ -2,80 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Funzionalità del linguaggio CSS", - "description": "Offre un supporto avanzato per i file CSS, LESS e SCSS", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", - "css.lint.boxModel.desc": "Non usare width o height con padding o border", - "css.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", - "css.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", - "css.lint.emptyRules.desc": "Non usare set di regole vuoti", - "css.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", - "css.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", - "css.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", - "css.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", - "css.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", - "css.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", - "css.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", - "css.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", - "css.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", - "css.lint.unknownProperties.desc": "Proprietà sconosciuta.", - "css.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", - "css.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", - "css.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", - "css.trace.server.desc": "Traccia la comunicazione tra VS Code e il server del linguaggio CSS.", - "css.validate.title": "Controlla la convalida CSS e le gravità dei problemi.", - "css.validate.desc": "Abilita o disabilita tutte le convalide", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", - "less.lint.boxModel.desc": "Non usare width o height con padding o border", - "less.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", - "less.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", - "less.lint.emptyRules.desc": "Non usare set di regole vuoti", - "less.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", - "less.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", - "less.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", - "less.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", - "less.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", - "less.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", - "less.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", - "less.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", - "less.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", - "less.lint.unknownProperties.desc": "Proprietà sconosciuta.", - "less.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", - "less.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", - "less.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", - "less.validate.title": "Controlla la convalida LESS e le gravità dei problemi.", - "less.validate.desc": "Abilita o disabilita tutte le convalide", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Numero di parametri non valido", - "scss.lint.boxModel.desc": "Non usare width o height con padding o border", - "scss.lint.compatibleVendorPrefixes.desc": "Quando si usa un prefisso specifico del fornitore, assicurarsi di includere anche tutte le altre proprietà specifiche del fornitore", - "scss.lint.duplicateProperties.desc": "Non usare definizioni di stile duplicate", - "scss.lint.emptyRules.desc": "Non usare set di regole vuoti", - "scss.lint.float.desc": "Evitare di usare 'float'. Con gli elementi float si ottiene codice CSS che causa facilmente interruzioni in caso di modifica di un aspetto del layout.", - "scss.lint.fontFaceProperties.desc": "La regola @font-face deve definire le proprietà 'src' e 'font-family'", - "scss.lint.hexColorLength.desc": "I colori esadecimali devono essere composti da tre o sei numeri esadecimali", - "scss.lint.idSelector.desc": "I selettori non devono contenere ID perché queste regole sono strettamente accoppiate al codice HTML.", - "scss.lint.ieHack.desc": "Gli hack IE sono necessari solo per il supporto di IE7 e versioni precedenti", - "scss.lint.important.desc": "Evitare di usare !important perché indica che la specificità dell'intero codice CSS non è più controllabile ed è necessario effettuarne il refactoring.", - "scss.lint.importStatement.desc": "Le istruzioni Import non vengono caricate in parallelo", - "scss.lint.propertyIgnoredDueToDisplay.desc": "La proprietà viene ignorata a causa della visualizzazione. Ad esempio, con 'display: inline', le proprietà width, height, margin-top, margin-bottom e float non hanno effetto", - "scss.lint.universalSelector.desc": "Il selettore universale (*) è notoriamente lento", - "scss.lint.unknownProperties.desc": "Proprietà sconosciuta.", - "scss.lint.unknownVendorSpecificProperties.desc": "Proprietà specifica del fornitore sconosciuta.", - "scss.lint.vendorPrefix.desc": "Quando si usa un prefisso specifico del fornitore, includere anche la proprietà standard", - "scss.lint.zeroUnits.desc": "Non è necessaria alcuna unità per lo zero", - "scss.validate.title": "Controlla la convalida SCSS e le gravità dei problemi.", - "scss.validate.desc": "Abilita o disabilita tutte le convalide", - "less.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", - "scss.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", - "css.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", - "css.colorDecorators.enable.deprecationMessage": "L'impostazione `css.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`.", - "scss.colorDecorators.enable.deprecationMessage": "L'impostazione `scss.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`.", - "less.colorDecorators.enable.deprecationMessage": "L'impostazione `less.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`." + "displayName": "Nozioni di base del linguaggio CSS", + "description": "Offre l'evidenziazione della sintassi e la corrispondenza delle parentesi nei file CSS, LESS e SCSS." } \ No newline at end of file diff --git a/i18n/ita/extensions/emmet/package.i18n.json b/i18n/ita/extensions/emmet/package.i18n.json index 93d915c9ea..325af035e6 100644 --- a/i18n/ita/extensions/emmet/package.i18n.json +++ b/i18n/ita/extensions/emmet/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Proprietà CSS delimitate da virgola che assumono il prefisso 'webkit' del vendor quando utilizzate nelle abbreviazioni di Emmet che iniziano per '-'. Per evitare sempre il prefisso 'webkit' impostare stringa vuota.", "emmetPreferencesCssMozProperties": "Proprietà CSS delimitate da virgola che assumono il prefisso 'moz' del vendor quando utilizzate nelle abbreviazioni di Emmet che iniziano per '-'. Per evitare sempre il prefisso 'moz' impostare stringa vuota.", "emmetPreferencesCssOProperties": "Proprietà CSS delimitate da virgola che assumono il prefisso 'o' del vendor quando utilizzate nelle abbreviazioni di Emmet che iniziano per '-'. Per evitare sempre il prefisso 'o' impostare stringa vuota.", - "emmetPreferencesCssMsProperties": "Proprietà CSS delimitate da virgola che assumono il prefisso 'ms' del vendor quando utilizzate nelle abbreviazioni di Emmet che iniziano per '-'. Per evitare sempre il prefisso 'ms' impostare stringa vuota." + "emmetPreferencesCssMsProperties": "Proprietà CSS delimitate da virgola che assumono il prefisso 'ms' del vendor quando utilizzate nelle abbreviazioni di Emmet che iniziano per '-'. Per evitare sempre il prefisso 'ms' impostare stringa vuota.", + "emmetPreferencesCssFuzzySearchMinScore": "Il valore minimo (da 0 a 1) che dovrebbe raggiungere un'abbreviazione di fuzzy-match. I valori più bassi possono produrre molti falsi positivi, i valori più alti possono ridurre le possibili corrispondenze.", + "emmetOptimizeStylesheetParsing": "Se è impostato su false, l'intero file viene analizzato per determinare se la posizione corrente è valida per l'espansione delle abbreviazioni di Emmet. Se è impostato su true, viene analizzato solo il contenuto circostante alla posizione corrente nei file css/scss/less." } \ No newline at end of file diff --git a/i18n/ita/extensions/git/out/commands.i18n.json b/i18n/ita/extensions/git/out/commands.i18n.json index eac0197e33..3f68d2df31 100644 --- a/i18n/ita/extensions/git/out/commands.i18n.json +++ b/i18n/ita/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Crea nuovo branch", "repourl": "URL del repository", "parent": "Directory padre", - "cancel": "$(sync~spin) Clonazione di repository in corso... Clicca per annullare", - "cancel tooltip": "Annulla l'operazione di clonazione", - "cloning": "Clonazione del repository GIT...", + "cloning": "Clonazione del repository GIT '{0}'...", "openrepo": "Apri repository", "proposeopen": "Aprire il repository clonato?", "init": "Selezionare la cartella dell'area di lavoro in cui inizializzare il Git repo", @@ -75,7 +73,7 @@ "ok": "OK", "push with tags success": "Il push con tag è riuscito.", "pick remote": "Selezionare un repository remoto in cui pubblicare il ramo '{0}':", - "sync is unpredictable": "Questa azione consentirà di effettuare il push e il pull di commit da e verso '{0}'.", + "sync is unpredictable": "Questa azione consentirà di effettuare il push e il pull di commit da e verso '{0}/[1]'.", "never again": "OK, non visualizzare più", "no remotes to publish": "Il repository non contiene elementi remoti configurati come destinazione della pubblicazione.", "no changes stash": "Non ci sono modifiche da accantonare.", diff --git a/i18n/ita/extensions/git/package.i18n.json b/i18n/ita/extensions/git/package.i18n.json index 268d1f348e..e10baefa84 100644 --- a/i18n/ita/extensions/git/package.i18n.json +++ b/i18n/ita/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Controlla se visualizzare un'azione Apri file inline nella visualizzazione modifiche GIT.", "config.inputValidation": "Controlla quando visualizzare la convalida sull'input del messaggio di commit.", "config.detectSubmodules": "Controlla se rilevare automaticamente i moduli secondari GIT.", + "config.detectSubmodulesLimit": "Controlla il limite dei sottomoduli git rilevati.", "colors.modified": "Colore delle risorse modificate.", "colors.deleted": "Colore delle risorse eliminate.", "colors.untracked": "Colore delle risorse non tracciate.", diff --git a/i18n/ita/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/ita/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..8313a5f7e1 --- /dev/null +++ b/i18n/ita/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "Server di linguaggio HTML", + "folding.start": "Inizio di una regione riducibile", + "folding.end": "Fine di una regione riducibile" +} \ No newline at end of file diff --git a/i18n/ita/extensions/html-language-features/package.i18n.json b/i18n/ita/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..b237335f1d --- /dev/null +++ b/i18n/ita/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Funzionalità del linguaggio HTML", + "description": "Offre un supporto avanzato sul linguaggio per i file HTML, Razor e Handlebars", + "html.format.enable.desc": "Abilita/Disabilita il formattatore HTML predefinito", + "html.format.wrapLineLength.desc": "Numero massimo di caratteri per riga (0 = disabilita).", + "html.format.unformatted.desc": "Elenco di tag, separati da virgole, che non devono essere riformattati. Con 'null' viene usata l'impostazione predefinita che prevede l'uso di tutti i tag elencati in https://www.w3.org/TR/html5/dom.html#phrasing-content.", + "html.format.contentUnformatted.desc": "Elenco di tag, separati da virgole, in cui il contenuto non deve essere riformattato. Per impostazione predefinita, con 'null' viene usato il tag 'pre'.", + "html.format.indentInnerHtml.desc": "Imposta un rientro per le sezioni <head> e <body>.", + "html.format.preserveNewLines.desc": "Indica se è necessario mantenere interruzioni di riga esistenti prima degli elementi. Funziona solo prima degli elementi e non all'interno di tag o per il testo.", + "html.format.maxPreserveNewLines.desc": "Numero massimo di interruzioni di riga da mantenere in un unico blocco. Per non impostare un numero massimo, usare 'null'.", + "html.format.indentHandlebars.desc": "Applica la formattazione e imposta un rientro per {{#foo}} e {{/foo}}.", + "html.format.endWithNewline.desc": "Termina con un carattere di nuova riga.", + "html.format.extraLiners.desc": "Elenco di tag, separati da virgole, che devono essere preceduti da un carattere di nuova riga. Con 'null' viene usata l'impostazione predefinita \"head, body, /html\".", + "html.format.wrapAttributes.desc": "Esegue il wrapping degli attributi.", + "html.format.wrapAttributes.auto": "Esegue il wrapping degli attributi solo quando viene superata la lunghezza di riga.", + "html.format.wrapAttributes.force": "Esegue il wrapping di ogni attributo ad eccezione del primo.", + "html.format.wrapAttributes.forcealign": "Esegue il wrapping di ogni attributo ad eccezione del primo e mantiene l'allineamento.", + "html.format.wrapAttributes.forcemultiline": "Esegue il wrapping di ogni attributo.", + "html.suggest.angular1.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag e proprietà di Angular V1.", + "html.suggest.ionic.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag, proprietà e valori di Ionic.", + "html.suggest.html5.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag, proprietà e valori di HTML5.", + "html.trace.server.desc": "Traccia la comunicazione tra VS Code e il server del linguaggio HTML.", + "html.validate.scripts": "Consente di configurare se il supporto del linguaggio HTML predefinito convalida gli script incorporati.", + "html.validate.styles": "Consente di configurare se il supporto del linguaggio HTML predefinito convalida gli stili incorporati.", + "html.autoClosingTags": "Abilita/Disabilita la chiusura automatica dei tag HTML." +} \ No newline at end of file diff --git a/i18n/ita/extensions/html/package.i18n.json b/i18n/ita/extensions/html/package.i18n.json index 4431275347..9015f75af4 100644 --- a/i18n/ita/extensions/html/package.i18n.json +++ b/i18n/ita/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Funzionalità del linguaggio HTML", - "description": "Offre un supporto avanzato sul linguaggio per i file HTML, Razor e Handlebars", - "html.format.enable.desc": "Abilita/Disabilita il formattatore HTML predefinito", - "html.format.wrapLineLength.desc": "Numero massimo di caratteri per riga (0 = disabilita).", - "html.format.unformatted.desc": "Elenco di tag, separati da virgole, che non devono essere riformattati. Con 'null' viene usata l'impostazione predefinita che prevede l'uso di tutti i tag elencati in https://www.w3.org/TR/html5/dom.html#phrasing-content.", - "html.format.contentUnformatted.desc": "Elenco di tag, separati da virgole, in cui il contenuto non deve essere riformattato. Per impostazione predefinita, con 'null' viene usato il tag 'pre'.", - "html.format.indentInnerHtml.desc": "Imposta un rientro per le sezioni <head> e <body>.", - "html.format.preserveNewLines.desc": "Indica se è necessario mantenere interruzioni di riga esistenti prima degli elementi. Funziona solo prima degli elementi e non all'interno di tag o per il testo.", - "html.format.maxPreserveNewLines.desc": "Numero massimo di interruzioni di riga da mantenere in un unico blocco. Per non impostare un numero massimo, usare 'null'.", - "html.format.indentHandlebars.desc": "Applica la formattazione e imposta un rientro per {{#foo}} e {{/foo}}.", - "html.format.endWithNewline.desc": "Termina con un carattere di nuova riga.", - "html.format.extraLiners.desc": "Elenco di tag, separati da virgole, che devono essere preceduti da un carattere di nuova riga. Con 'null' viene usata l'impostazione predefinita \"head, body, /html\".", - "html.format.wrapAttributes.desc": "Esegue il wrapping degli attributi.", - "html.format.wrapAttributes.auto": "Esegue il wrapping degli attributi solo quando viene superata la lunghezza di riga.", - "html.format.wrapAttributes.force": "Esegue il wrapping di ogni attributo ad eccezione del primo.", - "html.format.wrapAttributes.forcealign": "Esegue il wrapping di ogni attributo ad eccezione del primo e mantiene l'allineamento.", - "html.format.wrapAttributes.forcemultiline": "Esegue il wrapping di ogni attributo.", - "html.suggest.angular1.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag e proprietà di Angular V1.", - "html.suggest.ionic.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag, proprietà e valori di Ionic.", - "html.suggest.html5.desc": "Consente di configurare se il supporto del linguaggio HTML predefinito suggerisce tag, proprietà e valori di HTML5.", - "html.trace.server.desc": "Traccia la comunicazione tra VS Code e il server del linguaggio HTML.", - "html.validate.scripts": "Consente di configurare se il supporto del linguaggio HTML predefinito convalida gli script incorporati.", - "html.validate.styles": "Consente di configurare se il supporto del linguaggio HTML predefinito convalida gli stili incorporati.", - "html.experimental.syntaxFolding": "Abilita/disabilita i marcatori di folding con riconoscimento della sintassi.", - "html.autoClosingTags": "Abilita/Disabilita la chiusura automatica dei tag HTML." + "displayName": "Nozioni di base del linguaggio HTML", + "description": "Fornisce l'evidenziazione della sintassi, la corrispondenza delle parentesi & frammenti nei file HTML." } \ No newline at end of file diff --git a/i18n/ita/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/ita/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..b9cca5241b --- /dev/null +++ b/i18n/ita/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "Server di linguaggio JSON" +} \ No newline at end of file diff --git a/i18n/ita/extensions/json-language-features/package.i18n.json b/i18n/ita/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..2b426a9eac --- /dev/null +++ b/i18n/ita/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Funzionalità del linguaggio JSON", + "description": "Fornisce supporto avanzato del linguaggio per i file JSON.", + "json.schemas.desc": "Associa schemi a file JSON nel progetto corrente", + "json.schemas.url.desc": "URL di uno schema o percorso relativo di uno schema nella directory corrente", + "json.schemas.fileMatch.desc": "Matrice di criteri dei file da usare per la ricerca durante la risoluzione di file JSON in schemi.", + "json.schemas.fileMatch.item.desc": "Criteri dei file che possono contenere '*' da usare per la ricerca durante la risoluzione di file JSON in schemi.", + "json.schemas.schema.desc": "Definizione dello schema per l'URL specificato. È necessario specificare lo schema per evitare accessi all'URL dello schema.", + "json.format.enable.desc": "Abilita/Disabilita il formattatore JSON predefinito (richiede il riavvio)", + "json.tracing.desc": "Traccia le comunicazioni tra Visual Studio Code e il server di linguaggio JSON.", + "json.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", + "json.colorDecorators.enable.deprecationMessage": "L'impostazione `json.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`." +} \ No newline at end of file diff --git a/i18n/ita/extensions/json/package.i18n.json b/i18n/ita/extensions/json/package.i18n.json index b5d87ea1df..d1cf4899cf 100644 --- a/i18n/ita/extensions/json/package.i18n.json +++ b/i18n/ita/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Funzionalità del linguaggio JSON", - "description": "Fornisce supporto avanzato del linguaggio per i file JSON.", - "json.schemas.desc": "Associa schemi a file JSON nel progetto corrente", - "json.schemas.url.desc": "URL di uno schema o percorso relativo di uno schema nella directory corrente", - "json.schemas.fileMatch.desc": "Matrice di criteri dei file da usare per la ricerca durante la risoluzione di file JSON in schemi.", - "json.schemas.fileMatch.item.desc": "Criteri dei file che possono contenere '*' da usare per la ricerca durante la risoluzione di file JSON in schemi.", - "json.schemas.schema.desc": "Definizione dello schema per l'URL specificato. È necessario specificare lo schema per evitare accessi all'URL dello schema.", - "json.format.enable.desc": "Abilita/Disabilita il formattatore JSON predefinito (richiede il riavvio)", - "json.tracing.desc": "Traccia la comunicazione tra VS Code e il server del linguaggio JSON.", - "json.colorDecorators.enable.desc": "Abilita o disabilita gli elementi Decorator di tipo colore", - "json.colorDecorators.enable.deprecationMessage": "L'impostazione `json.colorDecorators.enable` è stata deprecata e sostituita da `editor.colorDecorators`.", - "json.experimental.syntaxFolding": "Abilita/disabilita i marcatori di folding con riconoscimento della sintassi." + "displayName": "Nozioni di base del linguaggio JSON", + "description": "Offre l'evidenziazione della sintassi e la corrispondenza delle parentesi nei file JSON." } \ No newline at end of file diff --git a/i18n/ita/extensions/markdown-basics/package.i18n.json b/i18n/ita/extensions/markdown-basics/package.i18n.json index 24bea32c34..816ce519d4 100644 --- a/i18n/ita/extensions/markdown-basics/package.i18n.json +++ b/i18n/ita/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/ita/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/ita/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..eb5c477e4c --- /dev/null +++ b/i18n/ita/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "Impossibile caricare 'markdown.styles': {0}" +} \ No newline at end of file diff --git a/i18n/ita/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/ita/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..c46a3464cc --- /dev/null +++ b/i18n/ita/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Anteprima] {0}", + "previewTitle": "Anteprima {0}" +} \ No newline at end of file diff --git a/i18n/ita/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/ita/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..991ae221d1 --- /dev/null +++ b/i18n/ita/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Alcuni contenuti sono stati disabilitati in questo documento", + "preview.securityMessage.title": "Contenuti potenzialmente non sicuri sono stati disattivati nell'anteprima del Markdown. Modificare l'impostazione di protezione dell'anteprima del Markdown per consentire la visualizzazione di contenuto insicuro o abilitare gli script", + "preview.securityMessage.label": "Avviso di sicurezza contenuto disabilitato" +} \ No newline at end of file diff --git a/i18n/ita/extensions/markdown-language-features/out/security.i18n.json b/i18n/ita/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..257cf27b76 --- /dev/null +++ b/i18n/ita/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Strict", + "strict.description": "Carica solo contenuto protetto", + "insecureLocalContent.title": "Consenti contenuto locale non protetto", + "insecureLocalContent.description": "Consente il caricamento di contenuti tramite HTTP servito da localhost", + "insecureContent.title": "Consenti contenuto non protetto", + "insecureContent.description": "Consente il caricamento di contenuti tramite HTTP", + "disable.title": "Disabilita", + "disable.description": "Consente l'esecuzione di tutti i contenuti e script. Scelta non consigliata", + "moreInfo.title": "Altre informazioni", + "enableSecurityWarning.title": "Abilita anteprima degli avvisi di protezione in questa area di lavoro", + "disableSecurityWarning.title": "Disabilita anteprima degli avvisi di protezione in questa area di lavoro", + "toggleSecurityWarning.description": "Non influisce sul livello di sicurezza del contenuto", + "preview.showPreviewSecuritySelector.title": "Seleziona impostazioni di protezione per le anteprime Markdown in questa area di lavoro" +} \ No newline at end of file diff --git a/i18n/ita/extensions/markdown-language-features/package.i18n.json b/i18n/ita/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..eeb708af9f --- /dev/null +++ b/i18n/ita/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Funzionalità del linguaggio Markdown", + "description": "Fornisce un supporto avanzato del linguaggio per Markdown.", + "markdown.preview.breaks.desc": "Imposta come le interruzioni di riga vengono visualizzate nell'anteprima di markdown. Impostarlo a 'true' crea un <br>per ogni carattere di nuova riga.", + "markdown.preview.linkify": "Abilita o disabilita la conversione di testo simile a URL in collegamenti nell'anteprima markdown.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Fare doppio clic nell'anteprima markdown per passare all'editor.", + "markdown.preview.fontFamily.desc": "Consente di controllare la famiglia di caratteri usata nell'anteprima markdown.", + "markdown.preview.fontSize.desc": "Consente di controllare le dimensioni del carattere in pixel usate nell'anteprima markdown.", + "markdown.preview.lineHeight.desc": "Consente di controllare l'altezza della riga usata nell'anteprima markdown. Questo numero è relativo alle dimensioni del carattere.", + "markdown.preview.markEditorSelection.desc": "Contrassegna la selezione dell'editor corrente nell'anteprima markdown.", + "markdown.preview.scrollEditorWithPreview.desc": "Quando si scorre l'anteprima markdown, aggiorna la visualizzazione dell'editor.", + "markdown.preview.scrollPreviewWithEditor.desc": "Quando si scorre l'editor markdown, aggiorna la visualizzazione dell'anteprima.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Deprecato] Scorre l'anteprima markdown in modo da visualizzare la riga attualmente selezionata dall'editor.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Questa impostazione è stata sostituita da 'markdown.preview.scrollPreviewWithEditor' e non ha più effetto.", + "markdown.preview.title": "Apri anteprima", + "markdown.previewFrontMatter.dec": "Consente di impostare il rendering del front matter YAML nell'anteprima markdown. Con 'hide' il front matter viene rimosso; altrimenti il front matter viene considerato come contenuto markdown.", + "markdown.previewSide.title": "Apri anteprima lateralmente", + "markdown.showLockedPreviewToSide.title": "Apri anteprima bloccata lateralmente", + "markdown.showSource.title": "Mostra origine", + "markdown.styles.dec": "Elenco di URL o percorsi locali dei fogli di stile CSS da usare dall'anteprima markdown. I percorsi relativi vengono interpretati come relativi alla cartella aperta nella finestra di esplorazione. Se non è presente alcuna cartella aperta, vengono interpretati come relativi al percorso del file markdown. Tutti i caratteri '\\' devono essere scritti come '\\\\'.", + "markdown.showPreviewSecuritySelector.title": "Modifica impostazioni di sicurezza anteprima", + "markdown.trace.desc": "Abilitare la registrazione debug per l'estensione markdown.", + "markdown.preview.refresh.title": "Aggiorna anteprima", + "markdown.preview.toggleLock.title": "Attiva/Disattiva blocco anteprima" +} \ No newline at end of file diff --git a/i18n/ita/extensions/markdown/out/features/preview.i18n.json b/i18n/ita/extensions/markdown/out/features/preview.i18n.json index 2aa6ddf178..c46a3464cc 100644 --- a/i18n/ita/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/ita/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/ita/extensions/npm/out/npmView.i18n.json b/i18n/ita/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..565aeceec1 --- /dev/null +++ b/i18n/ita/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "Non è possibile avviare \"{0}\" per eseguire il debug perché negli script manca un'opzione di debug dei nodi, ad esempio \"--inspect-brk\".", + "npm.scriptInvalid": "Non è stato possibile trovare lo script \"{0}\". Provare ad aggiornare la visualizzazione." +} \ No newline at end of file diff --git a/i18n/ita/extensions/npm/out/tasks.i18n.json b/i18n/ita/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..c3dbec0695 --- /dev/null +++ b/i18n/ita/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Rilevamento attività npm: non è stato possibile analizzare il file {0}" +} \ No newline at end of file diff --git a/i18n/ita/extensions/npm/package.i18n.json b/i18n/ita/extensions/npm/package.i18n.json index ac4bdc5471..fc81506bb8 100644 --- a/i18n/ita/extensions/npm/package.i18n.json +++ b/i18n/ita/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "Eseguire comandi npm con l'opzione `--silent`.", "config.npm.packageManager": "Il gestore dei pacchetti utilizzato per eseguire script.", "config.npm.exclude": "Configura i modelli glob per le cartelle che dovrebbero essere escluse dalla rilevazione automatica di script.", + "config.npm.enableScriptExplorer": "Abilita una visualizzazione di esplorazione per gli script di npm quando l'area di lavoro contiene un file 'package.json'.", "npm.parseError": "Rilevamento attività NPM: Impossibile analizzare il file {0}", "taskdef.script": "Lo script di npm da personalizzare.", - "taskdef.path": "Il percorso della cartella del file package.json che fornisce lo script. Può essere omesso." + "taskdef.path": "Il percorso della cartella del file package.json che fornisce lo script. Può essere omesso.", + "view.name": "Script di npm", + "command.refresh": "Aggiorna", + "command.run": "Esegui", + "command.debug": "Debug", + "command.openScript": "Apri", + "npm.scriptInvalid": "Non è stato possibile trovare lo script '{0}'. Provare ad aggiornare la visualizzazione.", + "npm.noDebugOptions": "Non è stato possibile avviare '{0}' per eseguire il debug perché negli script manca un'opzione di debug dei nodi, ad esempio '--inspect-brk'." } \ No newline at end of file diff --git a/i18n/ita/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/ita/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..7a30dfbedf --- /dev/null +++ b/i18n/ita/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Consentire l'esecuzione di {0} (definito come impostazione dell'area di lavoro) per il lint dei file PHP?", + "php.yes": "Consenti", + "php.no": "Non consentire", + "wrongExecutable": "Non è possibile eseguire la convalida perché {0} non è un file eseguibile di PHP valido. Usare l'impostazione 'php.validate.executablePath' per convalidare il file eseguibile di PHP.", + "noExecutable": "Non è possibile eseguire la convalida perché non è impostato alcun file eseguibile di PHP. Usare l'impostazione 'php.validate.executablePath' per convalidare il file eseguibile di PHP.", + "unknownReason": "Non è stato possibile eseguire php con il percorso {0}. Il motivo è sconosciuto." +} \ No newline at end of file diff --git a/i18n/ita/extensions/php-language-features/package.i18n.json b/i18n/ita/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..b68565b4e5 --- /dev/null +++ b/i18n/ita/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Consente di configurare l'abilitazione dei suggerimenti predefiniti per il linguaggio PHP. Il supporto suggerisce variabili e variabili globali PHP.", + "configuration.validate.enable": "Abilita/Disabilita la convalida PHP predefinita.", + "configuration.validate.executablePath": "Punta all'eseguibile di PHP.", + "configuration.validate.run": "Indica se il linter viene eseguito durante il salvataggio o la digitazione.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "Non consentire la convalida di PHP eseguibile (definito come impostazione dell'area di lavoro)", + "displayName": "Funzionalità del linguaggio PHP", + "description": "Fornisce supporto avanzato del linguaggio per i file PHP." +} \ No newline at end of file diff --git a/i18n/ita/extensions/php/package.i18n.json b/i18n/ita/extensions/php/package.i18n.json index e0ef5cde25..d8344412ea 100644 --- a/i18n/ita/extensions/php/package.i18n.json +++ b/i18n/ita/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Consente di configurare l'abilitazione dei suggerimenti predefiniti per il linguaggio PHP. Il supporto suggerisce variabili e variabili globali PHP.", - "configuration.validate.enable": "Abilita/Disabilita la convalida PHP predefinita.", - "configuration.validate.executablePath": "Punta all'eseguibile di PHP.", - "configuration.validate.run": "Indica se il linter viene eseguito durante il salvataggio o la digitazione.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "Non consentire la convalida di PHP eseguibile (definito come impostazione dell'area di lavoro)", - "displayName": "Funzionalità del linguaggio PHP", - "description": "Offre IntelliSense, linting e nozioni di base sul linguaggio per i file PHP." + "displayName": "Nozioni di base del linguaggio PHP", + "description": "Offre l'evidenziazione della sintassi e la corrispondenza delle parentesi nei file PHP." } \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/commands.i18n.json b/i18n/ita/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..ffa2bc44d1 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Aprire una cartella in Visual Studio Code per usare un progetto TypeScript o JavaScript", + "typescript.projectConfigUnsupportedFile": "Non è stato possibile determinare il progetto TypeScript o JavaScript. Il tipo di file non è supportato", + "typescript.projectConfigCouldNotGetInfo": "Non è stato possibile determinare il progetto TypeScript o JavaScript", + "typescript.noTypeScriptProjectConfig": "Il file non fa parte di un progetto TypeScript. Clicca [qui]({0}) per saperne di più.", + "typescript.noJavaScriptProjectConfig": "Il file non fa parte di un progetto JavaScript. Clicca [qui]({0}) per saperne di più.", + "typescript.configureTsconfigQuickPick": "Configura tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configura jsconfig.json" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..86de96163a --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Selezionare l'azione codice da applicare", + "acquiringTypingsLabel": "Acquisizione dei file typings...", + "acquiringTypingsDetail": "Acquisizione delle definizioni dei file typings per IntelliSense.", + "autoImportLabel": "Importazione automatica da {0}" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..98bb57ed99 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Attiva il controllo semantico in un file JavaScript. Deve essere all'inizio del file.", + "ts-nocheck": "Disattiva il controllo semantico in un file JavaScript. Deve essere all'inizio del file.", + "ts-ignore": "Elimina errori di @ts-check sulla riga successiva di un file." +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..cd8cac2d81 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 implementazione", + "manyImplementationLabel": "{0} implementazioni", + "implementationsErrorLabel": "Non è stato possibile determinare le implementazioni" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..2e98125f88 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "Commento JSDoc" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..40c311f338 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Organizza gli Imports" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..9bccba0f7a --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Correggi tutti nel file)" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..4c74ac0e94 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 riferimento", + "manyReferenceLabel": "{0} riferimenti", + "referenceErrorLabel": "Non è stato possibile determinare i riferimenti" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..a5aca9552f --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "Compila - {0}", + "buildAndWatchTscLabel": "Osserva - {0}" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/ita/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..78e5e160a6 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "Il percorso {0} non punta a un'installazione valida di tsserver. Verrà eseguito il fallback alla versione in bundle di TypeScript.", + "serverCouldNotBeStarted": "Non è stato possibile avviare il server di linguaggio TypeScript. Messaggio di errore: {0}", + "typescript.openTsServerLog.notSupported": "Per la registrazione del server TypeScript è necessario almeno TypeScript 2.2.2", + "typescript.openTsServerLog.loggingNotEnabled": "La registrazione del server TypeScript è disattivata. Per abilitarla, impostare `typescript.tsserver.log` e riavviare il server TypeScript", + "typescript.openTsServerLog.enableAndReloadOption": "Abilita la registrazione e riavvia il server TypeScript", + "typescript.openTsServerLog.noLogFile": "Il server TypeScript non ha avviato la registrazione.", + "openTsServerLog.openFileFailedFailed": "Non è stato possibile aprire il file di log del server TypeScript", + "serverDiedAfterStart": "Il servizio di linguaggio TypeScript è stato arrestato in modo imprevisto per cinque volte dopo che è stato avviato e non verrà riavviato.", + "serverDiedReportIssue": "Segnala problema", + "serverDied": "Il servizio di linguaggio Typescript è stato arrestato in modo imprevisto per cinque volte negli ultimi cinque minuti." +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..75f0f39401 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "versione non valida" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..ad1ac2efcc --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Per abilitare le funzionalità del linguaggio JavaScript/TypeScript a livello di progetto, escludere le cartelle che contengono molti file, come {0}", + "hintExclude.generic": "Per abilitare le funzionalità del linguaggio JavaScript/TypeScript a livello di progetto, escludere le cartelle di grandi dimensioni che contengono file di origine su cui non si lavora.", + "large.label": "Configura esclusioni", + "hintExclude.tooltip": "Per abilitare le funzionalità del linguaggio JavaScript/TypeScript a livello di progetto, escludere le cartelle di grandi dimensioni che contengono file di origine su cui non si lavora." +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..78cf90b25a --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Recupero dei dati per ottimizzare IntelliSense in TypeScript", + "typesInstallerInitializationFailed.title": "Non è stato possibile installare i file di definizione tipi per le funzionalità del linguaggio JavaScript. Verificare che NPM sia installato e o configurare 'typescript.npm' nelle impostazioni utente. Clicca [qui]({0}) per saperne di più.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Non visualizzare più questo messaggio" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..c0e1898354 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Usa versione di VS Code", + "useWorkspaceVersionOption": "Usa versione dell'area di lavoro", + "learnMore": "Altre informazioni", + "selectTsVersion": "Selezionare la versione di TypeScript usata per le funzionalità del linguaggio JavaScript e TypeScript" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/ita/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..385cbc6137 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Non è stato possibile caricare la versione di TypeScript in questo percorso", + "noBundledServerFound": "Il file tsserver di VS Code è stato eliminato da un'altra applicazione, ad esempio uno strumento di rilevamento virus che non funziona correttamente. Reinstallare VS Code." +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript-language-features/package.i18n.json b/i18n/ita/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..415fd9fe79 --- /dev/null +++ b/i18n/ita/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Funzionalità dei linguaggi TypeScript e JavaScript", + "description": "Fornisce un supporto avanzato per JavaScript e TypeScript", + "typescript.reloadProjects.title": "Ricarica progetto", + "javascript.reloadProjects.title": "Ricarica progetto", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Completare le funzioni con la relativa firma del parametro.", + "typescript.tsdk.desc": "Specifica il percorso della cartella che contiene i file tsserver e lib*.d.ts da usare.", + "typescript.disableAutomaticTypeAcquisition": "Disabilita l'acquisizione automatica del tipo. Richiede TypeScript >= 2.0.6.", + "typescript.tsserver.log": "Abilita la registrazione del server TypeScript in un file. Questo registro può essere utilizzato per diagnosticare problemi del server TypeScript. Il registro può contenere percorsi di file, codice sorgente e altre informazioni del progetto potenzialmente riservate. ", + "typescript.tsserver.pluginPaths": "Percorsi aggiuntivi per rilevare la presenza di plug-in del servizio di linguaggio Typescript. Richiede TypeScript >= 2.3.0.", + "typescript.tsserver.pluginPaths.item": "Percorso assoluto o relativo. Il percorso relativo verrà risolto in base alle cartelle dell'area di lavoro.", + "typescript.tsserver.trace": "Abilita la traccia dei messaggi inviati al server TypeScript. Questa traccia può essere utilizzata per diagnosticare problemi del server TypeScript. La traccia può contenere percorsi di file, codice sorgente e altre informazioni del progetto potenzialmente riservate.", + "typescript.validate.enable": "Abilita/Disabilita la convalida TypeScript.", + "typescript.format.enable": "Abilita/Disabilita il formattatore TypeScript predefinito.", + "javascript.format.enable": "Abilita/Disabilita il formattatore JavaScript predefinito.", + "format.insertSpaceAfterCommaDelimiter": "Consente di definire la gestione dello spazio dopo una virgola di delimitazione6", + "format.insertSpaceAfterConstructor": "Definisce la gestione dello spazio dopo la parola chiave constructor. Richiede TypeScript >= 2.3.0.", + "format.insertSpaceAfterSemicolonInForStatements": " Consente di definire la gestione dello spazio dopo un punto e virgola in un'istruzione for.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Consente di definire la gestione dello spazio dopo un operatore binario.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Consente di definire la gestione dello spazio dopo le parole chiave in un'istruzione del flusso di controllo.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Consente di definire la gestione dello spazio dopo la parola chiave function per funzioni anonime.", + "format.insertSpaceBeforeFunctionParenthesis": "Consente di definire la gestione dello spazio prima delle parentesi dell'argomento della funzione. Richiede TypeScript >= 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Consente di definire la gestione dello spazio dopo le parentesi tonde di apertura e di chiusura non vuote.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Consente di definire la gestione dello spazio dopo le parentesi quadre di apertura e di chiusura non vuote.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Consente di definire la gestione dello spazio dopo l'apertura e prima della chiusura di parentesi graffe non vuote. Richiede TypeScript >= 2.3.0.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Consente di definire la gestione dello spazio dopo la parentesi graffa iniziale e prima della parentesi graffa finale della stringa del modello. Richiede TypeScript >= 2.0.6", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Consente di definire la gestione dello spazio dopo la parentesi graffa iniziale e prima della parentesi graffa finale dell'espressione JSX. Richiede TypeScript >= 2.0.6", + "format.insertSpaceAfterTypeAssertion": "Definisce la gestione dello spazio dopo le asserzioni di tipo in TypeScript. Richiede TypeScript >= 2.4.", + "format.placeOpenBraceOnNewLineForFunctions": "Consente di definire se una parentesi graffa di apertura viene o meno inserita su una riga per le funzioni.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Consente di definire se una parentesi graffa di apertura viene o meno inserita su una riga per i blocchi di controllo.", + "javascript.validate.enable": "Abilita/Disabilita la convalida JavaScript.", + "typescript.goToProjectConfig.title": "Passa a Configurazione progetto", + "javascript.goToProjectConfig.title": "Passa a Configurazione progetto", + "javascript.referencesCodeLens.enabled": "Abilita/disabilita riferimenti CodeLens nei file JavaScript.", + "typescript.referencesCodeLens.enabled": "Abilita/disabilita riferimenti CodeLens nei file TypeScript. Richiede TypeScript >= 2.0.6.", + "typescript.implementationsCodeLens.enabled": "Abilita/Disabilita le finestre CodeLens per le implementazioni. Richiede una versione di TypeScript uguale o successiva alla 2.2.0.", + "typescript.openTsServerLog.title": "Apri il log del server TypeScript", + "typescript.restartTsServer": "Riavvia server TS", + "typescript.selectTypeScriptVersion.title": "Seleziona la versione di TypeScript", + "typescript.reportStyleChecksAsWarnings": "Evidenzia i controlli di stile come warning", + "jsDocCompletion.enabled": "Abilita/Disabilita commenti automatici JSDoc", + "javascript.implicitProjectConfig.checkJs": "Abilita/disabilita il controllo semantico di file JavaScript. File jsconfig.json o tsconfig.json esistenti sovrascrivono su questa impostazione. Richiede TypeScript >= 2.3.1.", + "typescript.npm": "Specifica il percorso dell'eseguibile NPM utilizzato per l'acquisizione automatica delle definizioni di tipi. Richiede TypeScript >= 2.3.4.", + "typescript.check.npmIsInstalled": "Controlla se NPM è installato per l'acquisizione automatica delle definizioni di tipi", + "javascript.nameSuggestions": "Abilita/disabilita l'inclusione di nomi univoci dal file negli elenchi di suggerimento di JavaScript.", + "typescript.tsc.autoDetect": "Controlla l'auto-rilevazione di attività di tsc. 'off' disabilita questa funzionalità. 'build' crea solo attività di singola compilazione esecuzione. 'watch' crea solo attività di compilazione e controllo. 'on' crea attività sia di tipo 'build' che 'watch'. Il valore predefinito è 'on'.", + "typescript.problemMatchers.tsc.label": "Problemi TypeScript", + "typescript.problemMatchers.tscWatch.label": "Problemi TypeScript (modalità espressione di controllo)", + "typescript.quickSuggestionsForPaths": "Abilita/disabilita i suggerimenti rapidi quando si digita un percorso di importazione.", + "typescript.locale": "Assegna le impostazioni internazionali utilizzate per riportare errori TypeScript. Richiede TypeScript > = 2.6.0. Il valore predefinito 'null' utilizza le impostazioni internazionali di VS Code.", + "javascript.implicitProjectConfig.experimentalDecorators": "Abilita/disabilita 'experimentalDecorators' per i file JavaScript che non fanno parte di un progetto. File jsconfig.json o tsconfig.json esistenti ignorano questa impostazione. Richiede TypeScript >= 2.3.1.", + "typescript.autoImportSuggestions.enabled": "Abilita/Disabilita suggerimenti importazione automatica. Richiede una versione di TypeScript >= 2.6.1", + "typescript.experimental.syntaxFolding": "Abilita/disabilita i marcatori di folding con riconoscimento della sintassi.", + "taskDefinition.tsconfig.description": "File tsconfig che definisce la compilazione TS.", + "javascript.suggestionActions.enabled": "Abilita/disabilita la diagnostica dei suggerimenti per i file JavaScript nell'editor. Richiede TypeScript >= 2.8.", + "typescript.suggestionActions.enabled": "Abilita/disabilita la diagnostica dei suggerimenti per i file TypeScript nell'editor. Richiede TypeScript >= 2.8." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/base/node/zip.i18n.json b/i18n/ita/src/vs/base/node/zip.i18n.json index d47c972382..182a37bdf0 100644 --- a/i18n/ita/src/vs/base/node/zip.i18n.json +++ b/i18n/ita/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Operazione incompleta. Sono state estratte {0} di {1} voci", "notFound": "{0} non è stato trovato all'interno del file ZIP." } \ No newline at end of file diff --git a/i18n/ita/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/ita/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 0815df049c..6bec92cf6a 100644 --- a/i18n/ita/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/ita/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "Anteprima in GitHub", "loadingData": "Caricamento dei dati...", + "rateLimited": "Superato il limite di query GitHub. Attendere prego.", "similarIssues": "Problemi simili", "open": "Apri", "closed": "Chiuso", - "noResults": "Non sono stati trovati risultati", + "noSimilarIssues": "Nessun problema simile trovato", "settingsSearchIssue": "Problema di ricerca impostazioni", "bugReporter": "Segnalazione bug", - "performanceIssue": "Problema di prestazioni", "featureRequest": "Richiesta di funzionalità", + "performanceIssue": "Problema di prestazioni", "stepsToReproduce": "Passi da riprodurre", "bugDescription": "Indicare i passaggi necessari per riprodurre il problema in modo affidabile. Includere i risultati effettivi e quelli previsti. È supportato il linguaggio Markdown per GitHub. Sarà possibile modificare il problema e aggiungere screenshot quando verrà visualizzato in anteprima in GitHub.", "performanceIssueDesciption": "Quando si è verificato questo problema di prestazioni? All'avvio o dopo una serie specifiche di azioni? È supportato il linguaggio Markdown per GitHub. Sarà possibile modificare il problema e aggiungere screenshot quando verrà visualizzato in anteprima in GitHub.", diff --git a/i18n/ita/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/ita/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index d848daa163..1ab03145d1 100644 --- a/i18n/ita/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/ita/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Completare il modulo in lingua inglese.", "issueTypeLabel": "Questo è un", + "issueSourceLabel": "File in", + "vscode": "Visual Studio Code", + "extension": "Un'estensione", + "disableExtensionsLabelText": "Provare a riprodurre il problema dopo {0}. Se il problema si verifica solo quando le estensioni sono attive, è probabilmente un problema legato ad un'estensione.", + "disableExtensions": "disabilitando tutte le estensioni e ricaricando la finestra", + "chooseExtension": "Estensione", "issueTitleLabel": "Titolo", "issueTitleRequired": "Immettere un titolo.", "titleLengthValidation": "Il titolo è troppo lungo.", @@ -18,13 +24,6 @@ "extensions": "Estensioni personali", "searchedExtensions": "Estensioni cercate", "settingsSearchDetails": "Dettagli ricerca impostazioni", - "tryDisablingExtensions": "Il problema è riproducibile quando le estensioni sono disabilitate?", - "yes": "Sì", - "no": "No", - "disableExtensionsLabelText": "Provare a riprodurre il problema dopo {0}.", - "disableExtensions": "disabilitando tutte le estensioni e ricaricando la finestra", - "showRunningExtensionsLabelText": "Se si sospetta che il problema sia relativo all'estensione, {0} per segnalare il problema.", - "showRunningExtensions": "visualizzare tutte le estensioni in esecuzione", "details": "Immettere i dettagli.", "loadingData": "Caricamento dei dati..." } \ No newline at end of file diff --git a/i18n/ita/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/ita/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..312cd92898 --- /dev/null +++ b/i18n/ita/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "% CPU", + "memory": "Memoria (MB)", + "pid": "PID", + "name": "Nome", + "killProcess": "Arresta il processo", + "forceKillProcess": "Arresto forzato del processo" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/code/electron-main/menus.i18n.json b/i18n/ita/src/vs/code/electron-main/menus.i18n.json index e90257e9c5..aa6cd54d39 100644 --- a/i18n/ita/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/ita/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "Punto di interruzione &&condizionale...", "miColumnBreakpoint": "Punto di interruzione &&colonna", "miFunctionBreakpoint": "Punto di interruzione &&funzione...", + "miLogPoint": "&&Punto di registrazione...", "miNewBreakpoint": "&&Nuovo punto di interruzione", "miEnableAllBreakpoints": "Abilita tutti i punti di interruzione", "miDisableAllBreakpoints": "Disabilita tutti i &&punti di interruzione", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Unisci tutte le finestre", "miToggleDevTools": "&&Attiva/Disattiva strumenti di sviluppo", "miAccessibilityOptions": "&&Opzioni accessibilità", + "miOpenProcessExplorerer": "Apri &&Process Explorer", "miReportIssue": "&&Segnala problema", "miWelcome": "&&Benvenuti", "miInteractivePlayground": "Playground &&interattivo", diff --git a/i18n/ita/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/ita/src/vs/editor/browser/widget/diffReview.i18n.json index c11014d41d..6b6ca5f9c5 100644 --- a/i18n/ita/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/ita/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Chiudi", - "header": "Differenza {0} di {1}: originali {2}, {3} righe, modificate {4}, righe {5}", + "no_lines": "nessuna linea", + "one_line": "1 linea", + "more_lines": "{0} linee", + "header": "Differenza {0} di {1}: originale {2}, {3}, modificate {4}, {5}", "blankLine": "vuota", "equalLine": "originali {0}, modificate {1}: {2}", "insertLine": "+ modificate {0}: {1}", diff --git a/i18n/ita/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/ita/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..9f68decbcc --- /dev/null +++ b/i18n/ita/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "Il numero di cursori è stato limitato a {0}." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json index b864bc800a..a4c0ee614a 100644 --- a/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "I numeri di riga vengono visualizzati come numeri assoluti.", "lineNumbers.relative": "I numeri di riga vengono visualizzati come distanza in linee alla posizione del cursore.", "lineNumbers.interval": "I numeri di riga vengono visualizzati ogni 10 righe.", - "lineNumbers": "Controlla la visualizzazione dei numeri di riga. I valori possibili sono 'on', 'off', 'relativi' ed 'intervallo'.", + "lineNumbers": "Controlla la visualizzazione dei numeri di riga.", "rulers": "Mostra righelli verticali dopo un certo numero di caratteri a spaziatura fissa. Utilizza più valori per più righelli. Nessun righello viene disegnati se la matrice è vuota", "wordSeparators": "Caratteri che verranno usati come separatori di parola quando si eseguono operazioni o spostamenti correlati a parole", "tabSize": "Il numero di spazi corrispondenti ad un carattere Tab. Questa impostazione viene sottoposta a override in base al contenuto dei file quando 'editor.detectIndentation' è 'on'.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Controlla se l'editor scorrerà oltre l'ultima riga", "smoothScrolling": "Controlla se per lo scorrimento dell'editor verrà usata un'animazione.", "minimap.enabled": "Controlla se la mini mappa è visualizzata", - "minimap.side": "Definisce il lato in cui viene mostrata la mini mappa. I possibili valori sono 'destra' o 'sinistra'", - "minimap.showSlider": "Controlla se il dispositivo di scorrimento della mini mappa viene nascosto automaticamente. I valori possibili sono 'always' e 'mouseover'", + "minimap.side": "Definisce il lato in cui eseguire il rendering della mini mappa.", + "minimap.showSlider": "Controlla se lo slider della mini mappa viene nascosto automaticamente.", "minimap.renderCharacters": "Esegue il rendering dei caratteri effettivi di una riga (in contrapposizione ai blocchi colore)", "minimap.maxColumn": "Limita la larghezza della mini mappa in modo da eseguire il rendering al massimo di un certo numero di colonne", "find.seedSearchStringFromSelection": "Controlla se inizializzare la stringa di ricerca nel Widget Trova con il testo selezionato nell'editor", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Rappresenta il tasto 'Control' (ctrl) su Windows e Linux e il tasto 'Comando' (cmd) su OSX.", "multiCursorModifier.alt": "Rappresenta il tasto 'Alt' su Windows e Linux e il tasto 'Opzione' su OSX.", "multiCursorModifier": "Il modificatore da utilizzare per aggiungere molteplici cursori con il mouse. 'ctrlCmd' rappresenta il tasto 'Control' su Windows e Linux e il tasto 'Comando' su OSX. I gesti del mouse Vai a definizione e Apri il Link si adatteranno in modo da non entrare in conflitto con il modificatore multi-cursore.", + "multiCursorMergeOverlapping": "Unire i cursori multipli se sovrapposti.", "quickSuggestions.strings": "Abilita i suggerimenti rapidi all'interno di stringhe.", "quickSuggestions.comments": "Abilita i suggerimenti rapidi all'interno di commenti.", "quickSuggestions.other": "Abilita i suggerimenti rapidi all'esterno di stringhe e commenti.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Controlla se l'editor deve evidenziare le occorrenze di simboli semantici", "overviewRulerLanes": "Controlla il numero di effetti che possono essere visualizzati nella stessa posizione nel righello delle annotazioni", "overviewRulerBorder": "Controlla se deve essere disegnato un bordo intorno al righello delle annotazioni.", - "cursorBlinking": "Controlla lo stile di animazione del cursore. I valori possibili sono: 'blink', 'smooth', 'phase', 'expand' e 'solid'", + "cursorBlinking": "Controllo dello stile di animazione del cursore.", "mouseWheelZoom": "Ingrandisce il carattere dell'editor quando si usa la rotellina del mouse e si tiene premuto CTRL", "cursorStyle": "Controlla lo stile del cursore. I valori accettati sono 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'", "cursorWidth": "Controlla la larghezza del cursore quando editor.cursorSyle è impostato a 'line'", @@ -86,8 +87,11 @@ "renderControlCharacters": "Controlla se l'editor deve eseguire il rendering dei caratteri di controllo", "renderIndentGuides": "Controlla se l'editor deve eseguire il rendering delle guide con rientro", "renderLineHighlight": "Consente di controllare in che modo l'editor deve eseguire il rendering dell'evidenziazione di riga corrente. Le opzioni possibili sono 'none', 'gutter', 'line' e 'all'.", - "codeLens": "Controlla se nell'editor sono visualizzate le finestre di CodeLens", + "codeLens": "Controlla se nell'editor è visualizzato CodeLens", "folding": "Controlla se per l'editor è abilitata la riduzione del codice", + "foldingStrategyAuto": "Se disponibile, usa una strategia di riduzione specifica del linguaggio, altrimenti esegue il fallback alla strategia di base per i rientri.", + "foldingStrategyIndentation": "Usa sempre la strategia di riduzione basata sui rientri", + "foldingStrategy": "Controlla in che modo vengono calcolati gli intervalli di riduzione. Con 'auto' viene usata l'eventuale strategia di riduzione specifica disponibile. Con 'indentation' viene usata forzatamente la strategia di riduzione basata sui rientri.", "showFoldingControls": "Controlla se i controlli di riduzione sul margine della barra di scorrimento sono automaticamente nascosti.", "matchBrackets": "Evidenzia le parentesi corrispondenti quando se ne seleziona una.", "glyphMargin": "Controlla se l'editor deve eseguire il rendering del margine verticale del glifo. Il margine del glifo viene usato principalmente per il debug.", @@ -102,8 +106,12 @@ "links": "Controlla se l'editor deve individuare i collegamenti e renderli cliccabili", "colorDecorators": "Controlla se l'editor deve eseguire il rendering del selettore di colore e degli elementi Decorator di tipo colore inline.", "codeActions": "Abilita il codice azione lightbulb", + "codeActionsOnSave.organizeImports": "Eseguire l'organizzazione degli Imports durante il salvataggio?", + "codeActionsOnSave": "Tipi di azione codice da eseguire durante il salvataggio.", + "codeActionsOnSaveTimeout": "Timeout per le azioni codice eseguite durante il salvataggio.", "selectionClipboard": "Controlla se gli appunti primari di Linux devono essere supportati.", "sideBySide": "Controlla se l'editor diff mostra le differenze affiancate o incorporate", "ignoreTrimWhitespace": "Controlla se l'editor diff mostra come differenze le modifiche relative a spazi vuoti iniziali e finali", + "largeFileOptimizations": "Gestione speciale dei file di grandi dimensioni per disabilitare alcune funzionalità che fanno un uso intensivo della memoria.", "renderIndicators": "Consente di controllare se l'editor diff mostra gli indicatori +/- per le modifiche aggiunte/rimosse" } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json index b8d72c60ab..3ca3c86bce 100644 --- a/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,8 +14,10 @@ "editorCursorBackground": "Colore di sfondo del cursore editor. Permette di personalizzare il colore di un carattere quando sovrapposto da un blocco cursore.", "editorWhitespaces": "Colore dei caratteri di spazio vuoto nell'editor.", "editorIndentGuides": "Colore delle guide per i rientri dell'editor.", + "editorActiveIndentGuide": "Colore delle guide di indentazione dell'editor attivo", "editorLineNumbers": "Colore dei numeri di riga dell'editor.", "editorActiveLineNumber": "Colore dei numeri per la riga attiva dell'editor", + "deprecatedEditorActiveLineNumber": "Id è deprecato. In alternativa utilizzare 'editorLineNumber.activeForeground'.", "editorRuler": "Colore dei righelli dell'editor.", "editorCodeLensForeground": "Colore primo piano delle finestre di CodeLens dell'editor", "editorBracketMatchBackground": "Colore di sfondo delle parentesi corrispondenti", @@ -28,7 +30,9 @@ "warningBorder": "Colore del bordo degli squggle di avviso nell'editor.", "infoForeground": "Colore primo piano degli squiggle di informazione nell'editor", "infoBorder": "Colore del bordo degli squiggle di informazione nell'editor", - "overviewRulerRangeHighlight": "Colore del marcatore del righello delle annotazioni per le evidenziazioni degli intervalli.", + "hintForeground": "Colore primo piano degli squiggle di suggerimento nell'editor.", + "hintBorder": "Colore del bordo degli squiggle di suggerimento nell'editor.", + "overviewRulerRangeHighlight": "Colore del marcatore righello panoramica per evidenziazione intervalli. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", "overviewRuleError": "Colore del marcatore del righello delle annotazioni per gli errori.", "overviewRuleWarning": "Colore del marcatore del righello delle annotazioni per gli avvisi.", "overviewRuleInfo": "Colore del marcatore del righello delle annotazioni per i messaggi di tipo informativo." diff --git a/i18n/ita/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/ita/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..b1dfa12d60 --- /dev/null +++ b/i18n/ita/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Mostra correzioni ({0})", + "quickFix": "Mostra correzioni", + "quickfix.trigger.label": "Correzione rapida...", + "editor.action.quickFix.noneMessage": "Azioni codice non disponibili", + "refactor.label": "Effettua refactoring...", + "editor.action.refactor.noneMessage": "Refactoring non disponibili", + "source.label": "Azione origine...", + "editor.action.source.noneMessage": "Azioni origine non disponibili", + "organizeImports.label": "Organizza gli Imports", + "editor.action.organize.noneMessage": "Azioni di organizzazione Imports non disponibili" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/find/findController.i18n.json b/i18n/ita/src/vs/editor/contrib/find/findController.i18n.json index 71eae775d8..cb8d2e1af9 100644 --- a/i18n/ita/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Trova", + "startFindWithSelectionAction": "Trova con selezione", "findNextMatchAction": "Trova successivo", "findPreviousMatchAction": "Trova precedente", "nextSelectionMatchFindAction": "Trova selezione successiva", diff --git a/i18n/ita/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/ita/src/vs/editor/contrib/format/formatActions.i18n.json index 72fa4fc3ce..4aac3989f8 100644 --- a/i18n/ita/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "Sono state apportate {0} modifiche di formattazione tra le righe {1} e {2}", "no.provider": "Non c'è alcun formattatore installato per i file '{0}'.", "formatDocument.label": "Formatta documento", - "formatSelection.label": "Formatta selezione" + "no.documentprovider": "Non è installato alcun formattatore di documenti per i file '{0}'.", + "formatSelection.label": "Formatta selezione", + "no.selectionprovider": "Non è installato alcun formattatore di selezione per i file '{0}'." } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 5c66455951..5f596c304d 100644 --- a/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Vai al problema successivo (Errore, Avviso, Informazioni)", - "markerAction.previous.label": "Vai al problema precedente (Errore, Avviso, Info)", - "editorMarkerNavigationError": "Colore per gli errori del widget di spostamento tra marcatori dell'editor.", - "editorMarkerNavigationWarning": "Colore per gli avvisi del widget di spostamento tra marcatori dell'editor.", - "editorMarkerNavigationInfo": "Colore delle informazioni del widget di navigazione marcatori dell'editor.", - "editorMarkerNavigationBackground": "Sfondo del widget di spostamento tra marcatori dell'editor." + "markerAction.previous.label": "Vai al problema precedente (Errore, Avviso, Info)" } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/ita/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..a69e81d71e --- /dev/null +++ b/i18n/ita/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Colore per gli errori del widget di spostamento tra marcatori dell'editor.", + "editorMarkerNavigationWarning": "Colore per gli avvisi del widget di spostamento tra marcatori dell'editor.", + "editorMarkerNavigationInfo": "Colore delle informazioni del widget di navigazione marcatori dell'editor.", + "editorMarkerNavigationBackground": "Sfondo del widget di spostamento tra marcatori dell'editor." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/links/links.i18n.json b/i18n/ita/src/vs/editor/contrib/links/links.i18n.json index 939e3f31f5..3c943a8412 100644 --- a/i18n/ita/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "CTRL + clic per seguire il collegamento", "links.command.mac": "Cmd + click per eseguire il comando", "links.command": "Ctrl + clic per eseguire il comando", + "links.navigate.al.mac": "Opzione + clic per seguire il collegamento", "links.navigate.al": "Alt + clic per seguire il collegamento", + "links.command.al.mac": "Opzione + clic per eseguire il comando", "links.command.al": "Alt + clic per eseguire il comando", "invalid.url": "Non è stato possibile aprire questo collegamento perché il formato non è valido: {0}", "missing.url": "Non è stato possibile aprire questo collegamento perché manca la destinazione.", diff --git a/i18n/ita/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/ita/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..c77490ad4d --- /dev/null +++ b/i18n/ita/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Non è possibile modificare nell'editor di sola lettura" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/ita/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 6fdcf1c016..ced7924196 100644 --- a/i18n/ita/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Colore di sfondo dell'editor di visualizzazioni rapide.", "peekViewEditorGutterBackground": "Colore di sfondo della barra di navigazione nell'editor visualizzazione rapida.", "peekViewResultsMatchHighlight": "Colore dell'evidenziazione delle corrispondenze nell'elenco risultati della visualizzazione rapida.", - "peekViewEditorMatchHighlight": "Colore dell'evidenziazione delle corrispondenze nell'editor di visualizzazioni rapide." + "peekViewEditorMatchHighlight": "Colore dell'evidenziazione delle corrispondenze nell'editor di visualizzazioni rapide.", + "peekViewEditorMatchHighlightBorder": "Bordo dell'evidenziazione delle corrispondenze nell'editor di visualizzazioni rapide." } \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/ita/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..af44bbbb9e --- /dev/null +++ b/i18n/ita/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Domenica", + "Monday": "Lunedì", + "Tuesday": "Martedì", + "Wednesday": "Mercoledì", + "Thursday": "Giovedì", + "Friday": "Venerdì", + "Saturday": "Sabato", + "SundayShort": "Dom", + "MondayShort": "Lun", + "TuesdayShort": "Mar", + "WednesdayShort": "Mer", + "ThursdayShort": "Gio", + "FridayShort": "Ven", + "SaturdayShort": "Sab", + "January": "Gennaio", + "February": "Febbraio", + "March": "Marzo", + "April": "Aprile", + "May": "Maggio", + "June": "Giugno", + "July": "Luglio", + "August": "Agosto", + "September": "Settembre", + "October": "Ottobre", + "November": "Novembre", + "December": "Dicembre", + "JanuaryShort": "Gen", + "FebruaryShort": "Feb", + "MarchShort": "Mar", + "AprilShort": "Apr", + "MayShort": "Mag", + "JuneShort": "Giu", + "JulyShort": "Lug", + "AugustShort": "Ago", + "SeptemberShort": "Set", + "OctoberShort": "Ott", + "NovemberShort": "Nov", + "DecemberShort": "Dic" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 42e92cd644..e0d2924969 100644 --- a/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -10,8 +10,8 @@ "wordHighlightStrong": "Colore di sfondo di un simbolo durante l'accesso in scrittura, per esempio durante la scrittura di una variabile. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "wordHighlightBorder": "Colore del bordo di un simbolo durante l'accesso in lettura, ad esempio durante la lettura di una variabile.", "wordHighlightStrongBorder": "Colore del bordo di un simbolo durante l'accesso in scrittura, ad esempio durante la scrittura in una variabile.", - "overviewRulerWordHighlightForeground": "Colore del marcatore del righello delle annotazioni per le evidenziazioni dei simboli.", - "overviewRulerWordHighlightStrongForeground": "Colore del marcatore del righello delle annotazioni per le evidenziazioni dei simboli di accesso in scrittura.", + "overviewRulerWordHighlightForeground": "Colore del marcatore righello panoramica per evidenziazione simboli. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", + "overviewRulerWordHighlightStrongForeground": "Colore del marcatore righello panoramica per evidenziazione simboli con accesso in scrittura. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", "wordHighlight.next.label": "Vai al prossimo simbolo evidenziato", "wordHighlight.previous.label": "Vai al precedente simbolo evidenziato" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/ita/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..6b01687be1 --- /dev/null +++ b/i18n/ita/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 altro file non visualizzato", + "moreFiles": "...{0} altri file non visualizzati" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/ita/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..37c77254e7 --- /dev/null +++ b/i18n/ita/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Annulla" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/environment/node/argv.i18n.json b/i18n/ita/src/vs/platform/environment/node/argv.i18n.json index 786bca266c..d91217d538 100644 --- a/i18n/ita/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/ita/src/vs/platform/environment/node/argv.i18n.json @@ -22,15 +22,15 @@ "showVersions": "Mostra le versioni delle estensioni installate, quando si usa --list-extension.", "installExtension": "Installa un'estensione.", "uninstallExtension": "Disinstalla un'estensione.", - "experimentalApis": "Abilita funzionalità di API proposte per un'estensione specifica.", + "experimentalApis": "Abilita funzionalità di API proposte per un'estensione.", "verbose": "Visualizza l'output dettagliato (implica --wait).", "log": "Livello di logging da utilizzare. Il valore predefinito è 'info'. I valori consentiti sono 'critical, 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Stampare le informazioni di utilizzo e diagnostica di processo.", "performance": "Eseguire l'avvio con il comando 'Developer: Startup Performance' abilitato.", "prof-startup": "Esegui il profiler della CPU durante l'avvio", "disableExtensions": "Disabilita tutte le estensioni installate.", - "inspect-extensions": "Consentire il debug e profiling delle estensioni. Controllare gli strumenti di sviluppo per l'uri di connessione.", - "inspect-brk-extensions": "Consentire il debug e profiling delle estensioni con l'host di estensione in pausa dopo inizio. Controllare gli strumenti di sviluppo per l'uri di connessione.", + "inspect-extensions": "Consente il debug e profiling delle estensioni. Controllare gli strumenti di sviluppo per la URI di connessione.", + "inspect-brk-extensions": "Consente di eseguire debug e profilatura delle estensioni con l'host dell'estensione messo in pausa dopo l'avvio. Controllare gli strumenti di sviluppo per l'URI di connessione.", "disableGPU": "Disabilita l'accelerazione hardware della GPU.", "uploadLogs": "Caricamento dei log della sessione corrente verso un punto di comunicazione sicuro.", "maxMemory": "Dimensione massima della memoria per una finestra (in Mbytes).", diff --git a/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index a50f080797..fd9808f2dd 100644 --- a/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Estensione non valida: package.json non è un file JSON.", + "incompatible": "Impossibile installare l'estensione '{0}' in quanto non è compatibile con VS Code '{1}'.", "restartCode": "Riavviare Code prima di reinstallare {0}.", "installingOutdatedExtension": "Una versione più recente di questa estensione è già installata. Vuoi eseguire l'override di questa con la versione precedente?", "override": "Eseguire l'override", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Errore durante l'installazione delle dipendenze. {0}", "MarketPlaceDisabled": "Il Marketplace non è abilitato", "removeError": "Errore durante la rimozione dell'estensione: {0}. Chiudere e riavviare VS Code prima di riprovare.", - "Not Market place extension": "Solo le Estensioni del Marketplace possono essere reinstallate", + "Not a Marketplace extension": "Solo le Estensioni del Marketplace possono essere reinstallate", "notFoundCompatible": "Impossibile installare '{0}'; non è presente alcuna versione compatibile con VS Code '{1}'.", "malicious extension": "Non è possibile installare l'estensione poiché è stata segnalata come problematica.", "notFoundCompatibleDependency": "Impossibile installare perché non è stata trovata l'estensione dipendente '{0}' compatibile con la versione corrente '{1}' di VS Code.", "quitCode": "Impossibile installare l'estensione. Riavviare VS Code prima di procedere ad un nuovo setup.", "exitCode": "Impossibile installare l'estensione. Riavviare VS Code prima di procedere ad un nuovo setup.", + "renameError": "Errore sconosciuto durante la ridenominazione di {0} in {1}", "uninstallDependeciesConfirmation": "Disinstallare solo '{0}' o anche le relative dipendenze?", - "uninstallOnly": "Solo", - "uninstallAll": "Tutto", + "uninstallOnly": "Solo Estensioni", + "uninstallAll": "Disinstalla tutti", "uninstallConfirmation": "Disinstallare '{0}'?", "ok": "OK", "singleDependentError": "Non è possibile disinstallare l'estensione '{0}'. L'estensione '{1}' dipende da tale estensione.", diff --git a/i18n/ita/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/ita/src/vs/platform/extensions/node/extensionValidator.i18n.json index 3078618298..5c31426523 100644 --- a/i18n/ita/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/ita/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Non è stato possibile analizzare il valore {0} di `engines.vscode`. Usare ad esempio: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x e così via.", + "versionSyntax": "Non è stato possibile analizzare il valore {0} di `engines.vscode`. Usare ad esempio: ^1.22.0, ^1.22.x e così via.", "versionSpecificity1": "La versione specificata in `engines.vscode` ({0}) non è abbastanza specifica. Per le versioni di vscode precedenti alla 1.0.0, definire almeno le versioni principale e secondaria desiderate, ad esempio ^0.10.0, 0.10.x, 0.11.0 e così via.", "versionSpecificity2": "La versione specificata in `engines.vscode` ({0}) non è abbastanza specifica. Per le versioni di vscode successive alla 1.0.0, definire almeno la versione principale desiderata, ad esempio ^1.10.0, 1.10.x, 1.x.x, 2.x.x e così via.", "versionMismatch": "L'estensione non è compatibile con Visual Studio Code {0}. Per l'estensione è richiesto: {1}." diff --git a/i18n/ita/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/ita/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 59968761c5..cfc5929845 100644 --- a/i18n/ita/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/ita/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "L'installazione di {0} sembra danneggiata. Reinstallare.", "integrity.moreInformation": "Altre informazioni", - "integrity.dontShowAgain": "Non visualizzare più questo messaggio", - "integrity.prompt": "L'installazione di {0} sembra danneggiata. Reinstallare." + "integrity.dontShowAgain": "Non visualizzare più questo messaggio" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/ita/src/vs/platform/issue/electron-main/issueService.i18n.json index 90bcf04698..9f56186d6c 100644 --- a/i18n/ita/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/ita/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Rapporti di issue" + "issueReporter": "Rapporti di issue", + "processExplorer": "Esplora processi" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/list/browser/listService.i18n.json b/i18n/ita/src/vs/platform/list/browser/listService.i18n.json index 0da9f933b9..29755f37a4 100644 --- a/i18n/ita/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/ita/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Modificatore da usare per aggiungere un elemento in alberi ed elenchi a una selezione multipla con il mouse (ad esempio editor aperti e visualizzazione Gestione controllo servizi in Esplora risorse). 'ctrlCmd' rappresenta il tasto 'CTRL' in Windows e Linux e il tasto 'Cmd' in OSX. I gesti del mouse Apri lateralmente, se supportati, si adatteranno in modo da non entrare in conflitto con il modificatore di selezione multipla.", "openMode.singleClick": "Apre elementi facendo un singolo clic col mouse.", "openMode.doubleClick": "Apre elementi facendo doppio clic col mouse.", - "openModeModifier": "Controlla la modalità di apertura degli elementi in alberi ed elenchi con il mouse, se supportata. Impostare su `singleClick` per aprire gli elementi con un unico clic del mouse e `doubleClick` per aprirli solo se viene fatto doppio clic. Per gli elementi padre con elementi figlio negli alberi, questa impostazione controllerà se per espandere l'elemento padre è necessario fare clic una sola volta o fare doppio clic. Tenere presente che alcuni alberi ed elenchi potrebbero scegliere di ignorare questa impostazione se non è applicabile. " + "openModeModifier": "Controlla la modalità di apertura degli elementi in alberi ed elenchi con il mouse, se supportata. Impostare su `singleClick` per aprire gli elementi con un unico clic del mouse e `doubleClick` per aprirli solo se viene fatto doppio clic. Per gli elementi padre con elementi figlio negli alberi, questa impostazione controllerà se per espandere l'elemento padre è necessario fare clic una sola volta o fare doppio clic. Tenere presente che alcuni alberi ed elenchi potrebbero scegliere di ignorare questa impostazione se non è applicabile. ", + "horizontalScrolling setting": "Controlla se gli alberi supportano lo scorrimento orizzontale in workbench." } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/markers/common/markers.i18n.json b/i18n/ita/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..f585e5046c --- /dev/null +++ b/i18n/ita/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Errore", + "sev.warning": "Avviso", + "sev.info": "Informazioni" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json index 1933e084b3..f7f5fc1552 100644 --- a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "Colore del bordo delle regioni con lo stesso contenuto della selezione.", "editorFindMatch": "Colore della corrispondenza di ricerca corrente.", "findMatchHighlight": "Colore degli altri risultati della ricerca. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", - "findRangeHighlight": "Colore dell'intervallo limite della ricerca. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "findRangeHighlight": "Colore dell'intervallo di limite della ricerca. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", "editorFindMatchBorder": "Colore del bordo della corrispondenza della ricerca corrente.", "findMatchHighlightBorder": "Colore del bordo delle altre corrispondenze della ricerca.", - "findRangeHighlightBorder": "Colore del bordo dell'intervallo che delimita la ricerca. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", + "findRangeHighlightBorder": "Colore del bordo dell'intervallo di limite della ricerca. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", "hoverHighlight": "Evidenziazione sotto la parola per cui è visualizzata un'area sensibile al passaggio del mouse. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "hoverBackground": "Colore di sfondo dell'area sensibile al passaggio del mouse dell'editor.", "hoverBorder": "Colore del bordo dell'area sensibile al passaggio del mouse dell'editor.", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "Sfondo intestazione modifica in ingresso in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "mergeIncomingContentBackground": "Sfondo contenuto modifica in ingresso in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "mergeCommonHeaderBackground": "Sfondo dell'intestazione dell'antenato comune nei conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", - "mergeCommonContentBackground": "Sfondo del contenuto dell'antenato comune nei conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeCommonContentBackground": "Sfondo del contenuto del predecessore comune in conflitti di merge in line. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", "mergeBorder": "Colore bordo su intestazioni e sulla barra di divisione di conflitti di merge in linea.", "overviewRulerCurrentContentForeground": "Colore primo piano righello panoramica attuale per i conflitti di merge in linea.", "overviewRulerIncomingContentForeground": "Colore primo piano del righello panoramica modifiche in arrivo per i conflitti di merge in linea.", "overviewRulerCommonContentForeground": "Colore primo piano righello panoramica dell'antenato comune per i conflitti di merge in linea.", - "overviewRulerFindMatchForeground": "Colore del marcatore del righello delle annotazioni per le corrispondenze della ricerca.", - "overviewRulerSelectionHighlightForeground": "Colore del marcatore del righello delle annotazioni per le evidenziazioni delle selezioni." + "overviewRulerFindMatchForeground": "Colore del marcatore righello panoramica per trovare corrispondenze. Il colore non deve essere opaco per non nascondere decorazioni sottostanti.", + "overviewRulerSelectionHighlightForeground": "Colore del marcatore righello panoramica per evidenziazione selezioni. Il colore non deve essere opaco per non nascondere decorazioni sottostanti." } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/ita/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..46a4d38868 --- /dev/null +++ b/i18n/ita/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "Consentire all'estensione {0} di aprire l'URL seguente?" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/ita/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..ef90c889f1 --- /dev/null +++ b/i18n/ita/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "ID univoco usato per identificare il contenitore in cui è possibile aggiungere visualizzazioni come contributo usando il punto di aggiunta contributo 'views'", + "vscode.extension.contributes.views.containers.title": "Stringa leggibile usata per il rendering del contenitore", + "vscode.extension.contributes.views.containers.icon": "Percorso dell'icona del contenitore. Le icone, le cui dimensioni sono 24x24, sono centrate in un riquadro le cui dimensioni sono 50x40 e sono caratterizzate dal colore di riempimento 'rgb(215, 218, 224)' o '#d7dae0'. Anche se è accettato qualsiasi tipo di file immagine, per le icone è consigliabile usare il formato SVG.", + "vscode.extension.contributes.viewsContainers": "Aggiunge come contributo contenitori di visualizzazioni all'editor", + "views.container.activitybar": "Aggiunge come contributo contenitori di visualizzazioni alla barra attività", + "test": "Test", + "proposed": "Il contributo 'viewsContainers' è disponibile solo durante l'esecuzione all'esterno dell'ambiente di sviluppo o con l'opzione seguente della riga di comando: --enable-proposed-api {0}", + "requirearray": "i contenitori di visualizzazioni devono essere una matrice", + "requireidstring": "la proprietà `{0}` è obbligatoria e deve essere di tipo `string`. Sono consentiti solo caratteri alfanumerici, '_' e '-'.", + "requirestring": "la proprietà `{0}` è obbligatoria e deve essere di tipo `string`", + "showViewlet": "Mostra {0}", + "view": "Visualizza" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/ita/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index a0411ed6db..a4967723c1 100644 --- a/i18n/ita/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/ita/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "Il nome della visualizzazione. Verrà mostrato", "vscode.extension.contributes.view.when": "Condizione che deve essere vera per mostrare questa visualizzazione", "vscode.extension.contributes.views": "Contribuisce visualizzazioni all'editor", - "views.explorer": "Visualizzazione di esplorazione", - "views.debug": "Visualizzazione Debug", - "locationId.invalid": "'{0}' non è una posizione valida per la visualizzazione", + "views.explorer": "Aggiunge come contributo visualizzazioni al contenitore Esplora risorse nella barra attività", + "views.debug": "Aggiunge come contributo visualizzazioni al contenitore Debug nella barra attività", + "views.scm": "Aggiunge come contributo visualizzazioni al contenitore Gestione controllo servizi nella barra attività", + "views.test": "Aggiunge come contributo visualizzazioni al contenitore Test nella barra attività", + "views.contributed": "Aggiunge come contributo visualizzazioni al contenitore delle visualizzazioni aggiunto come contributo", + "ViewContainerDoesnotExist": "Il contenitore di visualizzazioni '{0}' non esiste e tutte le visualizzazioni registrate verranno aggiunte a 'Esplora risorse'.", "duplicateView1": "Non è possibile registrare più visualizzazioni con stesso ID `{0}` nel percorso `{1}`", "duplicateView2": "Nel percorso `{1}` è già registrata una visualizzazione con ID `{0}` " } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index e63b76f62d..e6654eef53 100644 --- a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Comando Formatta dopo salvataggio interrotto dopo {0} ms", + "codeActionsOnSave.didTimeout": "codeActionsOnSave interrotto dopo {0} ms", + "timeout.onWillSave": "Evento onWillSaveTextDocument interrotto dopo 1750 ms", "saveParticipants": "Esecuzione del salvataggio partecipanti..." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 598b352837..8b6ff1d856 100644 --- a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "editor Webview" + "errorMessage": "Si è verificato un errore durante il tentativo di ripristinare la visualizzazione: {0}" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/ita/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..04c3870e62 --- /dev/null +++ b/i18n/ita/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (estensione)" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 64d6238070..4b668fbef7 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Sposta stato attivo sul gruppo successivo", "openToSide": "Apri lateralmente", "closeEditor": "Chiudi editor", + "closeOneEditor": "Chiudi", "revertAndCloseActiveEditor": "Ripristina e chiudi editor", "closeEditorsToTheLeft": "Chiudi editor a sinistra", "closeAllEditors": "Chiudi tutti gli editor", diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index dfe5104f07..b9722f0b5f 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Se non si utilizza un'utilità per la lettura dello schermo, si prega di impostare 'editor.accessibilitySupport' a \"off\".", "disableTabMode": "Disabilita modalità accessibilità", "gotoLine": "Vai alla riga", - "indentation": "Rientro", + "selectIndentation": "Seleziona rientro", "selectEncoding": "Seleziona codifica", "selectEOL": "Seleziona sequenza di fine riga", "selectLanguageMode": "Seleziona modalità linguaggio", diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 759e983d26..59c356c2cc 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} MB", "sizeGB": "{0} GB", "sizeTB": "{0} TB", - "largeImageError": "Le dimensioni del file dell'immagine sono eccessive (maggiori di 1 MB) per la visualizzazione nell'editor. ", + "largeImageError": "L'immagine non viene visualizzata nell'editor perché è troppo grande ({0}).", "resourceOpenExternalButton": "Aprire l'immagine utilizzando un programma esterno?", - "nativeBinaryError": "Il file non verrà visualizzato nell'editor perché è binario, è molto grande o usa una codifica testo non supportata.", + "nativeFileTooLargeError": "Il file non viene visualizzato nell'editor perché è troppo grande ({0}).", + "nativeBinaryError": "Il file non viene visualizzato nell'editor perché è binario o usa una codifica di testo non supportata.", + "openAsText": "Aprirlo comunque?", "zoom.action.fit.label": "Immagine intera", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index ebe5a4e072..451bfd814f 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Chiudi", "araLabelEditorActions": "Azioni editor" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 2d1037db02..a203ffaf2a 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Nessuna nuova notifica", "notifications": "Notifiche", "notificationsToolbar": "Azioni del centro notifiche", "notificationsList": "Elenco notifiche" diff --git a/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..d77f974321 --- /dev/null +++ b/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (premere 'INVIO' per confermare oppure 'ESC' per annullare)", + "inputModeEntry": "Premere 'INVIO' per confermare l'input oppure 'ESC' per annullare", + "quickInput.countSelected": "{0} selezionati", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..055b435ed7 --- /dev/null +++ b/i18n/ita/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Digitare per ridurre il numero di risultati." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json index aa0ffd70b6..a7402388fe 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Apri recenti...", "quickOpenRecent": "Apertura rapida recenti...", "reportIssueInEnglish": "Segnala problema", + "openProcessExplorer": "Apri Esplora processi", "reportPerformanceIssue": "Segnala problema di prestazioni", "keybindingsReference": "Riferimento per tasti di scelta rapida", "openDocumentationUrl": "Documentazione", diff --git a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json index 4c8e2adfde..8125fcc0d6 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Finestra", "window.openFilesInNewWindow.on": "I file verranno aperti in una nuova finestra", "window.openFilesInNewWindow.off": "I file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva", - "window.openFilesInNewWindow.default": "I file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva a meno che non vengano aperti tramite il pannello Dock o da Finder (solo MacOS)", - "openFilesInNewWindow": "Controlla se i file devono essere aperti in una nuova finestra.\n- default: i file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva a meno che non vengano aperti tramite il pannello Dock o da Finder (solo MacOS)\n- on: i file verranno aperti in una nuova finestra\n- off: i file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva\nNota: possono comunque verificarsi casi in cui questa impostazione viene ignorata, ad esempio quando si usa l'opzione della riga di comando -new-window o -reuse-window.", + "window.openFilesInNewWindow.defaultMac": "I file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva a meno che non vengano aperti tramite il pannello Dock o da Finder", + "window.openFilesInNewWindow.default": "I file verranno aperti in una nuova finestra a meno che non vengano selezionati all'interno dell'applicazione, ad esempio tramite il menu File", + "openFilesInNewWindowMac": "Controlla se i file devono essere aperti in una nuova finestra.\n- default: i file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva a meno che non vengano aperti tramite il pannello Dock o da Finder\n- on: i file verranno aperti in una nuova finestra\n- off: i file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva\nNota: possono comunque verificarsi casi in cui questa impostazione viene ignorata, ad esempio quando si usa l'opzione della riga di comando -new-window o -reuse-window.", + "openFilesInNewWindow": "Controlla se i file devono essere aperti in una nuova finestra.\n- default: i file verranno aperti in una nuova finestra a meno che non vengano selezionati all'interno dell'applicazione, ad esempio tramite il menu File\n- on: i file verranno aperti in una nuova finestra\n- off: i file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva\nNota: possono comunque verificarsi casi in cui questa impostazione viene ignorata, ad esempio quando si usa l'opzione della riga di comando -new-window o -reuse-window.", "window.openFoldersInNewWindow.on": "Le cartelle verranno aperte in una nuova finestra", "window.openFoldersInNewWindow.off": "Le cartelle sostituiranno l'ultima finestra attiva", "window.openFoldersInNewWindow.default": "Le cartelle verranno aperte in una nuova finestra a meno che non si selezioni una cartella dall'interno dell'applicazione, ad esempio tramite il menu File", "openFoldersInNewWindow": "Controlla se le cartelle devono essere aperte in una nuova finestra o sostituire l'ultima finestra attiva.\n- default: le cartelle verranno aperte in una nuova finestra a meno che non si selezioni una cartella dall'interno dell'applicazione, ad esempio tramite il menu File\n- on: le cartelle verranno aperte in una nuova finestra\n- off: le cartelle sostituiranno l'ultima finestra attiva\nNota: possono comunque verificarsi casi in cui questa impostazione viene ignorata, ad esempio quando si usa l'opzione della riga di comando -new-window o -reuse-window.", + "window.openWithoutArgumentsInNewWindow.on": "Apri una nuova finestra vuota", + "window.openWithoutArgumentsInNewWindow.off": "Imposta lo stato attivo sull'ultima istanza in esecuzione attiva", + "openWithoutArgumentsInNewWindow": "Controlla se deve essere aperta una nuova finestra vuota quando si avvia una seconda istanza senza argomento o se è necessario impostare lo stato attivo sull'ultima istanza in esecuzione.\n- on: apre una nuova finestra vuota\n- off: imposta lo stato attivo sull'ultima istanza in esecuzione attiva\nNota: possono comunque verificarsi casi in cui questa impostazione viene ignorata, ad esempio quando si usa l'opzione della riga di comando -new-window o -reuse-window.", "window.reopenFolders.all": "Riapre tutte le finestre.", "window.reopenFolders.folders": "Riapre tutte le cartelle. Le aree di lavoro vuote non verranno ripristinate.", "window.reopenFolders.one": "Riapre l'ultima finestra attiva.", @@ -58,7 +63,7 @@ "restoreWindows": "Controlla la modalità di riapertura delle finestre dopo un riavvio. Selezionare 'none' per iniziare sempre con un'area di lavoro vuota, 'one' per riaprire l'ultima finestra usata, 'folders' per riaprire tutte le finestre con cartelle aperte oppure 'all' per riaprire tutte le finestre dell'ultima sessione.", "restoreFullscreen": "Controlla se una finestra deve essere ripristinata a schermo intero se è stata chiusa in questa modalità.", "zoomLevel": "Consente di modificare il livello di zoom della finestra. Il valore originale è 0 e ogni incremento superiore (ad esempio 1) o inferiore (ad esempio -1) rappresenta un aumento o una diminuzione del 20% della percentuale di zoom. È anche possibile immettere valori decimali per modificare il livello di zoom con maggiore granularità.", - "title": "Controlla il titolo della finestra in base all'editor attivo. Le variabili vengono sostituite in base al contesto:\n${activeEditorShort}: il nome del file (ad es. MyFile.txt)\n${activeEditorMedium}: il percorso del file relativo alla cartella dell'area di lavoro (ad es. myFolder/myFile.txt)\n${activeEditorLong}: il percorso completo del file (ad es. / Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: nome della cartella dell'area di lavoro in cui è contenuto il file (ad es. myFolder)\n${folderPath}: percorso della cartella dell'area di lavoro in cui è contenuto il file (ad es. /Users/Development/myFolder)\n${rootName}: nome dell'area di lavoro (ad es. myFolder o myWorkspace)\n${rootPath}: percorso dell'area di lavoro (ad es. /Users/Development/myWorkspace)\n$(appName): ad esempio VS Code\n${dirty}: indica se l'editor attivo è in fase di modifica\n${separator}: un separatore condizionale (\" - \") che viene visualizzato solo quando circondato da variabili con valori", + "title": "Controlla il titolo della finestra in base all'editor attivo. Le variabili vengono sostituite in base al contesto:\n${activeEditorShort}: nome del file (ad es. MyFile.txt)\n${activeEditorMedium}: percorso del file relativo alla cartella dell'area di lavoro (ad es. myFolder/myFile.txt)\n${activeEditorLong}: percorso completo del file (ad es. / Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: nome della cartella dell'area di lavoro in cui è contenuto il file (ad es. myFolder)\n${folderPath}: percorso della cartella dell'area di lavoro in cui è contenuto il file (ad es. /Users/Development/myFolder)\n${rootName}: nome dell'area di lavoro (ad es. myFolder o myWorkspace)\n${rootPath}: percorso dell'area di lavoro (ad es. /Users/Development/myWorkspace)\n$(appName): ad esempio VS Code\n${dirty}: indica se l'editor attivo è in fase di modifica\n${separator}: separatore condizionale (\" - \") che viene visualizzato solo quando circondato da variabili con valori o testo statico", "window.newWindowDimensions.default": "Apre nuove finestre al centro della schermata.", "window.newWindowDimensions.inherit": "Apre nuove finestre le cui dimensioni sono uguali a quelle dell'ultima finestra attiva.", "window.newWindowDimensions.maximized": "Apre nuove finestre ingrandite a schermo intero.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Se è abilitata, passa automaticamente a un tema a contrasto elevato se Windows usa un tema di questo tipo e al tipo scuro quando non si usa più un tema a contrasto elevato Windows.", "titleBarStyle": "Consente di modificare l'aspetto della barra del titolo della finestra. Per applicare le modifiche, è necessario un riavvio completo.", "window.nativeTabs": "Abilita le finestre di tab per macOS Sierra. La modifica richiede un riavvio. Eventuali personalizzazioni della barra del titolo verranno disabilitate", + "window.smoothScrollingWorkaround": "Abilitare questa soluzione alternativa se lo scorrimento non è più fluido dopo il ripristino di una finestra di VS Code ridotta a icona. Si tratta di una soluzione alternativa per un problema (https://github.com/Microsoft/vscode/issues/13612) in cui si verificano ritardi nello scorrimento in dispositivi con trackpad di precisione, come quelli Surface di Microsoft. Se si abilita questa soluzione alternativa, si potrebbe riscontrare un certo sfarfallio del layout dopo aver ripristinato la finestra ridotta a icona alle dimensioni normali, ma in altre situazioni non produce alcun effetto negativo.", + "window.clickThroughInactive": "Se è abilitata, facendo clic su una finestra inattiva si attiverà non solo la finestra, ma anche l'elemento su cui è posizionato il puntatore del mouse se è selezionabile. Se è disabilitata, facendo clic in un punto qualsiasi in una finestra inattiva verrà attivata solo la finestra e sarà necessario fare di nuovo clic sull'elemento.", "zenModeConfigurationTitle": "Modalità Zen", "zenMode.fullScreen": "Consente di controllare se attivando la modalità Zen anche l'area di lavoro passa alla modalità schermo intero.", "zenMode.centerLayout": "Controlla se attivando la modalità Zen viene centrato anche il layout.", diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 10ffa3fd96..656b814006 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Modifica punto di interruzione...", + "logPoint": "Punto di registrazione", + "breakpoint": "Punto di interruzione", + "editBreakpoint": "Modifica {0}...", + "removeBreakpoint": "Rimuovi {0}", "functionBreakpointsNotSupported": "Punti di interruzione delle funzioni non sono supportati da questo tipo di debug", "functionBreakpointPlaceholder": "Funzione per cui inserire il punto di interruzione", "functionBreakPointInputAriaLabel": "Digitare il punto di interruzione della funzione", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Punto di interruzione non verificato", "functionBreakpointUnsupported": "Punti di interruzione di funzione non supportati da questo tipo di debug", "breakpointDirtydHover": "Punto di interruzione non verificato. Il file è stato modificato. Riavviare la sessione di debug.", + "logBreakpointUnsupported": "Punti di registrazione non supportati da questo tipo di debug", "conditionalBreakpointUnsupported": "Punti di interruzione condizionali non supportati da questo tipo di debug", "hitBreakpointUnsupported": "Sono stati raggiunti punti di interruzione condizionali non supportati da questo tipo di debug" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 7afdadba76..40e143fc40 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Disconnetti", "continueDebug": "Continua", "pauseDebug": "Sospendi", + "terminateThread": "Termina thread", "restartFrame": "Riavvia frame", "removeBreakpoint": "Rimuovi punto di interruzione", "removeAllBreakpoints": "Rimuovi tutti i punti di interruzione", - "enableBreakpoint": "Abilita punto di interruzione", - "disableBreakpoint": "Disabilita punto di interruzione", "enableAllBreakpoints": "Abilita tutti i punti di interruzione", "disableAllBreakpoints": "Disabilita tutti i punti di interruzione", "activateBreakpoints": "Attiva punti di interruzione", "deactivateBreakpoints": "Disattiva punti di interruzione", "reapplyAllBreakpoints": "Riapplica tutti i punti di interruzione", "addFunctionBreakpoint": "Aggiungi punto di interruzione della funzione", - "addConditionalBreakpoint": "Aggiungi punto di interruzione condizionale...", - "editConditionalBreakpoint": "Modifica punto di interruzione...", "setValue": "Imposta valore", "addWatchExpression": "Aggiungi espressione", "editWatchExpression": "Modifica espressione", diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index a2abde15ed..5d0cfad57b 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Debug: Attiva/Disattiva punto di interruzione", "conditionalBreakpointEditorAction": "Debug: Aggiungi Punto di interruzione condizionale...", + "logPointEditorAction": "Debug: Aggiungi punto di registrazione...", "runToCursor": "Esegui fino al cursore", "debugEvaluate": "Debug: Valuta", "debugAddToWatch": "Debug: Aggiungi a espressione di controllo", diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..10c6796d64 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "Messaggio da registrare quando viene raggiunto il punto di interruzione. Le espressioni tra parentesi graffe ({}) vengono interpolate. Premere 'INVIO' per accettare, \"ESC\" per annullare.", + "breakpointWidgetHitCountPlaceholder": "Interrompe quando viene soddisfatta la condizione del numero di passaggi. Premere 'INVIO' per accettare oppure 'ESC' per annullare.", + "breakpointWidgetExpressionPlaceholder": "Interrompe quando l'espressione restituisce true. Premere 'INVIO' per accettare oppure 'ESC' per annullare.", + "expression": "Espressione", + "hitCount": "Numero di passaggi", + "logMessage": "Messaggio di log" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 91f9f8210b..ef6954bebd 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Usare nomi di configurazione univoci.", "app.launch.json.compound.folder": "Nome della cartella in cui si trova l'elemento compounds.", "app.launch.json.compounds.configurations": "Nomi delle configurazioni che verranno avviate per questo elemento compounds.", - "debugNoType": "L'adattatore di debug 'type' non può essere omesso e deve essere di tipo 'string'.", + "debugNoType": "Il \"tipo\" del debugger non può essere omesso e deve essere di tipo \"string\"", "selectDebug": "Seleziona ambiente", "DebugConfig.failed": "Non è possibile creare il file 'launch.json' all'interno della cartella '.vscode' ({0}).", "workspace": "area di lavoro", diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index f4294fe452..bafcaa2f73 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Punto di registrazione", + "breakpoint": "Punto di interruzione", + "removeBreakpoint": "Rimuovi {0}", + "editBreakpoint": "Modifica {0}...", + "disableBreakpoint": "Disabilita {0}", + "enableBreakpoint": "Abilita {0}", "removeBreakpoints": "Rimuovi punti di interruzione", "removeBreakpointOnColumn": "Rimuovi punto di interruzione a colonna {0}", "removeLineBreakpoint": "Rimuovi punto di interruzione riga", @@ -18,5 +24,13 @@ "enableBreakpoints": "Abilita punto di interruzione a colonna {0}", "enableBreakpointOnLine": "Abilita punto di interruzione riga", "addBreakpoint": "Aggiungi punto di interruzione", + "addConditionalBreakpoint": "Aggiungi punto di interruzione condizionale...", + "addLogPoint": "Aggiungi punto di registrazione...", + "breakpointHasCondition": "Per questo {0} è presente un {1} che verrà perso in seguito alla rimozione. Provare invece a disabilitare il {0}.", + "message": "messaggio", + "condition": "condizione", + "removeLogPoint": "Rimuovi {0}", + "disableLogPoint": "Disabilita {0}", + "cancel": "Annulla", "addConfiguration": "Aggiungi configurazione..." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 41f6eb62bb..a19e5c306a 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Mostra errori", "noFolderWorkspaceDebugError": "Non è possibile eseguire il debug del file attivo. Assicurarsi che sia salvato su disco e che sia installata un'estensione di debug per tale tipo di file.", "cancel": "Annulla", - "DebugTaskNotFound": "L'attività di preavvio '{0}' non è stata trovata.", - "taskNotTracked": "Non è possibile tenere traccia del preLaunchTask '{0}'." + "DebugTaskNotFound": "Impossibile trovare l'attività '{0}'.", + "taskNotTracked": "L'attività '{0}' non può essere rintracciata." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index c574f7ef92..fe5b9456c3 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Altre info", - "unableToLaunchDebugAdapter": "Non è possibile avviare l'adattatore di debug da '{0}'.", - "unableToLaunchDebugAdapterNoArgs": "Non è possibile avviare l'adattatore di debug.", - "stoppingDebugAdapter": "{0}. L'adattatore di debug verrà arrestato.", "debugAdapterCrash": "Il processo dell'adattatore di debug è stato terminato in modo imprevisto" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 1380aa486b..1fdf743ec0 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "Il file eseguibile '{0}' dell'adattatore di debug non esiste.", "debugAdapterCannotDetermineExecutable": "Non è possibile determinare il file eseguibile per l'adattatore di debug '{0}'.", - "launch.config.comment1": "Usare IntelliSense per informazioni sui possibili attributi.", - "launch.config.comment2": "Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.", - "launch.config.comment3": "Per ulteriori informazioni, visitare: {0}", - "debugType": "Tipo di configurazione.", - "debugTypeNotRecognised": "Il tipo di debug non è riconosciuto. Assicurarsi di avere un'estensione appropriata per il debug installata e che sia abilitata.", - "node2NotSupported": "\"node2\" non è più supportato. In alternativa, usare \"node\" e impostare l'attributo \"protocol\" su \"inspector\".", - "debugName": "Nome della configurazione. Viene visualizzato nel menu a discesa della configurazione di avvio.", - "debugRequest": "Tipo della richiesta di configurazione. Può essere \"launch\" o \"attach\".", - "debugServer": "Solo per lo sviluppo dell'estensione di debug: se si specifica una porta, Visual Studio Code prova a connettersi a un adattatore di debug in esecuzione in modalità server", - "debugPrelaunchTask": "Attività da eseguire prima dell'avvio della sessione di debug.", - "debugWindowsConfiguration": "Attributi della configurazione di avvio specifici di Windows.", - "debugOSXConfiguration": "Attributi della configurazione di avvio specifici di OS X.", - "debugLinuxConfiguration": "Attributi della configurazione di avvio specifici di Linux.", - "deprecatedVariables": "'env.', 'config.' e 'command.' sono deprecati. In alternativa, usare 'env:', 'config:' e 'command:'." + "unableToLaunchDebugAdapter": "Non è possibile avviare l'adattatore di debug da '{0}'.", + "unableToLaunchDebugAdapterNoArgs": "Non è possibile avviare l'adattatore di debug." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..d7bf531b57 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Usare IntelliSense per informazioni sui possibili attributi.", + "launch.config.comment2": "Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.", + "launch.config.comment3": "Per ulteriori informazioni, visitare: {0}", + "debugType": "Tipo di configurazione.", + "debugTypeNotRecognised": "Il tipo di debug non è riconosciuto. Assicurarsi di avere un'estensione appropriata per il debug installata e che sia abilitata.", + "node2NotSupported": "\"node2\" non è più supportato. In alternativa, usare \"node\" e impostare l'attributo \"protocol\" su \"inspector\".", + "debugName": "Nome della configurazione. Viene visualizzato nel menu a discesa della configurazione di avvio.", + "debugRequest": "Tipo della richiesta di configurazione. Può essere \"launch\" o \"attach\".", + "debugServer": "Solo per lo sviluppo dell'estensione di debug: se si specifica una porta, Visual Studio Code prova a connettersi a un adattatore di debug in esecuzione in modalità server", + "debugPrelaunchTask": "Attività da eseguire prima dell'avvio della sessione di debug.", + "debugPostDebugTask": "Attività da eseguire dopo il completamento della sessione di debug.", + "debugWindowsConfiguration": "Attributi della configurazione di avvio specifici di Windows.", + "debugOSXConfiguration": "Attributi della configurazione di avvio specifici di OS X.", + "debugLinuxConfiguration": "Attributi della configurazione di avvio specifici di Linux.", + "deprecatedVariables": "'env.', 'config.' e 'command.' sono deprecati. In alternativa, usare 'env:', 'config:' e 'command:'." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..b2beae5d75 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "Console di Visual Studio Code", + "mac.terminal.script.failed": "Lo script '{0}' non è riuscito. Codice di uscita: {1}", + "mac.terminal.type.not.supported": "'{0}' non supportato", + "press.any.key": "Premere un tasto qualsiasi per continuare...", + "linux.term.failed": "'{0}' non riuscito. Codice di uscita: {1}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 4b13350c5c..71b7ee5c84 100644 --- a/i18n/ita/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Configura estensioni consigliate (cartella dell'area di lavoro)", "malicious tooltip": "Questa estensione è stata segnalata come problematica.", "malicious": "Dannosa", + "disabled": "Disabilitata", + "disabled globally": "Disabilitata", + "disabled workspace": "Disabilitata per questa area di lavoro", "disableAll": "Disabilita tutte le estensioni installate", "disableAllWorkspace": "Disabilita tutte le estensioni installate per questa area di lavoro", "enableAll": "Abilita tutte le estensioni", diff --git a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..89f32dfa7a --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Nome dell'estensione", + "extension id": "Identificatore dell'estensione", + "preview": "Anteprima", + "builtin": "Predefinita", + "publisher": "Nome dell'editore", + "install count": "Conteggio delle installazioni", + "rating": "Valutazione", + "repository": "Repository", + "license": "Licenza", + "details": "Dettagli", + "contributions": "Contributi", + "changelog": "Log delle modifiche", + "dependencies": "Dipendenze", + "noReadme": "File LEGGIMI non disponibile.", + "noChangelog": "Changelog non disponibile.", + "noContributions": "Nessun contributo", + "noDependencies": "Nessuna dipendenza", + "settings": "Impostazioni ({0})", + "setting name": "Nome", + "description": "Descrizione", + "default": "Impostazione predefinita", + "debuggers": "Debugger ({0})", + "debugger name": "Nome", + "debugger type": "Tipo", + "views": "Visualizzazioni ({0})", + "view id": "ID", + "view name": "Nome", + "view location": "Dove", + "localizations": "Localizzazioni ({0})", + "localizations language id": "ID lingua", + "localizations language name": "Nome della lingua", + "localizations localized language name": "Nome della lingua (localizzato)", + "colorThemes": "Temi colore ({0})", + "iconThemes": "Temi icona ({0})", + "colors": "Colori ({0})", + "colorId": "ID", + "defaultDark": "Predefinito scuro", + "defaultLight": "Predefinito chiaro", + "defaultHC": "Predefinito contrasto elevato", + "JSON Validation": "Convalida JSON ({0})", + "fileMatch": "Corrispondenza file", + "schema": "Schema", + "commands": "Comandi ({0})", + "command name": "Nome", + "keyboard shortcuts": "Scelte rapide da tastiera", + "menuContexts": "Contesti menu", + "languages": "Linguaggi ({0})", + "language id": "ID", + "language name": "Nome", + "file extensions": "Estensioni di file", + "grammar": "Grammatica", + "snippets": "Frammenti" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index b52b364599..48363670d3 100644 --- a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Questa estensione è consigliata dagli utenti dell'area di lavoro corrente.", "reallyRecommended2": "Per questo tipo di file è consigliabile utilizzare l'estensione '{0}'.", "reallyRecommendedExtensionPack": "Per questo tipo di file è consigliabile usare il pacchetto di estensione '{0}'.", - "showRecommendations": "Mostra gli elementi consigliati", "install": "Installa", + "showRecommendations": "Mostra gli elementi consigliati", "showLanguageExtensions": "Il Marketplace ha estensioni per i file '.{0}'", "workspaceRecommended": "Per questa area di lavoro sono disponibili estensioni consigliate.", "installAll": "Installa tutto", diff --git a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index faed42f971..5924664373 100644 --- a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Disabilitare altre mappature tastiera ({0}) per evitare conflitti tra tasti di scelta rapida?", "yes": "Sì", - "no": "No", - "betterMergeDisabled": "L'estensione Better Merge (miglior merge) è ora incorporata: l'estensione installata è stata disattivata e può essere disinstallata.", - "uninstall": "Disinstalla" + "no": "No" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index b83dda9466..17b06f638b 100644 --- a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Consigliate", "otherRecommendedExtensions": "Altri consigli", "workspaceRecommendedExtensions": "Consigli per l'area di lavoro", - "builtInExtensions": "Predefinite", + "builtInExtensions": "Funzionalità", + "builtInThemesExtensions": "Temi", + "builtInBasicsExtensions": "Linguaggi di programmazione", "searchExtensions": "Cerca le estensioni nel Marketplace", "sort by installs": "Ordina per: conteggio installazioni", "sort by rating": "Ordina per: classificazione", diff --git a/i18n/ita/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/ita/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 0d9a08eb7b..47c359b325 100644 --- a/i18n/ita/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Editor file di testo", "createFile": "Crea file", + "relaunchWithIncreasedMemoryLimit": "Riavvia con {0} MB", + "configureMemoryLimit": "Configura limite di memoria", "fileEditorWithInputAriaLabel": "{0}. Editor file di testo.", "fileEditorAriaLabel": "Editor file di testo." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index d3cca69302..fbe04d075b 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Copia", "pasteFile": "Incolla", "retry": "Riprova", + "renameWhenSourcePathIsParentOfTargetError": "Usare il comando 'Nuova cartella' o 'Nuovo file' per aggiungere elementi figlio a una cartella esistente", "newUntitledFile": "Nuovo file senza nome", "createNewFile": "Nuovo file", "createNewFolder": "Nuova cartella", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Si sta per eliminare una cartella con modifiche non salvate in {0} file. Continuare?", "dirtyMessageFileDelete": "Si sta per eliminare un file con modifiche non salvate. Continuare?", "dirtyWarning": "Le modifiche apportate andranno perse se non vengono salvate.", + "undoBin": "È possibile ripristinare dal Cestino.", + "undoTrash": "È possibile ripristinare dal Cestino.", + "doNotAskAgain": "Non chiedermelo di nuovo", + "irreversible": "Questa azione è irreversibile.", + "binFailed": "Impossibile eliminare utilizzando il Cestino. Si desidera eliminare definitivamente invece?", + "trashFailed": "Impossibile eliminare utilizzando il Cestino. Si desidera eliminare definitivamente invece?", + "deletePermanentlyButtonLabel": "&& Eliminare in modo permanente", + "retryButtonLabel": "&& Riprova", + "confirmMoveTrashMessageFilesAndDirectories": "Eliminare i {0} file/directory seguenti e il relativo contenuto?", + "confirmMoveTrashMessageMultipleDirectories": "Eliminare le {0} directory seguenti e il relativo contenuto?", "confirmMoveTrashMessageMultiple": "Sei sicuro di voler eliminarei seguenti {0} file?", "confirmMoveTrashMessageFolder": "Eliminare '{0}' e il relativo contenuto?", "confirmMoveTrashMessageFile": "Eliminare '{0}'?", - "undoBin": "È possibile ripristinare dal Cestino.", - "undoTrash": "È possibile ripristinare dal cestino.", - "doNotAskAgain": "Non chiedermelo di nuovo", + "confirmDeleteMessageFilesAndDirectories": "Eliminare definitivamente i {0} file/directory seguenti e il relativo contenuto?", + "confirmDeleteMessageMultipleDirectories": "Eliminare definitivamente le {0} directory seguenti e il relativo contenuto?", "confirmDeleteMessageMultiple": "Sei sicuro di voler eliminare permanentemente i seguenti {0} file?", "confirmDeleteMessageFolder": "Eliminare definitivamente '{0}' e il relativo contenuto?", "confirmDeleteMessageFile": "Eliminare definitivamente '{0}'?", - "irreversible": "Questa azione è irreversibile.", - "cancel": "Annulla", - "permDelete": "Elimina definitivamente", - "importFiles": "Importa file", + "addFiles": "Aggiungi file", "confirmOverwrite": "Nella cartella di destinazione esiste già un file o una cartella con lo stesso nome. Sovrascrivere?", "replaceButtonLabel": "&&Sostituisci", "fileIsAncestor": "Il file da incollare è un predecessore della cartella di destinazione", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Aprire prima un file per visualizzarlo in un'altra finestra", "copyPath": "Copia percorso", "emptyFileNameError": "È necessario specificare un nome file o un nome di cartella.", + "fileNameStartsWithSlashError": "Un nome di file o cartella non può iniziare con una barra.", "fileNameExistsError": "In questo percorso esiste già un file o una cartella **{0}**. Scegliere un nome diverso.", + "fileUsedAsFolderError": "**{0}** è un file e non può avere discendenti.", "invalidFileNameError": "Il nome **{0}** non è valido per un nome file o un nome di cartella. Scegliere un nome diverso.", "filePathTooLongError": "Con il nome **{0}** il percorso diventa troppo lungo. Scegliere un nome più breve.", "compareWithClipboard": "Confronta il file attivo con gli appunti", diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index d85e4781c9..66509faf1a 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Controlla se i file non salvati verranno memorizzati tra una sessione e l'altra, consentendo di ignorare il prompt di salvataggio alla chiusura dell'editor.", "useExperimentalFileWatcher": "Usa il nuovo watcher di file sperimentale.", "defaultLanguage": "Modalità linguaggio predefinita assegnata ai nuovi file.", + "maxMemoryForLargeFilesMB": "Controlla la memoria disponibile per VS Code dopo il riavvio durante il tentativo di aprire file di grandi dimensioni. Il risultato è uguale a quanto si specifica --max-memory=NEWSIZE sulla riga di comando.", "editorConfigurationTitle": "Editor", "formatOnSave": "Formatta un file durante il salvataggio. Deve essere disponibile un formattatore, il file non deve essere salvato automaticamente e l'editor non deve essere in fase di chiusura.", + "formatOnSaveTimeout": "Timeout per Formatta dopo il salvataggio. Specifica un limite di tempo in millisecondi per i comandi formatOnSave. I comandi che richiedono più tempo del timeout specificato verranno annullati.", "explorerConfigurationTitle": "Esplora file", "openEditorsVisible": "Numero di editor visualizzati nel riquadro degli editor aperti.", "autoReveal": "Controlla se Esplora risorse deve rivelare automaticamente e selezionare i file durante l'apertura.", diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 5e903783ce..a54b8fa48a 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -2,18 +2,22 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Digitare il nome file. Premere INVIO per confermare oppure ESC per annullare.", - "constructedPath": "Crea {0} in **{1}**", + "createFileFromExplorerInfoMessage": "Crea il file **{0}** in **{1}**", + "renameFileFromExplorerInfoMessage": "Sposta e rinomina in **{0}**", + "createFolderFromExplorerInfoMessage": "Crea la cartella **{0}** in **{1}**", "filesExplorerViewerAriaLabel": "{0}, Esplora file", "dropFolders": "Aggiungere le cartelle all'area di lavoro?", "dropFolder": "Aggiungere la cartella all'area di lavoro?", "addFolders": "&& Aggiungi cartelle", "addFolder": "&&Aggiungi cartella", + "confirmRootsMove": "Sei sicuro che si desidera modificare l'ordine di più cartelle root nell'area di lavoro?", "confirmMultiMove": "Sei sicuro di voler spostare i seguenti {0} file?", + "confirmRootMove": "Sei sicuro che si desidera modificare l'ordine delle cartella principale '{0}' nell'area di lavoro?", "confirmMove": "Sei sicuro di voler spostare '{0}'?", "doNotAskAgain": "Non chiedermelo di nuovo", "moveButtonLabel": "&&Sposta", diff --git a/i18n/ita/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..4d04454a2a --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Anteprima HTML" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/ita/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..6ad886b279 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "L'input dell'editor non è valido." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..2011975d15 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Sviluppatore" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/ita/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..ee36d0bcec --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Apri strumenti di sviluppo Webview", + "refreshWebviewLabel": "Ricarica Webview" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index fe0cc638cd..d50d23d98d 100644 --- a/i18n/ita/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Cambiare la lingua dell'interfaccia utente di VS Code in {0} e riavviare?", + "yes": "Sì", + "no": "No", + "neverAgain": "Non visualizzare più questo messaggio", "JsonSchema.locale": "Linguaggio dell'interfaccia utente da usare.", "vscode.extension.contributes.localizations": "Contribuisce traduzioni all'editor", "vscode.extension.contributes.localizations.languageId": "Id della lingua in cui sono tradotte le stringhe visualizzate.", diff --git a/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..595160a7a9 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Cambiare la lingua dell'interfaccia utente di VS Code in {0} e riavviare?", + "yes": "Sì", + "no": "No", + "neverAgain": "Non visualizzare più questo messaggio", + "install language pack": "Nel prossimo futuro VS Code supporterà solo Language Pack sotto forma di estensioni del Marketplace. Installare l'estensione '{0}' per poter continuare a usare la lingua attualmente configurata. ", + "install": "Installa", + "more information": "Altre informazioni...", + "JsonSchema.locale": "Linguaggio dell'interfaccia utente da usare.", + "vscode.extension.contributes.localizations": "Contribuisce traduzioni all'editor", + "vscode.extension.contributes.localizations.languageId": "Id della lingua in cui sono tradotte le stringhe visualizzate.", + "vscode.extension.contributes.localizations.languageName": "Nome della lingua in inglese.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Nome della lingua nella lingua stessa.", + "vscode.extension.contributes.localizations.translations": "Lista delle traduzioni associate alla lingua.", + "vscode.extension.contributes.localizations.translations.id": "ID di VS Code o dell'estensione cui si riferisce questa traduzione. L'ID di VS Code è sempre 'vscode' e quello di un'estensione deve essere nel formato 'publisherId.extensionName'.", + "vscode.extension.contributes.localizations.translations.id.pattern": "L'ID deve essere 'vscode' o essere nel formato 'publisherId.extensionName' per tradurre rispettivamente VS Code o un'estensione.", + "vscode.extension.contributes.localizations.translations.path": "Percorso relativo di un file che contiene le traduzioni per la lingua." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..339538154c --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Configura lingua", + "displayLanguage": "Definisce la lingua visualizzata di VSCode.", + "doc": "Per un elenco delle lingue supportate, vedere {0}.", + "restart": "Se si modifica il valore, è necessario riavviare VSCode.", + "fail.createSettings": "Non è possibile creare '{0}' ({1})." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..c8c335d94e --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Copia", + "copyMessage": "Copia messaggio " +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..f743668975 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Totale {0} problemi" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..2fafad9b70 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Problemi", + "tooltip.1": "1 problema in questo file ", + "tooltip.N": "{0} problemi in questo file", + "markers.showOnFile": "Mostra errori e avvisi relativi a file e cartella. " +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..4ec323652b --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Disabilita filtro di esclusione file.", + "clearFilter": "Cancella filtro." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..9cf8a09476 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "Visualizzazione di {0} di {1}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..f06a4d0563 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Visualizza", + "problems.view.toggle.label": "Attiva/Disattiva Problemi (Errori, Avvisi, Informazioni)", + "problems.view.focus.label": "Sposta lo stato attivo su problemi (Errori, Avvisi, Informazioni)", + "problems.panel.configuration.title": "Visualizzazione Problemi", + "problems.panel.configuration.autoreveal": "Controlla se la visualizzazione Problemi deve visualizzare automaticamente i file durante l'apertura", + "markers.panel.title.problems": "Problemi", + "markers.panel.aria.label.problems.tree": "Problemi raggruppati per file", + "markers.panel.no.problems.build": "Finora non sono stati rilevati problemi nell'area di lavoro.", + "markers.panel.no.problems.filters": "Non sono stati trovati risultati corrispondenti ai criteri di filtro specificati.", + "markers.panel.no.problems.file.exclusions": "Tutti i problemi sono nascosti perché è abilitato il filtro di esclusione file.", + "markers.panel.action.useFilesExclude": "Filtra usando l'impostazione di esclusione file", + "markers.panel.action.donotUseFilesExclude": "Non usare l'impostazione di esclusione file", + "markers.panel.action.filter": "Filtra problemi", + "markers.panel.filter.ariaLabel": "Filtra problemi", + "markers.panel.filter.placeholder": "Filtro. Ad esempio: text, **/*.ts,!**/node_modules/**", + "markers.panel.filter.errors": "errori", + "markers.panel.filter.warnings": "avvisi", + "markers.panel.filter.infos": "messaggi informativi", + "markers.panel.single.error.label": "1 errore", + "markers.panel.multiple.errors.label": "{0} errori", + "markers.panel.single.warning.label": "1 avviso", + "markers.panel.multiple.warnings.label": "{0} avvisi", + "markers.panel.single.info.label": "1 messaggio informativo", + "markers.panel.multiple.infos.label": "{0} messaggi informativi", + "markers.panel.single.unknown.label": "1 sconosciuto", + "markers.panel.multiple.unknowns.label": "{0} sconosciuti", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} con {1} problemi", + "problems.tree.aria.label.marker.relatedInformation": " Questo problema include riferimenti a {0} percorsi.", + "problems.tree.aria.label.error.marker": "Errore generato da {0}: {1} a riga {2} e carattere {3}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Errore: {0} a riga {1} e carattere {2}.{3}", + "problems.tree.aria.label.warning.marker": "Avviso generato da {0}: {1} a riga {2} e carattere {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Avviso: {0} a riga {1} e carattere {2}.{3}", + "problems.tree.aria.label.info.marker": "Messaggio informativo generato da {0}: {1} a riga {2} e carattere {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Messaggio informativo: {0} a riga {1} e carattere {2}.{3}", + "problems.tree.aria.label.marker": "Problema generato da {0}: {1} a riga {2} e carattere {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Problema: {0} a riga {1} e carattere {2}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{0} a riga {1} e carattere {2} in {3}", + "errors.warnings.show.label": "Mostra errori e avvisi" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/ita/src/vs/workbench/parts/output/browser/outputActions.i18n.json index 48ad8007ab..1f861f6442 100644 --- a/i18n/ita/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Attiva/Disattiva output", "clearOutput": "Cancella output", "toggleOutputScrollLock": "Attiva/Disattiva blocco scorrimento per output", - "switchToOutput.label": "Passa all'output" + "switchToOutput.label": "Passa all'output", + "openInLogViewer": "Apri file di log" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 3e2cd57328..405f2c3b97 100644 --- a/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Output", "logViewer": "Visualizzatore Log", "viewCategory": "Visualizza", - "clearOutput.label": "Cancella output" + "clearOutput.label": "Cancella output", + "openActiveLogOutputFile": "Visualizza: Apri file di output del log attivo" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index e15a00c512..08a6528ae5 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Scelte rapide da tastiera", + "showDefaultKeybindings": "Mostra tasti di scelta rapida predefiniti", + "showUserKeybindings": "Mostra tasti di scelta rapida utente", "SearchKeybindings.AriaLabel": "Cerca tasti di scelta rapida", "SearchKeybindings.Placeholder": "Cerca tasti di scelta rapida", "sortByPrecedene": "Ordina per Precedenza", diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 7ae86a4f1b..bf645644a0 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Apri impostazioni predefinite non elaborate", + "openSettings": "Apri impostazioni", "openGlobalSettings": "Apri impostazioni utente", "openGlobalKeybindings": "Apri tasti di scelta rapida", "openGlobalKeybindingsFile": "Apri file dei tasti di scelta rapida", diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 54a6e515bb..a40008fc09 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Impostazioni predefinite", "SearchSettingsWidget.AriaLabel": "Cerca impostazioni", "SearchSettingsWidget.Placeholder": "Cerca impostazioni", "noSettingsFound": "Nessun risultato", @@ -16,6 +15,8 @@ "nlpResult": "Risultati linguaggio naturale", "filterResult": "Risultati filtrati", "defaultSettings": "Impostazioni predefinite", + "defaultUserSettings": "Impostazioni predefinite utente", + "defaultWorkspaceSettings": "Impostazioni area di lavoro predefinite", "defaultFolderSettings": "Impostazioni cartella predefinite", "defaultEditorReadonly": "Modificare nell'editor a destra per ignorare le impostazioni predefinite.", "preferencesAriaLabel": "Preferenze predefinite. Editor di testo di sola lettura." diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 1c974d0592..b99928a636 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Mostra l'estensione \"{0}\"", "editTtile": "Modifica", "replaceDefaultValue": "Sostituisci nelle impostazioni", - "copyDefaultValue": "Copia nelle impostazioni", - "unsupportedPHPExecutablePathSetting": "Questa deve essere un'impostazione utente. Per configurare PHP per l'area di lavoro, aprire un file PHP e fare clic su 'Percorso PHP' nella barra di stato.", - "unsupportedWorkspaceSetting": "Questa deve essere un'impostazione utente.", - "unsupportedWorkbenchSetting": "Non è possibile applicare ora questa impostazione. Verrà applicata direttamente all'apertura della cartella.", - "unsupportedWorkbenchSettingDevMode": "L'impostazione non può essere applicata in questo momento. Essa verrà applicata se il suo ambito sarà definito come 'risorsa' durante la registrazione, o quando si aprirà questa cartella direttamente." + "copyDefaultValue": "Copia nelle impostazioni" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 75dbb68177..136ff37655 100644 --- a/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Installa ulteriori provider SCM ...", "no open repo": "Non esistono provider di controllo codice sorgente attivi.", "source control": "Controllo del codice sorgente", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Nascondi" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 3e370f5256..83a2b2f56d 100644 --- a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Mostra i criteri di esclusione per la ricerca precedenti", "nextSearchTerm": "Mostra il termine di ricerca successivo", "previousSearchTerm": "Mostra il termine di ricerca precedente", - "showSearchViewlet": "Mostra Cerca", "findInFiles": "Cerca nei file", "replaceInFiles": "Sostituisci nei file", "RefreshAction.label": "Aggiorna", diff --git a/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index aa8b287ddb..dab16abc98 100644 --- a/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Cerca", + "copyMatchLabel": "Copia", + "copyPathLabel": "Copia percorso", + "copyAllLabel": "Copia tutti", + "clearSearchHistoryLabel": "Cancella cronologia di ricerca", + "toggleSearchViewPositionLabel": "Attiva/Disattiva ricerca posizione della visualizzazione", "findInFolder": "Trova nella cartella...", "findInWorkspace": "Trova nell'area di lavoro...", "showTriggerActions": "Vai al simbolo nell'area di lavoro...", "name": "Cerca", - "search": "Cerca", "showSearchViewl": "Mostra Cerca", "view": "Visualizza", "findInFiles": "Cerca nei file", @@ -26,5 +31,5 @@ "search.followSymlinks": "Controlla se seguire i collegamenti simbolici durante la ricerca.", "search.smartCase": "Cerca in modo insensibile alle maiuscole/minuscole se il criterio è tutto minuscolo, altrimenti cerca in modalità sensibile a maiuscole/minuscole", "search.globalFindClipboard": "Controlla se il viewlet di ricerca deve leggere o modificare gli appunti di ricerca condivisi in macOS", - "search.location": "Anteprima: controlla se la ricerca verrà mostrata in una visualizzazione della barra laterale o in un pannello nell'area pannelli in modo da disporre di maggiore spazio in orizzontale. Nella versione successiva la ricerca nel pannello sarà caratterizzata da un layout orizzontale ottimizzato e questa funzione non sarà più un'anteprima." + "search.location": "Controlla se la ricerca verrà mostrata come visualizzazione nella barra laterale o come pannello nell'area pannelli per ottenere più spazio orizzontale. Nella prossima versione la ricerca nel pannello avrà un layout orizzontale migliorato e non sarà più disponibile in anteprima." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 773946d1c2..104bcf1c47 100644 --- a/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Aiutaci a migliorare il nostro supporto all'{0}", "takeShortSurvey": "Partecipa a un breve sondaggio", "remindLater": "Visualizza più tardi", - "neverAgain": "Non visualizzare più questo messaggio", - "helpUs": "Aiutaci a migliorare il nostro supporto all'{0}" + "neverAgain": "Non visualizzare più questo messaggio" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 86038edac9..cf40d93403 100644 --- a/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Partecipare a un breve sondaggio?", "takeSurvey": "Partecipa a sondaggio", "remindLater": "Visualizza più tardi", - "neverAgain": "Non visualizzare più questo messaggio", - "surveyQuestion": "Partecipare a un breve sondaggio?" + "neverAgain": "Non visualizzare più questo messaggio" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 3fb80982bf..4a0732e88c 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Criterio di problema o nome di un criterio di problema predefinito o aggiunto come contributo. Può essere omesso se si specifica base.", "ProblemMatcherSchema.base": "Nome di un matcher problemi di base da usare.", "ProblemMatcherSchema.owner": "Proprietario del problema in Visual Studio Code. Può essere omesso se si specifica base. Se è omesso e non si specifica base, viene usato il valore predefinito 'external'.", + "ProblemMatcherSchema.source": "Stringa in formato leggibile che descrive l'origine di questa diagnostica, ad esempio 'typescript' o 'super lint'.", "ProblemMatcherSchema.severity": "Gravità predefinita per i problemi di acquisizione. Viene usato se il criterio non definisce un gruppo di corrispondenze per la gravità.", "ProblemMatcherSchema.applyTo": "Controlla se un problema segnalato in un documento di testo è valido solo per i documenti aperti o chiusi oppure per tutti i documenti.", "ProblemMatcherSchema.fileLocation": "Consente di definire come interpretare i nomi file indicati in un criterio di problema.", diff --git a/i18n/ita/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 7f541a2d4c..713d0ea811 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Tipo di attività effettivo", + "TaskDefinition.description": "Tipo di attività effettivo. Notare che i tipi che iniziano con il carattere '$' sono riservati per l'utilizzo interno.", "TaskDefinition.properties": "Proprietà aggiuntive del tipo di attività", "TaskTypeConfiguration.noType": "Nella configurazione del tipo di attività manca la proprietà obbligatoria 'taskType'", "TaskDefinitionExtPoint": "Tipi di attività per contributes" diff --git a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 990ab7c0d3..6783a29e30 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "Non assegna l'attività ad alcun gruppo", "JsonSchema.tasks.group": "Definisce il gruppo di esecuzione a cui appartiene questa attività. Supporta \"build\" per aggiungerlo al gruppo di compilazione e \"test\" per aggiungerlo al gruppo di test.", "JsonSchema.tasks.type": "Definisce se l'attività viene eseguita come un processo o come un comando all'interno di una shell.", + "JsonSchema.command.quotedString.value": "Valore effettivo del comando", + "JsonSchema.tasks.quoting.escape": "Evita i caratteri utilizzando il carattere di escape della shell (per esempio ` sotto PowerShell e \\ sotto bash).", + "JsonSchema.tasks.quoting.strong": "Virgoletta l'argomento utilizzando il carattere di doppio apice della shell (per esempio \" sotto PowerShell e bash).", + "JsonSchema.tasks.quoting.weak": "Virgoletta l'argomento utilizzando il carattere di singolo apice della shell (per esempio ' sotto PowerShell e bash).", + "JsonSchema.command.quotesString.quote": "Come il valore del comando dovrebbe essere virgolettato", + "JsonSchema.command": "Comando da eseguire. Può essere un programma esterno o un comando della shell.", + "JsonSchema.args.quotedString.value": "Valore effettivo del comando", + "JsonSchema.args.quotesString.quote": "Come il valore dell'argomento dovrebbe essere virgolettato", + "JsonSchema.tasks.args": "Argomenti passati al comando quando viene richiamata questa attività.", "JsonSchema.tasks.label": "Etichetta dell'attività per l'interfaccia utente ", "JsonSchema.version": "Numero di versione della configurazione", "JsonSchema.tasks.identifier": "Identificatore definito dall'utente per fare riferimento all'attività in launch.json o in una clausola dependsOn.", diff --git a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index a9eb104cec..83baac9140 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "Attività", "ConfigureTaskRunnerAction.label": "Configura attività", + "totalErrors": "{0} errori", + "totalWarnings": "{0} avvisi", + "totalInfos": "{0} messaggi informativi", "problems": "Problemi", "building": "Compilazione in corso...", - "manyMarkers": "Più di 99", + "manyProblems": "Più di 10.000", "runningTasks": "Visualizza attività in esecuzione", "tasks": "Attività", "TaskSystem.noHotSwap": "Se si cambia il motore di esecuzione delle attività con un'attività attiva in esecuzione, è necessario ricaricare la finestra", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Selezionare il tipo di errori e di avvisi per cui analizzare l'output dell'attività", "customizeParseErrors": "La configurazione dell'attività corrente presenta errori. Per favore correggere gli errori prima di personalizzazione un'attività.", "moreThanOneBuildTask": "tasks.json contiene molte attività di compilazione. È in corso l'esecuzione della prima.\n", - "TaskSystem.activeSame.background": "L'attività '{0}' è già attiva ed in modalità background. Per terminarla, usare 'Termina attività' dal menu Attività.", - "TaskSystem.activeSame.noBackground": "L'attività '{0}' è già attiva. Per terminarla, usare 'Termina attività' dal menu Attività.", + "TaskSystem.activeSame.background": "L'attività '{0}' è già attiva e in modalità background.", + "TaskSystem.activeSame.noBackground": "L'attività '{0}' è già attiva.", + "terminateTask": "Termina attività", + "restartTask": "Riavvia attività", "TaskSystem.active": "Al momento c'è già un'attività in esecuzione. Terminarla prima di eseguirne un'altra.", "TaskSystem.restartFailed": "Non è stato possibile terminare e riavviare l'attività {0}", "TaskService.noConfiguration": "Errore: Il rilevamento di attività {0} non ha contribuito un'attività nella seguente configurazione: \n{1} \nL'attività verrà ignorata.\n", diff --git a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index c8d63aeca5..ce161d8eff 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Attività - {0}", "closeTerminal": "Premere un tasto qualsiasi per chiudere il terminale.", "reuseTerminal": "Terminale verrà riutilizzato dalle attività, premere un tasto qualsiasi per chiuderlo.", - "TerminalTaskSystem": "Non è possibile eseguire un comando della shell su un'unità UNC.", + "TerminalTaskSystem": "Non è possibile eseguire un comando della shell su un'unità UNC con cmd.exe.", "unkownProblemMatcher": "Il matcher problemi {0} non può essere risolto. il matcher verrà ignorato" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/ita/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index ed71866213..6c8a5d9a27 100644 --- a/i18n/ita/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Avviso: options.cwd deve essere di tipo string. Il valore {0} verrà ignorato.\n", + "ConfigurationParser.inValidArg": "Errore: l'argomento del comando deve essere una stringa o una stringa virgolettata. Il valore specificato è:\n{0}", "ConfigurationParser.noargs": "Errore: gli argomenti del comando devono essere un array di stringhe. Il valore specificato è:\n{0}", "ConfigurationParser.noShell": "Avviso: la configurazione della shell è supportata solo quando si eseguono attività nel terminale.", "ConfigurationParser.noName": "Errore: è necessario specificare un nome per il matcher problemi nell'ambito di dichiarazione:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Errore: nella configurazione di attività '{0}' manca la proprietà obbligatoria '{1}'. La configurazione dell'attività verrà ignorata.", "ConfigurationParser.notCustom": "Errore: tasks non è dichiarato come un'attività personalizzata. La configurazione verrà ignorata.\n{0}\n", "ConfigurationParser.noTaskName": "Errore: un'attività deve specificare una proprietà label. L'attività verrà ignorata.\n{0}\n", - "taskConfiguration.shellArgs": "Avviso: l'attività '{0}' è un comando di shell e uno dei suoi argomenti potrebbe avere spazi indesiderati. Per garantire la correttezza della riga di comando unire args nel comando stesso.", "taskConfiguration.noCommandOrDependsOn": "Errore: l'attività '{0}' non specifica un comando né una proprietà dependsOn. L'attività verrà ignorata. La sua definizione è:\n{1}", "taskConfiguration.noCommand": "Errore: l'attività '{0}' non definisce un comando. L'attività verrà ignorata. Definizione dell'attività:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "L'attività versione 2.0.0 non supporta attività specifiche globali del sistema operativo. Convertirle in un'attività con un comando specifico del sistema operativo. Attività interessate:\n{0}" diff --git a/i18n/ita/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..7ae3aac58f --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "Il colore di sfondo del terminale, questo consente di colorare il terminale in modo diverso dal pannello.", + "terminal.foreground": "Il colore di primo piano del terminale.", + "terminalCursor.foreground": "Colore di primo piano del cursore del terminale.", + "terminalCursor.background": "Colore di sfondo del cursore del terminale. Permette di personalizzare il colore di un carattere quando sovrapposto da un blocco cursore.", + "terminal.selectionBackground": "Colore di sfondo di selezione del terminale.", + "terminal.border": "Colore del bordo che separa i riquadri divisi all'interno del terminale. L'impostazione predefinita è panel.border.", + "terminal.ansiColor": "'{0}' colori ANSI nel terminale. " +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index d161d9a57b..42d1b0441a 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "Selezionare la cartella di lavoro corrente per un nuovo terminale.", "workbench.action.terminal.newInActiveWorkspace": "Crea un nuovo terminale integrato (nel workspace attivo)", "workbench.action.terminal.split": "Terminale diviso", + "workbench.action.terminal.splitInActiveWorkspace": "Terminale diviso (nell'area di lavoro attiva)", "workbench.action.terminal.focusPreviousPane": "Sposta stato attivo sul riquadro precedente", "workbench.action.terminal.focusNextPane": "Sposta stato attivo sul riquadro successivo", "workbench.action.terminal.resizePaneLeft": "Ridimensiona il riquadro a sinistra", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "Scorri su (pagina)", "workbench.action.terminal.scrollToTop": "Scorri all'inizio", "workbench.action.terminal.clear": "Cancella", + "workbench.action.terminal.clearSelection": "Cancella selezione", "workbench.action.terminal.allowWorkspaceShell": "Consente la configurazione della Shell dell'area di lavoro", "workbench.action.terminal.disallowWorkspaceShell": "Non consente la configurazione della Shell dell'area di lavoro", "workbench.action.terminal.rename": "Rinomina", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Nascondi widget Trova", "nextTerminalFindTerm": "Mostra il termine di ricerca successivo", "previousTerminalFindTerm": "Mostra il termine di ricerca precedente", - "quickOpenTerm": "Cambia terminale attivo" + "quickOpenTerm": "Cambia terminale attivo", + "workbench.action.terminal.scrollToPreviousCommand": "Scorri al comando precedente", + "workbench.action.terminal.scrollToNextCommand": "Scorri al comando successivo", + "workbench.action.terminal.selectToPreviousCommand": "Aggiungi selezione a comando precedente", + "workbench.action.terminal.selectToNextCommand": "Aggiungi selezione a comando successivo" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index e551449aa2..e7c8e50783 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "Il terminale non contiene alcuna selezione da copiare", "terminal.integrated.exitedWithCode": "Il processo del terminale è stato terminato. Codice di uscita: {0}", "terminal.integrated.waitOnExit": "Premere un tasto qualsiasi per chiudere il terminale", - "terminal.integrated.launchFailed": "Non è stato possibile avviare il comando '{0}{1}' del processo del terminale (codice di uscita: {2})" + "terminal.integrated.launchFailed": "Non è stato possibile avviare il comando '{0}{1}' del processo del terminale (codice di uscita: {2})", + "terminal.integrated.launchFailedExtHost": "Non è stato possibile avviare il processo del terminale (codice di uscita: {0})" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index b19a0690bf..327aa7f6a4 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copy": "Copia", + "split": "Dividi", "paste": "Incolla", "selectAll": "Seleziona tutto", "clear": "Cancella", diff --git a/i18n/ita/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 5926095b5b..77ad8ad577 100644 --- a/i18n/ita/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Quest'area di lavoro contiene impostazioni che è possibile specificare solo nelle impostazioni utente ({0}). Per maggiori informazioni, fare clic [qui]({1}).", "openWorkspaceSettings": "Apri impostazioni area di lavoro", "dontShowAgain": "Non visualizzare più questo messaggio", "unsupportedWorkspaceSettings": "Quest'area di lavoro contiene impostazioni che è possibile specificare solo nelle impostazioni utente ({0}). Per maggiori informazioni, fare clic [qui]({1})." diff --git a/i18n/ita/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/ita/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..a720e18d09 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Note sulla versione: {0}", + "unassigned": "non assegnato" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 7245774196..aed35ee0f7 100644 --- a/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "In seguito", - "unassigned": "non assegnato", "releaseNotes": "Note sulla versione", "showReleaseNotes": "Mostra note sulla versione", "read the release notes": "Benvenuti in {0} versione {1}. Leggere le note sulla versione?", @@ -17,13 +15,14 @@ "updateIsReady": "Nuovo aggiornamento di {0} disponibile.", "noUpdatesAvailable": "Al momento non sono disponibili aggiornamenti.", "ok": "OK", - "download now": "Scarica ora", "thereIsUpdateAvailable": "È disponibile un aggiornamento.", - "installUpdate": "Installa aggiornamento", + "download now": "Scarica ora", + "later": "In seguito", "updateAvailable": "È disponibile un aggiornamento: {0} {1}", + "installUpdate": "Installa aggiornamento", "updateInstalling": "{0} {1} verrà installato in background. Al termine, verrà visualizzato un messaggio.", + "updateAvailableAfterRestart": "Riavviare {0} per applicare l'aggiornamento più recente.", "updateNow": "Aggiorna adesso", - "updateAvailableAfterRestart": "{0} verrà aggiornato dopo il riavvio.", "commandPalette": "Riquadro comandi...", "settings": "Impostazioni", "keyboardShortcuts": "Scelte rapide da tastiera", diff --git a/i18n/ita/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..b57afe97de --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "Apri URL", + "developer": "Sviluppatore" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..09c98a2654 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "editor Webview", + "developer": "Sviluppatore" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..ee36d0bcec --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Apri strumenti di sviluppo Webview", + "refreshWebviewLabel": "Ricarica Webview" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/ita/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..647449f942 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Per contribuire al miglioramento di VS Code, è possibile consentire a Microsoft di raccogliere i dati di utilizzo. Leggere l'[informativa sulla privacy]({0}) per informazioni su come [rifiutare esplicitamente]({1}).", + "telemetryOptOut.optInNotice": "Per contribuire al miglioramento di VS Code, è possibile consentire a Microsoft di raccogliere i dati di utilizzo. Leggere l'[informativa sulla privacy]({0}) per informazioni su come [acconsentire esplicitamente]({1}).", + "telemetryOptOut.readMore": "Altre informazioni" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/ita/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index 1036676d6f..697e0512e4 100644 --- a/i18n/ita/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Gestisci le estensioni", "welcomeOverlay.problems": "Visualizza errori e avvisi", "welcomeOverlay.commandPalette": "Trova ed esegui tutti i comandi", + "welcomeOverlay.notifications": "Mostra notifiche", "welcomeOverlay": "Panoramica interfaccia utente", "hideWelcomeOverlay": "Nascondi panoramica interfaccia", "help": "Guida" diff --git a/i18n/ita/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/ita/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 4084cc7f2a..3865d04213 100644 --- a/i18n/ita/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Strumenti e linguaggi", "welcomePage.installExtensionPacksDescription": "Installare il supporto per {0} e {1}", "welcomePage.moreExtensions": "altro", - "welcomePage.installKeymapDescription": "Installa i tasti di scelta rapida", - "welcomePage.installKeymapExtension": "Installa i tasti di scelta rapida di {0} e {1}", + "welcomePage.installKeymapDescription": "Impostazioni e tasti di scelta rapida", + "welcomePage.installKeymapExtension": "Installa le impostazioni e i tasti di scelta rapida di {0} e {1}", "welcomePage.others": "altri", "welcomePage.colorTheme": "Tema colori", "welcomePage.colorThemeDescription": "Tutto quel che serve per configurare editor e codice nel modo desiderato", diff --git a/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index c9713be519..bdae9b7565 100644 --- a/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/ita/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Riepilogo delle impostazioni. Questa etichetta verrà usata nel file di impostazioni come commento di separazione.", "vscode.extension.contributes.configuration.properties": "Descrizione delle proprietà di configurazione.", + "scope.application.description": "Configurazione specifica dell'applicazione, che può essere configurata solo in Impostazioni utente.", "scope.window.description": "Configurazione specifica della finestra, che può essere configurata nelle impostazioni dell'utente o dell'area di lavoro.", "scope.resource.description": "Configurazione specifica di risorse, che possono essere configurate nelle impostazioni utente, in quelle dell'area di lavoro o di una cartella.", "scope.description": "Ambito in cui la configurazione è applicabile. Gli ambiti disponibili sono 'finestra' e 'risorsa'.", diff --git a/i18n/ita/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/ita/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 52f2907175..cff75c16d8 100644 --- a/i18n/ita/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Apri impostazioni", "saveAndRetry": "Salva e riprova", "errorUnknownKey": "Impossibile scrivere {0} perché {1} non è una configurazione registrata.", + "errorInvalidWorkspaceConfigurationApplication": "Non è possibile scrivere {0} in Impostazioni area di lavoro. Questa impostazione può essere scritta solo in Impostazioni utente.", "errorInvalidFolderConfiguration": "Impossibile scrivere nella cartella impostazioni perché {0} non supporta l'ambito di risorsa della cartella.", "errorInvalidUserTarget": "Impossibile scrivere le impostazioni utente perché {0} non supporta l'ambito globale.", "errorInvalidWorkspaceTarget": "Impossibile scrivere nell'area di lavoro perché {0} non supporta l'ambito globale in un'area di lavoro a cartelle multiple.", diff --git a/i18n/ita/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/ita/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..35c50e0a9d --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Questa impostazione può essere applicata solo in Impostazioni utente", + "unsupportedWindowSetting": "Non è possibile applicare ora questa impostazione. Verrà applicata direttamente all'apertura della cartella." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/ita/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/ita/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..a7e1f92550 --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "Non è possibile risolvere '{0}' perché non è assegnato alcun nome di variabile di ambiente.", + "configNotFound": "Non è possibile risolvere '{0}' perché l'impostazione '{1}' non è stata trovata.", + "configNoString": "Non è possibile risolvere '{0}' perché '{1}' è un valore strutturato.", + "missingConfigName": "Non è possibile risolvere '{0}' perché non è assegnato alcun nome di impostazioni.", + "noValueForCommand": "Non è possibile risolvere '{0}' perché al comando non è assegnato alcun valore.", + "canNotFindFolder": "Non è possibile risolvere '{0}'. La cartella '{1}' non esiste.", + "canNotResolveWorkspaceFolderMultiRoot": "Non è possibile risolvere '{0}' in un'area di lavoro a cartelle multiple. Assegnare un ambito a questa variabile usando ':' e un nome di cartella dell'area di lavoro.", + "canNotResolveWorkspaceFolder": "Non è possibile risolvere '{0}'. Aprire una cartella.", + "canNotResolveFile": "Non è possibile risolvere '{0}'. Aprire un editor.", + "canNotResolveLineNumber": "Non è possibile risolvere '{0}'. Assicurarsi che sia selezionata una riga nell'editor attivo.", + "canNotResolveSelectedText": "Non è possibile risolvere '{0}'. Assicurarsi che sia selezionato del testo nell'editor attivo." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/ita/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..bb1f14b4fc --- /dev/null +++ b/i18n/ita/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Sì", + "cancelButton": "Annulla" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/ita/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 3f7dda7232..9038798951 100644 --- a/i18n/ita/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/ita/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Compatibilità del motore.", "vscode.extension.engines.vscode": "Per le estensioni di Visual Studio Code consente di specificare la versione di Visual Studio Code con cui è compatibile l'estensione. Non può essere *. Ad esempio: ^0.10.5 indica la compatibilità con la versione minima 0.10.5 di Visual Studio Code.", "vscode.extension.publisher": "Editore dell'estensione Visual Studio Code.", "vscode.extension.displayName": "Nome visualizzato per l'estensione usato nella raccolta di Visual Studio Code.", "vscode.extension.categories": "Categorie usate dalla raccolta di Visual Studio Code per definire la categoria dell'estensione.", + "vscode.extension.category.languages.deprecated": "Usa in alternativa 'Linguaggi di programmazione'", "vscode.extension.galleryBanner": "Banner usato nel marketplace di Visual Studio Code.", "vscode.extension.galleryBanner.color": "Colore del banner nell'intestazione pagina del marketplace di Visual Studio Code.", "vscode.extension.galleryBanner.theme": "Tema colori per il tipo di carattere usato nel banner.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Un evento di attivazione emesso ogni volta che una sessione di debug di tipo specifico sta per essere lanciata (e un corrispondente metodo resolveDebugConfiguration deve essere chiamato).", "vscode.extension.activationEvents.workspaceContains": "Un evento di attivazione emesso ogni volta che si apre una cartella che contiene almeno un file corrispondente al criterio GLOB specificato.", "vscode.extension.activationEvents.onView": "Un evento di attivazione emesso ogni volta che la visualizzazione specificata viene espansa.", + "vscode.extension.activationEvents.onUri": "Un evento di attivazione emesso ogni volta che viene aperto un URI a livello di sistema indirizzato a questa estensione.", "vscode.extension.activationEvents.star": "Un evento di attivazione emesso all'avvio di VS Code. Per garantire la migliore esperienza per l'utente finale, sei pregato di utilizzare questo evento di attivazione nella tua estensione solo quando nessun'altra combinazione di eventi di attivazione funziona nel tuo caso.", "vscode.extension.badges": "Matrice di notifiche da visualizzare nella barra laterale della pagina delle estensioni del Marketplace.", "vscode.extension.badges.url": "URL di immagine della notifica.", "vscode.extension.badges.href": "Collegamento della notifica.", "vscode.extension.badges.description": "Descrizione della notifica.", + "vscode.extension.markdown": "Controlla il motore di rendering di Markdown usato nel Marketplace. Può essere github (impostazione predefinita) o standard.", + "vscode.extension.qna": "Controlla il collegamento alle domande frequenti nel Marketplace. Impostare su marketplace per abilitare il sito predefinito delle domande frequenti nel Marketplace. Impostare su una stringa per specificare l'URL di un sito personalizzato di domande frequenti. Impostare su false per disabilitare la sezione delle domande frequenti.", "vscode.extension.extensionDependencies": "Dipendenze ad altre estensioni. L'identificatore di un'estensione è sempre ${publisher}.${name}. Ad esempio: vscode.csharp.", "vscode.extension.scripts.prepublish": "Script eseguito prima che il pacchetto venga pubblicato come estensione Visual Studio Code.", "vscode.extension.scripts.uninstall": "Hook di disinstallazione per l'estensione VS Code. Script che viene eseguito quando l'estensione viene disinstallata completamente da VS Code, ovvero quando VS Code viene riavviato (arresto e avvio) dopo la disinstallazione dell'estensione. Sono supportati solo gli script Node.", diff --git a/i18n/ita/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/ita/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index b803950c55..ff5f293ed2 100644 --- a/i18n/ita/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Tutte le estensioni sono disabilitate.", "extensionHostProcess.crash": "L'host dell'estensione è stato terminato in modo imprevisto.", "extensionHostProcess.unresponsiveCrash": "L'host dell'estensione è stato terminato perché non rispondeva.", - "devTools": "Strumenti di sviluppo", + "devTools": "Apri strumenti di sviluppo", "restart": "Riavvia host dell'estensione", "overwritingExtension": "Sovrascrittura dell'estensione {0} con {1}.", "extensionUnderDevelopment": "Caricamento dell'estensione di sviluppo in {0}", diff --git a/i18n/ita/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/ita/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 1c2a0167ae..9d7b1a9583 100644 --- a/i18n/ita/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5 è obbligatorio. Selezionare il collegamento per installarlo.", "installNet": "Scarica .NET Framework 4.5", "neverShowAgain": "Non visualizzare più questo messaggio", - "netVersionError": "Microsoft .NET Framework 4.5 è obbligatorio. Selezionare il collegamento per installarlo.", + "enospcError": "{0} non è in grado di controllare le modifiche di una grande area di lavoro. Per risolvere questo problema, seguire il collegamento alle istruzioni. ", "learnMore": "Istruzioni", - "enospcError": "{0} sta esaurendo gli handle di file. Per risolvere questo problema, seguire il collegamento alle istruzioni.", + "fileInvalidPath": "Risorsa del file non valida ({0})", + "fileIsDirectoryError": "Il File è una Directory", + "fileNotModifiedError": "File non modificato dal giorno", + "fileTooLargeForHeapError": "Per aprire un file di queste dimensioni, è necessario riavviare VS Code e consentirgli di usare più memoria", + "fileTooLargeError": "File troppo grande per essere aperto", + "fileNotFoundError": "Il file non è stato trovato ({0})", + "fileBinaryError": "Il file sembra essere binario e non può essere aperto come file di testo", + "filePermission": "Autorizzazione di scrittura sul file negata ({0}) ", + "fileExists": "Il file da creare esiste già ({0})", + "fileModifiedError": "File modificato da", + "fileReadOnlyError": "Il file è di sola lettura", + "fileMoveConflict": "Non è possibile eseguire operazioni di spostamento/copia. Il file esiste già nella destinazione.", + "unableToMoveCopyError": "Non è possibile eseguire operazioni di spostamento/copia. Il file sostituirebbe la cartella in cui è contenuto.", "binFailed": "Non è stato possibile spostare '{0}' nel Cestino", "trashFailed": "Non è stato possibile spostare '{0}' nel Cestino" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index b94bb6e29c..d842f60e68 100644 --- a/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Il file non è stato trovato ({0})", "fileIsDirectoryError": "Il File è una Directory", "fileNotModifiedError": "File non modificato dal giorno", - "fileBinaryError": "Il file sembra essere binario e non può essere aperto come file di testo" + "fileBinaryError": "Il file sembra essere binario e non può essere aperto come file di testo", + "err.create": "Non è stato possibile creare il file {0}", + "fileMoveConflict": "Non è possibile eseguire operazioni di spostamento/copia. Il file esiste già nella destinazione." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/ita/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..04cf97f29c 100644 --- a/i18n/ita/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/ita/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Annulla" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 482cfc2572..8044dc85e1 100644 --- a/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Nome dell'ambito TextMate usato dal file tmLanguage.", "vscode.extension.contributes.grammars.path": "Percorso del file tmLanguage. È relativo alla cartella delle estensioni e in genere inizia con './syntaxes/'.", "vscode.extension.contributes.grammars.embeddedLanguages": "Mapping tra nome ambito e ID linguaggio se questa grammatica contiene linguaggi incorporati.", + "vscode.extension.contributes.grammars.tokenTypes": "Mapping tra nome di ambito e tipi di token.", "vscode.extension.contributes.grammars.injectTo": "Elenco di nomi di ambito del linguaggio in cui viene inserita questa grammatica." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 9cd6af8e90..cbdb92efcd 100644 --- a/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/ita/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "È previsto un valore stringa in `contributes.{0}.path`. Valore specificato: {1}", "invalid.injectTo": "Il valore in `contributes.{0}.injectTo` non è valido. Deve essere una matrice di nomi di ambito del linguaggio. Valore specificato: {1}", "invalid.embeddedLanguages": "Il valore in `contributes.{0}.embeddedLanguages` non è valido. Deve essere un mapping di oggetti tra nome ambito e linguaggio. Valore specificato: {1}", + "invalid.tokenTypes": "Il valore in `contributes.{0}.tokenTypes` non è valido. Deve essere un mapping di oggetti tra nome ambito e tipo di token. Valore specificato: {1}", "invalid.path.1": "Valore previsto di `contributes.{0}.path` ({1}) da includere nella cartella dell'estensione ({2}). L'estensione potrebbe non essere più portatile.", "no-tm-grammar": "Non è stata registrata alcuna grammatica TM per questo linguaggio." } \ No newline at end of file diff --git a/i18n/jpn/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/jpn/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..6d6b061cb7 --- /dev/null +++ b/i18n/jpn/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS 言語サーバー", + "folding.start": "折りたたみ領域の開始", + "folding.end": "折りたたみ領域の終了" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/css-language-features/package.i18n.json b/i18n/jpn/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..f77f0b75a0 --- /dev/null +++ b/i18n/jpn/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS 言語機能", + "description": "CSS、LESS、SCSS ファイルに豊富な言語サポートを提供。", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "無効なパラメーター数値", + "css.lint.boxModel.desc": "padding や border を使用するときに width や height を使用しないでください", + "css.lint.compatibleVendorPrefixes.desc": "ベンダー プレフィックス を使用するときは、他すべてのベンダー プレフィックスも必ず含めてください", + "css.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", + "css.lint.emptyRules.desc": "空の規則セットを使用しないでください", + "css.lint.float.desc": "'float' の使用を避けてください。float は脆弱な CSS につながり、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", + "css.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", + "css.lint.hexColorLength.desc": "Hex には 3 つまたは 6 つの 16 進数が含まれる必要があります", + "css.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", + "css.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", + "css.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", + "css.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", + "css.lint.propertyIgnoredDueToDisplay.desc": "display によってプロパティを無視します。例: 'display: inline' の場合、width、height、margin-top、margin-bottom、float プロパティには効果がありません。", + "css.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", + "css.lint.unknownProperties.desc": "不明なプロパティ。", + "css.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", + "css.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", + "css.lint.zeroUnits.desc": "0 に単位は必要ありません", + "css.trace.server.desc": "VS Code と CSS 言語サーバー間の通信をトレースします。", + "css.validate.title": "CSS の検証と問題の重大度を制御します。", + "css.validate.desc": "すべての検証を有効または無効にします", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "無効なパラメーター数値", + "less.lint.boxModel.desc": "padding や border を使用するときに width や height を使用しないでください", + "less.lint.compatibleVendorPrefixes.desc": "ベンダー プレフィックス を使用するときは、他すべてのベンダー プレフィックスも必ず含めてください", + "less.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", + "less.lint.emptyRules.desc": "空の規則セットを使用しないでください", + "less.lint.float.desc": "'float' の使用を避けてください。float は脆弱な CSS につながり、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", + "less.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", + "less.lint.hexColorLength.desc": "Hex には 3 つまたは 6 つの 16 進数が含まれる必要があります", + "less.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", + "less.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", + "less.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", + "less.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", + "less.lint.propertyIgnoredDueToDisplay.desc": "display によってプロパティを無視します。例: 'display: inline' の場合、width、height、margin-top、margin-bottom、float プロパティには効果がありません。", + "less.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", + "less.lint.unknownProperties.desc": "不明なプロパティ。", + "less.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", + "less.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", + "less.lint.zeroUnits.desc": "0 に単位は必要ありません", + "less.validate.title": "LESS の検証と問題の重大度を制御します。", + "less.validate.desc": "すべての検証を有効または無効にします", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "無効なパラメーター数値", + "scss.lint.boxModel.desc": "padding や border を使用するときに width や height を使用しないでください", + "scss.lint.compatibleVendorPrefixes.desc": "ベンダー プレフィックス を使用するときは、他すべてのベンダー プレフィックスも必ず含めてください", + "scss.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", + "scss.lint.emptyRules.desc": "空の規則セットを使用しないでください", + "scss.lint.float.desc": "'float' の使用を避けてください。float は脆弱な CSS につながり、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", + "scss.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", + "scss.lint.hexColorLength.desc": "Hex には 3 つまたは 6 つの 16 進数が含まれる必要があります", + "scss.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", + "scss.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", + "scss.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", + "scss.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", + "scss.lint.propertyIgnoredDueToDisplay.desc": "display によってプロパティを無視します。例: 'display: inline' の場合、width、height、margin-top、margin-bottom、float プロパティには効果がありません。", + "scss.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", + "scss.lint.unknownProperties.desc": "不明なプロパティ。", + "scss.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", + "scss.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", + "scss.lint.zeroUnits.desc": "0 に単位は必要ありません", + "scss.validate.title": "SCSS の検証と問題の重大度を制御します。", + "scss.validate.desc": "すべての検証を有効または無効にします", + "less.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", + "scss.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", + "css.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", + "css.colorDecorators.enable.deprecationMessage": "設定 `css.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。", + "scss.colorDecorators.enable.deprecationMessage": "設定 `scss.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。", + "less.colorDecorators.enable.deprecationMessage": "設定 `less.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/css/package.i18n.json b/i18n/jpn/extensions/css/package.i18n.json index d3f6a4beb4..8a47bb3475 100644 --- a/i18n/jpn/extensions/css/package.i18n.json +++ b/i18n/jpn/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS 言語機能", - "description": "CSS、LESS、SCSS ファイルに豊富な言語サポートを提供。", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "無効なパラメーター数値", - "css.lint.boxModel.desc": "padding や border を使用するときに width や height を使用しないでください", - "css.lint.compatibleVendorPrefixes.desc": "ベンダー プレフィックス を使用するときは、他すべてのベンダー プレフィックスも必ず含めてください", - "css.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", - "css.lint.emptyRules.desc": "空の規則セットを使用しないでください", - "css.lint.float.desc": "'float' の使用を避けてください。float は脆弱な CSS につながり、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", - "css.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", - "css.lint.hexColorLength.desc": "Hex には 3 つまたは 6 つの 16 進数が含まれる必要があります", - "css.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", - "css.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", - "css.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", - "css.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", - "css.lint.propertyIgnoredDueToDisplay.desc": "display によってプロパティを無視します。例: 'display: inline' の場合、width、height、margin-top、margin-bottom、float プロパティには効果がありません。", - "css.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", - "css.lint.unknownProperties.desc": "不明なプロパティ。", - "css.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", - "css.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", - "css.lint.zeroUnits.desc": "0 に単位は必要ありません", - "css.trace.server.desc": "VS Code と CSS 言語サーバー間の通信をトレースします。", - "css.validate.title": "CSS の検証と問題の重大度を制御します。", - "css.validate.desc": "すべての検証を有効または無効にします", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "正しくないパラメーターの数", - "less.lint.boxModel.desc": "パディングまたは枠線を使用する場合は幅または高さを使用しないでください", - "less.lint.compatibleVendorPrefixes.desc": "ベンダー固有のプレフィックスを使用する場合は、他のすべてのベンダー固有のプロパティも必ず含めてください", - "less.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", - "less.lint.emptyRules.desc": "空の規則セットを使用しないでください", - "less.lint.float.desc": "'float' は使用しないでください。float を使用すると、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", - "less.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", - "less.lint.hexColorLength.desc": "16 進数の色には、3 つまたは 6 つの 16 進数が含まれる必要があります", - "less.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", - "less.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", - "less.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", - "less.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", - "less.lint.propertyIgnoredDueToDisplay.desc": "表示によりプロパティが無視されます。たとえば、'display: inline' の場合、width、height、margin-top、margin-bottom、および float のプロパティには効果がありません", - "less.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", - "less.lint.unknownProperties.desc": "不明なプロパティ。", - "less.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", - "less.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", - "less.lint.zeroUnits.desc": "0 の単位は必要ありません", - "less.validate.title": "LESS の検証と問題の重大度を制御します。", - "less.validate.desc": "すべての検証を有効または無効にします", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "正しくないパラメーターの数", - "scss.lint.boxModel.desc": "パディングまたは枠線を使用する場合は幅または高さを使用しないでください", - "scss.lint.compatibleVendorPrefixes.desc": "ベンダー固有のプレフィックスを使用する場合は、他のすべてのベンダー固有のプロパティも必ず含めてください", - "scss.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", - "scss.lint.emptyRules.desc": "空の規則セットを使用しないでください", - "scss.lint.float.desc": "'float' は使用しないでください。float を使用すると、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", - "scss.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", - "scss.lint.hexColorLength.desc": "16 進数の色には、3 つまたは 6 つの 16 進数が含まれる必要があります", - "scss.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", - "scss.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", - "scss.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", - "scss.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", - "scss.lint.propertyIgnoredDueToDisplay.desc": "表示によりプロパティが無視されます。たとえば、'display: inline' の場合、width、height、margin-top、margin-bottom、および float のプロパティには効果がありません", - "scss.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", - "scss.lint.unknownProperties.desc": "不明なプロパティ。", - "scss.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", - "scss.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", - "scss.lint.zeroUnits.desc": "0 の単位は必要ありません", - "scss.validate.title": "SCSS の検証と問題の重大度を制御します。", - "scss.validate.desc": "すべての検証を有効または無効にします", - "less.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", - "scss.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", - "css.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", - "css.colorDecorators.enable.deprecationMessage": "設定 `css.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。", - "scss.colorDecorators.enable.deprecationMessage": "設定 `scss.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。", - "less.colorDecorators.enable.deprecationMessage": "設定 `less.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。" + "displayName": "CSS の基本言語サポート", + "description": "CSS、LESS、SCSS ファイル内で構文ハイライト、かっこ一致を提供します。" } \ No newline at end of file diff --git a/i18n/jpn/extensions/emmet/package.i18n.json b/i18n/jpn/extensions/emmet/package.i18n.json index f6dd86d7e2..b62ef40b26 100644 --- a/i18n/jpn/extensions/emmet/package.i18n.json +++ b/i18n/jpn/extensions/emmet/package.i18n.json @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Emmet のプロファイルとスニペットを含むフォルダーへのパス。", "emmetShowExpandedAbbreviation": "展開された Emmet 省略記法を候補として表示します。\n\"inMarkupAndStylesheetFilesOnly\" オプションは、html、haml、jade、slim、xml、xsl、css、scss、sass、less、stylus に適用されます。\n\"always\" オプションは markup/css に関係なくファイルのすべての部分に適用されます。", "emmetShowAbbreviationSuggestions": "利用できる Emmet 省略記法を候補として表示します。スタイルシートや emmet.showExpandedAbbreviation を \"never\" に設定していると適用されません。", - "emmetIncludeLanguages": "既定でサポートされていない言語で Emmet 省略記法を有効にします。 言語と Emmet がサポートする言語の間にマッピングを追加します。\n例: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "既定でサポートされていない言語で Emmet 略語を有効にします。ここに、その言語と Emmet でサポートされる言語のマッピングを追加します。\n 例: {\"vue-html\":\"html\"、\"javascript\":\"javascriptreact\"}", "emmetVariables": "Emmet のスニペットで使用される変数", "emmetTriggerExpansionOnTab": "有効にすると、TAB キーを押したときに Eemmet 省略記法が展開されます。", "emmetPreferences": "Emmet の一部のアクションやリゾルバーの動作の変更に使用される基本設定。", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Emmet 省略記法で使用される場合に `-` で始まる 'webkit' ベンダー プレフィックスを取得するカンマ区切りの CSS プロパティ。常に 'webkit' プレフィックスを避ける場合は空の文字列に設定します。", "emmetPreferencesCssMozProperties": "Emmet 省略記法で使用される場合に `-` で始まる 'moz' ベンダー プレフィックスを取得するカンマ区切りの CSS プロパティ。常に 'moz' プレフィックスを避ける場合は空の文字列に設定します。", "emmetPreferencesCssOProperties": "Emmet 省略記法で使用される場合に `-` で始まる 'o' ベンダー プレフィックスを取得するカンマ区切りの CSS プロパティ。常に 'o' プレフィックスを避ける場合は空の文字列に設定します。", - "emmetPreferencesCssMsProperties": "Emmet 省略記法で使用される場合に `-` で始まる 'ms' ベンダー プレフィックスを取得するカンマ区切りの CSS プロパティ。常に 'ms' プレフィックスを避ける場合は空の文字列に設定します。" + "emmetPreferencesCssMsProperties": "Emmet 省略記法で使用される場合に `-` で始まる 'ms' ベンダー プレフィックスを取得するカンマ区切りの CSS プロパティ。常に 'ms' プレフィックスを避ける場合は空の文字列に設定します。", + "emmetPreferencesCssFuzzySearchMinScore": "あいまい検索の省略形が達成すべき (0 から 1 の) 最小スコア。値が低ければ多くの誤検出が発生する可能性があります。値が高ければ一致する見込みが減る可能性があります。", + "emmetOptimizeStylesheetParsing": "false に設定すると、現在位置が Emmet 略語の展開位置として有効かどうかを判定するためにファイル全体を解析します。true に設定すると、css/scss/less ファイルの現在位置周辺のコンテンツのみを解析します。" } \ No newline at end of file diff --git a/i18n/jpn/extensions/git/out/commands.i18n.json b/i18n/jpn/extensions/git/out/commands.i18n.json index 60964323c4..2a37bf2715 100644 --- a/i18n/jpn/extensions/git/out/commands.i18n.json +++ b/i18n/jpn/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) 新しいブランチを作成", "repourl": "リポジトリ URL", "parent": "親ディレクトリ", - "cancel": "$(sync~spin) リポジトリのクローン中... キャンセルをクリックしてください", - "cancel tooltip": "クローンのキャンセル", - "cloning": "Git リポジトリを複製しています...", + "cloning": "Git リポジトリ '{0}' を複製しています...", "openrepo": "リポジトリを開く", "proposeopen": "クローンしたリポジトリを開きますか?", "init": "Git リポジトリを初期化するワークスペース フォルダーを選択してください", @@ -75,7 +73,7 @@ "ok": "OK", "push with tags success": "タグが正常にプッシュされました。", "pick remote": "リモートを選んで、ブランチ '{0}' を次に公開します:", - "sync is unpredictable": "このアクションはコミットを '{0}' との間でプッシュしたりプルしたりします。", + "sync is unpredictable": "このアクションはコミットを '{0}/{1}' との間でプッシュしたりプルしたりします。", "never again": "OK、今後は表示しない", "no remotes to publish": "リポジトリには、発行先として構成されているリモートがありません。", "no changes stash": "スタッシュする変更がありません。", diff --git a/i18n/jpn/extensions/git/package.i18n.json b/i18n/jpn/extensions/git/package.i18n.json index 3f0d557455..b0f10bc7ee 100644 --- a/i18n/jpn/extensions/git/package.i18n.json +++ b/i18n/jpn/extensions/git/package.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "displayName": "Git", - "description": "Git SCM の統合", + "description": "Git SCM統合", "command.clone": "クローン", "command.init": "リポジトリの初期化", "command.close": "リポジトリを閉じる", @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Git 変更の表示内にインラインのファイルを開くアクションを表示するかどうかを制御します。", "config.inputValidation": "コミット メッセージの入力検証をいつ表示するかを制御します。", "config.detectSubmodules": "Git のサブモジュールを自動的に検出するかどうかを制御します。", + "config.detectSubmodulesLimit": "Git サブモジュールの検出の制限を制御します。", "colors.modified": "リソースを改変した場合の配色", "colors.deleted": "リソースを検出した場合の配色", "colors.untracked": "リソースを追跡しない場合の配色", diff --git a/i18n/jpn/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/jpn/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..ed3272fd70 --- /dev/null +++ b/i18n/jpn/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML 言語サーバー", + "folding.start": "折りたたみ領域の開始", + "folding.end": "折りたたみ領域の終了" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/html-language-features/package.i18n.json b/i18n/jpn/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..18b6e348d4 --- /dev/null +++ b/i18n/jpn/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML 言語機能", + "description": "HTML、Razor、Handlebar ファイルに豊富な言語サポートを提供。", + "html.format.enable.desc": "既定の HTML フォーマッタを有効/無効にします", + "html.format.wrapLineLength.desc": "1 行あたりの最大文字数 (0 = 無効にする)。", + "html.format.unformatted.desc": "再フォーマットしてはならないタグの、コンマ区切りの一覧。'null' の場合、既定で https://www.w3.org/TR/html5/dom.html#phrasing-content にリストされているすべてのタグになります。", + "html.format.contentUnformatted.desc": "コンテンツを再フォーマットしてはならないタグをコンマで区切ってリストにします。'null' は、既定値の 'pre' タグを表します。", + "html.format.indentInnerHtml.desc": "<head> セクションと <body> セクションをインデントします。", + "html.format.preserveNewLines.desc": "要素の前にある既存の改行を保持するかどうか。要素の前でのみ機能し、タグの内側やテキストに対しては機能しません。", + "html.format.maxPreserveNewLines.desc": "1 つのチャンク内に保持できる改行の最大数。無制限にするには、'null' を使います。", + "html.format.indentHandlebars.desc": "書式設定とインデント {{#foo}} および {{/foo}}。", + "html.format.endWithNewline.desc": "末尾に改行を入れます。", + "html.format.extraLiners.desc": "直前に改行を 1 つ入れるタグの、コンマで区切られたリストです。'null' は、既定値の \"head, body, /html\" を表します。", + "html.format.wrapAttributes.desc": "属性を折り返します。", + "html.format.wrapAttributes.auto": "行の長さが超過した場合のみ属性を折り返します。", + "html.format.wrapAttributes.force": "先頭以外の各属性を折り返します。", + "html.format.wrapAttributes.forcealign": "先頭以外の各属性を折り返して位置を合わせます。", + "html.format.wrapAttributes.forcemultiline": "各属性を折り返します。", + "html.suggest.angular1.desc": "ビルトイン HTML 言語サポートが Angular V1 のタグおよびプロパティを候補表示するかどうかを構成します。", + "html.suggest.ionic.desc": "ビルトイン HTML 言語サポートが Ionic のタグ、プロパティ、および値を候補表示するかどうかを構成します。", + "html.suggest.html5.desc": "ビルトイン HTML 言語サポートが HTML5 のタグ、プロパティ、および値を候補表示するかどうかを構成します。", + "html.trace.server.desc": "VS Code と HTML 言語サーバー間の通信をトレースします。", + "html.validate.scripts": "ビルトイン HTML 言語サポートが埋め込みスクリプトを検証するかどうかを構成します。", + "html.validate.styles": "ビルトイン HTML 言語サポートが埋め込みスタイルを検証するかどうかを構成します。", + "html.autoClosingTags": "HTML タグの自動クローズを有効/無効にします。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/html/package.i18n.json b/i18n/jpn/extensions/html/package.i18n.json index e2a97afec1..2be6a2bcf4 100644 --- a/i18n/jpn/extensions/html/package.i18n.json +++ b/i18n/jpn/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML 言語機能", - "description": "HTML、Razor、Handlebar ファイルに豊富な言語サポートを提供。", - "html.format.enable.desc": "既定の HTML フォーマッタを有効/無効にします", - "html.format.wrapLineLength.desc": "1 行あたりの最大文字数 (0 = 無効にする)。", - "html.format.unformatted.desc": "再フォーマットしてはならないタグの、コンマ区切りの一覧。'null' の場合、既定で https://www.w3.org/TR/html5/dom.html#phrasing-content にリストされているすべてのタグになります。", - "html.format.contentUnformatted.desc": "コンテンツを再フォーマットしてはならないタグをコンマで区切ってリストにします。'null' は、既定値の 'pre' タグを表します。", - "html.format.indentInnerHtml.desc": "<head> セクションと <body> セクションをインデントします。", - "html.format.preserveNewLines.desc": "要素の前にある既存の改行を保持するかどうか。要素の前でのみ機能し、タグの内側やテキストに対しては機能しません。", - "html.format.maxPreserveNewLines.desc": "1 つのチャンク内に保持できる改行の最大数。無制限にするには、'null' を使います。", - "html.format.indentHandlebars.desc": "書式設定とインデント {{#foo}} および {{/foo}}。", - "html.format.endWithNewline.desc": "末尾に改行を入れます。", - "html.format.extraLiners.desc": "直前に改行を 1 つ入れるタグの、コンマで区切られたリストです。'null' は、既定値の \"head, body, /html\" を表します。", - "html.format.wrapAttributes.desc": "属性を折り返します。", - "html.format.wrapAttributes.auto": "行の長さが超過した場合のみ属性を折り返します。", - "html.format.wrapAttributes.force": "先頭以外の各属性を折り返します。", - "html.format.wrapAttributes.forcealign": "先頭以外の各属性を折り返して位置を合わせます。", - "html.format.wrapAttributes.forcemultiline": "各属性を折り返します。", - "html.suggest.angular1.desc": "ビルトイン HTML 言語サポートが Angular V1 のタグおよびプロパティを候補表示するかどうかを構成します。", - "html.suggest.ionic.desc": "ビルトイン HTML 言語サポートが Ionic のタグ、プロパティ、および値を候補表示するかどうかを構成します。", - "html.suggest.html5.desc": "ビルトイン HTML 言語サポートが HTML5 のタグ、プロパティ、および値を候補表示するかどうかを構成します。", - "html.trace.server.desc": "VS Code と HTML 言語サーバー間の通信をトレースします。", - "html.validate.scripts": "ビルトイン HTML 言語サポートが埋め込みスクリプトを検証するかどうかを構成します。", - "html.validate.styles": "ビルトイン HTML 言語サポートが埋め込みスタイルを検証するかどうかを構成します。", - "html.experimental.syntaxFolding": "構文の折りたたみマーカー認識を有効/無効にします。", - "html.autoClosingTags": "HTML タグの自動クローズを有効/無効にします。" + "displayName": "HTML の基本言語サポート", + "description": "HTML ファイル内で構文ハイライト、かっこ一致、スニペットを提供" } \ No newline at end of file diff --git a/i18n/jpn/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/jpn/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..2700229f8e --- /dev/null +++ b/i18n/jpn/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON 言語サーバー" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/json-language-features/package.i18n.json b/i18n/jpn/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..2960f3fa69 --- /dev/null +++ b/i18n/jpn/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON 言語機能", + "description": "JSON ファイルに豊富な言語サポートを提供。", + "json.schemas.desc": "スキーマを現在のプロジェクトの JSON ファイルに関連付けます", + "json.schemas.url.desc": "スキーマへの URL または現在のディレクトリのスキーマへの相対パス", + "json.schemas.fileMatch.desc": "JSON ファイルをスキーマに解決する場合に一致するファイル パターンの配列です。", + "json.schemas.fileMatch.item.desc": "JSON ファイルをスキーマに解決する場合に一致するよう '*' を含む可能性があるファイル パターンです。", + "json.schemas.schema.desc": "指定された URL のスキーマ定義です。スキーマは、スキーマ URL へのアクセスを避けるためにのみ指定する必要があります。", + "json.format.enable.desc": "既定の JSON フォーマッタを有効/無効にします (再起動が必要です)", + "json.tracing.desc": "VS Code と JSON 言語サーバー間の通信をトレースします。", + "json.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", + "json.colorDecorators.enable.deprecationMessage": "設定 `json.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/json/package.i18n.json b/i18n/jpn/extensions/json/package.i18n.json index e3daed82a1..e1aa3dfa1b 100644 --- a/i18n/jpn/extensions/json/package.i18n.json +++ b/i18n/jpn/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON 言語機能", - "description": "JSON ファイルに豊富な言語サポートを提供。", - "json.schemas.desc": "スキーマを現在のプロジェクトの JSON ファイルに関連付けます", - "json.schemas.url.desc": "スキーマへの URL または現在のディレクトリのスキーマへの相対パス", - "json.schemas.fileMatch.desc": "JSON ファイルをスキーマに解決する場合に一致するファイル パターンの配列です。", - "json.schemas.fileMatch.item.desc": "JSON ファイルをスキーマに解決する場合に一致するよう '*' を含む可能性があるファイル パターンです。", - "json.schemas.schema.desc": "指定された URL のスキーマ定義です。スキーマは、スキーマ URL へのアクセスを避けるためにのみ指定する必要があります。", - "json.format.enable.desc": "既定の JSON フォーマッタを有効/無効にします (再起動が必要です)", - "json.tracing.desc": "VS Code と JSON 言語サーバー間の通信をトレースします。", - "json.colorDecorators.enable.desc": "カラー デコレーターを有効または無効にします", - "json.colorDecorators.enable.deprecationMessage": "設定 `json.colorDecorators.enable` は使用されなくなりました。`editor.colorDecorators` を使用してください。", - "json.experimental.syntaxFolding": "構文の折りたたみマーカー認識を有効/無効にします。" + "displayName": "JSON の基本言語サポート", + "description": "JSON ファイル内で構文ハイライト、かっこ一致を提供" } \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown-basics/package.i18n.json b/i18n/jpn/extensions/markdown-basics/package.i18n.json index 50b3f66d21..24adb74821 100644 --- a/i18n/jpn/extensions/markdown-basics/package.i18n.json +++ b/i18n/jpn/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/jpn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/jpn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..0489b0c366 --- /dev/null +++ b/i18n/jpn/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "'markdown.styles' を読み込むことができません: {0}" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/jpn/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..21f810889f --- /dev/null +++ b/i18n/jpn/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[プレビュー] {0}", + "previewTitle": "プレビュー {0}" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/jpn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..8031d3c647 --- /dev/null +++ b/i18n/jpn/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "このドキュメントで一部のコンテンツが無効になっています", + "preview.securityMessage.title": "安全でない可能性があるか保護されていないコンテンツは、マークダウン プレビューで無効化されています。保護されていないコンテンツやスクリプトを有効にするには、マークダウン プレビューのセキュリティ設定を変更してください", + "preview.securityMessage.label": "セキュリティが無効なコンテンツの警告" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown-language-features/out/security.i18n.json b/i18n/jpn/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..4e88fd4f8b --- /dev/null +++ b/i18n/jpn/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "高レベル", + "strict.description": "セキュリティで保護されたコンテンツのみを読み込む", + "insecureLocalContent.title": "安全でないローカル コンテンツを許可する", + "insecureLocalContent.description": "localhost から http で提供されるコンテンツの読み込みを有効にします", + "insecureContent.title": "セキュリティで保護されていないコンテンツを許可する", + "insecureContent.description": "HTTP を介したコンテンツの読み込みを有効にする", + "disable.title": "無効にする", + "disable.description": "すべてのコンテンツとスクリプトの実行を許可します。推奨されません。", + "moreInfo.title": "詳細情報", + "enableSecurityWarning.title": "このワークスペースでプレビューのセキュリティ警告を有効にする", + "disableSecurityWarning.title": "このワークスペースでプレビューのセキュリティ警告を有効にする", + "toggleSecurityWarning.description": "コンテンツのセキュリティ レベルに影響しません", + "preview.showPreviewSecuritySelector.title": "ワークスペースのマークダウン プレビューに関するセキュリティ設定を選択 " +} \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown-language-features/package.i18n.json b/i18n/jpn/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..58b68df0b7 --- /dev/null +++ b/i18n/jpn/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown 言語機能", + "description": "Markdown に豊富な言語サポートを提供。", + "markdown.preview.breaks.desc": "マークダウン プレビューで改行をレンダリングする方法を設定します。'true' に設定すると改行ごとに <br> を作成します。", + "markdown.preview.linkify": "マークダウン プレビューで URL 形式のテキストからリンクへの変換を有効または無効にします。", + "markdown.preview.doubleClickToSwitchToEditor.desc": "マークダウンのプレビューでダブルクリックすると、エディターに切り替わります。", + "markdown.preview.fontFamily.desc": "マークダウン プレビューで使用されるフォント ファミリを制御します。", + "markdown.preview.fontSize.desc": "マークダウン プレビューで使用されるフォント サイズ (ピクセル単位) を制御します。", + "markdown.preview.lineHeight.desc": "マークダウン プレビューで使用される行の高さを制御します。この数値はフォント サイズを基準とします。", + "markdown.preview.markEditorSelection.desc": "マークダウンのプレビューに、エディターの現在の選択範囲を示すマークが付きます。", + "markdown.preview.scrollEditorWithPreview.desc": "マークダウンのプレビューをスクロールすると、エディターのビューが更新されます 。", + "markdown.preview.scrollPreviewWithEditor.desc": "マークダウンのエディターをスクロールすると、プレビューのビューが更新されます。", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[非推奨] エディターの現在選択されている行を表示するためにマークダウン プレビューをスクロールします。", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "この設定は 'markdown.preview.scrollPreviewWithEditor' に置き換えられ、もはや有効ではありません。", + "markdown.preview.title": "プレビューを開く", + "markdown.previewFrontMatter.dec": "マークダウン プレビューで YAML front matter がレンダリングされる方法を設定します。'hide' の場合、front matter が削除されます。その他の場合には、front matter はマークダウン コンテンツとして処理されます。", + "markdown.previewSide.title": "プレビューを横に表示", + "markdown.showLockedPreviewToSide.title": "ロックされたプレビューを横に表示", + "markdown.showSource.title": "ソースの表示", + "markdown.styles.dec": "マークダウン プレビューから使用する CSS スタイル シートの URL またはローカル パスの一覧。相対パスは、エクスプローラーで開かれているフォルダーへの絶対パスと解釈されます。開かれているフォルダーがない場合、マークダウン ファイルの場所を基準としていると解釈されます。'\\' はすべて '\\\\' と入力する必要があります。", + "markdown.showPreviewSecuritySelector.title": "プレビュー のセキュリティ設定を変更", + "markdown.trace.desc": "マークダウン拡張機能のデバッグ ログを有効にします。", + "markdown.preview.refresh.title": "プレビューを更新", + "markdown.preview.toggleLock.title": "プレビュー ロックの切り替え" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown/out/features/preview.i18n.json b/i18n/jpn/extensions/markdown/out/features/preview.i18n.json index bd71e11334..21f810889f 100644 --- a/i18n/jpn/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/jpn/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/jpn/extensions/npm/out/npmView.i18n.json b/i18n/jpn/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..65a4786ba2 --- /dev/null +++ b/i18n/jpn/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "スクリプトの Node デバッグ オプションが不足しているため、\"{0}\" をデバッグ起動できません。例: --inspect-brk\"。", + "npm.scriptInvalid": "スクリプト '{0}' が見つかりませんでした。ビューを更新してください。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/npm/out/tasks.i18n.json b/i18n/jpn/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..3995a9c7f9 --- /dev/null +++ b/i18n/jpn/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "npmタスク検出: ファイル {0} の解析に失敗しました" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/npm/package.i18n.json b/i18n/jpn/extensions/npm/package.i18n.json index ac6f54da92..dc9753211e 100644 --- a/i18n/jpn/extensions/npm/package.i18n.json +++ b/i18n/jpn/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "`--silent` オプションを使用して npm コマンドを実行する。", "config.npm.packageManager": "スクリプトを実行するために使用するパッケージ マネージャー。", "config.npm.exclude": "自動スクリプト検出から除外するフォルダーの glob パターンを構成します。", + "config.npm.enableScriptExplorer": "'package.json' ファイルがワークスペースに含まれている場合、npm スクリプトのエクスプ ローラー ビューを有効にします。", "npm.parseError": "npmタスク検出: ファイル {0} の解析に失敗しました", "taskdef.script": "カスタマイズする npm スクリプト。", - "taskdef.path": "スクリプトを提供する package.json ファイルのフォルダーへのパス。省略をすることができます。" + "taskdef.path": "スクリプトを提供する package.json ファイルのフォルダーへのパス。省略をすることができます。", + "view.name": "Npm スクリプト", + "command.refresh": "最新の情報に更新", + "command.run": "実行", + "command.debug": "デバッグ", + "command.openScript": "Open", + "npm.scriptInvalid": "スクリプト '{0}' が見つかりませんでした。ビューを更新してください。", + "npm.noDebugOptions": "スクリプトの Node デバッグ オプションが不足しているため、\"{0}\" をデバッグ起動できません。例: --inspect-brk\"。" } \ No newline at end of file diff --git a/i18n/jpn/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/jpn/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..3f34bb85ea --- /dev/null +++ b/i18n/jpn/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "PHP ファイルを lint するために {0} (ワークスペースの設定として定義されている) を実行することを許可しますか?", + "php.yes": "許可", + "php.no": "許可しない", + "wrongExecutable": "{0} が有効な PHP 実行可能ファイルではないため、検証できません。設定 'php.validate.executablePath' を使用して PHP 実行可能ファイルを構成してください。", + "noExecutable": "PHP 実行可能ファイルが設定されていないため、検証できません。設定 'php.validate.executablePath' を使用して PHP 実行可能ファイルを構成してください。", + "unknownReason": "パス {0} を使用して php を実行できませんでした。理由は不明です。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/php-language-features/package.i18n.json b/i18n/jpn/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..15a98a885d --- /dev/null +++ b/i18n/jpn/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "組み込みの PHP 言語候補機能を有効にするかどうかを設定します。このサポートによって、PHP グローバルと変数の候補が示されます。", + "configuration.validate.enable": "組み込みの PHP 検証を有効/無効にします。", + "configuration.validate.executablePath": "PHP 実行可能ファイルを指定します。", + "configuration.validate.run": "リンターを保存時に実行するか、入力時に実行するか。", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "PHP の検証を無効にします (ワークスペース設定として定義)。", + "displayName": "PHP 言語機能", + "description": "PHP ファイルに豊富な言語サポートを提供します。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/php/package.i18n.json b/i18n/jpn/extensions/php/package.i18n.json index 19c06bde8a..16bb0ef7ca 100644 --- a/i18n/jpn/extensions/php/package.i18n.json +++ b/i18n/jpn/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "組み込みの PHP 言語候補機能を有効にするかどうかを設定します。このサポートによって、PHP グローバルと変数の候補が示されます。", - "configuration.validate.enable": "組み込みの PHP 検証を有効/無効にします。", - "configuration.validate.executablePath": "PHP 実行可能ファイルを指定します。", - "configuration.validate.run": "リンターを保存時に実行するか、入力時に実行するか。", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "PHP の検証を無効にします (ワークスペース設定として定義)。", - "displayName": "PHP 言語機能", - "description": "PHP ファイルの IntelliSense、リンティング、および基本言語サポートを提供します。" + "displayName": "PHP の基本言語サポート", + "description": "PHP ファイル内に構文ハイライト、かっこ一致を提供します。" } \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/commands.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..e69dc45423 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "TypeScript または JavaScript プロジェクトを使用するには、VS Code でフォルダーを開いてください", + "typescript.projectConfigUnsupportedFile": "TypeScript または JavaScript のプロジェクトを判別できませんでした。サポートされていないファイルの種類です", + "typescript.projectConfigCouldNotGetInfo": "TypeScript または JavaScript のプロジェクトを判別できませんでした", + "typescript.noTypeScriptProjectConfig": "ファイルは TypeScript プロジェクトの一部ではありません。詳細情報は [こちら]({1}) をクリックしてください。", + "typescript.noJavaScriptProjectConfig": "ファイルは JavaScript プロジェクトの一部ではありません。詳細情報は [こちら]({1}) をクリックしてください。", + "typescript.configureTsconfigQuickPick": "tsconfig.json を構成する", + "typescript.configureJsconfigQuickPick": "jsconfig.json を構成する" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..adb307b976 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "適用するコード アクションを選択", + "acquiringTypingsLabel": "Typings の定義ファイルを取得中...", + "acquiringTypingsDetail": "IntelliSense の Typings の定義ファイルを取得しています。", + "autoImportLabel": "{0} から自動インポート" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..19d9bea48d --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "JavaScript ファイルのセマンティック チェックを有効にします。 ファイルの先頭にある必要があります。", + "ts-nocheck": "JavaScript ファイルのセマンティック チェックを無効にします。 ファイルの先頭にある必要があります。", + "ts-ignore": "ファイルの次の行で @ts-check エラーを抑制します。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..64c5084a0d --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 個の実装", + "manyImplementationLabel": "{0} 個の実装", + "implementationsErrorLabel": "実装を特定できませんでした" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..26a29c2851 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc コメント" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..7882c9fa95 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "インポートを整理" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..453c92d619 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (ファイルの中のすべてを修正する)" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..71699891f3 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 個の参照", + "manyReferenceLabel": "{0} 個の参照", + "referenceErrorLabel": "参照を判別できませんでした" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..bb8e166d15 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "ビルド - {0}", + "buildAndWatchTscLabel": "ウォッチ - {0}" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..904634944f --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "パス {0} は、有効な tsserver インストールを指していません。バンドルされている TypeScript バージョンにフォールバックしています。", + "serverCouldNotBeStarted": "TypeScript 言語サーバーを起動できません。エラー メッセージ: {0}", + "typescript.openTsServerLog.notSupported": "TS サーバーのログには TS 2.2.2 以降が必要です", + "typescript.openTsServerLog.loggingNotEnabled": "TS サーバーのログがオフになっています。ログを有効にするには、`typescript.tsserver.log` を設定して TS サーバーを再起動してください", + "typescript.openTsServerLog.enableAndReloadOption": "ログを有効にして、TS サーバーを再起動する", + "typescript.openTsServerLog.noLogFile": "TS サーバーはログを開始していません。", + "openTsServerLog.openFileFailedFailed": "TS サーバーのログ ファイルを開くことができませんでした", + "serverDiedAfterStart": "TypeScript 言語サービスは、開始直後に 5 回停止しました。サービスは再開されません。", + "serverDiedReportIssue": "問題の報告", + "serverDied": "TypeScript 言語サービスは、直前の 5 分間に 5 回、予期せずに停止しました。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..4b09d67cea --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "バージョンが無効です" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..d4f07accea --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "プロジェクト全体の JavaScript/TypeScript 言語機能を有効にするには、多数のファイルが含まれるフォルダーを除外します。例: {0}", + "hintExclude.generic": "プロジェクト全体の JavaScript/TypeScript 言語機能を有効にするには、作業していないソース ファイルが含まれるサイズの大きなフォルダーを除外します。", + "large.label": "除外の構成", + "hintExclude.tooltip": "プロジェクト全体の JavaScript/TypeScript 言語機能を有効にするには、作業していないソース ファイルが含まれるサイズの大きなフォルダーを除外します。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..416302dc01 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "より適した TypeScript IntelliSense に関するデータをフェッチしています", + "typesInstallerInitializationFailed.title": "JavaScript 言語機能のための型定義ファイルをインストールできませんでした。NPM のインストールを確認するか、ユーザー設定で 'typescript.npm' を構成してください。詳細は [こちら]({0}) をクリックしてください。", + "typesInstallerInitializationFailed.doNotCheckAgain": "今後は表示しない" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..e9aaf97815 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "VS Code のバージョンを使用", + "useWorkspaceVersionOption": "ワークスペースのバージョンを使用", + "learnMore": "詳細情報", + "selectTsVersion": "JavaScript および TypeScript 言語の機能に使用する TypeScript バージョンを選択します" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/jpn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..bb98209ca7 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "このパスでは TypeScript のバージョンを読み込むことができません", + "noBundledServerFound": "VS Code の tsserver が適切に動作しないウイルス検出ツールなどの他アプリケーションにより削除されました。VS Code を再インストールしてください。" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript-language-features/package.i18n.json b/i18n/jpn/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..9cfdd47338 --- /dev/null +++ b/i18n/jpn/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript と JavaScript の言語機能", + "description": "JavaScript と TypeScript ファイルに豊富な言語サポートを提供。", + "typescript.reloadProjects.title": "プロジェクトの再読み込み", + "javascript.reloadProjects.title": "プロジェクトの再読み込み", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "パラメーター シグネチャを含む完全な関数。", + "typescript.tsdk.desc": "使用する tsserver と lib*.d.ts ファイルが含まれているフォルダーのパスを指定します。", + "typescript.disableAutomaticTypeAcquisition": "型定義の自動取得を無効にします。TypeScript 2.0.6 以上が必要です。", + "typescript.tsserver.log": "ファイルへの TS サーバーのログを有効にします。このログは TS サーバーの問題を診断するために使用できます。ログには、プロジェクトのファイルパス、ソースコード、その他の潜在的に機密性の高い情報が含まれている場合があります。", + "typescript.tsserver.pluginPaths": "Typescript 言語サービス プラグインを検出する追加のパス。TypeScript 2.3.0以上が必要。", + "typescript.tsserver.pluginPaths.item": "絶対または相対パスのいずれか。相対パスはワークスペース フォルダーに対して解決されます。", + "typescript.tsserver.trace": "TS サーバーに送信されるメッセージのトレースを有効にします。このトレースは TS サーバーの問題を診断するために使用できます。トレースには、プロジェクトのファイルパス、ソースコード、その他の潜在的に機密性の高い情報が含まれている場合があります。", + "typescript.validate.enable": "TypeScript の検証を有効/無効にします。", + "typescript.format.enable": "既定の TypeScript フォーマッタを有効/無効にします。", + "javascript.format.enable": "既定の JavaScript フォーマッタを有効/無効にします。", + "format.insertSpaceAfterCommaDelimiter": "コンマ区切り記号の後のスペース処理を定義します。", + "format.insertSpaceAfterConstructor": "コンストラクター キーワードの後にスペース処理を定義します。TypeScript が 2.3.0 以上である必要があります。", + "format.insertSpaceAfterSemicolonInForStatements": " for ステートメント内のセミコロンの後のスペース処理を定義します。", + "format.insertSpaceBeforeAndAfterBinaryOperators": "2 項演算子の後のスペース処理を定義します。", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "制御フロー ステートメント内のキーワードの後のスペース処理を定義します。", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "匿名関数の関数キーワードの後のスペース処理を定義します。", + "format.insertSpaceBeforeFunctionParenthesis": "関数の引数のかっこの前にあるスペース処理を定義します。TypeScript が 2.1.5. 以上である必要があります。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "左右の空でないかっこの間のスペース処理を定義します。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "左右の空でない角かっこの間のスペース処理を定義します。", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "左右の空でないかっこの間のスペース処理を定義します。TypeScript が 2.3.0 以上である必要があります。", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "テンプレート文字列の始め波かっこの後と終わり波かっこの前のスペース処理を定義します。TypeScript が 2.0.6 以上である必要があります。", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "JSX 式の始め波かっこの後と終わり波かっこの前のスペース処理を定義します。TypeScript が 2.0.6 以上である必要があります。", + "format.insertSpaceAfterTypeAssertion": "TypeScript の型アサーションの後のスペース処理を定義します。TypeScript が 2.4 以上である必要があります。", + "format.placeOpenBraceOnNewLineForFunctions": "新しい行に関数の始め波かっこを配置するかどうかを定義します。", + "format.placeOpenBraceOnNewLineForControlBlocks": "新しい行にコントロール ブロックの始め波かっこを配置するかどうかを定義します。", + "javascript.validate.enable": "JavaScript の検証を有効/無効にします。", + "typescript.goToProjectConfig.title": "プロジェクト構成に移動", + "javascript.goToProjectConfig.title": "プロジェクト構成に移動", + "javascript.referencesCodeLens.enabled": "JavaScript ファイル内で CodeLens の参照を有効/無効にします。", + "typescript.referencesCodeLens.enabled": "TypeScript ファイル内で CodeLens の参照を有効/無効にします。TypeScript 2.0.6 以上が必要です。", + "typescript.implementationsCodeLens.enabled": "CodeLens の実装を有効/無効にします。TypeScript 2.2.0 以上が必要です。", + "typescript.openTsServerLog.title": "TS サーバーのログを開く", + "typescript.restartTsServer": "TS サーバーを再起動", + "typescript.selectTypeScriptVersion.title": "TypeScript のバージョンの選択", + "typescript.reportStyleChecksAsWarnings": "スタイルチェックレポートを警告扱いとする", + "jsDocCompletion.enabled": " 自動 JSDoc コメントを有効/無効にします", + "javascript.implicitProjectConfig.checkJs": "JavaScript ファイルのセマンティック チェックを有効/無効にします。既存の jsconfi.json や tsconfi.json ファイルの設定はこれより優先されます。TypeScript は 2.3.1 以上である必要があります。", + "typescript.npm": "型定義の自動取得に使用される NPM 実行可能ファイルへのパスを指定します。TypeScript 2.3.4 以上が必要です。", + "typescript.check.npmIsInstalled": "型定義の自動取得に NPM がインストールされているかどうかを確認します。", + "javascript.nameSuggestions": "JavaScript の候補リスト内でファイルから一意の名前を含むかどうかを有効/無効にします。", + "typescript.tsc.autoDetect": "tsc タスクの自動検出を制御します。'off' はこの機能を無効にします。'build' は 1 つのコンパイル実行タスクのみを表示します。'watch' はコンパイルとウォッチ タスクのみを表示します。'on' はビルド タスクとウォッチ タスクの両方を表示します。既定値は 'on' です。", + "typescript.problemMatchers.tsc.label": "TypeScript の問題", + "typescript.problemMatchers.tscWatch.label": "TypeScript の問題 (ウォッチ モード)", + "typescript.quickSuggestionsForPaths": "Import パスを入力するときのクイック候補を有効/無効にします。", + "typescript.locale": "TypeScript のエラーを報告するために使用するロケールを設定します。TypeScript 2.6.0 以上が必要です。'null' の規定値は TypeScript のエラーに VS Code のロケールを使用します。", + "javascript.implicitProjectConfig.experimentalDecorators": "プロジェクト外の JavaScript ファイルの 'experimentalDecorators' を有効/無効にします。既存の jsconfi.json や tsconfi.json ファイルの設定はこれより優先されます。TypeScript は 2.3.1 以上である必要があります。", + "typescript.autoImportSuggestions.enabled": "自動 import 提案を有効/無効にします。TypeScript 2.6.1 以上が必要です", + "typescript.experimental.syntaxFolding": "構文の折りたたみマーカー認識を有効/無効にします。", + "taskDefinition.tsconfig.description": "TS ビルドを定義する tsconfig ファイル。", + "javascript.suggestionActions.enabled": "エディター内で JavaScript ファイルの診断の提案を有効または無効にします。TypeScript 2.8 以上である必要があります。", + "typescript.suggestionActions.enabled": "エディター内で TypeScript ファイルの診断の提案を有効または無効にします。TypeScript 2.8 以上である必要があります。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/base/node/processes.i18n.json b/i18n/jpn/src/vs/base/node/processes.i18n.json index 33f50a8f3d..a5e43e509d 100644 --- a/i18n/jpn/src/vs/base/node/processes.i18n.json +++ b/i18n/jpn/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "UNC ドライブでシェル コマンドを実行できません。" + "TaskRunner.UNC": "UNC ドライブ上のシェル コマンドを実行できません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/base/node/zip.i18n.json b/i18n/jpn/src/vs/base/node/zip.i18n.json index e834107745..005cfd7640 100644 --- a/i18n/jpn/src/vs/base/node/zip.i18n.json +++ b/i18n/jpn/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "不完全。{0} / {1} 個のエントリが抽出されました", "notFound": "zip ファイルの中に {0} が見つかりません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/base/parts/quickopen/browser/quickOpenModel.i18n.json b/i18n/jpn/src/vs/base/parts/quickopen/browser/quickOpenModel.i18n.json index 24af83fb13..29dc72c4a6 100644 --- a/i18n/jpn/src/vs/base/parts/quickopen/browser/quickOpenModel.i18n.json +++ b/i18n/jpn/src/vs/base/parts/quickopen/browser/quickOpenModel.i18n.json @@ -6,6 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "quickOpenAriaLabelEntry": "{0}、選択", + "quickOpenAriaLabelEntry": "{0}, ピッカー", "quickOpenAriaLabel": "選択" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index af92c02737..5cd44ec9ec 100644 --- a/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "GitHub 上でプレビュー", "loadingData": "データを読み込んでいます...", + "rateLimited": "GitHub クエリの制限を超えました。お待ちください。", "similarIssues": "類似の問題", "open": "Open", "closed": "Closed", - "noResults": "一致する項目はありません", + "noSimilarIssues": "類似の問題は見つかりませんでした", "settingsSearchIssue": "設定検索の問題", "bugReporter": "バグ レポート", - "performanceIssue": "パフォーマンスの問題", "featureRequest": "機能欲求", + "performanceIssue": "パフォーマンスの問題", "stepsToReproduce": "再現手順", "bugDescription": "問題を再現するための正確な手順を共有します。このとき、期待する結果と実際の結果を提供してください。GitHub-flavored Markdown に対応しています。GitHub 上で確認するときに問題を編集してスクリーンショットを追加できます。", "performanceIssueDesciption": "このパフォーマンスの問題はいつ発生しましたか? それは起動時ですか? それとも特定のアクションのあとですか? GitHub-flavored Markdown に対応しています。GitHub 上で確認するときに問題を編集してスクリーンショットを追加できます。", diff --git a/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index 60652585f4..06d09e1c61 100644 --- a/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/jpn/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "英語で記入して下さい。", "issueTypeLabel": "種類", + "issueSourceLabel": "記録", + "vscode": "Visual Studio Code", + "extension": "拡張機能", + "disableExtensionsLabelText": "{0} を実行後に問題を再現してみてください。拡張機能がアクティブな場合にのみ問題が再現する場合は、拡張機能の問題である可能性があります。", + "disableExtensions": "すべての拡張機能を無効にしてウィンドウを再読みする", + "chooseExtension": "拡張機能", "issueTitleLabel": "題名", "issueTitleRequired": "題名を入力してください", "titleLengthValidation": "タイトルが長すぎます。", @@ -18,13 +24,6 @@ "extensions": "私の拡張機能", "searchedExtensions": "見つかった拡張機能", "settingsSearchDetails": "設定検索の詳細", - "tryDisablingExtensions": "拡張機能が無効な場合に問題は再現可能ですか?", - "yes": "はい", - "no": "いいえ", - "disableExtensionsLabelText": "{0} を実行後に問題を再現してみてください。", - "disableExtensions": "すべての拡張機能を無効にしてウィンドウを再読みする", - "showRunningExtensionsLabelText": "拡張機能の問題と疑われる場合、拡張機能の問題を報告するために {0} を実行してください。", - "showRunningExtensions": "すべての実行中の拡張機能を表示する", "details": "詳細を入力してください。", "loadingData": "データを読み込んでいます..." } \ No newline at end of file diff --git a/i18n/jpn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/jpn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..fb628eb4d5 --- /dev/null +++ b/i18n/jpn/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU %", + "memory": "メモリ (MB)", + "pid": "pid", + "name": "名前", + "killProcess": "プロセスの終了", + "forceKillProcess": "プロセスの強制終了" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/code/electron-main/menus.i18n.json b/i18n/jpn/src/vs/code/electron-main/menus.i18n.json index 86c5d0b50c..34246feba0 100644 --- a/i18n/jpn/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/jpn/src/vs/code/electron-main/menus.i18n.json @@ -57,7 +57,7 @@ "miPaste": "貼り付け(&&P)", "miFind": "検索(&&F)", "miReplace": "置換(&&R)", - "miFindInFiles": "ファイル内を検索(&&I)", + "miFindInFiles": "複数ファイルから検索(&&I)", "miReplaceInFiles": "複数のファイルで置換(&&I)", "miEmmetExpandAbbreviation": "Emmet: 略語の展開(&&X)", "miShowEmmetCommands": "Emmet(&&M)...", @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "条件付きブレークポイント(&&C)...", "miColumnBreakpoint": "列のブレークポイント(&&O)", "miFunctionBreakpoint": "関数のブレークポイント(&&F)...", + "miLogPoint": "ログポイント(&&L)", "miNewBreakpoint": "新しいブレークポイント(&&N)", "miEnableAllBreakpoints": "すべてのブレークポイントを有効にする", "miDisableAllBreakpoints": "すべてのブレークポイントを無効にする(&&L)", @@ -161,6 +162,7 @@ "mMergeAllWindows": "すべてのウィンドウを統合", "miToggleDevTools": "開発者ツールの切り替え(&&T)", "miAccessibilityOptions": "ユーザー補助オプション(&&O)", + "miOpenProcessExplorerer": "プロセス エクスプローラーを開く(&&P)", "miReportIssue": "問題の報告(&&I)", "miWelcome": "ようこそ(&&W)", "miInteractivePlayground": "対話型プレイグラウンド(&&I)", diff --git a/i18n/jpn/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/jpn/src/vs/editor/browser/widget/diffReview.i18n.json index 20eeed65e3..7a93bd4622 100644 --- a/i18n/jpn/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/jpn/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "閉じる", - "header": "{1} の差分 {0}: 変更前の {2}、{3} 行、変更後の {4}、{5} 行", + "no_lines": "行なし", + "one_line": "1 行", + "more_lines": "{0} 行", + "header": "{1} の差異 {0}: 変更前 {2}, {3}, 変更後 {4}, {5}", "blankLine": "空白", "equalLine": "変更前の {0}、変更後の {1}: {2}", "insertLine": "+ 変更後の {0}: {1}", diff --git a/i18n/jpn/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/jpn/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..f29a4df99e --- /dev/null +++ b/i18n/jpn/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "カーソルの数は {0} 個に制限されています。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json index b24c38ba63..ff6a459c07 100644 --- a/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "行番号は、絶対数として表示されます。", "lineNumbers.relative": "行番号は、カーソル位置までの行数として表示されます。", "lineNumbers.interval": "行番号は 10 行ごとに表示されます。", - "lineNumbers": "行番号の表示を制御します。使用可能な値は、'on'、'off'、'relative'、'interval' です。", + "lineNumbers": "行番号の表示を制御します。", "rulers": "等幅フォントの特定番号の後ろに垂直ルーラーを表示します。複数のルーラーには複数の値を使用します。配列が空の場合はルーラーを表示しません。", "wordSeparators": "単語に関連したナビゲーションまたは操作を実行するときに、単語の区切り文字として使用される文字", "tabSize": "1 つのタブに相当するスペースの数。`editor.detectIndentation` がオンの場合、この設定はファイル コンテンツに基づいて上書きされます。", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "エディターで最後の行を越えてスクロールするかどうかを制御します", "smoothScrolling": "アニメーションでエディターをスクロールするかどうかを制御します", "minimap.enabled": "ミニマップを表示するかどうかを制御します", - "minimap.side": "ミニマップの表示を制御します。使用可能な値は 'right'、および 'left' です。", - "minimap.showSlider": "ミニマップのスライダーを自動的に非表示にするかどうかを制御します。指定できる値は 'always' と 'mouseover' です", + "minimap.side": "ミニマップを表示する場所を制御します。", + "minimap.showSlider": "ミニマップのスライダーを自動的に非表示にするかどうかを制御します。", "minimap.renderCharacters": "行に (カラー ブロックではなく) 実際の文字を表示します", "minimap.maxColumn": "表示するミニマップの最大幅を特定の桁数に制限します", "find.seedSearchStringFromSelection": "エディターの選択から検索ウィジェット内の検索文字列を与えるかどうかを制御します", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Windows および Linux 上の `Control` キーと macOS 上の `Command` キーに割り当てます。", "multiCursorModifier.alt": "Windows および Linux 上の `Alt` キーと macOS 上の `Option` キーに割り当てます。", "multiCursorModifier": "マウスを使用して複数のカーソルを追加するときに使用する修飾キーです。`ctrlCmd` は Windows および Linux 上の `Control` キーと macOS 上の `Command` キーに割り当てます。「定義に移動」や「リンクを開く」のマウス操作は、マルチカーソルの修飾キーと競合しないように適用されます。", + "multiCursorMergeOverlapping": "複数のカーソルが重なっているときは、マージします。", "quickSuggestions.strings": "文字列内でクイック候補を有効にします。", "quickSuggestions.comments": "コメント内でクイック候補を有効にします。", "quickSuggestions.other": "文字列およびコメント外でクイック候補を有効にします。", @@ -76,7 +77,7 @@ "occurrencesHighlight": "エディターでセマンティック シンボルの出現箇所を強調表示するかどうかを制御します", "overviewRulerLanes": "概要ルーラーの同じ位置に表示できる装飾の数を制御します", "overviewRulerBorder": "概要ルーラーの周囲に境界線が描画されるかどうかを制御します。", - "cursorBlinking": "カーソルのアニメーション スタイルを制御します。指定できる値は 'blink'、'smooth'、'phase'、'expand'、'solid' です", + "cursorBlinking": "カーソルのアニメーション方式を制御します。", "mouseWheelZoom": "Ctrl キーを押しながらマウス ホイールを使用してエディターのフォントをズームします", "cursorStyle": "カーソルのスタイルを制御します。指定できる値は 'block'、'block-outline'、'line'、'line-thin'、'underline'、'underline-thin' です", "cursorWidth": "editor.cursorStyle が 'line' に設定されている場合、カーソルの幅を制御する", @@ -86,8 +87,11 @@ "renderControlCharacters": "エディターで制御文字を表示する必要があるかどうかを制御します", "renderIndentGuides": "エディターでインデントのガイドを表示する必要があるかどうかを制御します", "renderLineHighlight": "エディターが現在の行をどのように強調表示するかを制御します。考えられる値は 'none'、'gutter'、'line'、'all' です。", - "codeLens": "エディターで CodeLens を表示するかどうかを制御する", + "codeLens": "エディターが CodeLens を表示するかどうかを制御します", "folding": "エディターでコードの折りたたみを有効にするかどうかを制御します", + "foldingStrategyAuto": "利用可能であれば、言語に特有の折りたたみ方式を使用して、そうでない場合はインデント方式に戻ります。", + "foldingStrategyIndentation": "常にインデントに基づく折りたたみ方式を使用します", + "foldingStrategy": "折りたたみ範囲の計算方法を制御します。'auto' は利用可能であれば言語固有の折りたたみ方式を使用します。'indentation' は常にインデントに基づく折りたたみ方式を使用します。", "showFoldingControls": "余白上の折りたたみコントロールを自動的に非表示にするかどうかを制御します 。", "matchBrackets": "かっこを選択すると、対応するかっこを強調表示します。", "glyphMargin": "エディターで縦のグリフ余白が表示されるかどうかを制御します。ほとんどの場合、グリフ余白はデバッグに使用されます。", @@ -102,8 +106,12 @@ "links": "エディターがリンクを検出してクリック可能な状態にするかどうかを制御します", "colorDecorators": "エディターでインライン カラー デコレーターと色の選択を表示する必要があるかどうかを制御します。", "codeActions": "コード アクション (lightbulb) を有効にする", + "codeActionsOnSave.organizeImports": "保存時にインポートの整理を実行しますか?", + "codeActionsOnSave": "保存時に実行されるコードアクションの種類。", + "codeActionsOnSaveTimeout": "保存時に実行されるコード アクションのタイムアウト値。", "selectionClipboard": "Linux の PRIMARY クリップボードをサポートするかどうかを制御します。", "sideBySide": "差分エディターが差分を横に並べて表示するか、行内に表示するかを制御します", "ignoreTrimWhitespace": "差分エディターが、先頭または末尾の空白の変更を差分として表示するかどうかを制御します。", + "largeFileOptimizations": "大きなファイルでメモリが集中する特定の機能を無効にするための特別な処理。", "renderIndicators": "差分エディターが追加/削除された変更に +/- インジケーターを示すかどうかを制御します" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json index dfe1669d2c..a111c73efa 100644 --- a/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "選択された文字列の背景色です。選択された文字列の背景色をカスタマイズ出来ます。", "editorWhitespaces": "エディターのスペース文字の色。", "editorIndentGuides": "エディター インデント ガイドの色。", + "editorActiveIndentGuide": "アクティブなエディターのインデント ガイドの色。", "editorLineNumbers": "エディターの行番号の色。", "editorActiveLineNumber": "エディターのアクティブ行番号の色", + "deprecatedEditorActiveLineNumber": "id は使用しないでください。代わりに 'EditorLineNumber.activeForeground' を使用してください。", "editorRuler": "エディター ルーラーの色。", "editorCodeLensForeground": "CodeLens エディターの前景色。", "editorBracketMatchBackground": "一致するかっこの背景色", @@ -28,7 +30,9 @@ "warningBorder": "エディターで警告を示す波線の境界線の色。", "infoForeground": "エディターで情報を示す波線の前景色。", "infoBorder": "エディターで情報を示す波線の境界線の色。", - "overviewRulerRangeHighlight": "範囲を強調表示するときの概要ルーラーのマーカー色。", + "hintForeground": "エディターでヒントを示す波線の前景色。", + "hintBorder": "エディターでヒントを示す波線の境界線の色。", + "overviewRulerRangeHighlight": "範囲を強調表示するときの概要ルーラーのマーカー色。この色は下地の色に紛れないよう不明瞭であってはいけません。", "overviewRuleError": "エラーを示す概要ルーラーのマーカー色。", "overviewRuleWarning": "警告を示す概要ルーラーのマーカー色。", "overviewRuleInfo": "情報を示す概要ルーラーのマーカー色。" diff --git a/i18n/jpn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/jpn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..7e60a39f1e --- /dev/null +++ b/i18n/jpn/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "修正プログラム ({0}) を表示する", + "quickFix": "修正プログラムを表示する", + "quickfix.trigger.label": "クイック フィックス...", + "editor.action.quickFix.noneMessage": "利用可能なコード アクションはありません", + "refactor.label": "リファクター...", + "editor.action.refactor.noneMessage": "利用可能なリファクタリングはありません", + "source.label": "ソース アクション...", + "editor.action.source.noneMessage": "利用可能なソース アクションはありません", + "organizeImports.label": "インポートを整理", + "editor.action.organize.noneMessage": "利用可能なインポートの整理アクションはありません" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/find/findController.i18n.json b/i18n/jpn/src/vs/editor/contrib/find/findController.i18n.json index 2328586dcb..e9e29d2023 100644 --- a/i18n/jpn/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "検索", + "startFindWithSelectionAction": "選択範囲を検索", "findNextMatchAction": "次を検索", "findPreviousMatchAction": "前を検索", "nextSelectionMatchFindAction": "次の選択項目を検索", diff --git a/i18n/jpn/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/jpn/src/vs/editor/contrib/format/formatActions.i18n.json index 540a3759e5..5a2201e63d 100644 --- a/i18n/jpn/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "行 {1} と {2} の間で {0} 個の書式設定を編集", "no.provider": "インストールされた '{0}'ファイル用のフォーマッターが存在しません。", "formatDocument.label": "ドキュメントのフォーマット", - "formatSelection.label": "選択範囲のフォーマット" + "no.documentprovider": "インストールされた '{0}'ファイル用のドキュメント フォーマッターが存在しません。", + "formatSelection.label": "選択範囲のフォーマット", + "no.selectionprovider": "インストールされた '{0}' ファイル用の選択範囲フォーマッターが存在しません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 51dbe9a78e..d6f37d9e89 100644 --- a/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "次の問題 (エラー、警告、情報) へ移動", - "markerAction.previous.label": "前の問題 (エラー、警告、情報) へ移動", - "editorMarkerNavigationError": "エディターのマーカー ナビゲーション ウィジェットのエラーの色。", - "editorMarkerNavigationWarning": "エディターのマーカー ナビゲーション ウィジェットの警告の色。", - "editorMarkerNavigationInfo": "エディターのマーカー ナビゲーション ウィジェットの情報の色。", - "editorMarkerNavigationBackground": "エディターのマーカー ナビゲーション ウィジェットの背景。" + "markerAction.previous.label": "前の問題 (エラー、警告、情報) へ移動" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..a523dd7832 --- /dev/null +++ b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "エディターのマーカー ナビゲーション ウィジェットのエラーの色。", + "editorMarkerNavigationWarning": "エディターのマーカー ナビゲーション ウィジェットの警告の色。", + "editorMarkerNavigationInfo": "エディターのマーカー ナビゲーション ウィジェットの情報の色。", + "editorMarkerNavigationBackground": "エディターのマーカー ナビゲーション ウィジェットの背景。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/links/links.i18n.json b/i18n/jpn/src/vs/editor/contrib/links/links.i18n.json index f5f9ddb37c..7c29cf3ecc 100644 --- a/i18n/jpn/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "Ctrl キーを押しながらクリックしてリンク先を表示", "links.command.mac": "command キーを押しながらクリックしてコマンドを実行", "links.command": "Ctrl キーを押しながらクリックしてコマンドを実行", + "links.navigate.al.mac": "Option キーを押しながらクリックしてリンク先を表示", "links.navigate.al": "Altl キーを押しながらクリックしてリンク先を表示", + "links.command.al.mac": "Option キーを押しながらクリックしてコマンドを実行", "links.command.al": "Alt キーを押しながらクリックしてコマンドを実行", "invalid.url": "このリンクは形式が正しくないため開くことができませんでした: {0}", "missing.url": "このリンクはターゲットが存在しないため開くことができませんでした。", diff --git a/i18n/jpn/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/jpn/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..b11769a824 --- /dev/null +++ b/i18n/jpn/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "読み取り専用のエディターは編集できません" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/jpn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index b9c5959cc1..a35c95544e 100644 --- a/i18n/jpn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "ピーク ビュー エディターの背景色。", "peekViewEditorGutterBackground": "ピーク ビュー エディターの余白の背景色。", "peekViewResultsMatchHighlight": "ピーク ビュー結果リストの一致した強調表示色。", - "peekViewEditorMatchHighlight": "ピーク ビュー エディターの一致した強調表示色。" + "peekViewEditorMatchHighlight": "ピーク ビュー エディターの一致した強調表示色。", + "peekViewEditorMatchHighlightBorder": "ピーク ビュー エディターの一致した強調境界色。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/jpn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..7c0d7d8f47 --- /dev/null +++ b/i18n/jpn/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "日曜日", + "Monday": "月曜日", + "Tuesday": "火曜日", + "Wednesday": "水曜日", + "Thursday": "木曜日", + "Friday": "金曜日", + "Saturday": "土曜日", + "SundayShort": "日", + "MondayShort": "月", + "TuesdayShort": "火", + "WednesdayShort": "水", + "ThursdayShort": "木", + "FridayShort": "金", + "SaturdayShort": "土", + "January": "1 月", + "February": "2 月", + "March": "3 月", + "April": "4 月", + "May": "5 月", + "June": "6 月", + "July": "7 月", + "August": "8 月", + "September": "9 月", + "October": "10 月", + "November": "11 月", + "December": "12 月", + "JanuaryShort": "1 月", + "FebruaryShort": "2 月", + "MarchShort": "3 月", + "AprilShort": "4 月", + "MayShort": "5 月", + "JuneShort": "6 月", + "JulyShort": "7 月", + "AugustShort": "8 月", + "SeptemberShort": "9 月", + "OctoberShort": "10 月", + "NovemberShort": "11 月", + "DecemberShort": "12 月" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 626aee5350..ed9687773e 100644 --- a/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "変数への書き込みなど書き込みアクセス中のシンボルの背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", "wordHighlightBorder": "変数の読み取りなど読み取りアクセス中のシンボルの境界線の色。", "wordHighlightStrongBorder": "変数への書き込みなど書き込みアクセス中のシンボルの境界線の色。", - "overviewRulerWordHighlightForeground": "シンボルを強調表示するときの概要ルーラーのマーカー色。", - "overviewRulerWordHighlightStrongForeground": "書き込みアクセス シンボルを強調表示するときの概要ルーラーのマーカー色。", + "overviewRulerWordHighlightForeground": "シンボルを強調表示するときの概要ルーラーのマーカー色。この色は下地の色に紛れないよう不明瞭であってはいけません。", + "overviewRulerWordHighlightStrongForeground": "書き込みアクセス シンボルを強調表示するときの概要ルーラーのマーカー色。この色は下地の色に紛れないよう不明瞭であってはいけません。", "wordHighlight.next.label": "次のシンボル ハイライトに移動", "wordHighlight.previous.label": "前のシンボル ハイライトに移動" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/jpn/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..7921873c1f --- /dev/null +++ b/i18n/jpn/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 つの追加ファイルが表示されていません", + "moreFiles": "...{0} 個の追加ファイルが表示されていません" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/jpn/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..c2ef06b51e --- /dev/null +++ b/i18n/jpn/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "キャンセル" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json b/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json index d2f42a7950..29d2875e09 100644 --- a/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json @@ -29,8 +29,8 @@ "performance": "'Developer: Startup Performance' コマンドを有効にして開始します。", "prof-startup": "起動中に CPU プロファイラーを実行する", "disableExtensions": "インストールされたすべての拡張機能を無効にします。", - "inspect-extensions": "拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", - "inspect-brk-extensions": "起動後に一時停止されている拡張ホストとの拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", + "inspect-extensions": "拡張機能のデバッグとプロファイリングを許可します。connection URI を開発者ツールで確認します。", + "inspect-brk-extensions": "起動後に一時停止されている拡張ホストとの拡張機能のデバッグとプロファイリングを許可します。connection URI を開発者ツールで確認ます。", "disableGPU": "GPU ハードウェア アクセラレータを無効にします。", "uploadLogs": "現在のセッションから安全なエンドポイントにログをアップロードします。", "maxMemory": "ウィンドウの最大メモリ サイズ (バイト単位)。", diff --git a/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 370f1f6e42..91e8cedc8a 100644 --- a/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "正しくない拡張機能: package.json は JSON ファイルではありません。", + "incompatible": "Code '{1}' と互換性のない拡張機能 '{0}' をインストールできません。", "restartCode": "{0} を再インストールする前に、Code を再起動してください。", "installingOutdatedExtension": "この拡張機能の新しいバージョンが既にインストールされています。古いバージョンでこれを上書きしますか?", "override": "上書き", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "依存関係のインストール中にエラーが発生しました。{0}", "MarketPlaceDisabled": "Marketplace が有効になっていません", "removeError": "拡張機能の削除中にエラーが発生しました: {0}。もう一度やり直す前に、VS Code の終了と起動を実施してください。", - "Not Market place extension": "Marketplace の拡張機能のみ再インストールできます", + "Not a Marketplace extension": "Marketplace の拡張機能のみ再インストールできます", "notFoundCompatible": "'{0}' をインストールできません。VS Code '{1}' と互換性がある利用可能なバージョンがありません。", "malicious extension": "問題が報告されたので、拡張機能をインストールできません。", "notFoundCompatibleDependency": "VS Code の現在のバージョン '{1}' と互換性を持つ、依存関係がある拡張機能 '{0}' が見つからないため、インストールできません。", "quitCode": "拡張機能をインストールできません。再インストールの前に VS Code の終了と起動を実施してください。", "exitCode": "拡張機能をインストールできません。再インストールの前に VS Code の終了と起動を実施してください。", + "renameError": "{0} から {1} に名前変更中に不明なエラーが発生しました", "uninstallDependeciesConfirmation": "'{0}' のみをアンインストールしますか、または依存関係もアンインストールしますか?", - "uninstallOnly": "限定", - "uninstallAll": "すべて", + "uninstallOnly": "拡張機能のみ", + "uninstallAll": "すべてアンインストール", "uninstallConfirmation": "'{0}' をアンインストールしてもよろしいですか?", "ok": "OK", "singleDependentError": "拡張機能 '{0}' をアンインストールできません。拡張機能 '{1}' がこの拡張機能に依存しています。", diff --git a/i18n/jpn/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/jpn/src/vs/platform/extensions/node/extensionValidator.i18n.json index 32529f9e47..3b6047f17c 100644 --- a/i18n/jpn/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/jpn/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "`engines.vscode` 値 {0} を解析できませんでした。使用可能な値の例: ^0.10.0、^1.2.3、^0.11.0、^0.10.x など。", + "versionSyntax": "`engines.vscode` の値 {0} を解析できませんでした。使用可能な値の例: ^1.22.0、^1.22.x など。", "versionSpecificity1": "`engines.vscode` ({0}) で指定されたバージョンが十分に特定されていません。1.0.0 より前の vscode バージョンの場合は、少なくとも想定されているメジャー バージョンとマイナー バージョンを定義してください。例 ^0.10.0、0.10.x、0.11.0 など。", "versionSpecificity2": "`engines.vscode` ({0}) で指定されたバージョンが明確ではありません。1.0.0 より後のバージョンの vscode の場合は、少なくとも、想定されているメジャー バージョンを定義してください。例 ^1.10.0、1.10.x、1.x.x、2.x.x など。", "versionMismatch": "拡張機能が Code {0} と互換性がありません。拡張機能に必要なバージョン: {1}。" diff --git a/i18n/jpn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/jpn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 10819461ba..23d11239b9 100644 --- a/i18n/jpn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/jpn/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "{0} インストールが壊れている可能性があります。再インストールしてください。", "integrity.moreInformation": "詳細情報", - "integrity.dontShowAgain": "今後は表示しない", - "integrity.prompt": "{0} インストールが壊れている可能性があります。再インストールしてください。" + "integrity.dontShowAgain": "今後は表示しない" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/jpn/src/vs/platform/issue/electron-main/issueService.i18n.json index 238d440839..8d06b9ab12 100644 --- a/i18n/jpn/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/jpn/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "問題のレポーター" + "issueReporter": "問題のレポーター", + "processExplorer": "プロセス エクスプローラー" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json b/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json index 09cd574495..164dbf82a8 100644 --- a/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "マウスで複数の選択肢にツリーおよびリストの項目を追加するために使用される修飾子 (たとえば、エクスプローラーでエディターと scm ビューを開くなど)。`ctrlCmd` は、Windows と Linux では `Control` にマップされ、macOS では `Command` にマップされます。'横に並べて開く' マウス ジェスチャー (サポートされている場合) は、複数選択修飾子と競合しないように調整されます。", "openMode.singleClick": "マウスのシングル クリックで項目を開きます。", "openMode.doubleClick": "マウスのダブル クリックで項目を開きます。", - "openModeModifier": "マウスを使用して、ツリーとリストで項目を開く方法を制御します (サポートされている場合)。'SingleClick' に設定すると、項目をマウスのシングル クリックで開き、'doubleClick' に設定すると、ダブル クリックでのみ開きます。ツリーで子を持つ親の場合、この設定で、親をシングル クリックで展開するか、ダブル クリックで展開するかを制御します。該当しない場合、一部のツリーとリストでは、この設定が無視される場合があることに注意してください。" + "openModeModifier": "マウスを使用して、ツリーとリストで項目を開く方法を制御します (サポートされている場合)。'SingleClick' に設定すると、項目をマウスのシングル クリックで開き、'doubleClick' に設定すると、ダブル クリックでのみ開きます。ツリーで子を持つ親の場合、この設定で、親をシングル クリックで展開するか、ダブル クリックで展開するかを制御します。該当しない場合、一部のツリーとリストでは、この設定が無視される場合があることに注意してください。", + "horizontalScrolling setting": "ワークベンチでツリーが水平スクロールをサポートするかどうかを制御します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/markers/common/markers.i18n.json b/i18n/jpn/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..5842e6fd34 --- /dev/null +++ b/i18n/jpn/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "エラー", + "sev.warning": "警告", + "sev.info": "情報" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json index c4c1ec7d8b..2352214efc 100644 --- a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -93,6 +93,6 @@ "overviewRulerCurrentContentForeground": "行内マージ競合の現在の概要ルーラー前景色。", "overviewRulerIncomingContentForeground": "行内マージ競合の入力側の概要ルーラー前景色。", "overviewRulerCommonContentForeground": "行内マージ競合の共通の祖先概要ルーラー前景色。", - "overviewRulerFindMatchForeground": "一致項目を示す概要ルーラーのマーカー色。", - "overviewRulerSelectionHighlightForeground": "選択対象を強調表示するときの概要ルーラーのマーカー色。" + "overviewRulerFindMatchForeground": "検索一致項目を示す概要ルーラーのマーカー色。この色は下地の色に紛れないよう不明瞭であってはいけません。", + "overviewRulerSelectionHighlightForeground": "選択範囲を強調表示するときの概要ルーラーのマーカー色。この色は下地の色に紛れないよう不明瞭であってはいけません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/jpn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..710b493051 --- /dev/null +++ b/i18n/jpn/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "{0} 拡張機能に次の URL を開かせますか?" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/jpn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..a21d309305 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "'views' コントリビューション ポイントを使用して提供できるコンテナを識別するための一意の ID", + "vscode.extension.contributes.views.containers.title": "コンテナーの表示に使用する、人が判別できる文字列", + "vscode.extension.contributes.views.containers.icon": "コンテナ アイコンのパス。アイコンは、50x40 の四角形の中心に配置された 24x24 のサイズで、'rgb(215, 218, 224)' または '#d7dae0' の色で塗りつぶされます。アイコンでは、任意の種類の画像を使用できますが、SVG にすることをお勧めします。", + "vscode.extension.contributes.viewsContainers": "ビュー コンテナをエディターに提供します", + "views.container.activitybar": "アクティビティ バーにビュー コンテナを提供します", + "test": "テスト", + "proposed": "'viewsContainers' コントリビューションは、dev または次のコマンド ライン スイッチを使用しているときにのみ用いることができます: --enable-proposed-api {0}", + "requirearray": "ビュー コンテナは配列である必要があります", + "requireidstring": "プロパティ '{0}' は必須で、'string' 型でなければなりません。使用できるのは、半角英数字、'_'、'-' のみです。", + "requirestring": " `{0}` プロパティは必須で、`string` 型でなければなりません", + "showViewlet": "{0} を表示", + "view": "表示" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/jpn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index 30f4411955..ce1a7d8a35 100644 --- a/i18n/jpn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/jpn/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "ビューの判読できる名前。表示されます", "vscode.extension.contributes.view.when": "このビューを表示するために満たす必要がある条件", "vscode.extension.contributes.views": "ビューをエディターに提供します", - "views.explorer": "エクスプローラー ビュー", - "views.debug": "デバッグ ビュー", - "locationId.invalid": "`{0}` は有効なビューの場所ではありません", + "views.explorer": "アクション バーのエクスプローラー コンテナにビューを提供します", + "views.debug": "アクション バーのデバッグ コンテナにビューを提供します", + "views.scm": "アクション バーのSCM コンテナにビューを提供します", + "views.test": "アクション バーのテスト コンテナにビューを提供します", + "views.contributed": "コントリビューション ビュー コンテナにビューを提供します", + "ViewContainerDoesnotExist": "ビュー コンテナ '{0}' が存在しません。このコンテナに登録されているすべてのビューは 'エクスプローラー' に追加されます。", "duplicateView1": "location `{1}` で同じ id `{0}` を使用する複数のビューを登録できません", "duplicateView2": "location `{1}` で id `{0}` のビューが既に登録されています" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 7e11f65941..ac808515ce 100644 --- a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "保存時のフォーマットは {0}ms 後に中止されました", + "codeActionsOnSave.didTimeout": "codeActionsOnSave は {0} ms 後に中止されました", + "timeout.onWillSave": "onWillSaveTextDocument-event は 1750ms 後に中止されました", "saveParticipants": "Save Participants が実行中です..." } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 88655291de..b4fe8b7665 100644 --- a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "webview エディター" + "errorMessage": "view:{0} を復元中にエラーが発生しました" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/jpn/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..c56e83de88 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (拡張機能)" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index a728348848..bdeb6f3c80 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "次のグループにフォーカス", "openToSide": "横に並べて開く", "closeEditor": "エディターを閉じる", + "closeOneEditor": "閉じる", "revertAndCloseActiveEditor": "元に戻してエディターを閉じる", "closeEditorsToTheLeft": "左側のエディターを閉じる", "closeAllEditors": "すべてのエディターを閉じる", diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 955f27e63d..a70a8b80ce 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "スクリーン リーダーを使用しない場合、`editor.accessibilitySupport` を \"off\" にしてください。", "disableTabMode": "アクセシビリティ モードを無効にする", "gotoLine": "行へ移動", - "indentation": "インデント", + "selectIndentation": "インデントを選択", "selectEncoding": "エンコードの選択", "selectEOL": "改行コードの選択", "selectLanguageMode": "言語モードの選択", diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 8d31506bb7..707e9b904e 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0}MB", "sizeGB": "{0}GB", "sizeTB": "{0}TB", - "largeImageError": "画像のファイル サイズが非常に大きい (>1MB) ため、エディターに表示されません。 ", + "largeImageError": "画像が大きすぎるため、エディターに表示されません ({0})。", "resourceOpenExternalButton": "外部のプログラムを使用して画像を開きますか?", - "nativeBinaryError": "このファイルはバイナリか、非常に大きいか、またはサポートされていないテキスト エンコードを使用しているため、エディターに表示されません。", + "nativeFileTooLargeError": "ファイルが大きすぎるため、エディターに表示されません ({0})。", + "nativeBinaryError": "このファイルはバイナリか、サポートされていないテキスト エンコードを使用しているため、エディターに表示されません。", + "openAsText": "このまま開きますか?", "zoom.action.fit.label": "画像全体", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 1d80a193fc..a3bf2bc62d 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "閉じる", "araLabelEditorActions": "エディター操作" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 559bd5d808..cafeb324be 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "新しい通知はありません", "notifications": "通知", "notificationsToolbar": "通知センターのアクション", "notificationsList": "通知リスト" diff --git a/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..39a84641d9 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} ('Enter' を押して確認するか 'Escape' を押して取り消します)", + "inputModeEntry": "'Enter' を押して入力を確認するか 'Escape' を押して取り消します", + "quickInput.countSelected": "{0} 個選択済み", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..f4c7eecf0d --- /dev/null +++ b/i18n/jpn/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "入力すると結果が絞り込まれます。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json index a93fcc8bc7..ae85e4be80 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "最近開いた項目…", "quickOpenRecent": "最近使用したものを開く...", "reportIssueInEnglish": "問題の報告", + "openProcessExplorer": "プロセス エクスプローラーを開く", "reportPerformanceIssue": "パフォーマンスの問題のレポート", "keybindingsReference": "キーボード ショートカットの参照", "openDocumentationUrl": "ドキュメント", diff --git a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json index 5d9495b848..f5735aaf9b 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "ウィンドウ", "window.openFilesInNewWindow.on": "新しいウィンドウでファイルを開きます", "window.openFilesInNewWindow.off": "ファイルのフォルダーが開かれていたウィンドウまたは最後のアクティブ ウィンドウでファイルを開きます", - "window.openFilesInNewWindow.default": "ファイルのフォルダーが開かれていたウィンドウでファイルを開くか、Dock または Finder を使用して開く場合以外は最後のアクティブ ウィンドウでファイルを開きます (macOS のみ)", - "openFilesInNewWindow": "ファイルを新しいウィンドウで開くかどうかを制御します。\n- default: ファイルのフォルダーが開かれていたウィンドウでファイルを開くか、Dock または Finder を使用して開く場合以外は最後のアクティブ ウィンドウでファイルを開きます (macOS のみ\n- on: 新しいウィンドウでファイルを開きます\n- off: ファイルのフォルダーが開かれていたウィンドウまたは最後のアクティブ ウィンドウでファイルを開きます\nこの設定は無視される場合もあります (-new-window または -reuse-window コマンド ライン オプションを使用する場合など)。", + "window.openFilesInNewWindow.defaultMac": "Dock または Finder を使用して開いたときを除き、ファイルのフォルダーを開いているウィンドウまたは最後のアクティブ ウィンドウでファイルを開きます", + "window.openFilesInNewWindow.default": "アプリケーション内から選択したとき (例: ファイル メニュー介したとき) を除き 、新しいウィンドウでファイルを開きます", + "openFilesInNewWindowMac": "ファイルを新しいウィンドウで開くかどうかを制御します。\n- default: Dock または Finder を使用して開いたときを除き、ファイルのフォルダーを開いているウィンドウまたは最後のアクティブ ウィンドウでファイルを開きます\n- on: 新しいウィンドウでファイルを開きます\n- off: ファイルのフォルダーを開いているフォルダーまたは最後のアクティブ ウィンドウでファイルを開きます\nこの設定は無視される場合もあります (例: -new-window または -reuse-window コマンド ライン オプションを使用する場合など)。", + "openFilesInNewWindow": "ファイルを新しいウィンドウで開くかどうかを制御します。\n- default: アプリケーション内から選択したとき (例: ファイル メニュー介したとき) を除き 、新しいウィンドウでファイルを開きます\n- on: 新しいウィンドウでファイルを開きます\n- off: ファイルのフォルダーを開いているフォルダーまたは最後のアクティブ ウィンドウでファイルを開きます\nこの設定は無視される場合もあります (例: -new-window または -reuse-window コマンド ライン オプションを使用する場合など)。", "window.openFoldersInNewWindow.on": "新しいウィンドウでフォルダーを開きます", "window.openFoldersInNewWindow.off": "フォルダーは、最後のアクティブ ウィンドウで開きます", "window.openFoldersInNewWindow.default": "フォルダーがアプリケーション内から (たとえば、[ファイル] メニューから) 選択された場合を除いて、新しいウィンドウでフォルダーを開きます", "openFoldersInNewWindow": "フォルダーを新しいウィンドウで開くか、最後のアクティブ ウィンドウで開くかを制御します。\n- default: アプリケーション内で ([ファイル] メニューなどから) 選択したものでなければ、新しいウィンドウでフォルダーを開く\n- on: 新しいウィンドウでフォルダーを開く\n- off: 最後のアクティブ ウィンドウでフォルダーを開く\nこの設定は無視される場合もあります (-new-window または -reuse-window コマンド ライン オプションを使用する場合など)。", + "window.openWithoutArgumentsInNewWindow.on": "新しい空のウィンドウを開く", + "window.openWithoutArgumentsInNewWindow.off": "最後にアクティブだった実行中のインスタンスにフォーカスする", + "openWithoutArgumentsInNewWindow": "引数なしで 2 つ目のインスタンスを起動するとき、新しい空のウィンドウを開くか、最後に実行されていたウィンドウにフォーカスするかを制御します。\n- on: 新しい空のウィンドウを開く\n- off: 最後に実行されていたウィンドウにフォーカスする\nこの設定は無視される場合もあります (-new-window または -reuse-window コマンド ライン オプションを使用する場合など)。", "window.reopenFolders.all": "すべてのウィンドウを再度開きます。", "window.reopenFolders.folders": "すべてのフォルダーを再度開きます。空のワークスペースは復元されません。", "window.reopenFolders.one": "最後にアクティブだったウィンドウを再び開きます。", @@ -58,7 +63,7 @@ "restoreWindows": "再起動後にワークスペースを再度開く方法を制御します。'none' を選択すると常に空のワークスペースで開始します。'one' を選択すると最後に使用したウィンドウを再度開きます。'folders' を選択すると開かれていたフォルダーとすべてのウィンドウを再度開きます。'all' を選択すると前回のセッションのすべてのウィンドウを再度開きます。", "restoreFullscreen": "全画面表示モードで終了した場合に、ウィンドウを全画面表示モードに復元するかどうかを制御します。", "zoomLevel": "ウィンドウのズーム レベルを調整します。元のサイズは 0 で、1 つ上げるごとに (1 など) 20% ずつ拡大することを表し、1 つ下げるごとに (-1 など) 20% ずつ縮小することを表します。小数点以下の桁数を入力して、さらに細かくズーム レベルを調整することもできます。", - "title": "アクティブなエディターに基づいてウィンドウのタイトルを制御します。変数は、コンテキストに基づいて置換されます:\n${activeEditorShort}: ファイル名 (例: myFile.txt)\n${activeEditorMedium}: ワークスペース フォルダーへの相対パス (例: myFolder/myFile.txt)\n${activeEditorLong}: ファイルの完全なパス (例: /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: ファイルが含まれているワークスペース フォルダー名 (例: myFolder)\n${folderPath}: ァイルが含まれているワークスペース フォルダーのファイルパス (例: /Users/Development/myFolder)\n${rootName}: ワークスペースの名前 (例: myFolder や myWorkspace)\n${rootPath}: ワークスペースのファイル パス (例: /Users/Development/myWorkspace)\n${appName}: 例: VS Code\n${dirty}: アクティブなエディターがダーティである場合のダーティ インジゲーター\n${separator}: 値のある変数で囲まれた場合にのみ表示される条件付き区切り記号 (\" - \")", + "title": "アクティブなエディターに基づいてウィンドウのタイトルを制御します。変数は、コンテキストに基づいて置換されます:\n${activeEditorShort}: ファイル名 (例: myFile.txt)\n${activeEditorMedium}: ワークスペース フォルダーへの相対パス (例: myFolder/myFile.txt)\n${activeEditorLong}: ファイルの完全なパス (例: /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: ファイルが含まれているワークスペース フォルダー名 (例: myFolder)\n${folderPath}: ァイルが含まれているワークスペース フォルダーのファイルパス (例: /Users/Development/myFolder)\n${rootName}: ワークスペースの名前 (例: myFolder や myWorkspace)\n${rootPath}: ワークスペースのファイル パス (例: /Users/Development/myWorkspace)\n${appName}: 例: VS Code\n${dirty}: アクティブなエディターがダーティである場合のダーティ インジゲーター\n${separator}: 値のある変数かスタティック テキストで囲まれた場合にのみ表示される条件付き区切り記号 (\" - \")", "window.newWindowDimensions.default": "新しいウィンドウを画面の中央に開きます。", "window.newWindowDimensions.inherit": "新しいウィンドウを、最後にアクティブだったウィンドウと同じサイズで開きます。", "window.newWindowDimensions.maximized": "新しいウィンドウを最大化した状態で開きます。", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "有効にすると、Windows でハイ コントラスト テーマが使用されている場合にはハイ コントラスト テーマに自動的に変更され、Windows のハイ コントラスト テーマから切り替えられている場合にはダーク テーマに自動的に変更されます。", "titleBarStyle": "ウィンドウのタイトル バーの外観を調整します。変更を適用するには、完全に再起動する必要があります。", "window.nativeTabs": "macOS Sierra ウィンドウ タブを有効にします。この変更を適用するには完全な再起動が必要であり、ネイティブ タブでカスタムのタイトル バー スタイルが構成されていた場合はそれが無効になることに注意してください。", + "window.smoothScrollingWorkaround": "最小化した VS Code ウィンドウを元のサイズに戻したあと、スクロールが滑らかにならない場合はこの回避策を有効にしてください。これは Microsoft Surface のような高精度タッチパッドを備えたデバイスで、スクロールの開始が遅れる問題 (https://github.com/Microsoft/vscode/issues/13612) の回避策です。有効にすると、最小化の状態からウィンドウを元に戻したあとに少しレイアウトがちらつきますが、そうでなければ無害です。", + "window.clickThroughInactive": "有効な場合、非アクティブなウィンドウをクリックするとウィンドウがアクティブになり、クリック可能な場合はマウスの下の要素がトリガーされます。無効にすると、非アクティブなウィンドウの任意の場所をクリックするとそのウィンドウがアクティブになり、要素には 2 回目のクリックが必要になります。", "zenModeConfigurationTitle": "Zen Mode", "zenMode.fullScreen": "Zen Mode をオンにするとワークベンチを自動的に全画面モードに切り替えるかどうかを制御します。", "zenMode.centerLayout": "Zen Mode をオンにしたときにレイアウトを中央揃えにするかどうかを制御します。", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 48a62fe075..563331d9b6 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "ブレークポイントの編集...", + "logPoint": "ログポイント", + "breakpoint": "ブレークポイント", + "editBreakpoint": "{0} を編集", + "removeBreakpoint": "{0} を削除", "functionBreakpointsNotSupported": "このデバッグの種類では関数ブレークポイントはサポートされていません", "functionBreakpointPlaceholder": "中断対象の関数", "functionBreakPointInputAriaLabel": "関数ブレークポイントを入力します", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "未確認のブレークポイント", "functionBreakpointUnsupported": "このデバッグの種類では関数ブレークポイントはサポートされていません", "breakpointDirtydHover": "未確認のブレークポイント。ファイルは変更されているので、デバッグ セッションを再起動してください。", + "logBreakpointUnsupported": "ログポイントは、このデバッグの種類ではサポートされていません", "conditionalBreakpointUnsupported": "このデバッグの種類では、条件付きブレークポイントはサポートされていません。", "hitBreakpointUnsupported": "このデバッグの種類では、ヒットした条件付きブレークポイントはサポートされていません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 13ca76ca3c..1582dc356e 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "切断", "continueDebug": "続行", "pauseDebug": "一時停止", + "terminateThread": "スレッドを終了", "restartFrame": "フレームの再起動", "removeBreakpoint": "ブレークポイントの削除", "removeAllBreakpoints": "すべてのブレークポイントを削除する", - "enableBreakpoint": "ブレークポイントの有効化", - "disableBreakpoint": "ブレークポイントの無効化", "enableAllBreakpoints": "すべてのブレークポイントを有効にする", "disableAllBreakpoints": "すべてのブレークポイントを無効にする", "activateBreakpoints": "ブレークポイントのアクティブ化", "deactivateBreakpoints": "ブレークポイントの非アクティブ化", "reapplyAllBreakpoints": "すべてのブレークポイントを再適用する", "addFunctionBreakpoint": "関数ブレークポイントの追加", - "addConditionalBreakpoint": "条件付きブレークポイントの追加...", - "editConditionalBreakpoint": "ブレークポイントの編集...", "setValue": "値の設定", "addWatchExpression": "式の追加", "editWatchExpression": "式の編集", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 8b289cea08..3bb7ec0120 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "デバッグ: ブレークポイントの切り替え", "conditionalBreakpointEditorAction": "デバッグ: 条件付きブレークポイントの追加...", + "logPointEditorAction": "デバッグ: ログポイントの追加...", "runToCursor": "カーソル行の前まで実行", "debugEvaluate": "デバッグ: 評価", "debugAddToWatch": "デバッグ: ウォッチに追加", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..46a0d6b70e --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "ブレークポイントにヒットしたときにログに記録するメッセージ。{} 内の式は補間されます。受け入れるには 'Enter' を、キャンセルするには 'esc' を押します。", + "breakpointWidgetHitCountPlaceholder": "ヒット カウント条件が満たされる場合に中断します。'Enter' を押して受け入れるか 'Esc' を押して取り消します。", + "breakpointWidgetExpressionPlaceholder": "式が true と評価される場合に中断します。'Enter' を押して受け入れるか 'Esc' を押して取り消します。", + "expression": "式", + "hitCount": "ヒット カウント", + "logMessage": "ログ メッセージ" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 4df0c5b8f0..34ed685b9f 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "一意の構成名を使用してください。", "app.launch.json.compound.folder": "複合があるフォルダーの名前。", "app.launch.json.compounds.configurations": "この複合の一部として開始される構成の名前。", - "debugNoType": "デバッグ アダプター 'type' は省略不可で、'string' 型でなければなりません。", + "debugNoType": "デバッガー 'type' は省略不可で、'string' 型でなければなりません。", "selectDebug": "環境の選択", "DebugConfig.failed": "'launch.json' ファイルを '.vscode' フォルダー ({0}) 内に作成できません。", "workspace": "ワークスペース", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 242105012e..a0c1afdf3f 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "ログポイント", + "breakpoint": "ブレークポイント", + "removeBreakpoint": "{0} を削除", + "editBreakpoint": "{0} を編集...", + "disableBreakpoint": "{0} を無効にする", + "enableBreakpoint": "{0} を有効にする", "removeBreakpoints": "ブレークポイントの削除", "removeBreakpointOnColumn": "列 {0} のブレークポイントの削除", "removeLineBreakpoint": "行のブレークポイントの削除", @@ -18,5 +24,13 @@ "enableBreakpoints": "列 {0} のブレークポイントの有効化", "enableBreakpointOnLine": "行のブレークポイントの有効化", "addBreakpoint": "ブレークポイントの追加", + "addConditionalBreakpoint": "条件付きブレークポイントの追加...", + "addLogPoint": "ログポイントを追加...", + "breakpointHasCondition": "この {0} には削除時に失われる {1} があります。代わりに {0} を無効にすることを検討してください。", + "message": "メッセージ", + "condition": "条件", + "removeLogPoint": "{0} を削除", + "disableLogPoint": "{0} を無効にする", + "cancel": "キャンセル", "addConfiguration": "構成の追加..." } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 63f0a29951..68b543a482 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "エラーの表示", "noFolderWorkspaceDebugError": "アクティブ ファイルをデバッグできません。ファイルがディスクに保存されており、そのファイル タイプのデバッグ拡張機能がインストールされていることを確認してください。", "cancel": "キャンセル", - "DebugTaskNotFound": "preLaunchTask '{0}' が見つかりませんでした。", - "taskNotTracked": "preLaunchTask '{0}' を追跡できません。" + "DebugTaskNotFound": "タスク '{0}' を見つけられませんでした。", + "taskNotTracked": "タスク '{0}' を追跡できません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index b6899a2992..fb17a928e8 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "詳細情報", - "unableToLaunchDebugAdapter": "デバッグ アダプターを {0} から起動できません。", - "unableToLaunchDebugAdapterNoArgs": "デバッグ アダプターを起動できません。", - "stoppingDebugAdapter": "{0}。デバッグ アダプターを停止しています。", "debugAdapterCrash": "デバッグ アダプター プロセスが予期せず終了しました" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index da11ae9939..599f8457e7 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "デバッグ アダプターの実行可能ファイル '{0}' がありません。", "debugAdapterCannotDetermineExecutable": "デバッグ アダプター '{0}' の実行可能ファイルを判別できません。", - "launch.config.comment1": "IntelliSense を使用して利用可能な属性を学べます。", - "launch.config.comment2": "既存の属性の説明をホバーして表示します。", - "launch.config.comment3": "詳細情報は次を確認してください: {0}", - "debugType": "構成の種類。", - "debugTypeNotRecognised": "デバッグの種類は認識されませんでした。対応するデバッグの拡張機能がインストールされており、有効になっていることを確認してください。", - "node2NotSupported": "\"node2\" はサポートされていません。代わりに \"node\" を使用し、\"protocol\" 属性を \"inspector\" に設定してください。", - "debugName": "構成の名前。起動構成のドロップダウン メニューに表示されます。", - "debugRequest": "構成の要求の種類。\"launch\" または \"attach\" です。", - "debugServer": "デバッグ拡張機能の開発のみ。ポートが指定の VS Code の場合、サーバー モードで実行中のデバッグ アダプターへの接続が試行されます。", - "debugPrelaunchTask": "デバッグ セッションの開始前に実行するタスク。", - "debugWindowsConfiguration": "Windows 固有の起動構成の属性。", - "debugOSXConfiguration": "OS X 固有の起動構成の属性。", - "debugLinuxConfiguration": "Linux 固有の起動構成の属性。", - "deprecatedVariables": "'env.'、'config.'、'command.' は使用されていません。代わりに、'env:'、'config:'、'command:' を使用してください。" + "unableToLaunchDebugAdapter": "デバッグ アダプターを {0} から起動できません。", + "unableToLaunchDebugAdapterNoArgs": "デバッグ アダプターを起動できません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..af1ed51322 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "IntelliSense を使用して利用可能な属性を学べます。", + "launch.config.comment2": "既存の属性の説明をホバーして表示します。", + "launch.config.comment3": "詳細情報は次を確認してください: {0}", + "debugType": "構成の種類。", + "debugTypeNotRecognised": "デバッグの種類は認識されませんでした。対応するデバッグの拡張機能がインストールされており、有効になっていることを確認してください。", + "node2NotSupported": "\"node2\" はサポートされていません。代わりに \"node\" を使用し、\"protocol\" 属性を \"inspector\" に設定してください。", + "debugName": "構成の名前。起動構成のドロップダウン メニューに表示されます。", + "debugRequest": "構成の要求の種類。\"launch\" または \"attach\" です。", + "debugServer": "デバッグ拡張機能の開発のみ。ポートが指定の VS Code の場合、サーバー モードで実行中のデバッグ アダプターへの接続が試行されます。", + "debugPrelaunchTask": "デバッグ セッションの開始前に実行するタスク。", + "debugPostDebugTask": "デバッグ セッションの終了前に実行するタスク。", + "debugWindowsConfiguration": "Windows 固有の起動構成の属性。", + "debugOSXConfiguration": "OS X 固有の起動構成の属性。", + "debugLinuxConfiguration": "Linux 固有の起動構成の属性。", + "deprecatedVariables": "'env.'、'config.'、'command.' は使用されていません。代わりに、'env:'、'config:'、'command:' を使用してください。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..3b21863f9b --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code コンソール", + "mac.terminal.script.failed": "スクリプト '{0}' が終了コード {1} で失敗しました", + "mac.terminal.type.not.supported": "'{0}' はサポートされていません", + "press.any.key": "続行するには、任意のキーを押してください...", + "linux.term.failed": "'{0}' が終了コード {1} で失敗しました" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 3bc09f52d4..94afd2b58c 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "推奨事項の拡張機能を構成 (ワークスペース フォルダー)", "malicious tooltip": "この拡張機能は問題ありと報告されました。", "malicious": "悪意がある", + "disabled": "無効", + "disabled globally": "無効", + "disabled workspace": "このワークスペースでは無効", "disableAll": "インストール済みのすべての拡張機能を無効にする", "disableAllWorkspace": "このワークスペースのインストール済みの拡張機能をすべて無効にする", "enableAll": "すべての拡張機能を有効にする", diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..6012be2dbf --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "拡張機能名", + "extension id": "拡張機能の識別子", + "preview": "プレビュー", + "builtin": "ビルトイン", + "publisher": "発行者名", + "install count": "インストール数", + "rating": "評価", + "repository": "リポジトリ", + "license": "ライセンス", + "details": "詳細", + "contributions": "コントリビューション", + "changelog": "変更ログ", + "dependencies": "依存関係", + "noReadme": "利用できる README はありません。", + "noChangelog": "使用可能な変更ログはありません。", + "noContributions": "コントリビューションはありません", + "noDependencies": "依存関係はありません", + "settings": "設定 ({0})", + "setting name": "名前", + "description": "説明", + "default": "既定", + "debuggers": "デバッガー ({0})", + "debugger name": "名前", + "debugger type": "種類", + "views": "ビュー ({0})", + "view id": "ID", + "view name": "名前", + "view location": "場所", + "localizations": "ローカライズ ({0})", + "localizations language id": "言語 ID", + "localizations language name": "言語名", + "localizations localized language name": "言語名 (ローカライズ)", + "colorThemes": "配色テーマ ({0})", + "iconThemes": "アイコン テーマ ({0})", + "colors": "配色 ({0})", + "colorId": "Id", + "defaultDark": "ダーク テーマの既定値", + "defaultLight": "ライト テーマの既定値", + "defaultHC": "ハイ コントラストの既定値", + "JSON Validation": "JSON 検証 ({0})", + "fileMatch": "対象ファイル", + "schema": "スキーマ", + "commands": "コマンド ({0})", + "command name": "名前", + "keyboard shortcuts": "キーボード ショートカット", + "menuContexts": "メニュー コンテキスト", + "languages": "言語 ({0})", + "language id": "ID", + "language name": "名前", + "file extensions": "ファイル拡張子", + "grammar": "文章校正", + "snippets": "スニペット" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index bb4aed9c43..98f8cd7ff1 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "現在のワークスペースのユーザーによってこの拡張機能が推奨されています。", "reallyRecommended2": "このファイルの種類には拡張機能 '{0}' が推奨されます。", "reallyRecommendedExtensionPack": "このファイルの種類には拡張機能パック '{0}' が推奨されます。", - "showRecommendations": "推奨事項を表示", "install": "インストール", + "showRecommendations": "推奨事項を表示", "showLanguageExtensions": "'.{0}' ファイルに役立つ拡張機能が Marketplace にあります", "workspaceRecommended": "このワークスペースには拡張機能の推奨事項があります。", "installAll": "すべてインストール", diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index d22081aede..4a2f3eca05 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "キーバインド間の競合を回避するために、他のキーマップ ({0}) を無効にしますか?", "yes": "はい", - "no": "いいえ", - "betterMergeDisabled": "拡張機能 Better Merge は現在ビルトインです。インストール済みの拡張機能は無効化され、アンインストールできます。", - "uninstall": "アンインストール" + "no": "いいえ" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index faaf571abb..3ac1eab2cc 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -12,7 +12,9 @@ "recommendedExtensions": "推奨", "otherRecommendedExtensions": "その他の推奨事項", "workspaceRecommendedExtensions": "ワークスペースの推奨事項", - "builtInExtensions": "ビルトイン", + "builtInExtensions": "機能", + "builtInThemesExtensions": "テーマ", + "builtInBasicsExtensions": "プログラミング言語", "searchExtensions": "Marketplace で拡張機能を検索する", "sort by installs": "並べ替え: インストール数", "sort by rating": "並べ替え: 評価", diff --git a/i18n/jpn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 272e3df715..0f4709c46f 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "テキスト ファイル エディター", "createFile": "ファイルの作成", + "relaunchWithIncreasedMemoryLimit": "{0} MB で再起動", + "configureMemoryLimit": "メモリ制限を構成する", "fileEditorWithInputAriaLabel": "{0}。テキスト ファイル エディター。", "fileEditorAriaLabel": "テキスト ファイル エディター。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 0edf08b20a..9e89cdbe16 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,30 +13,37 @@ "copyFile": "コピー", "pasteFile": "貼り付け", "retry": "再試行", + "renameWhenSourcePathIsParentOfTargetError": "既存のフォルダーに子を追加するには 'New Folder' や 'New File' コマンドを使用してください", "newUntitledFile": "無題の新規ファイル", "createNewFile": "新しいファイル", "createNewFolder": "新しいフォルダー", "deleteButtonLabelRecycleBin": "ごみ箱に移動(&&M)", - "deleteButtonLabelTrash": "ゴミ箱に移動(&&M)", + "deleteButtonLabelTrash": "ごみ箱に移動(&&M)", "deleteButtonLabel": "削除(&&D)", "dirtyMessageFilesDelete": "保存されていない変更があるファイルを削除します。続行しますか?", "dirtyMessageFolderOneDelete": "保存されていない変更がある 1 個のファイルを含むフォルダーを削除します。続行しますか?", "dirtyMessageFolderDelete": "保存されていない変更があるファイルを {0} 個含むフォルダーを削除します。続行しますか?", "dirtyMessageFileDelete": "保存されていない変更があるファイルを削除します。続行しますか?", "dirtyWarning": "保存しないと変更内容が失われます。", + "undoBin": "ごみ箱から復元できます。", + "undoTrash": "ごみ箱から復元できます。", + "doNotAskAgain": "再度表示しない", + "irreversible": "このアクションは元に戻すことができません。", + "binFailed": "ごみ箱を使用した削除に失敗しました。代わりに完全に削除しますか?", + "trashFailed": "ごみ箱を使用した削除に失敗しました。代わりに完全に削除しますか?", + "deletePermanentlyButtonLabel": "完全に削除(&&D)", + "retryButtonLabel": "再試行(&&R)", + "confirmMoveTrashMessageFilesAndDirectories": "次の {0} ファイル/ディレクトリとその内容を削除しますか?", + "confirmMoveTrashMessageMultipleDirectories": "次の {0} ディレクトリとその内容を削除しますか?", "confirmMoveTrashMessageMultiple": "次の {0} 個のファイルを削除してもよろしいですか?", "confirmMoveTrashMessageFolder": "'{0}' とその内容を削除しますか?", "confirmMoveTrashMessageFile": "'{0}' を削除しますか?", - "undoBin": "ごみ箱から復元できます。", - "undoTrash": "ゴミ箱から復元できます。", - "doNotAskAgain": "再度表示しない", + "confirmDeleteMessageFilesAndDirectories": "次の {0} ファイル/ディレクトリとその内容を完全に削除しますか?", + "confirmDeleteMessageMultipleDirectories": "次の {0} ディレクトリとその内容を完全に削除しますか?", "confirmDeleteMessageMultiple": "次の {0} 個のファイルを完全に削除してもよろしいですか?", "confirmDeleteMessageFolder": "'{0}' とその内容を完全に削除してもよろしいですか?", "confirmDeleteMessageFile": "'{0}' を完全に削除してもよろしいですか?", - "irreversible": "このアクションは元に戻すことができません。", - "cancel": "キャンセル", - "permDelete": "完全に削除", - "importFiles": "ファイルのインポート", + "addFiles": "ファイルを追加", "confirmOverwrite": "保存先のフォルダーに同じ名前のファイルまたはフォルダーが既に存在します。置き換えてもよろしいですか?", "replaceButtonLabel": "置換(&&R)", "fileIsAncestor": "ペーストするファイルは送り先フォルダの上位にいます", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "まずファイルを開いてから新しいウィンドウで開きます", "copyPath": "パスのコピー", "emptyFileNameError": "ファイルまたはフォルダーの名前を指定する必要があります。", + "fileNameStartsWithSlashError": "ファイルまたはフォルダーの名前はスラッシュで始めることができません。", "fileNameExistsError": "**{0}** というファイルまたはフォルダーはこの場所に既に存在します。別の名前を指定してください。", + "fileUsedAsFolderError": "**{0}** はファイルのため階層構造を持つことはできません。", "invalidFileNameError": "名前 **{0}** がファイル名またはフォルダー名として無効です。別の名前を指定してください。", "filePathTooLongError": "名前 **{0}** のパスが長すぎます。名前を短くしてください。", "compareWithClipboard": "クリップボードとアクティブ ファイルを比較", diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 0900cf2886..16fbbfc144 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "エディターを終了するときに保存を確認するダイアログを省略し、保存されていないファイルをセッション後も保持するかどうかを制御します。", "useExperimentalFileWatcher": "新しい試験的な File Watcher を使用します。", "defaultLanguage": "新しいファイルに割り当てられる既定の言語モード。", + "maxMemoryForLargeFilesMB": "大きなファイルを開こうとしたとき、VS Code の再起動後に使用できるメモリを制御します。コマンド ラインで --max-memory=NEWSIZE を指定するのと同じ効果があります。", "editorConfigurationTitle": "エディター", "formatOnSave": "ファイルを保存するときにフォーマットしてください。フォーマッタを使用可能にして、ファイルを自動保存せず、エディターをシャットダウンしないでください。", + "formatOnSaveTimeout": "保存時フォーマットのタイムアウトを制御します。formatOnSave-コマンドの時間制限をミリ秒単位で指定してください。指定したタイムアウトよりも時間がかかるコマンドはキャンセルされます。", "explorerConfigurationTitle": "エクスプローラー", "openEditorsVisible": "[開いているエディター] ウィンドウに表示するエディターの数。", "autoReveal": "エクスプローラーでファイルを開くとき、自動的にファイルの内容を表示して選択するかどうかを制御します。", diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index c2c3526233..db802ff14c 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -7,13 +7,17 @@ "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "ファイル名を入力します。Enter キーを押して確認するか、Esc キーを押して取り消します。", - "constructedPath": "**{1}** に {0} を作成", + "createFileFromExplorerInfoMessage": "**{1}** にファイル **{0}** を作成", + "renameFileFromExplorerInfoMessage": "**{0}** に移動と名前変更", + "createFolderFromExplorerInfoMessage": "**{1}** にフォルダー **{0}** を作成", "filesExplorerViewerAriaLabel": "{0}、ファイル エクスプローラー", "dropFolders": "ワークスペースにフォルダーを追加しますか?", "dropFolder": "ワークスペースにフォルダーを追加しますか?", "addFolders": "フォルダーの追加(&&A)", "addFolder": "フォルダーの追加(&&A)", + "confirmRootsMove": "ワークスペース内の複数のルート フォルダーの順序が変更されますがよろしいですか?", "confirmMultiMove": "次の {0} 個のファイルを移動してもよろしいですか?", + "confirmRootMove": "ワークスペース内のルート フォルダー '{0}' の順序が変更されますがよろしいですか?", "confirmMove": "'{0}' を移動しますか?", "doNotAskAgain": "再度表示しない", "moveButtonLabel": "移動(&&M)", diff --git a/i18n/jpn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..47e72aa69e --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "HTML プレビュー" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..d8a322eb85 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "エディター入力が正しくありません。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..e619da1dc8 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "開発者" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..14a4dc2212 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview 開発者ツールを開く", + "refreshWebviewLabel": "WebView の再読み込み" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index 369a81371e..0ed053a754 100644 --- a/i18n/jpn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "VS Code の UI 言語を {0} にして再起動しますか?", + "yes": "はい", + "no": "いいえ", + "neverAgain": "今後は表示しない", "JsonSchema.locale": "使用する UI 言語。", "vscode.extension.contributes.localizations": "ローカリゼーションをエディターに提供します", "vscode.extension.contributes.localizations.languageId": "表示文字列が翻訳される言語の id。", diff --git a/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..a821e834d0 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "VS Code の UI 言語を {0} にして再起動しますか?", + "yes": "はい", + "no": "いいえ", + "neverAgain": "今後は表示しない", + "install language pack": "近い将来、VS Codeはマーケットプレイスの拡張機能のみをサポートします。現在構成されている言語を使い続けるためには、拡張機能 '{0}' をインストールしてください。", + "install": "インストール", + "more information": "詳細情報...", + "JsonSchema.locale": "使用する UI 言語。", + "vscode.extension.contributes.localizations": "ローカリゼーションをエディターに提供します", + "vscode.extension.contributes.localizations.languageId": "表示文字列が翻訳される言語の id。", + "vscode.extension.contributes.localizations.languageName": "英語での言語の名前。", + "vscode.extension.contributes.localizations.languageNameLocalized": "提供された言語での言語の名前。", + "vscode.extension.contributes.localizations.translations": "言語に関連付けられている翻訳のリスト。", + "vscode.extension.contributes.localizations.translations.id": "この翻訳が提供される VS Code または拡張機能の ID。VS Code は常に `vscode` で、拡張機能の形式は `publisherId.extensionName` になります。", + "vscode.extension.contributes.localizations.translations.id.pattern": "VS Code または拡張機能を変換するための ID はそれぞれ、`vscode` か、`publisherId.extensionName` の形式になります。", + "vscode.extension.contributes.localizations.translations.path": "言語の翻訳を含むファイルへの相対パス。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..3b68fb6c14 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "言語を構成する", + "displayLanguage": "VSCode の表示言語を定義します。", + "doc": "サポートされている言語の一覧については、{0} をご覧ください。", + "restart": "値を変更するには VS Code の再起動が必要です。", + "fail.createSettings": "'{0}' ({1}) を作成できません。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..c26e068a73 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "コピー", + "copyMessage": "メッセージのコピー" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..182631b876 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "合計 {0} 個の問題" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..c361cf56e9 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "問題", + "tooltip.1": "このファイルに 1 つの問題", + "tooltip.N": "このファイルに {0} 個の問題", + "markers.showOnFile": "ファイルとフォルダーにエラーと警告を表示します。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..9e750f7bf8 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "ファイルの除外フィルターを無効にします。", + "clearFilter": "フィルターの解除。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..568a2eaf8e --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "{0} / {1} を表示しています" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..58202066e4 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "表示", + "problems.view.toggle.label": "問題 (エラー、警告、情報) の切り替え", + "problems.view.focus.label": "問題 (エラー、警告、情報) にフォーカス", + "problems.panel.configuration.title": "問題ビュー", + "problems.panel.configuration.autoreveal": "ファイルを開くときに問題ビューに自動的にそのファイルを表示するかどうかを制御します", + "markers.panel.title.problems": "問題", + "markers.panel.aria.label.problems.tree": "ファイル別にグループ化した問題", + "markers.panel.no.problems.build": "現時点でワークスペースの問題は検出されていません。", + "markers.panel.no.problems.filters": "指定されたフィルター条件による結果はありません。", + "markers.panel.no.problems.file.exclusions": "ファイルの除外設定が有効なため、すべての問題が非表示になっています。", + "markers.panel.action.useFilesExclude": "ファイルの除外設定を使用してフィルター処理", + "markers.panel.action.donotUseFilesExclude": "ファイルの除外設定を使用しない", + "markers.panel.action.filter": "問題のフィルター処理", + "markers.panel.filter.ariaLabel": "問題のフィルター処理", + "markers.panel.filter.placeholder": "フィルター。例: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "エラー", + "markers.panel.filter.warnings": "警告", + "markers.panel.filter.infos": "情報", + "markers.panel.single.error.label": "エラー 1", + "markers.panel.multiple.errors.label": "エラー {0}", + "markers.panel.single.warning.label": "警告 1", + "markers.panel.multiple.warnings.label": "警告 {0}", + "markers.panel.single.info.label": "情報 1", + "markers.panel.multiple.infos.label": "情報 {0}", + "markers.panel.single.unknown.label": "不明 1", + "markers.panel.multiple.unknowns.label": "不明 {0}", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} (問題あり {1})", + "problems.tree.aria.label.marker.relatedInformation": "この問題は {0} 個の箇所へ参照を持っています。", + "problems.tree.aria.label.error.marker": "{0}: {1} によって生成されたエラー (行 {2}、文字 {3}.{4})", + "problems.tree.aria.label.error.marker.nosource": "エラー: {0} (行 {1}、文字 {2}.{3})", + "problems.tree.aria.label.warning.marker": "{0}: {1} によって生成された警告 (行 {2}、文字 {3}.{4})", + "problems.tree.aria.label.warning.marker.nosource": "警告: {0} (行 {1}、文字 {2}.{3})", + "problems.tree.aria.label.info.marker": "{0}: {1} によって生成された情報 (行 {2}、文字 {3}.{4})", + "problems.tree.aria.label.info.marker.nosource": "情報: {0} (行 {1}、文字 {2}.{3})", + "problems.tree.aria.label.marker": "{0} によって生成された問題: {1} (行 {2}、文字 {3}.{4})", + "problems.tree.aria.label.marker.nosource": "問題: {0} (行 {1}、文字 {2}.{3})", + "problems.tree.aria.label.relatedinfo.message": "{0} ({3} の行 {1}、文字 {2})", + "errors.warnings.show.label": "エラーと警告の表示" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/output/browser/outputActions.i18n.json index 0aef20c64e..4fd24942bd 100644 --- a/i18n/jpn/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "出力の切り替え", "clearOutput": "出力のクリア", "toggleOutputScrollLock": "出力スクロール ロックの切り替え", - "switchToOutput.label": "出力に切り替え" + "switchToOutput.label": "出力に切り替え", + "openInLogViewer": "ログ ファイルを開く" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 08991dcc3b..7c831f6174 100644 --- a/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "出力", "logViewer": "ログ ビューアー", "viewCategory": "表示", - "clearOutput.label": "出力のクリア" + "clearOutput.label": "出力のクリア", + "openActiveLogOutputFile": "表示: アクティブなログ出力ファイルを開く" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 33590de3a3..600af13090 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "キーボード ショートカット", + "showDefaultKeybindings": "既定のキーバインドを表示", + "showUserKeybindings": "ユーザーのキーバインドを表示", "SearchKeybindings.AriaLabel": "キー バインドの検索", "SearchKeybindings.Placeholder": "キー バインドの検索", "sortByPrecedene": "優先順位で並べ替え", diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 08c10ff4aa..b3c9c9cb67 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "既定の設定を Raw で開く", + "openSettings": "設定を開く", "openGlobalSettings": "ユーザー設定を開く", "openGlobalKeybindings": "キーボード ショートカットを開く", "openGlobalKeybindingsFile": "キーボード ショートカット ファイルを開く", diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index e2e1b71440..553010f09d 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "既定の設定", "SearchSettingsWidget.AriaLabel": "設定の検索", "SearchSettingsWidget.Placeholder": "設定の検索", "noSettingsFound": "結果なし", @@ -16,6 +15,8 @@ "nlpResult": "自然文 (natural language) の結果", "filterResult": "フィルター後の結果", "defaultSettings": "既定の設定", + "defaultUserSettings": "既定のユーザー設定", + "defaultWorkspaceSettings": "既定のワークスペース設定", "defaultFolderSettings": "既定のフォルダー設定", "defaultEditorReadonly": "既定値を上書きするには、右側のエディターを編集します。", "preferencesAriaLabel": "既定の基本設定。読み取り専用のテキスト エディター。" diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index c7537c8999..71add87443 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "拡張機能 \"{0}\" を表示", "editTtile": "編集", "replaceDefaultValue": "設定を置換", - "copyDefaultValue": "設定にコピー", - "unsupportedPHPExecutablePathSetting": "この設定はユーザー設定でなければなりません。ワークスペースのために PHP を構成するには、PHP ファイルを開き、ステータス バーの [PHP パス] をクリックします。", - "unsupportedWorkspaceSetting": "この設定はユーザー設定でなければなりません。", - "unsupportedWorkbenchSetting": "この設定は現在適用できません。このフォルダーを直接開いたときに適用されます。", - "unsupportedWorkbenchSettingDevMode": "この設定は現在適用できません。登録時にスコープを 'resource' と定義している場合かこのフォルダーを直接開いたときに適用されます。" + "copyDefaultValue": "設定にコピー" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index a2ef43d02e..0d3e1d21a3 100644 --- a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "その他の SCM プロバイダーをインストール...", "no open repo": "有効なソース管理プロバイダーがありません。", "source control": "ソース管理", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "非表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 42770d8e9d..3e019a0041 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "前の検索除外パターンを表示", "nextSearchTerm": "次の検索語句を表示", "previousSearchTerm": "前の検索語句を表示", - "showSearchViewlet": "検索の表示", "findInFiles": "フォルダーを指定して検索", "replaceInFiles": "複数のファイルで置換", "RefreshAction.label": "最新の情報に更新", diff --git a/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 527700c2fb..11a7af1bc6 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "検索", + "copyMatchLabel": "コピー", + "copyPathLabel": "パスのコピー", + "copyAllLabel": "すべてコピー", + "clearSearchHistoryLabel": "検索履歴のクリア", + "toggleSearchViewPositionLabel": "検索ビュー位置の切り替え", "findInFolder": "フォルダー内を検索...", "findInWorkspace": "ワークスペース内を検索...", "showTriggerActions": "ワークスペース内のシンボルへ移動...", "name": "検索", - "search": "検索", "showSearchViewl": "検索の表示", "view": "表示", "findInFiles": "フォルダーを指定して検索", @@ -26,5 +31,5 @@ "search.followSymlinks": "検索中にシンボリック リンクをたどるかどうかを制御します。", "search.smartCase": "すべて小文字のパターンの場合、大文字と小文字を区別しないで検索し、そうでない場合は大文字と小文字を区別して検索する", "search.globalFindClipboard": "macOS で検索ビューが共有の検索クリップボードを読み取りまたは変更するかどうかを制御します", - "search.location": "プレビュー: 検索をサイドバーのビューとして表示するか、より水平方向の空間をとるためにパネル領域のパネルとして表示するかを制御します。次のリリースのパネル内の検索で水平レイアウトが改善され、プレビューではなくなります。" + "search.location": "検索をサイドバーのビューとして、または、より水平的なパネルとして表示するかを制御します。次期リリースではパネル内検索の水平レイアウトが改善され、プレビューではなくなります。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index fc3b98cc9b..5a8ad2aa53 100644 --- a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -7,7 +7,7 @@ "Do not edit this file. It is machine generated." ], "invalid.path.0": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", - "invalid.language.0": "言語を省略するとき、`contributes.{0}.path` の値は `.code-snippets`-file にする必要があります。提供された値: {1}", + "invalid.language.0": "言語を省略するとき、`contributes.{0}.path` の値は `.code-snippets`-file にする必要があります。提供された値: {1}", "invalid.language": "`contributes.{0}.language` で不明な言語です。提供された値: {1}", "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。", "vscode.extension.contributes.snippets": "スニペットを提供します。", diff --git a/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 13dbdd9057..40dcbd3a11 100644 --- a/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "{0} のサポートの改善にご協力ください", "takeShortSurvey": "簡単なアンケートの実施", "remindLater": "後で通知する", - "neverAgain": "今後は表示しない", - "helpUs": "{0} のサポートの改善にご協力ください" + "neverAgain": "今後は表示しない" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 6343db1584..9d877a2b00 100644 --- a/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "短いフィードバック アンケートにご協力をお願いできますか?", "takeSurvey": "アンケートの実施", "remindLater": "後で通知する", - "neverAgain": "今後は表示しない", - "surveyQuestion": "短いフィードバック アンケートにご協力をお願いできますか?" + "neverAgain": "今後は表示しない" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index de844275ea..3580be6db7 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "問題パターン、あるいは提供されたか事前定義された問題パターンの名前。基本問題パターンが指定されている場合は省略できます。", "ProblemMatcherSchema.base": "使用する基本問題マッチャーの名前。", "ProblemMatcherSchema.owner": "Code 内の問題の所有者。base を指定すると省略できます。省略して base を指定しない場合、既定は 'external' になります。", + "ProblemMatcherSchema.source": "'typescript' または 'super lint' のような、この診断のソースを記述する解読可能な文字列", "ProblemMatcherSchema.severity": "キャプチャされた問題の既定の重大度。パターンが重要度の一致グループを定義していない場合に使用されます。", "ProblemMatcherSchema.applyTo": "テキスト ドキュメントで報告された問題が、開いているドキュメントのみ、閉じられたドキュメントのみ、すべてのドキュメントのいずれに適用されるかを制御します。", "ProblemMatcherSchema.fileLocation": "問題パターンで報告されたファイル名を解釈する方法を定義します。", diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index b4fa92317e..7f1a9da698 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "実際のタスクの種類", + "TaskDefinition.description": "実際のタスクの種類。先頭が '$' で始まる種類は内部使用のために予約されています。", "TaskDefinition.properties": "タスクの種類の追加プロパティ", "TaskTypeConfiguration.noType": "タスクの種類を構成するのに必要な 'taskType' プロパティがありません", "TaskDefinitionExtPoint": "タスクの種類を提供" diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 5aeb368812..5fef404b79 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "タスクをグループに割り当てない", "JsonSchema.tasks.group": "このタスクが属する実行グループを定義します。ビルド グループに追加する \"build\" とテスト グループに追加する \"test\" をサポートしています。", "JsonSchema.tasks.type": "タスクをプロセスとして実行するか、またはシェル内部でコマンドとして実行するかどうかを定義します。", + "JsonSchema.command.quotedString.value": "実際のコマンド値", + "JsonSchema.tasks.quoting.escape": "シェルのエスケープ文字を使用して文字をエスケープします (例: PowerShell の ` 、bash の \\)。", + "JsonSchema.tasks.quoting.strong": "シェルの strong quote 文字を使用して引数を引用します (例: PowerShell や bash の下の \")。", + "JsonSchema.tasks.quoting.weak": "シェルの weak quote 文字を使用して引数を引用します (例: PowerShell や bash の下の ')。", + "JsonSchema.command.quotesString.quote": "どのようにコマンドの値を引用符で囲うかを制御します。", + "JsonSchema.command": "実行されるコマンド。外部プログラムかシェル コマンドです。", + "JsonSchema.args.quotedString.value": "実際の引数値", + "JsonSchema.args.quotesString.quote": "どのように引数の値を引用符で囲うかを制御します。", + "JsonSchema.tasks.args": "このタスクの起動時にコマンドに渡される引数。", "JsonSchema.tasks.label": "タスクのユーザー インターフェイス ラベル", "JsonSchema.version": "構成のバージョン番号", "JsonSchema.tasks.identifier": "launch.json または dependsOn 句のタスクを参照するユーザー定義の識別子。", diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 01b112b1c0..7e04739a7b 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -8,9 +8,12 @@ ], "tasksCategory": "タスク", "ConfigureTaskRunnerAction.label": "タスクの構成", + "totalErrors": "エラー {0}", + "totalWarnings": "警告 {0}", + "totalInfos": "情報 {0}", "problems": "問題", "building": "ビルド中...", - "manyMarkers": "99+", + "manyProblems": "10K+", "runningTasks": "実行中のタスクを表示", "tasks": "タスク", "TaskSystem.noHotSwap": "アクティブなタスクを実行しているタスク実行エンジンを変更するには、ウィンドウの再読み込みが必要です", @@ -28,8 +31,10 @@ "selectProblemMatcher": "スキャンするタスク出力のエラーと警告の種類を選択", "customizeParseErrors": "現在のタスクの構成にはエラーがあります。タスクをカスタマイズする前にエラーを修正してください。", "moreThanOneBuildTask": "tasks.json で複数のビルド タスクが定義されています。最初のタスクのみを実行します。\\n", - "TaskSystem.activeSame.background": "'{0}' タスクは既にバックグラウンド モードでアクティブです。タスクを終了するにはタスク メニューから `タスクの終了...` を使用します。", - "TaskSystem.activeSame.noBackground": "{0}' タスクは既にアクティブです。タスクを終了するにはタスク メニューから `タスクの終了...` を使用します。", + "TaskSystem.activeSame.background": "タスク '{0}' は既にバックグラウンド モードでアクティブです。", + "TaskSystem.activeSame.noBackground": "タスク '{0}' は既にアクティブです。", + "terminateTask": "タスクの終了", + "restartTask": "タスクの再開", "TaskSystem.active": "既に実行中のタスクがあります。まずこのタスクを終了してから、別のタスクを実行してください。", "TaskSystem.restartFailed": "タスク {0} を終了して再開できませんでした", "TaskService.noConfiguration": "エラー: {0} タスク検出は次の構成に対してタスクを提供していません:\n{1}\nこのタスクは無視されます。\n", diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index c5b4e66ee0..12fae23e92 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "タスク - {0}", "closeTerminal": "任意のキーを押してターミナルを終了します。", "reuseTerminal": "ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。", - "TerminalTaskSystem": "UNC ドライブでシェル コマンドを実行できません。", + "TerminalTaskSystem": "cmd.exe を使用して UNC ドライブ上でシェル コマンドを実行できません。", "unkownProblemMatcher": "問題マッチャー {0} は解決できませんでした。マッチャーは無視されます" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/jpn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index d84fff057d..669d231194 100644 --- a/i18n/jpn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "警告: options.cwd は、string 型でなければなりません。値 {0} を無視します", + "ConfigurationParser.inValidArg": "エラー: コマンド引数は文字列もしくは引用文字列のどちらかである必要があります。指定された値:\n{0}", "ConfigurationParser.noargs": "エラー: コマンド引数は文字列の配列でなければなりません。指定された値:\n{0}", "ConfigurationParser.noShell": "警告: シェル構成がサポートされるのは、ターミナルでタスクを実行している場合のみです。", "ConfigurationParser.noName": "エラー: 宣言スコープ内の問題マッチャーに次の名前がなければなりません:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "エラー: タスク構成 '{0}' に必要な '{1}' プロパティがありません。構成は無視されます。 ", "ConfigurationParser.notCustom": "エラー: タスクがカスタム タスクとして定義されていません。この構成は無視されます。\n{0}\n", "ConfigurationParser.noTaskName": "エラー: タスクが label プロパティを提供しなければなりません。このタスクは無視されます。\n{0}\n", - "taskConfiguration.shellArgs": "警告: タスク '{0}' はシェル コマンドであり、その引数の 1 つにエスケープされていないスペースが含まれている可能性があります。コマンド ラインの引用が正しく解釈されるように、引数をコマンドにマージしてください。", "taskConfiguration.noCommandOrDependsOn": "エラー: タスク '{0}' は、コマンドも dependsOn プロパティも指定していません。このタスクは無視されます。定義は次のとおりです:\n{1}", "taskConfiguration.noCommand": "エラー: タスク '{0}' はコマンドを定義していません。このタスクは無視されます。定義は次のとおりです:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "バージョン 2.0.0 のタスクでは、OS に固有のグローバル タスクはサポートされません。OS に固有のコマンドを使用したタスクに変換してください。影響を受けるタスクは次のとおりです。\n{0}" diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..1941d0b632 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "ターミナルの背景色。パネルごとに異なる色を指定できます。", + "terminal.foreground": "ターミナルの前景色。", + "terminalCursor.foreground": "ターミナルのカーソル前景色。", + "terminalCursor.background": "ターミナルのカーソルの背景色。ブロックカーソルで重ねた文字の色をカスタマイズできます。", + "terminal.selectionBackground": "ターミナルの選択範囲の背景色。", + "terminal.border": "ターミナル内の分割パネルを区切る境界線色。デフォルトは panel.border です。", + "terminal.ansiColor": "ターミナルの '{0}' ANSI カラー。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 03226ac497..3d8535cf2d 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -19,8 +19,9 @@ "workbench.action.terminal.new": "新しい統合ターミナルの作成", "workbench.action.terminal.new.short": "新しいターミナル", "workbench.action.terminal.newWorkspacePlaceholder": "新しいターミナルの作業ディレクトリを選択してください", - "workbench.action.terminal.newInActiveWorkspace": "新しい統合ターミナルを作成 (アクティブなワークスペースに)", + "workbench.action.terminal.newInActiveWorkspace": "(アクティブなワークスペースで) 新しいターミナルの作成", "workbench.action.terminal.split": "ターミナルの分割", + "workbench.action.terminal.splitInActiveWorkspace": "(アクティブなワークスペースで) ターミナルの分割", "workbench.action.terminal.focusPreviousPane": "前のペインにフォーカス", "workbench.action.terminal.focusNextPane": "次のペインにフォーカス", "workbench.action.terminal.resizePaneLeft": "ペインを左にリサイズ", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "スクロール アップ (ページ)", "workbench.action.terminal.scrollToTop": "一番上にスクロール", "workbench.action.terminal.clear": "クリア", + "workbench.action.terminal.clearSelection": "選択のクリア", "workbench.action.terminal.allowWorkspaceShell": "ワークスペースでシェルを構成することを許可する", "workbench.action.terminal.disallowWorkspaceShell": "ワークスペースでシェルを構成することを許可しない", "workbench.action.terminal.rename": "名前変更", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "検索ウィジェットを非表示にする", "nextTerminalFindTerm": "次の検索語句を表示", "previousTerminalFindTerm": "前の検索語句を表示", - "quickOpenTerm": "アクティブなターミナルの切り替え" + "quickOpenTerm": "アクティブなターミナルの切り替え", + "workbench.action.terminal.scrollToPreviousCommand": "前のコマンドにスクロール", + "workbench.action.terminal.scrollToNextCommand": "次のコマンドにスクロール", + "workbench.action.terminal.selectToPreviousCommand": "前のコマンドを選択", + "workbench.action.terminal.selectToNextCommand": "次のコマンドを選択" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index 405e39e223..ff3e8a7649 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "ターミナルにコピー対象の選択範囲がありません", "terminal.integrated.exitedWithCode": "ターミナルの処理が終了しました (終了コード: {0})", "terminal.integrated.waitOnExit": "任意のキーを押して端末を終了します", - "terminal.integrated.launchFailed": "ターミナルのプロセス コマンド '{0}{1}' を起動できませんでした (終了コード: {2})" + "terminal.integrated.launchFailed": "ターミナルのプロセス コマンド '{0}{1}' を起動できませんでした (終了コード: {2})", + "terminal.integrated.launchFailedExtHost": "ターミナル プロセスが起動に失敗しました (終了コード: {0})" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 4c90d0c120..bf946d3e74 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "コピー", + "split": "分割", "paste": "貼り付け", "selectAll": "すべて選択", - "clear": "クリア", - "split": "分割" + "clear": "クリア" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 8a9f6312bf..86a0089a0d 100644 --- a/i18n/jpn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "このワークスペースには、ユーザー設定でのみ設定可能な設定が含まれています ({0})。詳細情報は[こちら]({1})をクリックしてください。", "openWorkspaceSettings": "ワークスペース設定を開く", - "dontShowAgain": "今後は表示しない", - "unsupportedWorkspaceSettings": "このワークスペースには、ユーザー設定でのみ設定可能な設定が含まれています ({0})。詳細情報は[こちら]({1})をクリックしてください。" + "dontShowAgain": "今後は表示しない" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..8bfa1cc30f --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "リリース ノート: {0}", + "unassigned": "未割り当て" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json index ce463e783a..be4c3ee187 100644 --- a/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "後で", - "unassigned": "未割り当て", "releaseNotes": "リリース ノート", "showReleaseNotes": "リリース ノートの表示", "read the release notes": "{0} v{1} へようこそ! リリース ノートを確認しますか?", @@ -17,13 +15,14 @@ "updateIsReady": "新しい更新 {0} が利用可能です。", "noUpdatesAvailable": "現在入手可能な更新はありません。", "ok": "OK", - "download now": "今すぐダウンロード", "thereIsUpdateAvailable": "利用可能な更新プログラムがあります。", - "installUpdate": "更新プログラムのインストール", + "download now": "今すぐダウンロード", + "later": "後で", "updateAvailable": "利用可能な更新プログラムがあります: {0} {1}", + "installUpdate": "更新プログラムのインストール", "updateInstalling": "バックグラウンドで {0} {1} がインストールされています。処理が完了次第、お知らせします。", + "updateAvailableAfterRestart": "最新の更新プログラムを適用するために {0} を再起動してください。", "updateNow": "今すぐ更新", - "updateAvailableAfterRestart": "{0} は再起動後に更新されます。", "commandPalette": "コマンド パレット...", "settings": "設定", "keyboardShortcuts": "キーボード ショートカット", diff --git a/i18n/jpn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..d4807e1221 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "URL を開く", + "developer": "開発者" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..4dfeb1219a --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "webview エディター", + "developer": "開発者" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..14a4dc2212 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview 開発者ツールを開く", + "refreshWebviewLabel": "WebView の再読み込み" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/jpn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..635368f942 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Microsoft による利用状況のデータ収集を許可することで VS Code の改善に役立てることができます。私たちの [プライバシーに関する声明]({0}) 参照し、[オプト アウト]({1}) する方法を確認してください。", + "telemetryOptOut.optInNotice": "Microsoft による利用状況のデータ収集を許可することで VS Code の改善に役立てることができます。私たちの [プライバシーに関する声明]({0}) 参照し、[オプト イン]({1}) する方法を確認してください。", + "telemetryOptOut.readMore": "詳細を参照" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/jpn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index 93e5a0ecfa..25419caa34 100644 --- a/i18n/jpn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "拡張機能の管理", "welcomeOverlay.problems": "エラーおよび警告の表示", "welcomeOverlay.commandPalette": "すべてのコマンドの検索と実行", + "welcomeOverlay.notifications": "通知を表示", "welcomeOverlay": "ユーザー インターフェイスの概要", "hideWelcomeOverlay": "インターフェイスの概要を非表示にします", "help": "ヘルプ" diff --git a/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 8115583938..30c676f7a6 100644 --- a/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "ツールと言語", "welcomePage.installExtensionPacksDescription": "{0} と {1} のサポートをインストールする ", "welcomePage.moreExtensions": "その他", - "welcomePage.installKeymapDescription": "キーボード ショートカットをインストールします", - "welcomePage.installKeymapExtension": "{0} と {1} のキーボード ショートカットをインストール", + "welcomePage.installKeymapDescription": "設定とキーバインド", + "welcomePage.installKeymapExtension": "{0} と {1} の設定とキーボード ショートカットをインストールします", "welcomePage.others": "その他", "welcomePage.colorTheme": "配色テーマ", "welcomePage.colorThemeDescription": "エディターとコードの外観を自由に設定します", diff --git a/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 053f353ef8..c46932cec9 100644 --- a/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "設定の概要です。このラベルは、設定ファイルでコメントの区切り文字として使用します。", "vscode.extension.contributes.configuration.properties": "構成のプロパティの説明です。", + "scope.application.description": "ユーザー設定でのみ構成できるアプリケーション固有の構成。", "scope.window.description": "ウィンドウ固有の構成。ユーザーまたはワークスペースの設定で構成できます。", "scope.resource.description": "リソース固有の構成。ユーザー、ワークスペース、またはフォルダーの設定で構成できます。", "scope.description": "構成が適用される範囲。 使用可能なスコープは `window` と ` resource` です。", diff --git a/i18n/jpn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/jpn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 05f628b36b..c91d82c38e 100644 --- a/i18n/jpn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "設定を開く", "saveAndRetry": "保存して再試行", "errorUnknownKey": "{1} は登録済みの構成ではないため、{0} に書き込むことができません。", + "errorInvalidWorkspaceConfigurationApplication": "{0} をワークスペース設定に書き込めません。この設定はユーザー設定にのみ書き込めます。", "errorInvalidFolderConfiguration": "{0} はフォルダーのリソース スコープをサポートしていないため、フォルダー設定に書き込むことができません。", "errorInvalidUserTarget": "{0} はグローバル スコープをサポートしていないため、ユーザー設定に書き込むことができません。", "errorInvalidWorkspaceTarget": "{0} はマルチ フォルダー ワークスペースでワークスペース スコープをサポートしていないため、ワークスペース設定を書き込むことができません。", diff --git a/i18n/jpn/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/jpn/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..8283d684b0 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "この設定はユーザー設定でのみ適用できます", + "unsupportedWindowSetting": "この設定は現在適用できません。このフォルダーを直接開いたときに適用されます。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/jpn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..9ca110727d --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "canNotResolveWorkspaceFolderMultiRoot": "'${workspaceFolder}' はマルチ フォルダー ワークスペースで解決できません。 ':' とフォルダー名を使用して、この変数のスコープを指定してください。", + "canNotResolveWorkspaceFolder": "'${workspaceFolder}' を解決できません。フォルダーを開いてください。", + "canNotResolveFolderBasenameMultiRoot": "'${workspaceFolderBasename}' はマルチ フォルダー ワークスペースで解決できません。 ':' とフォルダー名を使用して、この変数のスコープを指定してください。", + "canNotResolveFolderBasename": "'${workspaceFolderBasename}' を解決できません。フォルダーを開いてください。", + "canNotResolveLineNumber": "'${lineNumber}' を解決できません。エディターを開いてください。", + "canNotResolveSelectedText": "'${selectedText}' を解決できません。エディターを開いてください。", + "canNotResolveFile": "'${file}' を解決できません。エディターを開いてください。", + "canNotResolveRelativeFile": "'${relativeFile}' を解決できません。エディターを開いてください。", + "canNotResolveFileDirname": "'${fileDirname}' を解決できません。エディターを開いてください。", + "canNotResolveFileExtname": "'${fileExtname}' を解決できません。エディターを開いてください。", + "canNotResolveFileBasename": "'${fileBasename}' を解決できません。エディターを開いてください。", + "canNotResolveFileBasenameNoExtension": "'${fileBasenameNoExtension}' を解決できません。エディターを開いてください。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/jpn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..bd28d12355 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "環境変数名が指定されていないため、'{0}' を解決できません。", + "configNotFound": "設定 '{1}' が見つからないため、'{0}' を解決できません。", + "configNoString": "'{1}' は構造化された値であるため、'{0}' を解決できません。", + "missingConfigName": "設定名が指定されていないため、'{0}' を解決できません。", + "noValueForCommand": "コマンドに値がないため '{0}' を解決できません。", + "canNotFindFolder": "'{0}' を解決できません。フォルダー '{1}' がありません。", + "canNotResolveWorkspaceFolderMultiRoot": "'{0}' はマルチ フォルダー ワークスペースで解決できません。 ':' とフォルダー名を使用して、この変数のスコープを指定してください。", + "canNotResolveWorkspaceFolder": "'{0}' を解決できません。フォルダーを開いてください。", + "canNotResolveFile": "'{0}' を解決できません。エディターを開いてください。", + "canNotResolveLineNumber": "'{0}' を解決できません。アクティブなエディターに選択済みの行があることを確認してください。", + "canNotResolveSelectedText": "'{0}' を解決できません。アクティブなエディターに選択済みのテキストがあることを確認してください。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/jpn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..d51266c531 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "はい(&&Y)", + "cancelButton": "キャンセル" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/jpn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 2d02a95014..54ebb64a91 100644 --- a/i18n/jpn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "エンジンの互換性。", "vscode.extension.engines.vscode": "VS Code 拡張機能の場合、拡張機能と互換性のある VS Code バージョンを指定します。* を指定することはできません。たとえば、^0.10.5 は最小の VS Code バージョン 0.10.5 との互換性を示します。", "vscode.extension.publisher": "VS Code 拡張機能の公開元。", "vscode.extension.displayName": "VS Code ギャラリーで使用される拡張機能の表示名。", "vscode.extension.categories": "VS Code ギャラリーで拡張機能の分類に使用されるカテゴリ。", + "vscode.extension.category.languages.deprecated": "代わりに 'Programming Languages' を使用してください", "vscode.extension.galleryBanner": "VS Code マーケットプレースで使用されるバナー。", "vscode.extension.galleryBanner.color": "VS Code マーケットプレース ページ ヘッダー上のバナーの色。", "vscode.extension.galleryBanner.theme": "バナーで使用されるフォントの配色テーマ。", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "特定のタイプのデバッグ セッションが起動されるたびに(または、対応する resolveDebugConfiguration メソッドを呼び出す必要があるたびに)、アクティブ化イベントを発行します。", "vscode.extension.activationEvents.workspaceContains": "指定した glob パターンに一致するファイルを少なくとも 1 つ以上含むフォルダーを開くたびにアクティブ化イベントが発行されます。", "vscode.extension.activationEvents.onView": "指定したビューを展開するたびにアクティブ化イベントが発行されます。", + "vscode.extension.activationEvents.onUri": "この拡張機能用のシステム全体の URI が開かれるたびにアクティブ化イベントが発行されます。", "vscode.extension.activationEvents.star": "VS Code 起動時にアクティブ化イベントを発行します。優れたエンドユーザー エクスペリエンスを確保するために、他のアクティブ化イベントの組み合わせでは望む動作にならないときのみ使用してください。", "vscode.extension.badges": "Marketplace の拡張機能ページのサイドバーに表示されるバッジの配列。", "vscode.extension.badges.url": "バッジのイメージ URL。", "vscode.extension.badges.href": "バッジのリンク。", "vscode.extension.badges.description": "バッジの説明。", + "vscode.extension.markdown": "Marketplace で使用される Markdown レンダリング エンジンを制御します。github (既定) か standard のいずれかを指定できます。", + "vscode.extension.qna": "Marketplace の Q&A リンクを制御します。既定の Marketplace Q & A サイトを有効にするには marketplace を設定します。カスタム Q & A サイトの URL を提供するには文字列を設定します。Q & A を完全に無効にするには false を設定します。", "vscode.extension.extensionDependencies": "他の拡張機能に対する依存関係。拡張機能の識別子は常に ${publisher}.${name} です。例: vscode.csharp。", "vscode.extension.scripts.prepublish": "パッケージが VS Code 拡張機能として公開される前に実行されるスクリプト。", "vscode.extension.scripts.uninstall": "VS コード拡張機能のフックをアンインストールします。 VS コードから拡張機能を完全にアンインストールした時に実行されるスクリプトです。スクリプトは、拡張機能をアンインストールした後に VS コードを再起動 (シャット ダウンしてから起動) したときに実行されます。Node スクリプトのみがサポートされます。", diff --git a/i18n/jpn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/jpn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index f506afe894..607dc85410 100644 --- a/i18n/jpn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "すべての拡張機能が無効化されています。", "extensionHostProcess.crash": "拡張機能のホストが予期せずに終了しました。", "extensionHostProcess.unresponsiveCrash": "拡張機能のホストが応答しないため終了しました。", - "devTools": "開発者ツール", + "devTools": "開発者ツールを開く", "restart": "拡張機能のホストを再起動", "overwritingExtension": "拡張機能 {0} を {1} で上書きしています。", "extensionUnderDevelopment": "開発の拡張機能を {0} に読み込んでいます", diff --git a/i18n/jpn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/jpn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index ee55ecde77..79cddaa707 100644 --- a/i18n/jpn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -6,11 +6,24 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5 が必要です。リンクに移動してインストールしてください。", "installNet": ".NET Framework 4.5 をダウンロードします", "neverShowAgain": "今後は表示しない", - "netVersionError": "Microsoft .NET Framework 4.5 が必要です。リンクに移動してインストールしてください。", + "enospcError": "{0} はこの大規模なワークスペース内のファイル変更を監視できません。この問題を解決するには、リンクの手順に従ってください。", "learnMore": "説明書", - "enospcError": "{0} はファイル ハンドルを使い果たしています。この問題を解決するには、リンクの手順に従ってください。", + "fileInvalidPath": "ファイルのリソース ({0}) が無効です", + "fileIsDirectoryError": "ファイルはディレクトリです", + "fileNotModifiedError": "ファイルは次の時点以後に変更されていません:", + "fileTooLargeForHeapError": "このサイズのファイルを開くには、VS Code を再起動してより多くのメモリ使用を許可する必要があります", + "fileTooLargeError": "開くファイルが大きすぎます", + "fileNotFoundError": "ファイルが見つかりません ({0})", + "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません", + "filePermission": "ファイルへの書き込み許可が拒否されました ({0})", + "fileExists": "生成しようとしているファイル ({0}) は既に存在しています", + "fileModifiedError": "ファイルは次の時点以後に更新されました:", + "fileReadOnlyError": "ファイルは読み取り専用です", + "fileMoveConflict": "移動/コピーできません。移動/コピー先にファイルが既に存在します。", + "unableToMoveCopyError": "移動/コピーできません。ファイルが含まれるフォルダーが置き換わることになります。", "binFailed": "'{0}' をごみ箱に移動できませんでした", "trashFailed": "'{0}' をごみ箱に移動できませんでした" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 6c51852e85..1b25dacd1f 100644 --- a/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "ファイルが見つかりません ({0})", "fileIsDirectoryError": "ファイルはディレクトリです", "fileNotModifiedError": "ファイルは次の時点以後に変更されていません:", - "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません" + "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません", + "err.create": "ファイル {0} を作成できませんでした", + "fileMoveConflict": "移動/コピーできません。移動/コピー先にファイルが既に存在します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json index 1fad6594f7..248950a2d4 100644 --- a/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,7 @@ "fileInvalidPath": "ファイルのリソース ({0}) が無効です", "fileIsDirectoryError": "ファイルはディレクトリです", "fileNotModifiedError": "ファイルは次の時点以後に変更されていません:", - "fileTooLargeForHeapError": "ファイル サイズがウィンドウのメモリ制限を超えました。code --max-memory=NEWSIZE をお試しください", + "fileTooLargeForHeapError": "ファイル サイズが既定のメモリ制限を超えています。より大きい制限値で再起動してください。現在の設定では {0}MB で再起動するよう構成されています", "fileTooLargeError": "開くファイルが大きすぎます", "fileNotFoundError": "ファイルが見つかりません ({0})", "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません", diff --git a/i18n/jpn/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/jpn/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..abd7de124f 100644 --- a/i18n/jpn/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "キャンセル" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index f2ed54bfb4..fee9c35991 100644 --- a/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "tmLanguage ファイルにより使用される TextMate スコープ名。", "vscode.extension.contributes.grammars.path": "tmLanguage ファイルのパス。拡張機能フォルダーの相対パスであり、通常 './syntaxes/' で始まります。", "vscode.extension.contributes.grammars.embeddedLanguages": "この文法に言語が埋め込まれている場合は、言語 ID に対するスコープ名のマップ。", + "vscode.extension.contributes.grammars.tokenTypes": "スコープ名のトークン タイプへの割当て。", "vscode.extension.contributes.grammars.injectTo": "この文法が挿入される言語の範囲名の一覧。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 99d7cfb96e..54f8f3f79b 100644 --- a/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", "invalid.injectTo": "`contributes.{0}.injectTo` の値が無効です。言語の範囲名の配列である必要があります。指定された値: {1}", "invalid.embeddedLanguages": "`contributes.{0}.embeddedLanguages` の値が無効です。スコープ名から言語へのオブジェクト マップである必要があります。指定された値: {1}", + "invalid.tokenTypes": "`contributes.{0}.tokenTypes` の値が無効です。オブジェクトはスコープ名からトークン タイプへ割り当てられている必要があります。指定された値: {1}", "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。", "no-tm-grammar": "この言語に対して TM 文法は登録されていません。" } \ No newline at end of file diff --git a/i18n/kor/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/kor/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..18013d8de4 --- /dev/null +++ b/i18n/kor/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS 언어 서버", + "folding.start": "영역 접기 시작", + "folding.end": "접기 영역 끝" +} \ No newline at end of file diff --git a/i18n/kor/extensions/css-language-features/package.i18n.json b/i18n/kor/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..43cc6cb472 --- /dev/null +++ b/i18n/kor/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS 언어 기능", + "description": "CSS, LESS 및 SCSS 파일에 대한 다양한 언어 지원을 제공합니다.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", + "css.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", + "css.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", + "css.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", + "css.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", + "css.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", + "css.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", + "css.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", + "css.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", + "css.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", + "css.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", + "css.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", + "css.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", + "css.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", + "css.lint.unknownProperties.desc": "알 수 없는 속성입니다.", + "css.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", + "css.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", + "css.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", + "css.trace.server.desc": "VS Code와 CSS 언어 서버 간 통신을 추적합니다.", + "css.validate.title": "CSS 유효성 검사 및 문제 심각도를 제어합니다.", + "css.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", + "less.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", + "less.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", + "less.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", + "less.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", + "less.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", + "less.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", + "less.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", + "less.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", + "less.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", + "less.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", + "less.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", + "less.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", + "less.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", + "less.lint.unknownProperties.desc": "알 수 없는 속성입니다.", + "less.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", + "less.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", + "less.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", + "less.validate.title": "LESS 유효성 검사 및 문제 심각도를 제어합니다.", + "less.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", + "scss.title": "SCSS(Sass)", + "scss.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", + "scss.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", + "scss.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", + "scss.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", + "scss.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", + "scss.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", + "scss.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", + "scss.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", + "scss.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", + "scss.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", + "scss.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", + "scss.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", + "scss.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", + "scss.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", + "scss.lint.unknownProperties.desc": "알 수 없는 속성입니다.", + "scss.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", + "scss.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", + "scss.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", + "scss.validate.title": "SCSS 유효성 검사 및 문제 심각도를 제어합니다.", + "scss.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", + "less.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", + "scss.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", + "css.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", + "css.colorDecorators.enable.deprecationMessage": "`css.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다.", + "scss.colorDecorators.enable.deprecationMessage": "`scss.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다.", + "less.colorDecorators.enable.deprecationMessage": "`less.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/css/package.i18n.json b/i18n/kor/extensions/css/package.i18n.json index 138242b48e..2d4d9da939 100644 --- a/i18n/kor/extensions/css/package.i18n.json +++ b/i18n/kor/extensions/css/package.i18n.json @@ -2,80 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS 언어 기능", - "description": "CSS, LESS 및 SCSS 파일에 대한 다양한 언어 지원을 제공합니다.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", - "css.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", - "css.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", - "css.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", - "css.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", - "css.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", - "css.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", - "css.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", - "css.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", - "css.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", - "css.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", - "css.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", - "css.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", - "css.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", - "css.lint.unknownProperties.desc": "알 수 없는 속성입니다.", - "css.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", - "css.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", - "css.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", - "css.trace.server.desc": "VS Code와 CSS 언어 서버 간 통신을 추적합니다.", - "css.validate.title": "CSS 유효성 검사 및 문제 심각도를 제어합니다.", - "css.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", - "less.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", - "less.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", - "less.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", - "less.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", - "less.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", - "less.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", - "less.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", - "less.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", - "less.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", - "less.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", - "less.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", - "less.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", - "less.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", - "less.lint.unknownProperties.desc": "알 수 없는 속성입니다.", - "less.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", - "less.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", - "less.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", - "less.validate.title": "LESS 유효성 검사 및 문제 심각도를 제어합니다.", - "less.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", - "scss.title": "SCSS(Sass)", - "scss.lint.argumentsInColorFunction.desc": "잘못된 매개 변수 수", - "scss.lint.boxModel.desc": "패딩 또는 테두리를 사용하는 경우 너비 또는 높이를 사용하지 마세요.", - "scss.lint.compatibleVendorPrefixes.desc": "공급업체 관련 접두사를 사용할 경우 다른 모든 공급업체 관련 속성도 포함합니다.", - "scss.lint.duplicateProperties.desc": "중복된 스타일 정의를 사용하지 마세요.", - "scss.lint.emptyRules.desc": "빈 규칙 집합을 사용하지 마세요.", - "scss.lint.float.desc": "'float'를 사용하지 않도록 합니다. Float를 사용하면 레이아웃의 한쪽이 바뀔 경우 CSS가 쉽게 깨질 수 있습니다.", - "scss.lint.fontFaceProperties.desc": "@font-face 규칙에서 'src' 및 'font-family' 속성을 정의해야 합니다.", - "scss.lint.hexColorLength.desc": "16진수 색은 3개 또는 6개의 16진수로 구성되어야 합니다.", - "scss.lint.idSelector.desc": "이러한 규칙은 HTML과 긴밀하게 결합되므로 선택기에 ID를 포함하면 안 됩니다.", - "scss.lint.ieHack.desc": "IE 핵(Hack)은 IE7 이상을 지원할 때만 필요합니다.", - "scss.lint.important.desc": "!important는 사용하지 않도록 합니다. 이것은 전체 CSS의 특정성에 문제가 있어서 리팩터링해야 함을 나타냅니다.", - "scss.lint.importStatement.desc": "Import 문은 병렬로 로드되지 않습니다.", - "scss.lint.propertyIgnoredDueToDisplay.desc": "display 때문에 속성이 무시됩니다. 예를 들어 'display: inline'을 사용할 경우 width, height, margin-top, margin-bottom 및 float 속성은 적용되지 않습니다.", - "scss.lint.universalSelector.desc": "범용 선택기 (*)는 느린 것으로 알려져 있습니다.", - "scss.lint.unknownProperties.desc": "알 수 없는 속성입니다.", - "scss.lint.unknownVendorSpecificProperties.desc": "알 수 없는 공급업체 관련 속성입니다.", - "scss.lint.vendorPrefix.desc": "공급업체 관련 접두사를 사용할 때 표준 속성도 포함합니다.", - "scss.lint.zeroUnits.desc": "0에는 단위가 필요하지 않습니다.", - "scss.validate.title": "SCSS 유효성 검사 및 문제 심각도를 제어합니다.", - "scss.validate.desc": "모든 유효성 검사 사용 또는 사용 안 함", - "less.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", - "scss.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", - "css.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", - "css.colorDecorators.enable.deprecationMessage": "`css.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다.", - "scss.colorDecorators.enable.deprecationMessage": "`scss.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다.", - "less.colorDecorators.enable.deprecationMessage": "`less.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다." + "displayName": "CSS 언어 기본", + "description": "CSS,LESS,SCSS 파일에서 구문 강조 표시와 괄호 일치를 제공합니다." } \ No newline at end of file diff --git a/i18n/kor/extensions/emmet/package.i18n.json b/i18n/kor/extensions/emmet/package.i18n.json index 87dcbf43c2..517fee7baf 100644 --- a/i18n/kor/extensions/emmet/package.i18n.json +++ b/i18n/kor/extensions/emmet/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Emmet 프로필 및 코드 조각이 포함된 폴더의 경로입니다.'", "emmetShowExpandedAbbreviation": "확장된 emmet 약어를 제안으로 표시합니다.\n\"inMarkupAndStylesheetFilesOnly\" 옵션이 html, haml, jade, slim, xml, xsl, css, scss, sass, less 및 stylus에 적용됩니다.\n\"always\" 옵션이 마크업/css에 관계없이 파일의 모든 부분에 적용됩니다.", "emmetShowAbbreviationSuggestions": "가능한 emmet 약어를 제안으로 표시합니다. 스타일시트에는 적용되지 않고 emmet.showExpandedAbbreviation이 \"never\"로 설정되어 있을 때도 적용되지 않습니다.", - "emmetIncludeLanguages": "기본 지원되지 않는 언어에서 emmet 약어를 사용합니다. 언어와 emmet 지원 언어 사이에 매핑을 추가합니다.\n예: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "기본 지원되지 않는 언어에서 Emmet 약어를 사용하도록 설정합니다. 언어와 emmet 지원 언어 사이에 매핑을 추가합니다.\n예: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "emmet 조각에 사용되는 변수", "emmetTriggerExpansionOnTab": "사용하도록 설정하면 emmet 약어는 Tab 키를 눌렀을 때 확장됩니다.", "emmetPreferences": "Emmet의 일부 작업 및 해결 프로그램의 동작을 수정하는 데 사용되는 기본 설정입니다.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "`-`로 시작하는 Emmet 약어에서 사용될 때 'webkit' 공급업체 접두사를 가져오는 쉼표로 구분된 CSS 속성입니다. 항상 'webkit' 접두사를 사용하지 않으려면 빈 문자열로 설정합니다.", "emmetPreferencesCssMozProperties": "`-`로 시작하는 Emmet 약어에서 사용될 때 'moz' 공급업체 접두사를 가져오는 쉼표로 구분된 CSS 속성입니다. 항상 'moz' 접두사를 사용하지 않으려면 빈 문자열로 설정합니다.", "emmetPreferencesCssOProperties": "`-`로 시작하는 emmet 약어에서 사용할 때 'o' 공급업체 접두사를 가져오는 쉼표로 구분된 CSS 속성입니다. 항상 'o' 접두사를 사용하지 않으려면 빈 문자열로 설정합니다.", - "emmetPreferencesCssMsProperties": "`-`로 시작하는 emmet 약어에서 사용할 때 'ms' 공급업체 접두사를 가져오는 쉼표로 구분된 CSS 속성입니다. 항상 'ms' 접두사를 사용하지 않으려면 빈 문자열로 설정합니다." + "emmetPreferencesCssMsProperties": "`-`로 시작하는 emmet 약어에서 사용할 때 'ms' 공급업체 접두사를 가져오는 쉼표로 구분된 CSS 속성입니다. 항상 'ms' 접두사를 사용하지 않으려면 빈 문자열로 설정합니다.", + "emmetPreferencesCssFuzzySearchMinScore": "유사 일치 약어가 획득해야 하는 최소 점수(0에서 1 사이)입니다. 값이 낮을수록 가양성 일치 항목이 늘 수 있고, 값이 높을수록 가능한 일치 항목이 줄 수 있습니다.", + "emmetOptimizeStylesheetParsing": "False로 설정할 경우 전체 파일이 구문 분석되어 현재 위치가 Emmet 약어 확장에 유효한지 확인합니다. True로 설정할 경우 css/scss/less 파일에서 현재 위치 주변의 콘텐츠만 구문 분석합니다." } \ No newline at end of file diff --git a/i18n/kor/extensions/git/out/commands.i18n.json b/i18n/kor/extensions/git/out/commands.i18n.json index 966e0f6ab6..26beb55003 100644 --- a/i18n/kor/extensions/git/out/commands.i18n.json +++ b/i18n/kor/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) 새 분기 생성", "repourl": "리포지토리 URL", "parent": "부모 디렉터리", - "cancel": "$(sync~spin) 리포지토리를 복제하는 중... 취소하려면 클릭하세요.", - "cancel tooltip": "복제 취소", - "cloning": "Git 리포지토리를 복제하는 중...", + "cloning": "Git 리포지토리 '{0}'을(를) 복제하는 중...", "openrepo": "리포지토리 열기", "proposeopen": "복제된 리포지토리를 여시겠습니까?", "init": "Git 리포지토리를 초기화할 작업 영역 폴더 선택", @@ -75,7 +73,7 @@ "ok": "확인", "push with tags success": "태그와 함께 푸시되었습니다.", "pick remote": "'{0}' 분기를 다음에 게시하려면 원격을 선택하세요.", - "sync is unpredictable": "이 작업은 '{0}' 간에 커밋을 푸시하고 풀합니다.", + "sync is unpredictable": "이 작업은 '{0}/{1}' 간에 커밋을 푸시하고 풀합니다. ", "never again": "다시 표시 안 함", "no remotes to publish": "리포지토리에 게시하도록 구성된 원격이 없습니다.", "no changes stash": "스태시할 변경 내용이 없습니다.", diff --git a/i18n/kor/extensions/git/package.i18n.json b/i18n/kor/extensions/git/package.i18n.json index 0ab42491e0..24dd12f1d0 100644 --- a/i18n/kor/extensions/git/package.i18n.json +++ b/i18n/kor/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Git 변경점 보기에서 파일 열기 동작 줄을 표시할지의 여부를 제어합니다.", "config.inputValidation": "커밋 메시지 입력 유효성 검사를 언제 표시할지 제어합니다.", "config.detectSubmodules": "Git 하위 모듈을 자동으로 검색할지 여부를 제어합니다.", + "config.detectSubmodulesLimit": "Git submodules 검출 개수의 제한을 제어합니다.", "colors.modified": "수정된 리소스의 색상입니다.", "colors.deleted": "삭제된 리소스의 색상입니다.", "colors.untracked": "추적되지 않은 리소스의 색상입니다.", diff --git a/i18n/kor/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/kor/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..d112b7520a --- /dev/null +++ b/i18n/kor/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML 언어 서버", + "folding.start": "영역 접기 시작", + "folding.end": "접기 영역 끝" +} \ No newline at end of file diff --git a/i18n/kor/extensions/html-language-features/package.i18n.json b/i18n/kor/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..064a37a963 --- /dev/null +++ b/i18n/kor/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML 언어 기능", + "description": "HTML, Razor 및 Handlebar 파일에 대한 다양한 언어 지원을 제공합니다.", + "html.format.enable.desc": "기본 HTML 포맷터를 사용하거나 사용하지 않습니다.", + "html.format.wrapLineLength.desc": "한 줄당 최대 문자 수입니다(0 = 사용 안 함).", + "html.format.unformatted.desc": "쉼표로 분리된 태그 목록으로, 서식을 다시 지정해서는 안 됩니다. https://www.w3.org/TR/html5/dom.html#phrasing-content에 나열된 모든 태그의 기본값은 'null'로 설정됩니다.", + "html.format.contentUnformatted.desc": "쉼표로 분리된 태그 목록으로, 콘텐츠의 서식을 다시 지정해서는 안 됩니다. 'pre' 태그의 기본값은 'null'로 설정됩니다.", + "html.format.indentInnerHtml.desc": "<head> 및 <body> 섹션을 들여쓰기합니다.", + "html.format.preserveNewLines.desc": "요소 앞에 있는 기존 줄 바꿈의 유지 여부입니다. 요소 앞에만 적용되며 태그 안이나 텍스트에는 적용되지 않습니다.", + "html.format.maxPreserveNewLines.desc": "청크 한 개에 유지할 수 있는 최대 줄 바꿈 수입니다. 무제한일 때는 'null'을 사용합니다.", + "html.format.indentHandlebars.desc": "{{#foo}} 및 {{/foo}}를 서식 지정하고 들여쓰기합니다.", + "html.format.endWithNewline.desc": "줄 바꿈으로 끝납니다.", + "html.format.extraLiners.desc": "쉼표로 분리된 태그 목록으로 앞에 줄 바꿈을 추가로 넣어야 합니다. \"head, body, /html\"의 기본값은 'null'로 설정됩니다.", + "html.format.wrapAttributes.desc": "특성을 래핑합니다.", + "html.format.wrapAttributes.auto": "줄 길이를 초과하는 경우에만 특성을 래핑합니다.", + "html.format.wrapAttributes.force": "첫 번째 특성을 제외한 각 특성을 래핑합니다.", + "html.format.wrapAttributes.forcealign": "첫 번째 특성을 제외한 각 특성을 래핑하고 정렬된 상태를 유지합니다.", + "html.format.wrapAttributes.forcemultiline": "각 특성을 래핑합니다.", + "html.suggest.angular1.desc": "기본 제공 HTML 언어 지원에서 Angular V1 태그 및 속성을 제안하는지 여부를 구성합니다.", + "html.suggest.ionic.desc": "기본 제공 HTML 언어 지원에서 Ionic 태그, 속성 및 값을 제안하는지 여부를 구성합니다.", + "html.suggest.html5.desc": "기본 제공 HTML 언어 지원에서 HTML5 태그, 속성 및 값을 제안하는지 여부를 구성합니다.", + "html.trace.server.desc": "VS Code와 HTML 언어 서버 간 통신을 추적합니다.", + "html.validate.scripts": "기본 제공 HTML 언어 지원에서 포함 스크립트의 유효성을 검사하는지 여부를 구성합니다.", + "html.validate.styles": "기본 제공 HTML 언어 지원에서 포함 스타일의 유효성을 검사하는지 여부를 구성합니다.", + "html.autoClosingTags": "HTML 태그의 자동 닫기를 사용하거나 사용하지 않습니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/html/package.i18n.json b/i18n/kor/extensions/html/package.i18n.json index d6cc6edcca..0801cef7b5 100644 --- a/i18n/kor/extensions/html/package.i18n.json +++ b/i18n/kor/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML 언어 기능", - "description": "HTML, Razor 및 Handlebar 파일에 대한 다양한 언어 지원을 제공합니다.", - "html.format.enable.desc": "기본 HTML 포맷터를 사용하거나 사용하지 않습니다.", - "html.format.wrapLineLength.desc": "한 줄당 최대 문자 수입니다(0 = 사용 안 함).", - "html.format.unformatted.desc": "쉼표로 분리된 태그 목록으로, 서식을 다시 지정해서는 안 됩니다. https://www.w3.org/TR/html5/dom.html#phrasing-content에 나열된 모든 태그의 기본값은 'null'로 설정됩니다.", - "html.format.contentUnformatted.desc": "쉼표로 분리된 태그 목록으로, 콘텐츠의 서식을 다시 지정해서는 안 됩니다. 'pre' 태그의 기본값은 'null'로 설정됩니다.", - "html.format.indentInnerHtml.desc": "<head> 및 <body> 섹션을 들여쓰기합니다.", - "html.format.preserveNewLines.desc": "요소 앞에 있는 기존 줄 바꿈의 유지 여부입니다. 요소 앞에만 적용되며 태그 안이나 텍스트에는 적용되지 않습니다.", - "html.format.maxPreserveNewLines.desc": "청크 한 개에 유지할 수 있는 최대 줄 바꿈 수입니다. 무제한일 때는 'null'을 사용합니다.", - "html.format.indentHandlebars.desc": "{{#foo}} 및 {{/foo}}를 서식 지정하고 들여쓰기합니다.", - "html.format.endWithNewline.desc": "줄 바꿈으로 끝납니다.", - "html.format.extraLiners.desc": "쉼표로 분리된 태그 목록으로 앞에 줄 바꿈을 추가로 넣어야 합니다. \"head, body, /html\"의 기본값은 'null'로 설정됩니다.", - "html.format.wrapAttributes.desc": "특성을 래핑합니다.", - "html.format.wrapAttributes.auto": "줄 길이를 초과하는 경우에만 특성을 래핑합니다.", - "html.format.wrapAttributes.force": "첫 번째 특성을 제외한 각 특성을 래핑합니다.", - "html.format.wrapAttributes.forcealign": "첫 번째 특성을 제외한 각 특성을 래핑하고 정렬된 상태를 유지합니다.", - "html.format.wrapAttributes.forcemultiline": "각 특성을 래핑합니다.", - "html.suggest.angular1.desc": "기본 제공 HTML 언어 지원에서 Angular V1 태그 및 속성을 제안하는지 여부를 구성합니다.", - "html.suggest.ionic.desc": "기본 제공 HTML 언어 지원에서 Ionic 태그, 속성 및 값을 제안하는지 여부를 구성합니다.", - "html.suggest.html5.desc": "기본 제공 HTML 언어 지원에서 HTML5 태그, 속성 및 값을 제안하는지 여부를 구성합니다.", - "html.trace.server.desc": "VS Code와 HTML 언어 서버 간 통신을 추적합니다.", - "html.validate.scripts": "기본 제공 HTML 언어 지원에서 포함 스크립트의 유효성을 검사하는지 여부를 구성합니다.", - "html.validate.styles": "기본 제공 HTML 언어 지원에서 포함 스타일의 유효성을 검사하는지 여부를 구성합니다.", - "html.experimental.syntaxFolding": "구문 인식 접기 마커를 설정하거나 해제합니다.", - "html.autoClosingTags": "HTML 태그의 자동 닫기를 사용하거나 사용하지 않습니다." + "displayName": "HTML 언어 기본", + "description": "HTML 파일에서 구문 강조 표시, 괄호 일치 및 코드 조각을 제공합니다." } \ No newline at end of file diff --git a/i18n/kor/extensions/jake/package.i18n.json b/i18n/kor/extensions/jake/package.i18n.json index 41066bfae0..f83be6fbb6 100644 --- a/i18n/kor/extensions/jake/package.i18n.json +++ b/i18n/kor/extensions/jake/package.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "description": "VSCode에 Jake 기능을 추가할 확장입니다.", "displayName": "VSCode에 대한 Jake 지원", "jake.taskDefinition.type.description": "사용자 지정할 Jake 작업입니다.", "jake.taskDefinition.file.description": "작업을 제공하는 Jake 파일이며 생략할 수 있습니다.", diff --git a/i18n/kor/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/kor/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..115ea61271 --- /dev/null +++ b/i18n/kor/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON 언어 서버" +} \ No newline at end of file diff --git a/i18n/kor/extensions/json-language-features/package.i18n.json b/i18n/kor/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..d86c7ffa3d --- /dev/null +++ b/i18n/kor/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON 언어 기능", + "description": "JSON 파일에 대한 다양한 언어 지원을 제공합니다.", + "json.schemas.desc": "현재 프로젝트에서 스키마를 JSON 파일에 연결", + "json.schemas.url.desc": "현재 디렉터리에 있는 스키마의 URL 또는 상대 경로", + "json.schemas.fileMatch.desc": "스키마에 대한 JSON 파일을 확인할 때 일치할 파일 패턴의 배열입니다.", + "json.schemas.fileMatch.item.desc": "스키마에 대한 JSON 파일을 확인할 때 일치할 '*'를 포함할 수 있는 파일 패턴입니다.", + "json.schemas.schema.desc": "지정된 URL에 대한 스키마 정의입니다. 스키마 URL에 대한 액세스 방지를 위해서만 스키마를 제공해야 합니다.", + "json.format.enable.desc": "기본 JSON 포맷터 사용/사용 안 함(다시 시작해야 함)", + "json.tracing.desc": "VS Code와 JSON 언어 서버 간 통신을 추적합니다.", + "json.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", + "json.colorDecorators.enable.deprecationMessage": "`json.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/json/package.i18n.json b/i18n/kor/extensions/json/package.i18n.json index 2ebf12d439..c63982946e 100644 --- a/i18n/kor/extensions/json/package.i18n.json +++ b/i18n/kor/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON 언어 기능", - "description": "JSON 파일에 대한 다양한 언어 지원을 제공합니다.", - "json.schemas.desc": "현재 프로젝트에서 스키마를 JSON 파일에 연결", - "json.schemas.url.desc": "현재 디렉터리에 있는 스키마의 URL 또는 상대 경로", - "json.schemas.fileMatch.desc": "스키마에 대한 JSON 파일을 확인할 때 일치할 파일 패턴의 배열입니다.", - "json.schemas.fileMatch.item.desc": "스키마에 대한 JSON 파일을 확인할 때 일치할 '*'를 포함할 수 있는 파일 패턴입니다.", - "json.schemas.schema.desc": "지정된 URL에 대한 스키마 정의입니다. 스키마 URL에 대한 액세스 방지를 위해서만 스키마를 제공해야 합니다.", - "json.format.enable.desc": "기본 JSON 포맷터 사용/사용 안 함(다시 시작해야 함)", - "json.tracing.desc": "VS Code와 JSON 언어 서버 간 통신을 추적합니다.", - "json.colorDecorators.enable.desc": "색 데코레이터 사용 또는 사용 안 함", - "json.colorDecorators.enable.deprecationMessage": "`json.colorDecorators.enable` 설정은 `editor.colorDecorators`를 위해 사용되지 않습니다.", - "json.experimental.syntaxFolding": "구문 인식 접기 마커를 설정하거나 해제합니다." + "displayName": "JSON 언어 기본", + "description": "JSON 파일에서 구문 강조 표시 및 괄호 일치를 제공합니다. " } \ No newline at end of file diff --git a/i18n/kor/extensions/markdown-basics/package.i18n.json b/i18n/kor/extensions/markdown-basics/package.i18n.json index 8111754597..ef18fb49e6 100644 --- a/i18n/kor/extensions/markdown-basics/package.i18n.json +++ b/i18n/kor/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/kor/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/kor/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..84643755d0 --- /dev/null +++ b/i18n/kor/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "'markdown.styles': {0}을 불러올 수 없음" +} \ No newline at end of file diff --git a/i18n/kor/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/kor/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..4bc763aedc --- /dev/null +++ b/i18n/kor/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[미리 보기] {0}", + "previewTitle": "미리 보기 {0}" +} \ No newline at end of file diff --git a/i18n/kor/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/kor/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..01370fa604 --- /dev/null +++ b/i18n/kor/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "이 문서에서 일부 콘텐츠가 사용하지 않도록 설정되었습니다.", + "preview.securityMessage.title": "Markdown 미리 보기에서 잠재적으로 안전하지 않거나 보안되지 않은 콘텐츠가 사용하지 않도록 설정되어 있습니다. 이 콘텐츠나 스크립트를 허용하려면 Markdown 미리 보기 보안 설정을 변경하세요.", + "preview.securityMessage.label": "콘텐츠 사용할 수 없음 보안 경고" +} \ No newline at end of file diff --git a/i18n/kor/extensions/markdown-language-features/out/security.i18n.json b/i18n/kor/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..aa64002659 --- /dev/null +++ b/i18n/kor/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Strict", + "strict.description": "보안 콘텐츠만 로드", + "insecureLocalContent.title": "안전하지 않은 로컬 콘텐츠 허용", + "insecureLocalContent.description": "localhost에서 제공되는 http를 통한 콘텐츠 로드 사용", + "insecureContent.title": "안전하지 않은 콘텐츠 허용", + "insecureContent.description": "http를 통한 콘텐츠 로드 사용", + "disable.title": "사용 안 함", + "disable.description": "모든 콘텐츠 및 스크립트 실행을 허용합니다. 권장하지 않습니다.", + "moreInfo.title": "추가 정보", + "enableSecurityWarning.title": "이 작업 영역에서 미리 보기 보안 경고 사용", + "disableSecurityWarning.title": "이 작업 영역에서 미리보기 보안 경고 사용 안 함", + "toggleSecurityWarning.description": "콘텐츠 보안 수준에 영향을 주지 않습니다.", + "preview.showPreviewSecuritySelector.title": "이 작업 영역에 대해 Markdown 미리 보기의 보안 설정 선택" +} \ No newline at end of file diff --git a/i18n/kor/extensions/markdown-language-features/package.i18n.json b/i18n/kor/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..83878314eb --- /dev/null +++ b/i18n/kor/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown 언어 기능", + "description": "Markdown에 대한 다양한 언어 지원을 제공합니다.", + "markdown.preview.breaks.desc": "마크다운 미리 보기에서 줄바꿈 렌더링 방식을 설정합니다. 'true'로 설정하면 모든 행에 대해 <br>이(가) 생성됩니다.", + "markdown.preview.linkify": "Markdown 미리 보기에서 URL 같은 텍스트를 링크로 변환을 사용하거나 사용하지 않도록 설정합니다.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "markdown 미리 보기에서 두 번 클릭하여 편집기로 전환합니다.", + "markdown.preview.fontFamily.desc": "markdown 미리 보기에서 사용되는 글꼴 패밀리를 제어합니다.", + "markdown.preview.fontSize.desc": "markdown 미리 보기에서 사용되는 글꼴 크기(픽셀)를 제어합니다.", + "markdown.preview.lineHeight.desc": "markdown 미리 보기에 사용되는 줄 높이를 제어합니다. 이 숫자는 글꼴 크기에 상대적입니다.", + "markdown.preview.markEditorSelection.desc": "markdown 미리 보기에 현재 편집기 선택을 표시합니다.", + "markdown.preview.scrollEditorWithPreview.desc": "Markdown 미리 보기를 스크롤할 때 편집기의 보기를 업데이트합니다.", + "markdown.preview.scrollPreviewWithEditor.desc": "Markdown 편집기를 스크롤할 때 미리 보기의 보기를 업데이트합니다.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[사용되지 않음] markdown 미리 보기를 스크롤하여 편집기에서 현재 선택한 줄을 표시합니다.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "이 설정은 'markdown.preview.scrollPreviewWithEditor'로 대체되었으며 더 이상 영향을 주지 않습니다.", + "markdown.preview.title": "미리 보기 열기", + "markdown.previewFrontMatter.dec": "markdown 미리 보기에서 YAML 전문을 렌더링할 방법을 설정합니다. '숨기기' 기능을 사용하면 전문이 제거되고, 그러지 않으면 전문이 markdown 콘텐츠로 처리됩니다.", + "markdown.previewSide.title": "측면에서 미리 보기 열기", + "markdown.showLockedPreviewToSide.title": "측면에서 잠긴 미리 보기 열기", + "markdown.showSource.title": "소스 표시", + "markdown.styles.dec": "markdown 미리 보기에서 사용할 CSS 스타일시트의 URL 또는 로컬 경로 목록입니다. 상대 경로는 탐색기에서 열린 폴더를 기준으로 해석됩니다. 열린 폴더가 없으면 markdown 파일의 위치를 기준으로 해석됩니다. 모든 '\\'는 '\\\\'로 써야 합니다.", + "markdown.showPreviewSecuritySelector.title": "미리 보기 보안 설정 변경", + "markdown.trace.desc": "Markdown 확장에 대해 디버그 로깅을 사용하도록 설정합니다.", + "markdown.preview.refresh.title": "미리 보기 새로 고침", + "markdown.preview.toggleLock.title": "미리 보기 잠금 설정/해제" +} \ No newline at end of file diff --git a/i18n/kor/extensions/markdown/out/features/preview.i18n.json b/i18n/kor/extensions/markdown/out/features/preview.i18n.json index ebc5b3bfa3..4bc763aedc 100644 --- a/i18n/kor/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/kor/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/kor/extensions/npm/out/npmView.i18n.json b/i18n/kor/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..94edf3b4b0 --- /dev/null +++ b/i18n/kor/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "스크립트에 노드 디버그 옵션(예: '--inspect-brk')이 없으므로 디버깅에 사용할 \"{0}\"을(를) 시작할 수 없습니다.", + "npm.scriptInvalid": "\"{0}\" 스크립트를 찾을 수 없습니다. 뷰로 새로 고쳐 보세요." +} \ No newline at end of file diff --git a/i18n/kor/extensions/npm/out/tasks.i18n.json b/i18n/kor/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..c60d6694a0 --- /dev/null +++ b/i18n/kor/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Npm 작업 검색: {0} 파일을 구문 분석하지 못했습니다. " +} \ No newline at end of file diff --git a/i18n/kor/extensions/npm/package.i18n.json b/i18n/kor/extensions/npm/package.i18n.json index d173977889..ca92d6afee 100644 --- a/i18n/kor/extensions/npm/package.i18n.json +++ b/i18n/kor/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": " `--silent` 옵션으로 npm 명령 실행.", "config.npm.packageManager": "스크립트를 실행하는 데 사용하는 패키지 관리자.", "config.npm.exclude": "자동 스크립트 검색에서 제외할 폴더에 대한 Glob 패턴을 구성합니다.", + "config.npm.enableScriptExplorer": "작업 영역에 'package.json' 파일이 포함되어 있는 경우 npm 스크립트에 대한 탐색기 뷰를 사용하도록 설정합니다.", "npm.parseError": "Npm 작업 검색: {0} 파일을 구문 분석하지 못했습니다.", "taskdef.script": "사용자 지정할 npm 스크립트입니다.", - "taskdef.path": "스크립트를 제공하는 package.json 파일의 폴더에 대한 경로이며 생략할 수 있습니다." + "taskdef.path": "스크립트를 제공하는 package.json 파일의 폴더에 대한 경로이며 생략할 수 있습니다.", + "view.name": "Npm 스크립트", + "command.refresh": "새로 고침", + "command.run": "실행", + "command.debug": "디버그", + "command.openScript": "열기", + "npm.scriptInvalid": "'{0}' 스크립트를 찾을 수 없습니다. 뷰를 새로 고쳐 보세요.", + "npm.noDebugOptions": "스크립트에 노드 디버그 옵션(예: '--inspect-brk')이 없으므로 디버깅에 사용할 '{0}'을(를) 시작할 수 없습니다." } \ No newline at end of file diff --git a/i18n/kor/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/kor/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..e88d0e7552 --- /dev/null +++ b/i18n/kor/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "PHP 파일을 lint하기 위해 {0}(작업 영역 설정으로 정의됨)의 실행을 허용하시겠습니까?", + "php.yes": "허용", + "php.no": "허용 안 함", + "wrongExecutable": "{0}은(는) 유효한 PHP 실행 파일이 아니기 때문에 유효성을 검사할 수 없습니다. 'php.validate.executablePath' 설정을 사용하여 PHP 실행 파일을 구성하세요.", + "noExecutable": "PHP 실행 파일이 설정되지 않았기 때문에 유효성을 검사할 수 없습니다. 'php.validate.executablePath' 설정을 사용하여 PHP 실행 파일을 구성하세요.", + "unknownReason": "{0} 경로를 사용하여 php를 실행하지 못했습니다. 이유를 알 수 없습니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/php-language-features/package.i18n.json b/i18n/kor/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..462c5348bc --- /dev/null +++ b/i18n/kor/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "기본 제공 PHP 언어 제안을 사용하는지 여부를 구성합니다. 지원에서는 PHP 전역 및 변수를 제안합니다.", + "configuration.validate.enable": "기본 제공 PHP 유효성 검사를 사용하거나 사용하지 않습니다.", + "configuration.validate.executablePath": "PHP 실행 파일을 가리킵니다.", + "configuration.validate.run": "저장 시 또는 입력 시 Linter의 실행 여부입니다.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "PHP 유효성 검사 실행 파일을 허용하지 않음(작업\n 영역 설정으로 정의됨)", + "displayName": "PHP 언어 기능", + "description": "PHP 파일에 대한 다양한 언어 지원을 제공합니다. " +} \ No newline at end of file diff --git a/i18n/kor/extensions/php/package.i18n.json b/i18n/kor/extensions/php/package.i18n.json index 8d9916a916..ad3f734a9d 100644 --- a/i18n/kor/extensions/php/package.i18n.json +++ b/i18n/kor/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "기본 제공 PHP 언어 제안을 사용하는지 여부를 구성합니다. 지원에서는 PHP 전역 및 변수를 제안합니다.", - "configuration.validate.enable": "기본 제공 PHP 유효성 검사를 사용하거나 사용하지 않습니다.", - "configuration.validate.executablePath": "PHP 실행 파일을 가리킵니다.", - "configuration.validate.run": "저장 시 또는 입력 시 Linter의 실행 여부입니다.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "PHP 유효성 검사 실행 파일을 허용하지 않음(작업\n 영역 설정으로 정의됨)", - "displayName": "PHP 언어 기능", - "description": "PHP 파일에 대해 IntelliSense, lint 및 언어 기본을 제공합니다." + "displayName": "PHP 언어 기본", + "description": "PHP 파일에서 구문 강조 표시 및 괄호 일치를 제공합니다. " } \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/commands.i18n.json b/i18n/kor/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..dd43847bd6 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "TypeScript 또는 JavaScript 프로젝트를 사용하려면 VS Code의 폴더를 여세요.", + "typescript.projectConfigUnsupportedFile": "TypeScript 또는 JavaScript 프로젝트를 확인할 수 없습니다. 지원되지 않는 파일 형식", + "typescript.projectConfigCouldNotGetInfo": "TypeScript 또는 JavaScript 프로젝트를 확인할 수 없습니다.", + "typescript.noTypeScriptProjectConfig": "파일이 TypeScript 프로젝트의 일부가 아닙니다. 자세히 알아보려면 [여기]({0})를 클릭하세요.", + "typescript.noJavaScriptProjectConfig": "파일이 JavaScript 프로젝트의 일부가 아닙니다. 자세히 알아보려면 [여기]({0})를 클릭하세요.", + "typescript.configureTsconfigQuickPick": "tsconfig.json 구성", + "typescript.configureJsconfigQuickPick": "jsconfig.json 구성" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..65d840cf0b --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "적용할 코드 동작 선택", + "acquiringTypingsLabel": "typings를 가져오는 중...", + "acquiringTypingsDetail": "IntelliSense에 대한 typings 정의를 가져오는 중입니다.", + "autoImportLabel": "{0}에서 자동으로 가져오기" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..365792bc45 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "JavaScript 파일에서 의미 검사를 사용합니다. 파일의 최상단에 있어야 합니다.", + "ts-nocheck": "JavaScript 파일에서 의미 검사를 사용하지 않습니다. 파일의 최상단에 있어야 합니다.", + "ts-ignore": "파일의 다음 행에서 @ts-check 오류를 억제합니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..272312dad8 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1개 구현", + "manyImplementationLabel": "{0}개 구현", + "implementationsErrorLabel": "구현을 확인할 수 없음" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..de5777d4c7 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc 주석" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..86003226d9 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "가져오기 구성" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..b91c84de95 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (파일에서 모두 수정)" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..69609e31fc --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "참조 1개", + "manyReferenceLabel": "참조 {0}개", + "referenceErrorLabel": "참조를 확인할 수 없음" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..6982eedcfd --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "빌드 - {0}", + "buildAndWatchTscLabel": "보기 - {0}" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/kor/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..3f50eeec8a --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "경로 {0}이(가) 올바른 tsserver 설치를 가리키지 않습니다. 포함된 TypeScript 버전을 대신 사용합니다.", + "serverCouldNotBeStarted": "TypeScript 언어 서버를 시작할 수 없습니다. 오류 메시지: {0}", + "typescript.openTsServerLog.notSupported": "TS 서버 로깅을 사용하려면 TS 2.2.2 이상이 필요합니다.", + "typescript.openTsServerLog.loggingNotEnabled": "TS 서버 로깅이 꺼져 있습니다. `typescript.tsserver.log`를 설정하고 TS 서버를 다시 시작하여 로깅을 사용하도록 설정하세요.", + "typescript.openTsServerLog.enableAndReloadOption": "로깅 사용 및 TS 서버 다시 시작", + "typescript.openTsServerLog.noLogFile": "TS 서버에서 로깅을 시작하지 않았습니다.", + "openTsServerLog.openFileFailedFailed": "TS 서버 로그 파일을 열 수 없습니다.", + "serverDiedAfterStart": "TypeScript 언어 서비스가 시작된 직후 5번 종료되었습니다. 서비스가 다시 시작되지 않습니다.", + "serverDiedReportIssue": "문제 보고", + "serverDied": "TypeScript 언어 서비스가 지난 5분 동안 예기치 않게 5번 종료되었습니다." +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..f57994230c --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "잘못된 버전" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..49fa81ab46 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "프로젝트 전체에서 JavaScript/TypeScript 언어 기능을 사용하도록 설정하려면 {0}과(와) 같이 파일이 많은 폴더를 제외하세요.", + "hintExclude.generic": "프로젝트 전체에서 JavaScript/TypeScript 언어 기능을 사용하도록 설정하려면 사용하지 않는 소스 파일이 포함된 큰 폴더를 제외하세요.", + "large.label": "제외 구성", + "hintExclude.tooltip": "프로젝트 전체에서 JavaScript/TypeScript 언어 기능을 사용하도록 설정하려면 사용하지 않는 소스 파일이 포함된 큰 폴더를 제외하세요." +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..0fad82fa51 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "TypeScript IntelliSense를 향상하기 위해 데이터를 페치하는 중", + "typesInstallerInitializationFailed.title": "JavaScript 언어 기능에 대한 입력 파일을 설치할 수 없습니다. NPM이 설치되어 있는지 확인하거나 사용자 설정에서 'typescript.npm'을 구성하세요. 자세히 알아보려면 [여기]({0})를 클릭하세요.", + "typesInstallerInitializationFailed.doNotCheckAgain": "다시 표시 안 함" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..bdd4f232c5 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "VS Code의 버전 사용", + "useWorkspaceVersionOption": "작업 영역 버전 사용", + "learnMore": "자세한 정보", + "selectTsVersion": "JavaScript 및 TypeScript 언어 기능에 사용되는 TypeScript 버전 선택" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/kor/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..9a56332973 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "이 경로에서 TypeScript 버전을 로드할 수 없습니다.", + "noBundledServerFound": "잘못 동작하는 바이러스 감지 도구와 같은 다른 응용 프로그램에서 VS Code의 tsserver가 삭제되었습니다. VS Code를 다시 설치하세요." +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript-language-features/package.i18n.json b/i18n/kor/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..8aa324a017 --- /dev/null +++ b/i18n/kor/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript 및 JavaScript 언어 기능", + "description": "JavaScript 및 TypeScript에 대한 다양한 언어 지원을 제공합니다.", + "typescript.reloadProjects.title": "프로젝트 다시 로드", + "javascript.reloadProjects.title": "프로젝트 다시 로드", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "매개 변수 서명으로 함수를 완료하세요.", + "typescript.tsdk.desc": "사용할 tsserver 및 lib*.d.ts 파일이 들어 있는 폴더 경로를 지정합니다.", + "typescript.disableAutomaticTypeAcquisition": "자동 형식 인식을 사용하지 않습니다. TypeScript >= 2.0.6이 필요합니다.", + "typescript.tsserver.log": "파일에 대해 TS 서버 로깅을 사용하도록 설정합니다. 이 로그는 TS 서버 문제를 진단하는 데 사용될 수 있습니다. 로그에는 파일 경로, 소스 코드 및 프로젝트에서 잠재적으로 중요한 기타 정보가 포함될 수 있습니다.", + "typescript.tsserver.pluginPaths": "Typescript 언어 서비스 플러그 인을 검색할 추가 경로입니다. TypeScript 2.3.0 이상이 필요합니다.", + "typescript.tsserver.pluginPaths.item": "절대 또는 상대 경로입니다. 상대 경로는 작업 영역 폴더를 기준으로 확인됩니다.", + "typescript.tsserver.trace": "TS 서버로 전송한 메시지 추적을 사용하도록 설정합니다. 이\n 추적은 TS 서버 문제를 진단하는 데 사용될 수 있습니다. 추적에는 파일 경로, 소스 코드 및 프로젝트에서 잠재적으로 중요한\n 기타 정보가 포함될 수 있습니다.", + "typescript.validate.enable": "TypeScript 유효성 검사를 사용하거나 사용하지 않습니다.", + "typescript.format.enable": "기본 TypeScript 포맷터를 사용하거나 사용하지 않습니다.", + "javascript.format.enable": "기본 JavaScript 포맷터를 사용하거나 사용하지 않습니다.", + "format.insertSpaceAfterCommaDelimiter": "쉼표 구분 기호 뒤에 오는 공백 처리를 정의합니다.", + "format.insertSpaceAfterConstructor": "컨스트럭터 키워드 뒤 공백 처리를 정의합니다. TypeScript >= 2.3.0이 필요합니다.", + "format.insertSpaceAfterSemicolonInForStatements": " for 문에서 세미콜론 뒤에 오는 공백 처리를 정의합니다.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "이항 연산자 뒤에 오는 공백 처리를 정의합니다.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "제어 흐름 문의 키워드 뒤에 오는 공백 처리를 정의합니다.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "익명 함수의 function 키워드 뒤에 오는 공백 처리를 정의합니다.", + "format.insertSpaceBeforeFunctionParenthesis": "함수 인수 괄호 앞에 오는 공백 처리를 정의합니다. TypeScript 2.1.5 이상이 필요합니다.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "비어 있지 않은 여는 괄호 뒤와 닫는 괄호 앞에 오는 공백 처리를 정의합니다.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "비어 있지 않은 여는 대괄호 뒤와 닫는 대괄호 앞에 오는 공백 처리를 정의합니다.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "비어 있지 않은 여는 중괄호 뒤와 닫는 중괄호 앞의 공백 처리를 정의합니다. TypeScript 2.3.0 이상이 필요합니다.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "템플릿 문자열의 여는 중괄호 뒤와 닫는 중괄호 앞의 공백 처리를 정의합니다. TypeScript >= 2.0.6이 필요합니다.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "JSX 식의 여는 중괄호 뒤와 닫는 중괄호 앞의 공백 처리를 정의합니다. TypeScript >= 2.0.6이 필요합니다.", + "format.insertSpaceAfterTypeAssertion": "TypeScript에서 유형 어설션 이후 공백 처리를 정의합니다. TypeScript >= 2.4가 필요합니다.", + "format.placeOpenBraceOnNewLineForFunctions": "함수의 새 줄에 여는 중괄호를 넣을지 정의합니다.", + "format.placeOpenBraceOnNewLineForControlBlocks": "제어 블록의 새 줄에 여는 중괄호를 넣을지 정의합니다.", + "javascript.validate.enable": "JavaScript 유효성 검사를 사용하거나 사용하지 않습니다.", + "typescript.goToProjectConfig.title": "프로젝트 구성으로 이동", + "javascript.goToProjectConfig.title": "프로젝트 구성으로 이동", + "javascript.referencesCodeLens.enabled": "JavaScript 파일에서 CodeLense 참조를 사용/사용 안 함으로 설정합니다.", + "typescript.referencesCodeLens.enabled": "TypeScript 파일에서 참조 CodeLense를 사용/사용 안 함으로 설정합니다. TypeScript >= 2.0.6이 필요합니다.", + "typescript.implementationsCodeLens.enabled": "구현 CodeLens를 사용하거나 사용하지 않도록 설정합니다. TypeScript >= 2.2.0이 필요합니다.", + "typescript.openTsServerLog.title": "TS 서버 로그 열기", + "typescript.restartTsServer": "TS 서버 다시 시작", + "typescript.selectTypeScriptVersion.title": "TypeScript 버전 선택", + "typescript.reportStyleChecksAsWarnings": "스타일 검사를 경고로 보고", + "jsDocCompletion.enabled": "자동 JSDoc 주석 사용/사용 안 함", + "javascript.implicitProjectConfig.checkJs": "JavaScript 파일의 의미 체계 검사를 사용/사용하지 않습니다. 기존 jsconfig.json 또는 tsconfig.json 파일은 이 설정을 재정의합니다. TypeScript >=2.3.1이 필요합니다. ", + "typescript.npm": "자동 입력 인식에 사용된 NPM 실행 파일 경로를 지정합니다. TypeScript >= 2.3.4가 필요합니다.", + "typescript.check.npmIsInstalled": "자동 입력 인식에 대해 NPM이 설치되어 있는지 확인합니다.", + "javascript.nameSuggestions": "JavaScript 제안 목록의 파일에서 고유한 이름 포함을 사용/사용 안 함으로 설정합니다.", + "typescript.tsc.autoDetect": "tsc 작업의 자동 검색을 제어합니다. '해제'는 이 기능을 사용하지 않도록 설정합니다. '빌드'는 단일 실행 컴파일 작업만 만듭니다. '보기'는 컴파일 및 보기 작업만 만듭니다. '설정'은 빌드 및 보기 작업을 모두 만듭니다. 기본 옵션은 '설정'입니다.", + "typescript.problemMatchers.tsc.label": "TypeScript 문제", + "typescript.problemMatchers.tscWatch.label": "TypeScript 문제(감시 모드)", + "typescript.quickSuggestionsForPaths": "가져오기 경로를 입력할 때 빠른 제안을 사용하거나 사용하지 않습니다.", + "typescript.locale": "TypeScript 오류를 보고하는 데 사용하는 로캘을 설정합니다. TypeScript >= 2.6.0이 필요합니다. 기본값 'null'은 TypeScript 오류에 대해 VS Code의 로캘을 사용합니다.", + "javascript.implicitProjectConfig.experimentalDecorators": "프로젝트의 일부가 아닌 JavaScript 파일에 대해 'experimentalDecorators'를 사용하거나 사용하지 않도록 설정합니다. 기존 jsconfig.json 또는 tsconfig.json 파일은 이 설정을 재정의합니다. TypeScript >=2.3.1이 필요합니다.", + "typescript.autoImportSuggestions.enabled": "자동 가져오기 제안을 사용하거나 사용하지 않도록 설정합니다. TypeScript >=2.6.1이 필요합니다.", + "typescript.experimental.syntaxFolding": "구문 인식 접기 마커를 설정하거나 해제합니다.", + "taskDefinition.tsconfig.description": "TS 빌드를 정의하는 tsconfig 파일입니다.", + "javascript.suggestionActions.enabled": "편집기에서 JavaScript 파일에 대한 제안 진단을 사용하거나 사용하지 않도록 설정합니다. TypeScript 2.8 이상이 필요합니다.", + "typescript.suggestionActions.enabled": "편집기에서 TypeScript 파일에 대한 제안 진단을 사용하거나 사용하지 않도록 설정합니다. TypeScript 2.8 이상이 필요합니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/base/node/zip.i18n.json b/i18n/kor/src/vs/base/node/zip.i18n.json index 35de0f401f..d58831ee8b 100644 --- a/i18n/kor/src/vs/base/node/zip.i18n.json +++ b/i18n/kor/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "완료되지 않았습니다. {1}개 항목 중 {0}개가 추출되었습니다.", "notFound": "zip 파일 내에 {0}이(가) 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/kor/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 9895df5f30..e629243de3 100644 --- a/i18n/kor/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/kor/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "GitHub에서 미리 보기", "loadingData": "데이터 로드 중...", + "rateLimited": "GitHub 쿼리 제한이 초과되었습니다. 기다려 주세요.", "similarIssues": "유사한 문제", "open": "열기", "closed": "닫힘", - "noResults": "결과 없음", + "noSimilarIssues": "검색된 유사한 문제 없음", "settingsSearchIssue": "설정 검색 문제", "bugReporter": "버그 보고서", - "performanceIssue": "성능 문제", "featureRequest": "기능 요청", + "performanceIssue": "성능 문제", "stepsToReproduce": "재현 단계", "bugDescription": "문제를 안정적으로 재현시킬 수 있는 방법을 공유해주세요. 실제 결과와 예상 결과를 포함하세요. GitHub 버전의 Markdown을 지원합니다. GitHub에서 미리 볼 때 문제를 편집하고 스크린샷을 추가할 수 있습니다.", "performanceIssueDesciption": "이 성능 문제가 언제 발생합니까? 시작할 때 발생합니까? 특정 작업을 진행한 이후에 발생합니까? GitHub 버전의 Markdown을 지원합니다. GitHub에서 미리 볼 때 문제를 편집하고 스크린샷을 추가할 수 있습니다.", diff --git a/i18n/kor/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/kor/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index f151818e7c..ea3d4e905b 100644 --- a/i18n/kor/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/kor/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "양식을 영어로 작성해 주세요.", "issueTypeLabel": "이것은", + "issueSourceLabel": "제출 대상", + "vscode": "Visual Studio Code", + "extension": "확장", + "disableExtensionsLabelText": "{0} 후 문제를 재현해 보세요. 확장이 활성 상태인 경우에만 문제가 재현되면 확장과 관련된 문제일 수 있습니다.", + "disableExtensions": "모든 확장을 사용하지 않도록 설정하고 창 다시 로드", + "chooseExtension": "확장", "issueTitleLabel": "제목", "issueTitleRequired": "제목을 입력하세요.", "titleLengthValidation": "제목이 너무 깁니다.", @@ -18,13 +24,6 @@ "extensions": "내 확장", "searchedExtensions": "검색된 확장", "settingsSearchDetails": "설정 검색 세부 정보", - "tryDisablingExtensions": "확장을 사용하지 않도록 설정해도 문제 재현이 가능한가요?", - "yes": "예", - "no": "아니요", - "disableExtensionsLabelText": "{0} 후 문제를 재현해 보세요.", - "disableExtensions": "모든 확장을 사용하지 않도록 설정하고 창 다시 로드", - "showRunningExtensionsLabelText": "확장 문제로 의심되면 {0}에서 확장에 대한 문제를 보고하세요.", - "showRunningExtensions": "모든 실행 중인 확장 보기", "details": "상세 내용을 입력하세요.", "loadingData": "데이터 로드 중..." } \ No newline at end of file diff --git a/i18n/kor/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/kor/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..7fdbd9cc5d --- /dev/null +++ b/i18n/kor/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "CPU %", + "memory": "메모리(MB)", + "pid": "pid", + "name": "이름", + "killProcess": "프로세스 종료", + "forceKillProcess": "프로세스 강제 종료" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/code/electron-main/menus.i18n.json b/i18n/kor/src/vs/code/electron-main/menus.i18n.json index 0a5165abed..9982cf045f 100644 --- a/i18n/kor/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/kor/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "조건부 중단점(&&C)...", "miColumnBreakpoint": "열 중단점(&&O)", "miFunctionBreakpoint": "함수 중단점(&&F)...", + "miLogPoint": "Logpoint(&&L)...", "miNewBreakpoint": "새 중단점(&&N)", "miEnableAllBreakpoints": "모든 중단점 설정", "miDisableAllBreakpoints": "모든 중단점 사용 안 함(&&L)", @@ -161,6 +162,7 @@ "mMergeAllWindows": "모든 창 병합", "miToggleDevTools": "개발자 도구 설정/해제(&&T)", "miAccessibilityOptions": "접근성 옵션(&&O)", + "miOpenProcessExplorerer": "프로세스 탐색기 열기(&&P)", "miReportIssue": "문제 보고(&&I)", "miWelcome": "시작(&&W)", "miInteractivePlayground": "대화형 실습(&&I)", diff --git a/i18n/kor/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/kor/src/vs/editor/browser/widget/diffReview.i18n.json index d678f76c50..13bf67833b 100644 --- a/i18n/kor/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/kor/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "닫기", - "header": "다른 항목 {0} / {1}: 원본 {2}, {3}행, 수정 {4}, {5}행", + "no_lines": "줄 없음", + "one_line": "1줄", + "more_lines": "{0}줄", + "header": "차이 {0}/{1}개: 원본 {2}, {3}, 수정 {4}, {5}", "blankLine": "비어 있음", "equalLine": "원본 {0}, 수정 {1}: {2}", "insertLine": "+ 수정됨 {0}: {1}", diff --git a/i18n/kor/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/kor/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..abc2f81a46 --- /dev/null +++ b/i18n/kor/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "커서 수는 {0}(으)로 제한되었습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json index b828fef472..fb14d2e1bc 100644 --- a/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "줄 번호는 절대값으로 렌더링 됩니다.", "lineNumbers.relative": "줄 번호는 커서 위치에서 줄 간격 거리로 렌더링 됩니다.", "lineNumbers.interval": "줄 번호는 매 10 줄마다 렌더링이 이루어집니다.", - "lineNumbers": "줄 번호의 표시 방식을 제어합니다. 가능한 값은 'on', 'off', 'relative', 'interval' 입니다.", + "lineNumbers": "줄 번호 표시를 제어합니다.", "rulers": "특정 수의 고정 폭 문자 뒤에 세로 눈금자를 렌더링합니다. 여러 눈금자의 경우 여러 값을 사용합니다. 배열이 비어 있는 경우 눈금자가 그려져 있지 않습니다.", "wordSeparators": "단어 관련 탐색 또는 작업을 수행할 때 단어 구분 기호로 사용되는 문자입니다.", "tabSize": "탭 한 개에 해당하는 공백 수입니다. `editor.detectIndentation`이 켜져 있는 경우 이 설정은 파일 콘텐츠에 따라 재정의됩니다.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "편집기에서 마지막 줄 이후로 스크롤할지 여부를 제어합니다.", "smoothScrolling": "편집기에서 애니메이션을 사용하여 스크롤할지 여부를 제어합니다.", "minimap.enabled": "미니맵 표시 여부를 제어합니다.", - "minimap.side": "미니맵이 표시될 곳을 결정합니다. '오른쪽'과 '왼쪽'이 선택 가능합니다.", - "minimap.showSlider": "미니맵 슬라이더를 자동으로 숨길지 결정합니다. 가능한 값은 'always' 및 'mouseover'입니다.", + "minimap.side": "미니맵을 렌더링할 측면을 제어합니다.", + "minimap.showSlider": "미니맵 슬라이더를 자동으로 숨길지 결정합니다.", "minimap.renderCharacters": "줄의 실제 문자(색 블록 아님) 렌더링", "minimap.maxColumn": "최대 특정 수의 열을 렌더링하도록 미니맵의 너비를 제한합니다.", "find.seedSearchStringFromSelection": "편집기 선택에서 Find Widget의 검색 문자열을 시딩할지 설정합니다.", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Windows와 Linux의 'Control'을 macOS의 'Command'로 매핑합니다.", "multiCursorModifier.alt": "Windows와 Linux의 'Alt'를 macOS의 'Option'으로 매핑합니다.", "multiCursorModifier": "마우스로 여러 커서를 추가할 때 사용할 수정자입니다. `ctrlCmd`는 Windows와 Linux에서 `Control`로 매핑되고 macOS에서 `Command`로 매핑됩니다. Go To Definition 및 Open Link 마우스 제스처가 멀티커서 수정자와 충돌하지 않도록 조정됩니다.", + "multiCursorMergeOverlapping": "여러 커서가 겹치는 경우 커서를 병합합니다.", "quickSuggestions.strings": "문자열 내에서 빠른 제안을 사용합니다.", "quickSuggestions.comments": "주석 내에서 빠른 제안을 사용합니다.", "quickSuggestions.other": "문자열 및 주석 외부에서 빠른 제안을 사용합니다.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "편집기에서 의미 체계 기호 항목을 강조 표시할지 여부를 제어합니다.", "overviewRulerLanes": "개요 눈금자에서 동일한 위치에 표시될 수 있는 장식 수를 제어합니다.", "overviewRulerBorder": "개요 눈금자 주위에 테두리를 그릴지 여부를 제어합니다.", - "cursorBlinking": "커서 애니메이션 스타일을 제어합니다. 가능한 값은 'blink', 'smooth', 'phase', 'expand' 및 'solid'입니다.", + "cursorBlinking": "커서 애니메이션 스타일을 제어합니다.", "mouseWheelZoom": "마우스 휠을 사용할 때 Ctrl 키를 누르고 있으면 편집기의 글꼴 확대/축소", "cursorStyle": "커서 스타일을 제어합니다. 허용되는 값은 '블록', '블록-윤곽', '줄', '줄-가늘게', '밑줄' 및 '밑줄-가늘게'입니다.", "cursorWidth": "editor.cursorStyle 설정이 'line'으로 설정되어 있을 때 커서의 넓이를 조절합니다.", @@ -86,8 +87,11 @@ "renderControlCharacters": "편집기에서 제어 문자를 렌더링할지를 제어합니다.", "renderIndentGuides": "편집기에서 들여쓰기 가이드를 렌더링할지를 제어합니다.", "renderLineHighlight": "편집기가 현재 줄 강조 표시를 렌더링하는 방식을 제어합니다. 가능한 값은 'none', 'gutter', 'line' 및 'all'입니다.", - "codeLens": "편집기에서 코드 필터를 표시하는지 여부를 제어합니다.", + "codeLens": "편집기에서 CodeLens를 표시하는지 여부를 제어합니다.", "folding": "편집기에서 코드 접기를 사용할지 여부를 제어합니다.", + "foldingStrategyAuto": "사용 가능한 경우 언어 관련 접기 전략을 사용하고, 그렇지 않은 경우 들여쓰기 기반 전략으로 대체합니다.", + "foldingStrategyIndentation": "항상 들여쓰기 기반 접기 전략 사용", + "foldingStrategy": "접기 범위를 계산하는 방식을 제어합니다. '자동' 선택이면 사용 가능한 경우 언어 관련 접기 전략을 사용합니다. '들여쓰기'이면 들여쓰기 기반 접기 전략이 사용됩니다.", "showFoldingControls": "거터의 폴드 컨트롤을 자동으로 숨길지 결정합니다.", "matchBrackets": "대괄호 중 하나를 선택할 때 일치하는 대괄호를 강조 표시합니다.", "glyphMargin": "편집기에서 세로 문자 모양 여백을 렌더링할지 여부를 제어합니다. 문자 모양 여백은 주로 디버깅에 사용됩니다.", @@ -102,8 +106,12 @@ "links": "편집기에서 링크를 감지하고 클릭할 수 있게 만들지 결정합니다.", "colorDecorators": "편집기에서 인라인 색 데코레이터 및 색 선택을 렌더링할지를 제어합니다.", "codeActions": "코드 동작 전구를 사용합니다.", + "codeActionsOnSave.organizeImports": "저장할 때 가져오기 구성을 실행하시겠습니까?", + "codeActionsOnSave": "저장할 때 실행되는 코드 동작 종류입니다.", + "codeActionsOnSaveTimeout": "저장할 때 실행되는 코드 동작에 대한 시간 제한입니다.", "selectionClipboard": "Linux 주 클립보드의 지원 여부를 제어합니다.", "sideBySide": "diff 편집기에서 diff를 나란히 표시할지 인라인으로 표시할지 여부를 제어합니다.", "ignoreTrimWhitespace": "diff 편집기에서 선행 공백 또는 후행 공백 변경을 diffs로 표시할지 여부를 제어합니다.", + "largeFileOptimizations": "큰 파일에 대한 특수 처리로, 메모리를 많이 사용하는 특정 기능을 사용하지 않도록 설정합니다.", "renderIndicators": "diff 편집기에서 추가/제거된 변경 내용에 대해 +/- 표시기를 표시하는지 여부를 제어합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json index cbd45eb9fd..6dd11aae95 100644 --- a/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,11 +14,13 @@ "editorCursorBackground": "편집기 커서의 배경색입니다. 블록 커서와 겹치는 글자의 색상을 사용자 정의할 수 있습니다.", "editorWhitespaces": "편집기의 공백 문자 색입니다.", "editorIndentGuides": "편집기 들여쓰기 안내선 색입니다.", + "editorActiveIndentGuide": "활성 편집기 들여쓰기 안내선 색입니다.", "editorLineNumbers": "편집기 줄 번호 색입니다.", "editorActiveLineNumber": "편집기 활성 영역 줄번호 색상", + "deprecatedEditorActiveLineNumber": "Id는 사용 되지 않습니다. 대신 'editorLineNumber.activeForeground'를 사용 합니다.", "editorRuler": "편집기 눈금의 색상입니다.", "editorCodeLensForeground": "편집기 코드 렌즈의 전경색입니다.", - "editorBracketMatchBackground": "일치하는 브래킷 뒤의 배경색입니다.", + "editorBracketMatchBackground": "일치하는 괄호 뒤의 배경색", "editorBracketMatchBorder": "일치하는 브래킷 박스의 색상", "editorOverviewRulerBorder": "개요 눈금 경계의 색상입니다.", "editorGutter": "편집기 거터의 배경색입니다. 거터에는 글리프 여백과 행 수가 있습니다.", @@ -28,7 +30,9 @@ "warningBorder": "편집기 내 경고 표시선의 테두리 색입니다.", "infoForeground": "편집기 내 정보 표시선의 전경색입니다.", "infoBorder": "편집기 내 정보 표시선의 테두리 색입니다.", - "overviewRulerRangeHighlight": "범위 강조 표시의 개요 눈금자 마커 색입니다.", + "hintForeground": "편집기에서 힌트 표시선의 전경색입니다.", + "hintBorder": "편집기에서 힌트 표시선의 테두리 색입니다.", + "overviewRulerRangeHighlight": "범위 강조의 개요 눈금자 표식 색입니다. 이 색은 불투명해야만 내부 장식을 가리지 않습니다.", "overviewRuleError": "오류의 개요 눈금자 마커 색입니다.", "overviewRuleWarning": "경고의 개요 눈금자 마커 색입니다.", "overviewRuleInfo": "정보의 개요 눈금자 마커 색입니다." diff --git a/i18n/kor/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/kor/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..8c25ff6cd4 --- /dev/null +++ b/i18n/kor/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "수정 사항 표시({0})", + "quickFix": "수정 사항 표시", + "quickfix.trigger.label": "빠른 수정...", + "editor.action.quickFix.noneMessage": "사용 가능한 코드 동작이 없습니다.", + "refactor.label": "리팩터링...", + "editor.action.refactor.noneMessage": "사용 가능한 리펙터링이 없습니다.", + "source.label": "소스 작업...", + "editor.action.source.noneMessage": "사용 가능한 소스 작업이 없습니다.", + "organizeImports.label": "가져오기 구성", + "editor.action.organize.noneMessage": "사용 가능한 가져오기 구성 작업이 없습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/find/findController.i18n.json b/i18n/kor/src/vs/editor/contrib/find/findController.i18n.json index bb0b4cec00..0423484d19 100644 --- a/i18n/kor/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "찾기", + "startFindWithSelectionAction": "선택 영역에서 찾기", "findNextMatchAction": "다음 찾기", "findPreviousMatchAction": "이전 찾기", "nextSelectionMatchFindAction": "다음 선택 찾기", diff --git a/i18n/kor/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/kor/src/vs/editor/contrib/format/formatActions.i18n.json index 6fe197f468..1e60346179 100644 --- a/i18n/kor/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "줄 {1}과(와) {2} 사이에서 {0}개 서식 편집을 수행했습니다.", "no.provider": " '{0}'-파일에 대한 설치된 형식기가 없습니다.", "formatDocument.label": "문서 서식", - "formatSelection.label": "선택 영역 서식" + "no.documentprovider": " '{0}'-파일에 대한 문서 포맷터가 설치되어 있지 않습니다.", + "formatSelection.label": "선택 영역 서식", + "no.selectionprovider": "'{0}'-파일에 대한 선택 영역 포맷터가 설치되어 있지 않습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 17af735ed9..75c3b305c9 100644 --- a/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "다음 문제로 이동 (오류, 경고, 정보)", - "markerAction.previous.label": "이전 문제로 이동 (오류, 경고, 정보)", - "editorMarkerNavigationError": "편집기 표식 탐색 위젯 오류 색입니다.", - "editorMarkerNavigationWarning": "편집기 표식 탐색 위젯 경고 색입니다.", - "editorMarkerNavigationInfo": "편집기 표식 탐색 위젯 정보 색입니다.", - "editorMarkerNavigationBackground": "편집기 표식 탐색 위젯 배경입니다." + "markerAction.previous.label": "이전 문제로 이동 (오류, 경고, 정보)" } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/kor/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..ff17e99717 --- /dev/null +++ b/i18n/kor/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "편집기 표식 탐색 위젯 오류 색입니다.", + "editorMarkerNavigationWarning": "편집기 표식 탐색 위젯 경고 색입니다.", + "editorMarkerNavigationInfo": "편집기 표식 탐색 위젯 정보 색입니다.", + "editorMarkerNavigationBackground": "편집기 표식 탐색 위젯 배경입니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/links/links.i18n.json b/i18n/kor/src/vs/editor/contrib/links/links.i18n.json index a3c8ca3fbd..47af8da2d2 100644 --- a/i18n/kor/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "Ctrl 키를 누르고 클릭하여 링크로 이동", "links.command.mac": "명령을 실행하려면 Cmd+클릭", "links.command": "명령을 실행하려면 Ctrl+클릭", + "links.navigate.al.mac": "<Option> 키를 누르고 클릭하여 링크로 이동", "links.navigate.al": "Alt 키를 누르고 클릭하여 링크로 이동", + "links.command.al.mac": "<Option> 키를 누르고 클릭하여 명령 실행", "links.command.al": "명령을 실행하려면 Alt+클릭", "invalid.url": "{0} 형식이 올바르지 않으므로 이 링크를 열지 못했습니다", "missing.url": "대상이 없으므로 이 링크를 열지 못했습니다.", diff --git a/i18n/kor/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/kor/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..1ef12fcdba --- /dev/null +++ b/i18n/kor/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "읽기 전용 편집기에서 편집할 수 없습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/kor/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index a0e33d6de8..62c4de41f7 100644 --- a/i18n/kor/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Peek 뷰 편집기의 배경색입니다.", "peekViewEditorGutterBackground": "Peek 뷰 편집기의 거터 배경색입니다.", "peekViewResultsMatchHighlight": "Peek 뷰 결과 목록의 일치 항목 강조 표시 색입니다.", - "peekViewEditorMatchHighlight": "Peek 뷰 편집기의 일치 항목 강조 표시 색입니다." + "peekViewEditorMatchHighlight": "Peek 뷰 편집기의 일치 항목 강조 표시 색입니다.", + "peekViewEditorMatchHighlightBorder": "Peek 뷰 편집기의 일치 항목 강조 표시 테두리입니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/kor/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..7078503b8e --- /dev/null +++ b/i18n/kor/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "일요일", + "Monday": "월요일", + "Tuesday": "화요일", + "Wednesday": "수요일", + "Thursday": "목요일", + "Friday": "금요일", + "Saturday": "토요일", + "SundayShort": "일", + "MondayShort": "월", + "TuesdayShort": "화", + "WednesdayShort": "수", + "ThursdayShort": "목", + "FridayShort": "금", + "SaturdayShort": "토", + "January": "1 월", + "February": "2 월", + "March": "3 월", + "April": "4 월", + "May": "5 월", + "June": "6 월", + "July": "7 월", + "August": "8 월", + "September": "9 월", + "October": "10 월", + "November": "11 월", + "December": "12 월", + "JanuaryShort": "1 월", + "FebruaryShort": "2 월", + "MarchShort": "3 월", + "AprilShort": "4 월", + "MayShort": "5 월", + "JuneShort": "6 월", + "JulyShort": "7 월", + "AugustShort": "8 월", + "SeptemberShort": "9 월", + "OctoberShort": "10 월", + "NovemberShort": "11 월", + "DecemberShort": "12 월" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index e10e0822bd..0c65cd2c1b 100644 --- a/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "변수에 쓰기와 같은 쓰기 액세스 중 기호의 배경색입니다. 색상은 밑에 깔린 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", "wordHighlightBorder": "변수 읽기와 같은 읽기 액세스 중 기호의 테두리 색입니다.", "wordHighlightStrongBorder": "변수에 쓰기와 같은 쓰기 액세스 중 기호의 테두리 색입니다.", - "overviewRulerWordHighlightForeground": "기호 강조 표시의 개요 눈금자 마커 색입니다.", - "overviewRulerWordHighlightStrongForeground": "쓰기 권한 기호 강조 표시의 개요 눈금자 마커 색입니다.", + "overviewRulerWordHighlightForeground": "기호 강조의 개요 눈금자 표식 색입니다. 이 색은 불투명해야만 내부 장식을 가리지 않습니다.", + "overviewRulerWordHighlightStrongForeground": "쓰기 액세스 기호 강조의 개요 눈금자 표식 색입니다. 이 색은 불투명해야만 내부 장식을 가리지 않습니다.", "wordHighlight.next.label": "다음 강조 기호로 이동", "wordHighlight.previous.label": "이전 강조 기호로 이동" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/kor/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..e770ddd164 --- /dev/null +++ b/i18n/kor/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1개의 추가 파일이 표시되지 않음", + "moreFiles": "...{0}개의 추가 파일이 표시되지 않음" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/kor/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..a32e01e761 --- /dev/null +++ b/i18n/kor/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "취소" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/environment/node/argv.i18n.json b/i18n/kor/src/vs/platform/environment/node/argv.i18n.json index 2ba581eac6..7a2a4ec98f 100644 --- a/i18n/kor/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/kor/src/vs/platform/environment/node/argv.i18n.json @@ -29,8 +29,8 @@ "performance": "'Developer: Startup Performance' 명령을 사용하여 시작합니다.", "prof-startup": "시작하는 동안 CPU 프로파일러 실행", "disableExtensions": "설치된 모든 확장을 사용하지 않도록 설정합니다.", - "inspect-extensions": "디버깅 및 확장 프로파일링을 허용합니다. 연결 uri에 대한 개발자 도구를 확인하십시오.", - "inspect-brk-extensions": "시작 후 일시 중시된 확장 호스트에서 디버깅 및 확장 프로파일링을 허용합니다. 연결 URL은 개발자 도구를 확인하세요.", + "inspect-extensions": "디버깅 및 확장 프로파일링을 허용합니다. 연결 URI는 개발자 도구를 확인하세요.", + "inspect-brk-extensions": "시작 후 일시 중시된 확장 호스트에서 디버깅 및 확장 프로파일링을 허용합니다. 연결 URI는 개발자 도구를 확인하세요.", "disableGPU": "GPU 하드웨어 가속을 사용하지 않도록 설정합니다.", "uploadLogs": "현재의 세션에서 안전한 종점으로 로그 업로드", "maxMemory": "윈도우에 대한 최대 메모리 크기 (단위 MB).", diff --git a/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index d490601f55..79962c1adb 100644 --- a/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "잘못된 확장: package.json이 JSON 파일이 아닙니다.", + "incompatible": "'{0}' 확장은 Code '{1}'과(와) 호환되지 않으므로 설치할 수 없습니다.", "restartCode": "{0}을(를) 다시 설치하기 전에 Code를 다시 시작하세요.", "installingOutdatedExtension": "이 확장의 최신 버전이 이미 설치되어 있습니다. 이 버전을 이전 버전으로 재정의하시겠습니까?", "override": "재정의", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "의존성 설치 중 오류가 발생했습니다. {0}", "MarketPlaceDisabled": "Marketplace를 사용할 수 없습니다.", "removeError": "확장을 제거하는 동안 오류가 발생했습니다. {0}. 다시 시도하기 전에 VS Code를 종료하고 다시 시작하세요.", - "Not Market place extension": "마켓플레이스 확장만 다시 설치할 수 있습니다.", + "Not a Marketplace extension": "마켓플레이스 확장만 다시 설치할 수 있습니다.", "notFoundCompatible": "'{0}'을(를) 설치할 수 없습니다; VS Code '{1}'과 호환되는 버전이 없습니다.", "malicious extension": "문제가 있다고 보고되었으므로 확장을 설치할 수 없습니다.", "notFoundCompatibleDependency": "VS Code의 현재 버전 '{1}'과(와) 호환되는 종속된 확장 '{0}'을(를) 찾을 수 없으므로 설치할 수 없습니다.", "quitCode": "확장을 설치할 수 없습니다. 다시 설치하기 위해 VS Code를 종료하고 다시 시작하십시오.", "exitCode": "확장을 설치할 수 없습니다. 다시 설치하기 전에 VS 코드를 종료한 후 다시 시작하십시오. ", + "renameError": "이름을 {0}에서 {1}(으)로 변경하는 중 알 수 없는 오류 발생", "uninstallDependeciesConfirmation": "'{0}'만 제거할까요, 아니면 종속성도 제거할까요?", - "uninstallOnly": "만", - "uninstallAll": "모두", + "uninstallOnly": "확장만", + "uninstallAll": "모두 제거", "uninstallConfirmation": "'{0}'을(를) 제거할까요?", "ok": "확인", "singleDependentError": "확장 '{0}'을(를) 제거할 수 없습니다. 확장 '{1}'이(가) 이 확장에 종속됩니다.", diff --git a/i18n/kor/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/kor/src/vs/platform/extensions/node/extensionValidator.i18n.json index 3ff3704bf1..6df1453975 100644 --- a/i18n/kor/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/kor/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "`engines.vscode` 값 {0}을(를) 구문 분석할 수 없습니다. ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x 등을 사용하세요.", + "versionSyntax": "`engines.vscode` 값 {0}을(를) 구문 분석할 수 없습니다. ^1.22.0, ^1.22.x 등을 사용하세요.", "versionSpecificity1": "`engines.vscode`({0})에 지정된 버전이 명확하지 않습니다. vscode 버전이 1.0.0 이전이면 최소한 원하는 주 버전과 부 버전을 정의하세요( 예: ^0.10.0, 0.10.x, 0.11.0 등).", "versionSpecificity2": "`engines.vscode`({0})에 지정된 버전이 명확하지 않습니다. vscode 버전이 1.0.0 이후이면 최소한 원하는 주 버전을 정의하세요(예: ^1.10.0, 1.10.x, 1.x.x, 2.x.x 등).", "versionMismatch": "확장이 Code {0}과(와) 호환되지 않습니다. 확장에 {1}이(가) 필요합니다." diff --git a/i18n/kor/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/kor/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index d3be2d79bc..7e64a861b3 100644 --- a/i18n/kor/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/kor/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "{0} 설치가 손상된 것 같습니다. 다시 설치하세요.", "integrity.moreInformation": "추가 정보", - "integrity.dontShowAgain": "다시 표시 안 함", - "integrity.prompt": "{0} 설치가 손상된 것 같습니다. 다시 설치하세요." + "integrity.dontShowAgain": "다시 표시 안 함" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/kor/src/vs/platform/issue/electron-main/issueService.i18n.json index 4bfb0bc61a..ed76b29bfd 100644 --- a/i18n/kor/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/kor/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "문제 보고자" + "issueReporter": "문제 보고자", + "processExplorer": "프로세스 탐색기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/list/browser/listService.i18n.json b/i18n/kor/src/vs/platform/list/browser/listService.i18n.json index 3b27020b27..a36ea94ff8 100644 --- a/i18n/kor/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/kor/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "마우스로 트리와 목록의 항목을 다중 선택에 추가할 때 사용할 한정자입니다(예를 들어 탐색기에서 편집기와 SCM 보기를 여는 경우). `ctrlCmd`는 Windows와 Linux에서 `Control`로 매핑되고 macOS에서 `Command`로 매핑됩니다. '옆에서 열기' 마우스 제스처(지원되는 경우)는 다중 선택 한정자와 충돌하지 않도록 조정됩니다.", "openMode.singleClick": "마우스를 한 번 클릭하여 항목을 엽니다.", "openMode.doubleClick": "마우스를 두 번 클릭하여 항목을 엽니다.", - "openModeModifier": "트리와 목록에서 마우스를 사용하여 항목을 여는 방법을 제어합니다(지원되는 경우). 마우스을 한 번 클릭하여 항목을 열려면 `singleClick` 으로 설정하고 마우스 두 번 클릭을 통해서만 열려면 `doubleClick`으로 설정합니다. 트리에서 하위 항목이 있는 상위 항목의 경우 이 설정은 상위 항목을 한 번 클릭으로 확장할지 두 번 클릭으로 확장할지를 제어합니다. 일부 트리와 목록에서는 이 설정을 적용할 수 없는 경우 무시하도록 선택할 수 있습니다. " + "openModeModifier": "트리와 목록에서 마우스를 사용하여 항목을 여는 방법을 제어합니다(지원되는 경우). 마우스을 한 번 클릭하여 항목을 열려면 `singleClick` 으로 설정하고 마우스 두 번 클릭을 통해서만 열려면 `doubleClick`으로 설정합니다. 트리에서 하위 항목이 있는 상위 항목의 경우 이 설정은 상위 항목을 한 번 클릭으로 확장할지 두 번 클릭으로 확장할지를 제어합니다. 일부 트리와 목록에서는 이 설정을 적용할 수 없는 경우 무시하도록 선택할 수 있습니다. ", + "horizontalScrolling setting": "워크벤치에서 수평 스크롤 지원 여부를 제어 합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/markers/common/markers.i18n.json b/i18n/kor/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..d0a8772dd0 --- /dev/null +++ b/i18n/kor/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "오류", + "sev.warning": "경고", + "sev.info": "정보" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json index f08137dd42..f6ecf213a0 100644 --- a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "위치 표시자 텍스트에 대한 입력 상자 전경색입니다.", "inputValidationInfoBackground": "정보 심각도의 입력 유효성 검사 배경색입니다.", "inputValidationInfoBorder": "정보 심각도의 입력 유효성 검사 테두리 색입니다.", - "inputValidationWarningBackground": "정보 경고의 입력 유효성 검사 배경색입니다.", + "inputValidationWarningBackground": "경고 심각도의 입력 유효성 검사 배경색입니다.", "inputValidationWarningBorder": "경고 심각도의 입력 유효성 검사 테두리 색입니다.", "inputValidationErrorBackground": "오류 심각도의 입력 유효성 검사 배경색입니다.", "inputValidationErrorBorder": "오류 심각도의 입력 유효성 검사 테두리 색입니다.", @@ -71,10 +71,10 @@ "editorSelectionHighlightBorder": "선택 영역과 동일한 콘텐츠가 있는 영역의 테두리 색입니다.", "editorFindMatch": "현재 검색 일치 항목의 색입니다.", "findMatchHighlight": "기타 일치하는 검색의 색상. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", - "findRangeHighlight": "범위 제한 검색의 색상. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", + "findRangeHighlight": "검색을 제한하는 범위의 색입니다. 이 색은 기본 장식을 가리지 않도록 불투명하지 않아야 합니다.", "editorFindMatchBorder": "현재 검색과 일치하는 테두리 색입니다.", "findMatchHighlightBorder": "다른 검색과 일치하는 테두리 색입니다.", - "findRangeHighlightBorder": "범위 제한 검색의 테두리 색. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", + "findRangeHighlightBorder": "검색을 제한하는 범위의 테두리 색입니다. 이 색은 기본 장식을 가리지 않도록 불투명하지 않아야 합니다.", "hoverHighlight": "호버가 표시된 단어 아래를 강조 표시합니다. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", "hoverBackground": "편집기 호버의 배경색.", "hoverBorder": "편집기 호버의 테두리 색입니다.", @@ -88,11 +88,11 @@ "mergeIncomingHeaderBackground": "인라인 병합 충돌에서 수신 헤더 배경입니다. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", "mergeIncomingContentBackground": "인라인 병합 충돌에서 수신 콘텐츠 배경입니다. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", "mergeCommonHeaderBackground": "인라인 병합 충돌의 공통 과거 헤더 배경입니다. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", - "mergeCommonContentBackground": "인라인 병합 충돌의 공통 과거 콘텐츠 배경입니다. 색상은 밑의 꾸밈을 가리지 않도록 반드시 불투명이 아니어야 합니다.", + "mergeCommonContentBackground": "인라인 병합 충돌의 공용 상위 콘텐츠 배경입니다. 이 색은 기본 장식을 가리지 않도록 불투명하지 않아야 합니다.", "mergeBorder": "인라인 병합 충돌에서 헤더 및 스플리터의 테두리 색입니다.", "overviewRulerCurrentContentForeground": "인라인 병합 충돌에서 현재 개요 눈금 전경색입니다.", "overviewRulerIncomingContentForeground": "인라인 병합 충돌에서 수신 개요 눈금 전경색입니다.", "overviewRulerCommonContentForeground": "인라인 병합 충돌에서 공통 과거 개요 눈금 전경색입니다.", - "overviewRulerFindMatchForeground": "찾기 일치 항목의 개요 눈금자 마커 색입니다.", - "overviewRulerSelectionHighlightForeground": "선택 영역 강조 표시의 개요 눈금자 마커 색입니다." + "overviewRulerFindMatchForeground": "일치하는 항목 찾기의 개요 눈금자 표식 색입니다. 이 색은 불투명해야만 내부 장식을 가리지 않습니다.", + "overviewRulerSelectionHighlightForeground": "선택 영역 강조의 개요 눈금자 표식 색입니다. 이 색은 불투명해야만 내부 장식을 가리지 않습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/kor/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..06c3296dbe --- /dev/null +++ b/i18n/kor/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "{0} 확장에서 다음 URL을 열도록 허용하시겠습니까?" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/kor/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..a294bc2701 --- /dev/null +++ b/i18n/kor/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "'뷰' 기여 지점을 사용하여 뷰가 기여될 수 있는 컨테이너를 식별하는 데 사용되는 고유한 ID", + "vscode.extension.contributes.views.containers.title": "컨테이너를 렌더링하는 데 사용되는 사람이 읽을 수 있는 문자열", + "vscode.extension.contributes.views.containers.icon": "컨테이너 아이콘의 경로입니다. 아이콘은 50x40 사각형의 가운데에 있는 24x24 크기이며 채우기 색은 'rgb(215, 218, 224)' 또는 '#d7dae0'입니다. 아이콘의 이미지 파일 형식은 무엇이든 상관없지만 SVG를 사용하는 것이 좋습니다.", + "vscode.extension.contributes.viewsContainers": "뷰 컨테이너를 편집기에 기여합니다.", + "views.container.activitybar": "뷰 컨테이너를 작업 막대에 기여", + "test": "테스트", + "proposed": "'viewsContainers' 기여는 dev 외부에서 실행하거나 명령줄 스위치 --enable-proposed-api {0}을(를) 사용하여 실행할 때만 사용할 수 있습니다.", + "requirearray": "뷰 컨테이너는 배열이어야 합니다.", + "requireidstring": "`{0}` 속성은 필수이며 `string` 형식이어야 합니다. 영숫자, '_', '-'만 사용할 수 있습니다.", + "requirestring": "속성 `{0}`은(는) 필수이며 `string` 형식이어야 합니다.", + "showViewlet": "{0} 표시", + "view": "보기" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/kor/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index e2b33083f3..a641df0c18 100644 --- a/i18n/kor/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/kor/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "사용자가 읽을 수 있는 뷰 이름입니다. 표시됩니다.", "vscode.extension.contributes.view.when": "이 보기를 표시하기 위해 true여야 하는 조건입니다.", "vscode.extension.contributes.views": "뷰를 에디터에 적용합니다.", - "views.explorer": "탐색기 뷰", - "views.debug": "디버그 보기", - "locationId.invalid": "`{0}`은(는) 유효한 뷰 위치가 아닙니다.", + "views.explorer": "뷰를 작업 막대의 탐색기 컨테이너에 기여합니다.", + "views.debug": "뷰를 작업 막대의 디버그 컨테이너에 기여합니다.", + "views.scm": "뷰를 작업 막대의 SCM 컨테이너에 적용합니다.", + "views.test": "뷰를 작업 막대의 테스트 컨테이너에 적용합니다.", + "views.contributed": "뷰를 기여된 뷰 컨테이너에 기여합니다.", + "ViewContainerDoesnotExist": "뷰 컨테이너 '{0}'이(가) 없으므로 이 컨테이너에 등록된 모든 뷰가 '탐색기'에 추가됩니다.", "duplicateView1": "위치 '{1}'에서 동일한 ID '{0}'(으)로된 여러 개의 보기를 등록할 수 없습니다.", "duplicateView2": "ID `{0}`이(가) 포함된 뷰가 위치 `{1}`에 이미 등록되어 있습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 2ea4653af7..f25d7a24ad 100644 --- a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "저장 시 {0}ms 후에 서식 지정이 중단됨", + "codeActionsOnSave.didTimeout": "{0}밀리초 후 codeActionsOnSave 중단됨", + "timeout.onWillSave": "1750ms 후에 onWillSaveTextDocument-event가 중단됨", "saveParticipants": "실행중인 저장 관계자..." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 0ee84ee0a7..b55013c7df 100644 --- a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "webview 편집기" + "errorMessage": "뷰를 복원하는 중 오류 발생:{0}" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/kor/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..b3d4a23551 --- /dev/null +++ b/i18n/kor/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (확장)" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index a10a179615..d182289af8 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "다음 그룹에 포커스", "openToSide": "측면에서 열기", "closeEditor": "편집기 닫기", + "closeOneEditor": "닫기", "revertAndCloseActiveEditor": "편집기 되돌리기 및 닫기", "closeEditorsToTheLeft": "왼쪽에 있는 편집기 닫기", "closeAllEditors": "모든 편집기 닫기", diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index a634e19a3f..567eb21435 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "화면 읽기 프로그램을 사용하지 않는 경우 `editor.accessibilitySupport` 설정을 \"off\"로 변경하세요.", "disableTabMode": "접근성 모드 사용 안 함", "gotoLine": "줄 이동", - "indentation": "들여쓰기", + "selectIndentation": "들여쓰기 선택", "selectEncoding": "인코딩 선택", "selectEOL": "줄 시퀀스의 끝 선택", "selectLanguageMode": "언어 모드 선택", diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index cbcc1cae64..59854c824e 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0}MB", "sizeGB": "{0}GB", "sizeTB": "{0}TB", - "largeImageError": "이미지의 파일 크기가 너무 커서(>1MB) 편집기에서 표시할 수 없습니다. ", + "largeImageError": "이미지가 너무 커서 편집기에 표시할 수 없습니다({0}). ", "resourceOpenExternalButton": " 외부 프로그램으로 이미지를 열까요?", - "nativeBinaryError": "파일이 이진이거나 매우 크거나 지원되지 않는 텍스트 인코딩을 사용하기 때문에 편집기에서 표시되지 않습니다.", + "nativeFileTooLargeError": "파일이 너무 커서 편집기에서 표시되지 않습니다({0}).", + "nativeBinaryError": "파일이 이진이거나 지원되지 않는 텍스트 인코딩을 사용하기 때문에 편집기에서 표시되지 않습니다.", + "openAsText": "그래도 여시겠습니까?", "zoom.action.fit.label": "전체 이미지", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 3d6e62e089..776803781b 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "닫기", "araLabelEditorActions": "편집기 작업" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 73d9c1b4ff..68b015e845 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "새 알림 없음", "notifications": "알림", "notificationsToolbar": "알림 센터 작업", "notificationsList": "알림 목록" diff --git a/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..bcd2d0d145 --- /dev/null +++ b/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0}(확인하려면 'Enter' 키를 누르고, 취소하려면 'Escape' 키를 누름)", + "inputModeEntry": "입력을 확인하려면 'Enter' 키를 누르고, 취소하려면 'Esc' 키를 누르세요.", + "quickInput.countSelected": "{0} 선택됨", + "ok": "확인" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..4e4c6e6f12 --- /dev/null +++ b/i18n/kor/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "결과의 범위를 축소하려면 입력하세요." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json index 6bdca31191..895c1591ab 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "최근 항목 열기...", "quickOpenRecent": "빠른 최근 항목 열기...", "reportIssueInEnglish": "문제 보고", + "openProcessExplorer": "프로세스 탐색기 열기", "reportPerformanceIssue": "성능 문제 보고", "keybindingsReference": "바로 가기 키 참조", "openDocumentationUrl": "설명서", diff --git a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json index 8ee5f425ad..7632a07a26 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "창", "window.openFilesInNewWindow.on": "파일이 새 창에서 열립니다.", "window.openFilesInNewWindow.off": "파일이 파일의 폴더가 열려 있는 창 또는 마지막 활성 창에서 열립니다.", - "window.openFilesInNewWindow.default": "Dock 또는 Finder(macOS 전용)를 통해 파일을 연 경우를 제외하고 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.", - "openFilesInNewWindow": "파일을 새 창에서 열지 여부를 제어합니다.\n- default: Dock 또는 Finder(macOS 전용)를 통해 파일을 연 경우를 제외하고, 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.\n- on: 파일이 새 창에서 열립니다.\n- off: 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.\n이 설정이 무시되는 경우도 있을 수 있습니다(예: -new-window 또는 -reuse-window 명령줄 옵션을 사용할 경우).", + "window.openFilesInNewWindow.defaultMac": "Dock 또는 Finder를 통해 파일을 연 경우를 제외하고 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.", + "window.openFilesInNewWindow.default": "응용 프로그램 내에서 선택(예: 파일 메뉴를 통해)하는 경우를 제외하고 파일이 새 창에서 열립니다. ", + "openFilesInNewWindowMac": "파일을 새 창에서 열지 여부를 제어합니다.\n- default: Dock 또는 Finder를 통해 파일을 연 경우를 제외하고, 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.\n- on: 파일이 새 창에서 열립니다.\n- off: 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.\n이 설정이 무시되는 경우도 있을 수 있습니다(예: -new-window 또는 reuse-window 명령줄 옵션을 사용할 경우).", + "openFilesInNewWindow": "파일을 새 창에서 열지 여부를 제어합니다.\n- default: 응용 프로그램 내에서 [파일] 메뉴 등을 통해 파일을 선택하는 경우를 제외하고, 파일이 새 창에서 열립니다.\n- on: 파일이 새 창에서 열립니다.\n- off: 파일이 파일의 폴더가 열린 창 또는 마지막 활성 창에서 열립니다.\n이 설정이 무시되는 경우도 있을 수 있습니다(예: -new-window 또는 reuse-window 명령줄 옵션을 사용할 경우).", "window.openFoldersInNewWindow.on": "폴더가 새 창에서 열립니다.", "window.openFoldersInNewWindow.off": "폴더가 마지막 활성 창을 바꿉니다.", "window.openFoldersInNewWindow.default": "폴더를 응용 프로그램 내에서 선택(예: 파일 메뉴를 통해)하는 경우를 제외하고 폴더가 새 창에서 열립니다.", "openFoldersInNewWindow": "폴더를 새 창에서 열지, 마지막 활성 창과 바꿀지를 제어합니다.\n- default: 응용 프로그램 내에서 [파일] 메뉴 등을 통해 폴더를 선택하는 경우를 제외하고, 폴더는 새 창에서 열립니다.\n- on: 폴더가 새 창에서 열립니다.\n- off: 폴더가 마지막 활성 창을 대체합니다\n이 설정이 무시되는 경우도 있을 수 있습니다(예: -new-window 또는 -reuse-window 명령줄 옵션을 사용할 경우).", + "window.openWithoutArgumentsInNewWindow.on": "새로운 빈 창 열기", + "window.openWithoutArgumentsInNewWindow.off": "실행 중인 마지막 활성 인스턴스에 포커스", + "openWithoutArgumentsInNewWindow": "인수 없이 두 번째 인스턴스를 시작할 때 새로운 빈 창을 열지 또는 실행 중인 마지막 인스턴스에 포커스가 생길지 여부를 제어합니다.\n- on: 새로운 빈 창을 엽니다.\n- off: 실행 중인 마지막 활성 인스턴스에 포커스가 생깁니다.\n이 설정이 무시되는 경우도 있을 수 있습니다(예: -new-window 또는 -reuse-window 명령줄 옵션을 사용할 경우).", "window.reopenFolders.all": "모든 창을 다시 엽니다.", "window.reopenFolders.folders": "모든 폴더를 다시 엽니다. 빈 작업 영역은 복원되지 않습니다.", "window.reopenFolders.one": "마지막 활성 창을 다시 엽니다.", @@ -58,7 +63,7 @@ "restoreWindows": "다시 시작한 이후에 창을 다시 여는 방법을 설정합니다. 'none'을 선택하면 항상 빈 작업 영역으로 시작하고 'one'을 선택하면 마지막으로 작업한 창이 다시 열리고 'folders'를 선택하면 열었던 폴더가 포함된 모든 창이 다시 열리며 'all'을 선택하면 지난 세션의 모든 창이 다시 열립니다.", "restoreFullscreen": "창이 전체 화면 모드에서 종료된 경우 창을 전체 화면 모드로 복원할지 여부를 제어합니다.", "zoomLevel": "창의 확대/축소 수준을 조정합니다. 원래 크기는 0이고 각 상한 증분(예: 1) 또는 하한 증분(예: -1)은 20% 더 크거나 더 작게 확대/축소하는 것을 나타냅니다. 10진수를 입력하여 확대/축소 수준을 세부적으로 조정할 수도 있습니다.", - "title": "활성 편집기를 기반으로 창 제목을 제어합니다. 변수는 컨텍스트를 기반으로 대체됩니다.\n${activeEditorShort}: 파일 이름(예: myFile.txt)\n${activeEditorMedium}: 작업 영역 폴더에 상대적인 파일 경로(예: myFolder/myFile.txt)\n${activeEditorLong}: 파일 전체 경로(예: /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 파일이 포함된 작업 영역 폴더 이름(예: myFolder)\n${folderPath}: 파일이 포함된 작업 영역 폴더의 파일 경로(예: /Users/Development/myFolder)\n${rootName}: 작업 영역 이름(예: myFolder 또는 myWorkspace)\n${rootPath}: 작업 영역 파일 경로(예: /Users/Development/myWorkspace)\n${appName}: 예: VS Code\n${dirty}: 활성 편집기가 더티인 경우 더티 표시기\n${separator}: 값이 있는 변수로 둘러싸인 경우에만 표시되는 조건부 구분 기호(\" - \")", + "title": "활성 편집기를 기반으로 창 제목을 제어합니다. 변수는 컨텍스트를 기준으로 대체됩니다.\n${activeEditorShort}: 파일 이름(예: myFile.txt)\n${activeEditorMedium}: 작업 영역 폴더를 기준으로 하는 파일에 대한 상대 경로(예: myFolder/myFile.txt)\n${activeEditorLong}: 파일의 전체 경로(예: /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: 파일이 포함된 작업 영역 폴더의 이름(예: myFolder)\n${folderPath}: 파일이 포함된 작업 영역 폴더의 파일 경로(예: /Users/Development/myFolder)\n${rootName}: 작업 영역의 이름(예: myFolder or myWorkspace)\n${rootPath}: 작업 영역의 파일 경로(예: /Users/Development/myWorkspace)\n${appName}: 예: VS Code\n${dirty}: 활성 편집기가 더티인 경우 더티 표시기\n${separator}: 값 또는 정적 텍스트가 있는 변수로 둘러싸인 경우에만 표시되는 조건부 구분 기호(\" - \")", "window.newWindowDimensions.default": "화면 가운데에서 새 창을 엽니다.", "window.newWindowDimensions.inherit": "마지막 활성 창과 동일한 크기로 새 창을 엽니다.", "window.newWindowDimensions.maximized": "최대화된 새 창을 엽니다.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "사용하도록 설정한 경우 Windows에서 고대비 테마를 사용 중이면 고대비 테마로 자동으로 변경되고 Windows 고대비 테마를 해제하면 어두운 테마로 변경됩니다.", "titleBarStyle": "창 제목 표시줄의 모양을 조정합니다. 변경 내용을 적용하려면 전체 다시 시작해야 합니다.", "window.nativeTabs": "macOS Sierra 창 탭을 사용하도록 설정합니다. 변경\n 내용을 적용하려면 전체 다시 시작해야 하고, 기본 탭에서\n 사용자 지정 제목 표시줄 스타일(구성된 경우)을 비활성화합니다.", + "window.smoothScrollingWorkaround": "최소화된 VS Code 창을 복원한 후 더 이상 원활하게 스크롤되지 않으면 이 해결 방법을 사용하도록 설정하세요. 이 해결 방법은 Microsoft의 Surface 장치와 같이 정밀 트랙 패드가 장착된 장치에서 스크롤이 지연되기 시작하는 문제(https://github.com/Microsoft/vscode/issues/13612)를 해결합니다. 이 해결 방법을 사용하도록 설정하면 최소화된 상태에서 창을 복원한 후 약간의 레이아웃 깜박거림이 발생할 수 있지만 그 외의 해는 없습니다.", + "window.clickThroughInactive": "사용하도록 설정한 경우 비활성 창을 클릭하면 창도 활성화되고 클릭 가능한 경우 마우스 아래의 요소도 트리거됩니다. 사용하지 않도록 설정한 경우 비활성 창에서 아무곳이나 클릭하면 창만 활성화되며 요소는 또 한번 클릭해야 합니다.", "zenModeConfigurationTitle": "Zen 모드", "zenMode.fullScreen": "Zen 모드를 켜면 워크벤치도 전체 화면 모드로 전환되는지 여부를 제어합니다.", "zenMode.centerLayout": "Zen 모드를 켜면 레이아웃도 가운데로 맞춰지는지 여부를 제어합니다.", diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index ae10df1c03..0495fb536e 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "중단점 편집...", + "logPoint": "Logpoint", + "breakpoint": "중단점", + "editBreakpoint": "{0} 편집...", + "removeBreakpoint": "{0} 제거", "functionBreakpointsNotSupported": "이 디버그 형식은 함수 중단점을 지원하지 않습니다.", "functionBreakpointPlaceholder": "중단할 함수", "functionBreakPointInputAriaLabel": "함수 중단점 입력", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "확인되지 않은 중단점", "functionBreakpointUnsupported": "이 디버그 형식은 함수 중단점을 지원하지 않습니다.", "breakpointDirtydHover": "확인되지 않은 중단점입니다. 파일이 수정되었습니다. 디버그 세션을 다시 시작하세요.", + "logBreakpointUnsupported": "이 디버그 형식에서 지원되지 않는 logpoint", "conditionalBreakpointUnsupported": "이 디버그 형식에서 지원되지 않는 조건부 중단점", "hitBreakpointUnsupported": "이 디버그 형식은 조건부 중단점 적중을 지원하지 않습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index e0076ee2bd..a22249bbe4 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "연결 끊기", "continueDebug": "계속", "pauseDebug": "일시 중지", + "terminateThread": "스레드 종료", "restartFrame": "프레임 다시 시작", "removeBreakpoint": "중단점 제거", "removeAllBreakpoints": "모든 중단점 제거", - "enableBreakpoint": "중단점 사용", - "disableBreakpoint": "중단점 사용 안 함", "enableAllBreakpoints": "모든 중단점 설정", "disableAllBreakpoints": "모든 중단점 해제", "activateBreakpoints": "중단점 활성화", "deactivateBreakpoints": "중단점 비활성화", "reapplyAllBreakpoints": "모든 중단점 다시 적용", "addFunctionBreakpoint": "함수 중단점 추가", - "addConditionalBreakpoint": "조건부 중단점 추가...", - "editConditionalBreakpoint": "중단점 편집...", "setValue": "값 설정", "addWatchExpression": "식 추가", "editWatchExpression": "식 편집", diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index f760a5d2b8..9b0460519f 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "디버그: 중단점 설정/해제", "conditionalBreakpointEditorAction": "디버그: 조건부 중단점 추가...", + "logPointEditorAction": "디버그: Logpoint 추가...", "runToCursor": "커서까지 실행", "debugEvaluate": "디버그: 평가", "debugAddToWatch": "디버그: 조사식에 추가", diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..ff73e8551e --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "중단점이 적중될 때 기록할 메시지입니다. {} 내의 식은 보간됩니다. 수락하려면 'Enter' 키를 누르고 취소하려면 'esc' 키를 누르세요.", + "breakpointWidgetHitCountPlaceholder": "적중 횟수 조건이 충족될 경우 중단합니다. 적용하려면 'Enter' 키를 누르고 취소하려면 'Esc' 키를 누릅니다.", + "breakpointWidgetExpressionPlaceholder": "식이 true로 계산될 경우 중단합니다. 적용하려면 'Enter' 키를 누르고 취소하려면 'Esc' 키를 누릅니다.", + "expression": "식", + "hitCount": "적중 횟수", + "logMessage": "로그 메시지" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 06646e4831..cae66dae76 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "고유한 구성 이름을 사용하세요.", "app.launch.json.compound.folder": "복합형 항목이 있는 폴더의 이름입니다.", "app.launch.json.compounds.configurations": "이 복합의 일부로 시작되는 구성의 이름입니다.", - "debugNoType": "디버그 어댑터 '형식'은 생략할 수 없으며 '문자열' 형식이어야 합니다.", + "debugNoType": "디버거 '형식'은 생략할 수 없으며 '문자열' 형식이어야 합니다.", "selectDebug": "환경 선택", "DebugConfig.failed": "'.vscode' 폴더({0}) 내에 'launch.json' 파일을 만들 수 없습니다.", "workspace": "작업 영역", diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index c75ee2d9e7..e34b8e0458 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Logpoint", + "breakpoint": "중단점", + "removeBreakpoint": "{0} 제거", + "editBreakpoint": "{0} 편집...", + "disableBreakpoint": "{0} 사용 안 함", + "enableBreakpoint": "{0} 사용", "removeBreakpoints": "중단점 제거", "removeBreakpointOnColumn": "{0} 열에서 중단점 제거", "removeLineBreakpoint": "줄 중단점 제거", @@ -18,5 +24,13 @@ "enableBreakpoints": "{0} 열에서 중단점 사용", "enableBreakpointOnLine": "줄 중단점 사용", "addBreakpoint": "중단점 추가", + "addConditionalBreakpoint": "조건부 중단점 추가...", + "addLogPoint": "Logpoint 추가...", + "breakpointHasCondition": "이 {0}에는 제거 시 손실되는 {1}이(가) 있습니다. 대신 {0}을(를) 사용하지 않도록 설정하세요.", + "message": "메시지", + "condition": "조건", + "removeLogPoint": "{0} 제거", + "disableLogPoint": "{0} 사용 안 함", + "cancel": "취소", "addConfiguration": "구성 추가..." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index e952e7b200..229010aa64 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "오류 표시", "noFolderWorkspaceDebugError": "활성 파일은 디버그할 수 없습니다. 이 파일이 디스크에 저장되어 있고 해당 파일 형식에 대한 디버그 확장이 설치되어 있는지 확인하세요.", "cancel": "취소", - "DebugTaskNotFound": "preLaunchTask '{0}'을(를) 찾을 수 없습니다.", - "taskNotTracked": "PreLaunchTask '{0}'을(를) 추적할 수 없습니다." + "DebugTaskNotFound": "작업 '{0}' 을(를) 찾을 수 없습니다.", + "taskNotTracked": "작업 '{0}' 을(를) 추적할 수 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index 68e2452b64..e6d36df377 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "추가 정보", - "unableToLaunchDebugAdapter": "'{0}'에서 디버그 어댑터를 시작할 수 없습니다.", - "unableToLaunchDebugAdapterNoArgs": "디버그 어댑터를 시작할 수 없습니다.", - "stoppingDebugAdapter": "{0}. 디버그 어댑터를 중지합니다.", "debugAdapterCrash": "디버그 어댑터 프로세스가 예기치 않게 종료되었습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index bc208cb181..94a5aede84 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "디버그 어댑터 실행 파일 '{0}'이(가) 없습니다.", "debugAdapterCannotDetermineExecutable": "디버그 어댑터 '{0}'에 대한 실행 파일을 확인할 수 없습니다.", - "launch.config.comment1": "IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.", - "launch.config.comment2": "기존 특성에 대한 설명을 보려면 가리킵니다.", - "launch.config.comment3": "자세한 내용을 보려면 {0}을(를) 방문하세요.", - "debugType": "구성의 형식입니다.", - "debugTypeNotRecognised": "디버그 형식이 인식되지 않습니다. 해당하는 디버그 확장을 설치하고 사용하도록 설정했는지 확인하세요.", - "node2NotSupported": "\"node2\"는 더 이상 지원되지 않습니다. 대신 \"node\"를 사용하고 \"protocol\" 특성을 \"inspector\"로 설정하세요.", - "debugName": "구성 이름이며, 구성 시작 드롭다운 메뉴에 표시됩니다.", - "debugRequest": "구성 형식을 요청합니다. \"시작\" 또는 \"연결\"일 수 있습니다.", - "debugServer": "디버그 확장 배포 전용입니다. 포트가 지정된 경우 VS Code에서는 서버 모드로 실행하는 디버그 어댑터에 연결을 시도합니다.", - "debugPrelaunchTask": "디버그 세션이 시작되기 이전에 실행할 작업입니다.", - "debugWindowsConfiguration": "Windows 특정 시작 구성 특성입니다.", - "debugOSXConfiguration": "OS X 특정 시작 구성 특성입니다.", - "debugLinuxConfiguration": "Linux 특정 시작 구성 특성입니다.", - "deprecatedVariables": "'env.', 'config.' 및 'command.'는 사용되지 않습니다. 대신 'env:', 'config:' 및 'command:'를 사용하세요." + "unableToLaunchDebugAdapter": "'{0}'에서 디버그 어댑터를 시작할 수 없습니다.", + "unableToLaunchDebugAdapterNoArgs": "디버그 어댑터를 시작할 수 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..ded2c6ad58 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.", + "launch.config.comment2": "기존 특성에 대한 설명을 보려면 가리킵니다.", + "launch.config.comment3": "자세한 내용을 보려면 {0}을(를) 방문하세요.", + "debugType": "구성의 형식입니다.", + "debugTypeNotRecognised": "디버그 형식이 인식되지 않습니다. 해당하는 디버그 확장을 설치하고 사용하도록 설정했는지 확인하세요.", + "node2NotSupported": "\"node2\"는 더 이상 지원되지 않습니다. 대신 \"node\"를 사용하고 \"protocol\" 특성을 \"inspector\"로 설정하세요.", + "debugName": "구성 이름이며, 구성 시작 드롭다운 메뉴에 표시됩니다.", + "debugRequest": "구성 형식을 요청합니다. \"시작\" 또는 \"연결\"일 수 있습니다.", + "debugServer": "디버그 확장 배포 전용입니다. 포트가 지정된 경우 VS Code에서는 서버 모드로 실행하는 디버그 어댑터에 연결을 시도합니다.", + "debugPrelaunchTask": "디버그 세션이 시작되기 이전에 실행할 작업입니다.", + "debugPostDebugTask": "디버그 세션 종료 후 실행할 작업입니다.", + "debugWindowsConfiguration": "Windows 특정 시작 구성 특성입니다.", + "debugOSXConfiguration": "OS X 특정 시작 구성 특성입니다.", + "debugLinuxConfiguration": "Linux 특정 시작 구성 특성입니다.", + "deprecatedVariables": "'env.', 'config.' 및 'command.'는 사용되지 않습니다. 대신 'env:', 'config:' 및 'command:'를 사용하세요." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..850e1c758d --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code 콘솔", + "mac.terminal.script.failed": "스크립트 '{0}'이(가) 실패했습니다(종료 코드: {1}).", + "mac.terminal.type.not.supported": "'{0}'이(가) 지원되지 않습니다.", + "press.any.key": "계속하려면 아무 키나 누르세요.", + "linux.term.failed": "'{0}'에서 실패했습니다(종료 코드: {1})." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 7acb89b217..5241bb3fb6 100644 --- a/i18n/kor/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "권장 확장 구성(작업 영역 폴더)", "malicious tooltip": "이 확장은 문제가 있다고 보고되었습니다.", "malicious": "악성", + "disabled": "사용 안 함", + "disabled globally": "사용 안 함", + "disabled workspace": "이 작업 영역에 대해 사용 안 함", "disableAll": "설치된 모든 확장 사용 안 함", "disableAllWorkspace": "이 작업 영역에 대해 설치된 모든 확장 사용 안 함", "enableAll": "모든 확장 사용", diff --git a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..ac0d427930 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "확장 이름", + "extension id": "확장 ID", + "preview": "미리 보기", + "builtin": "기본 제공", + "publisher": "게시자 이름", + "install count": "설치 수", + "rating": "등급", + "repository": "리포지토리", + "license": "라이선스", + "details": "세부 정보", + "contributions": "기여", + "changelog": "변경 로그", + "dependencies": "종속성", + "noReadme": "사용 가능한 추가 정보가 없습니다.", + "noChangelog": "CHANGELOG를 사용할 수 없습니다.", + "noContributions": "참여 없음", + "noDependencies": "종속성 없음", + "settings": "설정({0})", + "setting name": "이름", + "description": "설명", + "default": "기본값", + "debuggers": "디버거({0})", + "debugger name": "이름", + "debugger type": "유형", + "views": "뷰({0})", + "view id": "ID", + "view name": "이름", + "view location": "위치", + "localizations": "지역화({0})", + "localizations language id": "언어 ID", + "localizations language name": "언어 이름", + "localizations localized language name": "언어 이름(지역화됨)", + "colorThemes": "색 테마({0})", + "iconThemes": "아이콘 테마({0})", + "colors": "색({0})", + "colorId": "ID", + "defaultDark": "어둡게 기본값", + "defaultLight": "밝게 기본값", + "defaultHC": "고대비 기본값", + "JSON Validation": "JSON 유효성 검사({0})", + "fileMatch": "파일 일치", + "schema": "스키마", + "commands": "명령({0})", + "command name": "이름", + "keyboard shortcuts": "바로 가기 키(&&K)", + "menuContexts": "메뉴 컨텍스트", + "languages": "언어({0})", + "language id": "ID", + "language name": "이름", + "file extensions": "파일 확장명", + "grammar": "문법", + "snippets": "코드 조각" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index f7178fda43..68ce51ca22 100644 --- a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "이 확장은 현재 작업 영역 사용자가 권장합니다.", "reallyRecommended2": "이 파일 형식에 대해 '{0}' 확장이 권장됩니다.", "reallyRecommendedExtensionPack": "이 파일 형식에 대해 '{0}' 확장 팩이 권장됩니다.", - "showRecommendations": "권장 사항 표시", "install": "설치", + "showRecommendations": "권장 사항 표시", "showLanguageExtensions": "Marketplace에 '.{0}' 파일이 지원되는 확장이 있습니다.", "workspaceRecommended": "이 작업 영역에 확장 권장 사항이 있습니다.", "installAll": "모두 설치", diff --git a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index ba1919114d..f3efb6e431 100644 --- a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "키 바인딩 간 충돌을 피하기 위해 다른 키 맵({0})을 사용하지 않도록 설정할까요?", "yes": "예", - "no": "아니요", - "betterMergeDisabled": "Better Merge 확장이 이제 빌드되었습니다. 설치된 확장은 사용하지 않도록 설정되었으며 제거할 수 있습니다.", - "uninstall": "제거" + "no": "아니요" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index d1db8393ee..018f63d5c0 100644 --- a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "권장", "otherRecommendedExtensions": "기타 권장 사항", "workspaceRecommendedExtensions": "작업 영역 권장 사항", - "builtInExtensions": "기본 제공", + "builtInExtensions": "기능", + "builtInThemesExtensions": "테마", + "builtInBasicsExtensions": "프로그래밍 언어", "searchExtensions": "마켓플레이스에서 확장 검색", "sort by installs": "정렬 기준: 설치 수", "sort by rating": "정렬 기준: 등급", diff --git a/i18n/kor/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/kor/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 2684761bca..49f52553d2 100644 --- a/i18n/kor/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "텍스트 파일 편집기", "createFile": "파일 만들기", + "relaunchWithIncreasedMemoryLimit": "{0}MB로 다시 시작", + "configureMemoryLimit": "메모리 제한 구성", "fileEditorWithInputAriaLabel": "{0}. 텍스트 파일 편집기입니다.", "fileEditorAriaLabel": "텍스트 파일 편집기입니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 145445d648..0d5d6c7188 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "복사", "pasteFile": "붙여넣기", "retry": "다시 시도", + "renameWhenSourcePathIsParentOfTargetError": "'새 폴더' 또는 '새 파일' 명령을 사용하여 기존 폴더에 자식을 추가하세요.", "newUntitledFile": "제목이 없는 새 파일", "createNewFile": "새 파일", "createNewFolder": "새 폴더", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "{0}개 파일에 저장되지 않은 변경 내용이 있는 폴더를 삭제하려고 합니다. 계속하시겠습니까?", "dirtyMessageFileDelete": "저장되지 않은 변경 내용이 있는 파일을 삭제하려고 합니다. 계속하시겠습니까?", "dirtyWarning": "변경 내용을 저장하지 않은 경우 변경 내용이 손실됩니다.", - "confirmMoveTrashMessageMultiple": "다음 {0}개 파일을 삭제하시겠습니까?", - "confirmMoveTrashMessageFolder": "'{0}'과(와) 해당 내용을 삭제할까요?", - "confirmMoveTrashMessageFile": "'{0}'을(를) 삭제할까요?", "undoBin": "휴지통에서 복원할 수 있습니다.", "undoTrash": "휴지통에서 복원할 수 있습니다.", "doNotAskAgain": "이 메시지를 다시 표시 안 함", + "irreversible": "이 작업은 취소할 수 없습니다.", + "binFailed": "휴지통을 사용하여 삭제하지 못했습니다. 대신 영구히 삭제하시겠습니까?", + "trashFailed": "휴지통을 사용하여 삭제하지 못했습니다. 대신 영구히 삭제하시겠습니까?", + "deletePermanentlyButtonLabel": "영구 삭제 (&&D)", + "retryButtonLabel": "다시 시도 (&&R)", + "confirmMoveTrashMessageFilesAndDirectories": "다음 {0}개 파일/디렉터리 및 해당 내용을 삭제하시겠습니까?", + "confirmMoveTrashMessageMultipleDirectories": "다음 {0}개 디렉터리 및 해당 내용을 삭제하시겠습니까?", + "confirmMoveTrashMessageMultiple": "다음 {0}개 파일을 삭제하시겠습니까?", + "confirmMoveTrashMessageFolder": "'{0}'과(와) 해당 내용을 삭제할까요?", + "confirmMoveTrashMessageFile": "'{0}'을(를) 삭제할까요?", + "confirmDeleteMessageFilesAndDirectories": "다음 {0}개 파일/디렉터리 및 해당 내용을 영구히 삭제하시겠습니까?", + "confirmDeleteMessageMultipleDirectories": "다음 {0}개 디렉터리 및 해당 내용을 영구히 삭제하시겠습니까?", "confirmDeleteMessageMultiple": "다음 {0}개 파일을 영구히 삭제하시겠습니까?", "confirmDeleteMessageFolder": "'{0}'과(와) 해당 내용을 영구히 삭제할까요?", "confirmDeleteMessageFile": "'{0}'을(를) 영구히 삭제할까요?", - "irreversible": "이 작업은 취소할 수 없습니다.", - "cancel": "취소", - "permDelete": "영구히 삭제", - "importFiles": "파일 가져오기", + "addFiles": "파일 추가", "confirmOverwrite": "이름이 같은 파일 또는 폴더가 대상 폴더에 이미 있습니다. 덮어쓸까요?", "replaceButtonLabel": "바꾸기(&&R)", "fileIsAncestor": "붙여 넣을 파일이 대상 폴더의 상위 항목입니다.", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "먼저 파일 한 개를 새 창에서 엽니다.", "copyPath": "경로 복사", "emptyFileNameError": "파일 또는 폴더 이름을 입력해야 합니다.", + "fileNameStartsWithSlashError": "파일 또는 폴더 이름은 슬래시로 시작할 수 없습니다.", "fileNameExistsError": "파일 또는 폴더 **{0}**이(가) 이 위치에 이미 있습니다. 다른 이름을 선택하세요.", + "fileUsedAsFolderError": "**{0}**은(는) 파일이며 하위 항목이 있을 수 없습니다.", "invalidFileNameError": "**{0}**(이)라는 이름은 파일 또는 폴더 이름으로 올바르지 않습니다. 다른 이름을 선택하세요.", "filePathTooLongError": "**{0}**(이)라는 이름을 사용하면 경로가 너무 길어집니다. 짧은 이름을 선택하세요.", "compareWithClipboard": "클립보드와 활성 파일 비교", diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 0a41bfb9e2..946d93993d 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "저장하지 않은 파일을 세션 간에 기억하여, 편집기를 종료할 때 저장할지 묻는 메시지를 건너뛸지 여부를 제어합니다.", "useExperimentalFileWatcher": "새로운 실험 파일 감시자를 사용하세요.", "defaultLanguage": "새 파일에 할당되는 기본 언어 모드입니다.", + "maxMemoryForLargeFilesMB": "큰 파일을 열려고 할 때 다시 시작한 후 VS Code에 사용 가능한 메모리를 제어합니다. 명령줄에 --max-memory=NEWSIZE를 지정하는 것과 결과가 같습니다. ", "editorConfigurationTitle": "편집기", "formatOnSave": "파일 저장 시 서식을 지정합니다. 포맷터를 사용할 수 있어야 하며, 파일이 자동으로 저장되지 않아야 하고, 편집기가 종료되지 않아야 합니다.", + "formatOnSaveTimeout": "저장 시 서식 지정의 시간 제한. FormatOnSave 명령에 대한 시간 제한을 밀리초로 지정합니다. 지정된 시간 제한보다 오래 걸리는 명령은 취소됩니다.", "explorerConfigurationTitle": "파일 탐색기", "openEditorsVisible": "열려 있는 편집기 창에 표시되는 편집기 수입니다.", "autoReveal": "탐색기에서 파일을 열 때 자동으로 표시하고 선택할지를 제어합니다.", diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 8417c022a7..0e96fcdac4 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -2,18 +2,22 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "파일 이름을 입력합니다. 확인하려면 Enter 키를 누르고, 취소하려면 Esc 키를 누릅니다.", - "constructedPath": "**{1}**에 {0} 만들기", + "createFileFromExplorerInfoMessage": "**{1}**에 **{0}** 만들기", + "renameFileFromExplorerInfoMessage": "이동 및 **{0}**(으)로 이름 바꾸기", + "createFolderFromExplorerInfoMessage": "**{1}**에 **{0}** 폴더 만들기", "filesExplorerViewerAriaLabel": "{0}, 파일 탐색기", "dropFolders": "작업 영역에 폴더를 추가하시겠습니까?", "dropFolder": "작업 영역에 폴더를 추가하시겠습니까?", "addFolders": "폴더 추가(&&A)", "addFolder": "폴더 추가(&&A)", + "confirmRootsMove": "작업 영역에서 다중 루트 폴더의 순서를 변경하시겠습니까? ", "confirmMultiMove": "다음 {0}개 파일을 이동하시겠습니까?", + "confirmRootMove": "작업 영역에서 루트 폴더 '{0}'의 순서를 변경하시겠습니까? ", "confirmMove": "'{0}'을(를) 이동하시겠습니까?", "doNotAskAgain": "이 메시지를 다시 표시 안 함", "moveButtonLabel": "이동(&&M)", diff --git a/i18n/kor/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..72937e2691 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Html 미리 보기" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/kor/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..a9bf271676 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "잘못된 편집기 입력입니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..73fa26c639 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "개발자" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/kor/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..3a107e5fb3 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview 개발자 도구 열기", + "refreshWebviewLabel": "Webview 다시 로드" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index e5cf72eebf..6b5162b502 100644 --- a/i18n/kor/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "VS Code의 UI 언어를 {0}(으)로 변경하고 다시 시작하시겠습니까?", + "yes": "예", + "no": "아니요", + "neverAgain": "다시 표시 안 함", "JsonSchema.locale": "사용할 UI 언어입니다.", "vscode.extension.contributes.localizations": "편집기에 지역화를 적용합니다.", "vscode.extension.contributes.localizations.languageId": "표시 문자열이 번역되는 언어의 ID입니다.", diff --git a/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..511e22e0dd --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "VS Code의 UI 언어를 {0}(으)로 변경하고 다시 시작하시겠습니까?", + "yes": "예", + "no": "아니요", + "neverAgain": "다시 표시 안 함", + "install language pack": "곧 VS Code에서는 Marketplace 확장 형식의 언어 팩만 지원합니다. 현재 구성된 언어를 계속 사용하도록 구성하려면 '{0}' 확장을 설치하세요. ", + "install": "설치", + "more information": "자세한 정보...", + "JsonSchema.locale": "사용할 UI 언어입니다.", + "vscode.extension.contributes.localizations": "편집기에 지역화를 적용합니다.", + "vscode.extension.contributes.localizations.languageId": "표시 문자열이 번역되는 언어의 ID입니다.", + "vscode.extension.contributes.localizations.languageName": "영어로 된 언어 이름입니다.", + "vscode.extension.contributes.localizations.languageNameLocalized": "적용된 언어로 된 언어 이름입니다.", + "vscode.extension.contributes.localizations.translations": "해당 언어에 연결된 번역 목록입니다.", + "vscode.extension.contributes.localizations.translations.id": "이 변환이 적용되는 VS Code 또는 확장의 ID입니다. VS Code의 ID는 항상 `vscode`이고 확장의 ID는 `publisherId.extensionName` 형식이어야 합니다.", + "vscode.extension.contributes.localizations.translations.id.pattern": "ID는 VS Code를 변환하거나 확장을 변환하는 경우 각각 `vscode` 또는 `publisherId.extensionName` 형식이어야 합니다.", + "vscode.extension.contributes.localizations.translations.path": "언어에 대한 변환을 포함하는 파일의 상대 경로입니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..e8656093b5 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "언어 구성", + "displayLanguage": "VSCode의 표시 언어를 정의합니다.", + "doc": "지원되는 언어 목록은 {0} 을(를) 참조하세요.", + "restart": "값을 변경하려면 VSCode를 다시 시작해야 합니다.", + "fail.createSettings": "{0}'({1})을(를) 만들 수 없습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..15ccb30fd5 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "복사", + "copyMessage": "메시지 복사" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..dae3babf1f --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "총 {0}개 문제" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..2103b0440b --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "문제", + "tooltip.1": "이 파일의 문제 1개", + "tooltip.N": "이 파일의 문제 {0}개", + "markers.showOnFile": "파일과 폴더의 오류 및 경고 표시" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..5145f166a0 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "파일 제외 필터를 사용하지 않도록 설정합니다.", + "clearFilter": "필터를 지웁니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..b597a05c76 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "{0}/{1} 표시" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..c7863f2ea1 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "보기", + "problems.view.toggle.label": "문제 토글(오류, 경고, 정보)", + "problems.view.focus.label": "포커스 문제(오류, 경고, 정보)", + "problems.panel.configuration.title": "문제 보기", + "problems.panel.configuration.autoreveal": "문제 보기를 열 때 문제 보기에 자동으로 파일이 표시되어야 하는지를 제어합니다.", + "markers.panel.title.problems": "문제", + "markers.panel.aria.label.problems.tree": "파일별로 그룹화된 문제", + "markers.panel.no.problems.build": "지금까지 작업 영역에서 문제가 감지되지 않았습니다.", + "markers.panel.no.problems.filters": "지정된 필터 조건으로 결과를 찾을 수 없습니다.", + "markers.panel.no.problems.file.exclusions": "파일 제외 필터를 사용하도록 설정했으므로 모든 문제가 숨겨집니다.", + "markers.panel.action.useFilesExclude": "파일 제외 필터를 사용하여 필터링", + "markers.panel.action.donotUseFilesExclude": "파일 제외 설정 사용 안 함", + "markers.panel.action.filter": "문제 필터링", + "markers.panel.filter.ariaLabel": "문제 필터링", + "markers.panel.filter.placeholder": "필터입니다. 예: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "오류", + "markers.panel.filter.warnings": "경고", + "markers.panel.filter.infos": "정보", + "markers.panel.single.error.label": "오류 1개", + "markers.panel.multiple.errors.label": "오류 {0}개", + "markers.panel.single.warning.label": "경고 1개", + "markers.panel.multiple.warnings.label": "경고 {0}개", + "markers.panel.single.info.label": "정보 1개", + "markers.panel.multiple.infos.label": "정보 {0}개", + "markers.panel.single.unknown.label": "알 수 없음 1개", + "markers.panel.multiple.unknowns.label": "알 수 없음 {0}개", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0}에 {1}개의 문제가 있음", + "problems.tree.aria.label.marker.relatedInformation": " 이 문제에는 {0} 위치에 대한 참조가 있습니다.", + "problems.tree.aria.label.error.marker": "{0}에 의해 오류 발생: 줄 {2} 및 문자 {3}.{4}의 {1}", + "problems.tree.aria.label.error.marker.nosource": "오류: 줄 {1} 및 문자 {2}의 {0}.{3}", + "problems.tree.aria.label.warning.marker": "{0}에 의해 경고 발생: 줄 {2} 및 문자 {3}의 {1}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "경고: 줄 {1} 및 문자 {2}의 {0}.{3}", + "problems.tree.aria.label.info.marker": "{0}에 의해 정보가 생성됨: 줄 {2} 및 문자 {3}의 {1}.{4}", + "problems.tree.aria.label.info.marker.nosource": "정보: 줄 {1} 및 문자 {2}의 {0}.{3}", + "problems.tree.aria.label.marker": "{0}에 의해 문제 발생: 줄 {2} 및 문자 {3}의 {1}.{4}", + "problems.tree.aria.label.marker.nosource": "문제: 줄 {1} 및 문자 {2}의 {0}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{3}에서 줄 {1} 및 문자 {2}의 {0}", + "errors.warnings.show.label": "오류 및 경고 표시" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/kor/src/vs/workbench/parts/output/browser/outputActions.i18n.json index c226c52b58..bc019ed384 100644 --- a/i18n/kor/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "출력 설정/해제", "clearOutput": "출력 내용 지우기", "toggleOutputScrollLock": "출력 스크롤 잠금 설정/해제", - "switchToOutput.label": "출력으로 전환" + "switchToOutput.label": "출력으로 전환", + "openInLogViewer": "로그 파일 열기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 22dda76b34..f1814b256d 100644 --- a/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "출력", "logViewer": "로그 표시기", "viewCategory": "보기", - "clearOutput.label": "출력 내용 지우기" + "clearOutput.label": "출력 내용 지우기", + "openActiveLogOutputFile": "보기: 활성 로그 출력 파일 열기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 471704e04b..c191033d1a 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "바로 가기 키(&&K)", + "showDefaultKeybindings": "기본 키 바인딩 표시", + "showUserKeybindings": "사용자 키 바인딩 표시", "SearchKeybindings.AriaLabel": "키 바인딩 검색", "SearchKeybindings.Placeholder": "키 바인딩 검색", "sortByPrecedene": "우선 순위별 정렬", diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 1f10b73881..b7c089a52d 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "원시 기본 설정 열기", + "openSettings": "설정 열기", "openGlobalSettings": "사용자 설정 열기", "openGlobalKeybindings": "바로 가기 키 열기", "openGlobalKeybindingsFile": "바로 가기 키 파일 열기", diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 58ae91696a..02c5e0b2c2 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "기본 설정", "SearchSettingsWidget.AriaLabel": "설정 검색", "SearchSettingsWidget.Placeholder": "설정 검색", "noSettingsFound": "결과 없음", @@ -16,6 +15,8 @@ "nlpResult": "자연어 결과", "filterResult": "필터링된 결과", "defaultSettings": "기본 설정", + "defaultUserSettings": "기본 사용자 설정", + "defaultWorkspaceSettings": "기본 작업 영역 설정", "defaultFolderSettings": "기본 폴더 설정", "defaultEditorReadonly": "기본값을 재정의하려면 오른쪽 편집기를 편집하세요.", "preferencesAriaLabel": "기본 설정. 읽기 전용 텍스트 편집기입니다." diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index c817223219..b0a4a6fdb9 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "\"{0}\" 확장 표시", "editTtile": "편집", "replaceDefaultValue": "설정에서 바꾸기", - "copyDefaultValue": "설정에 복사", - "unsupportedPHPExecutablePathSetting": "이 설정은 사용자 설정이어야 합니다. 작업 영역에 대해 PHP를 구성하려면 PHP 파일을 열고 상태 표시줄에서 'PHP 경로'를 클릭합니다.", - "unsupportedWorkspaceSetting": "이 설정은 사용자 설정이어야 합니다.", - "unsupportedWorkbenchSetting": "이 설정은 지금 적용할 수 없으며 이 폴더를 직접 열 경우에 적용됩니다.", - "unsupportedWorkbenchSettingDevMode": "현재 이 설정을 적용할 수 없습니다. 등록하는 동안 범위를 '리소스'로 정의하거나 이 폴더를 직접 여는 경우 적용됩니다." + "copyDefaultValue": "설정에 복사" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 6911c1d2f6..fb08258437 100644 --- a/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "추가 SCM 공급자 설치...", "no open repo": "활성 소스 제어 공급자가 없습니다.", "source control": "소스 제어", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "숨기기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json index d06e032b06..6fd284ba72 100644 --- a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "이전 검색 제외 패턴 표시", "nextSearchTerm": "다음 검색어 표시", "previousSearchTerm": "이전 검색어 표시", - "showSearchViewlet": "검색 표시", "findInFiles": "파일에서 찾기", "replaceInFiles": "파일에서 바꾸기", "RefreshAction.label": "새로 고침", diff --git a/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 4ee4faef2e..2d6e06f549 100644 --- a/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "검색", + "copyMatchLabel": "복사", + "copyPathLabel": "경로 복사", + "copyAllLabel": "모두 복사", + "clearSearchHistoryLabel": "검색 기록 지우기", + "toggleSearchViewPositionLabel": "검색 보기 위치 토글", "findInFolder": "폴더에서 찾기...", "findInWorkspace": "작업 영역에서 찾기...", "showTriggerActions": "작업 영역에서 기호로 이동...", "name": "검색", - "search": "검색", "showSearchViewl": "검색 표시", "view": "보기", "findInFiles": "파일에서 찾기", @@ -26,5 +31,5 @@ "search.followSymlinks": "검색하는 동안 symlink를 누를지 여부를 제어합니다.", "search.smartCase": "패턴이 모두 소문자인 경우 대/소문자를 구분하지 않고 검색하고, 그렇지 않으면 대/소문자를 구분하여 검색합니다.", "search.globalFindClipboard": "macOS에서 검색 보기가 공유 클립보드 찾기를 읽거나 수정해야 할지를 제어합니다.", - "search.location": "미리 보기: 검색을 사이드바의 보기로 표시할지 또는 가로 간격을 늘리기 위해 패널 영역의 패널로 표시할지를 제어합니다. 다음 릴리스의 패널에서의 검색은 가로 레이아웃이 개선되며 더 이상 미리 보기가 아닙니다." + "search.location": "검색을 사이드바의 보기로 표시할지 또는 가로 간격을 늘리기 위해 패널 영역의 패널로 표시할지를 제어합니다. 다음 릴리스의 패널에서의 검색은 가로 레이아웃이 개선되며 더 이상 미리 보기가 아닙니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index fdd79a3a86..29665fdee0 100644 --- a/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "{0}에 대한 지원을 개선하는 데 도움을 주세요.", "takeShortSurvey": "간단한 설문 조사 참여", "remindLater": "나중에 알림", - "neverAgain": "다시 표시 안 함", - "helpUs": "{0}에 대한 지원을 개선하는 데 도움을 주세요." + "neverAgain": "다시 표시 안 함" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 764abb5ca1..c271cf629e 100644 --- a/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "간단한 피드백 설문 조사에 참여하시겠어요?", "takeSurvey": "설문 조사 참여", "remindLater": "나중에 알림", - "neverAgain": "다시 표시 안 함", - "surveyQuestion": "간단한 피드백 설문 조사에 참여하시겠어요?" + "neverAgain": "다시 표시 안 함" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index e111cbad1b..a6d3822b0a 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -10,6 +10,7 @@ "ProblemPatternParser.problemPattern.kindProperty.notFirst": "문제 패턴이 잘못되었습니다. Kind 속성은 첫 번째 요소에만 지정해야 합니다.", "ProblemPatternParser.problemPattern.missingRegExp": "문제 패턴에 정규식이 없습니다.", "ProblemPatternParser.problemPattern.missingProperty": "문제 패턴이 잘못되었습니다. 하나 이상의 파일 및 메시지를 포함해야 합니다.", + "ProblemPatternParser.problemPattern.missingLocation": "문제 패턴이 잘못되었습니다. \"파일\" 종류, 줄 또는 위치 일치 그룹을 포함해야 합니다.", "ProblemPatternParser.invalidRegexp": "오류: {0} 문자열은 유효한 정규식이 아닙니다.\n", "ProblemPatternSchema.regexp": "출력에서 오류, 경고 또는 정보를 찾는 정규식입니다.", "ProblemPatternSchema.kind": "패턴이 위치(파일 및 줄)와 일치하는지 또는 파일하고만 일치하는지 여부입니다.", @@ -44,6 +45,7 @@ "PatternTypeSchema.description": "문제 패턴 또는 제공되거나 미리 정의된 문제 패턴의 이름입니다. 기본이 지정된 경우 생략할 수 있습니다.", "ProblemMatcherSchema.base": "사용할 기본 문제 선택기의 이름입니다.", "ProblemMatcherSchema.owner": "Code 내부의 문제 소유자입니다. 기본값을 지정한 경우 생략할 수 있습니다. 기본값을 지정하지 않고 생략한 경우 기본값은 '외부'입니다.", + "ProblemMatcherSchema.source": "이 진단의 소스를 설명하는 사람이 읽을 수 있는 문자열입니다(예: 'typescript' 또는 'super lint').", "ProblemMatcherSchema.severity": "캡처 문제에 대한 기본 심각도입니다. 패턴에서 심각도에 대한 일치 그룹을 정의하지 않은 경우에 사용됩니다.", "ProblemMatcherSchema.applyTo": "텍스트 문서에 복된 문제가 열린 문서, 닫힌 문서 또는 모든 문서에 적용되는지를 제어합니다.", "ProblemMatcherSchema.fileLocation": "문제 패턴에 보고된 파일 이름을 해석하는 방법을 정의합니다.", diff --git a/i18n/kor/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 4fadd7d7d2..54d3d5e66a 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "실제 작업 유형", + "TaskDefinition.description": "실제 작업 형식입니다. '$'로 시작하는 형식은 내부용으로 예약되어 있습니다.", "TaskDefinition.properties": "작업 유형의 추가 속성", "TaskTypeConfiguration.noType": "작업 유형 구성에 필요한 'taskType' 속성이 없음", "TaskDefinitionExtPoint": "작업 유형 적용" diff --git a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 00fa85793c..7f3fc4d619 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "작업을 그룹에 할당 안 함", "JsonSchema.tasks.group": "이 작업을 할당할 실행 그룹을 정의합니다. 빌드 그룹에 추가를 위한 \"build'와 테스트 그룹에 추가를 위한 \"test\"를 지원합니다.", "JsonSchema.tasks.type": "작업이 프로세스로 실행되는지 또는 셸 내의 명령으로 실행되는지를 제어합니다.", + "JsonSchema.command.quotedString.value": "실제 명령 값", + "JsonSchema.tasks.quoting.escape": "셸의 이스케이프 문자를 사용하여 문자를 이스케이프합니다(예: ` under PowerShell 및 \\ under bash).", + "JsonSchema.tasks.quoting.strong": "셸의 강력한 따옴표 문자를 사용하여 인수를 따옴표 처리합니다(예: \" under PowerShell and bash).", + "JsonSchema.tasks.quoting.weak": "셸의 약한 따옴표 문자를 사용하여 인수를 따옴표 처리합니다(예: PowerShell 및 bash의 경우 ').", + "JsonSchema.command.quotesString.quote": "명령 값을 따옴표로 묶을 방법입니다.", + "JsonSchema.command": "실행할 명령이며, 외부 프로그램 또는 셸 명령입니다.", + "JsonSchema.args.quotedString.value": "실제 인수 값", + "JsonSchema.args.quotesString.quote": "인수 값을 따옴표로 묶을 방법입니다.", + "JsonSchema.tasks.args": "이 작업이 호출될 때 명령에 전달되는 인수입니다.", "JsonSchema.tasks.label": "작업 사용자 인터페이스 레이블", "JsonSchema.version": "구성의 버전 번호입니다.", "JsonSchema.tasks.identifier": "작업을 launch.json 또는 dependsOn 구문에서 참조할 사용자 정의 식별자입니다.", diff --git a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 06360e9720..7b483f685d 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "작업", "ConfigureTaskRunnerAction.label": "작업 구성", + "totalErrors": "오류 {0}개", + "totalWarnings": "경고 {0}개", + "totalInfos": "정보 {0}개", "problems": "문제", "building": "빌드하고 있습니다...", - "manyMarkers": "99+", + "manyProblems": "10K+", "runningTasks": "실행 중인 작업 표시", "tasks": "작업", "TaskSystem.noHotSwap": "실행 중인 활성 작업이 있는 작업 실행 엔진을 변경하면 Window를 다시 로드해야 합니다.", @@ -28,8 +31,10 @@ "selectProblemMatcher": "작업 출력에서 스캔할 오류 및 경고 유형을 선택", "customizeParseErrors": "현재 작성 구성에 오류가 있습니다. 작업을 사용자 지정하기 전에 오류를 수정하세요.\n", "moreThanOneBuildTask": "tasks.json에 여러 빌드 작업이 정의되어 있습니다. 첫 번째 작업을 실행합니다.\n", - "TaskSystem.activeSame.background": "'{0}' 작업이 이미 활성 상태로 백그라운드 모드에 있습니다. 종료하려면 [작업] 메뉴에서 '작업 종료...'를 사용하세요.", - "TaskSystem.activeSame.noBackground": "'{0}' 작업이 이미 활성 상태입니다. 종료하려면 [작업] 메뉴에서 '작업 종료...'를 사용하세요.", + "TaskSystem.activeSame.background": "'{0}' 작업이 이미 활성 상태이며 백그라운드 모드입니다.", + "TaskSystem.activeSame.noBackground": "'{0}' 작업은 이미 활성 상태입니다.", + "terminateTask": "작업 종료", + "restartTask": "작업 다시 시작", "TaskSystem.active": "이미 실행 중인 작업이 있습니다. 다른 작업을 실행하려면 먼저 이 작업을 종료하세요.", "TaskSystem.restartFailed": "{0} 작업을 종료하고 다시 시작하지 못했습니다.", "TaskService.noConfiguration": "오류: {0} 작업 검색에서는 다음 구성에 대한 작업을 제공하지 않습니다:\n{1}\n이 작업이 무시됩니다.\n", @@ -46,6 +51,7 @@ "recentlyUsed": "최근에 사용한 작업", "configured": "구성된 작업", "detected": "감지된 작업", + "TaskService.ignoredFolder": "작업 버전 0.1.0을 사용하기 때문에 다음 작업 영역 폴더는 무시됩니다. {0}", "TaskService.notAgain": "다시 표시 안 함", "TaskService.pickRunTask": "실행할 작업 선택", "TaslService.noEntryToRun": "실행할 작업이 없습니다. 작업 구성...", diff --git a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 9a376a12f4..5fd4428702 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "작업 - {0}", "closeTerminal": "터미널을 종료하려면 아무 키나 누르세요.", "reuseTerminal": "터미널이 작업에서 다시 사용됩니다. 닫으려면 아무 키나 누르세요.", - "TerminalTaskSystem": "UNC 드라이브에서 셸 명령을 실행할 수 없습니다.", + "TerminalTaskSystem": "Cmd.exe를 사용하여 UNC 드라이브에 셸 명령을 실행할 수 없습니다.", "unkownProblemMatcher": "문제 선택기 {0}을(를) 확인할 수 없습니다. 이 선택기는 무시됩니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/kor/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index 192277284b..116b70c443 100644 --- a/i18n/kor/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "경고: options.cwd는 string 형식이어야 합니다. {0} 값을 무시합니다.\n", + "ConfigurationParser.inValidArg": "오류: 명령 인수는 문자열 또는 따옴표 붙은 문자열이어야 합니다. 제공된 값:\n{0}", "ConfigurationParser.noargs": "오류: 명령 인수는 문자열의 배열이어야 합니다. 제공된 값:\n{0}", "ConfigurationParser.noShell": "경고: 셸 구성은 작업을 터미널에서 실행 중일 때에만 지원됩니다.", "ConfigurationParser.noName": "오류: 선언 범위 내의 문제 선택기는 이름이 있어야 합니다.\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "오류: 작업 구성 '{0}'에 필요한 속성 '{1}'이(가) 없습니다. 작업 구성이 무시됩니다.", "ConfigurationParser.notCustom": "오류: 작업이 사용자 지정 작업으로 선언되지 않았습니다. 이 구성은 무시됩니다.\n{0}\n", "ConfigurationParser.noTaskName": "오류: 작업에서 레이블 속성을 제공해야 합니다. 이 작업은 무시됩니다.\n{0}\n", - "taskConfiguration.shellArgs": "경고: '{0}' 작업은 셸 명령이며 인수 중 하나에 이스케이프되지 않은 공백이 있을 수 있습니다. 올바른 명령줄 인용인지 확인하려면 인수를 명령으로 병합하세요.", "taskConfiguration.noCommandOrDependsOn": "오류: 작업 '{0}'에서 명령이나 dependsOn 속성을 지정하지 않습니다. 이 작업은 무시됩니다. 해당 작업의 정의는 {1}입니다.", "taskConfiguration.noCommand": "오류: 작업 '{0}'에서 명령을 정의하지 않습니다. 이 작업은 무시됩니다. 해당 작업의 정의는\n{1}입니다.", "TaskParse.noOsSpecificGlobalTasks": "작업 버전 2.0.0은 글로벌 OS별 작업을 지원하지 않습니다. OS별 명령을 사용하여 작업으로 변환하세요. 영향을 받는 작업::\n{0}" diff --git a/i18n/kor/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..d9e00ba078 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "터미널의 배경색입니다. 이 설정을 사용하면 터미널\n 색을 패널과 다르게 지정할 수 있습니다.", + "terminal.foreground": "터미널의 전경색입니다.", + "terminalCursor.foreground": "터미널 커서의 전경색입니다.", + "terminalCursor.background": "터미널 커서의 배경색입니다. 블록 커서와 겹친 문자의 색상을 사용자 정의할 수 있습니다.", + "terminal.selectionBackground": "터미널의 선택 영역 배경색입니다.", + "terminal.border": "터미널 내의 분할 창을 구분하는 테두리의 색입니다. 기본값은 panel.border입니다.", + "terminal.ansiColor": "터미널의 '{0}' ANSI 색상" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 15c1824a8b..3446947ad0 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "새 터미널의 현재 작업 디렉토리를 선택합니다.", "workbench.action.terminal.newInActiveWorkspace": "새 통합 터미널 만들기(활성 작업 영역에)", "workbench.action.terminal.split": "터미널 분할", + "workbench.action.terminal.splitInActiveWorkspace": "터미널 분할(활성 작업 영역에서)", "workbench.action.terminal.focusPreviousPane": "이전 창에 포커스", "workbench.action.terminal.focusNextPane": "다음 창에 포커스", "workbench.action.terminal.resizePaneLeft": "창 왼쪽 크기 조정", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "위로 스크롤(페이지)", "workbench.action.terminal.scrollToTop": "맨 위로 스크롤", "workbench.action.terminal.clear": "지우기", + "workbench.action.terminal.clearSelection": "선택 영역 지우기", "workbench.action.terminal.allowWorkspaceShell": "작업 영역 셸 구성 허용", "workbench.action.terminal.disallowWorkspaceShell": "작업 영역 셸 구성 허용 안 함", "workbench.action.terminal.rename": "이름 바꾸기", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "파인드 위젯 숨기기", "nextTerminalFindTerm": "다음 검색어 표시", "previousTerminalFindTerm": "이전 검색어 표시", - "quickOpenTerm": "활성 터미널 전환" + "quickOpenTerm": "활성 터미널 전환", + "workbench.action.terminal.scrollToPreviousCommand": "이전 명령으로 스크롤", + "workbench.action.terminal.scrollToNextCommand": "다음 명령으로 스크롤", + "workbench.action.terminal.selectToPreviousCommand": "이전 명령까지 선택", + "workbench.action.terminal.selectToNextCommand": "다음 명령까지 선택" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index a00cac3cea..5200a408de 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "터미널에 복사할 선택 항목이 없음", "terminal.integrated.exitedWithCode": "터미널 프로세스가 종료 코드 {0}(으)로 종료되었습니다.", "terminal.integrated.waitOnExit": "터미널을 닫으려면 아무 키나 누르세요.", - "terminal.integrated.launchFailed": "터미널 프로세스 명령 '{0}{1}'을(를) 실행하지 못했습니다(종료 코드: {2})." + "terminal.integrated.launchFailed": "터미널 프로세스 명령 '{0}{1}'을(를) 실행하지 못했습니다(종료 코드: {2}).", + "terminal.integrated.launchFailedExtHost": "터미널 프로세스를 시작하지 못했습니다(종료 코드: {0})." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 773e393a39..4a7107c09c 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copy": "복사", + "split": "분할", "paste": "붙여넣기", "selectAll": "모두 선택", "clear": "지우기", diff --git a/i18n/kor/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 0e9f47c7b1..bd4153193e 100644 --- a/i18n/kor/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "이 작업 영역에는 사용자 설정({0})에서만 지정할 수 있는 설정이 포함되어 있습니다. 자세히 알아보려면 [여기]({1})를 클릭하세요.", "openWorkspaceSettings": "작업 영역 설정 열기", "dontShowAgain": "다시 표시 안 함", "unsupportedWorkspaceSettings": "이 작업 영역에는 사용자 설정({0})에서만 지정할 수 있는 설정이 포함되어 있습니다. 자세히 알아보려면 [여기]({1})를 클릭하세요." diff --git a/i18n/kor/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/kor/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..3314e92b45 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "릴리스 정보: {0}", + "unassigned": "할당되지 않음" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 7c0e09cd6d..766dc7e7a2 100644 --- a/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "나중에", - "unassigned": "할당되지 않음", "releaseNotes": "릴리스 정보", "showReleaseNotes": "릴리스 정보 표시", "read the release notes": "{0} v{1}을(를) 시작합니다. 릴리스 정보를 확인하시겠습니까?", @@ -17,13 +15,14 @@ "updateIsReady": "새 {0} 업데이트를 사용할 수 있습니다.", "noUpdatesAvailable": "현재 사용할 수 있는 업데이트가 없습니다.", "ok": "확인", - "download now": "지금 다운로드", "thereIsUpdateAvailable": "사용 가능한 업데이트가 있습니다.", - "installUpdate": "업데이트 설치", + "download now": "지금 다운로드", + "later": "나중에", "updateAvailable": "사용 가능한 업데이트가 있습니다. {0} {1}", + "installUpdate": "업데이트 설치", "updateInstalling": "{0} {1}이(가) 백그라운드로 설치되고 있습니다. 완료되면 알려드리겠습니다.", + "updateAvailableAfterRestart": "최신 업데이트를 적용하려면 {0}을(를) 다시 시작하세요.", "updateNow": "지금 업데이트", - "updateAvailableAfterRestart": "다시 시작하면 {0}이(가) 업데이트됩니다.", "commandPalette": "명령 팔레트...", "settings": "설정", "keyboardShortcuts": "바로 가기 키(&&K)", diff --git a/i18n/kor/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..a154966e52 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "URL 열기", + "developer": "개발자" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..d6b00d8785 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "webview 편집기", + "developer": "개발자" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..3a107e5fb3 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Webview 개발자 도구 열기", + "refreshWebviewLabel": "Webview 다시 로드" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/kor/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..88ec2a103e --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Microsoft에서 사용 데이터를 수집하도록 허용하여 VS Code 개선에 도움을 주세요. Microsoft [개인정보처리방침]({0})을 읽고 [옵트아웃]({1})하는 방법을 알아보세요.", + "telemetryOptOut.optInNotice": "Microsoft에서 사용 데이터를 수집하도록 허용하여 VS Code 개선에 도움을 주세요. Microsoft [개인정보처리방침]({0})을 읽고 [옵트인]({1})하는 방법을 알아보세요.", + "telemetryOptOut.readMore": "자세히 알아보기" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/kor/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index 2926a4323a..0938d5cb44 100644 --- a/i18n/kor/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "확장 관리", "welcomeOverlay.problems": "오류 및 경고 보기", "welcomeOverlay.commandPalette": "모든 명령 찾기 및 실행", + "welcomeOverlay.notifications": "알림 표시", "welcomeOverlay": "사용자 인터페이스 개요", "hideWelcomeOverlay": "인터페이스 개요 숨기기", "help": "도움말" diff --git a/i18n/kor/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/kor/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index cccd10d821..c65bb0575b 100644 --- a/i18n/kor/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "도구 및 언어", "welcomePage.installExtensionPacksDescription": "{0} 및 {1}에 대한 지원 설치", "welcomePage.moreExtensions": "자세히", - "welcomePage.installKeymapDescription": "바로 가기 키 설치", - "welcomePage.installKeymapExtension": "{0} 및 {1}의 바로 가기 키 설치", + "welcomePage.installKeymapDescription": "설정 및 키 바인딩", + "welcomePage.installKeymapExtension": "설정과 {0} 및 {1}의 바로 가기 키 설치", "welcomePage.others": "기타", "welcomePage.colorTheme": "색 테마", "welcomePage.colorThemeDescription": "편집기 및 코드가 좋아하는 방식으로 표시되게 만들기", diff --git a/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 2a654df66a..9e248eddb0 100644 --- a/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/kor/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "설정을 요약합니다. 이 레이블은 설정 파일에서 구분 주석으로 사용됩니다.", "vscode.extension.contributes.configuration.properties": "구성 속성에 대한 설명입니다.", + "scope.application.description": "[사용자] 설정에서만 구성할 수 있는 응용 프로그램 관련 구성입니다.", "scope.window.description": "[사용자] 설정 또는 [작업 영역] 설정에서 구성할 수 있는 창 특정 구성입니다.", "scope.resource.description": "사용자, 작업 영역 또는 폴더 설정에서 구성할 수 있는 리소스 특정 구성", "scope.description": "구성이 적용되는 범위입니다. 사용 가능 범위는 '창'과 '리소스'입니다.", diff --git a/i18n/kor/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/kor/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index 9796c171f5..185d09e638 100644 --- a/i18n/kor/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "설정 열기", "saveAndRetry": "저장 및 다시 시도", "errorUnknownKey": "{1}은(는) 등록된 구성이 아니므로 {0}에 쓸 수 없습니다.", + "errorInvalidWorkspaceConfigurationApplication": "{0}을(를) [작업 영역] 설정에 쓸 수 없습니다. 이 설정은 [사용자] 설정에만 쓸 수 있습니다.", "errorInvalidFolderConfiguration": "{0}이(가) 폴더 리소스 범위를 지원하지 않으므로 폴더 설정에 쓸 수 없습니다.", "errorInvalidUserTarget": "{0}이(가) 글로벌 범위를 지원하지 않으므로 사용자 설정에 쓸 수 없습니다.", "errorInvalidWorkspaceTarget": "{0}이(가) 여러 폴더 작업 영역에서 작업 영역 범위를 지원하지 않으므로 작업 영역 설정에 쓸 수 없습니다.", diff --git a/i18n/kor/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/kor/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..ef1d360dbb --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "이 설정은 [사용자] 설정에서만 적용할 수 있습니다.", + "unsupportedWindowSetting": "이 설정은 지금 적용할 수 없으며 이 폴더를 직접 열 경우에 적용됩니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/kor/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/kor/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..aadf3905be --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "환경 변수 이름을 지정하지 않았으므로 '{0}'을(를) 확인할 수 없습니다.", + "configNotFound": "'{1}' 설정을 찾을 수 없으므로 '{0}'을(를) 확인할 수 없습니다.", + "configNoString": "'{1}'은(는) 구조적 값이므로 '{0}'을(를) 확인할 수 없습니다.", + "missingConfigName": "설정 이름을 지정하지 않았으므로 '{0}'을(를) 확인할 수 없습니다.", + "noValueForCommand": "명령에 값이 없으므로 '{0}'을(를) 확인할 수 없습니다.", + "canNotFindFolder": "'{0}'을(를) 확인할 수 없습니다. 해당 '{1}' 폴더가 없습니다.", + "canNotResolveWorkspaceFolderMultiRoot": "다중 폴더 작업 영역에서 '{0}'을(를) 확인할 수 없습니다. ':'과 작업 영역 폴더 이름을 사용하여 이 변수 범위를 정하세요.", + "canNotResolveWorkspaceFolder": "'{0}'을(를) 확인할 수 없습니다. 폴더를 여세요.", + "canNotResolveFile": "'{0}'을(를) 확인할 수 없습니다. 편집기를 여세요.", + "canNotResolveLineNumber": "'{0}'을(를) 확인할 수 없습니다. 선택한 줄이 활성 편집기에 있는지 확인하세요.", + "canNotResolveSelectedText": "'{0}'을(를) 확인할 수 없습니다. 선택한 텍스트가 활성 편집기에 있는지 확인하세요." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/kor/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..9604885992 --- /dev/null +++ b/i18n/kor/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "예(&&Y)", + "cancelButton": "취소" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/kor/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 8cd1ea6a64..b5e6586f03 100644 --- a/i18n/kor/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/kor/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "엔진 호환성입니다.", "vscode.extension.engines.vscode": "VS Code 확장의 경우, 확장이 호환되는 VS Code 버전을 지정합니다. *일 수 없습니다. 예를 들어 ^0.10.5는 최소 VS Code 버전인 0.10.5와 호환됨을 나타냅니다.", "vscode.extension.publisher": "VS Code 확장의 게시자입니다.", "vscode.extension.displayName": "VS Code 갤러리에 사용되는 확장의 표시 이름입니다.", "vscode.extension.categories": "확장을 분류하기 위해 VS Code 갤러리에서 사용하는 범주입니다.", + "vscode.extension.category.languages.deprecated": "대신 '프로그래밍 언어' 사용", "vscode.extension.galleryBanner": "VS Code 마켓플레이스에 사용되는 배너입니다.", "vscode.extension.galleryBanner.color": "VS Code 마켓플레이스 페이지 머리글의 배너 색상입니다.", "vscode.extension.galleryBanner.theme": "배너에 사용되는 글꼴의 색상 테마입니다.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "특정 유형의 디버그 세션이 시작하려고 할 때마다(그리고 해당하는 resolveDebugConfiguration 메서드를 호출해야 할 때마다) 발생하는 활성화 이벤트입니다.", "vscode.extension.activationEvents.workspaceContains": "지정된 glob 패턴과 일치하는 파일이 하나 이상 있는 폴더를 열 때마다 활성화 알림이 발송됩니다.", "vscode.extension.activationEvents.onView": "지정된 뷰가 확장될 때마다 활성화 이벤트가 내보내 집니다.", + "vscode.extension.activationEvents.onUri": "이 확장으로 이동되는 시스템 차원 URI를 열 때마다 활성화 이벤트를 내보냅니다.", "vscode.extension.activationEvents.star": "VS Code 시작 시 활성화 이벤트가 발송됩니다. 훌륭한 최종 사용자 경험을 보장하려면 사용 케이스에서 다른 활성화 이벤트 조합이 작동하지 않을 때에만 확장에서 이 활성화 이벤트를 사용하세요.", "vscode.extension.badges": "마켓플레이스 확장 페이지의 사이드바에 표시할 배지의 배열입니다.", "vscode.extension.badges.url": "배지 이미지 URL입니다.", "vscode.extension.badges.href": "배지 링크입니다.", "vscode.extension.badges.description": "배지 설명입니다.", + "vscode.extension.markdown": "Marketplace에서 사용되는 Markdown 렌더링 엔진을 제어합니다. Github(기본값) 또는 표준입니다.", + "vscode.extension.qna": "Marketplace에서 Q&A 링크를 제어합니다. 기본 Marketplace Q & A 사이트를 사용하도록 설정하려면 marketplace로 설정합니다. 사용자 지정 Q & A 사이트의 URL을 제공하려면 문자열로 설정합니다. Q & A를 전적으로 사용하지 않도록 설정하려면 false로 설정합니다.", "vscode.extension.extensionDependencies": "다른 확장에 대한 종속성입니다. 확장 식별자는 항상 ${publisher}.${name}입니다(예: vscode.csharp).", "vscode.extension.scripts.prepublish": "패키지가 VS Code 확장 형태로 게시되기 전에 스크립트가 실행되었습니다.", "vscode.extension.scripts.uninstall": "VS Code 확장에 대한 후크를 제거합니다. 확장이 VS Code에서 완전히 제거될 때 즉, 확장이 제거된 후 VS Code가 다시 시작할 때(종료하고 시작) 실행되는 스크립트입니다. 노드 스크립트만 지원됩니다.", diff --git a/i18n/kor/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/kor/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 81f0291ac2..708758860d 100644 --- a/i18n/kor/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "모든 확장을 사용할 수 없습니다.", "extensionHostProcess.crash": "확장 호스트가 예기치 않게 종료되었습니다.", "extensionHostProcess.unresponsiveCrash": "확장 호스트가 응답하지 않아서 종료되었습니다.", - "devTools": "개발자 도구", + "devTools": "개발자 도구 열기", "restart": "확장 호스트 다시 시작", "overwritingExtension": "확장 {0}을(를) {1}(으)로 덮어쓰는 중입니다.", "extensionUnderDevelopment": "{0}에서 개발 확장 로드 중", diff --git a/i18n/kor/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/kor/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 01ad83f8c0..361d1ad735 100644 --- a/i18n/kor/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5가 필요합니다. 설치하려면 링크를 클릭하세요.", "installNet": ".NET Framework 4.5 다운로드", "neverShowAgain": "다시 표시 안 함", - "netVersionError": "Microsoft .NET Framework 4.5가 필요합니다. 설치하려면 링크를 클릭하세요.", + "enospcError": "{0}은(는) 이 큰 작업 영역에서 파일 변경 내용을 감시할 수 없습니다. 지침 링크에 따라 이 문제를 해결하세요.", "learnMore": "지침", - "enospcError": "{0}에 파일 핸들이 부족합니다. 지침 링크를 클릭하여 문제를 해결하세요.", + "fileInvalidPath": "잘못된 파일 리소스({0})", + "fileIsDirectoryError": "파일이 디렉터리입니다.", + "fileNotModifiedError": "파일 수정 안 됨", + "fileTooLargeForHeapError": "이 크기의 파일을 열려면 VS Code를 다시 시작하여 더 많은 메모리를 사용하도록 허용해야 합니다.", + "fileTooLargeError": "파일이 너무 커서 열 수 없음", + "fileNotFoundError": "파일을 찾을 수 없습니다({0}).", + "fileBinaryError": "파일이 이진인 것 같으므로 테스트로 열 수 없습니다.", + "filePermission": "파일 쓰기 권한이 거부되었습니다. ({0})", + "fileExists": "만드려는 파일이 이미 있음({0})", + "fileModifiedError": "파일 수정됨", + "fileReadOnlyError": "파일이 읽기 전용입니다.", + "fileMoveConflict": "이동/복사할 수 없습니다. 대상에 파일이 이미 있습니다.", + "unableToMoveCopyError": "이동/복사할 수 없습니다. 파일이 포함된 폴더를 파일로 대체합니다.", "binFailed": "'{0}'을(를) 휴지통으로 이동하지 못함", "trashFailed": "'{0}'을(를) 휴지통으로 이동하지 못함" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 7d349f9c52..b7aef6c171 100644 --- a/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "파일을 찾을 수 없습니다({0}).", "fileIsDirectoryError": "파일이 디렉터리입니다.", "fileNotModifiedError": "파일 수정 안 됨", - "fileBinaryError": "파일이 이진인 것 같으므로 테스트로 열 수 없습니다." + "fileBinaryError": "파일이 이진인 것 같으므로 테스트로 열 수 없습니다.", + "err.create": "{0} 파일을 만들지 못했습니다.", + "fileMoveConflict": "이동/복사할 수 없습니다. 대상에 파일이 이미 있습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/kor/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..64d5a6ad78 100644 --- a/i18n/kor/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/kor/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "취소" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index e3cc7dc113..4df29a136d 100644 --- a/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "tmLanguage 파일에 사용되는 Textmate 범위 이름입니다.", "vscode.extension.contributes.grammars.path": "tmLanguage 파일의 경로입니다. 확장 폴더의 상대 경로이며 일반적으로 './syntaxes/'로 시작합니다.", "vscode.extension.contributes.grammars.embeddedLanguages": "이 문법에 포함된 언어가 있는 경우 언어 ID에 대한 범위 이름의 맵입니다.", + "vscode.extension.contributes.grammars.tokenTypes": "토큰 형식에 대한 범위 이름의 맵입니다.", "vscode.extension.contributes.grammars.injectTo": "이 문법이 삽입되는 언어 범위 이름 목록입니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index 6efd8a6b39..584995246b 100644 --- a/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/kor/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "`contributes.{0}.path`에 문자열이 필요합니다. 제공된 값: {1}", "invalid.injectTo": "`contributes.{0}.injectTo`의 값이 잘못되었습니다. 언어 범위 이름 배열이어야 합니다. 제공된 값: {1}", "invalid.embeddedLanguages": "`contributes.{0}.embeddedLanguages` 값이 잘못되었습니다. 범위 이름에서 언어까지의 개체 맵이어야 합니다. 제공된 값: {1}", + "invalid.tokenTypes": "`contributes.{0}.tokenTypes` 값이 잘못되었습니다. 범위 이름에서 언어까지의 개체 맵이어야 합니다. 제공된 값: {1}", "invalid.path.1": "확장 폴더({2})에 포함할 `contributes.{0}.path`({1})가 필요합니다. 확장이 이식 불가능해질 수 있습니다.", "no-tm-grammar": "이 언어에 대해 등록된 TM 문법이 없습니다." } \ No newline at end of file diff --git a/i18n/ptb/extensions/clojure/package.i18n.json b/i18n/ptb/extensions/clojure/package.i18n.json index 873bc4073f..d146e27fa4 100644 --- a/i18n/ptb/extensions/clojure/package.i18n.json +++ b/i18n/ptb/extensions/clojure/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Clojure" + "displayName": "Noções Básicas Sobre a Linguagem Clojure", + "description": "Fornece realce de sintaxe e correspondência de suporte e dobramento em arquivos Clojure." } \ No newline at end of file diff --git a/i18n/ptb/extensions/coffeescript/package.i18n.json b/i18n/ptb/extensions/coffeescript/package.i18n.json index 05dc61acfc..95fe95501c 100644 --- a/i18n/ptb/extensions/coffeescript/package.i18n.json +++ b/i18n/ptb/extensions/coffeescript/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem CoffeeScript" + "displayName": "Noções Básicas Sobre a Linguagem CoffeeScript", + "description": "Fornece trechos de código, realce de sintaxe, correspondência de suporte e dobramento em arquivos CoffeeScript." } \ No newline at end of file diff --git a/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index 041d293f04..68a9f0dbe3 100644 --- a/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/ptb/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -13,7 +13,7 @@ "rootPath": "caminho do arquivo da área de trabalho (por exemplo, /Usuarios/Desenvolvimento/minhaAreadeTrabalho)", "folderName": "nome do diretório da área de trabalho onde arquivo está localizado (por exemplo, myFolder)", "folderPath": "caminho do arquivo no diretório da área de trabalho onde o arquivo está localizado (por exemplo, /Users/Development/myFolder)", - "appName": "e.g. VS Code", + "appName": "por exemplo VS Code", "dirty": "Um indicador de alteração se o editor ativo foi alterado", "separator": "um separador condicional (' - ') que somente é mostrado quando envolvido por variáveis com valores", "assocLabelFile": "Arquivos com Extensão", diff --git a/i18n/ptb/extensions/configuration-editing/package.i18n.json b/i18n/ptb/extensions/configuration-editing/package.i18n.json index a61a007f7b..10996414b6 100644 --- a/i18n/ptb/extensions/configuration-editing/package.i18n.json +++ b/i18n/ptb/extensions/configuration-editing/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Edição de Configuração" + "displayName": "Edição de Configuração", + "description": "Fornece recursos (IntelliSense avançado, correção automática) em arquivos de configuração, como configurações, inicialização e arquivos de recomendação de extensão." } \ No newline at end of file diff --git a/i18n/ptb/extensions/cpp/package.i18n.json b/i18n/ptb/extensions/cpp/package.i18n.json index 6140181616..08236c7ff8 100644 --- a/i18n/ptb/extensions/cpp/package.i18n.json +++ b/i18n/ptb/extensions/cpp/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem C/C++" + "displayName": "Noções Básicas Sobre a Linguagem C/C++", + "description": "Fornece trechos de código, realce de sintaxe, correspondência de suporte e dobramento em arquivos C/C++." } \ No newline at end of file diff --git a/i18n/ptb/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/ptb/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..d8cc299417 --- /dev/null +++ b/i18n/ptb/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "Servidor de linguagem CSS", + "folding.start": "Início da Região Expansível", + "folding.end": "Fim da Região Expansível" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/css-language-features/package.i18n.json b/i18n/ptb/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..a05cdcfbdc --- /dev/null +++ b/i18n/ptb/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Recursos da Linguagem CSS", + "description": "Fornece suporte de linguagem rico para arquivos CSS, LESS e SCSS.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", + "css.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", + "css.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", + "css.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", + "css.lint.emptyRules.desc": "Não use conjuntos de regra em branco", + "css.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", + "css.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", + "css.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", + "css.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", + "css.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", + "css.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", + "css.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", + "css.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", + "css.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", + "css.lint.unknownProperties.desc": "Propriedade desconhecida.", + "css.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", + "css.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", + "css.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", + "css.trace.server.desc": "Rastrear a comunicação entre o VS Code e o servidor de linguagem CSS.", + "css.validate.title": "Controla a validação CSS and a gravidade dos problemas.", + "css.validate.desc": "Habilita ou desabilita todas as validações", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", + "less.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", + "less.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", + "less.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", + "less.lint.emptyRules.desc": "Não use conjuntos de regra em branco", + "less.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", + "less.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", + "less.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", + "less.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", + "less.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", + "less.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", + "less.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", + "less.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", + "less.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", + "less.lint.unknownProperties.desc": "Propriedade desconhecida.", + "less.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", + "less.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", + "less.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", + "less.validate.title": "Controla MENOS as severidades de validação e problemas.", + "less.validate.desc": "Habilita ou desabilita todas as validações", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", + "scss.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", + "scss.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", + "scss.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", + "scss.lint.emptyRules.desc": "Não use conjuntos de regra em branco", + "scss.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", + "scss.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", + "scss.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", + "scss.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", + "scss.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", + "scss.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", + "scss.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", + "scss.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", + "scss.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", + "scss.lint.unknownProperties.desc": "Propriedade desconhecida.", + "scss.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", + "scss.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", + "scss.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", + "scss.validate.title": "Controla severidades de validação e problemas SCSS.", + "scss.validate.desc": "Habilita ou desabilita todas as validações", + "less.colorDecorators.enable.desc": "Habilita ou desabilita os decoradores de cor", + "scss.colorDecorators.enable.desc": "Habilita ou desabilita os decoradores de cor", + "css.colorDecorators.enable.desc": "Habilita ou desabilita os decoradores de cor", + "css.colorDecorators.enable.deprecationMessage": "A configuração 'css.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'.", + "scss.colorDecorators.enable.deprecationMessage": "A configuração 'scss.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'.", + "less.colorDecorators.enable.deprecationMessage": "A configuração 'less.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/css/package.i18n.json b/i18n/ptb/extensions/css/package.i18n.json index a277a52f81..a156a7ebd9 100644 --- a/i18n/ptb/extensions/css/package.i18n.json +++ b/i18n/ptb/extensions/css/package.i18n.json @@ -6,76 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Recursos da Linguagem CSS", - "description": "Fornece suporte de linguagem rico para arquivos CSS, LESS e SCSS.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", - "css.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", - "css.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", - "css.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", - "css.lint.emptyRules.desc": "Não use conjuntos de regra em branco", - "css.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", - "css.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", - "css.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", - "css.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", - "css.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", - "css.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", - "css.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", - "css.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", - "css.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", - "css.lint.unknownProperties.desc": "Propriedade desconhecida.", - "css.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", - "css.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", - "css.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", - "css.trace.server.desc": "Rastrear a comunicação entre o VS Code e o servidor de linguagem CSS.", - "css.validate.title": "Controla a validação CSS and a gravidade dos problemas.", - "css.validate.desc": "Habilita ou desabilita todas as validações", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", - "less.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", - "less.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", - "less.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", - "less.lint.emptyRules.desc": "Não use conjuntos de regra em branco", - "less.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", - "less.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", - "less.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", - "less.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", - "less.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", - "less.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", - "less.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", - "less.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", - "less.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", - "less.lint.unknownProperties.desc": "Propriedade desconhecida.", - "less.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", - "less.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", - "less.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", - "less.validate.title": "Controla MENOS as severidades de validação e problemas.", - "less.validate.desc": "Habilita ou desabilita todas as validações", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Número inválido de parâmetros", - "scss.lint.boxModel.desc": "Não use largura ou altura ao usar preenchimento ou borda", - "scss.lint.compatibleVendorPrefixes.desc": "Ao usar um prefixo específico de fornecedor, certifique-se de também incluir todas as outras propriedades específicas do fornecedor", - "scss.lint.duplicateProperties.desc": "Não use as definições de estilo duplicadas", - "scss.lint.emptyRules.desc": "Não use conjuntos de regra em branco", - "scss.lint.float.desc": "Evite usar 'float'. Floats levam a CSS frágil, que é fácil de quebrar se um aspecto do layout for alterado.", - "scss.lint.fontFaceProperties.desc": "A regra @font-face deve definir propriedades 'src' e 'font-family'", - "scss.lint.hexColorLength.desc": "Cores hexadecimais devem consistir em três ou seis números hexadecimais", - "scss.lint.idSelector.desc": "Seletores não devem conter IDs, pois essas regras estão firmemente acopladas ao HTML.", - "scss.lint.ieHack.desc": "IE hacks somente são necessários ao dar suporte ao IE7 e mais antigos", - "scss.lint.important.desc": "Evite usar !important. Esta é uma indicação de que a especificidade do CSS inteiro saiu de controle e precisa ser fatorada novamente.", - "scss.lint.importStatement.desc": "Instruções de importação não carregam em paralelo", - "scss.lint.propertyIgnoredDueToDisplay.desc": "Propriedade ignorada devido à exibição. Por exemplo, com 'display: inline', as propriedades width, height, margin-top, margin-bottom e float não têm efeito", - "scss.lint.universalSelector.desc": "O seletor universal (*) é conhecido por ser lento", - "scss.lint.unknownProperties.desc": "Propriedade desconhecida.", - "scss.lint.unknownVendorSpecificProperties.desc": "Propriedade específica do fornecedor desconhecida.", - "scss.lint.vendorPrefix.desc": "Ao usar um prefixo específico do fornecedor, inclua também a propriedade padrão", - "scss.lint.zeroUnits.desc": "Nenhuma unidade para zero é necessária", - "scss.validate.title": "Controla severidades de validação e problemas SCSS.", - "scss.validate.desc": "Habilita ou desabilita todas as validações", - "less.colorDecorators.enable.desc": "Habilita ou desabilita decoradores de cores", - "scss.colorDecorators.enable.desc": "Habilita ou desabilita decoradores de cores", - "css.colorDecorators.enable.desc": "Habilita ou desabilita decoradores de cores", - "css.colorDecorators.enable.deprecationMessage": "A configuração 'css.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'.", - "scss.colorDecorators.enable.deprecationMessage": "A configuração 'scss.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'.", - "less.colorDecorators.enable.deprecationMessage": "A configuração 'less.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'." + "displayName": "Noções Básicas da Linguagem CSS", + "description": "Fornece realce de sintaxe e correspondência de colchetes para arquivos CSS, LESS e SCSS." } \ No newline at end of file diff --git a/i18n/ptb/extensions/emmet/package.i18n.json b/i18n/ptb/extensions/emmet/package.i18n.json index f108b6f476..fc83ad1dc0 100644 --- a/i18n/ptb/extensions/emmet/package.i18n.json +++ b/i18n/ptb/extensions/emmet/package.i18n.json @@ -35,7 +35,7 @@ "emmetExtensionsPath": "Caminho para uma pasta que contém os perfis Emmet e trechos de códigos.'", "emmetShowExpandedAbbreviation": "Mostrar abreviaturas Emmet expandidas como sugestões.\nA opção \"inMarkupAndStylesheetFilesOnly\" aplica-se a html, haml, jade, slim, xml, xsl, css, scss, sass, less e stylus.\nA opção \"always\" se aplica a todas as partes do arquivo independentemente de marcação/css.", "emmetShowAbbreviationSuggestions": "Mostra abreviações Emmet possíveis como sugestões. Não aplicável em folhas de estilo ou quando emmet.showExpandedAbbreviation é definido como \"never\".", - "emmetIncludeLanguages": "Habilita as abreviaturas Emmet em linguagens que não são suportados por padrão. Adicionar um mapeamento aqui entre a linguagem e a linguagem emmet suportada.\n Por exemplo: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", + "emmetIncludeLanguages": "Ative abreviações do Emmet em idiomas que não são suportados por padrão. Adicione um mapeamento aqui entre o idioma e a linguagem suportada emmet.\nPor exemplo: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "Variáveis a serem usadas em trechos de código Emmet", "emmetTriggerExpansionOnTab": "Quando habilitado, abreviações Emmet são expandidas ao pressionar TAB.", "emmetPreferences": "Preferências usadas para modificar o comportamento de algumas ações e resolvedores de Emmet.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Propriedades CSS separadas por vírgula que recebem o prefixo vendor 'webkit' quando utilizado em abreviações do Emmet que iniciam com `-`. Defina como string vazia para sempre evitar o prefixo 'webkit'.", "emmetPreferencesCssMozProperties": "Propriedades CSS separadas por vírgula que recebem o prefixo vendor 'moz' quando utilizado em abreviações do Emmet que iniciam com `-`. Defina como string vazia para sempre evitar o prefixo 'moz'.", "emmetPreferencesCssOProperties": "Propriedades CSS separadas por vírgula que recebem o prefixo vendor 'o' quando utilizado em abreviações do Emmet que iniciam com `-`. Defina como string vazia para sempre evitar o prefixo 'o'.", - "emmetPreferencesCssMsProperties": "Propriedades CSS separadas por vírgula que recebem o prefixo vendor 'ms' quando utilizado em abreviações do Emmet que iniciam com `-`. Defina como string vazia para sempre evitar o prefixo 'ms'." + "emmetPreferencesCssMsProperties": "Propriedades CSS separadas por vírgula que recebem o prefixo vendor 'ms' quando utilizado em abreviações do Emmet que iniciam com `-`. Defina como string vazia para sempre evitar o prefixo 'ms'.", + "emmetPreferencesCssFuzzySearchMinScore": "A pontuação mínima (de 0 a 1) que a abreviação difusa deve alcançar. Os valores mais baixos podem produzir muitas correspondências falso-positivas, valores mais elevados podem reduzir possíveis correspondências.\n", + "emmetOptimizeStylesheetParsing": "Quando definido como false, o arquivo inteiro é analisado para determinar se a posição atual é válida para expandir as abreviações Emmet. Quando definido como true, somente o conteúdo em torno da posição atual em arquivos css / scss / less é analisado." } \ No newline at end of file diff --git a/i18n/ptb/extensions/extension-editing/package.i18n.json b/i18n/ptb/extensions/extension-editing/package.i18n.json index 9ed6e69ff0..5be926c7d7 100644 --- a/i18n/ptb/extensions/extension-editing/package.i18n.json +++ b/i18n/ptb/extensions/extension-editing/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Edição de Arquivo de Pacote" + "displayName": "Edição de Arquivo de Pacote", + "description": "Fornece IntelliSense para os pontos de extensão de código do VS Code e capacidade de linting em arquivos package.json." } \ No newline at end of file diff --git a/i18n/ptb/extensions/fsharp/package.i18n.json b/i18n/ptb/extensions/fsharp/package.i18n.json index 7d630d3877..3d6dee1adb 100644 --- a/i18n/ptb/extensions/fsharp/package.i18n.json +++ b/i18n/ptb/extensions/fsharp/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem F#" + "displayName": "Noções Básicas Sobre a Linguagem F#", + "description": "Fornece trechos de código, realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos F#." } \ No newline at end of file diff --git a/i18n/ptb/extensions/git/out/commands.i18n.json b/i18n/ptb/extensions/git/out/commands.i18n.json index 5ee5b5695b..cfaa264b8b 100644 --- a/i18n/ptb/extensions/git/out/commands.i18n.json +++ b/i18n/ptb/extensions/git/out/commands.i18n.json @@ -11,9 +11,6 @@ "create branch": "$(plus) criar nova ramificação", "repourl": "URL do repositório", "parent": "Diretório pai", - "cancel": "$(sync~spin) Clonando o repositório... Clique para cancelar", - "cancel tooltip": "Cancelar o clone", - "cloning": "Clonando repositório do Git...", "openrepo": "Abrir Repositório", "proposeopen": "Gostaria de abrir o repositório clonado?", "init": "Escolher a pasta de trabalho para inicializar o git repo", @@ -75,7 +72,7 @@ "ok": "OK", "push with tags success": "Envio de rótulos finalizado com sucesso.", "pick remote": "Pegue um remoto para publicar o ramo '{0}':", - "sync is unpredictable": "Esta ação vai fazer push e pull nos commits de e para '{0}'.", + "sync is unpredictable": "Esta ação vai empurrar e puxar commits de e para '{0}/{1}'.", "never again": "OK, Não Mostrar Novamente", "no remotes to publish": "Seu repositório não possui remotos configurados para publicação.", "no changes stash": "Não há nenhuma mudança para esconder.", diff --git a/i18n/ptb/extensions/git/package.i18n.json b/i18n/ptb/extensions/git/package.i18n.json index 9519da62c4..7437aa0be4 100644 --- a/i18n/ptb/extensions/git/package.i18n.json +++ b/i18n/ptb/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Controla se deve mostrar uma ação Abrir Arquivo em linha na visualização de alterações do Git.", "config.inputValidation": "Controla quando exibir validação do campo de mensagem do commit.", "config.detectSubmodules": "Controla se deve detectar automaticamente os sub-módulos do git.", + "config.detectSubmodulesLimit": "Controla o limite de sub-módulos git detectados.", "colors.modified": "Cor para recursos modificados.", "colors.deleted": "Cor para recursos excluídos.", "colors.untracked": "Cor para recursos não controlados.", diff --git a/i18n/ptb/extensions/go/package.i18n.json b/i18n/ptb/extensions/go/package.i18n.json index c0b1461bdf..203f97d160 100644 --- a/i18n/ptb/extensions/go/package.i18n.json +++ b/i18n/ptb/extensions/go/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Go" + "displayName": "Noções Básicas Sobre a Linguagem Go", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Go." } \ No newline at end of file diff --git a/i18n/ptb/extensions/groovy/package.i18n.json b/i18n/ptb/extensions/groovy/package.i18n.json index 840a78de7f..abdb1ff088 100644 --- a/i18n/ptb/extensions/groovy/package.i18n.json +++ b/i18n/ptb/extensions/groovy/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Groovy" + "displayName": "Noções Básicas Sobre a Linguagem Groovy", + "description": "Fornece trechos de código, realce de sintaxe e correspondência de colchetes em arquivos Groovy." } \ No newline at end of file diff --git a/i18n/ptb/extensions/handlebars/package.i18n.json b/i18n/ptb/extensions/handlebars/package.i18n.json index 6f4790883d..2eb0ec888d 100644 --- a/i18n/ptb/extensions/handlebars/package.i18n.json +++ b/i18n/ptb/extensions/handlebars/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Handlebars" + "displayName": "Noções Básicas Sobre a Linguagem Handlebars", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Handlebars." } \ No newline at end of file diff --git a/i18n/ptb/extensions/hlsl/package.i18n.json b/i18n/ptb/extensions/hlsl/package.i18n.json index 0722d53bc7..f00e509b8c 100644 --- a/i18n/ptb/extensions/hlsl/package.i18n.json +++ b/i18n/ptb/extensions/hlsl/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem HLSL" + "displayName": "Noções Básicas Sobre a Linguagem HLSL", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos HLSL." } \ No newline at end of file diff --git a/i18n/ptb/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/ptb/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..6e9a973c17 --- /dev/null +++ b/i18n/ptb/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "Servidor de Linguagem HTML", + "folding.start": "Início da Região Expansível", + "folding.end": "Fim da Região Expansível" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/html-language-features/package.i18n.json b/i18n/ptb/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..a434dbe0f1 --- /dev/null +++ b/i18n/ptb/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Recursos da Linguagem HTML", + "description": "Fornece suporte de linguagem rico para arquivos HTML, Razor e Handlebar.", + "html.format.enable.desc": "Ativar/desativar o formatador HTML padrão", + "html.format.wrapLineLength.desc": "Quantidade máxima de caracteres por linha (0 = desativar).", + "html.format.unformatted.desc": "Lista de tags, separados por vírgula, que não deveria ser reformatada. o padrão é 'nulo' para todas as tags listadas em https://www.w3.org/TR/html5/dom.html#phrasing-content.", + "html.format.contentUnformatted.desc": "Lista de tags, separada por vírgula, onde o conteúdo não deve ser reformatado. o padrão é 'nulo' para a tag 'pré'.", + "html.format.indentInnerHtml.desc": "Indentar secões <head>e <body>.", + "html.format.preserveNewLines.desc": "Se quebras de linha existentes antes de elementos deveriam ser preservadas. Só funciona antes de elementos, não dentro de rótulos ou para texto.", + "html.format.maxPreserveNewLines.desc": "Número máximo de quebras de linha a serem preservadas em um bloco. Use 'null' para ilimitado.", + "html.format.indentHandlebars.desc": "Formatar e indentar {{#foo}} e {{/ foo}}.", + "html.format.endWithNewline.desc": "Finalizar com uma nova linha.", + "html.format.extraLiners.desc": "Lista de rótulos, separados por vírgulas, que deveriam ter uma quebra de linha extra antes deles. 'null' admite o padrão \"head, body, /html\".", + "html.format.wrapAttributes.desc": "Agrupar atributos.", + "html.format.wrapAttributes.auto": "Agrupar atributos somente quando o tamanho da linha é excedido.", + "html.format.wrapAttributes.force": "Agrupar cada atributo exceto o primeiro.", + "html.format.wrapAttributes.forcealign": "Agrupar cada atributo, exceto o primeiro e manter alinhado.", + "html.format.wrapAttributes.forcemultiline": "Agrupar cada atributo.", + "html.suggest.angular1.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos e propriedades do Angular V1.", + "html.suggest.ionic.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos, propriedades e valores Ionic.", + "html.suggest.html5.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos, propriedades e valores HTML5.", + "html.trace.server.desc": "Rastrear a comunicação entre o VS Code e o servidor de linguagem HTML.", + "html.validate.scripts": "Configura se o suporte da linguagem HTML interna valida scripts embutidos.", + "html.validate.styles": "Configura se o suporte da linguagem HTML interna valida estilos embutidos.", + "html.autoClosingTags": "Ativar/desativar o fechamento automático de tags HTML." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/html/package.i18n.json b/i18n/ptb/extensions/html/package.i18n.json index 2e47b51c2c..52c717cdd6 100644 --- a/i18n/ptb/extensions/html/package.i18n.json +++ b/i18n/ptb/extensions/html/package.i18n.json @@ -6,29 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Recursos da Linguagem HTML", - "description": "Fornece suporte de linguagem rico para arquivos HTML, Razor e Handlebar.", - "html.format.enable.desc": "Ativar/desativar o formatador HTML padrão", - "html.format.wrapLineLength.desc": "Quantidade máxima de caracteres por linha (0 = desativar).", - "html.format.unformatted.desc": "Lista de tags, separados por vírgula, que não deveria ser reformatada. o padrão é 'nulo' para todas as tags listadas em https://www.w3.org/TR/html5/dom.html#phrasing-content.", - "html.format.contentUnformatted.desc": "Lista de tags, separada por vírgula, onde o conteúdo não deve ser reformatado. o padrão é 'nulo' para a tag 'pré'.", - "html.format.indentInnerHtml.desc": "Indentar secões <head>e <body>.", - "html.format.preserveNewLines.desc": "Se quebras de linha existentes antes de elementos deveriam ser preservadas. Só funciona antes de elementos, não dentro de rótulos ou para texto.", - "html.format.maxPreserveNewLines.desc": "Número máximo de quebras de linha a serem preservadas em um bloco. Use 'null' para ilimitado.", - "html.format.indentHandlebars.desc": "Formatar e indentar {{#foo}} e {{/ foo}}.", - "html.format.endWithNewline.desc": "Finalizar com uma nova linha.", - "html.format.extraLiners.desc": "Lista de rótulos, separados por vírgulas, que deveriam ter uma quebra de linha extra antes deles. 'null' admite o padrão \"head, body, /html\".", - "html.format.wrapAttributes.desc": "Agrupar atributos.", - "html.format.wrapAttributes.auto": "Agrupar atributos somente quando o tamanho da linha é excedido.", - "html.format.wrapAttributes.force": "Agrupar cada atributo exceto o primeiro.", - "html.format.wrapAttributes.forcealign": "Agrupar cada atributo, exceto o primeiro e manter alinhado.", - "html.format.wrapAttributes.forcemultiline": "Agrupar cada atributo.", - "html.suggest.angular1.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos e propriedades do Angular V1.", - "html.suggest.ionic.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos, propriedades e valores Ionic.", - "html.suggest.html5.desc": "Configura se o suporte da linguagem HTML interna sugere rótulos, propriedades e valores HTML5.", - "html.trace.server.desc": "Rastrear a comunicação entre o VS Code e o servidor de linguagem HTML.", - "html.validate.scripts": "Configura se o suporte da linguagem HTML interna valida scripts embutidos.", - "html.validate.styles": "Configura se o suporte da linguagem HTML interna valida estilos embutidos.", - "html.experimental.syntaxFolding": "Habilita/Desabilita a sintaxe dos marcadores de pastas ativas.", - "html.autoClosingTags": "Ativar/desativar o fechamento automático de tags HTML." + "displayName": "Noções Básicas da Linguagem HTML", + "description": "Fornece realce de sintaxe, correspondência de colchetes e trechos em arquivos HTML." } \ No newline at end of file diff --git a/i18n/ptb/extensions/ini/package.i18n.json b/i18n/ptb/extensions/ini/package.i18n.json index 05fe8cb036..f7e7bd037d 100644 --- a/i18n/ptb/extensions/ini/package.i18n.json +++ b/i18n/ptb/extensions/ini/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Ini" + "displayName": "Noções Básicas Sobre a Linguagem Ini", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Ini." } \ No newline at end of file diff --git a/i18n/ptb/extensions/java/package.i18n.json b/i18n/ptb/extensions/java/package.i18n.json index 570d85b56c..207e95a5b2 100644 --- a/i18n/ptb/extensions/java/package.i18n.json +++ b/i18n/ptb/extensions/java/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Java" + "displayName": "Noções Básicas Sobre a Linguagem Java", + "description": "Fornece trechos de código, realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos Java." } \ No newline at end of file diff --git a/i18n/ptb/extensions/javascript/package.i18n.json b/i18n/ptb/extensions/javascript/package.i18n.json index 21f6cc4b07..582a7ee0ba 100644 --- a/i18n/ptb/extensions/javascript/package.i18n.json +++ b/i18n/ptb/extensions/javascript/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem JavaScript" + "displayName": "Noções Básicas Sobre a Linguagem JavaScript", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos JavaScript." } \ No newline at end of file diff --git a/i18n/ptb/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/ptb/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..3db289491e --- /dev/null +++ b/i18n/ptb/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "Servidor de linguagem JSON" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/json-language-features/package.i18n.json b/i18n/ptb/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..5be341b619 --- /dev/null +++ b/i18n/ptb/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Recursos da Linguagem JSON", + "description": "Fornece suporte de linguagem rico para arquivos JSON.", + "json.schemas.desc": "Esquemas associadas a arquivos de JSON no projeto atual", + "json.schemas.url.desc": "Um URL para um esquema ou um caminho relativo a um esquema no diretório atual", + "json.schemas.fileMatch.desc": "Uma matriz de padrões de arquivos para correspondência ao resolver arquivos JSON para esquemas.", + "json.schemas.fileMatch.item.desc": "Um padrão de arquivos que pode conter '*' para fazer a correspondência ao resolver arquivos JSON para esquemas.", + "json.schemas.schema.desc": "A definição de esquema para o URL dado. O esquema precisa ser fornecido apenas para evitar acessos ao URL do esquema.", + "json.format.enable.desc": "Habilitar/desabilitar o formatador JSON padrão (requer reinicialização)", + "json.tracing.desc": "Loga a comunicação entre o VS Code e o servidor de linguagem JSON.", + "json.colorDecorators.enable.desc": "Habilita ou desabilita os decoradores de cor", + "json.colorDecorators.enable.deprecationMessage": "A configuração 'json.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/json/package.i18n.json b/i18n/ptb/extensions/json/package.i18n.json index 0fc54f17aa..ee39b8276f 100644 --- a/i18n/ptb/extensions/json/package.i18n.json +++ b/i18n/ptb/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Recursos da Linguagem JSON", - "description": "Fornece suporte de linguagem rico para arquivos JSON.", - "json.schemas.desc": "Esquemas associadas a arquivos de JSON no projeto atual", - "json.schemas.url.desc": "Um URL para um esquema ou um caminho relativo a um esquema no diretório atual", - "json.schemas.fileMatch.desc": "Uma matriz de padrões de arquivos para correspondência ao resolver arquivos JSON para esquemas.", - "json.schemas.fileMatch.item.desc": "Um padrão de arquivos que pode conter '*' para fazer a correspondência ao resolver arquivos JSON para esquemas.", - "json.schemas.schema.desc": "A definição de esquema para o URL dado. O esquema precisa ser fornecido apenas para evitar acessos ao URL do esquema.", - "json.format.enable.desc": "Habilitar/desabilitar o formatador JSON padrão (requer reinicialização)", - "json.tracing.desc": "Loga a comunicação entre o VS Code e o servidor de linguagem JSON.", - "json.colorDecorators.enable.desc": "Habilita ou desabilita os decoradores de cor", - "json.colorDecorators.enable.deprecationMessage": "A configuração 'json.colorDecorators.enable' foi descontinuada em favor de 'editor.colorDecorators'.", - "json.experimental.syntaxFolding": "Habilita/Desabilita a sintaxe dos marcadores de pastas ativas." + "displayName": "Noções Básicas da Linguagem JSON", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos JSON." } \ No newline at end of file diff --git a/i18n/ptb/extensions/less/package.i18n.json b/i18n/ptb/extensions/less/package.i18n.json index 8fba3ccce6..f83a843880 100644 --- a/i18n/ptb/extensions/less/package.i18n.json +++ b/i18n/ptb/extensions/less/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Less" + "displayName": "Noções Básicas Sobre a Linguagem Less", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos Less." } \ No newline at end of file diff --git a/i18n/ptb/extensions/log/package.i18n.json b/i18n/ptb/extensions/log/package.i18n.json index b16d35eeb8..0f7313e5de 100644 --- a/i18n/ptb/extensions/log/package.i18n.json +++ b/i18n/ptb/extensions/log/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Log" + "displayName": "Log", + "description": "Fornece realce de sintaxe para arquivos com extensão .log." } \ No newline at end of file diff --git a/i18n/ptb/extensions/lua/package.i18n.json b/i18n/ptb/extensions/lua/package.i18n.json index a1968a09ee..a85199917e 100644 --- a/i18n/ptb/extensions/lua/package.i18n.json +++ b/i18n/ptb/extensions/lua/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Lua" + "displayName": "Noções Básicas Sobre a Linguagem Lua", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Lua." } \ No newline at end of file diff --git a/i18n/ptb/extensions/make/package.i18n.json b/i18n/ptb/extensions/make/package.i18n.json index 1d6c2ec91b..52ddd461b8 100644 --- a/i18n/ptb/extensions/make/package.i18n.json +++ b/i18n/ptb/extensions/make/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Make" + "displayName": "Noções Básicas Sobre a Linguagem Make", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Make." } \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-basics/package.i18n.json b/i18n/ptb/extensions/markdown-basics/package.i18n.json index c7429230ef..4295e53ce2 100644 --- a/i18n/ptb/extensions/markdown-basics/package.i18n.json +++ b/i18n/ptb/extensions/markdown-basics/package.i18n.json @@ -2,8 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." - ] + ], + "displayName": "Noções Básicas Sobre a Linguagem Markdown", + "description": "Fornece trechos de código e destaque de sintaxe para Markdown." } \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/ptb/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..b72e8b907d --- /dev/null +++ b/i18n/ptb/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "Não foi possível carregar o 'markdown.styles': {0}" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/ptb/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..c84ba98d82 --- /dev/null +++ b/i18n/ptb/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Pré-visualização] {0}", + "previewTitle": "Pré-visualização {0}" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/ptb/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..3d1337eab3 --- /dev/null +++ b/i18n/ptb/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Parte do conteúdo foi desativada neste documento", + "preview.securityMessage.title": "Conteúdo potencialmente inseguro foi desativado na visualização de remarcação. Altere a configuração de segurança de visualização do Markdown para permitir conteúdo inseguro ou habilitar scripts", + "preview.securityMessage.label": "Conteúdo do Aviso de Segurança Desativado" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-language-features/out/security.i18n.json b/i18n/ptb/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..ead307bcb9 --- /dev/null +++ b/i18n/ptb/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Estrito", + "strict.description": "Somente carregar conteúdo seguro", + "insecureLocalContent.title": "Permitir conteúdo local inseguro", + "insecureLocalContent.description": "Permitir carregar conteúdo por http servida por localhost", + "insecureContent.title": "Permitir conteúdo inseguro", + "insecureContent.description": "Permitir o carregamento de conteúdo via http", + "disable.title": "Desabilitar", + "disable.description": "Permitir a execução de conteúdo e scripts. Não recomendado", + "moreInfo.title": "Mais informações", + "enableSecurityWarning.title": "Habilitar a visualização de avisos de segurança neste espaço de trabalho", + "disableSecurityWarning.title": "Desabilitar a visualização de avisos de segurança neste espaço de trabalho", + "toggleSecurityWarning.description": "Não afeta o nível de segurança do conteúdo", + "preview.showPreviewSecuritySelector.title": "Selecione as configurações de segurança para pré-visualização de Markdown nesta área de trabalho." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown-language-features/package.i18n.json b/i18n/ptb/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..2a40b86854 --- /dev/null +++ b/i18n/ptb/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Recursos da Linguagem Markdown", + "description": "Fornece suporte à linguagem rica para Markdown.", + "markdown.preview.breaks.desc": "Configura como quebras de linha são processadas na visualização de markdown. Configurando como 'true' cria um <br> para cada nova linha.", + "markdown.preview.linkify": "Habilitar ou desabilitar a conversão de texto URL para links na visualização markdown.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Duplo clique na pré-visualização markdown para alternar para o editor.", + "markdown.preview.fontFamily.desc": "Controla a família de fonte usada na pré-visualização de markdown.", + "markdown.preview.fontSize.desc": "Controla o tamanho da fonte em pixels usado na pré-visualização de markdown.", + "markdown.preview.lineHeight.desc": "Controla a altura de linha usada na pré-visualização de markdown. Este número é relativo ao tamanho de fonte.", + "markdown.preview.markEditorSelection.desc": "Marca a seleção atual do editor na pré-visualização de markdown.", + "markdown.preview.scrollEditorWithPreview.desc": "Quando uma pré-visualização de markdown é rolada, atualiza a exibição do editor.", + "markdown.preview.scrollPreviewWithEditor.desc": "Quando um editor de markdown é rolado, atualiza a exibição da pré-visualização.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Descontinuada] Rola a pré-visualização Markdown para mostrar a linha atualmente selecionada no editor.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Esta configuração foi substituída por 'markdown.preview.scrollPreviewWithEditor' e já não tem qualquer efeito.", + "markdown.preview.title": "Abrir a visualização", + "markdown.previewFrontMatter.dec": "Configura como o frontispicio YAML frente questão devem ser processado na pré-visualização de markdown. 'hide' remove o frontispicio. Caso contrário, o frontispicio é tratado como conteúdo de markdown.", + "markdown.previewSide.title": "Abre pré-visualização ao lado", + "markdown.showLockedPreviewToSide.title": "Abrir pré-visualização travada ao lado", + "markdown.showSource.title": "Exibir Código-Fonte", + "markdown.styles.dec": "Uma lista de URLs ou caminhos locais para folhas de estilo CSS para usar na pré-visualização do markdown. Caminhos relativos são interpretados em relação à pasta aberta no explorer. Se não houver nenhuma pasta aberta, eles são interpretados em relação ao local do arquivo markdown. Todos os ' \\' precisam ser escritos como ' \\ \\ '.", + "markdown.showPreviewSecuritySelector.title": "Alterar configurações de segurança da pré-visualização", + "markdown.trace.desc": "Habilitar log de depuração para a extensão do markdown.", + "markdown.preview.refresh.title": "Atualizar pré-visualização", + "markdown.preview.toggleLock.title": "Alternar Bloqueio de Visualização" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/markdown/out/features/preview.i18n.json b/i18n/ptb/extensions/markdown/out/features/preview.i18n.json index a941c33e93..c84ba98d82 100644 --- a/i18n/ptb/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/ptb/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/ptb/extensions/merge-conflict/package.i18n.json b/i18n/ptb/extensions/merge-conflict/package.i18n.json index 8049c711f7..7c3c080425 100644 --- a/i18n/ptb/extensions/merge-conflict/package.i18n.json +++ b/i18n/ptb/extensions/merge-conflict/package.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "displayName": "Mesclar conflitos", + "description": "Realce e comandos para mesclagem de conflitos inline.", "command.category": "Conflito de Mesclagem", "command.accept.all-current": "Aceitar Todos os Atuais", "command.accept.all-incoming": "Aceitar todas entradas", diff --git a/i18n/ptb/extensions/npm/out/npmView.i18n.json b/i18n/ptb/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/extensions/npm/out/tasks.i18n.json b/i18n/ptb/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/extensions/npm/package.i18n.json b/i18n/ptb/extensions/npm/package.i18n.json index c3743977a6..1e4935decb 100644 --- a/i18n/ptb/extensions/npm/package.i18n.json +++ b/i18n/ptb/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,5 +14,9 @@ "config.npm.exclude": "Configure padrões glob para pastas que devem ser excluídos da detecção automática de script.", "npm.parseError": "Deteção de tarefa NPM: falha ao analisar o arquivo {0}", "taskdef.script": "O script npm para personalizar.", - "taskdef.path": "O caminho para a pasta do arquivo package.json que fornece o script. Pode ser omitido." + "taskdef.path": "O caminho para a pasta do arquivo package.json que fornece o script. Pode ser omitido.", + "command.refresh": "Atualizar", + "command.run": "Executar", + "command.debug": "Depurar", + "command.openScript": "Abrir" } \ No newline at end of file diff --git a/i18n/ptb/extensions/objective-c/package.i18n.json b/i18n/ptb/extensions/objective-c/package.i18n.json index 56ef2cf241..be2418c54c 100644 --- a/i18n/ptb/extensions/objective-c/package.i18n.json +++ b/i18n/ptb/extensions/objective-c/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Objective-C" + "displayName": "Noções Básicas Sobre a Linguagem Objective-C", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Objective-C." } \ No newline at end of file diff --git a/i18n/ptb/extensions/perl/package.i18n.json b/i18n/ptb/extensions/perl/package.i18n.json index 90d5c04386..5b15ff68e4 100644 --- a/i18n/ptb/extensions/perl/package.i18n.json +++ b/i18n/ptb/extensions/perl/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Perl" + "displayName": "Noções Básicas Sobre a Linguagem Perl", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Perl." } \ No newline at end of file diff --git a/i18n/ptb/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/ptb/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..bfb1b796de --- /dev/null +++ b/i18n/ptb/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Você permite {0} (definido como uma configuração do espaço de trabalho) a ser executado para lint de arquivos PHP?", + "php.yes": "Permitir", + "php.no": "Não permitir", + "wrongExecutable": "Não é possível validar {0} pois não é um executável php válido. Use a configuração 'php.validate.executablePath' para configurar o executável do PHP.", + "noExecutable": "Não é possível validar porque nenhum executável PHP está definido. Use a configuração 'php.validate.executablePath' para configurar o executável do PHP.", + "unknownReason": "Falha ao executar o php usando o caminho: {0}. O motivo é desconhecido." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/php-language-features/package.i18n.json b/i18n/ptb/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..7779248205 --- /dev/null +++ b/i18n/ptb/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Configura se as sugestões intrínsecas da linguagem PHP estão habilitadas. O suporte sugere globais e variáveis do PHP.", + "configuration.validate.enable": "Habilita/desabilita a validação interna do PHP.", + "configuration.validate.executablePath": "Aponta para o executável do PHP.", + "configuration.validate.run": "Se o linter é executado ao salvar ou ao digitar.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "Desabilita a validação de executável do PHP (definida como configuração do espaço de trabalho)", + "displayName": "Recursos da linguagem PHP", + "description": "Fornece suporte de linguagem rica para arquivos PHP." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/php/package.i18n.json b/i18n/ptb/extensions/php/package.i18n.json index 79b1487d44..5ebf52a77a 100644 --- a/i18n/ptb/extensions/php/package.i18n.json +++ b/i18n/ptb/extensions/php/package.i18n.json @@ -2,16 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Configura se as sugestões intrínsecas da linguagem PHP estão habilitadas. O suporte sugere globais e variáveis do PHP.", - "configuration.validate.enable": "Habilita/desabilita a validação interna do PHP.", - "configuration.validate.executablePath": "Aponta para o executável do PHP.", - "configuration.validate.run": "Se o linter é executado ao salvar ou ao digitar.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "Desabilita a validação de executável do PHP (definida como configuração do espaço de trabalho)", - "displayName": "Recursos da linguagem PHP" + "displayName": "Noções básicas de linguagem PHP", + "description": "Fornece realce de sintaxe e suporte a correspondência de colchetes para arquivos PHP." } \ No newline at end of file diff --git a/i18n/ptb/extensions/powershell/package.i18n.json b/i18n/ptb/extensions/powershell/package.i18n.json index 9dbfbf4ea1..c8d4a44ac0 100644 --- a/i18n/ptb/extensions/powershell/package.i18n.json +++ b/i18n/ptb/extensions/powershell/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Powershell" + "displayName": "Noções Básicas Sobre a Linguagem Powershell", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos Powershell." } \ No newline at end of file diff --git a/i18n/ptb/extensions/pug/package.i18n.json b/i18n/ptb/extensions/pug/package.i18n.json index 70c16c97bf..a4a9f443d8 100644 --- a/i18n/ptb/extensions/pug/package.i18n.json +++ b/i18n/ptb/extensions/pug/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Pug" + "displayName": "Noções Básicas Sobre a Linguagem Pug", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Pug." } \ No newline at end of file diff --git a/i18n/ptb/extensions/python/package.i18n.json b/i18n/ptb/extensions/python/package.i18n.json index 5e05db6319..ee8ff1f709 100644 --- a/i18n/ptb/extensions/python/package.i18n.json +++ b/i18n/ptb/extensions/python/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Python" + "displayName": "Noções Básicas Sobre a Linguagem Python", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos Python." } \ No newline at end of file diff --git a/i18n/ptb/extensions/r/package.i18n.json b/i18n/ptb/extensions/r/package.i18n.json index a7b3e75ded..d6beac66e3 100644 --- a/i18n/ptb/extensions/r/package.i18n.json +++ b/i18n/ptb/extensions/r/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem R" + "displayName": "Noções Básicas Sobre a Linguagem R", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos R." } \ No newline at end of file diff --git a/i18n/ptb/extensions/razor/package.i18n.json b/i18n/ptb/extensions/razor/package.i18n.json index a650afd145..c79997f74c 100644 --- a/i18n/ptb/extensions/razor/package.i18n.json +++ b/i18n/ptb/extensions/razor/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Razor" + "displayName": "Noções Básicas Sobre a Linguagem Razor", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos Razor." } \ No newline at end of file diff --git a/i18n/ptb/extensions/ruby/package.i18n.json b/i18n/ptb/extensions/ruby/package.i18n.json index 3b2dd1909c..11ef2cb215 100644 --- a/i18n/ptb/extensions/ruby/package.i18n.json +++ b/i18n/ptb/extensions/ruby/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Ruby" + "displayName": "Noções Básicas Sobre a Linguagem Ruby", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Ruby." } \ No newline at end of file diff --git a/i18n/ptb/extensions/rust/package.i18n.json b/i18n/ptb/extensions/rust/package.i18n.json index c0146b1166..7812f5b58c 100644 --- a/i18n/ptb/extensions/rust/package.i18n.json +++ b/i18n/ptb/extensions/rust/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Rust" + "displayName": "Noções Básicas Sobre a Linguagem Rust", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Rust." } \ No newline at end of file diff --git a/i18n/ptb/extensions/scss/package.i18n.json b/i18n/ptb/extensions/scss/package.i18n.json index 9407e1294c..1f732d38a0 100644 --- a/i18n/ptb/extensions/scss/package.i18n.json +++ b/i18n/ptb/extensions/scss/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem SCSS" + "displayName": "Noções Básicas Sobre a Linguagem SCSS", + "description": "Fornece realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos SCSS." } \ No newline at end of file diff --git a/i18n/ptb/extensions/shaderlab/package.i18n.json b/i18n/ptb/extensions/shaderlab/package.i18n.json index 9f240935da..6138101920 100644 --- a/i18n/ptb/extensions/shaderlab/package.i18n.json +++ b/i18n/ptb/extensions/shaderlab/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Shaderlab" + "displayName": "Noções Básicas Sobre a Linguagem Shaderlab", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos Shaderlab." } \ No newline at end of file diff --git a/i18n/ptb/extensions/shellscript/package.i18n.json b/i18n/ptb/extensions/shellscript/package.i18n.json index 74e5a7c0bf..f52f15ed9d 100644 --- a/i18n/ptb/extensions/shellscript/package.i18n.json +++ b/i18n/ptb/extensions/shellscript/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Shell Script" + "displayName": "Noções Básicas Sobre a Linguagem Shell Script", + "description": "Fornece realce de sintaxe e correspondência de colchetes em arquivos de Script de Shell." } \ No newline at end of file diff --git a/i18n/ptb/extensions/sql/package.i18n.json b/i18n/ptb/extensions/sql/package.i18n.json index 3148f032ca..95abedb5aa 100644 --- a/i18n/ptb/extensions/sql/package.i18n.json +++ b/i18n/ptb/extensions/sql/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem SQL" + "displayName": "Noções Básicas Sobre a Linguagem SQL", + "description": "Fornece realce de sintaxe e correspondência de colchetes nos arquivos SQL." } \ No newline at end of file diff --git a/i18n/ptb/extensions/swift/package.i18n.json b/i18n/ptb/extensions/swift/package.i18n.json index 1cb8938a71..aa1efe8c49 100644 --- a/i18n/ptb/extensions/swift/package.i18n.json +++ b/i18n/ptb/extensions/swift/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Swift" + "displayName": "Noções Básicas Sobre a Linguagem Swift", + "description": "Fornece trechos de código, realce de sintaxe e correspondência de colchetes em arquivos Swift." } \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-basics/package.i18n.json b/i18n/ptb/extensions/typescript-basics/package.i18n.json index 956447bf3d..db82cf367c 100644 --- a/i18n/ptb/extensions/typescript-basics/package.i18n.json +++ b/i18n/ptb/extensions/typescript-basics/package.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas da Linguagem TypeScript" + "displayName": "Noções Básicas da Linguagem TypeScript", + "description": "Fornece trechos, realce de sintaxe, correspondência de colchetes e oclusão de código em arquivos TypeScript." } \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/commands.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..43bfcb4644 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Favor abrir uma pasta no VS Code para usar um projeto TypeScript ou JavaScript", + "typescript.projectConfigUnsupportedFile": "Não foi possível determinar o projeto TypeScript ou JavaScript. Tipo de arquivo não suportado", + "typescript.projectConfigCouldNotGetInfo": "Não foi possível determinar o projeto TypeScript ou JavaScript", + "typescript.noTypeScriptProjectConfig": "O arquivo não é parte do projeto TypeScript. Clique [aqui]({0}) para mais informações.", + "typescript.noJavaScriptProjectConfig": "O arquivo não é parte do projeto JavaScript. Clique [aqui]({0}) para mais informações.", + "typescript.configureTsconfigQuickPick": "Configurar tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurar jsconfig.json" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..07ef27a5bc --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Selecione uma ação de código para aplicar", + "acquiringTypingsLabel": "Adquirindo digitações...", + "acquiringTypingsDetail": "Adquirindo definições de digitações para o Intellisense.", + "autoImportLabel": "Importação automática de {0}" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..eafca22f53 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Habilita verificação semântica em um arquivo JavaScript. Deve estar no topo de um arquivo.", + "ts-nocheck": "Desabilita verificação semântica em um arquivo JavaScript. Deve estar no topo de um arquivo.", + "ts-ignore": "Suprime erros de @ts-check na próxima linha de um arquivo." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..c0ccafb600 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 implementação", + "manyImplementationLabel": "{0} implementações", + "implementationsErrorLabel": "Não foi possível determinar implementações" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..0f22e0563e --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "Comentário JSDoc" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..a0dd22d5e1 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Organizar as importações" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..96d00a06bb --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Reparar tudo no arquivo)" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..fd899d9620 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 referência", + "manyReferenceLabel": "{0} referências", + "referenceErrorLabel": "Não foi possível determinar as referências" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..083f9cdd4a --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "compilar - {0}", + "buildAndWatchTscLabel": "monitorar - {0}" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..18d31ac595 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "O caminho {0} não aponta para uma instalação de tsserver válida. Voltando para a versão do TypeScript empacotada.", + "serverCouldNotBeStarted": "Servidor de linguagem TypeScript não pôde ser iniciado. Mensagem de erro é: {0}", + "typescript.openTsServerLog.notSupported": "Logging de TS Server requer TS TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "Logging de TS Server está desligado. Por favor configure 'typescript.tsserver.log' e reinicie o TS Server para habilitar o log", + "typescript.openTsServerLog.enableAndReloadOption": "Habilitar logging e reniciar TS server", + "typescript.openTsServerLog.noLogFile": "O TS Server não iniciou o logging.", + "openTsServerLog.openFileFailedFailed": "Não foi possível abrir o arquivo de log do TS Server", + "serverDiedAfterStart": "O serviço de linguagem TypeScript morreu 5 vezes depois que começou. O serviço não será reiniciado.", + "serverDiedReportIssue": "Reportar Problema", + "serverDied": "O serviço TypeScript morreu inesperadamente 5 vezes nos últimos 5 minutos." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..c723b32adb --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "versão inválida" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..6cf4fd3d7e --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Para habilitar os recursos de linguagem JavaScript/TypeScipt em todo o projeto, excluir pastas com muitos arquivos, como: {0}", + "hintExclude.generic": "Para habilitar os recursos de linguagem JavaScript/TypeScipt em todo o projeto, excluir pastas grandes com arquivos em que você não trabalha.", + "large.label": "Configurar exclusões", + "hintExclude.tooltip": "Para habilitar os recursos de linguagem JavaScript/TypeScipt em todo o projeto, excluir pastas grandes com arquivos em que você não trabalha." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..26560f00bf --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Buscando dados para melhor IntelliSense do TypeScript", + "typesInstallerInitializationFailed.title": "Não foi possível instalar os arquivos de tipagem para recursos da linguagem JavaScript. Por favor, certifique-se que o NPM está instalado ou configure 'typescript.npm' em suas configurações de usuário. Clique [aqui]({0}) para mais informações.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Não mostrar novamente" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..8f3cd072f3 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Use a versão do VS Code", + "useWorkspaceVersionOption": "Use a versão de área de trabalho", + "learnMore": "Saiba Mais", + "selectTsVersion": "Selecione a versão do TypeScript usada para os recursos de linguagem JavaScript e TypeScript" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/ptb/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..ba136d68e8 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Não foi possível carregar a versão do TypeScript neste caminho", + "noBundledServerFound": "Tsserver do VS Code foi eliminado por outro aplicativo como uma ferramenta de detecção de vírus com um comportamento inadequado. Por favor reinstale o VS Code." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript-language-features/package.i18n.json b/i18n/ptb/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..fbb3ef5c00 --- /dev/null +++ b/i18n/ptb/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Recursos da Linguagem TypeScript e JavaScript", + "description": "Fornece suporte à linguagem rica pra JavaScript e TypeScript.", + "typescript.reloadProjects.title": "Recarregar Projeto", + "javascript.reloadProjects.title": "Recarregar Projeto", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Funções completas com a assinatura do parâmetro.", + "typescript.tsdk.desc": "Especifica o caminho da pasta que contém os arquivos tsserver e lib*.d.ts para usar.", + "typescript.disableAutomaticTypeAcquisition": "Desabilita a aquisição automática de tipo. Requer TypeScript > = 2.0.6.", + "typescript.tsserver.log": "Habilita o log do servidor TS para um arquivo. Este log pode ser usado para diagnosticar problemas do servidor de TS. O log pode conter caminhos de arquivo, código-fonte e outras informações potencialmente confidenciais do seu projeto.", + "typescript.tsserver.pluginPaths": "Caminhos adicionais para descobrir os plugins do serviço de linguagem TypeScript. Requer TypeScript > = 2.3.0.", + "typescript.tsserver.pluginPaths.item": "Pode ser um caminho absoluto ou relativo. Caminho relativo será resolvido a partir da pasta da área de trabalho.", + "typescript.tsserver.trace": "Habilita o rastreamento de mensagens enviadas para o servidor de TS. Este rastreamento pode ser usado para diagnosticar problemas do servidor de TS. O rastreamento pode conter caminhos de arquivo, código-fonte e outras informações potencialmente confidenciais do seu projeto.", + "typescript.validate.enable": "Habilita/Desabilita a validação TypeScript.", + "typescript.format.enable": "Habilita/Desabilita o formatador padrão TypeScript.", + "javascript.format.enable": "Habilita/Desabilita o formatador padrão JavaScript.", + "format.insertSpaceAfterCommaDelimiter": "Define o tratamento de espaços após um delimitador vírgula.", + "format.insertSpaceAfterConstructor": "Define a manipulação de espaços após a palavra-chave do construtor. Requer TypeScript > = 2.3.0.", + "format.insertSpaceAfterSemicolonInForStatements": "Define o tratamento de espaços após um ponto e vírgula para um comando.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Define o tratamento de espaços após um operador binário.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Define o tratamento de espaços após palavras-chave em um comando de controle de fluxo.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Define o tratamento de espaços após uma palavra-chave de função para funções anônimas.", + "format.insertSpaceBeforeFunctionParenthesis": "Define a manipulação de espaços antes de parênteses do argumento de função. Requer TypeScript > = 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Define a manipulação de espaços após abrir e antes de fechar parênteses não vazios.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Define a manipulação de espaços após abrir e antes de fechar colchetes não vazios.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Define o espaço de manipulação após a abertura e antes de fechar chaves não vazias. Requer TypeScript >= 2.3.0.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Define a manipulação de espaços após abrir e antes de fechar chaves de cadeias de caracteres de modelos. Requer TypeScript >= 2.0.6.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Define a manipulação de espaços após abrir e antes de fechar chaves de expressões JSX. Requer TypeScript >= 2.0.6.", + "format.insertSpaceAfterTypeAssertion": "Define a manipulação de espaços após asserções de tipo em TypeScript. Requer TypeScript >= 2,4.", + "format.placeOpenBraceOnNewLineForFunctions": "Define-se uma chave de abertura é colocada em uma nova linha para funções ou não.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Define-se uma chave de abertura é colocada em uma nova linha para blocos de controle ou não.", + "javascript.validate.enable": "Habilitar/Desabilitar validação JavaScript.", + "typescript.goToProjectConfig.title": "Ir para a Configuração do Projeto", + "javascript.goToProjectConfig.title": "Ir para a Configuração do Projeto", + "javascript.referencesCodeLens.enabled": "Habilitar/desabilitar referências CodeLens em arquivos JavaScript.", + "typescript.referencesCodeLens.enabled": "Habilitar/desabilitar referências CodeLens em arquivos TypeScript. Requer TypeScript > = 2.0.6.", + "typescript.implementationsCodeLens.enabled": "Habilitar/desabilitar implementações CodeLens. Requer TypeScript > = 2.0.6.", + "typescript.openTsServerLog.title": "Abrir arquivo de log do servidor TS", + "typescript.restartTsServer": "Reiniciar o servidor TS", + "typescript.selectTypeScriptVersion.title": "Selecionar a versão do JavaScript", + "typescript.reportStyleChecksAsWarnings": "Reportar verificações de estilo como avisos", + "jsDocCompletion.enabled": "Habilitar/Desabilitar comentários JSDoc automáticos.", + "javascript.implicitProjectConfig.checkJs": "Habilitar/desabilitar verificação semântica de arquivos JavaScript. Os arquivos existentes jsconfig.json ou tsconfig.json substituem essa configuração. Requer TypeScript > = 2.3.1.", + "typescript.npm": "Especifica o caminho para o executável do NPM usado para Aquisição de Tipo Automático. Requer TypeScript > = 2.3.4.", + "typescript.check.npmIsInstalled": "Verificar se o NPM está instalado para aquisição automática de tipo.", + "javascript.nameSuggestions": "Habilitar/desabilitar incluindo nomes exclusivos do arquivo nas listas de sugestão de JavaScript.", + "typescript.tsc.autoDetect": "Controla a auto deteção das tarefas de tsc. 'off' desativa esse recurso. 'build' só cria tarefas de compilação de execução única. 'watch' cria apenas tarefas de compilação e monitoramento. 'on' cria ambas as tarefas de compilar e monitoramento. Padrão é 'on'.", + "typescript.problemMatchers.tsc.label": "Problemas TypeScript", + "typescript.problemMatchers.tscWatch.label": "Problemas TypeScript (modo observação)", + "typescript.quickSuggestionsForPaths": "Ativar/desativar sugestões rápidas quando estiver digitando um caminho de importação.", + "typescript.locale": "Define a localidade usada para relatar erros TypeScript. Requer TypeScript > = 2.6.0. Padrão 'null' usa a localidade do VS Code para erros TypeScript.", + "javascript.implicitProjectConfig.experimentalDecorators": "Ativar/desativar 'experimentalDecorators' para arquivos JavaScript que não fazem parte de um projeto. Os arquivos existentes de jsconfig.json ou tsconfig.json substituem essa configuração. Requer TypeScript >= 2.3.1.", + "typescript.autoImportSuggestions.enabled": "Ativar/desativar sugestões de importação automática. Requer TypeScript >= 2.6.1", + "typescript.experimental.syntaxFolding": "Habilita/Desabilita a sintaxe dos marcadores de pastas ativas.", + "taskDefinition.tsconfig.description": "O arquivo tsconfig que define a compilação do TS.", + "javascript.suggestionActions.enabled": "Ativar/desativar o diagnóstico de sugestões para arquivos JavaScript no editor. Requer TypeScript > = 2.8", + "typescript.suggestionActions.enabled": "Ativar/desativar o diagnóstico de sugestões para arquivos TypeScript no editor. Requer TypeScript > = 2.8." +} \ No newline at end of file diff --git a/i18n/ptb/extensions/vb/package.i18n.json b/i18n/ptb/extensions/vb/package.i18n.json index 91fc3248f6..eaf6b99fa5 100644 --- a/i18n/ptb/extensions/vb/package.i18n.json +++ b/i18n/ptb/extensions/vb/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem Visual Basic" + "displayName": "Noções Básicas Sobre a Linguagem Visual Basic", + "description": "Fornece trechos, destaque de sintaxe, correspondência de colchetes e oclusão em arquivos do Visual Basic." } \ No newline at end of file diff --git a/i18n/ptb/extensions/xml/package.i18n.json b/i18n/ptb/extensions/xml/package.i18n.json index c53384f376..a5b0890198 100644 --- a/i18n/ptb/extensions/xml/package.i18n.json +++ b/i18n/ptb/extensions/xml/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem XML" + "displayName": "Noções Básicas Sobre a Linguagem XML", + "description": "Fornece realce de sintaxe e suporte a correspondência de colchetes em arquivos XML." } \ No newline at end of file diff --git a/i18n/ptb/extensions/yaml/package.i18n.json b/i18n/ptb/extensions/yaml/package.i18n.json index c3166c20c1..4a6a3b45e4 100644 --- a/i18n/ptb/extensions/yaml/package.i18n.json +++ b/i18n/ptb/extensions/yaml/package.i18n.json @@ -2,9 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Noções Básicas Sobre a Linguagem YAML" + "displayName": "Noções Básicas Sobre a Linguagem YAML", + "description": "Fornece realce de sintaxe e suporte a correspondência de colchetes em arquivos YAML." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/base/node/zip.i18n.json b/i18n/ptb/src/vs/base/node/zip.i18n.json index 102cf6f142..583cfd913f 100644 --- a/i18n/ptb/src/vs/base/node/zip.i18n.json +++ b/i18n/ptb/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Incompleto. Extraído {0} de {1} entradas", "notFound": "{0} não encontrado dentro do zip." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index a5ba8e7ad9..402bfbc5f1 100644 --- a/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -8,14 +8,15 @@ ], "previewOnGitHub": "Pré-visualizar no GitHub", "loadingData": "Carregando dados...", + "rateLimited": "Limite de consulta do GitHub excedido. Por favor, espere.", "similarIssues": "Problemas semelhantes", "open": "Abrir", "closed": "Fechado", - "noResults": "Nenhum resultado encontrado", + "noSimilarIssues": "Nenhum problema semelhante encontrado", "settingsSearchIssue": "Problema na Pesquisa de Configurações", "bugReporter": "Relatório de Bug", - "performanceIssue": "Problema de Performance", "featureRequest": "Solicitação de Recurso", + "performanceIssue": "Problema de Performance", "stepsToReproduce": "Etapas para Reproduzir", "bugDescription": "Nós suportamos Markdown no padrão GitHub. Você poderá editar o seu problema e adicionar capturas de tela quando nós o pré-visualizarmos no GitHub. ", "performanceIssueDesciption": "Nós suportamos Markdown no padrão GitHub. Você poderá editar o seu problema e adicionar capturas de tela quando nós o pré-visualizarmos no GitHub. ", diff --git a/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index c70febfcc6..c780dda977 100644 --- a/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/ptb/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -8,6 +8,12 @@ ], "completeInEnglish": "Por favor, preencha o formulário em inglês.", "issueTypeLabel": "Isso é um", + "issueSourceLabel": "Arquivo na", + "vscode": "Visual Studio Code", + "extension": "Uma extensão", + "disableExtensionsLabelText": "Tente reproduzir o problema depois de {0}. Se o problema só se reproduz quando as extensões são ativas, provavelmente é um problema com uma extensão.", + "disableExtensions": "desabilitando todas as extensões e recarregando a janela", + "chooseExtension": "Extensão", "issueTitleLabel": "Título", "issueTitleRequired": "Por favor, digite um título.", "titleLengthValidation": "O título é muito longo.", @@ -18,9 +24,6 @@ "extensions": "Minhas extensões", "searchedExtensions": "Extensões Pesquisadas", "settingsSearchDetails": "Detalhes da Pesquisa de Configurações", - "yes": "Sim", - "no": "Não", - "disableExtensions": "desabilitando todas as extensões e recarregando a janela", "details": "Por favor informe detalhes.", "loadingData": "Carregando dados..." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/ptb/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..8f468bf0ef --- /dev/null +++ b/i18n/ptb/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "% DE CPU", + "memory": "Memória (MB)", + "pid": "PID", + "name": "Nome", + "killProcess": "Matar processo", + "forceKillProcess": "Matar processo a força" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/code/electron-main/logUploader.i18n.json b/i18n/ptb/src/vs/code/electron-main/logUploader.i18n.json index 094a56fc71..852eb1805b 100644 --- a/i18n/ptb/src/vs/code/electron-main/logUploader.i18n.json +++ b/i18n/ptb/src/vs/code/electron-main/logUploader.i18n.json @@ -9,6 +9,7 @@ "invalidEndpoint": "Destino para envio do log é inválido.", "beginUploading": "Enviando...", "didUploadLogs": "Envio bem-sucedido! ID do arquivo de Log: {0}", + "logUploadPromptHeader": "Você está prestes a fazer o envio de seus logs de sessão para um ponto de extremidade seguro da Microsoft e que apenas membros da equipe Microsoft e do time VS Code podem acessar.", "logUploadPromptBody": "Logs de sessão podem conter informações pessoais como caminhos completos ou conteúdos de arquivos. Por favor revise e elimine seus arquivos de log de sessão aqui: '{0}'", "logUploadPromptBodyDetails": "Ao continuar você confirma que você revisou e eliminou seus arquivos de log de sessão e que você concorda que a Microsoft use eles para depurar o VS Code.", "logUploadPromptAcceptInstructions": "Por favor execute o code com '--upload-logs={0}' para proceder com o upload", diff --git a/i18n/ptb/src/vs/code/electron-main/menus.i18n.json b/i18n/ptb/src/vs/code/electron-main/menus.i18n.json index c6935a1b05..84ea5b779e 100644 --- a/i18n/ptb/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/ptb/src/vs/code/electron-main/menus.i18n.json @@ -93,6 +93,7 @@ "miOpenView": "&&Abrir Visualização...", "miToggleFullScreen": "Alternar &&Tela Inteira", "miToggleZenMode": "Alternar modo Zen", + "miToggleCenteredLayout": "Alternar para Layout Centralizado", "miToggleMenuBar": "Alternar &&Barra de Menus", "miSplitEditor": "Dividir &&editor", "miToggleEditorLayout": "Alternar &&Layout do Grupo de Editor", @@ -160,6 +161,7 @@ "mMergeAllWindows": "Mesclar todas as janelas", "miToggleDevTools": "&&Alternar Ferramentas do Desenvolvedor", "miAccessibilityOptions": "&&Opções de Acessibilidade", + "miOpenProcessExplorerer": "Abrir o &&Process Explorer", "miReportIssue": "Reportar &&Problema", "miWelcome": "&&Bem-vindo", "miInteractivePlayground": "Playground &&Interativo", diff --git a/i18n/ptb/src/vs/code/electron-main/windows.i18n.json b/i18n/ptb/src/vs/code/electron-main/windows.i18n.json index 8d329261a4..f4c36337a9 100644 --- a/i18n/ptb/src/vs/code/electron-main/windows.i18n.json +++ b/i18n/ptb/src/vs/code/electron-main/windows.i18n.json @@ -8,7 +8,7 @@ ], "ok": "OK", "pathNotExistTitle": "O caminho não existe", - "pathNotExistDetail": "O caminho '{0}' não parece mais existir no disco.", + "pathNotExistDetail": "Aparentemente o caminho {0} não existe mais no disco.", "reopen": "&&Reabrir", "wait": "&&Continuar Aguardando", "close": "&&Fechar", diff --git a/i18n/ptb/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/ptb/src/vs/editor/browser/widget/diffReview.i18n.json index 903ad323b8..d8178db811 100644 --- a/i18n/ptb/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/ptb/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,8 @@ "Do not edit this file. It is machine generated." ], "label.close": "Fechar", - "header": "Diferença {0} de {1}: original {2}, {3} linhas, modificado {4}, {5} linhas", + "no_lines": "sem linhas", + "one_line": "1 linha", "blankLine": "branco", "equalLine": "original {0}, modificados {1}: {2}", "insertLine": "+ modificado {0}: {1}", diff --git a/i18n/ptb/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/ptb/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json index 5c040d4c26..1f4dffee76 100644 --- a/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,6 @@ "lineNumbers.on": "Números de linhas são renderizados em números absolutos.", "lineNumbers.relative": "Números de linhas são renderizadas como distância em linhas até a posição do cursor.", "lineNumbers.interval": "Números de linhas são renderizados a cada 10 linhas.", - "lineNumbers": "Controla a exibição dos números de linha. Os valores possíveis são 'on', 'off', 'relative' e 'interval'.", "rulers": "Renderiza réguas verticais após um certo número de caracteres de espaço. Use vários valores para várias réguas. Réguas não serão desenhadas se a matriz estiver vazia", "wordSeparators": "Caracteres que serão usados como separadores de palavras ao fazer navegação relacionada a palavras ou operações", "tabSize": "O número de espaços equivalentes a uma tabulação. Esta configuração é sobreposta com base no conteúdo do arquivo quando `editor.detectIndentation` está ligado.", @@ -28,8 +27,7 @@ "scrollBeyondLastLine": "Controla se o editor rolará além da última linha", "smoothScrolling": "Controla se o editor irá rolar usando uma animação", "minimap.enabled": "Controla se o mini mapa é exibido", - "minimap.side": "Controla o lado onde processar o minimap. Os valores possíveis são 'direita' e 'esquerda'", - "minimap.showSlider": "Controla se o controle deslizante minimap é automaticamente escondido. Os valores possíveis são 'sempre' e 'mouseover'", + "minimap.showSlider": "Controla se o controle deslizante minimap é oculto automaticamente.", "minimap.renderCharacters": "Renderizar os caracteres em uma linha (em oposição a blocos de caracteres)", "minimap.maxColumn": "Limitar o tamanho de um mini-mapa para renderizar no máximo um número determinado de colunas", "find.seedSearchStringFromSelection": "Controla se nós inicializamos a string de pesquisa na Ferramenta de Pesquisa a partir da seleção do editor", @@ -46,6 +44,7 @@ "multiCursorModifier.ctrlCmd": "Mapeia para 'Control' no Windows e Linux e para 'Command' no macOS.", "multiCursorModifier.alt": "Mapeia para 'Alt' em Windows e Linux e para 'Option' em macOS.", "multiCursorModifier": "O modificador a ser usado para adicionar vários cursores com o mouse. `ctrlCmd` mapeia para 'Control' no Windows e Linux e para 'Command' no macOS. Os gestos do mouse Ir para definição e Abrir Link irão adaptar-se de forma que eles não entrem em conflito com o modificador multicursor.", + "multiCursorMergeOverlapping": "Mesclar vários cursores quando eles estão sobrepostos.", "quickSuggestions.strings": "Habilitar sugestões rápidas dentro de strings.", "quickSuggestions.comments": "Habilitar sugestões rápidas dentro de comentários.", "quickSuggestions.other": "Habilitar sugestões rápidas fora de strings e comentários.", @@ -76,7 +75,6 @@ "occurrencesHighlight": "Controla se o editor deve realçar ocorrências de símbolos semânticos.", "overviewRulerLanes": "Controla o número de decorações que podem ser exibidas na mesma posição na régua de visão geral", "overviewRulerBorder": "Controla se deve desenhar uma borda ao redor da régua de visão geral.", - "cursorBlinking": "Controla o estilo de animação do cursor, os valores possíveis são 'blink', 'smooth', 'phase', 'expand' e 'solid'", "mouseWheelZoom": "Alterar o zoom da fonte editor quando utilizada a roda do mouse e pressionando Ctrl", "cursorStyle": "Controla o estilo do cursor, os valores aceitos são 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'", "cursorWidth": "Controla a largura do cursor quando editor.cursorStyle está definido como 'line'", @@ -86,8 +84,10 @@ "renderControlCharacters": "Controla se o editor deve renderizar caracteres de controle", "renderIndentGuides": "Controla se o editor deve renderizar guias de identação", "renderLineHighlight": "Controla como o editor deve renderizar a linha atual, as possibilidades são 'none', 'gutter', 'line' e 'all'.", - "codeLens": "Controla se o editor exibirá a lente de códigos.", "folding": "Controla se o editor tem codigo colapsível hablitado", + "foldingStrategyAuto": "Se disponível, use uma estratégia de dobramento específica de idioma, caso contrário, recua para a estratégia baseada na indentação.", + "foldingStrategyIndentation": "Sempre use a estratégia de dobragem baseada no indentação ", + "foldingStrategy": "Controla a maneira como os intervalos de dobra são calculados. As opções 'auto' usam uma estratégia de dobra específica de idioma, se disponível. 'indentação' força o uso da estratégia de dobragem baseada na indentação.", "showFoldingControls": "Controla se os controles de desdobramento na divisão são ocultas automaticamente.", "matchBrackets": "Realça colchetes correspondente quando um deles estiver selecionado.", "glyphMargin": "Controla se o editor deve renderizar a margem vertical de ícones. A margem vertical de ícones é usada primordialmente na depuração", diff --git a/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json index f7906b9a12..4610e65c95 100644 --- a/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -16,6 +16,7 @@ "editorIndentGuides": "Cor das guias de indentação do editor.", "editorLineNumbers": "Cor dos números de linha do editor.", "editorActiveLineNumber": "Cor dos números de linhas do editor", + "deprecatedEditorActiveLineNumber": "Identificação foi descontinuado. Use 'editorLineNumber.activeForeground' em vez disso.", "editorRuler": "Cor das réguas do editor.", "editorCodeLensForeground": "Cor do primeiro plano das lentes de código do editor", "editorBracketMatchBackground": "Cor de fundo atrás do colchetes correspondentes", @@ -28,7 +29,9 @@ "warningBorder": "Cor da borda das linhas onduladas de aviso no editor.", "infoForeground": "Cor do primeiro plano das linhas de informação no editor.", "infoBorder": "Cor da borda das linhas de informação no editor.", - "overviewRulerRangeHighlight": "Visão geral da cor do marcador da régua para intervalos de destaques.", + "hintForeground": "Cor de primeiro plano de linhas onduladas de dica no editor.", + "hintBorder": "Cor da borda de linhas onduladas de dica no editor.", + "overviewRulerRangeHighlight": "Visão geral da cor do marcador da régua para destaques do intervalo. A cor não deve ser opaca para não esconder decorações subjacentes.", "overviewRuleError": "Visão geral da cor do marcador da régua para erros.", "overviewRuleWarning": "Visão geral da cor do marcador da régua para avisos.", "overviewRuleInfo": "Visão geral da cor do marcador da régua para informações." diff --git a/i18n/ptb/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/ptb/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..11ddcaff63 --- /dev/null +++ b/i18n/ptb/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Mostrar correções ({0})", + "quickFix": "Mostrar correções" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json index b4e4a53238..cfb10fe44e 100644 --- a/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Ir para o Próximo Problema (Erro, Aviso, Informação)", - "markerAction.previous.label": "Ir para o Problema Anterior (Erro, Aviso, Informação)", - "editorMarkerNavigationError": "Ferramenta de marcação de edição apresentando error na cor ", - "editorMarkerNavigationWarning": "Ferramenta de marcação de edição apresentando adventência na cor", - "editorMarkerNavigationInfo": "Cor de informação da ferramenta de navegação do marcador do editor.", - "editorMarkerNavigationBackground": "Cor de fundo da ferramenta de marcação de navegação do editor." + "markerAction.previous.label": "Ir para o Problema Anterior (Erro, Aviso, Informação)" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..e76001982d --- /dev/null +++ b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Ferramenta de marcação de edição apresentando error na cor ", + "editorMarkerNavigationWarning": "Ferramenta de marcação de edição apresentando adventência na cor", + "editorMarkerNavigationInfo": "Cor de informação da ferramenta de navegação do marcador do editor.", + "editorMarkerNavigationBackground": "Cor de fundo da ferramenta de marcação de navegação do editor." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/ptb/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/ptb/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..8b1d4736ce --- /dev/null +++ b/i18n/ptb/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Domingo", + "Monday": "Segunda-feira", + "Tuesday": "Terça-feira", + "Wednesday": "Quarta-feira", + "Thursday": "Quinta-feira", + "Friday": "Sexta-feira", + "Saturday": "Sábado", + "SundayShort": "Dom", + "MondayShort": "Seg", + "TuesdayShort": "Ter", + "WednesdayShort": "Qua", + "ThursdayShort": "Qui", + "FridayShort": "Sex", + "SaturdayShort": "Sáb", + "January": "Janeiro", + "February": "Fevereiro", + "March": "Março", + "April": "Abril", + "May": "Maio", + "June": "Junho", + "July": "Julho", + "August": "Agosto", + "September": "Setembro", + "October": "Outubro", + "November": "Novembro", + "December": "Dezembro", + "JanuaryShort": "Jan", + "FebruaryShort": "Fev", + "MarchShort": "Mar", + "AprilShort": "Abr", + "MayShort": "Mai", + "JuneShort": "Jun", + "JulyShort": "Jul", + "AugustShort": "Ago", + "SeptemberShort": "Set", + "OctoberShort": "Out", + "NovemberShort": "Nov", + "DecemberShort": "Dez" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 0fd29a18bd..034e276072 100644 --- a/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Cor de fundo de um símbolo durante o acesso de escrita, como ao escrever uma variável. A cor não deve ser opaca para não ocultar as decorações subjacentes.", "wordHighlightBorder": "Cor de fundo de um símbolo durante acesso de leitura, como ao ler uma variável.", "wordHighlightStrongBorder": "Cor de fundo de um símbolo durante acesso de escrita, como ao escrever uma variável.", - "overviewRulerWordHighlightForeground": "Visão geral da cor do marcador da régua para destaques de símbolos.", - "overviewRulerWordHighlightStrongForeground": "Visão geral da cor do marcador da régua para gravação de destaques de símbolos.", + "overviewRulerWordHighlightForeground": "Visão geral da cor do marcador da régua para destaques de símbolos. A cor não deve ser opaca para não esconder decorações subjacentes.", + "overviewRulerWordHighlightStrongForeground": "Visão geral da cor do marcador da régua para destaques de símbolos de acesso de escrita. A cor não deve ser opaca para não esconder decorações subjacentes.", "wordHighlight.next.label": "Ir para o próximo símbolo em destaque", "wordHighlight.previous.label": "Ir para o símbolo de destaque anterior" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/ptb/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..f3c382a82f --- /dev/null +++ b/i18n/ptb/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "... 1 arquivo adicional não está mostrado", + "moreFiles": "... {0} arquivos adicionais não estão mostrados" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/ptb/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..4a277edc56 --- /dev/null +++ b/i18n/ptb/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Cancelar" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json b/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json index 1dcb25732f..fa678991d3 100644 --- a/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json @@ -22,16 +22,13 @@ "showVersions": "Exibir versões de extensões instaladas, quando estiver usando --list-extension", "installExtension": "Instala uma extensão.", "uninstallExtension": "Desinstala uma extensão.", - "experimentalApis": "Permite recursos de api propostos para uma extensão.", "verbose": "Imprimir a saída detalhada (Implica -- esperar).", "log": "Nível de log a ser utilizado. O padrão é 'info'. Os valores permitidos são 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Utilização do processo de impressão e informações de diagnóstico.", "performance": "Comece com o 'Desenvolvedor: Desempenho de inicialização' comando habilitado.", "prof-startup": "Rodar o CPU profiler durante a inicialização", "disableExtensions": "Desabilita todas as extensões instaladas.", - "inspect-extensions": "Permite depuração e criação de perfis de extensões. Verifique as ferramentas de desenvolvimento para a conexão uri.", - "inspect-brk-extensions": "Permitir depuração e criação de perfil de extensões com o host de extensão em pausa após o início. Verifique as ferramentas do desenvolvedor para a conexão uri.", - "disableGPU": "Desabilita aceleração de hardware da GPU.", + "disableGPU": "Desabilita aceleração de hardware via GPU.", "uploadLogs": "Envia os registros de atividade da sessão atual para um destino seguro.", "maxMemory": "Tamanho máximo de memória para uma janela (em Mbytes).", "usage": "Uso", diff --git a/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 70b6c3e592..6bd9ed493b 100644 --- a/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,15 +14,15 @@ "errorInstallingDependencies": "Erro ao instalar dependências. {0}", "MarketPlaceDisabled": "Loja não está habilitada.", "removeError": "Erro ao remover a extensão: {0}. por favor, Saia e Inicie o VS Code antes de tentar novamente.", - "Not Market place extension": "Somente Extensões da Loja podem ser reinstaladas", + "Not a Marketplace extension": "Somente Extensões da Loja podem ser reinstaladas", "notFoundCompatible": "Não foi possível instalar '{0}; não existe nenhuma versão compatível com o VSCode '{1}'.", "malicious extension": "Não foi possível instalar a extensão, pois foi relatada como problemática.", "notFoundCompatibleDependency": "Não foi possível instalar porque a extensão dependente '{0}' compatível com a versão atual '{1}' do VS Code não foi encontrada.", "quitCode": "Não foi possível instalar a extensão. Por favor, saia e reinicie o VS Code antes de reinstalar.", "exitCode": "Não foi possível instalar a extensão. Por favor, saia e reinicie o VS Code antes de reinstalar.", "uninstallDependeciesConfirmation": "Gostaria de desinstalar '{0}' somente, ou suas dependências também?", - "uninstallOnly": "Apenas", - "uninstallAll": "Todos", + "uninstallOnly": "Somente Extensão", + "uninstallAll": "Desinstalar Tudo", "uninstallConfirmation": "Tem certeza que deseja desinstalar '{0}'?", "ok": "OK", "singleDependentError": "Não foi possível desinstalar a extensão '{0}'. A extensão '{1}' depende dela.", diff --git a/i18n/ptb/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/ptb/src/vs/platform/extensions/node/extensionValidator.i18n.json index ce5a03782e..94e508a0cc 100644 --- a/i18n/ptb/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/ptb/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Não foi possível analisar o valor de 'engines.vscode' {0}. Por favor, utilize, por exemplo: ^ 0.10.0, ^ 1.2.3, ^ 0.11.0, ^ 0.10.x, etc.", "versionSpecificity1": "Versão especificada em 'engines.vscode' ({0}) não é específica o suficiente. Para versões do vscode anteriores a 1.0.0, por favor defina no mínimo a versão principal e secundária desejada. Por exemplo, ^ 0.10.0, 0.10.x, 0.11.0, etc.", "versionSpecificity2": "Versão especificada em 'engines.vscode' ({0}) não é específica o suficiente. Para as versões do vscode posteriores a 1.0.0, por favor defina no mínimo a versão principal do desejado. Por exemplo, ^ 1.10.0, 1.10.x 1. XX, 2.x.x, etc.", "versionMismatch": "Extensão não é compatível com Code {0}. A extensão requer: {1}." diff --git a/i18n/ptb/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/ptb/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 38292bb368..1ad3b875bb 100644 --- a/i18n/ptb/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/ptb/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "Sua instalação de {0} parece estar corrompida. Favor reinstalar.", "integrity.moreInformation": "Mais informações", - "integrity.dontShowAgain": "Não mostrar novamente", - "integrity.prompt": "Sua instalação de {0} parece estar corrompida. Favor reinstalar." + "integrity.dontShowAgain": "Não mostrar novamente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json b/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json index 10e4b4a477..505689a9a5 100644 --- a/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "O modificador deve ser usado para adicionar um item nas listas e árvores para uma multi-seleção com o mouse (por exemplo, no explorador, editores abertos e exibição scm). 'ctrlCmd' mapeia para 'Control' no Windows e Linux e 'Command' no macOS. Os gestos do mouse 'Aberto ao lado' - se suportado - irá adaptar-se de tal forma que eles não entrem em conflito com o modificador de várias seleções.", "openMode.singleClick": "Abre os itens em um único clique do mouse.", "openMode.doubleClick": "Abre os itens com duplo clique do mouse. ", - "openModeModifier": "Controla como abrir itens em árvores e listas usando o mouse (se suportado). Definido como 'singleClick' para abrir itens com um único clique do mouse e 'doubleClick' para abrir somente através do duplo clique do mouse. Para os pais com filhos em árvores, essa configuração controla se um único clique expande o pai ou um clique duplo. Note que algumas árvores e listas podem optar por ignorar essa configuração, se não for aplicável. " + "openModeModifier": "Controla como abrir itens em árvores e listas usando o mouse (se suportado). Definido como 'singleClick' para abrir itens com um único clique do mouse e 'doubleClick' para abrir somente através do duplo clique do mouse. Para os pais com filhos em árvores, essa configuração controla se um único clique expande o pai ou um clique duplo. Note que algumas árvores e listas podem optar por ignorar essa configuração, se não for aplicável. ", + "horizontalScrolling setting": "Controla se as árvores suportam a rolagem horizontal na área de trabalho." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/markers/common/markers.i18n.json b/i18n/ptb/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..1b82ec1834 --- /dev/null +++ b/i18n/ptb/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Erro", + "sev.warning": "Aviso", + "sev.info": "Informações" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json index af6cc218db..faab052a8a 100644 --- a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,6 @@ "inputPlaceholderForeground": "Cor de primeiro plano da caixa de entrada para o texto de espaço reservado.", "inputValidationInfoBackground": "Cor de fundo de validação de entrada para a severidade de informações.", "inputValidationInfoBorder": "Cor da borda de validação de entrada para a severidade de informações.", - "inputValidationWarningBackground": "Cor de fundo de validação de entrada para avisos.", "inputValidationWarningBorder": "Cor da borda de validação para a severidade de avisos.", "inputValidationErrorBackground": "Cor de fundo de validação de entrada para a severidade do erro.", "inputValidationErrorBorder": "Cor da borda de validação de entrada para a severidade do erro.", @@ -71,10 +70,8 @@ "editorSelectionHighlightBorder": "Cor da borda para regiões com o mesmo conteúdo da seleção.", "editorFindMatch": "Cor da correspondência de pesquisa atual.", "findMatchHighlight": "Cor dos outros termos que correspondem ao da pesquisa. A cor não deve ser opaca para não esconder as decorações subjacentes.", - "findRangeHighlight": "Cor do intervalo limitando a pesquisa. A cor não deve ser opaca para não esconder decorações subjacentes.", "editorFindMatchBorder": "Cor da borda da correspondência de pesquisa atual.", "findMatchHighlightBorder": "Cor da borda dos outros resultados de pesquisa.", - "findRangeHighlightBorder": "Cor da borda do intervalo limitando a pesquisa. A cor não deve ser opaca para não esconder decorações subjacentes.", "hoverHighlight": "Destaque abaixo da palavra para qual um flutuador é mostrado. A cor não deve ser opaca para não esconder decorações subjacentes.", "hoverBackground": "Cor de fundo para o item flutuante do editor", "hoverBorder": "Cor da borda para o item flutuante do editor.", @@ -88,11 +85,10 @@ "mergeIncomingHeaderBackground": "Fundo do cabeçalho entrante em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", "mergeIncomingContentBackground": "Fundo do conteúdo entrante em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", "mergeCommonHeaderBackground": "Fundo comum do cabeçalho antepassado em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", - "mergeCommonContentBackground": "Fundo comum do conteúdo antepassado em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", "mergeBorder": "Cor da borda dos cabeçalhos e separadores estão em conflito de mesclagem em linha.", "overviewRulerCurrentContentForeground": "Cor de fundo de régua de visuaização atual em conflito de mesclagem em linha.", "overviewRulerIncomingContentForeground": "Cor de fundo de régua de visuaização de entrada em conflito de mesclagem em linha.", "overviewRulerCommonContentForeground": "Ancestral comum da cor da régua de visão geral para conflitos de mesclagem inline.", - "overviewRulerFindMatchForeground": "Visão geral da cor do marcador da régua para buscas correspondentes.", - "overviewRulerSelectionHighlightForeground": "Visão geral da cor do marcador da régua para a seleção de destaques" + "overviewRulerFindMatchForeground": "Visão geral da cor do marcador da régua para correspondências de localização. A cor não deve ser opaca para não esconder decorações subjacentes.", + "overviewRulerSelectionHighlightForeground": "Visão geral da cor do marcador da régua para destaques de seleção. A cor não deve ser opaca para não esconder decorações subjacentes." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/ptb/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/ptb/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..7fc8296317 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,17 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "ID exclusivo usado para identificar o contêiner no qual as visualizações podem ser contribuídas usando o ponto de contribuição \"visualizações\"", + "vscode.extension.contributes.views.containers.title": "Sequência legível humana usada para renderizar o contêiner", + "vscode.extension.contributes.viewsContainers": "Contribui com os contêineres de visualizações para o editor", + "test": "Teste", + "requirearray": "visualizações de contêineres devem ser uma matriz", + "requirestring": "a propriedade `{0}` é obrigatória e deve ser do tipo `string`", + "showViewlet": "Mostrar {0}", + "view": "Exibir" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/ptb/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index dcbe12b124..c5690b78fe 100644 --- a/i18n/ptb/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/ptb/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,6 @@ "vscode.extension.contributes.view.name": "O nome legível da visualização. Será mostrado", "vscode.extension.contributes.view.when": "Condição que deve ser verdadeira para mostrar esta visualização", "vscode.extension.contributes.views": "Contribui visualizações ao editor", - "views.explorer": "Visualização do explorador", - "views.debug": "Visualizar Depurador", - "locationId.invalid": "'{0}' não é um local válido de visualização", "duplicateView1": "Não é possível registrar vários modos de exibição com a mesma id '{0}' no local '{1}'", "duplicateView2": "Uma exibição com id '{0}' já está registrada no local '{1}'" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadMessageService.i18n.json b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadMessageService.i18n.json index 128729cc20..03d51e81e8 100644 --- a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadMessageService.i18n.json +++ b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadMessageService.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionSource": "{0} (Extensão)", "defaultSource": "Extensão", "manageExtension": "Gerenciar Extensão", "cancel": "Cancelar", diff --git a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 6a0d4ec54f..c7429230ef 100644 --- a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -5,6 +5,5 @@ "Licensed under the Source EULA. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." - ], - "webview.editor.label": "editor webview" + ] } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/ptb/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..d53bcb288c --- /dev/null +++ b/i18n/ptb/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (Extensão)" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index cf8a3c2e7d..d4203ddd18 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -19,12 +19,14 @@ "close": "Fechar", "closeOthers": "Fechar Outros", "closeRight": "Fechar à direita", + "closeAllSaved": "Fechar Salvos", "closeAll": "Fechar todos", "keepOpen": "Manter aberto", "toggleInlineView": "Alternar para exibição embutida", "showOpenedEditors": "Mostrar editores abertos", "keepEditor": "Manter editor", "closeEditorsInGroup": "Fechar todos editores no grupo", + "closeSavedEditors": "Fechar Editores Salvos em Grupo", "closeOtherEditors": "Fechar outros editores", "closeRightEditors": "Fechar editores à direita" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 83537689b4..953b19a5af 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Focalizar próximo grupo", "openToSide": "Aberto para o lado", "closeEditor": "Fechar editor", + "closeOneEditor": "Fechar", "revertAndCloseActiveEditor": "Reverter e fechar editor", "closeEditorsToTheLeft": "Fechar editores à esquerda ", "closeAllEditors": "Fechar todos editores", diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 81488a1fd7..0fabd0726b 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,6 @@ "screenReaderDetectedExtra": "Se você não estiver usando um leitor de tela, por favor altere a configuração `editor.accessibilitySupport` para \"desligado\".", "disableTabMode": "Desativar o modo de acessibilidade", "gotoLine": "Ir para linha", - "indentation": "Indentação", "selectEncoding": "Selecionar a codificação", "selectEOL": "Selecionar a sequência de fim de linha", "selectLanguageMode": "Selecionar modo de idioma", diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 169e02e43f..b3ec564ba5 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,7 @@ "sizeMB": "{0}MB", "sizeGB": "{0}GB", "sizeTB": "{0}TB", - "largeImageError": "O tamanho do arquivo da imagem é muito grande (>1MB) para exibir no editor. ", "resourceOpenExternalButton": "Abrir imagem usando um programa externo?", - "nativeBinaryError": "O arquivo não pode ser exibido no editor porque é binário, muito grande ou usa uma codificação de texto sem suporte.", "zoom.action.fit.label": "Toda a imagem", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index ae0a29e85e..a068c79084 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Fechar", "araLabelEditorActions": "Ações de editor" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsActions.i18n.json index 78a43045b3..1e5e833c84 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsActions.i18n.json @@ -6,9 +6,11 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "clearNotification": "Limpar Notificação", "clearNotifications": "Limpar Todas as Notificações", "hideNotificationsCenter": "Ocultar Notificações", "expandNotification": "Expandir Notificação", "collapseNotification": "Recolher Notificação", - "configureNotification": "Configurar Notificação" + "configureNotification": "Configurar Notificação", + "copyNotification": "Copiar Texto" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 28b51518d6..746c7cead8 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -6,6 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Nenhuma nova notificação", "notifications": "Notificações", + "notificationsToolbar": "Ações da Central de Notificações", "notificationsList": "Lista de Notificações" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsStatus.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsStatus.i18n.json index 5adb0c591b..ddafd52d11 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsStatus.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/notifications/notificationsStatus.i18n.json @@ -6,5 +6,9 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "hideNotifications": "Ocultar Notificações" + "hideNotifications": "Ocultar Notificações", + "zeroNotifications": "Sem Notificações", + "noNotifications": "Sem Novas Notificações", + "oneNotification": "1 Nova Notificação", + "notifications": "{0} Novas Notificações" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..9d17b283ca --- /dev/null +++ b/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Pressione 'Enter' para confirmar ou 'Esc' para cancelar)", + "inputModeEntry": "Pressione 'Enter' para confirmar o texto digitado ou 'Esc' para cancelar", + "ok": "OK" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/viewlet.i18n.json b/i18n/ptb/src/vs/workbench/browser/viewlet.i18n.json index 0f1e754af4..51eacac5c8 100644 --- a/i18n/ptb/src/vs/workbench/browser/viewlet.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/viewlet.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "compositePart.hideSideBarLabel": "Ocultar a Barra Lateral", "collapse": "Recolher tudo" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json index 79c57c9c35..6fc9a994b2 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json @@ -18,6 +18,7 @@ "zoomReset": "Reinicializar Zoom", "appPerf": "Desempenho de inicialização", "reloadWindow": "Recarregar Janela", + "reloadWindowWithExntesionsDisabled": "Recarregar Janela Com Extensões Desabilitadas", "switchWindowPlaceHolder": "Selecionar uma janela para onde alternar", "current": "Janela Atual", "close": "Fechar Janela", @@ -48,5 +49,6 @@ "moveWindowTabToNewWindow": "Mover a guia da janela para a nova janela", "mergeAllWindowTabs": "Mesclar todas as janelas", "toggleWindowTabsBar": "Alternar a Barra de Guias da Janela", - "about": "Sobre {0}" + "about": "Sobre {0}", + "inspect context keys": "Inspecionar Chaves de Contexto" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json index ab3c4a151e..7c5fda0886 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,13 @@ "windowConfigurationTitle": "Janela", "window.openFilesInNewWindow.on": "Arquivos serão abertos em uma nova janela", "window.openFilesInNewWindow.off": "Arquivos serão abertos em uma nova janela com a pasta de arquivos aberta ou com a última janela ativa.", - "window.openFilesInNewWindow.default": "Os arquivos serão abertos na janela com a pasta de arquivos aberta ou a última janela ativa, a menos que seja aberto através do dock ou do finder (somente macOS)", - "openFilesInNewWindow": "Controla se os arquivos devem ser abertos em uma nova janela\n- padrão: os arquivos serão abertos em uma nova janela com a pasta de arquivos aberta ou na última janela ativa, a menos que seja aberta através do dock ou do finder (apenas macOS)\n- ligado: os arquivos serão abertos em uma nova janela\n- desligado: os arquivos serão abertos em uma janela com a pasta de arquivos aberta ou a última janela ativa\nNote que ainda podem haver casos em que esta configuração será ignorada (por exemplo, quando estiver usando as opções de linha de comando -new-window ou -reuse-window).", + "window.openFilesInNewWindow.defaultMac": "Arquivos serão abertos na janela com a pasta dos arquivos aberta ou a última janela ativa, a menos que tenha sido aberta pelo Dock ou pelo Finder", + "window.openFilesInNewWindow.default": "Arquivos serão abertos em uma nova janela, a menos que escolhidos dentro do aplicativo (por exemplo, através do menu de arquivo)", "window.openFoldersInNewWindow.on": "As pastas serão abertas em uma nova janela", "window.openFoldersInNewWindow.off": "As pastas substituirão a última janela ativa", "window.openFoldersInNewWindow.default": "As pastas serão abertas em uma nova janela, a menos que uma pasta seja selecionada dentro do aplicativo (por exemplo, através do menu Arquivo)", "openFoldersInNewWindow": "Controla se as pastas devem ser abertas em uma nova janela ou substituir a última janela ativa\n- padrão: as pastas serão abertas em uma nova janela, a menos que seja selecionada dentro do aplicativo (por exemplo, através do menu Arquivo)\n- ligado: as pastas serão abertas em uma nova janela\n- desligado: as pastas substituirão a última janela ativa\nNote que ainda podem haver casos em que esta configuração será ignorada (por exemplo, quando estiver usando as opções de linha de comando -new-window ou -reuse-window).", + "window.openWithoutArgumentsInNewWindow.on": "Abrir uma nova janela vazia", "window.reopenFolders.all": "Reabrir todas as janelas.", "window.reopenFolders.folders": "Reabrir todas as pastas. Espaços de trabalho vazios não serão restaurados.", "window.reopenFolders.one": "Reabrir a última janela ativa.", @@ -58,7 +59,6 @@ "restoreWindows": "Controla como as janelas serão reabertas após uma reinicialização. Selecione 'nenhum' para sempre iniciar com uma área de trabalho vazia, 'um' para reabrir a última janela que você trabalhou, 'pastas' para reabrir todas as janelas que tinham pastas abertas ou 'todos' para reabrir todas as janelas da sua última sessão.", "restoreFullscreen": "Controla se uma janela deve ser restaurada em modo de tela cheia se ela foi finalizada em modo de tela cheia.", "zoomLevel": "Ajusta o nível de zoom da janela. O tamanho original é 0 e cada aumento (por exemplo, 1) ou redução (por exemplo, -1) representa um zoom 20% maior ou menor. Você também pode digitar decimais para ajustar o nível de zoom com uma granularidade mais fina.", - "title": "Controla o título de janela baseado no editor ativo. Variáveis são substituídas com base no contexto: \n${activeEditorShort}: o nome do arquivo (por exemplo, MyFile txt)\n${activeEditorMedium}: o caminho do arquivo relativo à pasta da área de trabalho (por exemplo, myFolder/myFile.txt) \n${activeEditorLong}: o caminho completo do arquivo (por exemplo, /Users/Development/myProject/myFolder/myFile.txt) \n${folderName}: nome da pasta de trabalho em que o arquivo está contido (por exemplo, myFolder) \n${folderPath}: caminho do arquivo da pasta de trabalho em que o arquivo está contido (por exemplo, /Users/Development/myFolder) {\n$(rootName}: nome do espaço de trabalho (por exemplo, myFolder ou myWorkspace)\n${rootPath}: caminho do espaço de trabalho (por exemplo, /Users/Development/myWorkspace) \n${appName}: por exemplo, VS Code\n${dirty}: um indicador se o editor ativo foi modificado\n${separator}: um separador condicional (\"-\") que é mostrado apenas quando cercado por variáveis com valores", "window.newWindowDimensions.default": "Abrir novas janelas no centro da tela.", "window.newWindowDimensions.inherit": "Abrir novas janelas com a mesma dimensão da última janela ativa.", "window.newWindowDimensions.maximized": "Abrir novas janelas maximizadas.", @@ -76,6 +76,7 @@ "window.nativeTabs": "Habilita as abas da janela do macOS Sierra. Note que as alterações exigem um reinício completo e que as abas nativas desabilitarão um estilo de barra de título customizado, se configurado.", "zenModeConfigurationTitle": "Modo Zen", "zenMode.fullScreen": "Controla se a ativação do modo Zen também coloca o espaço de trabalho em modo de tela cheia.", + "zenMode.centerLayout": "Controla se ativar o Modo Zen também centraliza o layout.", "zenMode.hideTabs": "Controla se a ativação do modo Zen também oculta as abas do espaço de trabalho.", "zenMode.hideStatusBar": "Controla se a ativação do modo Zen também oculta a barra de status no rodapé do espaço de trabalho.", "zenMode.hideActivityBar": "Controla se a ativação do modo Zen também oculta a barra de atividades à esquerda do espaço de trabalho.", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 4cafc6a1da..1b1684e0d8 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -6,10 +6,16 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Editar o Ponto de Parada...", + "breakpoint": "Ponto de interrupção", + "editBreakpoint": "Editar {0}...", + "removeBreakpoint": "Remover {0}", "functionBreakpointsNotSupported": "Pontos de parada de função não são suportados por este tipo de depuração", "functionBreakpointPlaceholder": "Função de parada", "functionBreakPointInputAriaLabel": "Digitar Ponto de Parada de Função", + "breakpointDisabledHover": "Ponto de interrupção desativado", + "breakpointUnverifieddHover": "Ponto de Parada não Verificado", + "functionBreakpointUnsupported": "Função de ponto de parada não é suportado por este tipo de debug", "breakpointDirtydHover": "Ponto de parada não verificado. O arquivo foi modificado, por favor reinicie a sessão de depuração.", - "conditionalBreakpointUnsupported": "Pontos de parada condicionais não são suportados por esse tipo de depurador" + "conditionalBreakpointUnsupported": "Pontos de parada condicionais não são suportados por esse tipo de depurador", + "hitBreakpointUnsupported": "Pontos de parada condicionais não são suportados por este tipo de debug" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index a3919494f7..2db51d9839 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Desconectar", "continueDebug": "Continuar", "pauseDebug": "Pausa", + "terminateThread": "Finalizar Tarefa", "restartFrame": "Reiniciar o Frame", "removeBreakpoint": "Remover Ponto de Parada", "removeAllBreakpoints": "Remover Todos os Pontos de Parada", - "enableBreakpoint": "Habilitar ponto de Parada", - "disableBreakpoint": "Desativar Ponto de Parada", "enableAllBreakpoints": "Habilitar Todos os Pontos de Parada", "disableAllBreakpoints": "Desabilitar Todos Pontos de Parada", "activateBreakpoints": "Ativar Pontos de Parada", "deactivateBreakpoints": "Desativar Pontos de Parada", "reapplyAllBreakpoints": "Reaplicar Todos os Pontos de Parada", "addFunctionBreakpoint": "Adicionar Ponto de Parada de Função", - "addConditionalBreakpoint": "Adicionar Ponto de Parada Condicional...", - "editConditionalBreakpoint": "Editar o Ponto de Parada...", "setValue": "Definir Valor", "addWatchExpression": "Adicionar Expressão", "editWatchExpression": "Editar expressão", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugCommands.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugCommands.i18n.json index c5d83c70c6..0ecfb5f189 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugCommands.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugCommands.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "noFolderDebugConfig": "Primeiro abra uma pasta para fazer uma configuração de depuração avançada.", + "columnBreakpoint": "Coluna de ponto de parada", "debug": "Depurar", "addColumnBreakpoint": "Adicionar Ponto de Interrupção de Coluna" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugContentProvider.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugContentProvider.i18n.json index 117b5aef0f..924d27e4e8 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugContentProvider.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugContentProvider.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "unable": "Não é possível resolver o recurso sem uma sessão de depuração" + "unable": "Não é possível resolver o recurso sem uma sessão de depuração", + "canNotResolveSource": "Não foi possível resolver o recurso {0}, não há resposta da extensão do debug." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..1770196e49 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetHitCountPlaceholder": "Parar quando contagem de ocorrências condição for alcançada. 'Enter' para aceitar, 'esc' para cancelar.", + "breakpointWidgetExpressionPlaceholder": "Parar quando a expressão for avaliada como true. 'Enter' para aceitar, 'esc' para cancelar.", + "expression": "Expressão", + "hitCount": "Contagem de ocorrências", + "logMessage": "Mensagem de log" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debug.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debug.contribution.i18n.json index adc20895c6..1a2d0c2dbf 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debug.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debug.contribution.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -26,5 +26,6 @@ "always": "Sempre mostrar depurar na barra de status", "onFirstSessionStart": "Mostrar depurar na barra de status somente após a depuração ser iniciada pela primeira vez", "showInStatusBar": "Controla quando a barra de status de depuração deve ser visível", + "openDebug": "Controla se a visualização de depuração deve ser aberta no início da sessão de depuração.", "launch": "Configuração global do lançamento do depurador. Deve ser usado como uma alternativa para o arquivo 'launch.json' que é compartilhado entre os espaços de trabalho" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 3a8eeace4f..00085d53f2 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Por favor, use nomes únicos de configuração.", "app.launch.json.compound.folder": "Nome da pasta em que o composto se encontra.", "app.launch.json.compounds.configurations": "Nomes das configurações que serão iniciadas como parte deste composto.", - "debugNoType": "'type' do adaptador de depuração não pode ser omitido e deve ser do tipo 'string'.", + "debugNoType": "Depurador 'tipo' não pode ser omitido e deve ser do tipo 'string'.", "selectDebug": "Selecione o ambiente", "DebugConfig.failed": "Não é possível criar o arquivo 'launch.json' dentro da pasta '.vscode' ({0}).", "workspace": "espaço de trabalho", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index d20a7e02e4..1a3d1edf6a 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,11 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "breakpoint": "Ponto de interrupção", + "removeBreakpoint": "Remover {0}", + "editBreakpoint": "Editar {0}...", + "disableBreakpoint": "Desabilitar {0}", + "enableBreakpoint": "Habilitar {0}", "removeBreakpoints": "Remover pontos de interrupção", "removeBreakpointOnColumn": "Remover ponto de interrupção na coluna {0}", "removeLineBreakpoint": "Remover ponto de interrupção de linha", @@ -18,5 +23,11 @@ "enableBreakpoints": "Habilitar o ponto de interrupção na coluna {0}", "enableBreakpointOnLine": "Habilitar o ponto de interrupção de linha", "addBreakpoint": "Adicionar ponto de interrupção", + "addConditionalBreakpoint": "Adicionar Ponto de Parada Condicional...", + "message": "Mensagem", + "condition": "condição", + "removeLogPoint": "Remover {0}", + "disableLogPoint": "Desabilitar {0}", + "cancel": "Cancelar", "addConfiguration": "Adicionar Configuração..." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index afa869368d..a35d2e70e9 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -14,9 +14,11 @@ "breakpointRemoved": "Ponto de interrupção removido, linha {0}, arquivo {1}", "compoundMustHaveConfigurations": "Composição deve ter o atributo \"configurations\" definido para iniciar várias configurações.", "noConfigurationNameInWorkspace": "Não foi possível encontrar a configuração de inicialização '{0}' na área de trabalho.", + "multipleConfigurationNamesInWorkspace": "Existem múltiplas configurações de lançamento '{0}' na área de trabalho. Use o nome da pasta para qualificar a configuração.", "noFolderWithName": "Não é possível encontrar a pasta com nome '{0}' para configuração '{1}' no composto '{2}'.", "configMissing": "Configuração '{0}' não tem 'launch.json'.", "launchJsonDoesNotExist": "'launch.json' não existe.", + "debugRequestNotSupported": "Atributo '{0}' tem um valor sem suporte '{1}' na configuração de debug escolhida.", "debugRequesMissing": "Atributo '{0}' está faltando para a configuração de depuração escolhida.", "debugTypeNotSupported": "Tipo de depuração configurado '{0}' não é suportado.", "debugTypeMissing": "Falta a propriedade 'type' para a configuração de lançamento escolhida.", @@ -27,6 +29,6 @@ "showErrors": "Mostrar erros", "noFolderWorkspaceDebugError": "O arquivo ativo não pode ser depurado. Certifique-se de que ele está salvo no disco e que tem uma extensão de depuração instalada para esse tipo de arquivo.", "cancel": "Cancelar", - "DebugTaskNotFound": "Não foi possível encontrar o preLaunchTask '{0}'.", - "taskNotTracked": "Tarefa de pré-lançamento ${0} não pode ser rastreada." + "DebugTaskNotFound": "Não foi possível encontrar a tarefa '{0}'.", + "taskNotTracked": "A tarefa '{0}' não pode ser rastreada." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.i18n.json index e60c064879..1a15549c5b 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copyValue": "Copiar valor", + "copyAsExpression": "Copiar como Expressão", "copy": "Copiar", "copyAll": "Copiar todos", "copyStackTrace": "Copiar Pilha de Chamadas" diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index 1562e3ffed..1f0f6ec005 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Mais Informações", - "unableToLaunchDebugAdapter": "Não é possível executar o adaptador de depuração de '{0}'.", - "unableToLaunchDebugAdapterNoArgs": "Não é possível executar o adaptador de depuração.", - "stoppingDebugAdapter": "{0}. Parando o adaptador de depuração.", "debugAdapterCrash": "Processo do adaptador de depuração foi finalizado inesperadamente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 3e951300c5..4d9a77f3ab 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "Executável do adaptador de depuração '{0}' não existe.", "debugAdapterCannotDetermineExecutable": "Não é possível determinar o executável para o adaptador de depuração '{0}'.", - "launch.config.comment1": "Use o IntelliSense para aprender sobre possíveis atributos.", - "launch.config.comment2": "Passe o mouse para ver as descrições dos atributos existentes.", - "launch.config.comment3": "Para obter mais informações, visite: {0}", - "debugType": "Tipo de configuração.", - "debugTypeNotRecognised": "O tipo de depuração não é reconhecido. Certifique-se de que você tem uma extensão de depuração correspondente instalada e que ela está habilitada.", - "node2NotSupported": "\"node2\" não é mais suportado, use \"node\" ao invés e defina o atributo \"protocol\" para \"inspector\".", - "debugName": "Nome da configuração; aparece no menu drop-down da configuração de lançamento. ", - "debugRequest": "Requer o tipo de configuração. Pode ser \"launch\" ou \"attach\".", - "debugServer": "Somente para o desenvolvimento de extensão de depuração: se uma porta é especificada, o VS Code tenta se conectar a um adaptador de depuração executando em modo de servidor", - "debugPrelaunchTask": "Tarefa para ser executada antes de começar a sessão de depuração.", - "debugWindowsConfiguration": "Atributos de configuração de lançamento específicos do Windows.", - "debugOSXConfiguration": "Atributos de configuração de lançamento específicos do OS X.", - "debugLinuxConfiguration": "Atributos de configuração de lançamento específicos do Linux.", - "deprecatedVariables": "'env.', 'config.' e 'command.' foram descontinuados, use ' env:', ' config:' e ' command:' em vez disso." + "unableToLaunchDebugAdapter": "Não é possível executar o adaptador de depuração de '{0}'.", + "unableToLaunchDebugAdapterNoArgs": "Não é possível executar o adaptador de depuração." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..f91926ec3d --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Use o IntelliSense para aprender sobre possíveis atributos.", + "launch.config.comment2": "Passe o mouse para ver as descrições dos atributos existentes.", + "launch.config.comment3": "Para obter mais informações, visite: {0}", + "debugType": "Tipo de configuração.", + "debugTypeNotRecognised": "O tipo de depuração não é reconhecido. Certifique-se de que você tem uma extensão de depuração correspondente instalada e que ela está habilitada.", + "node2NotSupported": "\"node2\" não é mais suportado, use \"node\" ao invés e defina o atributo \"protocol\" para \"inspector\".", + "debugName": "Nome da configuração; aparece no menu drop-down da configuração de lançamento. ", + "debugRequest": "Requer o tipo de configuração. Pode ser \"launch\" ou \"attach\".", + "debugServer": "Somente para o desenvolvimento de extensão de depuração: se uma porta é especificada, o VS Code tenta se conectar a um adaptador de depuração executando em modo de servidor", + "debugPrelaunchTask": "Tarefa para ser executada antes de começar a sessão de depuração.", + "debugPostDebugTask": "Tarefa para ser executada após término da sessão de debug.", + "debugWindowsConfiguration": "Atributos de configuração de lançamento específicos do Windows.", + "debugOSXConfiguration": "Atributos de configuração de lançamento específicos do OS X.", + "debugLinuxConfiguration": "Atributos de configuração de lançamento específicos do Linux.", + "deprecatedVariables": "'env.', 'config.' e 'command.' foram descontinuados, use ' env:', ' config:' e ' command:' em vez disso." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..0043a4db9f --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "Console VS Code", + "mac.terminal.script.failed": "Script '{0}' falhou com código de saída {1}", + "mac.terminal.type.not.supported": "'{0}' não suportado", + "press.any.key": "Pressione qualquer tecla para continuar...", + "linux.term.failed": "'{0}' falhou com código de saída {1}" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 06fbeaa8cc..86302d2d21 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -2,16 +2,19 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "download": "Baixar manualmente", "installAction": "Instalar", "installing": "Instalando", + "failedToInstall": "Falha ao instalar '{0}'.", "uninstallAction": "Desinstalar", "Uninstalling": "Desinstalando", "updateAction": "Atualizar", "updateTo": "Atualizar para {0}", + "failedToUpdate": "Falha ao atualizar '{0}'.", "ManageExtensionAction.uninstallingTooltip": "Desinstalando", "enableForWorkspaceAction": "Habilitar (Espaço de Trabalho)", "enableGloballyAction": "Habilitar", @@ -54,8 +57,11 @@ "configureWorkspaceFolderRecommendedExtensions": "Configurar as Extensões Recomendadas (Pasta do Espaço de Trabalho)", "malicious tooltip": "Esta extensão foi relatada como problemática.", "malicious": "Malicioso", + "disabled": "Desativado", + "disabled globally": "Desativado", "disableAll": "Desabilitar Todas as Extensões Instaladas", "disableAllWorkspace": "Desabilitar Todas as Extensões Instaladas para este Espaço de Trabalho", + "enableAll": "Ativar Todas as Extensões", "openExtensionsFolder": "Abrir a Pasta de Extensões", "installVSIX": "Instalar do VSIX...", "installFromVSIX": "Instalar a partir do VSIX", diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..f6209cf359 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,57 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Nome da extensão", + "extension id": "Identificador da extensão", + "preview": "Visualizar", + "builtin": "Intrínseco", + "publisher": "Nome do editor", + "install count": "Quantidade de Instalações", + "rating": "Avaliação", + "license": "Licença", + "details": "Detalhes", + "contributions": "Contribuições", + "changelog": "Registro de Alterações", + "dependencies": "Dependências", + "noReadme": "README não disponível.", + "noChangelog": "Registro de Alterações não disponível.", + "noContributions": "Sem Contribuições", + "noDependencies": "Sem Dependências", + "settings": "Configurações ({0})", + "setting name": "Nome", + "description": "Descrição", + "default": "Valor padrão", + "debuggers": "Depuradores ({0})", + "debugger name": "Nome", + "debugger type": "Tipo", + "views": "Visualizações ({0})", + "view id": "ID", + "view name": "Nome", + "view location": "Onde", + "localizations": "Localizações ({0})", + "localizations language id": "Id do Idioma", + "colorThemes": "Temas de cores ({0})", + "iconThemes": "Temas de ícones ({0})", + "colors": "Cores ({0})", + "colorId": "Id", + "defaultDark": "Padrão Escuro", + "defaultLight": "Padrão Claro", + "defaultHC": "Padrão de Alto Contraste", + "JSON Validation": "Validação JSON ({0})", + "schema": "Esquema", + "commands": "Comandos ({0})", + "command name": "Nome", + "keyboard shortcuts": "Atalhos de Teclado", + "menuContexts": "Contextos de Menu", + "languages": "Linguagens ({0})", + "language id": "ID", + "language name": "Nome", + "file extensions": "Extensões de Arquivo", + "grammar": "Gramática", + "snippets": "Trechos" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 5b473117e4..7e61a7b286 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -8,13 +8,15 @@ ], "neverShowAgain": "Não mostrar novamente", "searchMarketplace": "Pesquisar na Loja", + "showLanguagePackExtensions": "A loja possui extensões que podem ajudar na localização do VS Code para o local '{0}'", + "dynamicWorkspaceRecommendation": "Esta extensão pode interessá-lo porque é popular entre os usuários do repositório {0}.", "exeBasedRecommendation": "Esta extensão é recomendada porque você tem {0} instalado.", "fileBasedRecommendation": "Esta extensão é recomendada baseada nos arquivos que você abriu recentemente.", "workspaceRecommendation": "Esta extensão é recomendada pelos usuários da área de trabalho atual.", "reallyRecommended2": "A extensão {0} é recomendada para este tipo de arquivo.", "reallyRecommendedExtensionPack": "O pacote de extensão '{0}' é recomendado para este tipo de arquivo.", - "showRecommendations": "Mostrar Recomendações", "install": "Instalar", + "showRecommendations": "Mostrar Recomendações", "showLanguageExtensions": "A Loja tem extensões que podem ajudar com arquivos '.{0}'", "workspaceRecommended": "Este espaço de trabalho possui recomendações de extensão.", "installAll": "Instalar Tudo", diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index e5a53994bd..4d9a137631 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Desabilitar outros mapeamentos de teclado ({0}) para evitar conflitos entre as combinações de teclas?", "yes": "Sim", - "no": "Não", - "betterMergeDisabled": "A extensão Better Merge agora é intrínseca, a extensão instalada foi desabilitada e pode ser desinstalada.", - "uninstall": "Desinstalar" + "no": "Não" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index 6e9a2c42b9..e9816c51d3 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -12,7 +12,8 @@ "recommendedExtensions": "Recomendado", "otherRecommendedExtensions": "Outras recomendações", "workspaceRecommendedExtensions": "Recomendações do Espaço de Trabalho", - "builtInExtensions": "Incorporado", + "builtInExtensions": "Funcionalidades", + "builtInThemesExtensions": "Temas", "searchExtensions": "Pesquisar Extensões na Loja", "sort by installs": "Ordenar por: Quantidade de Instalações", "sort by rating": "Ordenar por: Avaliação", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index e1128560e1..59f5f276cc 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -24,19 +24,16 @@ "dirtyMessageFolderDelete": "Você está excluindo uma pasta com alterações não salvas em {0} arquivos. Você quer continuar?", "dirtyMessageFileDelete": "Você está excluindo um arquivo com alterações não salvas. Você quer continuar?", "dirtyWarning": "Suas alterações serão perdidas se você não salvá-las.", + "doNotAskAgain": "Não me pergunte novamente", + "irreversible": "Esta ação é irreversível!", + "deletePermanentlyButtonLabel": "&&Excluir Permanentemente", + "retryButtonLabel": "&&Tentar Novamente", "confirmMoveTrashMessageMultiple": "Você tem certeza que deseja excluir os seguintes {0} arquivos?", "confirmMoveTrashMessageFolder": "Tem certeza de que deseja excluir '{0}' e seu conteúdo?", "confirmMoveTrashMessageFile": "Tem certeza de que deseja excluir '{0}'?", - "undoBin": "Você pode restaurar da lixeira.", - "undoTrash": "Você pode restaurar a partir do lixo.", - "doNotAskAgain": "Não me pergunte novamente", "confirmDeleteMessageMultiple": "Você tem certeza que deseja excluir permanentemente os seguintes {0} arquivos?", "confirmDeleteMessageFolder": "Tem certeza de que deseja excluir permanentemente '{0}' e seu conteúdo?", "confirmDeleteMessageFile": "Tem certeza de que deseja excluir permanentemente '{0}'?", - "irreversible": "Esta ação é irreversível!", - "cancel": "Cancelar", - "permDelete": "Excluir permanentemente", - "importFiles": "Importar Arquivos", "confirmOverwrite": "Um arquivo ou pasta com o mesmo nome já existe na pasta de destino. Você quer substituí-lo?", "replaceButtonLabel": "&&Substituir", "fileDeleted": "Arquivo para colar foi excluído ou movido no meio-tempo", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index d3c63c74b8..acedf3f707 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -7,7 +7,6 @@ "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Digite o Nome do arquivo. Pressione Enter para confirmar ou Escape para cancelar.", - "constructedPath": "Criar {0} em **{1}**", "filesExplorerViewerAriaLabel": "{0}, Explorador de Arquivos", "dropFolders": "Você deseja adicionar as pastas ao espaço de trabalho?", "dropFolder": "Você quer adicionar a pasta no espaço de trabalho?", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 77806c0f44..45a7636e78 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "openEditors": "Abrir Editores", + "openEditors": "Editores Abertos", "openEditosrSection": "Abrir Seção de Editores", "dirtyCounter": "{0} não salvos" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..2f618f306d --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Visualização Html" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..478273f97f --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Entrada inválida do editor." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..1bdb832ea4 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Desenvolvedor" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..c9dceaeb49 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "refreshWebviewLabel": "Recarregar Webviews" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index f7dbd73fdb..31f281d25e 100644 --- a/i18n/ptb/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Gostaria de alternar o idioma da interface do usuário do VS Code para {0} e reiniciar?", + "yes": "Sim", + "no": "Não", + "neverAgain": "Não mostrar novamente", "JsonSchema.locale": "O idioma da interface do usuário a ser usada.", "vscode.extension.contributes.localizations": "Contribui localizações ao editor", "vscode.extension.contributes.localizations.languageId": "Id do idioma em que as strings de exibição estão traduzidas.", diff --git a/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..804ed1a7c8 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,23 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Gostaria de alternar o idioma da interface do usuário do VS Code para {0} e reiniciar?", + "yes": "Sim", + "no": "Não", + "neverAgain": "Não mostrar novamente", + "install": "Instalar", + "JsonSchema.locale": "O idioma da interface do usuário a ser usada.", + "vscode.extension.contributes.localizations": "Contribui localizações ao editor", + "vscode.extension.contributes.localizations.languageId": "Id do idioma em que as strings de exibição estão traduzidas.", + "vscode.extension.contributes.localizations.languageName": "Nome do idioma em Inglês.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Nome do idioma no idioma de contribuição.", + "vscode.extension.contributes.localizations.translations": "Lista de traduções associadas ao idioma.", + "vscode.extension.contributes.localizations.translations.id": "Id do VS Code ou Extensão para o qual essa tradução teve contribuição. Id do VS Code é sempre `vscode` e da extensão deve ser no formato `publisherId.extensionName`.", + "vscode.extension.contributes.localizations.translations.id.pattern": "Id deve ser `vscode` ou no formato `publisherId.extensionName` para traduzir VS code ou uma extensão, respectivamente.", + "vscode.extension.contributes.localizations.translations.path": "Um caminho relativo para um arquivo contendo traduções para o idioma." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..3490c90bd2 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Configurar Idioma", + "displayLanguage": "Define o idioma de exibição do VSCode.", + "doc": "Veja {0} para obter uma lista dos idiomas suportados.", + "restart": "Modificar o valor requer reinicialização do VSCode.", + "fail.createSettings": "Não foi possível criar '{0}' ({1})." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..ed26614c2c --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Copiar", + "copyMessage": "Copiar Mensagem" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..8323facb36 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Total {0} Problemas" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..4af5054b91 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Problemas", + "tooltip.1": "1 problema neste arquivo", + "tooltip.N": "{0} problemas neste arquivo" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..4c8c7d44a4 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Exibir", + "problems.view.toggle.label": "Esconder/exibir Problemas (Erros, Avisos, Infos)", + "problems.view.focus.label": "Focar Problemas (Erros, Avisos, Infos)", + "problems.panel.configuration.title": "Visualização de Problemas", + "problems.panel.configuration.autoreveal": "Controla se a visaulização de problemas evela os arquivos automaticamente ao abri-los", + "markers.panel.title.problems": "Problemas", + "markers.panel.aria.label.problems.tree": "Problemas agrupados por arquivos", + "markers.panel.no.problems.build": "Nenhum problema foi detectado na área de trabalho até agora.", + "markers.panel.action.filter": "Problemas de Filtro", + "markers.panel.filter.ariaLabel": "Problemas de Filtro", + "markers.panel.filter.errors": "erros", + "markers.panel.filter.warnings": "avisos", + "markers.panel.filter.infos": "informações", + "markers.panel.single.error.label": "1 Erro", + "markers.panel.multiple.errors.label": "{0} Erros", + "markers.panel.single.warning.label": "1 Aviso", + "markers.panel.multiple.warnings.label": "{0} Avisos", + "markers.panel.single.info.label": "1 Informação", + "markers.panel.multiple.infos.label": "{0} Informações", + "markers.panel.single.unknown.label": "1 Desconhecido", + "markers.panel.multiple.unknowns.label": "{0} Desconhecidos", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} com {1} problemas", + "errors.warnings.show.label": "Mostrar Erros e Avisos" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/output/browser/outputActions.i18n.json index fa7fc88d28..2bf61fcbfe 100644 --- a/i18n/ptb/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Alternar Saída", "clearOutput": "Limpar saída", "toggleOutputScrollLock": "Alternar Scroll Lock de Saída", - "switchToOutput.label": "Mudar para Saída" + "switchToOutput.label": "Mudar para Saída", + "openInLogViewer": "Abrir Arquivo de Log" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 7ea3aff3df..0975e05f7b 100644 --- a/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Saída", "logViewer": "Visualizador do Log", "viewCategory": "Exibir", - "clearOutput.label": "Limpar saída" + "clearOutput.label": "Limpar saída", + "openActiveLogOutputFile": "Exibir: Abrir Arquivo de Saída de Log Ativo" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 806042a3da..758c2cd2fb 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Atalhos de Teclado", "SearchKeybindings.AriaLabel": "Pesquisar keybindings", "SearchKeybindings.Placeholder": "Pesquisar keybindings", "sortByPrecedene": "Ordenar por precedência", diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 50c7b55dd6..1428484d33 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Abrir Configurações Padrão Raw", + "openSettings": "Abrir configurações", "openGlobalSettings": "Abra as Configurações de Usuário", "openGlobalKeybindings": "Abrir Atalhos de Teclado", "openGlobalKeybindingsFile": "Abrir Arquivo de Atalhos de Teclado", diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 4c03228269..0dace3b610 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Configurações Padrão", "SearchSettingsWidget.AriaLabel": "Configurações de Pesquisa", "SearchSettingsWidget.Placeholder": "Configurações de Pesquisa", "noSettingsFound": "Nenhum resultado", diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 2353c8b642..be7834d241 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Mostrar Extensão \"{0}\"", "editTtile": "Editar", "replaceDefaultValue": "Substituir nas Configurações", - "copyDefaultValue": "Copiar para Configurações", - "unsupportedPHPExecutablePathSetting": "Essa configuração deve ser uma Configuração de Usuário. Para configurar o PHP para o espaço de trabalho, abra um arquivo PHP e clique em 'Caminho do PHP' na barra de status.", - "unsupportedWorkspaceSetting": "Essa configuração deve ser uma Configuração de Usuário.", - "unsupportedWorkbenchSetting": "Essa configuração não pode ser aplicada agora. Será aplicada quando você abrir esta pasta diretamente.", - "unsupportedWorkbenchSettingDevMode": "Essa configuração não pode ser aplicada agora. Ela será aplicada se você definir o seu escopo como 'recurso' durante o registo, ou quando você abrir esta pasta diretamente." + "copyDefaultValue": "Copiar para Configurações" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index e5bdc88825..9d1e905197 100644 --- a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -9,7 +9,8 @@ "scm providers": "Provedores de Controle de Código Fonte", "hideRepository": "Ocultar", "installAdditionalSCMProviders": "Instalar provedores de SCM adicionais...", - "no open repo": "Não existem provedores controle de código fonte ativos.", + "no open repo": "Não existem provedores de controle de código fonte ativos.", "source control": "Controle de código-fonte", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Ocultar" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 6628b45deb..b42c6c03c5 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Mostrar a Busca Anterior Excluindo Padrões", "nextSearchTerm": "Mostrar o Próximo Termo de Pesquisa", "previousSearchTerm": "Mostrar Termo de Pesquisa Anterior", - "showSearchViewlet": "Mostrar Busca", "findInFiles": "Localizar nos Arquivos", "replaceInFiles": "Substituir nos Arquivos", "RefreshAction.label": "Atualizar", diff --git a/i18n/ptb/src/vs/workbench/parts/search/browser/searchView.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/browser/searchView.i18n.json index 213f9b1949..f87abccd93 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/browser/searchView.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/browser/searchView.i18n.json @@ -30,6 +30,7 @@ "removeAll.occurrences.files.confirmation.message": "Substituir {0} ocorrências nos arquivos {1} com '{2}'?", "replaceAll.occurrences.files.confirmation.message": "Substituir {0} ocorrências nos arquivos {1}?", "treeAriaLabel": "Resultados da Pesquisa", + "searchPathNotFoundError": "Caminho de pesquisa não encontrado: {0}", "searchMaxResultsWarning": "O conjunto de resultados contém apenas um subconjunto de todas as correspondências. Seja mais específico na sua pesquisa para diminuir o número de resultados.", "searchCanceled": "Pesquisa foi cancelada antes de qualquer resultado ser encontrado - ", "noResultsIncludesExcludes": "Nenhum resultado encontrado em '{0}' excluindo '{1}' - ", diff --git a/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 0409b4e23a..56d88e0a64 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Pesquisar", + "copyMatchLabel": "Copiar", + "copyPathLabel": "Copiar Caminho", + "copyAllLabel": "Copiar todos", "findInFolder": "Procurar na pasta...", "findInWorkspace": "Procurar no Espaço de Trabalho...", "showTriggerActions": "Ir para Símbolo no Espaço de Trabalho...", "name": "Pesquisar", - "search": "Pesquisar", "showSearchViewl": "Mostrar Busca", "view": "Exibir", "findInFiles": "Localizar nos Arquivos", @@ -24,5 +27,6 @@ "useIgnoreFiles": "Controla se utiliza arquivos .gitignore e .ignore por padrão ao fazer pesquisas de arquivos.", "search.quickOpen.includeSymbols": "Configurar para incluir resultados de uma pesquisa símbolo global nos resultados do arquivo para Abertura Rápida.", "search.followSymlinks": "Controla quando seguir symlinks ao realizar uma busca.", - "search.smartCase": "Faz pesquisas do tipo case-insensitive se o termo for totalmente minúsculo, caso contrário, faz pesquisas do tipo case-sensitive." + "search.smartCase": "Faz pesquisas do tipo case-insensitive se o termo for totalmente minúsculo, caso contrário, faz pesquisas do tipo case-sensitive.", + "search.globalFindClipboard": "Controla se a visualização de busca deve ler ou modificar a área de transferência de busca compartilhada no macOS" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 4c2904ecab..9d5e4cdd4f 100644 --- a/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Nos ajude a melhorar o nosso apoio para {0}", "takeShortSurvey": "Responda a uma pesquisa curta", "remindLater": "Lembrar mais tarde", - "neverAgain": "Não mostrar novamente", - "helpUs": "Nos ajude a melhorar o nosso apoio para {0}" + "neverAgain": "Não mostrar novamente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index bfc5d2fe58..1c16684732 100644 --- a/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Você deseja responder a uma pequena pesquisa?", "takeSurvey": "Responder a pesquisa", "remindLater": "Lembrar mais tarde", - "neverAgain": "Não mostrar novamente", - "surveyQuestion": "Você deseja responder a uma pequena pesquisa?" + "neverAgain": "Não mostrar novamente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 16d7bd5a02..cd00bb4f95 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "O tipo de tarefa atual", "TaskDefinition.properties": "Propriedades adicionais do tipo de tarefa", "TaskTypeConfiguration.noType": "A propriedade necessária 'taskType' está faltando na configuração do tipo de tarefa ", "TaskDefinitionExtPoint": "Contribui com os tipos de tarefa" diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 49a7c7f8fe..073777f3ab 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,8 @@ "JsonSchema.tasks.group.none": "Atribui a tarefa para nenhum grupo", "JsonSchema.tasks.group": "Define a que grupo de execução desta tarefa pertence. Suporta \"build\" para adicioná-lo ao grupo de compilação e \"test\" para adicioná-lo ao grupo de teste.", "JsonSchema.tasks.type": "Define quando a tarefa é executada como um processo ou como um comando dentro do shell.", + "JsonSchema.command": "O comando a ser executado. Pode ser um programa externo ou um comando shell.", + "JsonSchema.tasks.args": "Argumentos passados para o comando quando esta tarefa é invocada.", "JsonSchema.tasks.label": "O rótulo da tarefa na interface do usuário.", "JsonSchema.version": "O número da versão do config.", "JsonSchema.tasks.identifier": "Um identificador definido pelo usuário para fazer referência a tarefa em launch.json ou uma cláusula dependsOn.", diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index 49b0d87e0f..9926f718ac 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -8,9 +8,12 @@ ], "tasksCategory": "Tarefas", "ConfigureTaskRunnerAction.label": "Configurar a tarefa", + "totalErrors": "{0} Erros", + "totalWarnings": "{0} Avisos", + "totalInfos": "{0} Informações", "problems": "Problemas", "building": "Compilando...", - "manyMarkers": "99+", + "manyProblems": "10K+", "runningTasks": "Mostrar tarefas em execução", "tasks": "Tarefas", "TaskSystem.noHotSwap": "Alterar o mecanismo de execução da tarefa com uma tarefa ativa executando exige que a janela seja recarregada", @@ -28,8 +31,8 @@ "selectProblemMatcher": "Selecione quais tipos de erros e avisos da saída da tarefa você deseja verificar", "customizeParseErrors": "A configuração da tarefa atual tem erros. Por favor, corrija os erros primeiro antes de personalizar uma tarefa.", "moreThanOneBuildTask": "Há muitas tarefas de compilação definidas em tasks.json. Executando a primeira.\n", - "TaskSystem.activeSame.background": "A tarefa '{0}' já está ativa e executando em segundo plano. Para finalizá-la use 'Finalizar Tarefa' no menu Tarefas.", - "TaskSystem.activeSame.noBackground": "A tarefa '{0}' já está ativa. Para finalizá-la use 'Finalizar Tarefa' no menu Tarefas.", + "terminateTask": "Finalizar Tarefa", + "restartTask": "Reiniciar Tarefa", "TaskSystem.active": "Já existe uma tarefa sendo executada. Finalize-a antes de executar outra tarefa.", "TaskSystem.restartFailed": "Falha ao finalizar e reiniciar a tarefa {0}", "TaskService.noConfiguration": "Erro: A deteção de tarefa {0} não contribuiu para uma tarefa para a seguinte configuração: {1} a tarefa será ignorada.\n", diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index fe30402e7d..22fb4c3fec 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,5 @@ "TerminalTaskSystem.terminalName": "Tarefa - {0}", "closeTerminal": "Pressione qualquer tecla para fechar o terminal.", "reuseTerminal": "Terminal será reutilizado pelas tarefas, pressione qualquer tecla para fechar.", - "TerminalTaskSystem": "Não é possível executar um comando shell em uma unidade UNC.", "unkownProblemMatcher": "Problem matcher {0} não pode ser resolvido. O matcher será ignorado" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/ptb/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index d4d06f19fb..3bbfa2ba48 100644 --- a/i18n/ptb/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -17,7 +17,6 @@ "ConfigurationParser.missingRequiredProperty": "Erro: a configuração de tarefa '{0}' não possui a propriedade obrigatória '{1}'. A configuração de tarefa será ignorada.", "ConfigurationParser.notCustom": "Erro: tarefas não está declarada como uma tarefa personalizada. A configuração será ignorada.\n{0}\n", "ConfigurationParser.noTaskName": "Erro: uma tarefa deve fornecer uma propriedade de rótulo. A tarefa será ignorada.\n{0}\n", - "taskConfiguration.shellArgs": "Aviso: a tarefa '{0}' é um comando shell e um dos seus argumentos pode ter espaços sem escape. Para garantir a citação da linha de comando correta por favor mesclar args ao comando.", "taskConfiguration.noCommandOrDependsOn": "Erro: a tarefa '{0}' não especifica nem um comando nem uma propriedade dependsOn. A tarefa será ignorada. Sua definição é: \n{1}", "taskConfiguration.noCommand": "Erro: a tarefa '{0}' não define um comando. A tarefa será ignorada. Sua definição é: {1}", "TaskParse.noOsSpecificGlobalTasks": "Tarefa versão 2.0.0 não oferece suporte a tarefas globais específicas do sistema operacional. Converta-as em uma tarefa com um comando específico do sistema operacional. Tarefas afetadas:\n{0}" diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..eb2f070aaf --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "A cor de fundo do terminal, isso permite colorir o terminal com uma cor diferente do painel.", + "terminal.foreground": "A cor de primeiro plano do terminal.", + "terminal.ansiColor": "'{0}' cor ANSI no terminal." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 5e68eea965..b5347d0795 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -35,6 +35,7 @@ "terminal.integrated.env.linux": "Objeto com variáveis de ambiente que serão adicionadas ao VS Code e utilizadas pelo terminal no Linux", "terminal.integrated.env.windows": "Objeto com variáveis de ambiente que serão adicionadas ao VS Code e utilizadas pelo terminal no Windows", "terminal.integrated.showExitAlert": "Mostrar alerta 'O processo terminal foi encerrado com código de saída' quando o código de saída é diferente de zero.", + "terminal.integrated.experimentalRestore": "Se deseja restaurar sessões de terminal para a área de trabalho automaticamente quando executa o VS Code. Essa é uma configuração experimental; Ele pode ser falho e pode mudar no futuro.", "terminalCategory": "Terminal", "viewCategory": "Exibir" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 3e3ccd862d..701314f988 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -22,6 +22,7 @@ "workbench.action.terminal.newInActiveWorkspace": "Criar Novo Terminal Integrado (No Espaço de Trabalho Ativo)", "workbench.action.terminal.split": "Dividir Terminal", "workbench.action.terminal.focusPreviousPane": "Focar Painel Anterior", + "workbench.action.terminal.focusNextPane": "Foco próximo painel", "workbench.action.terminal.resizePaneLeft": "Redimensionar Painel à Esquerda", "workbench.action.terminal.resizePaneRight": "Redimensionar Painel à Direita", "workbench.action.terminal.resizePaneUp": "Redimensionar Painel Superior", diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 840621a3f7..84d160cb7a 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,8 +7,8 @@ "Do not edit this file. It is machine generated." ], "copy": "Copiar", + "split": "Dividir", "paste": "Colar", "selectAll": "Selecionar Tudo", - "clear": "Limpar", - "split": "Dividir" + "clear": "Limpar" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index d0107f458c..e9ff1ac2f4 100644 --- a/i18n/ptb/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Esta área de trabalho contém configurações que só podem ser definidas nas configurações do usuário. ({0}). Clique [aqui]({1}) para mais informações.", "openWorkspaceSettings": "Abrir as configurações do espaço de trabalho", - "dontShowAgain": "Não mostrar novamente", - "unsupportedWorkspaceSettings": "Esta área de trabalho contém configurações que só podem ser definidas nas configurações do usuário. ({0}). Clique [aqui]({1}) para mais informações." + "dontShowAgain": "Não mostrar novamente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..4290f9be0b --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Notas da Versão: {0}", + "unassigned": "Não atribuído" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json index d0454fc31e..0fbbffad2c 100644 --- a/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Mais tarde", - "unassigned": "Não atribuído", "releaseNotes": "Notas da Versão", "showReleaseNotes": "Mostrar Notas da Versão", "read the release notes": "Bem-vindo a {0} v{1}! Gostaria de ler as Notas da Versão?", @@ -17,13 +15,14 @@ "updateIsReady": "Nova atualização de {0} disponível.", "noUpdatesAvailable": "Não há nenhuma atualização disponível no momento.", "ok": "OK", - "download now": "Baixar agora", "thereIsUpdateAvailable": "Há uma atualização disponível.", - "installUpdate": "Instalar Atualização", + "download now": "Baixar agora", + "later": "Mais tarde", "updateAvailable": "Há uma atualização disponível: {0} {1}", + "installUpdate": "Instalar Atualização", "updateInstalling": "{0} {1} está sendo instalado no plano de fundo, nós te avisaremos quando estiver pronto.", + "updateAvailableAfterRestart": "Reinicie o {0} para aplicar a atualização mais recente.", "updateNow": "Atualizar Agora", - "updateAvailableAfterRestart": "{0} será atualizado após reiniciar.", "commandPalette": "Paleta de comandos...", "settings": "Configurações", "keyboardShortcuts": "Atalhos de Teclado", diff --git a/i18n/ptb/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..549c77a453 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "Abrir URL", + "developer": "Desenvolvedor" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..0169a44311 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "editor webview", + "developer": "Desenvolvedor" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..3533d84f53 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Abrir Ferramentas de Desenvolvedor do Webview", + "refreshWebviewLabel": "Recarregar Webviews" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/ptb/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..69d43b6f30 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Ajude a melhorar o VS Code permitindo que a Microsoft colete dados de uso. Leia nossa [política de privacidade]({0}) e saiba como [optar por sair]({1}).", + "telemetryOptOut.optInNotice": "Ajude a melhorar o VS Code permitindo que a Microsoft colete dados de uso. Leia nossa [política de privacidade]({0}) e saiba como [optar por isso]({1}).", + "telemetryOptOut.readMore": "Ler Mais" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index a29cbda1ba..f05cb923fc 100644 --- a/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,6 @@ "welcomePage.installExtensionPacks": "Ferramentas e linguagens", "welcomePage.installExtensionPacksDescription": "Instalar o suporte para {0} e {1}", "welcomePage.moreExtensions": "mais", - "welcomePage.installKeymapDescription": "Instalar atalhos de teclado", - "welcomePage.installKeymapExtension": "Instalar os atalhos de teclado de {0} e {1}", "welcomePage.others": "outros", "welcomePage.colorTheme": "Tema de cores", "welcomePage.colorThemeDescription": "Fazer o editor e seu código parecer do jeito que você gosta", diff --git a/i18n/ptb/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/ptb/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index ec4b0ed3be..d75d039b28 100644 --- a/i18n/ptb/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -16,6 +16,11 @@ "errorInvalidWorkspaceTarget": "Não é possível gravar as configurações do espaço de trabalho porque {0} não oferece suporte para o escopo de espaço de trabalho em um espaço de trabalho de múltiplas pastas.", "errorInvalidFolderTarget": "Não é possível gravar as configurações da pasta porque nenhum recurso é fornecido.", "errorNoWorkspaceOpened": "Não é possível gravar {0} porque nenhum espaço de trabalho está aberto. Por favor, abra um espaço de trabalho primeiro e tente novamente.", + "errorInvalidTaskConfiguration": "Não é possível escrever no arquivo de configuração de tarefas. Por favor, abra o arquivo para corrigir erros/avisos e tente novamente.", + "errorInvalidLaunchConfiguration": "Não é possível escrever no arquivo de configuração de lançamento. Por favor, abra o arquivo para corrigir erros/avisos e tente novamente.", + "errorInvalidConfiguration": "Não é possível escrever nas configurações do usuário. Por favor, abra as configurações do usuário para corrigir erros/avisos e tente novamente.", + "errorInvalidConfigurationWorkspace": "Não é possível escrever nas configurações do espaço de trabalho. Por favor, abra as configurações do espaço de trabalho para corrigir erros/avisos no arquivo e tente novamente.", + "errorInvalidConfigurationFolder": "Não é possível escrever nas configurações de pasta. Por favor, abra as configurações da pasta '{0}' para corrigir erros/avisos e tente novamente.", "userTarget": "Configurações de Usuário", "workspaceTarget": "Configurações de Espaço de Trabalho", "folderTarget": "Configurações de pasta" diff --git a/i18n/ptb/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/ptb/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..54475988a3 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedWindowSetting": "Essa configuração não pode ser aplicada agora. Será aplicada quando você abrir esta pasta diretamente." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/ptb/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/ptb/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/ptb/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..7fbcc0a808 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Sim", + "cancelButton": "Cancelar" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/ptb/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 46b35e3985..ff686dfa06 100644 --- a/i18n/ptb/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -30,5 +30,6 @@ "vscode.extension.badges.description": "Descrição do emblema.", "vscode.extension.extensionDependencies": "Dependências para outras extensões. O identificador de uma extensão sempre é ${publisher}. ${nome}. Por exemplo: vscode.csharp.", "vscode.extension.scripts.prepublish": "Script a ser executado antes do pacote ser publicado como uma extensão VS Code.", + "vscode.extension.scripts.uninstall": "Desinstala o hook para a extensão do VS Code. O script que é executado quando a extensão é completamente desinstalada do VS Code e é quando o VS Code é reiniciado (desligar e iniciar) depois que a extensão for desinstalada. Somente scripts Node são suportados.", "vscode.extension.icon": "O caminho para um ícone de 128x128 pixels." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/ptb/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index c5211d2d49..7d22c9b410 100644 --- a/i18n/ptb/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -8,7 +8,6 @@ ], "extensionHostProcess.crash": "Host de extensão foi encerrado inesperadamente.", "extensionHostProcess.unresponsiveCrash": "Host de extensão encerrado porque não foi responsivo.", - "devTools": "Ferramentas do Desenvolvedor", "restart": "Reinicie o Host de extensão", "overwritingExtension": "Sobrescrevendo extensão {0} por {1}.", "extensionUnderDevelopment": "Carregando extensão de desenvolvimento em {0}", diff --git a/i18n/ptb/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/ptb/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 946c6bd730..14d740ae0f 100644 --- a/i18n/ptb/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -6,11 +6,22 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "O Microsoft .NET Framework 4.5 é necessário. Por favor siga o link para instalá-lo.", "installNet": "Baixar o .NET Framework 4.5", "neverShowAgain": "Não mostrar novamente", - "netVersionError": "O Microsoft .NET Framework 4.5 é necessário. Por favor siga o link para instalá-lo.", "learnMore": "Instruções", - "enospcError": "{0} está ficando sem tratamento de arquivos. Por favor, siga o link de instruções para resolver esse problema.", + "fileInvalidPath": "Recurso de arquivo inválido ({0})", + "fileIsDirectoryError": "Arquivo é um diretório", + "fileNotModifiedError": "Arquivo não modificado desde", + "fileTooLargeError": "Arquivo muito grande para abrir", + "fileNotFoundError": "Arquivo não encontrado ({0})", + "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto", + "filePermission": "Permissão negada ao escrever no arquivo ({0})", + "fileExists": "Arquivo a ser criado já existe ({0})", + "fileModifiedError": "Arquivo Modificado Desde", + "fileReadOnlyError": "Arquivo é Somente Leitura", + "fileMoveConflict": "Não é possível mover/copiar. Arquivo já existe no destino.", + "unableToMoveCopyError": "Não é possível mover/copiar. Arquivo poderia substituir a pasta em que está contida.", "binFailed": "Falha ao mover '{0}' para a lixeira", "trashFailed": "Falha em mover '{0}' para a lixeira" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 4763dc038e..c3fdd817f2 100644 --- a/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,9 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Arquivo não encontrado ({0})", "fileIsDirectoryError": "Arquivo é um diretório", "fileNotModifiedError": "Arquivo não modificado desde", - "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto" + "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto", + "fileMoveConflict": "Não é possível mover/copiar. Arquivo já existe no destino." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json index ca6d6c7c51..01e4ca397b 100644 --- a/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json @@ -9,7 +9,6 @@ "fileInvalidPath": "Recurso de arquivo inválido ({0})", "fileIsDirectoryError": "Arquivo é um diretório", "fileNotModifiedError": "Arquivo não modificado desde", - "fileTooLargeForHeapError": "O tamanho do arquivo excede o limite de memória da janela. Por favor, tente executar o codigo -max-memory=NOVOVALOR", "fileTooLargeError": "Arquivo muito grande para abrir", "fileNotFoundError": "Arquivo não encontrado ({0})", "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto", diff --git a/i18n/ptb/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/ptb/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..08d17ebd20 100644 --- a/i18n/ptb/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Cancelar" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/ptb/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index e7e189169c..c5c90b4e69 100644 --- a/i18n/ptb/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Nome do escopo Textmate usado pelo arquivo tmLanguage.", "vscode.extension.contributes.grammars.path": "Caminho para o arquivo tmLanguage. O caminho é relativo a pasta da extensão e geralmente começa com './syntaxes/'.", "vscode.extension.contributes.grammars.embeddedLanguages": "Um mapeamento no nome do escopo para o Id da linguagem se esta gramática contenha linguagens embutidas.", + "vscode.extension.contributes.grammars.tokenTypes": "Um mapa do nome do escopo para tipos de token.", "vscode.extension.contributes.grammars.injectTo": "Lista de nomes de escopos de linguagem aos quais esta gramática é injetada." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json index 8783e181f2..f0b6187231 100644 --- a/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/themes/common/colorThemeSchema.i18n.json @@ -9,6 +9,8 @@ "schema.token.settings": "Cores e estilos para o token.", "schema.token.foreground": "Cor do primeiro plano para o token.", "schema.token.background.warning": "Atualmente as cores de fundo do token não são suportadas.", + "schema.token.fontStyle": "Estilo da fonte da regra: 'itálico', 'negrito', 'sublinhado' ou uma combinação. Cadeia de caracteres vazia desfaz configurações herdadas.", + "schema.fontStyle.error": "O estilo da fonte deve ser 'itálico', 'negrito' ou 'sublinhado', uma combinação ou cadeia de caracteres vazia.", "schema.token.fontStyle.none": "Nenhum (limpar estilo herdado)", "schema.properties.name": "Descrição da regra.", "schema.properties.scope": "Seletor de escopo que bate com esta regra.", diff --git a/i18n/rus/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/rus/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..01ee817cdc --- /dev/null +++ b/i18n/rus/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "Языковой сервер CSS", + "folding.start": "Начало сворачиваемого региона", + "folding.end": "Окончание сворачиваемого региона" +} \ No newline at end of file diff --git a/i18n/rus/extensions/css-language-features/package.i18n.json b/i18n/rus/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..13b750e8b5 --- /dev/null +++ b/i18n/rus/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Возможности языка CSS", + "description": "Предоставляет широкую поддержку языка для файлов CSS, LESS и SCSS.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", + "css.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", + "css.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", + "css.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", + "css.lint.emptyRules.desc": "Не использовать пустые наборы правил", + "css.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", + "css.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", + "css.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", + "css.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", + "css.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", + "css.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", + "css.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", + "css.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", + "css.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", + "css.lint.unknownProperties.desc": "Неизвестное свойство.", + "css.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", + "css.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", + "css.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", + "css.trace.server.desc": "Отслеживает обмен данными между VS Code и языковым сервером CSS.", + "css.validate.title": "Управляет проверкой CSS и серьезностью проблем.", + "css.validate.desc": "Включает или отключает все проверки", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", + "less.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", + "less.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", + "less.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", + "less.lint.emptyRules.desc": "Не использовать пустые наборы правил", + "less.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", + "less.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", + "less.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", + "less.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", + "less.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", + "less.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", + "less.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", + "less.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", + "less.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", + "less.lint.unknownProperties.desc": "Неизвестное свойство.", + "less.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", + "less.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", + "less.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", + "less.validate.title": "Управляет проверкой LESS и уровнями серьезности проблем. ", + "less.validate.desc": "Включает или отключает все проверки", + "scss.title": "SCSS (SASS)", + "scss.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", + "scss.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", + "scss.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", + "scss.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", + "scss.lint.emptyRules.desc": "Не использовать пустые наборы правил", + "scss.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", + "scss.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", + "scss.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", + "scss.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", + "scss.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", + "scss.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", + "scss.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", + "scss.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", + "scss.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", + "scss.lint.unknownProperties.desc": "Неизвестное свойство.", + "scss.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", + "scss.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", + "scss.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", + "scss.validate.title": "Управляет проверкой SCSS и уровнями серьезности проблем.", + "scss.validate.desc": "Включает или отключает все проверки", + "less.colorDecorators.enable.desc": "Включает или отключает декораторы цвета", + "scss.colorDecorators.enable.desc": "Включает или отключает декораторы цвета", + "css.colorDecorators.enable.desc": "Включает или отключает декораторы цвета", + "css.colorDecorators.enable.deprecationMessage": "Параметр \"css.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". ", + "scss.colorDecorators.enable.deprecationMessage": "Параметр \"scss.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". ", + "less.colorDecorators.enable.deprecationMessage": "Параметр \"less.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". " +} \ No newline at end of file diff --git a/i18n/rus/extensions/css/package.i18n.json b/i18n/rus/extensions/css/package.i18n.json index ba6da59a64..f94884afe4 100644 --- a/i18n/rus/extensions/css/package.i18n.json +++ b/i18n/rus/extensions/css/package.i18n.json @@ -2,80 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Возможности языка CSS", - "description": "Предоставляет широкую поддержку языка для файлов CSS, LESS и SCSS.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", - "css.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", - "css.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", - "css.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", - "css.lint.emptyRules.desc": "Не использовать пустые наборы правил", - "css.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", - "css.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", - "css.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", - "css.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", - "css.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", - "css.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", - "css.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", - "css.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", - "css.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", - "css.lint.unknownProperties.desc": "Неизвестное свойство.", - "css.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", - "css.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", - "css.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", - "css.trace.server.desc": "Отслеживает обмен данными между VS Code и языковым сервером CSS.", - "css.validate.title": "Управляет проверкой CSS и серьезностью проблем.", - "css.validate.desc": "Включает или отключает все проверки", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", - "less.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", - "less.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", - "less.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", - "less.lint.emptyRules.desc": "Не использовать пустые наборы правил", - "less.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", - "less.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", - "less.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", - "less.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", - "less.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", - "less.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", - "less.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", - "less.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", - "less.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", - "less.lint.unknownProperties.desc": "Неизвестное свойство.", - "less.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", - "less.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", - "less.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", - "less.validate.title": "Управляет проверкой LESS и уровнями серьезности проблем. ", - "less.validate.desc": "Включает или отключает все проверки", - "scss.title": "SCSS (SASS)", - "scss.lint.argumentsInColorFunction.desc": "Недопустимое число параметров", - "scss.lint.boxModel.desc": "Не использовать ширину или высоту при использовании поля или границы", - "scss.lint.compatibleVendorPrefixes.desc": "При использовании зависящего от поставщика префикса также указывайте все остальные свойства поставщика", - "scss.lint.duplicateProperties.desc": "Не использовать дублирующиеся определения стилей", - "scss.lint.emptyRules.desc": "Не использовать пустые наборы правил", - "scss.lint.float.desc": "Старайтесь не использовать \"float\". Из-за элементов \"float\" работа кода CSS может легко нарушиться, если изменить один из аспектов разметки.", - "scss.lint.fontFaceProperties.desc": "Правило @font-face должно определять свойства src и font-family", - "scss.lint.hexColorLength.desc": "Цвета в шестнадцатеричном формате должны содержать три или шесть шестнадцатеричных чисел", - "scss.lint.idSelector.desc": "Селекторы не должны содержать идентификаторов, потому что эти правила слишком тесно связаны с HTML.", - "scss.lint.ieHack.desc": "Полезные советы для Internet Explorer требуются только при поддержке Internet Explorer 7 и более ранних версий", - "scss.lint.important.desc": "Старайтесь не использовать !important, так как это признак того, что весь код CSS стал неуправляемым и его надо переработать.", - "scss.lint.importStatement.desc": "Операторы импорта не загружаются параллельно", - "scss.lint.propertyIgnoredDueToDisplay.desc": "Свойство проигнорировано из-за значения свойства display. Например, при \"display: inline\" свойства width, height, margin-top, margin-bottom и float не работают", - "scss.lint.universalSelector.desc": "Универсальный селектор (*) работает медленно", - "scss.lint.unknownProperties.desc": "Неизвестное свойство.", - "scss.lint.unknownVendorSpecificProperties.desc": "Неизвестное свойство поставщика.", - "scss.lint.vendorPrefix.desc": "При использовании зависящего от поставщика префикса также указывайте стандартное свойство", - "scss.lint.zeroUnits.desc": "Для нуля не требуется единица измерения", - "scss.validate.title": "Управляет проверкой SCSS и уровнями серьезности проблем.", - "scss.validate.desc": "Включает или отключает все проверки", - "less.colorDecorators.enable.desc": "Включает или отключает декораторы цвета.", - "scss.colorDecorators.enable.desc": "Включает или отключает декораторы цвета.", - "css.colorDecorators.enable.desc": "Включает или отключает декораторы цвета.", - "css.colorDecorators.enable.deprecationMessage": "Параметр \"css.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". ", - "scss.colorDecorators.enable.deprecationMessage": "Параметр \"scss.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". ", - "less.colorDecorators.enable.deprecationMessage": "Параметр \"less.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\". " + "displayName": "Основы языка CSS", + "description": "Предоставляет подсветку синтаксиса и выделение парных скобок в файлах CSS, LESS и SCSS." } \ No newline at end of file diff --git a/i18n/rus/extensions/emmet/package.i18n.json b/i18n/rus/extensions/emmet/package.i18n.json index 8d7e130391..e8a08df3b0 100644 --- a/i18n/rus/extensions/emmet/package.i18n.json +++ b/i18n/rus/extensions/emmet/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "Разделенный запятыми список свойств CSS, которые получают префикс разработчика \"webkit\" при использовании в сокращениях Emmet, которые начинаются с \"-\". Чтобы префикс \"webkit\" никогда не подставлялся, установите в качестве этого параметра пустое значение.", "emmetPreferencesCssMozProperties": "Разделенный запятыми список свойств CSS, которые получают префикс разработчика \"moz\" при использовании в сокращениях Emmet, которые начинаются с \"-\". Чтобы префикс \"moz\" никогда не подставлялся, установите в качестве этого параметра пустое значение. ", "emmetPreferencesCssOProperties": "Разделенный запятыми список свойств CSS, которые получают префикс разработчика \"o\" при использовании в сокращениях Emmet, которые начинаются с \"-\". Чтобы префикс \"o\" никогда не подставлялся, установите в качестве этого параметра пустое значение. ", - "emmetPreferencesCssMsProperties": "Разделенный запятыми список свойств CSS, которые получают префикс разработчика \"ms\" при использовании в сокращениях Emmet, которые начинаются с \"-\". Чтобы префикс \"ms\" никогда не подставлялся, установите в качестве этого параметра пустое значение. " + "emmetPreferencesCssMsProperties": "Разделенный запятыми список свойств CSS, которые получают префикс разработчика \"ms\" при использовании в сокращениях Emmet, которые начинаются с \"-\". Чтобы префикс \"ms\" никогда не подставлялся, установите в качестве этого параметра пустое значение. ", + "emmetPreferencesCssFuzzySearchMinScore": "Минимальное количество очков для нечеткого соответствия сокращения (от 0 до 1). При указании более низких значений возможно увеличение числа ложных срабатываний, при указании более высоких значений - уменьшение числа возможных соответствий.", + "emmetOptimizeStylesheetParsing": "Если значение равно false, весь файл анализируется для определения, является ли текущая позиция допустимой для расширения сокращений Emmet. Когда присвоено значение true, только содержимое вокруг текущей позиции в файлах css/scss/less подвергается синтаксическому анализу." } \ No newline at end of file diff --git a/i18n/rus/extensions/git/out/commands.i18n.json b/i18n/rus/extensions/git/out/commands.i18n.json index 608951b9dc..61e4db033a 100644 --- a/i18n/rus/extensions/git/out/commands.i18n.json +++ b/i18n/rus/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Создать новую ветвь", "repourl": "URL-адрес репозитория", "parent": "Родительский каталог", - "cancel": "$(sync~spin) Клонирование репозитория... Чтобы отменить эту операцию, щелкните здесь", - "cancel tooltip": "Отменить клонирование", - "cloning": "Клонируется репозиторий Git...", + "cloning": "Клонирование репозитория Git \"{0}\"...", "openrepo": "Открыть репозиторий", "proposeopen": "Вы хотите открыть клонированный репозиторий?", "init": "Выберите папку рабочей области для инициализации репозитория Git", @@ -75,7 +73,7 @@ "ok": "ОК", "push with tags success": "Файлы с тегами успешно отправлены.", "pick remote": "Выберите удаленный сервер, на котором нужно опубликовать ветвь \"{0}\":", - "sync is unpredictable": "Это действие отправляет фиксации в \"{0}\" и извлекает их из этого расположения.", + "sync is unpredictable": "Это действие отправляет фиксации в \"{0}/{1}\" и извлекает их из этого расположения.", "never again": "ОК, больше не показывать", "no remotes to publish": "Для вашего репозитория не настроены удаленные репозитории для публикации.", "no changes stash": "Отсутствуют изменения, которые необходимо спрятать.", diff --git a/i18n/rus/extensions/git/package.i18n.json b/i18n/rus/extensions/git/package.i18n.json index 1f1906bfc9..3891946dfb 100644 --- a/i18n/rus/extensions/git/package.i18n.json +++ b/i18n/rus/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Определяет, должно ли отображаться интерактивное действие \"Открыть файл\" в представлении \"Изменения Git\".", "config.inputValidation": "Определяет, следует ли проверять введенные данные в сообщении фиксации.", "config.detectSubmodules": "Определяет, следует ли автоматически определять подмодули Git.", + "config.detectSubmodulesLimit": "Управляет ограничением на количество обнаруженных подмодулей Git.", "colors.modified": "Цвет измененных ресурсов.", "colors.deleted": "Цвет удаленных ресурсов.", "colors.untracked": "Цвет неотслеживаемых ресурсов.", diff --git a/i18n/rus/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/rus/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..113482bb26 --- /dev/null +++ b/i18n/rus/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "Языковой сервер HTML", + "folding.start": "Начало сворачиваемого региона", + "folding.end": "Окончание сворачиваемого региона" +} \ No newline at end of file diff --git a/i18n/rus/extensions/html-language-features/package.i18n.json b/i18n/rus/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..ffedf2c26a --- /dev/null +++ b/i18n/rus/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Возможности языка HTML", + "description": "Предоставляет широкую поддержку языка для файлов HTML, Razor и Handlebar.", + "html.format.enable.desc": "Включить/отключить модуль форматирования HTML по умолчанию", + "html.format.wrapLineLength.desc": "Максимальное число символов на строку (0 — отключить).", + "html.format.unformatted.desc": "Список тегов, которые не следует повторно форматировать, с разделителями-запятыми. Значение \"NULL\" по умолчанию означает все теги, перечисленные на странице https://www.w3.org/TR/html5/dom.html#phrasing-content.", + "html.format.contentUnformatted.desc": "Разделенный запятыми список тегов, в которых формат содержимого не должен изменяться. Значение null задается по умолчанию для тега pre.", + "html.format.indentInnerHtml.desc": "Отступ в разделах <head> и <body>.", + "html.format.preserveNewLines.desc": "Следует ли сохранять разрывы строк перед элементами. Работает только перед элементами, а не внутри тегов или для текста.", + "html.format.maxPreserveNewLines.desc": "Максимальное число разрывов строк для сохранения в блоке. Чтобы указать неограниченное число строк, используйте \"null\".", + "html.format.indentHandlebars.desc": "Формат и отступ {{#foo}} и {{/foo}}.", + "html.format.endWithNewline.desc": "Завершение символом новой строки.", + "html.format.extraLiners.desc": "Список тегов с разделителями-запятыми и дополнительными новыми строками между ними. Значение \"null\" по умолчанию ставится для \"head, body, /html\".", + "html.format.wrapAttributes.desc": "Перенос атрибутов.", + "html.format.wrapAttributes.auto": "Перенос атрибутов только при превышении длины строки.", + "html.format.wrapAttributes.force": "Перенос всех атрибутов, кроме первого.", + "html.format.wrapAttributes.forcealign": "Перенос всех атрибутов, кроме первого, и сохранение выравнивания.", + "html.format.wrapAttributes.forcemultiline": "Перенос всех атрибутов.", + "html.suggest.angular1.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги и свойства Angular 1.", + "html.suggest.ionic.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги, свойства и значения Ionic.", + "html.suggest.html5.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги, свойства и значения HTML5.", + "html.trace.server.desc": "Отслеживает обмен данными между VS Code и языковым сервером HTML. ", + "html.validate.scripts": "Определяет, будет ли встроенная поддержка языка HTML проверять внедренные сценарии.", + "html.validate.styles": "Определяет, будет ли встроенная поддержка языка HTML проверять внедренные стили.", + "html.autoClosingTags": "Включить или отключить автоматическое закрытие тегов HTML. " +} \ No newline at end of file diff --git a/i18n/rus/extensions/html/package.i18n.json b/i18n/rus/extensions/html/package.i18n.json index 55c7a44cbe..42837cfec9 100644 --- a/i18n/rus/extensions/html/package.i18n.json +++ b/i18n/rus/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Возможности языка HTML", - "description": "Предоставляет широкую поддержку языка для файлов HTML, Razor и Handlebar.", - "html.format.enable.desc": "Включить/отключить модуль форматирования HTML по умолчанию", - "html.format.wrapLineLength.desc": "Максимальное число символов на строку (0 — отключить).", - "html.format.unformatted.desc": "Список тегов, которые не следует повторно форматировать, с разделителями-запятыми. Значение \"NULL\" по умолчанию означает все теги, перечисленные на странице https://www.w3.org/TR/html5/dom.html#phrasing-content.", - "html.format.contentUnformatted.desc": "Разделенный запятыми список тегов, в которых формат содержимого не должен изменяться. Значение null задается по умолчанию для тега pre.", - "html.format.indentInnerHtml.desc": "Отступ в разделах <head> и <body>.", - "html.format.preserveNewLines.desc": "Следует ли сохранять разрывы строк перед элементами. Работает только перед элементами, а не внутри тегов или для текста.", - "html.format.maxPreserveNewLines.desc": "Максимальное число разрывов строк для сохранения в блоке. Чтобы указать неограниченное число строк, используйте \"null\".", - "html.format.indentHandlebars.desc": "Формат и отступ {{#foo}} и {{/foo}}.", - "html.format.endWithNewline.desc": "Завершение символом новой строки.", - "html.format.extraLiners.desc": "Список тегов с разделителями-запятыми и дополнительными новыми строками между ними. Значение \"null\" по умолчанию ставится для \"head, body, /html\".", - "html.format.wrapAttributes.desc": "Перенос атрибутов.", - "html.format.wrapAttributes.auto": "Перенос атрибутов только при превышении длины строки.", - "html.format.wrapAttributes.force": "Перенос всех атрибутов, кроме первого.", - "html.format.wrapAttributes.forcealign": "Перенос всех атрибутов, кроме первого, и сохранение выравнивания.", - "html.format.wrapAttributes.forcemultiline": "Перенос всех атрибутов.", - "html.suggest.angular1.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги и свойства Angular 1.", - "html.suggest.ionic.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги, свойства и значения Ionic.", - "html.suggest.html5.desc": "Определяет, будет ли встроенная поддержка языка HTML предлагать теги, свойства и значения HTML5.", - "html.trace.server.desc": "Отслеживает обмен данными между VS Code и языковым сервером HTML. ", - "html.validate.scripts": "Определяет, будет ли встроенная поддержка языка HTML проверять внедренные сценарии.", - "html.validate.styles": "Определяет, будет ли встроенная поддержка языка HTML проверять внедренные стили.", - "html.experimental.syntaxFolding": "Включает/отключает маркеры свертывания с учетом синтаксиса.", - "html.autoClosingTags": "Включить или отключить автоматическое закрытие тегов HTML. " + "displayName": "Основы языка HTML", + "description": "Обеспечивает подсветку синтаксиса, выделение парных скобок и сниппеты в HTML-файлах." } \ No newline at end of file diff --git a/i18n/rus/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/rus/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..ae46a81e4e --- /dev/null +++ b/i18n/rus/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "Языковой сервер JSON" +} \ No newline at end of file diff --git a/i18n/rus/extensions/json-language-features/package.i18n.json b/i18n/rus/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..c12c7e1110 --- /dev/null +++ b/i18n/rus/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Возможности языка JSON", + "description": "Предоставляет широкую поддержку языка для файлов JSON.", + "json.schemas.desc": "Связь схем с JSON-файлами в текущем проекте", + "json.schemas.url.desc": "URL-адрес схемы или относительный путь к ней в текущем каталоге", + "json.schemas.fileMatch.desc": "Массив шаблонов файлов, с которым выполняется сравнение, при разрешении JSON-файлов в схемах.", + "json.schemas.fileMatch.item.desc": "Шаблон файла, который может содержать \"*\" и с которым выполняется сравнение, при разрешении JSON-файлов в схемах.", + "json.schemas.schema.desc": "Определение схемы для указанного URL-адреса. Схему необходимо указать только для того, чтобы не обращаться по URL-адресу схемы.", + "json.format.enable.desc": "Включение или отключение модуля форматирования JSON по умолчанию (требуется перезагрузка)", + "json.tracing.desc": "Отслеживает связь между VS Code и языковым сервером JSON.", + "json.colorDecorators.enable.desc": "Включает или отключает декораторы цвета", + "json.colorDecorators.enable.deprecationMessage": "Параметр \"json.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\"." +} \ No newline at end of file diff --git a/i18n/rus/extensions/json/package.i18n.json b/i18n/rus/extensions/json/package.i18n.json index 6f687dc8a1..85f61bdfc1 100644 --- a/i18n/rus/extensions/json/package.i18n.json +++ b/i18n/rus/extensions/json/package.i18n.json @@ -2,20 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "Возможности языка JSON", - "description": "Предоставляет широкую поддержку языка для файлов JSON.", - "json.schemas.desc": "Связь схем с JSON-файлами в текущем проекте", - "json.schemas.url.desc": "URL-адрес схемы или относительный путь к ней в текущем каталоге", - "json.schemas.fileMatch.desc": "Массив шаблонов файлов, с которым выполняется сравнение, при разрешении JSON-файлов в схемах.", - "json.schemas.fileMatch.item.desc": "Шаблон файла, который может содержать \"*\" и с которым выполняется сравнение, при разрешении JSON-файлов в схемах.", - "json.schemas.schema.desc": "Определение схемы для указанного URL-адреса. Схему необходимо указать только для того, чтобы не обращаться по URL-адресу схемы.", - "json.format.enable.desc": "Включение или отключение модуля форматирования JSON по умолчанию (требуется перезагрузка)", - "json.tracing.desc": "Отслеживает связь между VS Code и языковым сервером JSON.", - "json.colorDecorators.enable.desc": "Включает или отключает декораторы цвета.", - "json.colorDecorators.enable.deprecationMessage": "Параметр \"json.colorDecorators.enable\" устарел. Теперь вместо него используется параметр \"editor.colorDecorators\".", - "json.experimental.syntaxFolding": "Включает/отключает маркеры свертывания с учетом синтаксиса." + "displayName": "Основы языка JSON", + "description": "Обеспечивает подсветку синтаксиса и выделение парных скобок в файлах JSON." } \ No newline at end of file diff --git a/i18n/rus/extensions/markdown-basics/package.i18n.json b/i18n/rus/extensions/markdown-basics/package.i18n.json index e528514a5e..d41fad1120 100644 --- a/i18n/rus/extensions/markdown-basics/package.i18n.json +++ b/i18n/rus/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/rus/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/rus/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..b4a7172627 --- /dev/null +++ b/i18n/rus/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "Не удалось загрузить 'markdown.styles': {0}" +} \ No newline at end of file diff --git a/i18n/rus/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/rus/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..5788adc61f --- /dev/null +++ b/i18n/rus/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Предварительный просмотр] {0}", + "previewTitle": "Открыть {0} для предварительного просмотра" +} \ No newline at end of file diff --git a/i18n/rus/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/rus/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..01fb924a32 --- /dev/null +++ b/i18n/rus/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Некоторое содержимое в этом документе было отключено", + "preview.securityMessage.title": "В предварительном просмотре Markdown было отключено потенциально опасное или ненадежное содержимое. Чтобы разрешить ненадежное содержимое или включить сценарии, измените параметры безопасности предварительного просмотра Markdown.", + "preview.securityMessage.label": "Предупреждение безопасности об отключении содержимого" +} \ No newline at end of file diff --git a/i18n/rus/extensions/markdown-language-features/out/security.i18n.json b/i18n/rus/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..d51d2ea286 --- /dev/null +++ b/i18n/rus/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Строгий", + "strict.description": "Загружать только безопасное содержимое", + "insecureLocalContent.title": "Разрешить небезопасное локальное содержимое", + "insecureLocalContent.description": "Включить загрузку содержимого через HTTP из localhost", + "insecureContent.title": "Разрешить небезопасное содержимое", + "insecureContent.description": "Включить загрузку содержимого через HTTP", + "disable.title": "Отключить", + "disable.description": "Разрешить все содержимое и выполнение сценариев. Не рекомендуется", + "moreInfo.title": "Дополнительные сведения", + "enableSecurityWarning.title": "Включить предварительный просмотр предупреждений системы безопасности в этой рабочей области", + "disableSecurityWarning.title": "Отключить предварительный просмотр предупреждений системы безопасности в этой рабочей области", + "toggleSecurityWarning.description": "Не влияет на уровень безопасности содержимого", + "preview.showPreviewSecuritySelector.title": "Установите параметры безопасности для предварительного просмотра Markdown в этой рабочей области" +} \ No newline at end of file diff --git a/i18n/rus/extensions/markdown-language-features/package.i18n.json b/i18n/rus/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..0c20585821 --- /dev/null +++ b/i18n/rus/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Возможности языка Markdown", + "description": "Предоставляет широкую поддержку языка для Markdown.", + "markdown.preview.breaks.desc": "Определяет, как переносы строк отображаются в области предварительного просмотра файла Markdown. Если установить этот параметр в значение 'true', <br>будут создаваться для каждой новой строки.", + "markdown.preview.linkify": "Включить или отключить преобразование текста в URL для предварительного просмотра Markdown.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Двойной щелчок в области предварительного просмотра Markdown в редакторе.", + "markdown.preview.fontFamily.desc": "Определяет семейство шрифтов, используемое в области предварительного просмотра файла Markdown.", + "markdown.preview.fontSize.desc": "Определяет размер шрифта (в пикселях), используемый в области предварительного просмотра файла Markdown.", + "markdown.preview.lineHeight.desc": "Определяет высоту строки, используемую в области предварительного просмотра файла Markdown. Это значение задается относительно размера шрифта.", + "markdown.preview.markEditorSelection.desc": "Выделение выбранного в текущем редакторе в предпросмотре Markdown.", + "markdown.preview.scrollEditorWithPreview.desc": "Обновить представление редактора при прокрутке предварительного просмотра Markdown.", + "markdown.preview.scrollPreviewWithEditor.desc": "Обновить представление предварительного просмотра при прокрутке редактора Markdown.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Устаревшая функция] Прокрутка предварительного просмотра Markdown до выбранной строки в редакторе.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Этот параметр был заменен на 'markdown.preview.scrollPreviewWithEditor' и больше не используется.", + "markdown.preview.title": "Открыть область предварительного просмотра", + "markdown.previewFrontMatter.dec": "Определяет обработку титульных листов YAML в области предварительного просмотра файла Markdown. Значение \"скрыть\" удаляет титульные листы. В противном случае титульные листы обрабатываются как содержимое файла Markdown.", + "markdown.previewSide.title": "Открыть область предварительного просмотра сбоку", + "markdown.showLockedPreviewToSide.title": "Открыть заблокированную область предварительного просмотра сбоку", + "markdown.showSource.title": "Показать источник", + "markdown.styles.dec": "Список URL-адресов или локальных путей к таблицам стилей CSS, используемых из области предварительного просмотра файла Markdown. Относительные пути интерпретируются относительно папки, открытой в проводнике. Если папка не открыта, они интерпретируются относительно расположения файла Markdown. Все символы '\\' должны записываться в виде '\\\\'.", + "markdown.showPreviewSecuritySelector.title": "Изменить параметры безопасности для предварительного просмотра", + "markdown.trace.desc": "Включить ведение журнала отладки для расширения Markdown.", + "markdown.preview.refresh.title": "Обновить область предварительного просмотра", + "markdown.preview.toggleLock.title": "Включить/отключить блокировку области предварительного просмотра" +} \ No newline at end of file diff --git a/i18n/rus/extensions/markdown/out/features/preview.i18n.json b/i18n/rus/extensions/markdown/out/features/preview.i18n.json index dfbe859788..b3ffeb70b7 100644 --- a/i18n/rus/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/rus/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/rus/extensions/npm/out/npmView.i18n.json b/i18n/rus/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..b6387cc4b5 --- /dev/null +++ b/i18n/rus/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "Не удалось запустить \"{0}\" для отладки, так как в сценариях отсутствует параметр отладки узла, например, \"--inspect-brk\".", + "npm.scriptInvalid": "Не удалось найти сценарий \"{0}\". Попробуйте обновить представление." +} \ No newline at end of file diff --git a/i18n/rus/extensions/npm/out/tasks.i18n.json b/i18n/rus/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..df41ba3c21 --- /dev/null +++ b/i18n/rus/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Определение задач npm: не удалось проанализировать файл {0} " +} \ No newline at end of file diff --git a/i18n/rus/extensions/npm/package.i18n.json b/i18n/rus/extensions/npm/package.i18n.json index 5f5c2e9b6b..ff1cc85f4a 100644 --- a/i18n/rus/extensions/npm/package.i18n.json +++ b/i18n/rus/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "Запускать команды npm с параметром '--silent'.", "config.npm.packageManager": "Диспетчер пакетов, используемый для запуска сценариев.", "config.npm.exclude": "Настройте стандартные маски для папок, которые должны быть обработаны с помощью автоматического определения сценария.", + "config.npm.enableScriptExplorer": "Включить представление обозревателя для сценариев npm, если рабочая область содержит файл 'package.json'.", "npm.parseError": "Определение задач npm: не удалось проанализировать файл {0}", "taskdef.script": "Скрипт npm для изменения.", - "taskdef.path": "Путь к папке с файлом package.json, который содержит сценарий. Можно опустить." + "taskdef.path": "Путь к папке с файлом package.json, который содержит сценарий. Можно опустить.", + "view.name": "Сценарии NPM", + "command.refresh": "Обновить", + "command.run": "Запустить", + "command.debug": "Отладка", + "command.openScript": "Открыть", + "npm.scriptInvalid": "Не удалось найти сценарий '{0}'. Попробуйте обновить представление.", + "npm.noDebugOptions": "Не удалось запустить '{0}' для отладки, так как в сценариях не указан параметр отладки узла, например, '--inspect-brk'." } \ No newline at end of file diff --git a/i18n/rus/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/rus/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..5696440e52 --- /dev/null +++ b/i18n/rus/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "Разрешить выполнять {0} (определяется как параметр рабочей области) для обработки PHP-файлов через lint?", + "php.yes": "Разрешить", + "php.no": "Запретить", + "wrongExecutable": "Не удается проверить, так как {0} не является допустимым исполняемым PHP-файлом. Используйте параметр php.validate.executablePath, чтобы настроить исполняемый PHP-файл.", + "noExecutable": "Не удается проверить, так как не задан исполняемый PHP-файл. Используйте параметр php.validate.executablePath, чтобы настроить исполняемый PHP-файл.", + "unknownReason": "Не удалось запустить PHP-файл, используя путь {0}. Причина неизвестна." +} \ No newline at end of file diff --git a/i18n/rus/extensions/php-language-features/package.i18n.json b/i18n/rus/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..b0eb11ff03 --- /dev/null +++ b/i18n/rus/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Указывает, включены ли встроенные языковые предложения для PHP. Поддержка предлагает глобальные значения и переменные PHP.", + "configuration.validate.enable": "Включение или отключение встроенной проверки PHP.", + "configuration.validate.executablePath": "Указывает на исполняемый файл PHP.", + "configuration.validate.run": "Запускается ли анализатор кода при сохранении или при печати.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "Запретить исполняемый файл проверки PHP (определяется как параметр рабочей области)", + "displayName": "Функции языка PHP", + "description": "Предоставляет широкую поддержку возможностей языка для файлов PHP." +} \ No newline at end of file diff --git a/i18n/rus/extensions/php/package.i18n.json b/i18n/rus/extensions/php/package.i18n.json index ef06e544ec..1e2e55fbb4 100644 --- a/i18n/rus/extensions/php/package.i18n.json +++ b/i18n/rus/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Указывает, включены ли встроенные языковые предложения для PHP. Поддержка предлагает глобальные значения и переменные PHP.", - "configuration.validate.enable": "Включение или отключение встроенной проверки PHP.", - "configuration.validate.executablePath": "Указывает на исполняемый файл PHP.", - "configuration.validate.run": "Запускается ли анализатор кода при сохранении или при печати.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "Запретить исполняемый файл проверки PHP (определяется как параметр рабочей области)", - "displayName": "Функции языка PHP", - "description": "Предоставляет IntelliSense, функции жанров и основные функции языка для файлов PHP." + "displayName": "Основы языка PHP", + "description": "Предоставляет подсветку синтаксиса и выделение парных скобок в файлах PHP." } \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/commands.i18n.json b/i18n/rus/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..c2ebfd1924 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Откройте папку в VS Code, чтобы использовать проект JavaScript или TypeScript.", + "typescript.projectConfigUnsupportedFile": "Не удалось определить проект TypeScript или JavaScript. Неподдерживаемый тип файла", + "typescript.projectConfigCouldNotGetInfo": "Не удалось определить проект TypeScript или JavaScript.", + "typescript.noTypeScriptProjectConfig": "Файл не является частью проекта TypeScript. Дополнительные сведения см. [здесь]({0}).", + "typescript.noJavaScriptProjectConfig": "Файл не является частью проекта JavaScript. Дополнительные сведения см. [здесь]({0}).", + "typescript.configureTsconfigQuickPick": "Настроить tsconfig.json", + "typescript.configureJsconfigQuickPick": "Настроить jsconfig.json" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..3df8eafb05 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Выберите применяемое действие кода", + "acquiringTypingsLabel": "Получение typings...", + "acquiringTypingsDetail": "Получение определений typings для IntelliSense.", + "autoImportLabel": "Автоматический импорт из {0}" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..3add3405e1 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Включает семантическую проверку в JavaScript файле. Необходимо расположить в самом начале файла.", + "ts-nocheck": "Отключает семантическую проверку в JavaScript файле. Необходимо расположить в самом начале файла.", + "ts-ignore": "Отключает вывод ошибок @ts-check для следующей строки файла." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..8f5e9d5ec4 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 реализация", + "manyImplementationLabel": "Реализации {0}", + "implementationsErrorLabel": "Не удалось определить реализации." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..b4cad43043 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "Комментарий JSDoc" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..1787a125fa --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "Организация импортов" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..72b696f9b0 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Исправить все в файле)" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..63583231cd --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 ссылка", + "manyReferenceLabel": "Ссылок: {0}", + "referenceErrorLabel": "Не удалось определить ссылки." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..a641634e07 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "сборка – {0}", + "buildAndWatchTscLabel": "отслеживание – {0}" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/rus/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..0a42c8c674 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "Путь {0} не указывает на допустимый файл программы установки tsserver. Выполняется откат до пакетной версии TypeScript.", + "serverCouldNotBeStarted": "Не удалось запустить языковой сервер TypeScript. Сообщение об ошибке: \"{0}\".", + "typescript.openTsServerLog.notSupported": "Для ведения журнала сервера TS требуется TS 2.2.2+", + "typescript.openTsServerLog.loggingNotEnabled": "Вход в TS Server отключен. Задайте \"typescript.tsserver.log\" и перезагрузите VS Code, чтобы включить ведение журнала", + "typescript.openTsServerLog.enableAndReloadOption": "Войдите и перезагрузите TS server", + "typescript.openTsServerLog.noLogFile": "Сервер TS не начал ведение журнала.", + "openTsServerLog.openFileFailedFailed": "Не удалось открыть файл журнала сервера TS", + "serverDiedAfterStart": "Языковая служба TypeScript пять раз завершила работу сразу после запуска. Служба не будет перезапущена.", + "serverDiedReportIssue": "Сообщить об ошибке", + "serverDied": "Языковая служба TypeScript пять раз непредвиденно завершила работу за последние пять минут." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..9e87774a83 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "Недопустимая версия" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..54d1199165 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Чтобы включить языковые функции JavaScript/TypeScript IntelliSense во всем проекте, исключите папки с большим числом файлов, например: {0}.", + "hintExclude.generic": "Чтобы включить языковые функции JavaScript/TypeScript IntelliSense во всем проекте, исключите большие папки с исходными файлами, с которыми вы не работаете.", + "large.label": "Настройка исключений", + "hintExclude.tooltip": "Чтобы включить языковые функции JavaScript/TypeScript IntelliSense во всем проекте, исключите большие папки с исходными файлами, с которыми вы не работаете." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..f5ffd76a57 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Получение данных для повышения эффективности IntelliSense TypeScript", + "typesInstallerInitializationFailed.title": "Не удалось установить файлы типизации для языка JavaScript. Убедитесь, что NPM установлен или укажите путь к файлу 'typescript.npm' в параметрах среды пользователя. Дополнительные сведения см. [здесь]({0}).", + "typesInstallerInitializationFailed.doNotCheckAgain": "Больше не показывать" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..f475eb8cea --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "Использовать версию VS Code", + "useWorkspaceVersionOption": "Использовать версию рабочей области", + "learnMore": "Дополнительные сведения", + "selectTsVersion": "Выберите версию TypeScript, используемую для языковых функций JavaScript и TypeScript." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/rus/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..5de17783d5 --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Не удалось загрузить версию TypeScript по этому пути", + "noBundledServerFound": "Файл tsserver VSCode был удален другим приложением, например, в результате ошибочного срабатывания средства обнаружения вирусов. Переустановите VSCode." +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript-language-features/package.i18n.json b/i18n/rus/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..c7f564e29d --- /dev/null +++ b/i18n/rus/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Возможности языков TypeScript и JavaScript", + "description": "Предоставляет широкую поддержку языка для JavaScript и TypeScript.", + "typescript.reloadProjects.title": "Перезагрузить проект", + "javascript.reloadProjects.title": "Перезагрузить проект", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "Дополните функции сигнатурами их параметров.", + "typescript.tsdk.desc": "Указывает путь к папке, содержащей файлы tsserver и lib*.d.ts, которые необходимо использовать.", + "typescript.disableAutomaticTypeAcquisition": "Отключает автоматическое получение типов. Требуется TypeScript 2.0.6 и более поздней версии.", + "typescript.tsserver.log": "Включает ведение журнала для сервера TS. Этот журнал можно использовать для диагностики проблем сервера TS. В журнале могут содержаться пути к файлам, исходный код и другие сведения из вашего проекта, в том числе носящие конфиденциальный характер.", + "typescript.tsserver.pluginPaths": "Дополнительные пути для обнаружения подключаемых модулей языковой службы TypeScript. Требуется TypeScript версии 2.3.0 или более поздней версии.", + "typescript.tsserver.pluginPaths.item": "Абсолютный или относительный путь. Относительный путь должен быть указан относительно папок рабочей области.", + "typescript.tsserver.trace": "Включает трассировку сообщений, отправляемых на сервер TS. Эту трассировку можно использовать для диагностики проблем сервера TS. Трассировка может содержать пути к файлам, исходный код и другие сведения из вашего проекта, в том числе конфиденциальные данные.", + "typescript.validate.enable": "Включение или отключение проверки TypeScript.", + "typescript.format.enable": "Включение или отключение модуля форматирования TypeScript по умолчанию.", + "javascript.format.enable": "Включение или отключение модуля форматирования JavaScript по умолчанию.", + "format.insertSpaceAfterCommaDelimiter": "Определяет метод обработки пробелов после разделителя-запятой.", + "format.insertSpaceAfterConstructor": "Определяет метод обработки пробелов после ключевого слова constructor. Требуется TypeScript 2.3.0 или более поздней версии.", + "format.insertSpaceAfterSemicolonInForStatements": " Определяет метод обработки пробелов после точки с запятой в операторе for.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Определяет метод обработки пробелов после двоичного оператора.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Определяет метод обработки пробелов после ключевых слов в операторе управления потоком выполнения.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Определяет метод обработки пробелов после ключевого слова function у анонимных функций.", + "format.insertSpaceBeforeFunctionParenthesis": "Определяет метод обработки пробелов перед скобками аргумента функции. Требует TypeScript >= 2.1.5.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Определяет метод обработки пробелов после открытия и до закрытия непустых круглых скобок.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Определяет метод обработки пробелов после открытия и до закрытия непустых квадратных скобок.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Определяет метод обработки пробелов после открытия и до закрытия непустых квадратных скобок. Требуется TypeScript 2.3.0 или более поздней версии.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Определяет метод обработки пробелов после открытия и до закрытия скобок в строке шаблона. Требуется TypeScript 2.0.6 или более поздней версии.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Определяет метод обработки пробелов после открытия и до закрытия скобок выражения JSX. Требуется TypeScript 2.0.6 или более поздней версии.", + "format.insertSpaceAfterTypeAssertion": "Определяет метод обработки пробелов после утверждений типа в TypeScript. Требуется TypeScript 2.4 или более поздней версии.", + "format.placeOpenBraceOnNewLineForFunctions": "Определяет, ставится ли открывающая фигурная скобка с новой строки в функциях.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Определяет, ставится ли открывающая фигурная скобка с новой строки в блоках управления.", + "javascript.validate.enable": "Включение или отключение проверки JavaScript.", + "typescript.goToProjectConfig.title": "Перейти к конфигурации проекта", + "javascript.goToProjectConfig.title": "Перейти к конфигурации проекта", + "javascript.referencesCodeLens.enabled": "Включить/отключить ссылки CodeLens для файлов JavaScript.", + "typescript.referencesCodeLens.enabled": "Включить/отключить ссылки CodeLens для файлов TypeScript. Требуется TypeScript версии 2.0.6 или более поздней версии.", + "typescript.implementationsCodeLens.enabled": "Включить или отключить CodeLens для реализаций. Требуется TypeScript >= 2.2.0.", + "typescript.openTsServerLog.title": "Открыть журнал сервера TS", + "typescript.restartTsServer": "Перезапустить сервер TS", + "typescript.selectTypeScriptVersion.title": "Выберите версию TypeScript.", + "typescript.reportStyleChecksAsWarnings": "Отображать ошибки при проверке стиля в виде предупреждений", + "jsDocCompletion.enabled": "Включить или отключить JSDoc коментарии", + "javascript.implicitProjectConfig.checkJs": "Включает/отключает семантическую проверку файлов JavaScript. Этот параметр может переопределяться в файле jsconfig.json или tsconfig.json. Требуется TypeScript 2.3.1 или более поздней версии.", + "typescript.npm": "Указывает путь к исполняемому файлу NPM, используемому для автоматического получения типа. Требуется TypeScript версии 2.3.4 или более поздней версии.", + "typescript.check.npmIsInstalled": "Проверяет, установлен ли NPM для автоматического получения типов.", + "javascript.nameSuggestions": "Включить/отключить использование уникальных имен из файла в списках предложений JavaScript.", + "typescript.tsc.autoDetect": "Управляет автоматическим обнаружением задач tsc. При указании значения 'off' эта функция отключается. При указании значения 'build' создаются задачи компиляции для однократного запуска. При указании значения 'watch' создаются только задачи компиляции и наблюдения. При указании значения 'on' создаются как задачи сборки, так и задачи наблюдения. По умолчанию используется значение 'on'.", + "typescript.problemMatchers.tsc.label": "Проблемы TypeScript", + "typescript.problemMatchers.tscWatch.label": "Проблемы TypeScript (режим наблюдения)", + "typescript.quickSuggestionsForPaths": "Включить/отключить краткие предложения при вводе пути импорта.", + "typescript.locale": "Устанавливает языковой стандарт, используемый для сообщений об ошибках TypeScript. Требуется TypeScript 2.6.0 или более поздней версии. Значение по умолчанию — 'null'. При указании значения null для сообщений об ошибках TypeScript используется языковой стандарт VS Code.", + "javascript.implicitProjectConfig.experimentalDecorators": "Включает/отключает параметр 'experimentalDecorators' для файлов JavaScript, которые не являются частью проекта. Этот параметр может переопределяться в файле jsconfig.json или tsconfig.json. Требуется TypeScript 2.3.1 или более поздней версии.", + "typescript.autoImportSuggestions.enabled": "Включить/отключить предложения автоматического импорта. Требуется TypeScript 2.6.1 или более поздней версии", + "typescript.experimental.syntaxFolding": "Включает/отключает маркеры свертывания с учетом синтаксиса.", + "taskDefinition.tsconfig.description": "Файл tsconfig, который определяет сборку TS.", + "javascript.suggestionActions.enabled": "Включить/отключить предложения диагностики для файлов JavaScript в редакторе. Требуется TypeScript версии 2.8 или более поздней версии.", + "typescript.suggestionActions.enabled": "Включить/отключить предложения диагностики для файлов TypeScript в редакторе. Требуется TypeScript версии 2.8 или более поздней версии." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/base/node/processes.i18n.json b/i18n/rus/src/vs/base/node/processes.i18n.json index cf63f86d38..40cbe03523 100644 --- a/i18n/rus/src/vs/base/node/processes.i18n.json +++ b/i18n/rus/src/vs/base/node/processes.i18n.json @@ -6,5 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskRunner.UNC": "Невозможно выполнить команду оболочки на диске UNC." + "TaskRunner.UNC": "Не удается выполнить команду оболочки на диске UNC." } \ No newline at end of file diff --git a/i18n/rus/src/vs/base/node/zip.i18n.json b/i18n/rus/src/vs/base/node/zip.i18n.json index 0eb1c9ef08..deb54c61b8 100644 --- a/i18n/rus/src/vs/base/node/zip.i18n.json +++ b/i18n/rus/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Операция не завершена. Извлечено {0} из {1} записей", "notFound": "{0} не найдено в ZIP-архиве." } \ No newline at end of file diff --git a/i18n/rus/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/rus/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index 920e12e24a..49cc89f5ef 100644 --- a/i18n/rus/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/rus/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "Предварительный просмотр в GitHub", "loadingData": "Загрузка данных...", + "rateLimited": "Превышено ограничение на количество запросов GitHub. Подождите.", "similarIssues": "Похожие проблемы", "open": "Открыть", "closed": "Закрыто", - "noResults": "Результаты не найдены", + "noSimilarIssues": "Подобные задачи не найдены", "settingsSearchIssue": "Проблема с параметрами поиска", "bugReporter": "Отчет об ошибках", - "performanceIssue": "Проблема с производительностью", "featureRequest": "Запрос функции", + "performanceIssue": "Проблема с производительностью", "stepsToReproduce": "Действия для воспроизведения проблемы", "bugDescription": "Опишите действия для точного воспроизведения проблемы. Включите фактические и ожидаемые результаты. Поддерживается разметка Markdown в стиле GitHub. Вы можете отредактировать текст проблемы и добавить снимки экрана при просмотре проблемы в GitHub.", "performanceIssueDesciption": "Когда возникла эта проблема с производительностью? Происходит ли она при запуске или после указанной серии действий? Поддерживается разметка Markdown в стиле GitHub. Вы можете отредактировать текст проблемы и добавить снимки экрана при просмотре проблемы в GitHub.", diff --git a/i18n/rus/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/rus/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index 6fab7d361a..ec1142c973 100644 --- a/i18n/rus/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/rus/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Заполните форму на английском языке.", "issueTypeLabel": "Это", + "issueSourceLabel": "Файл в", + "vscode": "Visual Studio Code", + "extension": "Расширение", + "disableExtensionsLabelText": "Попробуйте воспроизвести проблему после {0}. Если проблема появляется только когда расширения включены, то это скорее всего проблема с расширением.", + "disableExtensions": "отключение всех расширений и перезагрузка окна", + "chooseExtension": "Расширение", "issueTitleLabel": "Название", "issueTitleRequired": "Введите название.", "titleLengthValidation": "Название слишком длинное.", @@ -18,13 +24,6 @@ "extensions": "Мои расширения", "searchedExtensions": "Расширения, для которых выполнялся поиск", "settingsSearchDetails": "Сведения о параметрах поиска", - "tryDisablingExtensions": "Сохраняется ли проблема после отключения расширений?", - "yes": "Да", - "no": "Нет", - "disableExtensionsLabelText": "Попробуйте воспроизвести проблему после {0}.", - "disableExtensions": "отключение всех расширений и перезагрузка окна", - "showRunningExtensionsLabelText": "Если вы подозреваете, что проблема связана с расширениями, сообщите о проблеме с расширением с помощью {0}.", - "showRunningExtensions": "просмотр всех запущенных расширений", "details": "Укажите сведения.", "loadingData": "Загрузка данных..." } \ No newline at end of file diff --git a/i18n/rus/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/rus/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..c07ddc329b --- /dev/null +++ b/i18n/rus/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "Загрузка ЦП (%)", + "memory": "Память (МБ)", + "pid": "PID", + "name": "Имя", + "killProcess": "Убить процесс", + "forceKillProcess": "Принудительно убить процесс" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/code/electron-main/menus.i18n.json b/i18n/rus/src/vs/code/electron-main/menus.i18n.json index bec5dadc84..6c8c10fb36 100644 --- a/i18n/rus/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/rus/src/vs/code/electron-main/menus.i18n.json @@ -9,8 +9,8 @@ "mFile": "&&Файл", "mEdit": "&&Правка", "mSelection": "&&Выделение", - "mView": "&&Вид", - "mGoto": "&&Перейти", + "mView": "В&&ид", + "mGoto": "Перей&&ти", "mDebug": "&&Отладка", "mWindow": "Окно", "mHelp": "&&Справка", @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "У&&словная точка останова...", "miColumnBreakpoint": "Т&&очка останова столбца", "miFunctionBreakpoint": "&&Точка останова функции...", + "miLogPoint": "&&Точка журнала...", "miNewBreakpoint": "&&Новая точка останова", "miEnableAllBreakpoints": "Включить все точки останова", "miDisableAllBreakpoints": "Отключить &&все точки останова", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Объединить все окна", "miToggleDevTools": "&&Показать/скрыть средства разработчика", "miAccessibilityOptions": "Специальные &&возможности", + "miOpenProcessExplorerer": "Открыть &&обозреватель процессов", "miReportIssue": "Сообщить о &&проблеме", "miWelcome": "&&Приветствие", "miInteractivePlayground": "&&Интерактивная площадка", diff --git a/i18n/rus/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/rus/src/vs/editor/browser/widget/diffReview.i18n.json index d144083418..df034319a3 100644 --- a/i18n/rus/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/rus/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Закрыть", - "header": "Различие {0} из {1}; исходная версия: {2}, строки: {3}, измененная версия: {4}, строки: {5}", + "no_lines": "строки отсутствуют", + "one_line": "1 строка", + "more_lines": "строк: {0}", + "header": "Различие {0} из {1}; исходная версия: {2}, {3}, измененная версия: {4}, {5}", "blankLine": "пустой", "equalLine": "Исходная версия: {0}, измененная версия: {1}: {2}", "insertLine": "+ измененная версия: {0}: {1}", diff --git a/i18n/rus/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/rus/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..b56dc782df --- /dev/null +++ b/i18n/rus/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "Количество курсоров ограничено {0}." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json index 754b901767..65df61d33a 100644 --- a/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "Отображаются абсолютные номера строк.", "lineNumbers.relative": "Отображаемые номера строк вычисляются как расстояние в строках до положения курсора.", "lineNumbers.interval": "Номера строк отображаются каждые 10 строк.", - "lineNumbers": "Управляет отображением номеров строк. Возможные значения: 'on', 'off', 'relative' и 'interval'.", + "lineNumbers": "Управляет отображением номеров строк.", "rulers": "Отображать вертикальные линейки после определенного числа моноширинных символов. Для отображения нескольких линеек укажите несколько значений. Если не указано ни одного значения, вертикальные линейки отображаться не будут.", "wordSeparators": "Символы, которые будут использоваться как разделители слов при выполнении навигации или других операций, связанных со словами.", "tabSize": "Число пробелов в табуляции. Этот параметр переопределяется на основе содержимого файла, если установлен параметр \"editor.detectIndentation\".", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Определяет, будет ли содержимое редактора прокручиваться за последнюю строку.", "smoothScrolling": "Определяет, будет ли использоваться анимация при прокрутке содержимого редактора", "minimap.enabled": "Определяет, отображается ли мини-карта", - "minimap.side": "Определяет, с какой стороны будет отображаться мини-карта. Возможные значения: \"right\" и \"left\"", - "minimap.showSlider": "Определяет, будет ли автоматически скрываться ползунок мини-карты. Возможные значения: 'always' (всегда) и 'mouseover' (при наведении курсора мыши)", + "minimap.side": "Определяет, с какой стороны будет отображаться мини-карта.", + "minimap.showSlider": "Определяет, будет ли автоматически скрываться ползунок мини-карты", "minimap.renderCharacters": "Отображает фактические символы в строке вместо цветных блоков.", "minimap.maxColumn": "Ограничивает ширину мини-карты для отображения числа столбцов не больше определенного.", "find.seedSearchStringFromSelection": "Определяет, можно ли передать строку поиска в мини-приложение поиска из текста, выделенного в редакторе", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Соответствует клавише CTRL в Windows и Linux и клавише COMMAND в macOS.", "multiCursorModifier.alt": "Соответствует клавише ALT в Windows и Linux и клавише OPTION в macOS.", "multiCursorModifier": "Модификатор, который будет использоваться для добавления нескольких курсоров с помощью мыши. \"ctrlCmd\" соответствует клавише CTRL в Windows и Linux и клавише COMMAND в macOS. Жесты мыши \"Перейти к определению\" и \"Открыть ссылку\" будут изменены так, чтобы они не конфликтовали с несколькими курсорами.", + "multiCursorMergeOverlapping": "Объединить несколько курсоров, когда они перекрываются.", "quickSuggestions.strings": "Разрешение кратких предложений в строках.", "quickSuggestions.comments": "Разрешение кратких предложений в комментариях.", "quickSuggestions.other": "Разрешение кратких предложений вне строк и комментариев.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Определяет, должен ли редактор выделять экземпляры семантических символов.", "overviewRulerLanes": "Определяет, сколько украшений могут отображаться на одном месте в обзорной линейке.", "overviewRulerBorder": "Определяет, следует ли рисовать границу на обзорной линейке.", - "cursorBlinking": "Управляет стилем анимации курсора. Допустимые значения: \"blink\", \"smooth\", \"phase\", \"expand\" и \"solid\"", + "cursorBlinking": "Управление стилем анимации курсора.", "mouseWheelZoom": "Изменение размера шрифта в редакторе при нажатой клавише CTRL и движении колесика мыши", "cursorStyle": "Определяет стиль курсора. Допустимые значения: \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" и \"underline-thin\"", "cursorWidth": "Управляет шириной курсора, когда для параметра editor.cursorStyle установлено значение 'line'", @@ -86,8 +87,11 @@ "renderControlCharacters": "Определяет, должны ли в редакторе отображаться управляющие символы.", "renderIndentGuides": "Определяет, должны ли в редакторе отображаться направляющие отступа.", "renderLineHighlight": "Определяет, должен ли редактор выделять текущую строку. Возможные значения: none, gutter, line и all.", - "codeLens": "Управляет показом групп связанных элементов кода в редакторе", + "codeLens": "Управляет отображением CodeLens в редакторе", "folding": "Определяет, включено ли сворачивание кода в редакторе.", + "foldingStrategyAuto": "Использовать стратегию сворачивания для конкретного языка, если она доступна; в противном случае использовать стратегию на основе отступов", + "foldingStrategyIndentation": "Всегда использовать стратегию сворачивания на основе отступов", + "foldingStrategy": "Управляет тем, как вычисляются диапазоны сворачивания. При указании параметра 'auto' используется стратегия сворачивания на основе языка, если она доступна. При указании параметра 'indentation' принудительно используется стратегия на основе отступов.", "showFoldingControls": "Определяет, будут ли автоматически скрываться элементы управления свертыванием на полях.", "matchBrackets": "Выделяет соответствующие скобки при выборе одной из них.", "glyphMargin": "Управляет отображением вертикальных полей глифа в редакторе. Поля глифа в основном используются для отладки.", @@ -102,8 +106,12 @@ "links": "Определяет, должен ли редактор определять ссылки и делать их доступными для щелчка", "colorDecorators": "Определяет, должны ли в редакторе отображаться внутренние декораторы цвета и средство выбора цвета.", "codeActions": "Включает индикатор действия кода", + "codeActionsOnSave.organizeImports": "Упорядочить импорты при сохранении?", + "codeActionsOnSave": "Типы действий кода, которые будут выполнены при сохранении.", + "codeActionsOnSaveTimeout": "Время ожидания для действий кода, которые будут выполнены при сохранении.", "selectionClipboard": "Контролирует, следует ли поддерживать первичный буфер обмена Linux.", "sideBySide": "Определяет, как редактор несовпадений отображает отличия: рядом или в тексте.", "ignoreTrimWhitespace": "Определяет, должен ли редактор несовпадений трактовать несовпадения символов-разделителей как различия.", + "largeFileOptimizations": "Специальная обработка для больших файлов с отключением некоторых функций, которые интенсивно используют память.", "renderIndicators": "Определяет отображение редактором несовпадений индикаторов +/- для добавленных или удаленных изменений" } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json index 58ae3030c3..c89275c69c 100644 --- a/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -14,8 +14,10 @@ "editorCursorBackground": "Цвет фона курсора редактора. Позволяет настраивать цвет символа, перекрываемого прямоугольным курсором.", "editorWhitespaces": "Цвет пробелов в редакторе.", "editorIndentGuides": "Цвет направляющих для отступов редактора.", + "editorActiveIndentGuide": "Цвет активных направляющих для отступов редактора.", "editorLineNumbers": "Цвет номеров строк редактора.", "editorActiveLineNumber": "Цвет номера активной строки редактора", + "deprecatedEditorActiveLineNumber": "Параметр 'Id' является устаревшим. Используйте вместо него параметр 'editorLineNumber.activeForeground'.", "editorRuler": "Цвет линейки редактора.", "editorCodeLensForeground": "Цвет переднего плана элемента CodeLens в редакторе", "editorBracketMatchBackground": "Цвет фона парных скобок", @@ -28,7 +30,9 @@ "warningBorder": "Цвет границ волнистой линии для выделения предупреждений в редакторе.", "infoForeground": "Цвет волнистой линии для выделения информационных сообщений в редакторе.", "infoBorder": "Цвет границ волнистой линии для выделения информационных сообщений в редакторе. ", - "overviewRulerRangeHighlight": "Цвет метки линейки в окне просмотра для выделений диапазонов.", + "hintForeground": "Цвет волнистой линии для выделения подсказок в редакторе.", + "hintBorder": "Цвет границ волнистой линии для выделения подсказок в редакторе. ", + "overviewRulerRangeHighlight": "Цвет метки линейки в окне просмотра для выделений диапазонов. Цвет должен быть прозрачным, чтобы не перекрывать основные знаки отличия.", "overviewRuleError": "Цвет метки линейки в окне просмотра для ошибок.", "overviewRuleWarning": "Цвет метки линейки в окне просмотра для предупреждений.", "overviewRuleInfo": "Цвет метки линейки в окне просмотра для информационных сообщений." diff --git a/i18n/rus/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/rus/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..7137b191ca --- /dev/null +++ b/i18n/rus/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Показать исправления ({0})", + "quickFix": "Показать исправления", + "quickfix.trigger.label": "Быстрое исправление...", + "editor.action.quickFix.noneMessage": "Доступные действия кода отсутствуют", + "refactor.label": "Рефакторинг...", + "editor.action.refactor.noneMessage": "Доступные операции рефакторинга отсутствуют", + "source.label": "Исходное действие...", + "editor.action.source.noneMessage": "Доступные исходные действия отсутствуют", + "organizeImports.label": "Организация импортов", + "editor.action.organize.noneMessage": "Действие для упорядочения импортов отсутствует" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/find/findController.i18n.json b/i18n/rus/src/vs/editor/contrib/find/findController.i18n.json index f0a2e06766..d0f335ea4d 100644 --- a/i18n/rus/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Найти", + "startFindWithSelectionAction": "Найти в выбранном", "findNextMatchAction": "Найти далее", "findPreviousMatchAction": "Найти ранее", "nextSelectionMatchFindAction": "Найти следующее выделение", diff --git a/i18n/rus/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/rus/src/vs/editor/contrib/format/formatActions.i18n.json index e6312ce93f..881bfaaa22 100644 --- a/i18n/rus/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "Внесены правки форматирования ({0}) между строками {1} и {2}.", "no.provider": "Модуль форматирования для файлов '{0}' не установлен.", "formatDocument.label": "Форматировать документ", - "formatSelection.label": "Форматировать выбранный фрагмент" + "no.documentprovider": "Модуль форматирования документов для файлов '{0}' не установлен.", + "formatSelection.label": "Форматировать выбранный фрагмент", + "no.selectionprovider": "Модуль форматирования выделения для файлов '{0}' не установлен. " } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 0a19e32eff..cc4cd3d50d 100644 --- a/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Перейти к Следующей Проблеме (Ошибке, Предупреждению, Информации)", - "markerAction.previous.label": "Перейти к Предыдущей Проблеме (Ошибке, Предупреждению, Информации)", - "editorMarkerNavigationError": "Цвет ошибки в мини-приложении навигации по меткам редактора.", - "editorMarkerNavigationWarning": "Цвет предупреждения в мини-приложении навигации по меткам редактора.", - "editorMarkerNavigationInfo": "Цвет информационного сообщения в мини-приложении навигации по меткам редактора.", - "editorMarkerNavigationBackground": "Фон мини-приложения навигации по меткам редактора." + "markerAction.previous.label": "Перейти к Предыдущей Проблеме (Ошибке, Предупреждению, Информации)" } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/rus/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..696263e5f6 --- /dev/null +++ b/i18n/rus/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Цвет ошибки в мини-приложении навигации по меткам редактора.", + "editorMarkerNavigationWarning": "Цвет предупреждения в мини-приложении навигации по меткам редактора.", + "editorMarkerNavigationInfo": "Цвет информационного сообщения в мини-приложении навигации по меткам редактора.", + "editorMarkerNavigationBackground": "Фон мини-приложения навигации по меткам редактора." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/links/links.i18n.json b/i18n/rus/src/vs/editor/contrib/links/links.i18n.json index ea183d86f1..c971bb83dd 100644 --- a/i18n/rus/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/links/links.i18n.json @@ -10,7 +10,9 @@ "links.navigate": "Щелкните с нажатой клавишей Ctrl, чтобы перейти по ссылке", "links.command.mac": "Для выполнения команды щелкните ее, удерживая нажатой клавишу CMD", "links.command": "Для выполнения команды щелкните ее, удерживая нажатой клавишу CTRL", + "links.navigate.al.mac": "Чтобы перейти по ссылке, щелкните по ней, удерживая клавишу OPTION", "links.navigate.al": "Щелкните с нажатой клавишей ALT, чтобы перейти по ссылке.", + "links.command.al.mac": "Чтобы выполнить команду, щелкните по ней, удерживая клавишу OPTION ", "links.command.al": "Для выполнения команды щелкните ее, удерживая нажатой клавишу ALT", "invalid.url": "Не удалось открыть ссылку, так как она имеет неправильный формат: {0}", "missing.url": "Не удалось открыть ссылку, у нее отсутствует целевой объект.", diff --git a/i18n/rus/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/rus/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..deab62e9c4 --- /dev/null +++ b/i18n/rus/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Не удается выполнить изменение в редакторе только для чтения" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/rus/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 8bc9e17b66..a3224ba22f 100644 --- a/i18n/rus/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Цвет фона быстрого редактора.", "peekViewEditorGutterBackground": "Цвет фона поля в окне быстрого редактора.", "peekViewResultsMatchHighlight": "Цвет выделения совпадений в списке результатов быстрого редактора.", - "peekViewEditorMatchHighlight": "Цвет выделения совпадений в быстром редакторе." + "peekViewEditorMatchHighlight": "Цвет выделения совпадений в быстром редакторе.", + "peekViewEditorMatchHighlightBorder": "Граница выделения совпадений в быстром редакторе." } \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/rus/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..5831d974e5 --- /dev/null +++ b/i18n/rus/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Воскресенье", + "Monday": "Понедельник", + "Tuesday": "Вторник", + "Wednesday": "Среда", + "Thursday": "Четверг", + "Friday": "Пятница", + "Saturday": "Суббота", + "SundayShort": "Вс", + "MondayShort": "Пн", + "TuesdayShort": "Вт", + "WednesdayShort": "Ср", + "ThursdayShort": "Чт", + "FridayShort": "Пт", + "SaturdayShort": "Сб", + "January": "Январь", + "February": "Февраль", + "March": "Март", + "April": "Апрель", + "May": "Май", + "June": "Июнь", + "July": "Июль", + "August": "Август", + "September": "Сентябрь", + "October": "Октябрь", + "November": "Ноябрь", + "December": "Декабрь", + "JanuaryShort": "Янв", + "FebruaryShort": "Фев", + "MarchShort": "Мар", + "AprilShort": "Апр", + "MayShort": "Май", + "JuneShort": "Июн", + "JulyShort": "Июл", + "AugustShort": "Авг", + "SeptemberShort": "Сен", + "OctoberShort": "Окт", + "NovemberShort": "Ноя", + "DecemberShort": "Дек" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 89aa542341..5b31b385ff 100644 --- a/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -10,8 +10,8 @@ "wordHighlightStrong": "Фон символа при доступе для записи, например при записи переменной. Цвет должен быть прозрачным чтобы не перекрывать основных знаков отличия.", "wordHighlightBorder": "Цвет границы символа при доступе на чтение, например, при считывании переменной.", "wordHighlightStrongBorder": "Цвет границы символа при доступе на запись, например, при записи переменной. ", - "overviewRulerWordHighlightForeground": "Цвет метки линейки в окне просмотра для выделений символов.", - "overviewRulerWordHighlightStrongForeground": "Цвет метки линейки в окне просмотра для выделений символов, доступных для записи. ", + "overviewRulerWordHighlightForeground": "Цвет метки линейки в окне просмотра для выделения символов. Цвет не должен был прозрачным, чтобы не перекрывать основные знаки отличия.", + "overviewRulerWordHighlightStrongForeground": "Цвет метки линейки в окне просмотра для выделения символов с доступом на запись. Цвет не должен был прозрачным, чтобы не перекрывать основные знаки отличия.", "wordHighlight.next.label": "Перейти к следующему выделению символов", "wordHighlight.previous.label": "Перейти к предыдущему выделению символов" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/rus/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..cd5317488f --- /dev/null +++ b/i18n/rus/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 дополнительный файл не показан", + "moreFiles": "...не показано дополнительных файлов: {0}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/rus/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..a9e4b3696a --- /dev/null +++ b/i18n/rus/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "Отмена" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index bc6ce2c682..e7308bcfc7 100644 --- a/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Недопустимое расширение: package.json не является файлом JSON.", + "incompatible": "Не удалось установить расширение '{0}', так как оно не совместимо с Code '{1}'.", "restartCode": "Перезапустите код перед переустановкой {0}.", "installingOutdatedExtension": "Уже установлена более новая версия этого расширения. Вы хотите переопределить ее более старой версией?", "override": "Переопределить", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Ошибка при установке зависимостей. {0}", "MarketPlaceDisabled": "Marketplace не включен", "removeError": "Ошибка при удалении расширения: {0}. Закройте и снова откройте VS Code, затем повторите попытку.", - "Not Market place extension": "Повторно устанавливать можно только расширения из Marketplace", + "Not a Marketplace extension": "Можно переустановить только расширения из Marketplace", "notFoundCompatible": "Невозможно установить '{0}'; нет версии, совместимой с VS Code '{1}'.", "malicious extension": "Не удается установить расширение, так как оно помечено как проблемное.", "notFoundCompatibleDependency": "Не удается выполнить установку, так как не найдено зависимое расширение '{0}', совместимое с текущей версией VS Code '{1}'. ", "quitCode": "Невозможно установить расширение. Пожалуйста, выйдите и зайдите в VS Code перед переустановкой.", "exitCode": "Невозможно установить расширение. Пожалуйста, выйдите и зайдите в VS Code перед переустановкой.", + "renameError": "Неизвестная ошибка при переименовании {0} в {1}", "uninstallDependeciesConfirmation": "Вы хотите удалить \"{0}\" отдельно или вместе с зависимостями?", - "uninstallOnly": "Только", - "uninstallAll": "Все", + "uninstallOnly": "Только расширение", + "uninstallAll": "Удалить все", "uninstallConfirmation": "Вы действительно хотите удалить \"{0}\"?", "ok": "ОК", "singleDependentError": "Не удается удалить расширение \"{0}\". От него зависит расширение \"{1}\".", diff --git a/i18n/rus/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/rus/src/vs/platform/extensions/node/extensionValidator.i18n.json index 9f75ca5f3c..cb7ec349cc 100644 --- a/i18n/rus/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/rus/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "Не удалось проанализировать значение engines.vscode {0}. Используйте, например, ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x и т. д.", + "versionSyntax": "Не удалось проанализировать значение engines.vscode {0}. Используйте такие значения как ^1.22.0, ^1.22.x и т.д.", "versionSpecificity1": "Версия, указанная в engines.vscode ({0}), недостаточно конкретная. Для версий vscode до 1.0.0 укажите по крайней мере основной и дополнительный номер версии. Например, 0.10.0, 0.10.x, 0.11.0 и т. д.", "versionSpecificity2": "Версия, указанная в engines.vscode ({0}), недостаточно конкретная. Для версий vscode после 1.0.0 укажите по крайней мере основной номер версии. Например, 1.10.0, 1.10.x, 1.x.x, 2.x.x и т. д.", "versionMismatch": "Расширение несовместимо с кодом \"{0}\". Расширению требуется: {1}." diff --git a/i18n/rus/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/rus/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 9b76a4fc81..8405352744 100644 --- a/i18n/rus/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/rus/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "Похоже, ваша установка {0} повреждена. Повторите установку.", "integrity.moreInformation": "Дополнительные сведения", - "integrity.dontShowAgain": "Больше не показывать", - "integrity.prompt": "Похоже, ваша установка {0} повреждена. Повторите установку." + "integrity.dontShowAgain": "Больше не показывать" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/rus/src/vs/platform/issue/electron-main/issueService.i18n.json index f8f9015ffe..8d22645773 100644 --- a/i18n/rus/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/rus/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Средство создания отчетов о неполадках" + "issueReporter": "Средство создания отчетов о неполадках", + "processExplorer": "Обозреватель процессов" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/list/browser/listService.i18n.json b/i18n/rus/src/vs/platform/list/browser/listService.i18n.json index b903bbbe44..313f0d8ea8 100644 --- a/i18n/rus/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/rus/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Модификатор, который будет использоваться для добавления элементов в деревьях и списках в элемент множественного выбора с помощью мыши (например, в проводнике, в открытых редакторах и в представлении scm). \"ctrlCmd\" соответствует клавише CTRL в Windows и Linux и клавише COMMAND в macOS. Жесты мыши \"Открыть сбоку\" (если они поддерживаются), будут изменены таким образом, чтобы они не конфликтовали с модификатором элемента множественного выбора.", "openMode.singleClick": "Открывает элемент одним щелчком мыши.", "openMode.doubleClick": "Открывает элемент двойным щелчком мыши.", - "openModeModifier": "Управляет тем, как открывать элементы в деревьях и списках с помощью мыши (если поддерживается). Укажите значение \"singleClick\", чтобы открывать элементы одним щелчком мыши, и \"doubleClick\", чтобы открывать их только двойным щелчком мыши. Для родительских элементов с дочерними элементами в деревьях этот параметр управляет тем, будет ли родительский элемент разворачиваться по одинарному или по двойному щелчку мыши. Обратите внимание, что этот параметр может игнорироваться в некоторых деревьях и списках, если он не применяется к ним. " + "openModeModifier": "Управляет тем, как открывать элементы в деревьях и списках с помощью мыши (если поддерживается). Укажите значение \"singleClick\", чтобы открывать элементы одним щелчком мыши, и \"doubleClick\", чтобы открывать их только двойным щелчком мыши. Для родительских элементов с дочерними элементами в деревьях этот параметр управляет тем, будет ли родительский элемент разворачиваться по одинарному или по двойному щелчку мыши. Обратите внимание, что этот параметр может игнорироваться в некоторых деревьях и списках, если он не применяется к ним. ", + "horizontalScrolling setting": "Определяет, поддерживают ли древа горизонтальную прокрутку в рабочей области." } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/markers/common/markers.i18n.json b/i18n/rus/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..eaeabe6709 --- /dev/null +++ b/i18n/rus/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Ошибка", + "sev.warning": "Предупреждение", + "sev.info": "Сведения" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json index 895f902fae..431b0eeb96 100644 --- a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -71,7 +71,7 @@ "editorSelectionHighlightBorder": "Цвет границы регионов с тем же содержимым, что и в выделении.", "editorFindMatch": "Цвет текущего поиска совпадений.", "findMatchHighlight": "Цвет для других результатов поиска. Цвет должен быть прозрачным, чтобы не перекрывать основные знаки отличия.", - "findRangeHighlight": "Выделите диапазон для ограничения поиска. Цвет должен быть прозрачным, чтобы не перекрывать основные знаки отличия.", + "findRangeHighlight": "Цвет диапазона для ограничения поиска. Цвет должен быть прозрачным, чтобы не перекрывать основные знаки отличия.", "editorFindMatchBorder": "Цвет границы текущего результата поиска.", "findMatchHighlightBorder": "Цвет границы других результатов поиска.", "findRangeHighlightBorder": "Цвет границы диапазона для ограничения поиска. Цвет должен быть прозрачным, чтобы не перекрывать основные знаки отличия.", @@ -93,6 +93,6 @@ "overviewRulerCurrentContentForeground": "Цвет переднего плана линейки текущего окна во внутренних конфликтах слияния.", "overviewRulerIncomingContentForeground": "Цвет переднего плана линейки входящего окна во внутренних конфликтах слияния.", "overviewRulerCommonContentForeground": "Цвет переднего плана для обзорной линейки для общего предка во внутренних конфликтах слияния. ", - "overviewRulerFindMatchForeground": "Цвет метки линейки в окне просмотра для результатов поиска.", - "overviewRulerSelectionHighlightForeground": "Цвет метки линейки в окне просмотра для выделения." + "overviewRulerFindMatchForeground": "Цвет метки линейки в окне просмотра для результатов поиска. Цвет не должен был прозрачным, чтобы не перекрывать основные знаки отличия.", + "overviewRulerSelectionHighlightForeground": "Цвет метки линейки в окне просмотра для выделения. Цвет не должен был прозрачным, чтобы не перекрывать основные знаки отличия." } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/rus/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..1d30401977 --- /dev/null +++ b/i18n/rus/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "Вы хотите разрешить расширению {0} открыть следующий URL-адрес?" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/rus/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..e0e9544610 --- /dev/null +++ b/i18n/rus/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,21 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.id": "Уникальный идентификатор, используемый для идентификации контейнера, в котором могут быть размещены представления с помощью точки вклада 'views'", + "vscode.extension.contributes.views.containers.title": "Строка в понятном формате, используемая для отображения контейнера", + "vscode.extension.contributes.views.containers.icon": "Путь к значку контейнера. Значки имеют размер 24x24, расположены в центре прямоугольника размером 50x40 и имеют цвет заливки rgb (215, 218, 224) или #d7dae0. Для значков рекомендуется использовать формат SVG, хотя допускается любой тип изображения.", + "vscode.extension.contributes.viewsContainers": "Добавляет контейнеры представлений в редактор", + "views.container.activitybar": "Добавляет контейнеры представлений на панель действий", + "test": "Проверить", + "proposed": "Вклад 'viewsContainers' доступен только при запуске из среды разработки или при запуске с параметром командной строки --enable-proposed-api {0}", + "requirearray": "Контейнер представлений должен быть массивом", + "requireidstring": "Свойство '{0}' является обязательным и должно иметь тип 'string'. Оно может содержать только буквенно-цифровые символы и символы '_' и '-'.", + "requirestring": "свойство \"{0}\" является обязательным и должно иметь тип string", + "showViewlet": "Показать {0}", + "view": "Просмотр" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/rus/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index cacaa99a68..2d58baa38f 100644 --- a/i18n/rus/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/rus/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,12 @@ "vscode.extension.contributes.view.name": "Понятное имя представления. Будет отображаться на экране", "vscode.extension.contributes.view.when": "Условие, которое должно иметь значение 'true', чтобы отображалось это представление", "vscode.extension.contributes.views": "Добавляет представления в редактор", - "views.explorer": "Представление проводника", - "views.debug": "Представление отладки", - "locationId.invalid": "\"{0}\" не является допустимым расположением представления", + "views.explorer": "Добавляет представления в контейнер обозревателя на панели действий", + "views.debug": "Добавляет представления в контейнер отладки на панели действий", + "views.scm": "Добавляет представления в контейнер диспетчера служб на панели действий ", + "views.test": "Добавляет представления в контейнер проверки на панели действий ", + "views.contributed": "Добавляет представления в контейнер добавленных представлений", + "ViewContainerDoesnotExist": "Контейнер представлений '{0}' не существует, и все представления, зарегистрированные в этом контейнере, будут добавлены в обозреватель.", "duplicateView1": "Не удается зарегистрировать несколько представлений с одинаковым идентификатором '{0}' в расположении '{1}'", "duplicateView2": "Представление с идентификатором '{0}' уже зарегистрировано в расположении '{1}'" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index 1926df91ea..d13232b532 100644 --- a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Форматирование при сохранении прервано через {0} мс", + "codeActionsOnSave.didTimeout": "Метод codeActionsOnSave прерван через {0} мс", + "timeout.onWillSave": "Событие onWillSaveTextDocument-event прервано по истечении 1750 мс", "saveParticipants": "Сохранение участников..." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 3a49c63d0d..a45e83f260 100644 --- a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "Редактор веб-представления" + "errorMessage": "Ошибка при восстановлении представления: {0}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/rus/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..06bdf111ed --- /dev/null +++ b/i18n/rus/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (расширение)" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 1746c9f421..165d97eff8 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Фокус на следующую группу", "openToSide": "Открыть сбоку", "closeEditor": "Закрыть редактор", + "closeOneEditor": "Закрыть", "revertAndCloseActiveEditor": "Отменить изменения и закрыть редактор", "closeEditorsToTheLeft": "Закрыть редакторы слева", "closeAllEditors": "Закрыть все редакторы", diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 9064007505..3b062742e9 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,7 +17,7 @@ "screenReaderDetectedExtra": "Если вы не используете средство чтения с экрана, измените значение параметра \"editor.accessibilitySupport\" на \"off\".", "disableTabMode": "Отключить режим специальных возможностей", "gotoLine": "Перейти к строке", - "indentation": "Отступ", + "selectIndentation": "Выберите отступ", "selectEncoding": "Выберите кодировку", "selectEOL": "Выберите последовательность конца строки", "selectLanguageMode": "Выберите языковой режим", diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index 686d592e9a..bec25a262b 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0} МБ", "sizeGB": "{0} ГБ", "sizeTB": "{0} ТБ", - "largeImageError": "Изображение имеет слишком большой размер для отображения в редакторе (более 1 МБ). ", + "largeImageError": "Изображение не отображается в редакторе, так как имеет слишком большой размер ({0}).", "resourceOpenExternalButton": "Открыть изображение с помощью внешней программы?", - "nativeBinaryError": "Файл не будет отображен в редакторе, так как он двоичный, очень большой или использует неподдерживаемую кодировку текста.", + "nativeFileTooLargeError": "Файл не отображается в редакторе, так как имеет слишком большой размер ({0}).", + "nativeBinaryError": "Файл не отображается в редакторе, так как является двоичным или использует неподдерживаемую кодировку текста.", + "openAsText": "Открыть его в любом случае?", "zoom.action.fit.label": "Все изображение", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 87bf8d8e95..82745fdbba 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Закрыть", "araLabelEditorActions": "Действия редактора" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 96b5537958..d6c896929e 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Новые уведомления отсутствуют", "notifications": "Уведомления", "notificationsToolbar": "Действия центра уведомлений", "notificationsList": "Список уведомлений" diff --git a/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..531da4af79 --- /dev/null +++ b/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (нажмите клавишу ВВОД, чтобы подтвердить введенные данные, или ESCAPE для отмены)", + "inputModeEntry": "Нажмите клавишу ВВОД, чтобы подтвердить введенные данные, или ESCAPE для отмены", + "quickInput.countSelected": "{0} выбрано", + "ok": "ОК" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..e0dfe281c3 --- /dev/null +++ b/i18n/rus/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Введите текст, чтобы уменьшить число результатов." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json index ba21e07cb2..35bd24c4ee 100644 --- a/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Открыть последние...", "quickOpenRecent": "Быстро открыть последние...", "reportIssueInEnglish": "Сообщить об ошибке", + "openProcessExplorer": "Открыть обозреватель процессов ", "reportPerformanceIssue": "Сообщать о проблемах производительности", "keybindingsReference": "Справочник по сочетаниям клавиш", "openDocumentationUrl": "Документация", diff --git a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json index 8fad13df0c..04ce9e355d 100644 --- a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Окно", "window.openFilesInNewWindow.on": "Файлы будут открываться в новом окне.", "window.openFilesInNewWindow.off": "Файлы будут открываться в окне с открытой папкой файлов или последнем активном окне.", - "window.openFilesInNewWindow.default": "Файлы будут открываться в окне с открытой папкой файлов или последнем активном окне, если они не открываются из панели Dock или системы поиска (только macOS).", - "openFilesInNewWindow": "Определяет, будут ли файлы открываться в новом окне.\n- default: файлы будут открываться в окне с открытой папкой файлов или последнем активном окне, если они не открываются из панели Dock или системы поиска (только macOS).\n- on: файлы будут открываться в новом окне.\n- off: файлы будут открываться в окне с открытой папкой файлов или последнем активном окне.\nОбратите внимание, что возможны случаи, когда этот параметр игнорируется (например, при использовании параметра командной строки -new-window или -reuse-window).", + "window.openFilesInNewWindow.defaultMac": "Файлы будут открыты в новом окне с открытой папкой файлов или в последнем активном окне, если они не были открыты с помощью панели Dock или поиска", + "window.openFilesInNewWindow.default": "Файлы будут открыты в новом окне, если они не были выбраны в приложении (например, из меню \"Файл\")", + "openFilesInNewWindowMac": "Определяет, будут ли файлы открываться в новом окне.\n- default: файлы будут открываться в окне с открытой папкой файлов или последнем активном окне, если они не открываются из панели Dock или системы поиска.\n- on: файлы будут открываться в новом окне.\n- off: файлы будут открываться в окне с открытой папкой файлов или последнем активном окне.\nОбратите внимание, что возможны случаи, когда этот параметр игнорируется (например, при использовании параметра командной строки -new-window или -reuse-window).", + "openFilesInNewWindow": "Определяет, будут ли файлы открываться в новом окне.\n- default: файлы будут открываться в новом окне, если они не выбраны в приложении (например, из меню \"Файл\").\n- on: файлы будут открываться в новом окне.\n- off: файлы будут открываться в окне с открытой папкой файлов или последнем активном окне.\nОбратите внимание, что возможны случаи, когда этот параметр игнорируется (например, при использовании параметра командной строки -new-window или -reuse-window).", "window.openFoldersInNewWindow.on": "Папки будут открываться в новом окне.", "window.openFoldersInNewWindow.off": "Папки будут заменять последнее активное окно.", "window.openFoldersInNewWindow.default": "Папки будут открываться в новом окне, если папка не выбрана в приложении (например, в меню \"Файл\").", "openFoldersInNewWindow": "Определяет, будут ли папки открываться в новом окне или заменять последнее активное окно.\n- default: папки будут открываться в новом окне, если папка не выбрана из приложения (например, из меню \"Файл\").\n- on: папки будут открываться в новом окне.\n- off: папки будут заменять последнее активное окно.\nОбратите внимание, что возможны случаи, когда этот параметр игнорируется (например, при использовании параметра командной строки -new-window или -reuse-window).", + "window.openWithoutArgumentsInNewWindow.on": "Открыть новое пустое окно", + "window.openWithoutArgumentsInNewWindow.off": "Перенести фокус на последний активный запущенный экземпляр", + "openWithoutArgumentsInNewWindow": "Определяет, следует ли открыть второй активный экземпляр без аргументов или перевести выделение на последний запущенный экземпляр.\n- on: открыть новое пустое окно.\n- off: перевести выделение на последний запущенный экземпляр.\nОбратите внимание, что возможны случаи, когда этот параметр игнорируется (например, при использовании параметра командной строки -new-window или -reuse-window).", "window.reopenFolders.all": "Повторно открыть все окна.", "window.reopenFolders.folders": "Повторно откройте все папки. Пустые рабочие области не будут восстановлены.", "window.reopenFolders.one": "Повторно открыть последнее активное окно.", @@ -58,7 +63,7 @@ "restoreWindows": "Управляет повторным открытием окон после перезапуска. Выберите 'none', чтобы всегда начинать с пустой рабочей области; 'one', чтобы открыть последнее окно, с которым вы работали; 'folders', чтобы открыть все окна с открытыми папками, и 'all', чтобы открыть все окна последнего сеанса.", "restoreFullscreen": "Определяет, должно ли окно восстанавливаться в полноэкранном режиме, если оно было закрыто в полноэкранном режиме.", "zoomLevel": "Настройте масштаб окна. Исходный размер равен 0. Увеличение или уменьшение значения на 1 означает увеличение или уменьшение окна на 20 %. Чтобы более точно задать масштаб, можно также ввести десятичное число.", - "title": "Определяет заголовок окна в зависимости от активного редактора. Подстановка переменных выполняется на основе контекста:\n${activeEditorShort}: имя файла (например, myFile.txt)\n${activeEditorMedium}: путь к файлу относительно папки рабочей области (например, myFolder/myFile.txt)\n${activeEditorLong}: полный путь к файлу (например, /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: имя папки рабочей области, в которой находится файл (например, myFolder)\n${folderPath}: путь к папке рабочей области, в которой находится файл (например, /Users/Development/myFolder)\n${rootName}: имя рабочей области (например, myFolder или myWorkspace)\n${rootPath}: путь к папке рабочей области (например, /Users/Development/myWorkspace)\n${appName}: например, VS Code\n${dirty}: индикатор изменения файла в активном редакторе\n${separator}: условный разделитель (\" - \"), который отображается, только если окружен переменными со значениями ", + "title": "Определяет заголовок окна в зависимости от активного редактора. Подстановка переменных выполняется на основе контекста:\n${activeEditorShort}: имя файла (например, myFile.txt)\n${activeEditorMedium}: путь к файлу относительно папки рабочей области (например, myFolder/myFile.txt)\n${activeEditorLong}: полный путь к файлу (например, /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: имя папки рабочей области, в которой находится файл (например, myFolder)\n${folderPath}: путь к папке рабочей области, в которой находится файл (например, /Users/Development/myFolder)\n${rootName}: имя рабочей области (например, myFolder или myWorkspace)\n${rootPath}: путь к папке рабочей области (например, /Users/Development/myWorkspace)\n${appName}: например, VS Code\n${dirty}: индикатор изменения файла в активном редакторе\n${separator}: условный разделитель (\" - \"), который отображается, только если окружен переменными со значениями или статическим текстом", "window.newWindowDimensions.default": "Открывать новые окна в центре экрана.", "window.newWindowDimensions.inherit": "Открывать новые окна того же размера, что и последнее активное окно.", "window.newWindowDimensions.maximized": "Открывать новые окна в развернутом состоянии.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Если включено, будет выполняться автоматический переход к высококонтрастной теме, если в Windows используется тема высокой контрастности, или к темной теме при выходе из темы высокой контрастности Windows.", "titleBarStyle": "Настройка внешнего вида заголовка окна. Чтобы применить изменения, потребуется полный перезапуск.", "window.nativeTabs": "Включает вкладки окна macOS Sierra. Обратите внимание, что для применения этих изменений потребуется полная перезагрузка, и что для всех внутренних вкладок будет отключен пользовательский стиль заголовка, если он был настроен.", + "window.smoothScrollingWorkaround": "Включите это обходное решение, если после восстановления свернутого окна кода VS Code прокрутка не выполняется плавно. Это обходное решение для проблемы (https://github.com/Microsoft/vscode/issues/13612), при которой возникают задержки прокрутки на устройствах с сенсорными панелями высокой точности, такими как устройства Surface от Майкрософт. Включение этого обходного решения может привести к небольшому дрожанию элементов окна во время восстановления, но не имеет других негативных последствий.", + "window.clickThroughInactive": "Если этот параметр включен, то при щелчке в неактивном окне будут активированы как оно, так и элемент управления, на котором находился курсор мыши в момент щелчка, если этот элемент управления должен активироваться по щелчку мыши. Если этот параметр отключен, то при щелчке в любом месте неактивного окна будет активировано только окно, и для активации элемента управления на нем будет нужно щелкнуть еще раз.", "zenModeConfigurationTitle": "Режим Zen", "zenMode.fullScreen": "Определяет, будет ли переключение в режим Zen переключать рабочее пространство в полноэкранный режим.", "zenMode.centerLayout": "Определяет, будет ли также выполняться выравнивание по центру при включении режима Zen.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index be148a4735..c7d8282666 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Изменить точку останова…", + "logPoint": "Точка журнала", + "breakpoint": "Точка останова", + "editBreakpoint": "Изменить {0}...", + "removeBreakpoint": "Удалить {0}", "functionBreakpointsNotSupported": "Точки останова функций не поддерживаются в этом типе отладки", "functionBreakpointPlaceholder": "Функция, в которой производится останов", "functionBreakPointInputAriaLabel": "Введите точку останова в функции", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Непроверенная точка останова", "functionBreakpointUnsupported": "Точки останова функций не поддерживаются в этом типе отладки", "breakpointDirtydHover": "Непроверенная точка останова. Файл был изменен, перезапустите сеанс отладки.", + "logBreakpointUnsupported": "Точки журнала не поддерживаются для этого типа отладки", "conditionalBreakpointUnsupported": "Условные точки останова не поддерживаются этим типом отладки", "hitBreakpointUnsupported": "Останавливаться на условных точках останова, которые не поддерживаются этим типом отладки" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 80b477a50c..89c4641e03 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Отключить", "continueDebug": "Продолжить", "pauseDebug": "Приостановить", + "terminateThread": "Завершить поток", "restartFrame": "Перезапустить кадр", "removeBreakpoint": "Удалить точку останова", "removeAllBreakpoints": "Удалить все точки останова", - "enableBreakpoint": "Включить точку останова", - "disableBreakpoint": "Выключить точку останова", "enableAllBreakpoints": "Включить все точки останова", "disableAllBreakpoints": "Отключить все точки останова", "activateBreakpoints": "Активировать точки останова", "deactivateBreakpoints": "Отключить точки останова", "reapplyAllBreakpoints": "Повторно применить все точки останова", "addFunctionBreakpoint": "Добавить точку останова в функции", - "addConditionalBreakpoint": "Добавить условную точку останова…", - "editConditionalBreakpoint": "Изменить точку останова…", "setValue": "Задать значение", "addWatchExpression": "Добавить выражение", "editWatchExpression": "Изменить выражение", diff --git a/i18n/rus/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 9881b4768b..9abcd29048 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Отладка: переключить точку останова", "conditionalBreakpointEditorAction": "Отладка: добавить условную точку останова…", + "logPointEditorAction": "Отладка: добавить точку журнала... ", "runToCursor": "Выполнить до курсора", "debugEvaluate": "Отладка: вычисление", "debugAddToWatch": "Отладка: добавить контрольное значение", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..0c479344e1 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetLogMessagePlaceholder": "Сообщение, которое должно быть записано в журнал при срабатывании точки останова. Выражения в фигурных скобках {} интерполируются. Нажмите клавишу ВВОД, чтобы принять, или ESC, чтобы отменить действие.", + "breakpointWidgetHitCountPlaceholder": "Прервать при определенном количестве обращений. Нажмите клавишу ВВОД, чтобы принять, или ESC для отмены.", + "breakpointWidgetExpressionPlaceholder": "Прервать выполнение, если выражение равно true. Нажмите клавишу ВВОД, чтобы принять, или ESC для отмены.", + "expression": "Выражение", + "hitCount": "Количество обращений", + "logMessage": "Сообщение журнала" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 16075996dc..2566c06081 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Используйте уникальное имя конфигурации.", "app.launch.json.compound.folder": "Имя папки, в которой расположен составной объект.", "app.launch.json.compounds.configurations": "Имена конфигураций, которые будут запущены как часть этого составного объекта.", - "debugNoType": "Параметр type адаптера отладки не может быть опущен и должен иметь тип string.", + "debugNoType": "Параметр 'type' отладчика является обязательным и должен иметь тип 'string'.", "selectDebug": "Выбор среды", "DebugConfig.failed": "Не удается создать файл launch.json в папке .vscode ({0}).", "workspace": "рабочая область", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 06ff3eaa14..fb7d93803d 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Точка журнала", + "breakpoint": "Точка останова", + "removeBreakpoint": "Удалить {0}", + "editBreakpoint": "Изменить {0}...", + "disableBreakpoint": "Отключить {0}", + "enableBreakpoint": "Включить {0}", "removeBreakpoints": "Удалить точки останова", "removeBreakpointOnColumn": "Удалить точку останова из столбца {0}", "removeLineBreakpoint": "Удалить точку останова из строки", @@ -18,5 +24,13 @@ "enableBreakpoints": "Включить точку останова в столбце {0}", "enableBreakpointOnLine": "Включить точку останова в строке", "addBreakpoint": "Добавить точку останова", + "addConditionalBreakpoint": "Добавить условную точку останова…", + "addLogPoint": "Добавить точку журнала...", + "breakpointHasCondition": "Этот {0} содержит {1}, который будет утерян при удалении. Попробуйте отключить {0} вместо удаления.", + "message": "Сообщение", + "condition": "Условие", + "removeLogPoint": "Удалить {0}", + "disableLogPoint": "Отключить {0}", + "cancel": "Отмена", "addConfiguration": "Добавить конфигурацию..." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 7f9dcb27e8..0fb76fb217 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Показывать ошибки", "noFolderWorkspaceDebugError": "Нельзя выполнить отладку активного файла. Убедитесь, что файл сохранен на диске и установлено расширение отладки для этого типа файла.", "cancel": "Отмена", - "DebugTaskNotFound": "Не удалось найти задачу preLaunchTask \"{0}\".", - "taskNotTracked": "Не удается отследить задачу предварительного запуска '{0}'." + "DebugTaskNotFound": "Не удалось найти задачу \"{0}\".", + "taskNotTracked": "Не удается отследить задачу \"{0}\"." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index d057171007..1a2c2b88e6 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Подробнее", - "unableToLaunchDebugAdapter": "Не удается запустить адаптер отладки из \"{0}\".", - "unableToLaunchDebugAdapterNoArgs": "Не удается запустить адаптер отладки.", - "stoppingDebugAdapter": "{0}. Адаптер отладки останавливается.", "debugAdapterCrash": "Процесс адаптера отладки неожиданно завершился" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 4bef054b5f..bdbeb09a96 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "Исполняемый файл адаптера отладки \"{0}\" не существует.", "debugAdapterCannotDetermineExecutable": "Невозможно определить исполняемый файл для адаптера отладки \"{0}\".", - "launch.config.comment1": "Используйте IntelliSense, чтобы узнать о возможных атрибутах.", - "launch.config.comment2": "Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.", - "launch.config.comment3": "Для получения дополнительной информации посетите: {0}", - "debugType": "Тип конфигурации.", - "debugTypeNotRecognised": "Не удается распознать тип отладки. Убедитесь, что соответствующее расширение отладки установлено и включено.", - "node2NotSupported": "Значение \"node2\" больше не поддерживается; используйте \"node\" и задайте для атрибута \"protocol\" значение \"inspector\".", - "debugName": "Имя конфигурации; отображается в раскрывающемся меню конфигурации запуска.", - "debugRequest": "Запросите тип конфигурации. Возможные типы: \"запуск\" и \"подключение\".", - "debugServer": "Только для разработки расширений отладки: если указан порт, VS Code пытается подключиться к адаптеру отладки, запущенному в режиме сервера.", - "debugPrelaunchTask": "Задача, выполняемая перед началом сеанса отладки.", - "debugWindowsConfiguration": "Атрибуты конфигурации запуска для Windows.", - "debugOSXConfiguration": "Атрибуты конфигурации запуска для OS X.", - "debugLinuxConfiguration": "Атрибуты конфигурации запуска для Linux.", - "deprecatedVariables": "\"env.\", \"config.\" и \"command.\" устарели, используйте \"env:\", \"config:\" и \"command:\"." + "unableToLaunchDebugAdapter": "Не удается запустить адаптер отладки из \"{0}\".", + "unableToLaunchDebugAdapterNoArgs": "Не удается запустить адаптер отладки." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..3ac477e5e5 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,24 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Используйте IntelliSense, чтобы узнать о возможных атрибутах.", + "launch.config.comment2": "Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.", + "launch.config.comment3": "Для получения дополнительной информации посетите: {0}", + "debugType": "Тип конфигурации.", + "debugTypeNotRecognised": "Не удается распознать тип отладки. Убедитесь, что соответствующее расширение отладки установлено и включено.", + "node2NotSupported": "Значение \"node2\" больше не поддерживается; используйте \"node\" и задайте для атрибута \"protocol\" значение \"inspector\".", + "debugName": "Имя конфигурации; отображается в раскрывающемся меню конфигурации запуска.", + "debugRequest": "Запросите тип конфигурации. Возможные типы: \"запуск\" и \"подключение\".", + "debugServer": "Только для разработки расширений отладки: если указан порт, VS Code пытается подключиться к адаптеру отладки, запущенному в режиме сервера.", + "debugPrelaunchTask": "Задача, выполняемая перед началом сеанса отладки.", + "debugPostDebugTask": "Задача, которая будет запущена после завершения сеанса отладки.", + "debugWindowsConfiguration": "Атрибуты конфигурации запуска для Windows.", + "debugOSXConfiguration": "Атрибуты конфигурации запуска для OS X.", + "debugLinuxConfiguration": "Атрибуты конфигурации запуска для Linux.", + "deprecatedVariables": "\"env.\", \"config.\" и \"command.\" устарели, используйте \"env:\", \"config:\" и \"command:\"." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..1402209c14 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "Консоль VS Code", + "mac.terminal.script.failed": "Сбой скрипта \"{0}\" с кодом выхода {1}", + "mac.terminal.type.not.supported": "\"{0}\" не поддерживается", + "press.any.key": "Для продолжения нажмите любую клавишу...", + "linux.term.failed": "Сбой \"{0}\" с кодом выхода {1}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index 9e41e1861c..f48fc30ce7 100644 --- a/i18n/rus/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Настроить рекомендуемые расширения (папка рабочей области)", "malicious tooltip": "Это расширение помечено как проблемное.", "malicious": "Вредоносный", + "disabled": "Отключено", + "disabled globally": "Отключено", + "disabled workspace": "Отключено для этой рабочей области", "disableAll": "Отключить все установленные расширения", "disableAllWorkspace": "Отключить все установленные расширения для этой рабочей области", "enableAll": "Включить все расширения", diff --git a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..80214fe333 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Имя расширения", + "extension id": "Идентификатор расширений", + "preview": "Предварительный просмотр", + "builtin": "Встроенное", + "publisher": "Имя издателя", + "install count": "Число установок", + "rating": "Оценка", + "repository": "Репозиторий", + "license": "Лицензия", + "details": "Подробности", + "contributions": "Вклады", + "changelog": "Журнал изменений", + "dependencies": "Зависимости", + "noReadme": "Файл сведений недоступен.", + "noChangelog": "Журнал изменений недоступен.", + "noContributions": "Нет публикаций", + "noDependencies": "Нет зависимостей", + "settings": "Параметры ({0})", + "setting name": "Имя", + "description": "Описание", + "default": "По умолчанию", + "debuggers": "Отладчики ({0})", + "debugger name": "Имя", + "debugger type": "Тип", + "views": "Представления ({0})", + "view id": "Идентификатор", + "view name": "Имя", + "view location": "Где", + "localizations": "Локализации ({0})", + "localizations language id": "Идентификатор языка", + "localizations language name": "Название языка", + "localizations localized language name": "Название языка (локализованное)", + "colorThemes": "Цветовые темы ({0})", + "iconThemes": "Темы значков ({0})", + "colors": "Цвета ({0})", + "colorId": "Идентификатор", + "defaultDark": "Темная по умолчанию", + "defaultLight": "Светлая по умолчанию", + "defaultHC": "С высоким контрастом по умолчанию", + "JSON Validation": "Проверка JSON ({0})", + "fileMatch": "Сопоставление файла", + "schema": "Схема", + "commands": "Команды ({0})", + "command name": "Имя", + "keyboard shortcuts": "Сочетания клавиш", + "menuContexts": "Контексты меню", + "languages": "Языки ({0})", + "language id": "Идентификатор", + "language name": "Имя", + "file extensions": "Расширения файлов", + "grammar": "Грамматика", + "snippets": "Фрагменты" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 8c553e3c91..7932bb5cda 100644 --- a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Это расширение рекомендуется пользователями текущей рабочей области.", "reallyRecommended2": "Для этого типа файлов рекомендуется использовать расширение '{0}'.", "reallyRecommendedExtensionPack": "Для этого типа файлов рекомендуется использовать пакет расширений '{0}'.", - "showRecommendations": "Показать рекомендации", "install": "Установить", + "showRecommendations": "Показать рекомендации", "showLanguageExtensions": "В Marketplace есть расширения для работы с файлами '.{0}'", "workspaceRecommended": "Эта рабочая область включает рекомендации по расширениям.", "installAll": "Установить все", diff --git a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index c2fec36985..7df6960e48 100644 --- a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Отключить другие раскладки клавиатуры ({0}), чтобы избежать конфликта между настраиваемыми сочетаниями клавиш?", "yes": "Да", - "no": "Нет", - "betterMergeDisabled": "В текущую версию встроено средство слияния с лучшей функциональностью. Установленное расширение было отключено и не может быть удалено.", - "uninstall": "Удаление" + "no": "Нет" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index 0808961d91..2237c231d5 100644 --- a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Рекомендуемое", "otherRecommendedExtensions": "Другие рекомендации", "workspaceRecommendedExtensions": "Рекомендации рабочей области", - "builtInExtensions": "Встроенный", + "builtInExtensions": "Функции", + "builtInThemesExtensions": "Темы", + "builtInBasicsExtensions": "Языки программирования", "searchExtensions": "Поиск расширений в Marketplace", "sort by installs": "Сортировать по: числу установок", "sort by rating": "Сортировать по: рейтинг", diff --git a/i18n/rus/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/rus/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index 14d7e22bcb..a7979f590c 100644 --- a/i18n/rus/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Редактор текстовых файлов", "createFile": "Создать файл", + "relaunchWithIncreasedMemoryLimit": "Перезапустить с объемом памяти {0} МБ", + "configureMemoryLimit": "Настроить ограничение памяти", "fileEditorWithInputAriaLabel": "{0}. Редактор текстовых файлов.", "fileEditorAriaLabel": "Редактор текстовых файлов." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 2b3ad37eae..c41752e19f 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -13,6 +13,7 @@ "copyFile": "Копировать", "pasteFile": "Вставить", "retry": "Повторить попытку", + "renameWhenSourcePathIsParentOfTargetError": "Для добавления дочерних элементов к существующей папке используйте команды \"Создать папку\" или \"Создать файл\"", "newUntitledFile": "Новый файл без имени", "createNewFile": "Создать файл", "createNewFolder": "Создать папку", @@ -24,19 +25,25 @@ "dirtyMessageFolderDelete": "Вы удаляете папку с несохраненными изменениями в нескольких файлах ({0}). Вы хотите продолжить?", "dirtyMessageFileDelete": "Вы удаляете файл с несохраненными изменениями. Вы хотите продолжить?", "dirtyWarning": "Если не сохранить изменения, они будут утеряны.", - "confirmMoveTrashMessageMultiple": "Вы действительно хотите удалить следующие файлы ({0})?", - "confirmMoveTrashMessageFolder": "Вы действительно хотите удалить папку \"{0}\" и ее содержимое?", - "confirmMoveTrashMessageFile": "Вы действительно хотите удалить \"{0}\"?", "undoBin": "Вы можете выполнить восстановление из корзины.", "undoTrash": "Вы можете выполнить восстановление из корзины.", "doNotAskAgain": "Больше не спрашивать", + "irreversible": "Это действие необратимо.", + "binFailed": "Не удалось выполнить удаление в корзину. Вы хотите выполнить удаление навсегда?", + "trashFailed": "Не удалось выполнить удаление в корзину. Вы действительно хотите выполнить удаление навсегда?", + "deletePermanentlyButtonLabel": "&&Удалить навсегда", + "retryButtonLabel": "&&Повторить", + "confirmMoveTrashMessageFilesAndDirectories": "Вы уверены, что вы хотите удалить следующие файлы и каталоги ({0}) и их содержимое?", + "confirmMoveTrashMessageMultipleDirectories": "Вы уверены, что вы хотите удалить следующие каталоги ({0}) и их содержимое? ", + "confirmMoveTrashMessageMultiple": "Вы действительно хотите удалить следующие файлы ({0})?", + "confirmMoveTrashMessageFolder": "Вы действительно хотите удалить папку \"{0}\" и ее содержимое?", + "confirmMoveTrashMessageFile": "Вы действительно хотите удалить \"{0}\"?", + "confirmDeleteMessageFilesAndDirectories": "Вы уверены, что вы хотите удалить следующие файлы и каталоги ({0}) и их содержимое без возможности восстановления?", + "confirmDeleteMessageMultipleDirectories": "Вы уверены, что вы хотите удалить следующие каталоги ({0}) и их содержимое без возможности восстановления? ", "confirmDeleteMessageMultiple": "Вы действительно хотите удалить следующие файлы ({0}) без возможности восстановления?", "confirmDeleteMessageFolder": "Вы действительно хотите удалить папку \"{0}\" и ее содержимое без возможности восстановления?", "confirmDeleteMessageFile": "Вы действительно хотите удалить \"{0}\" без возможности восстановления?", - "irreversible": "Это действие необратимо.", - "cancel": "Отмена", - "permDelete": "Удалить навсегда", - "importFiles": "Импорт файлов", + "addFiles": "Добавить файлы", "confirmOverwrite": "Файл или папка с таким именем уже существует в конечной папке. Заменить их?", "replaceButtonLabel": "Заменить", "fileIsAncestor": "Файл для вставки является предком папки назначения", @@ -56,7 +63,9 @@ "openFileToShowInNewWindow": "Чтобы открыть файл в новом окне, сначала откройте его.", "copyPath": "Скопировать путь", "emptyFileNameError": "Необходимо указать имя файла или папки.", + "fileNameStartsWithSlashError": "Имя папки или файла не может начинаться с косой черты.", "fileNameExistsError": "Файл или папка **{0}** уже существует в данном расположении. Выберите другое имя.", + "fileUsedAsFolderError": "**{0}** является файлом и не может иметь потомков.", "invalidFileNameError": "Имя **{0}** недопустимо для файла или папки. Выберите другое имя.", "filePathTooLongError": "Из-за использования имени **{0}** путь слишком длинный. Выберите более короткое имя.", "compareWithClipboard": "Сравнить активный файл с буфером обмена", diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 33ae5ce8ef..b818a53c49 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -35,8 +35,10 @@ "hotExit": "Определяет, запоминаются ли несохраненные файлы между сеансами. В этом случае приглашение на их сохранение при выходе из редактора не появляется.", "useExperimentalFileWatcher": "Использовать новое экспериментальное средство наблюдения за файлами.", "defaultLanguage": "Режим языка по умолчанию, который назначается новым файлам.", + "maxMemoryForLargeFilesMB": "Управляет объемом памяти, который доступен VS Code после перезапуска при попытке открытия больших файлов. Действие этого параметра аналогично указанию параметра --max-memory=<новый размер> в командной строке.", "editorConfigurationTitle": "Редактор", "formatOnSave": "Форматирование файла при сохранении. Модуль форматирования должен быть доступен, файл не должен сохраняться автоматически, а работа редактора не должна завершаться.", + "formatOnSaveTimeout": "Время ожидания форматирования при сохранении. Указывает ограничение времени в миллисекундах для команд форматирования при сохранении. Команды, выполнение которых превышает указанное время ожидания, будут отменены.", "explorerConfigurationTitle": "Проводник", "openEditorsVisible": "Число редакторов, отображаемых на панели \"Открытые редакторы\".", "autoReveal": "Определяет, будет ли проводник автоматически отображать и выбирать файлы при их открытии.", diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 9296a77d2f..b30660862f 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -2,18 +2,22 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "fileInputAriaLabel": "Введите имя файла. Нажмите клавишу ВВОД, чтобы подтвердить введенные данные, или ESCAPE для отмены.", - "constructedPath": "Создать {0} в **{1}**", + "createFileFromExplorerInfoMessage": "Создать файл **{0}** в **{1}**", + "renameFileFromExplorerInfoMessage": "Переместить и переименовать в **{0}**", + "createFolderFromExplorerInfoMessage": "Создать папку **{0}** в **{1}**", "filesExplorerViewerAriaLabel": "{0}, Проводник", "dropFolders": "Вы хотите действительно добавить папки в эту рабочую область?", "dropFolder": "Вы хотите действительно добавить папку в эту рабочую область?", "addFolders": "&&Добавить папки", "addFolder": "&&Добавить папку", + "confirmRootsMove": "Вы действительно хотите изменить порядок нескольких корневых папок в рабочей области?", "confirmMultiMove": "Вы действительно хотите переместить следующие файлы ({0})?", + "confirmRootMove": "Вы действительно хотите изменить порядок корневой папки \"{0}\" в рабочей области?", "confirmMove": "Вы действительно хотите переместить '{0}'?", "doNotAskAgain": "Больше не спрашивать", "moveButtonLabel": "&&Переместить", diff --git a/i18n/rus/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..36cadcfcce --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Предварительный просмотр HTML" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/rus/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..a80ebf7aef --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Недопустимые входные данные для редактора." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..e4db582c42 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Разработчик" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/rus/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..18d62a0945 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Открыть инструменты разработчика веб-представлений", + "refreshWebviewLabel": "Перезагрузить веб-представления" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index 30710b09a0..e843fc29d1 100644 --- a/i18n/rus/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,6 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "Вы хотели бы изменить язык пользовательского интерфейса VS Code на {0} и перезапустить VS Code?", + "yes": "Да", + "no": "Нет", + "neverAgain": "Больше не показывать", "JsonSchema.locale": "Язык пользовательского интерфейса.", "vscode.extension.contributes.localizations": "Добавляет локализации в редактор", "vscode.extension.contributes.localizations.languageId": "Идентификатор языка, на который будут переведены отображаемые строки.", diff --git a/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..d5124404f9 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "Вы хотели бы изменить язык пользовательского интерфейса VS Code на {0} и перезапустить VS Code?", + "yes": "Да", + "no": "Нет", + "neverAgain": "Больше не показывать", + "install language pack": "В ближайшем будущем VS Code будет поддерживать языковые пакеты только в виде расширений Marketplace. Установите расширение '{0}', чтобы продолжить использование текущего языка.", + "install": "Установить", + "more information": "Дополнительные сведения...", + "JsonSchema.locale": "Язык пользовательского интерфейса.", + "vscode.extension.contributes.localizations": "Добавляет локализации в редактор", + "vscode.extension.contributes.localizations.languageId": "Идентификатор языка, на который будут переведены отображаемые строки.", + "vscode.extension.contributes.localizations.languageName": "Название языка на английском языке.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Название языка на предоставленном языке.", + "vscode.extension.contributes.localizations.translations": "Список переводов, связанных с языком.", + "vscode.extension.contributes.localizations.translations.id": "Идентификатор VS Code или расширения, для которого предоставляется этот перевод. Идентификатор VS Code всегда имеет формат \"vscode\", а идентификатор расширения должен иметь формат \"publisherId.extensionName\".", + "vscode.extension.contributes.localizations.translations.id.pattern": "Идентификатор должен иметь формат \"vscode\" или \"publisherId.extensionName\" для перевода VS Code или расширения соответственно.", + "vscode.extension.contributes.localizations.translations.path": "Относительный путь к файлу, содержащему переводы для языка." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..d4a882b6b2 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Настроить язык", + "displayLanguage": "Определяет язык интерфейса VSCode.", + "doc": "Список поддерживаемых языков см. в {0}.", + "restart": "Для изменения значения требуется перезапуск VSCode.", + "fail.createSettings": "Невозможно создать \"{0}\" ({1})." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..8bfb35ec63 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Копировать", + "copyMessage": "Копировать сообщение" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..44eeaa06f3 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Всего проблем: {0}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..e99ea34227 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Проблемы", + "tooltip.1": "Проблем в этом файле: 1", + "tooltip.N": "Проблем в этом файле: {0}", + "markers.showOnFile": "Показывать ошибки и предупреждения для файлов и папки." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..214db1a2f2 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Отключить фильтр исключения файлов.", + "clearFilter": "Очистить фильтр." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..ea464c71d9 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "Показано: {0} из {1}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..0d3a91c0c6 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Просмотр", + "problems.view.toggle.label": "Включить или отключить сообщения о проблемах (ошибки, предупреждения, информационные сообщения)", + "problems.view.focus.label": "Перевести фокус на сообщения о проблемах (ошибки, предупреждения, информационные сообщения) ", + "problems.panel.configuration.title": "Представление \"Проблемы\"", + "problems.panel.configuration.autoreveal": "Определяет, следует ли представлению \"Проблемы\" отображать файлы при их открытии", + "markers.panel.title.problems": "Проблемы", + "markers.panel.aria.label.problems.tree": "Проблемы, сгруппированные по файлам", + "markers.panel.no.problems.build": "В рабочей области проблемы пока не обнаружены.", + "markers.panel.no.problems.filters": "Для указанного условия фильтра результаты не обнаружены.", + "markers.panel.no.problems.file.exclusions": "Все ошибки скрыты, так как включен фильтр исключения файлов.", + "markers.panel.action.useFilesExclude": "Фильтр, использующий параметр исключения файлов", + "markers.panel.action.donotUseFilesExclude": "Не использовать параметр исключения файлов", + "markers.panel.action.filter": "Фильтр проблем", + "markers.panel.filter.ariaLabel": "Фильтр проблем", + "markers.panel.filter.placeholder": "Фильтр. Например: text, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "ошибки", + "markers.panel.filter.warnings": "предупреждения", + "markers.panel.filter.infos": "сообщения", + "markers.panel.single.error.label": "1 ошибка", + "markers.panel.multiple.errors.label": "Ошибок: {0}", + "markers.panel.single.warning.label": "1 предупреждение", + "markers.panel.multiple.warnings.label": "Предупреждения: {0}", + "markers.panel.single.info.label": "1 сообщение", + "markers.panel.multiple.infos.label": "Сообщения: {0}", + "markers.panel.single.unknown.label": "1 неизвестный", + "markers.panel.multiple.unknowns.label": "Неизвестные: {0}", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} с проблемами ({1})", + "problems.tree.aria.label.marker.relatedInformation": "У этой проблемы есть ссылки на несколько расположений ({0}).", + "problems.tree.aria.label.error.marker": "Ошибка выдана {0}: {1}, строка {2}, символ {3}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Ошибка: {0}, строка {1}, символ {2}.{3}", + "problems.tree.aria.label.warning.marker": "Предупреждение выдано {0}: {1}, строка {2}, символ {3}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Предупреждение: {0}, строка {1}, символ {2}.{3} ", + "problems.tree.aria.label.info.marker": "Информационное сообщение выдано {0}: {1}, строка {2}, символ {3}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Информационное сообщение: {0}, строка {1}, символ {2}.{3} ", + "problems.tree.aria.label.marker": "Проблема выдана {0}: {1}, строка {2}, символ {3}.{4}", + "problems.tree.aria.label.marker.nosource": "Проблема: {0}, строка {1}, символ {2}.{3} ", + "problems.tree.aria.label.relatedinfo.message": "{0}, строка {1}, символ {2} в {3}", + "errors.warnings.show.label": "Показать ошибки и предупреждения" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/rus/src/vs/workbench/parts/output/browser/outputActions.i18n.json index ca46abc3b9..2bda5d8770 100644 --- a/i18n/rus/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Переключить выходные данные", "clearOutput": "Очистить выходные данные", "toggleOutputScrollLock": "Включить/отключить SCROLL LOCK для вывода", - "switchToOutput.label": "Переключиться на выходные данные" + "switchToOutput.label": "Переключиться на выходные данные", + "openInLogViewer": "Открыть файл журнала" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index cc22bc9377..81834b94ef 100644 --- a/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Вывод", "logViewer": "Средство просмотра журналов", "viewCategory": "Просмотр", - "clearOutput.label": "Очистить выходные данные" + "clearOutput.label": "Очистить выходные данные", + "openActiveLogOutputFile": "Просмотр: открыть активный выходной файл журнала" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 68568b71de..517dbd764f 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Сочетания клавиш", + "showDefaultKeybindings": "Показать сочетания клавиш по умолчанию", + "showUserKeybindings": "Показать пользовательские сочетания клавиш", "SearchKeybindings.AriaLabel": "Поиск настраиваемых сочетаний клавиш", "SearchKeybindings.Placeholder": "Поиск настраиваемых сочетаний клавиш", "sortByPrecedene": "Сортировать по приоритету", diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 526a2d4fe4..27ac035bad 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Открыть исходные параметры по умолчанию", + "openSettings": "Открыть параметры", "openGlobalSettings": "Открыть пользовательские параметры", "openGlobalKeybindings": "Открыть сочетания клавиш", "openGlobalKeybindingsFile": "Открыть файл сочетаний клавиш", diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 1d2ff88d8d..1f85ae395e 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Параметры по умолчанию", "SearchSettingsWidget.AriaLabel": "Параметры поиска", "SearchSettingsWidget.Placeholder": "Параметры поиска", "noSettingsFound": "Нет результатов", @@ -16,6 +15,8 @@ "nlpResult": "Результаты естественного языка", "filterResult": "Отфильтрованные результаты", "defaultSettings": "Параметры по умолчанию", + "defaultUserSettings": "Параметры пользователя по умолчанию", + "defaultWorkspaceSettings": "Параметры рабочей области по умолчанию", "defaultFolderSettings": "Параметры папок по умолчанию", "defaultEditorReadonly": "Редактировать в правой области редактора, чтобы переопределить значения по умолчанию.", "preferencesAriaLabel": "Параметры по умолчанию. Текстовый редактор только для чтения." diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 4d0353d7e7..bf74e0bb4e 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "Показать расширение «{0}»", "editTtile": "Изменить", "replaceDefaultValue": "Заменить в параметрах", - "copyDefaultValue": "Копировать в параметры", - "unsupportedPHPExecutablePathSetting": "Этот параметр должен быть параметром пользователя. Чтобы настроить в рабочей области PHP, откройте PHP-файл и щелкните \"Путь PHP\" в строке состояния.", - "unsupportedWorkspaceSetting": "Этот параметр должен быть параметром пользователя.", - "unsupportedWorkbenchSetting": "Сейчас применить этот параметр нельзя. Он будет применен, когда вы откроете эту папку напрямую.", - "unsupportedWorkbenchSettingDevMode": "Сейчас применить этот параметр нельзя. Он будет применен, когда вы определите область параметра как 'resource' при регистрации или когда вы откроете эту папку напрямую." + "copyDefaultValue": "Копировать в параметры" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 7b1b87bed2..2e295d7ab1 100644 --- a/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Установить дополнительных поставщиков SCM...", "no open repo": "Отсутствуют активные поставщики систем управления версиями.", "source control": "Система управления версиями", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Скрыть" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json index dfc3d808ea..26408e3a23 100644 --- a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Показать предыдущий шаблон исключения из поиска", "nextSearchTerm": "Показать следующее условие поиска", "previousSearchTerm": "Показать предыдущее условие поиска", - "showSearchViewlet": "Показать средство поиска", "findInFiles": "Найти в файлах", "replaceInFiles": "Заменить в файлах", "RefreshAction.label": "Обновить", diff --git a/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 3eee0745ea..90e23af847 100644 --- a/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Поиск", + "copyMatchLabel": "Копировать", + "copyPathLabel": "Скопировать путь", + "copyAllLabel": "Копировать все", + "clearSearchHistoryLabel": "Очистить историю поиска", + "toggleSearchViewPositionLabel": "Переключить положение представления поиска", "findInFolder": "Найти в папке...", "findInWorkspace": "Найти в рабочей области...", "showTriggerActions": "Перейти к символу в рабочей области...", "name": "Поиск", - "search": "Поиск", "showSearchViewl": "Показать средство поиска", "view": "Просмотр", "findInFiles": "Найти в файлах", @@ -26,5 +31,5 @@ "search.followSymlinks": "Определяет, нужно ли следовать символическим ссылкам при поиске.", "search.smartCase": "Выполняет поиск без учета регистра, если шаблон состоит только из букв нижнего регистра; в противном случае выполняет поиск с учетом регистра", "search.globalFindClipboard": "Определяет, должно ли представление поиска считывать или изменять общий буфер обмена поиска в macOS", - "search.location": "Предварительная версия: управляет тем, будет ли панель поиска отображаться в виде представления в боковой колонке или в виде панели в области панели для освобождения пространства по горизонтали. В следующем выпуске горизонтальное расположение поиска в панели будет улучшено, и этот параметр больше не будет находиться в предварительной версии." + "search.location": "Управляет тем, будет ли панель поиска отображаться в виде представления в боковой колонке или в виде панели в области панели для освобождения пространства по горизонтали. В следующем выпуске горизонтальное расположение поиска в панели будет улучшено, и этот параметр больше не будет находиться в предварительной версии." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index 98007f5496..4de6065e06 100644 --- a/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "Помогите нам улучшить поддержку {0}", "takeShortSurvey": "Пройдите краткий опрос", "remindLater": "Напомнить мне позже", - "neverAgain": "Больше не показывать", - "helpUs": "Помогите нам улучшить поддержку {0}" + "neverAgain": "Больше не показывать" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 92c2557786..4f65c41b59 100644 --- a/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Вас не затруднит пройти краткий опрос?", "takeSurvey": "Пройти опрос", "remindLater": "Напомнить мне позже", - "neverAgain": "Больше не показывать", - "surveyQuestion": "Вас не затруднит пройти краткий опрос?" + "neverAgain": "Больше не показывать" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index bf40773066..fcd8926b0d 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,6 +45,7 @@ "PatternTypeSchema.description": "Шаблон проблем либо имя добавленного или предопределенного шаблона проблем. Его можно опустить, если указано базовое значение.", "ProblemMatcherSchema.base": "Имя используемого базового сопоставителя проблем.", "ProblemMatcherSchema.owner": "Владелец проблемы в Code. Можно опустить, если указан элемент base. Если владелец опущен, а элемент base не указан, значение по умолчанию — \"внешний\".", + "ProblemMatcherSchema.source": "Строка, описывающая источник диагностических сведений, в удобном формате, например, \"typescript\" или \"super lint\".", "ProblemMatcherSchema.severity": "Серьезность по умолчанию для выявленных проблем. Используется, если в шаблоне не определена группа сопоставления для серьезности.", "ProblemMatcherSchema.applyTo": "Определяет, относится ли проблема, о которой сообщается для текстового документа, только к открытым, только к закрытым или ко всем документам.", "ProblemMatcherSchema.fileLocation": "Определяет способ интерпретации имен файлов, указываемых в шаблоне проблемы.", diff --git a/i18n/rus/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index ed9ac8cf67..429571bf3a 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Фактический тип задачи", + "TaskDefinition.description": "Фактический тип задачи. Обратите внимание, что типы, начинающиеся с символа '$', зарезервированы для внутреннего использования.", "TaskDefinition.properties": "Дополнительные свойства типа задачи", "TaskTypeConfiguration.noType": "В конфигурации типа задачи отсутствует обязательное свойство 'taskType'", "TaskDefinitionExtPoint": "Добавляет типы задачи" diff --git a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index 71500fb589..aa9e0dcee8 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "Отменяет связь задачи со всеми группами", "JsonSchema.tasks.group": "Определяет, к какой группе выполнения принадлежит эта задача. Поддерживаемые значения: \"build\" для добавления задачи к группе сборки и \"test\" для добавления задачи к группе тестирования.", "JsonSchema.tasks.type": "Определяет, выполняется ли задача в виде процесса или в виде команды оболочки.", + "JsonSchema.command.quotedString.value": "Фактическое значение команды", + "JsonSchema.tasks.quoting.escape": "Экранирует символы с помощью escape-символа оболочки (например, \"`\" в PowerShell и\"\\\" в bash).", + "JsonSchema.tasks.quoting.strong": "Заключает аргумент в кавычки с использованием символа двойной кавычки (например, \" в PowerShell и bash).", + "JsonSchema.tasks.quoting.weak": "Заключает аргумент в кавычки с использованием символа одинарной кавычки (например, ' в PowerShell и bash).", + "JsonSchema.command.quotesString.quote": "Указывает, как значение команды должно быть заключено в кавычки.", + "JsonSchema.command": "Выполняемая команда. Это может быть внешняя программа или команда оболочки.", + "JsonSchema.args.quotedString.value": "Фактическое значение аргумента.", + "JsonSchema.args.quotesString.quote": "Указывает, как значение аргумента должно быть заключено в кавычки.", + "JsonSchema.tasks.args": "Аргументы, передаваемые в команду при вызове этой задачи.", "JsonSchema.tasks.label": "Метка пользовательского интерфейса задачи", "JsonSchema.version": "Номер версии конфигурации.", "JsonSchema.tasks.identifier": "Пользовательский идентификатор задачи в файле launch.json или в предложении dependsOn.", diff --git a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index e387d7018e..3ad2e6ca5f 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "Задачи", "ConfigureTaskRunnerAction.label": "Настроить задачу", + "totalErrors": "Ошибок: {0}", + "totalWarnings": "Предупреждения: {0}", + "totalInfos": "Сообщения: {0}", "problems": "Проблемы", "building": "Сборка...", - "manyMarkers": "99+", + "manyProblems": "Более 10 тысяч", "runningTasks": "Показать выполняемые задачи", "tasks": "Задачи", "TaskSystem.noHotSwap": "Чтобы изменить подсистему выполнения задач, в которой запущена активная задача, необходимо перезагрузить окно", @@ -28,8 +31,10 @@ "selectProblemMatcher": "Выберите, на какие ошибки и предупреждения следует проверять выходные данные задачи", "customizeParseErrors": "В конфигурации текущей задачи есть ошибки. Исправьте ошибки перед изменением задачи.", "moreThanOneBuildTask": "В файле tasks.json определено несколько задач сборки. Выполняется первая задача.\n", - "TaskSystem.activeSame.background": "Задача '{0}' уже активна и находится в фоновом режиме. Чтобы завершить задачу, выберите \"Завершить задачу\" в меню \"Задачи\".", - "TaskSystem.activeSame.noBackground": "Задача '{0}' уже активна. Чтобы завершить задачу, выберите \"Завершить задачу\" из меню \"Задачи\".", + "TaskSystem.activeSame.background": "Задача '{0}' уже активна и находится в фоновом режиме.", + "TaskSystem.activeSame.noBackground": "Задача '{0}' уже выполняется.", + "terminateTask": "Завершить задачу", + "restartTask": "Перезапустить задачу", "TaskSystem.active": "Уже выполняется задача. Завершите ее, прежде чем выполнять другую задачу.", "TaskSystem.restartFailed": "Не удалось завершить и перезапустить задачу {0}", "TaskService.noConfiguration": "Ошибка: в определении задачи {0} не выявлена задача для следующей конфигурации:\n{1}\nЗадача будет проигнорирована.\n", diff --git a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 8355da67c3..176c40909d 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,6 @@ "TerminalTaskSystem.terminalName": "Задача — {0}", "closeTerminal": "Нажмите любую клавишу, чтобы закрыть терминал.", "reuseTerminal": "Терминал будет повторно использоваться задачами. Чтобы закрыть его, нажмите любую клавишу.", - "TerminalTaskSystem": "Невозможно выполнить команду оболочки на диске UNC.", + "TerminalTaskSystem": "Не удается выполнить команду оболочки на диске UNC с помощью cmd.exe.", "unkownProblemMatcher": "Не удается разрешить сопоставитель проблем {0}. Сопоставитель будет проигнорирован" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/rus/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index e5e813de17..c114daa9c1 100644 --- a/i18n/rus/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Предупреждение: options.cwd должен иметь тип string. Игнорируется значение {0}\n", + "ConfigurationParser.inValidArg": "Ошибка: аргумент команды должен представлять строку или строку в кавычках. Указанное значение:\n{0}", "ConfigurationParser.noargs": "Ошибка: аргументы команды должны представлять собой массив строк. Указанное значение:\n{0}", "ConfigurationParser.noShell": "Предупреждение: конфигурация оболочки поддерживается только при выполнении задач в терминале.", "ConfigurationParser.noName": "Ошибка: сопоставитель проблем в области объявления должен иметь имя:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Ошибка: в конфигурации задачи '{0}' отсутствует необходимое свойство '{1}'. Конфигурация задачи будет проигнорирована.", "ConfigurationParser.notCustom": "Ошибка: задачи не объявлены в качестве пользовательской задачи. Конфигурация будет проигнорирована.\n{0}\n", "ConfigurationParser.noTaskName": "Ошибка: в задаче должно быть указано свойство метки. Задача будет проигнорирована.\n{0}\n", - "taskConfiguration.shellArgs": "Предупреждение: задача \"{0}\" является командой оболочки, и один из ее аргументов содержит пробелы без escape-последовательности. Чтобы обеспечить правильную расстановку кавычек в командной строке, объедините аргументы в команде.", "taskConfiguration.noCommandOrDependsOn": "Ошибка: в задаче \"{0}\" не указаны ни команда, ни свойство dependsOn. Задача будет проигнорирована. Определение задачи:\n{1}", "taskConfiguration.noCommand": "Ошибка: задача \"{0}\" не определяет команду. Задача будет игнорироваться. Ее определение:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "Версия задач 2.0.0 не поддерживает глобальные задачи для конкретных ОС. Преобразуйте их в задачи с помощью команд для конкретных ОС.\nЗатронутые задачи: {0}" diff --git a/i18n/rus/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..aca12bf106 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "Цвет фона терминала. С его помощью можно указать цвет терминала, отличный от цвета панели.", + "terminal.foreground": "Цвет переднего плана терминала.", + "terminalCursor.foreground": "Цвет переднего плана курсора терминала.", + "terminalCursor.background": "Цвет фона курсора терминала. Позволяет выбрать цвет символа, который перекрывается блочным курсором.", + "terminal.selectionBackground": "Цвет фона выделения терминала.", + "terminal.border": "Цвет границы, которая отделяет области в терминале. По умолчанию используется panel.border.", + "terminal.ansiColor": "Цвет ANSI \"{0}\" в терминале." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index f5a2956662..73aa5a7d0b 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -21,6 +21,7 @@ "workbench.action.terminal.newWorkspacePlaceholder": "Выбрать текущий рабочий каталог для нового терминала", "workbench.action.terminal.newInActiveWorkspace": "Создать новый интегрированный терминал (в активной рабочей области)", "workbench.action.terminal.split": "Разделить терминал", + "workbench.action.terminal.splitInActiveWorkspace": "Разбить окно терминала (в активной рабочей области)", "workbench.action.terminal.focusPreviousPane": "Перейти на предыдущую область", "workbench.action.terminal.focusNextPane": "Перейти на следующую область", "workbench.action.terminal.resizePaneLeft": "Изменить размер области слева", @@ -43,6 +44,7 @@ "workbench.action.terminal.scrollUpPage": "Прокрутить вверх (страницу)", "workbench.action.terminal.scrollToTop": "Прокрутить до верхней границы", "workbench.action.terminal.clear": "Очистить", + "workbench.action.terminal.clearSelection": "Очистить выбранное", "workbench.action.terminal.allowWorkspaceShell": "Разрешить настройку оболочки в рабочей области", "workbench.action.terminal.disallowWorkspaceShell": "Запретить настройку оболочки в рабочей области", "workbench.action.terminal.rename": "Переименовать", @@ -51,5 +53,9 @@ "workbench.action.terminal.hideFindWidget": "Скрыть мини-приложение поиска", "nextTerminalFindTerm": "Показать следующий найденный термин", "previousTerminalFindTerm": "Показать предыдущий найденный термин", - "quickOpenTerm": "Переключить активный терминал" + "quickOpenTerm": "Переключить активный терминал", + "workbench.action.terminal.scrollToPreviousCommand": "Перейти к предыдущей команде", + "workbench.action.terminal.scrollToNextCommand": "Перейти к следующей команде", + "workbench.action.terminal.selectToPreviousCommand": "Выбрать предыдущую команду", + "workbench.action.terminal.selectToNextCommand": "Выбрать следующую команду" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json index da560d36c1..f96a099bc5 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,5 +12,6 @@ "terminal.integrated.copySelection.noSelection": "В терминале отсутствует выделенный текст для копирования", "terminal.integrated.exitedWithCode": "Процесс терминала завершен с кодом выхода: {0}", "terminal.integrated.waitOnExit": "Нажмите любую клавишу, чтобы закрыть терминал.", - "terminal.integrated.launchFailed": "Не удалось запустить команду процесса терминала \"{0}{1}\" (код выхода: {2})" + "terminal.integrated.launchFailed": "Не удалось запустить команду процесса терминала \"{0}{1}\" (код выхода: {2})", + "terminal.integrated.launchFailedExtHost": "Не удалось запустить процесс терминала (код выхода: {0})" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 44d961dccb..757a34d7ee 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copy": "Копировать", + "split": "Разделить", "paste": "Вставить", "selectAll": "Выбрать все", "clear": "Очистить", diff --git a/i18n/rus/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index 3bc58ea6cd..bb2052c5cc 100644 --- a/i18n/rus/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Эта рабочая область содержит параметры, которые можно задать только в параметрах пользователя. ({0}) Дополнительные сведения см. [здесь]({1}).", "openWorkspaceSettings": "Открыть параметры рабочей области", "dontShowAgain": "Больше не показывать", "unsupportedWorkspaceSettings": "Эта рабочая область содержит параметры, которые можно задать только в параметрах пользователя. ({0}) Дополнительные сведения см. [здесь]({1})." diff --git a/i18n/rus/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/rus/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..52d5c03cd5 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Заметки о выпуске: {0}", + "unassigned": "не присвоено" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/rus/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 29037d7151..0aa4567511 100644 --- a/i18n/rus/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Позже", - "unassigned": "не присвоено", "releaseNotes": "Заметки о выпуске", "showReleaseNotes": "Показать заметки о выпуске", "read the release notes": "Вас приветствует {0} v{1}! Вы хотите прочитать заметки о выпуске?", @@ -17,13 +15,14 @@ "updateIsReady": "Доступно новое обновление {0}.", "noUpdatesAvailable": "Доступные обновления отсутствуют.", "ok": "ОК", - "download now": "Скачать сейчас", "thereIsUpdateAvailable": "Доступно обновление.", - "installUpdate": "Установить обновление", + "download now": "Скачать сейчас", + "later": "Позже", "updateAvailable": "Доступно обновление: {0} {1}", + "installUpdate": "Установить обновление", "updateInstalling": "{0} {1} устанавливается в фоновом режиме, мы сообщим вам о завершении.", + "updateAvailableAfterRestart": "Перезапустите {0}, чтобы применить последнее обновление.", "updateNow": "Обновить сейчас", - "updateAvailableAfterRestart": "{0} будет обновлен после перезапуска.", "commandPalette": "Палитра команд...", "settings": "Параметры", "keyboardShortcuts": "Сочетания клавиш", diff --git a/i18n/rus/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..2c18fffece --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "Открыть URL", + "developer": "Разработчик" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..dfb29cabd8 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "Редактор веб-представления", + "developer": "Разработчик" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..18d62a0945 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Открыть инструменты разработчика веб-представлений", + "refreshWebviewLabel": "Перезагрузить веб-представления" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/rus/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..1f21447797 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Помогите улучшить VS Code, разрешив корпорации Майкрософт сбор данных об использовании. Прочтите наше [заявление о конфиденциальности]({0}) и узнайте, как [явно отказаться от него]({1}).", + "telemetryOptOut.optInNotice": "Помогите улучшить VS Code, разрешив корпорации Майкрософт сбор данных об использовании. Прочтите наше [заявление о конфиденциальности]({0}) и узнайте, как [его принять]({1}). ", + "telemetryOptOut.readMore": "Подробнее" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/rus/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index f24148fc4b..a68e48aa96 100644 --- a/i18n/rus/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Управление расширениями", "welcomeOverlay.problems": "Просмотр ошибок и предупреждений", "welcomeOverlay.commandPalette": "Найти и выполнить все команды.", + "welcomeOverlay.notifications": "Отображать уведомления", "welcomeOverlay": "Обзор пользовательского интерфейса", "hideWelcomeOverlay": "Скрыть наложение интерфейса", "help": "Справка" diff --git a/i18n/rus/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/rus/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 768712ab22..4a88bc6437 100644 --- a/i18n/rus/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Средства и языки", "welcomePage.installExtensionPacksDescription": "Установить поддержку для {0} и {1}", "welcomePage.moreExtensions": "Еще", - "welcomePage.installKeymapDescription": "Установка сочетаний клавиш", - "welcomePage.installKeymapExtension": "Настроить сочетания клавиш для {0} и {1}", + "welcomePage.installKeymapDescription": "Параметры и настраиваемые сочетания клавиш", + "welcomePage.installKeymapExtension": "Установить параметры и настраиваемые сочетания клавиш из {0} и {1}", "welcomePage.others": "Другие", "welcomePage.colorTheme": "Цветовая тема", "welcomePage.colorThemeDescription": "Настройте редактор и код удобным образом.", diff --git a/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index bb9a27b7b9..a09bcd64b7 100644 --- a/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/rus/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Краткая сводка параметров. Эта метка будет использоваться в файле параметров в качестве разделяющего комментария.", "vscode.extension.contributes.configuration.properties": "Описание свойств конфигурации.", + "scope.application.description": "Конфигурация для конкретного приложения, которая может быть задана только в параметрах пользователя.", "scope.window.description": "Конфигурация окна, которая может быть задана в параметрах пользователя или рабочей области.", "scope.resource.description": "Конфигурации ресурсов, которые могут быть заданы в параметрах пользователей, рабочих областей или папок.", "scope.description": "Область, в которой применяется конфигурация. Доступные области — 'window' и 'resource'.", diff --git a/i18n/rus/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json b/i18n/rus/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json index c69ade137c..400f7497d1 100644 --- a/i18n/rus/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/configuration/node/configurationEditingService.i18n.json @@ -11,6 +11,7 @@ "open": "Открыть параметры", "saveAndRetry": "Сохранить и повторить", "errorUnknownKey": "Не удалось записать в {0}, так как {1} не является зарегистрированной конфигурацией.", + "errorInvalidWorkspaceConfigurationApplication": "Не удается записать {0} в параметры рабочей области. Этот параметр можно записать только в параметры пользователя.", "errorInvalidFolderConfiguration": "Не удается изменить параметры папок, так как {0} не поддерживает область ресурсов папок. ", "errorInvalidUserTarget": "Не удается изменить параметры пользователей, так как {0} не поддерживает глобальную область.", "errorInvalidWorkspaceTarget": "Не удается изменить параметры рабочей области, так как {0} не поддерживает рабочие области в в рабочей области из нескольких папок.", diff --git a/i18n/rus/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/rus/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..96f827a5c6 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedApplicationSetting": "Этот параметр может применяться только в параметрах пользователя", + "unsupportedWindowSetting": "Сейчас применить этот параметр нельзя. Он будет применен, когда вы откроете эту папку напрямую." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/rus/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/rus/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..b412351864 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "Не удалось разрешить '{0}', так как не указано имя переменной среды. ", + "configNotFound": "Не удалось разрешить '{0}', так как параметр '{1}' не найден.", + "configNoString": "Не удалось разрешить '{0}', так как '{1}' является структурированным значением.", + "missingConfigName": "Не удается разрешить '{0}', так как не указано имя параметров.", + "noValueForCommand": "Не удалось разрешить '{0}', так как не указано значение команды.", + "canNotFindFolder": "Не удается разрешить '{0}'. Отсутствует папка '{1}'.", + "canNotResolveWorkspaceFolderMultiRoot": "Не удалось разрешить папку '{0}' в рабочей области с несколькими папками. Определите область действия этой переменной, указав \":\" и имя папки.", + "canNotResolveWorkspaceFolder": "Не удается разрешить '{0}'. Откройте папку.", + "canNotResolveFile": "Не удается разрешить '{0}'. Откройте редактор. ", + "canNotResolveLineNumber": "Не удается разрешить '{0}'. Убедитесь, что в активном редакторе выбрана строка.", + "canNotResolveSelectedText": "Не удается разрешить '{0}'. Убедитесь, что в активном редакторе выбран какой-либо текст." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/rus/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..360b3b18b2 --- /dev/null +++ b/i18n/rus/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Да", + "cancelButton": "Отмена" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/rus/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index bf759d2221..d85c0a70e5 100644 --- a/i18n/rus/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/rus/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Совместимость с подсистемой.", "vscode.extension.engines.vscode": "Для расширений VS Code указывает версию VS Code, с которой совместимо расширение. Она не может быть задана как \"*\". Например, ^0.10.5 сообщает о совместимости с минимальной версией VS Code 0.10.5.", "vscode.extension.publisher": "Издатель расширения VS Code.", "vscode.extension.displayName": "Отображаемое имя расширения, используемого в коллекции VS Code.", "vscode.extension.categories": "Категории, используемые коллекцией VS Code для классификации расширения.", + "vscode.extension.category.languages.deprecated": "Используйте \"Языки программирования\"", "vscode.extension.galleryBanner": "Баннер, используемый в магазине VS Code.", "vscode.extension.galleryBanner.color": "Цвет баннера в заголовке страницы магазина VS Code.", "vscode.extension.galleryBanner.theme": "Цветовая тема для шрифта, используемого в баннере.", @@ -23,11 +25,14 @@ "vscode.extension.activationEvents.onDebugResolve": "Событие активации выдается каждый раз при запуске сеанса отладки указанного типа (и при вызове соответствующего метода resolveDebugConfiguration).", "vscode.extension.activationEvents.workspaceContains": "Событие активации выдается каждый раз при открытии папки, содержащей по крайней мере один файл, который соответствует указанной стандартной маске.", "vscode.extension.activationEvents.onView": "Событие активации выдается каждый раз при развертывании указанного окна.", + "vscode.extension.activationEvents.onUri": "Событие активации, которое выдается каждый раз при открытии системного URI этого расширения.", "vscode.extension.activationEvents.star": "Событие активации выдается при запуске VS Code. Для удобства пользователя используйте это событие в своем расширении только в том случае, если другие сочетания событий не подходят.", "vscode.extension.badges": "Массив эмблем, отображаемых на боковой панели страницы расширения Marketplace.", "vscode.extension.badges.url": "URL-адрес изображения эмблемы.", "vscode.extension.badges.href": "Ссылка на эмблему.", "vscode.extension.badges.description": "Описание эмблемы.", + "vscode.extension.markdown": "Управляет подсистемой отображения Markdown, используемой в Marketplace. Допустимые значения: 'github' (по умолчанию) или 'standard' (стандартный).", + "vscode.extension.qna": "Управляет ссылкой на раздел \"Часто задаваемые вопросы\" в Marketplace. Установите значение 'marketplace', чтобы включить раздел часто задаваемых вопросов Marketplace по умолчанию. Установите значение 'false', чтобы вообще отключить раздел \"Часто задаваемые вопросы\". Вы также можете указать строку с URL-адресом пользовательского сайта с часто задаваемыми вопросами.", "vscode.extension.extensionDependencies": "Зависимости от других расширений. Идентификатор расширения — всегда ${publisher}.${name}. Например: vscode.csharp.", "vscode.extension.scripts.prepublish": "Скрипт, выполняемый перед публикацией пакета в качестве расширения VS Code.", "vscode.extension.scripts.uninstall": "Удалить обработчик для расширения VS Code. Скрипт, который выполняется после полного удаления расширения из VS Code, когда VS Code перезапускается (выключается и запускается) после удаления расширения. Поддерживаются только скрипты Node.", diff --git a/i18n/rus/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/rus/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index bd4f61f802..f81c75be41 100644 --- a/i18n/rus/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Все расширения отключены.", "extensionHostProcess.crash": "Хост-процесс для расширений неожиданно завершил работу.", "extensionHostProcess.unresponsiveCrash": "Работа хост-процесса для расширений была завершена, так как он перестал отвечать на запросы.", - "devTools": "Средства разработчика", + "devTools": "Открыть инструменты разработчика", "restart": "Перезапустить хост-процесс для расширений", "overwritingExtension": "Идет перезапись расширения {0} на {1}.", "extensionUnderDevelopment": "Идет загрузка расширения разработки в {0}.", diff --git a/i18n/rus/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/rus/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 72d82c87a6..8ebd66bbd8 100644 --- a/i18n/rus/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Требуется платформа Microsoft .NET Framework 4.5. Нажмите ссылку, чтобы установить ее.", "installNet": "Скачать .NET Framework 4.5", "neverShowAgain": "Больше не показывать", - "netVersionError": "Требуется платформа Microsoft .NET Framework 4.5. Нажмите ссылку, чтобы установить ее.", + "enospcError": "{0} не удалось проследить изменения файлов в этой большой рабочей области. Для решения проблемы воспользуйтесь ссылкой на инструкции.", "learnMore": "Инструкции", - "enospcError": "В {0} закончились дескрипторы файлов. Для решения проблемы воспользуйтесь ссылкой на инструкции.", + "fileInvalidPath": "Недопустимый ресурс файла ({0})", + "fileIsDirectoryError": "Файл является каталогом", + "fileNotModifiedError": "undefined", + "fileTooLargeForHeapError": "Чтобы открыть файл такого размера, необходимо перезапустить VS Code, увеличив допустимый объем используемой памяти", + "fileTooLargeError": "Не удается открыть файл, так как он имеет слишком большой размер", + "fileNotFoundError": "Файл не найден ({0})", + "fileBinaryError": "Похоже, файл является двоичным, и его нельзя открыть как текстовый.", + "filePermission": "Отсутствует разрешение на запись в файл ({0})", + "fileExists": "Создаваемый файл уже существует ({0})", + "fileModifiedError": "Файл изменен с", + "fileReadOnlyError": "Файл доступен только для чтения", + "fileMoveConflict": "Невозможно переместить или скопировать файл, так как он уже существует в папке назначения.", + "unableToMoveCopyError": "Невозможно переместить или скопировать файл, так как он заменил бы папку, в которой содержится.", "binFailed": "Не удалось переместить \"{0}\" в корзину", "trashFailed": "Не удалось переместить \"{0}\" в корзину." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index d96dfa8c18..21140f4d50 100644 --- a/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Файл не найден ({0})", "fileIsDirectoryError": "Файл является каталогом", "fileNotModifiedError": "undefined", - "fileBinaryError": "Похоже, файл является двоичным, и его нельзя открыть как текстовый." + "fileBinaryError": "Похоже, файл является двоичным, и его нельзя открыть как текстовый.", + "err.create": "Не удалось создать файл {0}", + "fileMoveConflict": "Невозможно переместить или скопировать файл, так как он уже существует в папке назначения." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/rus/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..9663fb93d7 100644 --- a/i18n/rus/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/rus/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "Отмена" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index 92abc433d5..24bd27fbec 100644 --- a/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -11,5 +11,6 @@ "vscode.extension.contributes.grammars.scopeName": "Имя области TextMate, используемое в файле tmLanguage.", "vscode.extension.contributes.grammars.path": "Путь к файлу tmLanguage. Путь указывается относительно папки расширения и обычно начинается с \"./syntaxes/\".", "vscode.extension.contributes.grammars.embeddedLanguages": "Сопоставление имени области и идентификатора языка, если грамматика содержит внедренные языки.", + "vscode.extension.contributes.grammars.tokenTypes": "Сопоставление имени области с типами маркеров.", "vscode.extension.contributes.grammars.injectTo": "Список имен языковых областей, в которые вставляется эта грамматика." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index c74e071c8a..2abfb98230 100644 --- a/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/rus/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "В contributes.{0}.path требуется строка. Указанное значение: {1}", "invalid.injectTo": "Недопустимое значение в \"contributes.{0}.injectTo\". Должен быть задан массив имен языковых областей. Указанное значение: {1}", "invalid.embeddedLanguages": "Недопустимое значение в \"contributes.{0}.embeddedLanguages\". Оно должно быть сопоставлением объекта между именем области и языком. Указанное значение: {1}.", + "invalid.tokenTypes": "Недопустимое значение в \"contributes.{0}.tokenTypes\". Необходимо указать сопоставление объекта между именем объекта и типом маркера. Указанное значение: {1}.", "invalid.path.1": "contributes.{0}.path ({1}) должен был быть включен в папку расширения ({2}). Это может сделать расширение непереносимым.", "no-tm-grammar": "Нет грамматики TM, зарегистрированной для этого языка." } \ No newline at end of file diff --git a/i18n/trk/extensions/css-language-features/client/out/cssMain.i18n.json b/i18n/trk/extensions/css-language-features/client/out/cssMain.i18n.json new file mode 100644 index 0000000000..5d438afc47 --- /dev/null +++ b/i18n/trk/extensions/css-language-features/client/out/cssMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cssserver.name": "CSS Dil Sunucusu", + "folding.start": "Katlama Bölgesi Başlangıcı", + "folding.end": "Katlama Bölgesi Sonu" +} \ No newline at end of file diff --git a/i18n/trk/extensions/css-language-features/package.i18n.json b/i18n/trk/extensions/css-language-features/package.i18n.json new file mode 100644 index 0000000000..5a93ed1e78 --- /dev/null +++ b/i18n/trk/extensions/css-language-features/package.i18n.json @@ -0,0 +1,81 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "CSS Dili Özellikleri", + "description": "CSS, LESS, SCSS dosyaları için zengin dil desteği sağlar.", + "css.title": "CSS", + "css.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", + "css.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", + "css.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", + "css.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", + "css.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", + "css.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", + "css.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", + "css.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", + "css.lint.idSelector.desc": " ID'ler HTML'e çok sıkı bağlı olduğundan, seçiciler ID içermemelidir. ", + "css.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", + "css.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", + "css.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", + "css.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", + "css.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", + "css.lint.unknownProperties.desc": "Bilinmeyen özellik.", + "css.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", + "css.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", + "css.lint.zeroUnits.desc": "Sıfır için birim gerekmez", + "css.trace.server.desc": "VS Code ve CSS dil sunucusu arasındaki iletişimi izler.", + "css.validate.title": "CSS doğrulamasını ve sorunların önem derecelerini denetler.", + "css.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", + "less.title": "LESS", + "less.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", + "less.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", + "less.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", + "less.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", + "less.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", + "less.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", + "less.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", + "less.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", + "less.lint.idSelector.desc": " ID'ler HTML'e çok sıkı bağlı olduğundan, seçiciler ID içermemelidir. ", + "less.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", + "less.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", + "less.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", + "less.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", + "less.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", + "less.lint.unknownProperties.desc": "Bilinmeyen özellik.", + "less.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", + "less.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", + "less.lint.zeroUnits.desc": "Sıfır için birim gerekmez", + "less.validate.title": "LESS doğrulamasını ve sorunların önem derecelerini denetler.", + "less.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", + "scss.title": "SCSS (Sass)", + "scss.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", + "scss.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", + "scss.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", + "scss.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", + "scss.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", + "scss.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", + "scss.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", + "scss.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", + "scss.lint.idSelector.desc": " ID'ler HTML'e çok sıkı bağlı olduğundan, seçiciler ID içermemelidir. ", + "scss.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", + "scss.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", + "scss.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", + "scss.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", + "scss.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", + "scss.lint.unknownProperties.desc": "Bilinmeyen özellik.", + "scss.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", + "scss.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", + "scss.lint.zeroUnits.desc": "Sıfır için birim gerekmez", + "scss.validate.title": "SCSS doğrulamasını ve sorunların önem derecelerini denetler.", + "scss.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", + "less.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", + "scss.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", + "css.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", + "css.colorDecorators.enable.deprecationMessage": "`css.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır.", + "scss.colorDecorators.enable.deprecationMessage": "`scss.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır.", + "less.colorDecorators.enable.deprecationMessage": "`less.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır." +} \ No newline at end of file diff --git a/i18n/trk/extensions/css/package.i18n.json b/i18n/trk/extensions/css/package.i18n.json index 28a40ba1e3..66b4b1f060 100644 --- a/i18n/trk/extensions/css/package.i18n.json +++ b/i18n/trk/extensions/css/package.i18n.json @@ -2,80 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "CSS Dili Özellikleri", - "description": "CSS, LESS, SCSS dosyaları için zengin dil desteği sağlar.", - "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", - "css.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", - "css.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", - "css.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", - "css.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", - "css.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", - "css.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", - "css.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", - "css.lint.idSelector.desc": "Bu kurallar HTML'ye çok sıkı bağlı olduğundan seçiciler kimlikleri içermemelidir.", - "css.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", - "css.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", - "css.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", - "css.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", - "css.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", - "css.lint.unknownProperties.desc": "Bilinmeyen özellik.", - "css.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", - "css.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", - "css.lint.zeroUnits.desc": "Sıfır için birim gerekmez", - "css.trace.server.desc": "VS Code ve CSS dil sunucusu arasındaki iletişimi izler.", - "css.validate.title": "CSS doğrulamasını ve sorunların önem derecelerini denetler.", - "css.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", - "less.title": "LESS", - "less.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", - "less.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", - "less.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", - "less.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", - "less.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", - "less.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", - "less.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", - "less.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", - "less.lint.idSelector.desc": "Bu kurallar HTML'ye çok sıkı bağlı olduğundan seçiciler kimlikleri içermemelidir.", - "less.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", - "less.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", - "less.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", - "less.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", - "less.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", - "less.lint.unknownProperties.desc": "Bilinmeyen özellik.", - "less.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", - "less.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", - "less.lint.zeroUnits.desc": "Sıfır için birim gerekmez", - "less.validate.title": "LESS doğrulamasını ve sorunların önem derecelerini denetler.", - "less.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", - "scss.title": "SCSS (Sass)", - "scss.lint.argumentsInColorFunction.desc": "Geçersiz sayıda parametre", - "scss.lint.boxModel.desc": "Doldurma veya kenarlık kullanırken genişlik veya yükseklik kullanmayın", - "scss.lint.compatibleVendorPrefixes.desc": "Satıcıya özgü bir ön ek kullanırken satıcıya özgü diğer tüm özellikleri de dahil ettiğinizden emin olun", - "scss.lint.duplicateProperties.desc": "Yinelenen stil tanımları kullanmayın", - "scss.lint.emptyRules.desc": "Boş kural kümeleri kullanmayın", - "scss.lint.float.desc": "'float' kullanmaktan kaçının. Float'lar, düzenin herhangi bir unsuru değiştiğinde kolayca bozulan kırılgan CSS ile sonuçlanır.", - "scss.lint.fontFaceProperties.desc": "@font-face kuralı 'src' ve 'font-family' özelliklerini tanımlamalıdır", - "scss.lint.hexColorLength.desc": "Onaltılık renkler üç veya altı onaltılık sayıdan oluşmalıdır", - "scss.lint.idSelector.desc": "Bu kurallar HTML'ye çok sıkı bağlı olduğundan seçiciler kimlikleri içermemelidir.", - "scss.lint.ieHack.desc": "IE izinsiz girişleri yalnızca IE7 ve daha eski sürümler desteklenirken gereklidir", - "scss.lint.important.desc": "!important kullanmaktan kaçının. Tüm CSS'nin belirginlik düzeyi üzerindeki denetimin kaybedildiğinin ve yeniden düzenlenmesi gerektiğinin bir belirtisidir.", - "scss.lint.importStatement.desc": "İçe aktarma deyimleri paralel olarak yüklenmez", - "scss.lint.propertyIgnoredDueToDisplay.desc": "Özellik gösterim nedeniyle yoksayıldı. Örn. 'display: inline' ile width, height, margin-top, margin-bottom ve float özelliklerinin hiçbir etkisi olmaz", - "scss.lint.universalSelector.desc": "Evrensel seçici (*) yavaş olarak bilinir", - "scss.lint.unknownProperties.desc": "Bilinmeyen özellik.", - "scss.lint.unknownVendorSpecificProperties.desc": "Bilinmeyen satıcıya özel özellik.", - "scss.lint.vendorPrefix.desc": "Satıcıya özgü bir ön ek kullanırken standart özelliği de dahil edin", - "scss.lint.zeroUnits.desc": "Sıfır için birim gerekmez", - "scss.validate.title": "SCSS doğrulamasını ve sorunların önem derecelerini denetler.", - "scss.validate.desc": "Tüm doğrulamaları etkinleştirir veya devre dışı bırakır", - "less.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", - "scss.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", - "css.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", - "css.colorDecorators.enable.deprecationMessage": "`css.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır.", - "scss.colorDecorators.enable.deprecationMessage": "`scss.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır.", - "less.colorDecorators.enable.deprecationMessage": "`less.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır." + "displayName": "CSS Dil Temelleri", + "description": "CSS, LESS ve SCSS dosyaları için söz dizimi vurgulama ve ayraç eşleştirme sağlar." } \ No newline at end of file diff --git a/i18n/trk/extensions/emmet/package.i18n.json b/i18n/trk/extensions/emmet/package.i18n.json index 0aca22a488..b25d2ee3ad 100644 --- a/i18n/trk/extensions/emmet/package.i18n.json +++ b/i18n/trk/extensions/emmet/package.i18n.json @@ -34,8 +34,8 @@ "emmetExclude": "Emmet kısaltmalarının genişletilmeyeceği bir diller dizisi.", "emmetExtensionsPath": "Emmet profileri ve parçacıklarını içeren bir klasör yolu.'", "emmetShowExpandedAbbreviation": "Genişletilmiş Emmet kısaltmalarını öneriler olarak gösterir.\n\"inMarkupAndStylesheetFilesOnly\" seçeneği\" html, haml, jade, xml, xsl, css, scss, sass, less ve stylus'a uygulanır.\n\"always\" seçeneği işaretleme/css'den bağımsız olarak dosyanın tüm bölümlerine uygulanır.", - "emmetShowAbbreviationSuggestions": "Olası Emmet kısaltmalarını öneriler olarak gösterir. Stil dosyalarında veya emmet.showExpandedAbbreviation, \"never\" olarak ayarlandığında uygulanamaz.", - "emmetIncludeLanguages": "Varsayılan olarak desteklenmeyen dillerde Emmet kısaltmalarını etkinleştirin. Burada dil ile desteklenen emmet destekli dil arasında eşleme ekleyin.", + "emmetShowAbbreviationSuggestions": "Olası Emmet kısaltmalarını öneriler olarak gösterir. Stil dosyalarında veya emmet.showExpandedAbbreviation'a \"never\" değeri atandığında uygulanamaz.", + "emmetIncludeLanguages": "Varsayılan olarak desteklenmeyen dillerde Emmet kısaltmalarını etkinleştirin. Burada dil ile desteklenen emmet destekli dil arasında bir eşleme ekleyin.\nÖr: {\"vue-html\": \"html\", \"javascript\": \"javascriptreact\"}", "emmetVariables": "Emmet parçacıklarında kullanılacak değişkenler", "emmetTriggerExpansionOnTab": "Etkinleştirildiğinde, Emmet kısaltmaları TAB tuşuna basıldığında genişletilir.", "emmetPreferences": "Emmet'in bazı eylemleri ve çözümleyicilerinin davranışını değiştirmek için kullanılacak tercihler.", @@ -47,7 +47,7 @@ "emmetPreferencesCssBetween": "CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", "emmetPreferencesSassBetween": "Sass dosyalarında CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", "emmetPreferencesStylusBetween": "Stylus dosyalarında CSS kısaltmaları genişletilirken CSS özelliği ve değerinin arasına koyulacak sembol", - "emmetShowSuggestionsAsSnippets": "Doğru ise, Emmet önerileri, editor.snippetSuggestions ayarı ile sıralayabilmenizi sağlayan parçacıklar olarak gösterilir.", + "emmetShowSuggestionsAsSnippets": "Doğruysa, Emmet önerileri, editor.snippetSuggestions ayarı ile sıralayabilmenizi sağlayan parçacıklar olarak gösterilir.", "emmetPreferencesBemElementSeparator": "BEM filtresi kullanırken sınıflar için kullanılacak öğe ayrıcı", "emmetPreferencesBemModifierSeparator": "BEM filtresi kullanırken sınıflar için kullanılacak niteleyici ayrıcı", "emmetPreferencesFilterCommentBefore": "Yorum filtresi uygulandığında eşleşen öğenin önüne yerleştirilmesi gereken yorumun tanımı.", @@ -59,5 +59,7 @@ "emmetPreferencesCssWebkitProperties": "`-` ile başlayan Emmet kısaltmasında kullanıldığında 'webkit' önekini alacak virgülle ayrılmış CSS özellikleri. 'webkit' önekinden her zaman kaçınmak için boş bir dize olarak ayarlayın.", "emmetPreferencesCssMozProperties": "`-` ile başlayan Emmet kısaltmasında kullanıldığında 'moz' önekini alacak virgülle ayrılmış CSS özellikleri. 'moz' önekinden her zaman kaçınmak için boş bir dize olarak ayarlayın.", "emmetPreferencesCssOProperties": "`-` ile başlayan Emmet kısaltmasında kullanıldığında 'o' önekini alacak virgülle ayrılmış CSS özellikleri. 'o' önekinden her zaman kaçınmak için boş bir dize olarak ayarlayın.", - "emmetPreferencesCssMsProperties": "`-` ile başlayan Emmet kısaltmasında kullanıldığında 'ms' önekini alacak virgülle ayrılmış CSS özellikleri. 'ms' önekinden her zaman kaçınmak için boş bir dize olarak ayarlayın." + "emmetPreferencesCssMsProperties": "`-` ile başlayan Emmet kısaltmasında kullanıldığında 'ms' önekini alacak virgülle ayrılmış CSS özellikleri. 'ms' önekinden her zaman kaçınmak için boş bir dize olarak ayarlayın.", + "emmetPreferencesCssFuzzySearchMinScore": "Bulanık eşleştirilmiş kısaltmaların elde etmesi gereken minimum puan (0'dan 1'e kadar). Düşük değerler birçok yanlış pozitif eşleşme oluşturabilir, daha yüksek değerler olası eşleşmeleri azaltabilir.", + "emmetOptimizeStylesheetParsing": "\"false\" değeri atandığında, Emmet kısaltmalarının genişletilmesinde o anki konumun geçerli olup olmadığını belirlemek için tüm dosya ayrıştırılır. \"true\" değeri atandığında, css/scss/less dosyalarında sadece o anki konumun çevresi ayrıştırılır." } \ No newline at end of file diff --git a/i18n/trk/extensions/git/out/commands.i18n.json b/i18n/trk/extensions/git/out/commands.i18n.json index c7a037bf90..114eaf858a 100644 --- a/i18n/trk/extensions/git/out/commands.i18n.json +++ b/i18n/trk/extensions/git/out/commands.i18n.json @@ -11,9 +11,7 @@ "create branch": "$(plus) Yeni dal oluştur", "repourl": "Depo URL'si", "parent": "Üst Klasör", - "cancel": "$(sync~spin) Depo kopyalanıyor... İptal etmek için tıklayın", - "cancel tooltip": "Kopyalamayı iptal et", - "cloning": "Git deposu kopyalanıyor...", + "cloning": "'{0}' git deposu kopyalanıyor...", "openrepo": "Depoyu Aç", "proposeopen": "Kopyalanan depoyu açmak ister misiniz?", "init": "Git deposunun oluşturulacağı çalışma alanı klasörünü seçin", @@ -75,7 +73,7 @@ "ok": "Tamam", "push with tags success": "Başarılı bir şekilde etiketlerle gönderildi.", "pick remote": "'{0}' dalının yayınlanacağı bir uzak uçbirim seçin:", - "sync is unpredictable": "Bu eylem, '{0}' esas projesine commitleri gönderecek ve alacaktır.", + "sync is unpredictable": "Bu eylem, '{0}/{1}' deposuna commitleri gönderecek ve alacaktır.", "never again": "Tamam, Tekrar Gösterme", "no remotes to publish": "Deponuzda yayınlamanın yapılacağı hiçbir uzak uçbirim yapılandırılmamış.", "no changes stash": "Geçici olarak saklanacak bir değişiklik yok.", diff --git a/i18n/trk/extensions/git/package.i18n.json b/i18n/trk/extensions/git/package.i18n.json index b979528b9a..e9ce5fff76 100644 --- a/i18n/trk/extensions/git/package.i18n.json +++ b/i18n/trk/extensions/git/package.i18n.json @@ -77,6 +77,7 @@ "config.showInlineOpenFileAction": "Git değişiklikleri görünümünde satır içi Dosyayı Aç eyleminin gösterilip gösterilmeyeceğini denetler.", "config.inputValidation": "Commit mesajı doğrulamasının ne zaman gösterileceğini kontrol eder.", "config.detectSubmodules": "Git alt modüllerin otomatik olarak tespit edilip edilmeyeceğini denetler.", + "config.detectSubmodulesLimit": "Algılanan git alt modüllerinin limitini denetler.", "colors.modified": "Değiştirilen kaynakların rengi.", "colors.deleted": "Silinen kaynakların rengi.", "colors.untracked": "İzlenmeyen kaynakların rengi.", diff --git a/i18n/trk/extensions/html-language-features/client/out/htmlMain.i18n.json b/i18n/trk/extensions/html-language-features/client/out/htmlMain.i18n.json new file mode 100644 index 0000000000..cd480d4212 --- /dev/null +++ b/i18n/trk/extensions/html-language-features/client/out/htmlMain.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "htmlserver.name": "HTML Dil Sunucusu", + "folding.start": "Katlama Bölgesi Başlangıcı", + "folding.end": "Katlama Bölgesi Sonu" +} \ No newline at end of file diff --git a/i18n/trk/extensions/html-language-features/package.i18n.json b/i18n/trk/extensions/html-language-features/package.i18n.json new file mode 100644 index 0000000000..00e0da3830 --- /dev/null +++ b/i18n/trk/extensions/html-language-features/package.i18n.json @@ -0,0 +1,33 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "HTML Dili Özellikleri", + "description": "HTML, Razor ve Handlebar dosyaları için zengin dil desteği sağlar.", + "html.format.enable.desc": "Varsayılan HTML biçimlendiricisini etkinleştirin/devre dışı bırakın", + "html.format.wrapLineLength.desc": "Satır başına en fazla karakter miktarı (0 = devre dışı bırak)", + "html.format.unformatted.desc": "Yeniden biçimlendirilmeyecek virgülle ayrılmış etiketler listesi. 'null' değeri, https://www.w3.org/TR/html5/dom.html#phrasing-content adresinde listelenen tüm etiketleri varsayılan olarak belirler.", + "html.format.contentUnformatted.desc": "İçeriğin yeniden biçimlendirilmeyeceği virgülle ayrılmış etiketler listesi. 'null' değeri, 'pre' etiketini varsayılan olarak belirler.", + "html.format.indentInnerHtml.desc": "<head> ve <body> bölümlerini girintile.", + "html.format.preserveNewLines.desc": "Ögelerden önceki mevcut satır sonlarının korunup korunmayacağı. Yalnızca ögelerden önce çalışır, etiketler içinde veya metinde çalışmaz.", + "html.format.maxPreserveNewLines.desc": "Bir öbekte korunacak maksimum satır sonu sayısı. Sınırsız için 'null' değerini kullanın.", + "html.format.indentHandlebars.desc": "{{#foo}} ve {{/foo}}'yu biçimlendir ve girintile.", + "html.format.endWithNewline.desc": "Boş bir satırla bitir.", + "html.format.extraLiners.desc": "Kendilerinden önce ek bir boş satır bulunması gereken virgülle ayrılmış etiketler listesi. 'null' değeri, \"head, body, /html\" değerini varsayılan olarak belirler.", + "html.format.wrapAttributes.desc": "Öznitelikleri sarmala.", + "html.format.wrapAttributes.auto": "Öznitelikleri sadece satır uzunluğu aşıldığında sarmala.", + "html.format.wrapAttributes.force": "İlki hariç tüm öznitelikleri sarmala.", + "html.format.wrapAttributes.forcealign": "İlki hariç tüm öznitelikleri sarmala ve hizada tut.", + "html.format.wrapAttributes.forcemultiline": "Tüm öznitelikleri sarmala.", + "html.suggest.angular1.desc": "Yerleşik HTML dili desteğinin Angular V1 etiketlerini ve özelliklerini önerip önermeyeceğini yapılandırır.", + "html.suggest.ionic.desc": "Yerleşik HTML dili desteğinin Ionic etiketlerini, özelliklerini ve değerlerini önerip önermeyeceğini yapılandırır.", + "html.suggest.html5.desc": "Yerleşik HTML dili desteğinin HTML5 etiketlerini, özelliklerini ve değerlerini önerip önermeyeceğini yapılandırır.", + "html.trace.server.desc": "VS Code ve HTML dil sunucusu arasındaki iletişimi izler.", + "html.validate.scripts": "Yerleşik HTML dili desteğinin HTML5 gömülü betikleri doğrulayıp doğrulamayacağını yapılandırır.", + "html.validate.styles": "Yerleşik HTML dili desteğinin HTML5 gömülü stilleri doğrulayıp doğrulamayacağını yapılandırır.", + "html.autoClosingTags": "HTML etiketlerinin otomatik kapatılmasını etkinleştirin/devre dışı bırakın" +} \ No newline at end of file diff --git a/i18n/trk/extensions/html/package.i18n.json b/i18n/trk/extensions/html/package.i18n.json index 7dc01f1b78..7b449502bb 100644 --- a/i18n/trk/extensions/html/package.i18n.json +++ b/i18n/trk/extensions/html/package.i18n.json @@ -2,33 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "HTML Dili Özellikleri", - "description": "HTML, Razor ve Handlebar dosyaları için zengin dil desteği sağlar.", - "html.format.enable.desc": "Varsayılan HTML biçimlendiricisini etkinleştirin/devre dışı bırakın", - "html.format.wrapLineLength.desc": "Satır başına en fazla karakter miktarı (0 = devre dışı bırak)", - "html.format.unformatted.desc": "Yeniden biçimlendirilmeyecek virgülle ayrılmış etiketler listesi. 'null' değeri, https://www.w3.org/TR/html5/dom.html#phrasing-content adresinde listelenen tüm etiketleri varsayılan olarak belirler.", - "html.format.contentUnformatted.desc": "İçeriğin yeniden biçimlendirilmeyeceği virgülle ayrılmış etiketler listesi. 'null' değeri, 'pre' etiketini varsayılan olarak belirler.", - "html.format.indentInnerHtml.desc": "<head> ve <body> bölümlerini girintile.", - "html.format.preserveNewLines.desc": "Ögelerden önceki mevcut satır sonlarının korunup korunmayacağı. Yalnızca ögelerden önce çalışır, etiketler içinde veya metinde çalışmaz.", - "html.format.maxPreserveNewLines.desc": "Bir öbekte korunacak maksimum satır sonu sayısı. Sınırsız için 'null' değerini kullanın.", - "html.format.indentHandlebars.desc": "{{#foo}} ve {{/foo}}'yu biçimlendir ve girintile.", - "html.format.endWithNewline.desc": "Boş bir satırla bitir.", - "html.format.extraLiners.desc": "Kendilerinden önce ek bir boş satır bulunması gereken virgülle ayrılmış etiketler listesi. 'null' değeri, \"head, body, /html\" değerini varsayılan olarak belirler.", - "html.format.wrapAttributes.desc": "Öznitelikleri sarmala.", - "html.format.wrapAttributes.auto": "Öznitelikleri sadece satır uzunluğu aşıldığında sarmala.", - "html.format.wrapAttributes.force": "İlki hariç tüm öznitelikleri sarmala.", - "html.format.wrapAttributes.forcealign": "İlki hariç tüm öznitelikleri sarmala ve hizada tut.", - "html.format.wrapAttributes.forcemultiline": "Tüm öznitelikleri sarmala.", - "html.suggest.angular1.desc": "Yerleşik HTML dili desteğinin Angular V1 etiketlerini ve özelliklerini önerip önermeyeceğini yapılandırır.", - "html.suggest.ionic.desc": "Yerleşik HTML dili desteğinin Ionic etiketlerini, özelliklerini ve değerlerini önerip önermeyeceğini yapılandırır.", - "html.suggest.html5.desc": "Yerleşik HTML dili desteğinin HTML5 etiketlerini, özelliklerini ve değerlerini önerip önermeyeceğini yapılandırır.", - "html.trace.server.desc": "VS Code ve HTML dil sunucusu arasındaki iletişimi izler.", - "html.validate.scripts": "Yerleşik HTML dili desteğinin HTML5 gömülü betikleri doğrulayıp doğrulamayacağını yapılandırır.", - "html.validate.styles": "Yerleşik HTML dili desteğinin HTML5 gömülü stilleri doğrulayıp doğrulamayacağını yapılandırır.", - "html.experimental.syntaxFolding": "Sözdimine duyarlı katlama işaretleyicilerini etkinleştirin/devre dışı bırakın.", - "html.autoClosingTags": "HTML etiketlerinin otomatik kapatılmasını etkinleştirin/devre dışı bırakın" + "displayName": "HTML Dil Temelleri", + "description": "HTML dosyaları için söz dizimi vurgulama, ayraç eşleştirme ve kod parçacıkları sağlar." } \ No newline at end of file diff --git a/i18n/trk/extensions/json-language-features/client/out/jsonMain.i18n.json b/i18n/trk/extensions/json-language-features/client/out/jsonMain.i18n.json new file mode 100644 index 0000000000..34990f7158 --- /dev/null +++ b/i18n/trk/extensions/json-language-features/client/out/jsonMain.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "jsonserver.name": "JSON Dil Sunucusu" +} \ No newline at end of file diff --git a/i18n/trk/extensions/json-language-features/package.i18n.json b/i18n/trk/extensions/json-language-features/package.i18n.json new file mode 100644 index 0000000000..94799976a7 --- /dev/null +++ b/i18n/trk/extensions/json-language-features/package.i18n.json @@ -0,0 +1,20 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "JSON Dili Özellikleri", + "description": "JSON dosyaları için zengin dil desteği sağlar.", + "json.schemas.desc": "Şemaları geçerli projedeki JSON dosyalarıyla ilişkilendir", + "json.schemas.url.desc": "Bir şemanın URL'si veya geçerli dizindeki bir şemanın göreli yolu", + "json.schemas.fileMatch.desc": "JSON dosyaları şemalara çözümlenirken eşleşme için kullanılacak bir dosya düzenleri dizisi.", + "json.schemas.fileMatch.item.desc": "JSON dosyaları şemalara çözümlenirken eşleşme için '*' içerebilen bir dosya düzeni.", + "json.schemas.schema.desc": "Verilen URL için şema tanımı. Şema, yalnızca şema URL'sine erişimi önlemek için sağlanmalıdır.", + "json.format.enable.desc": "Varsayılan JSON biçimlendiricisini etkinleştirin/devre dışı bırakın (yeniden başlatma gerektirir)", + "json.tracing.desc": "VS Code ve JSON dil sunucusu arasındaki iletişimi izler.", + "json.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", + "json.colorDecorators.enable.deprecationMessage": "`json.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır." +} \ No newline at end of file diff --git a/i18n/trk/extensions/json/package.i18n.json b/i18n/trk/extensions/json/package.i18n.json index b9ead1ddcd..c90ee18586 100644 --- a/i18n/trk/extensions/json/package.i18n.json +++ b/i18n/trk/extensions/json/package.i18n.json @@ -6,16 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "displayName": "JSON Dili Özellikleri", - "description": "JSON dosyaları için zengin dil desteği sağlar.", - "json.schemas.desc": "Şemaları geçerli projedeki JSON dosyalarıyla ilişkilendir", - "json.schemas.url.desc": "Bir şemanın URL'si veya geçerli dizindeki bir şemanın göreli yolu", - "json.schemas.fileMatch.desc": "JSON dosyaları şemalara çözümlenirken eşleşme için kullanılacak bir dosya düzenleri dizisi.", - "json.schemas.fileMatch.item.desc": "JSON dosyaları şemalara çözümlenirken eşleşme için '*' içerebilen bir dosya düzeni.", - "json.schemas.schema.desc": "Verilen URL için şema tanımı. Şema, yalnızca şema URL'sine erişimi önlemek için sağlanmalıdır.", - "json.format.enable.desc": "Varsayılan JSON biçimlendiricisini etkinleştirin/devre dışı bırakın (yeniden başlatma gerektirir)", - "json.tracing.desc": "VS Code ve JSON dil sunucusu arasındaki iletişimi izler.", - "json.colorDecorators.enable.desc": "Renk dekoratörlerini etkinleştirir veya devre dışı bırakır", - "json.colorDecorators.enable.deprecationMessage": "`json.colorDecorators.enable` ayarı, `editor.colorDecorators` yüzünden kullanım dışıdır.", - "json.experimental.syntaxFolding": "Sözdizimi duyarlı katlama işaretçilerini etkinleştirin/devre dışı bırakın." + "displayName": "JSON Dil Temelleri", + "description": "JSON dosyaları için söz dizimi vurgulama ve ayraç eşleştirme sağlar." } \ No newline at end of file diff --git a/i18n/trk/extensions/markdown-basics/package.i18n.json b/i18n/trk/extensions/markdown-basics/package.i18n.json index 011e43dc3e..c24d4dc769 100644 --- a/i18n/trk/extensions/markdown-basics/package.i18n.json +++ b/i18n/trk/extensions/markdown-basics/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/trk/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json b/i18n/trk/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json new file mode 100644 index 0000000000..44f66398a7 --- /dev/null +++ b/i18n/trk/extensions/markdown-language-features/out/commands/onPreviewStyleLoadError.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "onPreviewStyleLoadError": "'markdown.styles' yüklenemedi: {0}" +} \ No newline at end of file diff --git a/i18n/trk/extensions/markdown-language-features/out/features/preview.i18n.json b/i18n/trk/extensions/markdown-language-features/out/features/preview.i18n.json new file mode 100644 index 0000000000..3a5b0eca0e --- /dev/null +++ b/i18n/trk/extensions/markdown-language-features/out/features/preview.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "lockedPreviewTitle": "[Önizleme] {0}", + "previewTitle": "{0} Önizlemesi" +} \ No newline at end of file diff --git a/i18n/trk/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json b/i18n/trk/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json new file mode 100644 index 0000000000..76db8cd58c --- /dev/null +++ b/i18n/trk/extensions/markdown-language-features/out/features/previewContentProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "preview.securityMessage.text": "Bu belgedeki bazı içerikler devre dışı bırakıldı", + "preview.securityMessage.title": "Markdown önizlemesinde potansiyel olarak tehlikeli veya güvenli olmayan içerik devre dışı bırakıldı. Güvenli olmayan içeriğe izin vermek veya betikleri etkinleştirmek için Markdown önizleme güvenlik ayarını değiştirin", + "preview.securityMessage.label": "İçerik Devre Dışı Güvenlik Uyarısı" +} \ No newline at end of file diff --git a/i18n/trk/extensions/markdown-language-features/out/security.i18n.json b/i18n/trk/extensions/markdown-language-features/out/security.i18n.json new file mode 100644 index 0000000000..e905bb535f --- /dev/null +++ b/i18n/trk/extensions/markdown-language-features/out/security.i18n.json @@ -0,0 +1,22 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "strict.title": "Katı", + "strict.description": "Sadece güvenli içeriği yükle", + "insecureLocalContent.title": "Güvenli olmayan yerel içeriğe izin ver", + "insecureLocalContent.description": "localhost'tan http üzerinde sunulan içeriğin yüklenmesini etkinleştir", + "insecureContent.title": "Güvenli olmayan içeriğe izin ver", + "insecureContent.description": "Http üzerinden içerik yüklemeyi etkinleştir", + "disable.title": "Devre Dışı Bırak", + "disable.description": "Tüm içeriğe ve betik yürütmeye izin ver. Tavsiye edilmez", + "moreInfo.title": "Daha Fazla Bilgi", + "enableSecurityWarning.title": "Bu çalışma alanında önizleme güvenlik uyarılarını etkinleştir", + "disableSecurityWarning.title": "Bu çalışma alanında önizleme güvenlik uyarılarını devre dışı bırak", + "toggleSecurityWarning.description": "İçerik güvenlik seviyesini etkilemez", + "preview.showPreviewSecuritySelector.title": "Bu çalışma alanında Markdown önizlemeleri için güvenlik ayarlarını seçin" +} \ No newline at end of file diff --git a/i18n/trk/extensions/markdown-language-features/package.i18n.json b/i18n/trk/extensions/markdown-language-features/package.i18n.json new file mode 100644 index 0000000000..c7a539dac4 --- /dev/null +++ b/i18n/trk/extensions/markdown-language-features/package.i18n.json @@ -0,0 +1,32 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "Markdown Dili Özellikleri", + "description": "Markdown için zengin dil desteği sağlar.", + "markdown.preview.breaks.desc": "Markdown önizlemesinde satır sonlarının nasıl gösterileceğini ayarlar. 'true' olarak ayarlamak, her yeni satırda bir <br> oluşturur.", + "markdown.preview.linkify": "Markdown önizlemesinde URL benzeri metinlerin bağlantıya çevrilmesini etkinleştir veya devre dışı bırak.", + "markdown.preview.doubleClickToSwitchToEditor.desc": "Düzenleyiciye geçiş yapmak için Markdown önizlemesine çift tıklayın.", + "markdown.preview.fontFamily.desc": "Markdown önizlemesinde kullanılan yazı tipi ailesini denetler.", + "markdown.preview.fontSize.desc": "Markdown önizlemesinde kullanılan yazı tipi boyutunu piksel olarak denetler.", + "markdown.preview.lineHeight.desc": "Markdown önizlemesinde kullanılan satır yüksekliğini denetler. Bu sayı yazı tipi boyutuna görecelidir.", + "markdown.preview.markEditorSelection.desc": "Markdown önizlemesinde geçerli düzenleyici seçimini işaretle.", + "markdown.preview.scrollEditorWithPreview.desc": "Markdown önizlemesi kaydırıldığında, düzenleyicinin görünümünü güncelle.", + "markdown.preview.scrollPreviewWithEditor.desc": "Markdown düzenleyicisi kaydırıldığında, önizlemenin görünümünü güncelle.", + "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Kullanım Dışı] Düzenleyicide seçili satırın görünmesi için Markdown önizlemesini kaydırır.", + "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "Bu ayar 'markdown.preview.scrollPreviewWithEditor' ile değiştirildi ve artık hiçbir etkisi bulunmamaktadır.", + "markdown.preview.title": "Önizlemeyi Aç", + "markdown.previewFrontMatter.dec": "YAML ön maddesinin Markdown önizlemesinde nasıl gösterilmesi gerektiğini ayarlar. 'hide' ön maddeyi kaldırır. Diğer türlü; ön madde, Markdown içeriği olarak sayılır.", + "markdown.previewSide.title": "Önizlemeyi Yana Aç", + "markdown.showLockedPreviewToSide.title": "Kilitlenmiş Önizlemeyi Yana Aç", + "markdown.showSource.title": "Kaynağı Göster", + "markdown.styles.dec": "Markdown önizlemesinde kullanılmak üzere CSS stil dosyalarını işaret eden bir URL'ler veya yerel yollar listesi. Göreli yollar, gezginde açılan klasöre göreli olarak yorumlanır.", + "markdown.showPreviewSecuritySelector.title": "Önizleme Güvenlik Ayarlarını Değiştir", + "markdown.trace.desc": "Markdown eklentisi için hata ayıklama günlüğünü etkinleştir.", + "markdown.preview.refresh.title": "Önizlemeyi Yenile", + "markdown.preview.toggleLock.title": "Önizleme Kilitlemeyi Aç/Kapat" +} \ No newline at end of file diff --git a/i18n/trk/extensions/markdown/out/features/preview.i18n.json b/i18n/trk/extensions/markdown/out/features/preview.i18n.json index c3d4db4abd..3a5b0eca0e 100644 --- a/i18n/trk/extensions/markdown/out/features/preview.i18n.json +++ b/i18n/trk/extensions/markdown/out/features/preview.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], diff --git a/i18n/trk/extensions/npm/out/npmView.i18n.json b/i18n/trk/extensions/npm/out/npmView.i18n.json new file mode 100644 index 0000000000..a032c07941 --- /dev/null +++ b/i18n/trk/extensions/npm/out/npmView.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.noDebugOptions": "Betiklerde node hata ayıklama seçeneği(ör. \"--inspect-brk\") eksik olduğundan hata ayıklamak için \"{0}\" başlatılamadı.", + "npm.scriptInvalid": "\"{0}\" betik dosyası bulunamadı. Görünümü yenilemeyi deneyin." +} \ No newline at end of file diff --git a/i18n/trk/extensions/npm/out/tasks.i18n.json b/i18n/trk/extensions/npm/out/tasks.i18n.json new file mode 100644 index 0000000000..30e9e07e3a --- /dev/null +++ b/i18n/trk/extensions/npm/out/tasks.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "npm.parseError": "Npm görev algılama: {0} dosyası ayrıştırılamadı" +} \ No newline at end of file diff --git a/i18n/trk/extensions/npm/package.i18n.json b/i18n/trk/extensions/npm/package.i18n.json index 294438d86f..b1dbbb9d92 100644 --- a/i18n/trk/extensions/npm/package.i18n.json +++ b/i18n/trk/extensions/npm/package.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,15 @@ "config.npm.runSilent": "npm komutlarını `--silent`(sessiz) seçeneğiyle çalıştır.", "config.npm.packageManager": "Betikleri çalıştırmada kullanılacak paket yöneticisi.", "config.npm.exclude": "Otomatik betik algılamadan hariç tutulacak klasörler için glob desenlerini yapılandırın.", + "config.npm.enableScriptExplorer": "Çalışma alanı bir 'package.json' dosyası içerdiğinde, npm betikleri için gezgin görünümünü etkinleştir.", "npm.parseError": "Npm görev algılama: {0} dosyası ayrıştırılamadı", "taskdef.script": "Özelleştirilecek npm betiği.", - "taskdef.path": "Betiği sağlayan package.json dosyasını içeren klasör yolu. Atlanabilir." + "taskdef.path": "Betiği sağlayan package.json dosyasını içeren klasör yolu. Atlanabilir.", + "view.name": "Npm Betikleri", + "command.refresh": "Yenile", + "command.run": "Çalıştır", + "command.debug": "Hata Ayıklama", + "command.openScript": "Aç", + "npm.scriptInvalid": "'{0}' betik dosyası bulunamadı. Görünümü yenilemeyi deneyin.", + "npm.noDebugOptions": "Betiklerde node hata ayıklama seçeneği(ör. '--inspect-brk') eksik olduğundan hata ayıklamak için '{0}' başlatılamadı." } \ No newline at end of file diff --git a/i18n/trk/extensions/php-language-features/out/features/validationProvider.i18n.json b/i18n/trk/extensions/php-language-features/out/features/validationProvider.i18n.json new file mode 100644 index 0000000000..d882c2764d --- /dev/null +++ b/i18n/trk/extensions/php-language-features/out/features/validationProvider.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "php.useExecutablePath": "{0} (çalışma alanı ayarı olarak tanımlı) yürütülebilir dosyasına PHP dosyalarını doğrulama izni veriyor musunuz?", + "php.yes": "İzin Ver", + "php.no": "İzin Verme", + "wrongExecutable": "{0} geçerli bir php yürütülebilir dosyası olmadığı için doğrulanamıyor. PHP yürütülebilir dosyasını yapılandırmak için 'php.validate.executablePath' ayarını kullanın.", + "noExecutable": "Hiçbir PHP yürütülebilir dosyası ayarlanmadığı için doğrulanamıyor. PHP yürütülebilir dosyasını yapılandırmak için 'php.validate.executablePath' ayarını kullanın.", + "unknownReason": "{0} yolu kullanılarak php çalıştırılamadı. Sebep bilinmiyor." +} \ No newline at end of file diff --git a/i18n/trk/extensions/php-language-features/package.i18n.json b/i18n/trk/extensions/php-language-features/package.i18n.json new file mode 100644 index 0000000000..9ee5b59f86 --- /dev/null +++ b/i18n/trk/extensions/php-language-features/package.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configuration.suggest.basic": "Yerleşik PHP dili önerilerinin etkinleştirilip etkinleştirilmediğini yapılandırır. Destek, PHP globalleri ve değişkenleri önerir.", + "configuration.validate.enable": "Yerleşik PHP doğrulamasını etkinleştir/devre dışı bırak.", + "configuration.validate.executablePath": "PHP çalıştırılabilir dosyasına işaret eder.", + "configuration.validate.run": "Doğrulayıcının kayıt esnasında mı tuşlama esnasında mı çalışacağı.", + "configuration.title": "PHP", + "commands.categroy.php": "PHP", + "command.untrustValidationExecutable": "PHP doğrulama yürütülebilir dosyasına izin verme (çalışma alanı ayarı olarak tanımlanır)", + "displayName": "PHP Dil Özellikleri", + "description": "PHP dosyaları için zengin dil desteği sağlar." +} \ No newline at end of file diff --git a/i18n/trk/extensions/php/package.i18n.json b/i18n/trk/extensions/php/package.i18n.json index a729f62807..42f1e7562a 100644 --- a/i18n/trk/extensions/php/package.i18n.json +++ b/i18n/trk/extensions/php/package.i18n.json @@ -2,17 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "configuration.suggest.basic": "Yerleşik PHP dili önerilerinin etkinleştirilip etkinleştirilmediğini yapılandırır. Destek, PHP globalleri ve değişkenleri önerir.", - "configuration.validate.enable": "Yerleşik PHP doğrulamasını etkinleştir/devre dışı bırak.", - "configuration.validate.executablePath": "PHP çalıştırılabilir dosyasına işaret eder.", - "configuration.validate.run": "Doğrulayıcının kayıt esnasında mı tuşlama esnasında mı çalışacağı.", - "configuration.title": "PHP", - "commands.categroy.php": "PHP", - "command.untrustValidationExecutable": "PHP doğrulama yürütülebilir dosyasına izin verme (çalışma alanı ayarı olarak tanımlanır)", - "displayName": "PHP Dil Özellikleri", - "description": "PHP dosyaları için gelişmiş kod tamamlama(IntelliSense), doğrulama ve dil temelleri sağlar." + "displayName": "PHP Dil Temelleri", + "description": "PHP dosyaları için söz dizimi vurgulama ve ayraç eşleştirme sağlar." } \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/commands.i18n.json b/i18n/trk/extensions/typescript-language-features/out/commands.i18n.json new file mode 100644 index 0000000000..8893bf346b --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/commands.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.projectConfigNoWorkspace": "Bir TypeScript veya JavaScript projesini kullanmak için lütfen bir klasör açın", + "typescript.projectConfigUnsupportedFile": "TypeScript mi yoksa JavaScript mi projesi olduğu tespit edilemedi. Desteklenmeyen dosya türü", + "typescript.projectConfigCouldNotGetInfo": "TypeScript mi yoksa JavaScript mi projesi olduğu tespit edilemedi", + "typescript.noTypeScriptProjectConfig": "Dosya bir TypeScript projesinin parçası değil. Daha fazla bilgi almak için [buraya]({0}) tıklayın.", + "typescript.noJavaScriptProjectConfig": "Dosya bir JavaScript projesinin parçası değil. Daha fazla bilgi almak için [buraya]({0}) tıklayın.", + "typescript.configureTsconfigQuickPick": "tsconfig.json'u yapılandır", + "typescript.configureJsconfigQuickPick": "jsconfig.json'u yapılandır" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json new file mode 100644 index 0000000000..73c28f59b2 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/completionItemProvider.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "selectCodeAction": "Uygulanacak kod eylemini seçin", + "acquiringTypingsLabel": "Tuşlamalar alınıyor...", + "acquiringTypingsDetail": "IntelliSense için tuşlama tanımları alınıyor...", + "autoImportLabel": "{0} kaynağından otomatik içe aktar" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json new file mode 100644 index 0000000000..9125b191bf --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/directiveCommentCompletionProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "ts-check": "Bir JavaScript dosyasının anlamsal kontrolünü etkinleştirir. Bir dosyanın en üstünde olmalıdır.", + "ts-nocheck": "Bir JavaScript dosyasının anlamsal kontrolünü devre dışı bırakır. Bir dosyanın en üstünde olmalıdır.", + "ts-ignore": "Bir dosyanın sonraki satırında @ts-check hatalarını bastırır." +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json new file mode 100644 index 0000000000..3561a581ba --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/implementationsCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneImplementationLabel": "1 uygulama", + "manyImplementationLabel": "{0} uygulama", + "implementationsErrorLabel": "Uygulamalar belirlenemedi" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json new file mode 100644 index 0000000000..d6c2956028 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/jsDocCompletionProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "typescript.jsDocCompletionItem.documentation": "JSDoc yorumu" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/organizeImports.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/organizeImports.i18n.json new file mode 100644 index 0000000000..4f692e9af1 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/organizeImports.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oraganizeImportsAction.title": "İçe Aktarımları Düzenle" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json new file mode 100644 index 0000000000..323d1a9939 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/quickFixProvider.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "fixAllInFileLabel": "{0} (Dosyadaki tümünü düzelt)" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json new file mode 100644 index 0000000000..48ebde6847 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/referencesCodeLensProvider.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "oneReferenceLabel": "1 başvuru", + "manyReferenceLabel": "{0} başvuru", + "referenceErrorLabel": "Başvurular belirlenemedi" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/features/taskProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/features/taskProvider.i18n.json new file mode 100644 index 0000000000..e69846fe63 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/features/taskProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "buildTscLabel": "derleme - {0}", + "buildAndWatchTscLabel": "izleme - {0}" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json b/i18n/trk/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json new file mode 100644 index 0000000000..d378e70d32 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/typescriptServiceClient.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "noServerFound": "{0} yolu geçerli bir tsserver kurulumuna işaret etmiyor. Paketlenmiş TypeScript sürümüne geri dönülüyor.", + "serverCouldNotBeStarted": "TypeScript dil sunucusu başlatılamadı. Hata mesajı: {0}", + "typescript.openTsServerLog.notSupported": "TS Sunucu günlüğü için TS 2.2.2+ gerekiyor", + "typescript.openTsServerLog.loggingNotEnabled": "TS Sunucu günlüğü kapalı. Lütfen `typescript.tsserver.log` ögesini ayarlayın ve günlüğe yazmayı etkinleştirmek için TS sunucusunu yeniden başlatın", + "typescript.openTsServerLog.enableAndReloadOption": "Günlüğe yazmayı etkinleştir ve TS sunucusunu yeniden başlat", + "typescript.openTsServerLog.noLogFile": "TS sunucu günlüğe yazmaya başlamadı.", + "openTsServerLog.openFileFailedFailed": "TS Sunucu günlük dosyası açılamadı", + "serverDiedAfterStart": "TypeScript dil hizmeti, başladıktan hemen sonra 5 kez kapandı. Hizmet yeniden başlatılmayacaktır.", + "serverDiedReportIssue": "Sorun Bildir", + "serverDied": "TypeScript dil hizmeti, son 5 dakikada 5 kez beklenmedik şekilde kapandı." +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/api.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/api.i18n.json new file mode 100644 index 0000000000..4a8a4fba71 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/api.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "invalidVersion": "geçersiz sürüm" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/logger.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/logger.i18n.json new file mode 100644 index 0000000000..8f5ef5415b --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/logger.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "channelName": "TypeScript" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/projectStatus.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/projectStatus.i18n.json new file mode 100644 index 0000000000..61c40dd9a3 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/projectStatus.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "hintExclude": "Proje çapında JavaScript/TypeScript dil özelliklerini etkinleştirmek için, şunlar gibi birçok dosyaya sahip klasörleri hariç tutun: {0}", + "hintExclude.generic": "Proje çapında JavaScript/TypeScript dil özelliklerini etkinleştirmek için, üzerinde çalışmadığınız kaynak dosyalar içeren büyük klasörleri hariç tutun.", + "large.label": "Hariç Tutmaları Yapılandır", + "hintExclude.tooltip": "Proje çapında JavaScript/TypeScript dil özelliklerini etkinleştirmek için, üzerinde çalışmadığınız kaynak dosyalar içeren büyük klasörleri hariç tutun." +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json new file mode 100644 index 0000000000..6f7d1c5609 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/typingsStatus.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "installingPackages": "Daha iyi TypeScript IntelliSense için veri alınıyor", + "typesInstallerInitializationFailed.title": "JavaScript dil özellikleri için tuşlama dosyaları yüklenemedi. Lütfen NPM'in yüklenmiş olduğundan emin olun veya kullanıcı ayarlarınızdaki 'typescript.npm' ögesini yapılandırın. Daha fazla bilgi almak için [buraya]({0}) tıklayın.", + "typesInstallerInitializationFailed.doNotCheckAgain": "Tekrar Gösterme" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/versionPicker.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/versionPicker.i18n.json new file mode 100644 index 0000000000..bbccc6cfbc --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/versionPicker.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "useVSCodeVersionOption": "VS Code'un Sürümünü Kullan", + "useWorkspaceVersionOption": "Çalışma Alanı Sürümünü Kullan", + "learnMore": "Daha Fazla Bilgi Edin", + "selectTsVersion": "JavaScript ve TypeScript dil özellikleri için kullanılacak TypeScript sürümünü seçin" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/out/utils/versionProvider.i18n.json b/i18n/trk/extensions/typescript-language-features/out/utils/versionProvider.i18n.json new file mode 100644 index 0000000000..86f606ebb3 --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/out/utils/versionProvider.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "couldNotLoadTsVersion": "Bu yolda TypeScript sürümü yüklenemedi", + "noBundledServerFound": "VS Code'un tsserver'ı hatalı bir virüs tespit aracı gibi bir uygulama tarafından silindi. Lütfen VS Code'u yeniden yükleyin." +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript-language-features/package.i18n.json b/i18n/trk/extensions/typescript-language-features/package.i18n.json new file mode 100644 index 0000000000..1adbd875cd --- /dev/null +++ b/i18n/trk/extensions/typescript-language-features/package.i18n.json @@ -0,0 +1,65 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "displayName": "TypeScript ve JavaScript Dili Özellikleri", + "description": "JavaScript ve TypeScript için zengin dil desteği sağlar.", + "typescript.reloadProjects.title": "Projeyi Yeniden Yükle", + "javascript.reloadProjects.title": "Projeyi Yeniden Yükle", + "configuration.typescript": "TypeScript", + "typescript.useCodeSnippetsOnMethodSuggest.dec": "İşlevleri parametre imzalarıyla tamamlayın.", + "typescript.tsdk.desc": "Kullanılacak tsserver ve lib*.d.ts dosyalarını içeren klasör yolunu belirtir.", + "typescript.disableAutomaticTypeAcquisition": "Otomatik tür kazanımını devre dışı bırakır. TypeScript >= 2.0.6 gerektirir.", + "typescript.tsserver.log": "TS sunucusunun bir dosyaya günlük yazmasını etkinleştirir. Bu günlük, TS Sunucu sorunlarını teşhis etmek için kullanılabilir. Günlük dosya yollarını, kaynak kodunu ve projenizdeki diğer muhtemel hassas bilgileri içerebilir.", + "typescript.tsserver.pluginPaths": "Typescript Dil Hizmeti eklentilerinin aranacağı ek yollar. TypeScript >= 2.3.0 gerektirir.", + "typescript.tsserver.pluginPaths.item": "Mutlak veya göreli bir yol. Göreli yol, çalışma alanı klasörü veya klasörlerine göre çözümlenecektir.", + "typescript.tsserver.trace": "TS sunucusuna gönderilen mesajları izlemeyi etkinleştirir. Bu izleme, TS Sunucu sorunlarını teşhis etmek için kullanılabilir. İzleme; dosya yollarını, kaynak kodunu ve projenizdeki diğer muhtemel hassas bilgileri içerebilir.", + "typescript.validate.enable": "TypeScript doğrulamasını etkinleştir veya devre dışı bırak.", + "typescript.format.enable": "Varsayılan TypeScript biçimlendiricisini etkinleştirin/devre dışı bırakın.", + "javascript.format.enable": "Varsayılan JavaScript biçimlendiricisini etkinleştir veya devre dışı bırak.", + "format.insertSpaceAfterCommaDelimiter": "Virgül sınırlayıcısından sonra boşluk eklenmesini tanımlar.", + "format.insertSpaceAfterConstructor": "Oluşturucu anahtar kelimesinden sonra boşluk eklenip eklenmeyeceğini tanımlar. TypeScript >= 2.3.0 gerektirir.", + "format.insertSpaceAfterSemicolonInForStatements": "Bir ifade için noktalı virgülden sonra boşluk eklenmesini tanımlar.", + "format.insertSpaceBeforeAndAfterBinaryOperators": "Bir ikili operatöründen sonra boşluk eklenmesini tanımlar.", + "format.insertSpaceAfterKeywordsInControlFlowStatements": "Bir kontrol akışı ifadesi için anahtar kelimelerden sonra boşluk eklenmesini tanımlar.", + "format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": "Anonim fonksiyonlar için \"function\" anahtar kelimesinden sonra boşluk eklenmesini tanımlar.", + "format.insertSpaceBeforeFunctionParenthesis": "Fonksiyon argüman parantezlerinden önce boşluk eklenmesini tanımlar. TypeScript >= 2.1.5 gerektirir.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": "Boş olmayan parantezler açıldıktan sonra ve kapatılmadan önce boşluk eklenmesini tanımlar.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": "Boş olmayan köşeli parantezler açıldıktan sonra ve kapatılmadan önce boşluk eklenmesini tanımlar.", + "format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": "Boş olmayan küme parantezleri açıldıktan sonra ve kapatılmadan önce boşluk eklenmesini tanımlar. TypeScript >= 2.3.0 gerektirir.", + "format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": "Şablon dizesi ayraçları açıldıktan sonra ve kapatılmadan önce boşluk eklenmesini tanımlar. TypeScript >= 2.0.6 gerektirir.", + "format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "JSX ifadesi ayraçları açıldıktan sonra ve kapatılmadan önce boşluk eklenmesini tanımlar. TypeScript >= 2.0.6 gerektirir.", + "format.insertSpaceAfterTypeAssertion": "TypeScript'te tür iddialarından sonra boşluk eklenip eklenmeyeceğini tanımlar. TypeScript >= 2.4 gerektirir.", + "format.placeOpenBraceOnNewLineForFunctions": "Fonksiyonlarda bir açılış ayracının yeni satıra koyulup koyulmayacağını tanımlar.", + "format.placeOpenBraceOnNewLineForControlBlocks": "Kontrol bloklarında bir açılış ayracının yeni satıra koyulup koyulmayacağını tanımlar.", + "javascript.validate.enable": "JavaScript doğrulamasını etkinleştir veya devre dışı bırak.", + "typescript.goToProjectConfig.title": "Proje Yapılandırmasına Git", + "javascript.goToProjectConfig.title": "Proje Yapılandırmasına Git", + "javascript.referencesCodeLens.enabled": "JavaScript dosyalarında başvuru kod objektifini etkinleştir veya devre dışı bırak.", + "typescript.referencesCodeLens.enabled": "TypeScript dosyalarında başvuru kod objektifini etkinleştir veya devre dışı bırak. TypeScript >= 2.0.6 gerektirir.", + "typescript.implementationsCodeLens.enabled": "Uygulama kod objektifini etkinleştir veya devre dışı bırak. TypeScript >= 2.2.0 gerektirir.", + "typescript.openTsServerLog.title": "TS Sunucu günlüğünü aç", + "typescript.restartTsServer": "TS sunucusunu yeniden başlat", + "typescript.selectTypeScriptVersion.title": "TypeScript Sürümünü Seç", + "typescript.reportStyleChecksAsWarnings": "Stil kontrollerini uyarı olarak bildir", + "jsDocCompletion.enabled": "Otomatik JSDoc yorumlarını etkinleştir veya devre dışı bırak.", + "javascript.implicitProjectConfig.checkJs": "JavaScript dosyalarının anlamsal kontrolünü etkinleştir veya devre dışı bırak. Mevcut jsconfig.json veya tsconfig.json dosyaları bu ayarı geçersiz kılar. TypeScript >= 2.3.1 gerektirir.", + "typescript.npm": "Otomatik Tür Kazanımı için kullanılacak NPM yürütülebilir dosyasının yolunu belirtir. TypeScript >= 2.3.4 gerektirir.", + "typescript.check.npmIsInstalled": "Otomatik Tür Kazanımı için NPM'in yüklü olup olmadığını kontrol et.", + "javascript.nameSuggestions": "JavaScript öneri listelerindeki dosyadan benzersiz adları eklemeyi etkinleştir veya devre dışı bırak.", + "typescript.tsc.autoDetect": "tsc görevlerinin otomatik algılanmasını denetler. 'off' bu özelliği devre dışı bırakır. 'build' sadece bir kez çalışan derleme görevleri oluşturur. 'watch' sadece derleme ve izleme görevleri oluşturur. 'on' derleme ve izleme görevlerinin her ikisini de oluşturur. Varsayılan 'on'dur. ", + "typescript.problemMatchers.tsc.label": "TypeScript sorunları", + "typescript.problemMatchers.tscWatch.label": "TypeScript sorunları (izleme modu)", + "typescript.quickSuggestionsForPaths": "Bir içe aktarım yolu girerken hızlı önerileri etkinleştir/devre dışı bırak.", + "typescript.locale": "TypeScript hatalarını bildirirken kullanılarak dili(bölgeyi) ayarlar. TypeScript >= 2.6.0 gerektirir. 'null' varsayılanı, TypeScript hataları için VS Code'un dil(bölge) ayarlarını kullanır.", + "javascript.implicitProjectConfig.experimentalDecorators": "Bir projenin parçası olmayan JavaScript dosyaları için deneysel dekoratörler ('experimentalDecorators') özelliğini etkinleştir veya devre dışı bırak. Mevcut jsconfig.json veya tsconfig.json dosyaları bu ayarı geçersiz kılar. TypeScript >= 2.3.1 gerektirir.", + "typescript.autoImportSuggestions.enabled": "Otomatik içe aktarım önerilerini etkinleştir/devre dışı bırak. TypeScript >= 2.6.1 gerektirir.", + "typescript.experimental.syntaxFolding": "Sözdimine duyarlı katlama işaretleyicilerini etkinleştirin/devre dışı bırakın.", + "taskDefinition.tsconfig.description": "TS derlemesini tanımlayan tsconfig dosyası.", + "javascript.suggestionActions.enabled": "Düzenleyicideki JavaScript dosyalarında öneri tanılamayı etkinleştir veya devre dışı bırak. TypeScript >= 2.8 gerektirir.", + "typescript.suggestionActions.enabled": "Düzenleyicideki TypeScript dosyalarında öneri tanılamayı etkinleştir veya devre dışı bırak. TypeScript >= 2.8 gerektirir." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/base/node/zip.i18n.json b/i18n/trk/src/vs/base/node/zip.i18n.json index f8ecffe31a..2e3412b9ed 100644 --- a/i18n/trk/src/vs/base/node/zip.i18n.json +++ b/i18n/trk/src/vs/base/node/zip.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "incompleteExtract": "Tamamlanamadı. {1} girdiden {0} tanesi çıkarıldı", "notFound": "{0}, zip içerisinde bulunamadı." } \ No newline at end of file diff --git a/i18n/trk/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json b/i18n/trk/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json index f3ffad7178..b3174c22b7 100644 --- a/i18n/trk/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json +++ b/i18n/trk/src/vs/code/electron-browser/issue/issueReporterMain.i18n.json @@ -2,20 +2,21 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "previewOnGitHub": "GitHub'da Önizle", "loadingData": "Veri yükleniyor...", + "rateLimited": "GitHub sorgu sınırı aşıldı. Lütfen bekleyin.", "similarIssues": "Benzer sorunlar", "open": "Aç", "closed": "Kapalı", - "noResults": "Sonuç bulunamadı", + "noSimilarIssues": "Benzer bir sorun bulunmadı", "settingsSearchIssue": "Ayar Arama Sorunu", "bugReporter": "Hata Raporu", - "performanceIssue": "Performans Sorunu", "featureRequest": "Özellik İsteği", + "performanceIssue": "Performans Sorunu", "stepsToReproduce": "Yeniden oluşturma adımları", "bugDescription": "Sorunu güvenilir şekilde yeniden oluşturmak için gerekli adımları paylaşın. Lütfen gerçekleşen ve beklenen sonuçları ekleyin. GitHub-tarzı Markdown'ı destekliyoruz. GitHub'da önizleme yaptığımızda sorununuzu düzenleyebilecek ve ekran görüntüleri ekleyebileceksiniz.", "performanceIssueDesciption": "Bu performans sorunu ne zaman oluştu? Başlangıçta mı yoksa belirli eylemlerden sonra mı oluşuyor? GitHub-tarzı Markdown'ı destekliyoruz. GitHub'da önizleme yaptığımızda sorununuzu düzenleyebilecek ve ekran görüntüleri ekleyebileceksiniz.", diff --git a/i18n/trk/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json b/i18n/trk/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json index 8938571dbc..e80a0b446f 100644 --- a/i18n/trk/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json +++ b/i18n/trk/src/vs/code/electron-browser/issue/issueReporterPage.i18n.json @@ -2,12 +2,16 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "completeInEnglish": "Lütfen formu İngilizce olarak doldurunuz.", "issueTypeLabel": "Bu bir", + "vscode": "Visual Studio Code", + "extension": "Eklenti", + "disableExtensions": "tüm eklentileri devre dışı bırakıp pencereyi yeniden yükleyin", + "chooseExtension": "Eklenti", "issueTitleLabel": "Başlık", "issueTitleRequired": "Lütfen bir başlık girin.", "titleLengthValidation": "Başlık çok uzun.", @@ -18,13 +22,6 @@ "extensions": "Eklentilerim", "searchedExtensions": "Aranan Eklentiler", "settingsSearchDetails": "Ayar Arama Detayları", - "tryDisablingExtensions": "Eklentiler devre dışı bırakıldığında sorun yeniden oluşturulabiliyor mu?", - "yes": "Evet", - "no": "Hayır", - "disableExtensionsLabelText": "Sorunu {0} sonrasında yeniden oluşturmaya çalışın.", - "disableExtensions": "tüm eklentileri devre dışı bırakıp pencereyi yeniden yükleyin", - "showRunningExtensionsLabelText": "Bunun bir eklenti sorunu olduğundan şüpheleniyorsanız, eklentideki sorunu bildirmek için {0}.", - "showRunningExtensions": "çalışan tüm eklentileri göster", "details": "Lütfen detayları giriniz.", "loadingData": "Veri yükleniyor..." } \ No newline at end of file diff --git a/i18n/trk/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json b/i18n/trk/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json new file mode 100644 index 0000000000..9e32cb61fb --- /dev/null +++ b/i18n/trk/src/vs/code/electron-browser/processExplorer/processExplorerMain.i18n.json @@ -0,0 +1,15 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cpu": "İşlemci %", + "memory": "Bellek (MB)", + "pid": "pid", + "name": "Adı", + "killProcess": "İşlemi Sonlandır", + "forceKillProcess": "İşlemi Sonlanmaya Zorla" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/code/electron-main/menus.i18n.json b/i18n/trk/src/vs/code/electron-main/menus.i18n.json index 950ebc12cf..fc5e43d9d3 100644 --- a/i18n/trk/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/trk/src/vs/code/electron-main/menus.i18n.json @@ -146,6 +146,7 @@ "miConditionalBreakpoint": "&&Koşullu Kesme Noktası...", "miColumnBreakpoint": "&&Sütun Kesme Noktası", "miFunctionBreakpoint": "&&Fonksiyon Kesme Noktası", + "miLogPoint": "&&Günlük Noktası...", "miNewBreakpoint": "&&Yeni Kesme Noktası", "miEnableAllBreakpoints": "Tüm Kesme Noktalarını Etkinleştir", "miDisableAllBreakpoints": "&&Tüm Kesme Noktalarını Devre Dışı Bırak", @@ -161,6 +162,7 @@ "mMergeAllWindows": "Tüm Pencereleri Birleştir", "miToggleDevTools": "&&Geliştirici Araçlarını Aç/Kapat", "miAccessibilityOptions": "&&Erişilebilirlik Seçenekleri", + "miOpenProcessExplorerer": "İşlem &&Yöneticisini Aç", "miReportIssue": "&&Sorun Bildir", "miWelcome": "&&Hoş Geldiniz", "miInteractivePlayground": "&&İnteraktif Oyun Alanı", diff --git a/i18n/trk/src/vs/editor/browser/widget/diffReview.i18n.json b/i18n/trk/src/vs/editor/browser/widget/diffReview.i18n.json index eb26f9b5c6..fb5b74cac3 100644 --- a/i18n/trk/src/vs/editor/browser/widget/diffReview.i18n.json +++ b/i18n/trk/src/vs/editor/browser/widget/diffReview.i18n.json @@ -7,7 +7,10 @@ "Do not edit this file. It is machine generated." ], "label.close": "Kapat", - "header": "Farklılık {0}/{1}: orijinal {2}, {3} satırları, değiştirilen {4}, {5} satırları", + "no_lines": "hiçbir satır", + "one_line": "1 satır", + "more_lines": "{0} satır", + "header": "Farklılık {0}/{1}: orijinal {2}, {3}, değiştirilen {4}, {5}", "blankLine": "boş", "equalLine": "orijinal {0}, değiştirilen {1}: {2}", "insertLine": "+ değiştirilen {0}: {1}", diff --git a/i18n/trk/src/vs/editor/common/commonCodeEditor.i18n.json b/i18n/trk/src/vs/editor/common/commonCodeEditor.i18n.json new file mode 100644 index 0000000000..782a6d9ff8 --- /dev/null +++ b/i18n/trk/src/vs/editor/common/commonCodeEditor.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cursors.maximum": "İmleç sayısı {0} ile sınırlandırılmış durumda." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json index b255802096..b756815007 100644 --- a/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -16,7 +16,7 @@ "lineNumbers.on": "Satır numaraları mutlak sayı olarak gösterilir.", "lineNumbers.relative": "Satır numaraları imlecin konumuna olan uzaklık olarak gösterilir.", "lineNumbers.interval": "Satır numaraları her 10 satırda bir gösterilir.", - "lineNumbers": "Satır numaralarının görüntülenmesini denetler. Olası değerler 'on', 'off', 'relative' ve 'interval'dir.\n", + "lineNumbers": "Satır numaralarının görüntülenmesini denetler.", "rulers": "Belirli bir eşit genişlikli karakterlerden sonra dikey cetveller göster. Birden çok cetvel için birden çok değer kullanın. Dizi boş ise cetvel gösterilmez", "wordSeparators": "Sözcüklerle ilgili gezinti veya işlem yaparken kelime ayırıcı olarak kullanılacak karakterler", "tabSize": "Bir sekmenin eşit olduğu boşluk sayısı. Bu ayar, `editor.detectIndentation` açıkken dosya içeriğine bağlı olarak geçersiz kılınır.", @@ -28,8 +28,8 @@ "scrollBeyondLastLine": "Düzenleyicinin son satırın ötesine ilerleyip ilerlemeyeceğini denetler", "smoothScrolling": "Düzenleyicinin bir animasyon kullanarak kaydırıp kaydırmayacağını denetler", "minimap.enabled": "Mini haritanın gösterilip gösterilmeyeceğini denetler", - "minimap.side": "Mini haritanın görüntüleneceği tarafı denetler. Olası değerler 'right' ve 'left'tir", - "minimap.showSlider": "Mini harita kaydıracının otomatik olarak gizlenip gizlenmeyeceğini denetler. Alabileceği değerler 'always' ve 'mouseover'dır.", + "minimap.side": "Mini haritanın görüntüleneceği tarafı denetler.", + "minimap.showSlider": "Mini harita kaydıracının otomatik olarak gizlenip gizlenmeyeceğini denetler.", "minimap.renderCharacters": "(Renk blokları yerine) Bir satırdaki gerçek harfleri göster", "minimap.maxColumn": "Hazırlanacak mini haritanın azami genişliğini belirli sayıda sütunla sınırla", "find.seedSearchStringFromSelection": "Bulma Araç Çubuğu'ndaki arama metninin, düzenleyicideki seçili alandan beslenmesini denetler", @@ -46,6 +46,7 @@ "multiCursorModifier.ctrlCmd": "Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir.", "multiCursorModifier.alt": "Windows ve Linux'da `Alt` ve macOS'de `Option` ile eşleşir.", "multiCursorModifier": "Fare ile birden çok imleç eklenmesinde kullanılacak değiştirici. `ctrlCmd` Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir. Tanıma Git ve Bağlantıyı Aç fare hareketleri, birden çok imleç değiştiricisi ile çakışmayacak şekilde uyum sağlarlar.", + "multiCursorMergeOverlapping": "Üst üste geldiğinde çoklu imleçleri birleştir.", "quickSuggestions.strings": "Dizelerin içinde hızlı önerileri etkinleştir.", "quickSuggestions.comments": "Yorumların içinde hızlı önerileri etkinleştir.", "quickSuggestions.other": "Dizeler ve yorumlar dışında hızlı önerileri etkinleştirin.", @@ -76,7 +77,7 @@ "occurrencesHighlight": "Düzenleyicinin semantik sembol tekrarlamalarını vurgulayıp vurgulamayacağını denetler", "overviewRulerLanes": "Genel bakış cetvelinde aynı konumda gösterilebilecek süsleme sayısını denetler", "overviewRulerBorder": "Genel bakış cetvelinin etrafına bir kenarlık çizilmesi gerekip gerekmediğini denetler.", - "cursorBlinking": "İmleç animasyon stilini denetler, olası değerler 'blink', 'smooth', 'phase', 'expand' ve 'solid'dir", + "cursorBlinking": "İmleç animasyon stilini denetler.", "mouseWheelZoom": "Ctrl tuşuna basarken fare tekerleği ile düzenleyici yazı tipini yakınlaştırın", "cursorStyle": "İmleç stilini denetler, kabul edilen değerler: 'block', 'block-outline', 'line', 'line-thin', 'underline' ve 'underline-thin'", "cursorWidth": "editor.cursorStyle, 'line' olarak ayarlandığında imlecin genişliğini denetler", @@ -86,8 +87,11 @@ "renderControlCharacters": "Düzenleyicinin kontrol karakterlerini gösterip göstermemesini denetler", "renderIndentGuides": "Düzenleyicinin girinti kılavuzlarını gösterip göstermemesini denetler", "renderLineHighlight": "Düzenleyicinin geçerli satır vurgusunu nasıl göstereceğini denetler, seçenekler: 'none', 'gutter', 'line', ve 'all'.", - "codeLens": "Düzenleyicinin kod objektiflerini gösterip göstermediğini denetler", + "codeLens": "Düzenleyicinin Kod Objektifi gösterip göstermeyeceğini denetler", "folding": "Düzenleyicide kod katlamanın etkin olup olmadığını denetler", + "foldingStrategyAuto": "Mevcutsa dile özel katlama stratejisi kullan, mevcut değilse girintileme tabanlı stratejiyi kullan.", + "foldingStrategyIndentation": "Daima girintileme tabanlı katlama stratejisini kullan", + "foldingStrategy": "Katlama aralıklarının hesaplanma şeklini denetler. 'auto' seçimi, mevcutsa dile özel katlama stratejisi kullanır. 'indentation' ise girintileme tabanlı katlama stratejisinin kullanılmasını zorlar.", "showFoldingControls": "Oluktaki kat kontrollerinin otomatik olarak gizlenip gizlenmeyeceğini denetler.", "matchBrackets": "Eşleşen ayraçları, onlardan biri seçildiğinde vurgula.", "glyphMargin": "Düzenleyicinin dikey glif boşluğunu oluşturup oluşturmayacağını kontrol eder. Glif boşluğu çoğunlukla hata ayıklamak için kullanılır.", @@ -102,8 +106,12 @@ "links": "Düzenleyicinin bağlantıları otomatik algılayıp, onları tıklanabilir yapıp yapmayacağını denetler", "colorDecorators": "Düzenleyicinin satır içi renk dekoratörlerini ve renk seçiciyi gösterip göstermemesini denetler.", "codeActions": "Kod eylemleri ampulunu etkinleştirir", + "codeActionsOnSave.organizeImports": "Kaydederken \"içe aktarımları düzenle\" çalıştırılsın mı?", + "codeActionsOnSave": "Kaydetme esnasında çalıştırılacak kod eylem türleri.", + "codeActionsOnSaveTimeout": "Kaydetme esnasında çalıştırılacak kod eylem türleri için zaman aşımı.", "selectionClipboard": "Linux birincil panosunun desteklenip desteklenmeyeceğini denetler.", "sideBySide": "Karşılaştırma düzenleyicisinin farklılıkları yan yana mı yoksa satır içinde mi göstereceğini denetler", "ignoreTrimWhitespace": "Karşılaştırma düzenleyicisinin baştaki veya sondaki boşluklardaki değişmeleri farklılık olarak gösterip göstermemesini denetler", + "largeFileOptimizations": "Yoğun bellek kullanan belirli özellikleri devre dışı bırakacak şekilde büyük dosyalarla özel olarak ilgilenilmesi.", "renderIndicators": "Karşılaştırma düzenleyicisinin ekleme/çıkarma değişiklikleri için +/- göstergeleri gösterip göstermemesini denetler." } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json index fcfcdca2b2..30d2f3364e 100644 --- a/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -14,8 +14,10 @@ "editorCursorBackground": "Düzenleyici imlecinin arka plan rengi. Bir blok imlecinin kapladığı bir karakterin rengini özelleştirmeyi sağlar.", "editorWhitespaces": "Düzenleyicideki boşluk karakterlerinin rengi.", "editorIndentGuides": "Düzenleyici girinti kılavuzlarının rengi.", + "editorActiveIndentGuide": "Aktif düzenleyici girinti kılavuzlarının rengi.", "editorLineNumbers": "Düzenleyici satır numaralarının rengi.", "editorActiveLineNumber": "Düzenleyici etkin satır numara rengi", + "deprecatedEditorActiveLineNumber": "Id kullanımdan kaldırıldı. Bunun yerine 'editorLineNumber.activeForeground' kullanın.", "editorRuler": "Düzenleyici cetvellerinin rengi.", "editorCodeLensForeground": "Düzenleyici kod objektiflerinin ön plan rengi", "editorBracketMatchBackground": "Eşleşen parantezlerin arka plan rengi", @@ -28,7 +30,9 @@ "warningBorder": "Düzenleyicideki uyarı karalamalarının kenarlık rengi.", "infoForeground": "Düzenleyicideki bilgilendirme karalamalarının ön plan rengi.", "infoBorder": "Düzenleyicideki bilgilendirme karalamalarının kenarlık rengi.", - "overviewRulerRangeHighlight": "Aralık vurguları için genel bakış cetvelinin işaretleyici rengi.", + "hintForeground": "Düzenleyicideki ipucu karalamalarının ön plan rengi.", + "hintBorder": "Düzenleyicideki ipucu karalamalarının kenarlık rengi.", + "overviewRulerRangeHighlight": "Aralık vurguları için genel bakış cetvelinin işaretleyici rengi. Altta yer alan süslemeleri gizlememek için renk opak olmamalıdır.", "overviewRuleError": "Hatalar için genel bakış cetvelinin işaretleyici rengi.", "overviewRuleWarning": "Uyarılar için genel bakış cetvelinin işaretleyici rengi.", "overviewRuleInfo": "Bilgilendirmeler için genel bakış cetvelinin işaretleyici rengi." diff --git a/i18n/trk/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json b/i18n/trk/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json new file mode 100644 index 0000000000..ef87b0b173 --- /dev/null +++ b/i18n/trk/src/vs/editor/contrib/codeAction/codeActionCommands.i18n.json @@ -0,0 +1,19 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickFixWithKb": "Düzeltmeleri Göster ({0})", + "quickFix": "Düzeltmeleri Göster", + "quickfix.trigger.label": "Hızlı Düzeltme...", + "editor.action.quickFix.noneMessage": "Hiçbir kod eylemi mevcut değil", + "refactor.label": "Elden Geçir...", + "editor.action.refactor.noneMessage": "Elden geçirme mevcut değil", + "source.label": "Kaynak Eylemi...", + "editor.action.source.noneMessage": "Hiçbir kaynak eylemi mevcut değil", + "organizeImports.label": "İçe Aktarımları Düzenle", + "editor.action.organize.noneMessage": "İçe aktarımları düzenle eylemi mevcut değil" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/find/findController.i18n.json b/i18n/trk/src/vs/editor/contrib/find/findController.i18n.json index 21f6828fd7..586e1ec11d 100644 --- a/i18n/trk/src/vs/editor/contrib/find/findController.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/find/findController.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "startFindAction": "Bul", + "startFindWithSelectionAction": "Seçimdekini Bul", "findNextMatchAction": "Sonrakini Bul", "findPreviousMatchAction": "Öncekini Bul", "nextSelectionMatchFindAction": "Sonraki Seçimi Bul", diff --git a/i18n/trk/src/vs/editor/contrib/format/formatActions.i18n.json b/i18n/trk/src/vs/editor/contrib/format/formatActions.i18n.json index e5908603e9..741aec85a3 100644 --- a/i18n/trk/src/vs/editor/contrib/format/formatActions.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/format/formatActions.i18n.json @@ -12,5 +12,7 @@ "hintnn": "{1} ve {2} satırları arasında {0} biçimlendirme düzenlemesi yapıldı", "no.provider": "'{0}' dosyaları için yüklenmiş bir biçimlendirici yok.", "formatDocument.label": "Belgeyi Biçimlendir", - "formatSelection.label": "Seçimi Biçimlendir" + "no.documentprovider": "'{0}' dosyaları için yüklenmiş bir doküman biçimlendiricisi yok.", + "formatSelection.label": "Seçimi Biçimlendir", + "no.selectionprovider": "'{0}' dosyaları için yüklenmiş bir seçim biçimlendiricisi yok." } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json index e5b1ca4027..e4387458b0 100644 --- a/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -6,11 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "title.wo_source": "({0}/{1})", "markerAction.next.label": "Sonraki Soruna Git (Hata, Uyarı, Bilgi)", - "markerAction.previous.label": "Önceki Soruna Git (Hata, Uyarı, Bilgi)", - "editorMarkerNavigationError": "Düzenleyicinin işaretçi gezinti aracının hata rengi.", - "editorMarkerNavigationWarning": "Düzenleyicinin işaretçi gezinti aracının uyarı rengi.", - "editorMarkerNavigationInfo": "Düzenleyicinin işaretçi gezinti aracının bilgilendirme rengi.", - "editorMarkerNavigationBackground": "Düzenleyicinin işaretçi gezinti aracının arka planı." + "markerAction.previous.label": "Önceki Soruna Git (Hata, Uyarı, Bilgi)" } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json b/i18n/trk/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json new file mode 100644 index 0000000000..c3b60a4637 --- /dev/null +++ b/i18n/trk/src/vs/editor/contrib/gotoError/gotoErrorWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "title.wo_source": "({0}/{1})", + "editorMarkerNavigationError": "Düzenleyicinin işaretçi gezinti aracının hata rengi.", + "editorMarkerNavigationWarning": "Düzenleyicinin işaretçi gezinti aracının uyarı rengi.", + "editorMarkerNavigationInfo": "Düzenleyicinin işaretçi gezinti aracının bilgilendirme rengi.", + "editorMarkerNavigationBackground": "Düzenleyicinin işaretçi gezinti aracının arka planı." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/links/links.i18n.json b/i18n/trk/src/vs/editor/contrib/links/links.i18n.json index 6de80f8e4b..6f4f0109d0 100644 --- a/i18n/trk/src/vs/editor/contrib/links/links.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/links/links.i18n.json @@ -8,10 +8,12 @@ ], "links.navigate.mac": "Bağlantıyı izlemek için Cmd tuşuna basarak tıklayın", "links.navigate": "Bağlantıyı izlemek için Ctrl tuşuna basarak tıklayın", - "links.command.mac": "Komutu yürütmek için Cmd + tıklama yapın", - "links.command": "Komutu yürütmek için Ctrl + tıklama yapın", + "links.command.mac": "Komutu çalıştırmak için Cmd tuşuna basarak tıklayın", + "links.command": "Komutu çalıştırmak için Ctrl tuşuna basarak tıklayın", + "links.navigate.al.mac": "Bağlantıyı izlemek için Option tuşuna basarak tıklayın", "links.navigate.al": "Bağlantıyı izlemek için Alt tuşuna basarak tıklayın", - "links.command.al": "Komutu yürütmek için Alt + tıklama yapın", + "links.command.al.mac": "Komutu çalıştırmak için Option tuşuna basarak tıklayın ", + "links.command.al": "Komutu çalıştırmak için Alt tuşuna basarak tıklayın", "invalid.url": "Bu bağlantı iyi oluştrulmamış olduğu için açılamadı: {0}", "missing.url": "Bu bağlantı hedefi eksik olduğu için açılamadı.", "label": "Bağlantıyı Aç" diff --git a/i18n/trk/src/vs/editor/contrib/message/messageController.i18n.json b/i18n/trk/src/vs/editor/contrib/message/messageController.i18n.json new file mode 100644 index 0000000000..61231658c0 --- /dev/null +++ b/i18n/trk/src/vs/editor/contrib/message/messageController.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "editor.readonly": "Salt okunur düzenleyicide düzenleme yapılamıyor" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json b/i18n/trk/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json index 76d14cc6da..1050988fc7 100644 --- a/i18n/trk/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/referenceSearch/referencesWidget.i18n.json @@ -25,5 +25,6 @@ "peekViewEditorBackground": "Gözetleme görünümü düzenleyicisinin arka plan rengi.", "peekViewEditorGutterBackground": "Gözetleme görünümü düzenleyicisindeki oluğun arka plan rengi.", "peekViewResultsMatchHighlight": "Gözetleme görünümü sonuç listesindeki eşleşme vurgusu rengi.", - "peekViewEditorMatchHighlight": "Gözetleme görünümü düzenleyicisindeki eşleşme vurgusu rengi." + "peekViewEditorMatchHighlight": "Gözetleme görünümü düzenleyicisindeki eşleşme vurgusu rengi.", + "peekViewEditorMatchHighlightBorder": "Gözetleme görünümü düzenleyicisindeki eşleşme vurgusu kenarlığı." } \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/snippet/snippetVariables.i18n.json b/i18n/trk/src/vs/editor/contrib/snippet/snippetVariables.i18n.json new file mode 100644 index 0000000000..635fee26cd --- /dev/null +++ b/i18n/trk/src/vs/editor/contrib/snippet/snippetVariables.i18n.json @@ -0,0 +1,47 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "Sunday": "Pazar", + "Monday": "Pazartesi", + "Tuesday": "Salı", + "Wednesday": "Çarşamba", + "Thursday": "Perşembe", + "Friday": "Cuma", + "Saturday": "Cumartesi", + "SundayShort": "Paz", + "MondayShort": "Pzt", + "TuesdayShort": "Sal", + "WednesdayShort": "Çar", + "ThursdayShort": "Per", + "FridayShort": "Cum", + "SaturdayShort": "Cmt", + "January": "Ocak", + "February": "Şubat", + "March": "Mart", + "April": "Nisan", + "May": "Mayıs", + "June": "Haziran", + "July": "Temmuz", + "August": "Ağustos", + "September": "Eylül", + "October": "Ekim", + "November": "Kasım", + "December": "Aralık", + "JanuaryShort": "Oca", + "FebruaryShort": "Şub", + "MarchShort": "Mar", + "AprilShort": "Nis", + "MayShort": "May", + "JuneShort": "Haz", + "JulyShort": "Tem", + "AugustShort": "Ağu", + "SeptemberShort": "Eyl", + "OctoberShort": "Eki", + "NovemberShort": "Kas", + "DecemberShort": "Ara" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 9a94a84347..0537df82a9 100644 --- a/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -10,8 +10,8 @@ "wordHighlightStrong": "Bir değişkene yazmak gibi, yazma-erişimi sırasındaki bir sembolün arka plan rengi. Altta yer alan süslemeleri gizlememek için renk opak olmamalıdır.", "wordHighlightBorder": "Bir değişken okunurken ki gibi, bir sembolün okuma-erişimi sırasındaki kenarlık rengi.", "wordHighlightStrongBorder": "Bir değişkene yazılırken ki gibi, bir sembolün yazma erişimi sırasındaki kenarlık rengi.", - "overviewRulerWordHighlightForeground": "Sembol vurguları için genel bakış cetvelinin işaretleyici rengi.", - "overviewRulerWordHighlightStrongForeground": "Yazma erişimli sembol vurguları için genel bakış cetvelinin işaretleyici rengi.", + "overviewRulerWordHighlightForeground": "Sembol vurguları için genel bakış cetvelinin işaretleyici rengi. Altta yer alan süslemeleri gizlememek için renk mat olmamalıdır.", + "overviewRulerWordHighlightStrongForeground": "Yazma erişimli sembol vurguları için genel bakış cetvelinin işaretleyici rengi. Altta yer alan süslemeleri gizlememek için renk mat olmamalıdır.", "wordHighlight.next.label": "Sonraki Sembol Vurgusuna Git", "wordHighlight.previous.label": "Önceki Sembol Vurgusuna Git" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/dialogs/common/dialogs.i18n.json b/i18n/trk/src/vs/platform/dialogs/common/dialogs.i18n.json new file mode 100644 index 0000000000..0bc4bb5dea --- /dev/null +++ b/i18n/trk/src/vs/platform/dialogs/common/dialogs.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "moreFile": "...1 ek dosya gösterilmiyor", + "moreFiles": "...{0} ek dosya gösterilmiyor" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/dialogs/node/dialogService.i18n.json b/i18n/trk/src/vs/platform/dialogs/node/dialogService.i18n.json new file mode 100644 index 0000000000..40e62eb8c3 --- /dev/null +++ b/i18n/trk/src/vs/platform/dialogs/node/dialogService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "cancel": "İptal" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index d1ec839698..281e824753 100644 --- a/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -2,11 +2,12 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "invalidManifest": "Eklenti geçersiz: package.json bir JSON dosyası değil.", + "incompatible": "VS Code '{1}' ile uyumlu olmadığı için '{0}' eklentisi yüklenemiyor.", "restartCode": "{0} eklentisini yeniden yüklemeden önce lütfen Code'u yeniden başlatın.", "installingOutdatedExtension": "Bu eklentinin daha yeni bir sürümü zaten yüklü. Bunu, daha eski bir sürümle geçersiz kılmak ister misiniz?", "override": "Geçersiz Kıl", @@ -14,15 +15,16 @@ "errorInstallingDependencies": "Bağımlılıklar yüklenirken hata oluştu. {0}", "MarketPlaceDisabled": "Market etkin değil", "removeError": "Eklenti kaldırılırken hata oluştu: {0}. Yeniden yüklemeden önce lütfen VS Code'dan çıkın ve tekrar açın.", - "Not Market place extension": "Sadece Market Eklentileri yeniden yüklenebilir", + "Not a Marketplace extension": "Sadece Market Eklentileri yeniden yüklenebilir", "notFoundCompatible": "'{0}' yüklenemiyor; VS Code '{1}' ile uyumlu mevcut bir sürümü yok.", "malicious extension": "Eklenti sorunlu olarak bildirildiği için yüklenemiyor.", "notFoundCompatibleDependency": "Yükleme başarısız oldu çünkü, bağımlılığı bulunan '{0}' eklentisinin uyumlu olduğu VS Code'un '{1}' sürümü bulunamadı.", "quitCode": "Eklenti yüklenemedi. Lütfen yeniden yüklemeden önce VS Code'u sonlandırın ve tekrar başlatın.", "exitCode": "Eklenti yüklenemedi. Lütfen yeniden yüklemeden önce VS Code'u sonlandırın ve tekrar başlatın.", + "renameError": "{0}, {1} olarak yeniden adlandırılırken bilinmeyen hata oluştu", "uninstallDependeciesConfirmation": "Yalnızca '{0}' eklentisini mi yoksa bağımlılıklarını da kaldırmak ister misiniz?", "uninstallOnly": "Sadece Eklenti", - "uninstallAll": "Tümü", + "uninstallAll": "Tümünü Kaldır", "uninstallConfirmation": "'{0}' eklentisini kaldırmak istediğinizden emin misiniz?", "ok": "Tamam", "singleDependentError": "'{0}' eklentisi kaldırılamıyor. '{1}' eklentisi buna bağlı.", diff --git a/i18n/trk/src/vs/platform/extensions/node/extensionValidator.i18n.json b/i18n/trk/src/vs/platform/extensions/node/extensionValidator.i18n.json index 6d93344381..83faa9853c 100644 --- a/i18n/trk/src/vs/platform/extensions/node/extensionValidator.i18n.json +++ b/i18n/trk/src/vs/platform/extensions/node/extensionValidator.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "versionSyntax": "`engines.vscode` değeri {0} ayrıştırılamadı. Lütfen örnekte verilenlere benzer ifadeler kullanın: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x, vb.", + "versionSyntax": "`engines.vscode` değeri {0} ayrıştırılamadı. Lütfen örnekte verilenlere benzer ifadeler kullanın: ^1.22.0, ^1.22.x, vb.", "versionSpecificity1": "`engines.vscode`da belirtilen sürüm ({0}) yeterince belirli değil. vscode 1.0.0'dan önceki sürümler için, lütfen istenecek minimum majör ve minör sürüm numarasını tanımlayın. Örneğin: ^0.10.0, 0.10.x, 0.11.0, vb.", "versionSpecificity2": "`engines.vscode`da belirtilen sürüm ({0}) yeterince belirli değil. vscode 1.0.0'dan sonraki sürümler için, lütfen istenecek minimum majör sürüm numarasını tanımlayın. Örneğin: ^1.10.0, 1.10.x, 1.x.x, 2.x.x, vb.", "versionMismatch": "Eklenti, Code {0} ile uyumlu değil. Gereken sürüm: {1}." diff --git a/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index dc5cfc5efa..f44139863a 100644 --- a/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -6,7 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "integrity.prompt": "{0} kurulumunuz bozuk görünüyor. Lütfen yeniden yükleyin.", "integrity.moreInformation": "Daha Fazla Bilgi", - "integrity.dontShowAgain": "Tekrar Gösterme", - "integrity.prompt": "{0} kurulumunuz bozuk görünüyor. Lütfen yeniden yükleyin." + "integrity.dontShowAgain": "Tekrar Gösterme" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/issue/electron-main/issueService.i18n.json b/i18n/trk/src/vs/platform/issue/electron-main/issueService.i18n.json index 214c94d8db..6d40ddac81 100644 --- a/i18n/trk/src/vs/platform/issue/electron-main/issueService.i18n.json +++ b/i18n/trk/src/vs/platform/issue/electron-main/issueService.i18n.json @@ -6,5 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "issueReporter": "Sorun Bildirici" + "issueReporter": "Sorun Bildirici", + "processExplorer": "İşlem Yöneticisi" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/list/browser/listService.i18n.json b/i18n/trk/src/vs/platform/list/browser/listService.i18n.json index 39e8763796..fb8bc6f5c1 100644 --- a/i18n/trk/src/vs/platform/list/browser/listService.i18n.json +++ b/i18n/trk/src/vs/platform/list/browser/listService.i18n.json @@ -12,5 +12,6 @@ "multiSelectModifier": "Ağaç veya listelerdeki bir ögenin çoklu seçime fare ile eklenmesinde kullanılacak değiştirici(örneğin gezgin, açık düzenleyiciler ve scm görünümlerinde). `ctrlCmd` Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir. 'Yana Aç' fare hareketleri - destekleniyorsa - birden çok seçim değiştiricisi ile çakışmayacak şekilde uyum sağlarlar.", "openMode.singleClick": "Tek tıklamayla ögeleri aç.", "openMode.doubleClick": "Çift tıklamayla ögeleri aç.", - "openModeModifier": "Ağaç ve listelerdeki ögelerin (destekleniyorsa) fare ile nasıl açılacağını denetler. Ögeleri tek tıklamayla açmak için `singleClick`, çift tıklamayla açmak için `doubleClick` olarak ayarlayın. Ağaçlardaki alt ögeler içeren ögeler için bu ayar üst ögenin tek veya çift tıklama tarafından genişletilmesini denetler. Bazı ağaç veya listelerin, bu ayar uygulanamaz ise görmezden gelmeyi seçebileceklerini unutmayın." + "openModeModifier": "Ağaç ve listelerdeki ögelerin (destekleniyorsa) fare ile nasıl açılacağını denetler. Ögeleri tek tıklamayla açmak için `singleClick`, çift tıklamayla açmak için `doubleClick` olarak ayarlayın. Ağaçlardaki alt ögeler içeren ögeler için bu ayar üst ögenin tek veya çift tıklama tarafından genişletilmesini denetler. Bazı ağaç veya listelerin, bu ayar uygulanamaz ise görmezden gelmeyi seçebileceklerini unutmayın.", + "horizontalScrolling setting": "Çalışma ekranındaki ağaçların yatay kaydırmayı destekleyip desteklemeyeceğini denetler." } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/markers/common/markers.i18n.json b/i18n/trk/src/vs/platform/markers/common/markers.i18n.json new file mode 100644 index 0000000000..bc3e810811 --- /dev/null +++ b/i18n/trk/src/vs/platform/markers/common/markers.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "sev.error": "Hata", + "sev.warning": "Uyarı", + "sev.info": "Bilgi" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json index 0353fac427..46aedee276 100644 --- a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -29,7 +29,7 @@ "inputPlaceholderForeground": "Yer tutucu metin için girdi kutusu ön plan rengi.", "inputValidationInfoBackground": "Bilgi önem derecesi için girdi doğrulama arka plan rengi.", "inputValidationInfoBorder": "Bilgi önem derecesi için girdi doğrulama kenarlık rengi.", - "inputValidationWarningBackground": "Bilgi uyarısı için girdi doğrulama arka plan rengi.", + "inputValidationWarningBackground": "Uyarı önem derecesi için girdi doğrulama arka plan rengi.", "inputValidationWarningBorder": "Uyarı önem derecesi için girdi doğrulama kenarlık rengi.", "inputValidationErrorBackground": "Hata önem derecesi için girdi doğrulama arka plan rengi.", "inputValidationErrorBorder": "Hata önem derecesi için girdi doğrulama kenarlık rengi.", @@ -93,6 +93,6 @@ "overviewRulerCurrentContentForeground": "Satır içi birleştirme çakışmalarında \"mevcut olan\" için genel bakış cetveli ön planı.", "overviewRulerIncomingContentForeground": "Satır içi birleştirme çakışmalarında gelen genel bakış cetveli ön planı.", "overviewRulerCommonContentForeground": "Satır içi birleştirme çakışmalarında ortak ata genel bakış cetveli ön planı.", - "overviewRulerFindMatchForeground": "Bulunan eşler için genel bakış cetvelinin işaretleyici rengi.", - "overviewRulerSelectionHighlightForeground": "Seçim vurguları için genel bakış cetvelinin işaretleyici rengi." + "overviewRulerFindMatchForeground": "Bulunan eşler için genel bakış cetvelinin işaretleyici rengi. Altta yer alan süslemeleri gizlememek için renk opak olmamalıdır.", + "overviewRulerSelectionHighlightForeground": "Seçim vurguları için genel bakış cetvelinin işaretleyici rengi. Altta yer alan süslemeleri gizlememek için renk opak olmamalıdır." } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json b/i18n/trk/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json new file mode 100644 index 0000000000..034d05ed9f --- /dev/null +++ b/i18n/trk/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "confirmUrl": "{0} eklentisine aşağıdaki URL'i açması için izin vermek istiyor musunuz?" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json new file mode 100644 index 0000000000..7253cd5ae1 --- /dev/null +++ b/i18n/trk/src/vs/workbench/api/browser/viewsContainersExtensionPoint.i18n.json @@ -0,0 +1,18 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "vscode.extension.contributes.views.containers.title": "Kapsayıcıda gösterilecek insanlar tarafından okunabilir dize", + "vscode.extension.contributes.views.containers.icon": "Kapsayıcı simgesinin yolu. Simgeler, 50x40'lık bir dörtgen içinde 24x24 olarak ortalanmış ve 'rgb(215, 218, 224)' veya '#d7dae0' dolgu rengine sahiptir. Simgelerin SVG formatında olması tavsiye edilir ancak herhangi bir resim dosyası türü kabul edilir.", + "vscode.extension.contributes.viewsContainers": "Görünüm kapsayıcılarını düzenleyiciye ekler.", + "views.container.activitybar": "Etkinlik Çubuğu'na görünüm kapsayıcıları ekle", + "test": "Test", + "requirearray": "görünüm kapsayıcıları bir dizi olmalıdır", + "requirestring": "`{0}` özelliği zorunludur ve `string` türünde olmalıdır", + "showViewlet": "{0}'i Göster", + "view": "Görüntüle" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json index e5fe32cfad..1130991fdf 100644 --- a/i18n/trk/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json +++ b/i18n/trk/src/vs/workbench/api/browser/viewsExtensionPoint.i18n.json @@ -13,9 +13,11 @@ "vscode.extension.contributes.view.name": "Görünümün insanlar tarafından okunabilir adı. Gösterilecektir", "vscode.extension.contributes.view.when": "Bu görünümü göstermek için doğru olması gereken koşul", "vscode.extension.contributes.views": "Görünümleri düzenleyiciye ekler.", - "views.explorer": "Gezgin Görünümü", - "views.debug": "Hata Ayıklama Görünümü", - "locationId.invalid": "`{0}` geçerli bir görünüm konumu değil", - "duplicateView1": "`{1}` konumunda aynı `{0}` kimliğine sahip birden çok görünüm kaydedilemiyor", - "duplicateView2": "`{0}` kimliğine sahip bir görünüm `{1}` konumunda zaten kayıtlı" + "views.explorer": "Etkinlik Çubuğu'ndaki Gezgin kapsayıcısına görünümler ekler", + "views.debug": "Etkinlik Çubuğu'ndaki Hata Ayıklama kapsayıcısına görünümler ekler", + "views.scm": "Etkinlik Çubuğu'ndaki SCM kapsayıcısına görünümler ekler", + "views.test": "Etkinlik Çubuğu'ndaki Test kapsayıcısına görünümler ekler", + "views.contributed": "Görünümleri katkıda bulunan görünümü kapsayıcısına ekler", + "duplicateView1": "`{1}` konumunda aynı `{0}` id'sine sahip birden çok görünüm kaydedilemiyor", + "duplicateView2": "`{0}` id'sine sahip bir görünüm `{1}` konumunda zaten kayıtlı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json index f7574d57ba..2c701fd270 100644 --- a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json +++ b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -6,5 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "timeout.formatOnSave": "Kaydederken biçimlendirme {0}ms sonrasında durduruldu", + "codeActionsOnSave.didTimeout": "{0}ms sonra codeActionsOnSave durduruldu", + "timeout.onWillSave": "onWillSaveTextDocument olayı 1750ms sonrasında durduruldu", "saveParticipants": "Katılımcıların Kaydedilmesi İşlemi Çalıştırılıyor..." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json new file mode 100644 index 0000000000..ee8688cdc8 --- /dev/null +++ b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadTask.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "task.label": "{0}: {1}" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json index 5cdf354425..d58fb353ec 100644 --- a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json +++ b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadWebview.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "webview.editor.label": "web görünümü düzenleyicisi" + "errorMessage": "Görünüm geri yüklenirken bir hata oluştu:{0}" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/node/extHostProgress.i18n.json b/i18n/trk/src/vs/workbench/api/node/extHostProgress.i18n.json new file mode 100644 index 0000000000..b8ebfa4861 --- /dev/null +++ b/i18n/trk/src/vs/workbench/api/node/extHostProgress.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "extensionSource": "{0} (Eklenti)" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 8eea59d103..6a90db445d 100644 --- a/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -7,5 +7,5 @@ "Do not edit this file. It is machine generated." ], "treeView.notRegistered": "Kayıtlı '{0}' Id'li ağaç görünümü yok.", - "treeView.duplicateElement": "{0} kimliğine sahip bir öge zaten kayıtlı" + "treeView.duplicateElement": "{0} id'sine sahip bir öge zaten kayıtlı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index d54582f2ed..08dcab59ff 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,6 +17,7 @@ "focusNextGroup": "Sonraki Gruba Odakla", "openToSide": "Yana Aç", "closeEditor": "Düzenleyiciyi Kapat", + "closeOneEditor": "Kapat", "revertAndCloseActiveEditor": "Geri Al ve Düzenleyiciyi Kapat", "closeEditorsToTheLeft": "Düzenleyicinin Solundakileri Kapat", "closeAllEditors": "Tüm Düzenleyicileri Kapat", diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json index 1b14cea1f0..9ca6370bb4 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editorStatus.i18n.json @@ -17,10 +17,10 @@ "screenReaderDetectedExtra": "Bir Ekran Okuyucu kullanmıyorsanız, lütfen `editor.accessibilitySupport` ayarını \"off\" olarak değiştirin", "disableTabMode": "Erişilebilirlik Modunu Devre Dışı Bırak", "gotoLine": "Satıra Git", - "indentation": "Girinti", + "selectIndentation": "Girinti Seç", "selectEncoding": "Kodlamayı Seç", "selectEOL": "Satır Sonu Sıralamasını Seç", - "selectLanguageMode": "Dil Modunu Seçin", + "selectLanguageMode": "Dil Modunu Seç", "fileInfo": "Dosya Bilgisi", "spacesSize": "Boşluk: {0}", "tabSize": "Sekme Boyutu: {0}", @@ -33,9 +33,9 @@ "configureModeSettings": "'{0}' dili tabanlı ayarları yapılandır...", "configureAssociationsExt": "'{0}' için Dosya İlişkilendirmesini Yapılandır...", "autoDetect": "Otomatik Algıla", - "pickLanguage": "Dil Modunu Seçin", + "pickLanguage": "Dil Modunu Seç", "currentAssociation": "Geçerli İlişkilendirme", - "pickLanguageToConfigure": " '{0}' ile İlişkilendirilecek Dil Modunu Seçin", + "pickLanguageToConfigure": "'{0}' ile İlişkilendirilecek Dil Modunu Seç", "changeIndentation": "Girintiyi Değiştir", "noWritableCodeEditor": "Aktif kod düzenleyici salt okunur.", "indentView": "görünümü değiştir", diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json index d5432cf1f1..afa9dbf6f0 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/resourceViewer.i18n.json @@ -11,9 +11,11 @@ "sizeMB": "{0}MB", "sizeGB": "{0}GB", "sizeTB": "{0}TB", - "largeImageError": "Resim dosyası boyutu düzenleyicide görüntülemek için çok büyük (>1MB).", + "largeImageError": "Görüntü çok büyük olduğu için düzenleyicide görüntülenemiyor ({0}).", "resourceOpenExternalButton": "Harici program kullanarak resmi aç", - "nativeBinaryError": "Dosya ikili olduğu, çok büyük olduğu veya desteklenmeyen bir metin kodlaması kullandığı için düzenleyicide görüntülenemiyor.", + "nativeFileTooLargeError": "Dosya çok büyük olduğu için düzenleyicide görüntülenemiyor ({0}).", + "nativeBinaryError": "Dosya ikili olduğu veya desteklenmeyen bir metin kodlaması kullandığı için düzenleyicide görüntülenemiyor.", + "openAsText": "Yine de açmak ister misiniz?", "zoom.action.fit.label": "Resmin Tamamı", "imgMeta": "{0}x{1} {2}" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 79c207ec29..a107144022 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -6,6 +6,5 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "close": "Kapat", "araLabelEditorActions": "Düzenleyici eylemleri" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json index 15b3967992..05ae29fe42 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/notifications/notificationsCenter.i18n.json @@ -2,10 +2,11 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "notificationsEmpty": "Yeni bildirim yok", "notifications": "Bildirimler", "notificationsToolbar": "Bildirim Merkezi Eylemleri", "notificationsList": "Bildirim Listesi" diff --git a/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json new file mode 100644 index 0000000000..29901080c8 --- /dev/null +++ b/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInput.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "inputModeEntryDescription": "{0} (Onaylamak için 'Enter' veya iptal etmek için 'Escape' tuşuna basın)", + "inputModeEntry": "Girdinizi onaylamak için 'Enter' veya iptal etmek için 'Escape' tuşuna basın", + "quickInput.countSelected": "{0} Seçili", + "ok": "Tamam" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json new file mode 100644 index 0000000000..411049d886 --- /dev/null +++ b/i18n/trk/src/vs/workbench/browser/parts/quickinput/quickInputBox.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "quickInputBox.ariaLabel": "Sonuçları daraltmak için yazmaya başlayın." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/common/views.i18n.json b/i18n/trk/src/vs/workbench/common/views.i18n.json index b9b60a3bf5..352d616cb2 100644 --- a/i18n/trk/src/vs/workbench/common/views.i18n.json +++ b/i18n/trk/src/vs/workbench/common/views.i18n.json @@ -2,9 +2,9 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "duplicateId": "'{0}' kimliğine sahip bir görünüm '{1}' konumunda zaten kayıtlı" + "duplicateId": "'{0}' id'sine sahip bir görünüm '{1}' konumunda zaten kayıtlı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json index 3b10e770d4..5f7b7de831 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json @@ -32,6 +32,7 @@ "openRecent": "Son Kullanılanları Aç...", "quickOpenRecent": "Son Kullanılanları Hızlı Aç...", "reportIssueInEnglish": "Sorun Bildir", + "openProcessExplorer": "İşlem Yöneticisini Aç", "reportPerformanceIssue": "Performans Sorunu Bildir", "keybindingsReference": "Klavye Kısayolları Başvurusu", "openDocumentationUrl": "Belgeler", diff --git a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json index 0a0e2f6261..aa1dad73cf 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -18,7 +18,7 @@ "workbench.editor.labelFormat.medium": "Dosyanın adını ve ardından çalışma alanı klasörüne göreli yolunu göster.", "workbench.editor.labelFormat.long": "Dosyanın adını ve ardından mutlak yolunu göster.", "tabDescription": "Bir düzenleyici için etiketin biçimini denetler. Bu ayarı değiştirmek; örneğin, bir dosyanın konumunun daha kolay anlaşılmasını sağlar:\n- short: 'ustklasor'\n- medium: 'calismaalani/src/ustklasor'\n- long: '/home/user/calismaalani/src/ustklasor'\n- default: diğer bir sekme aynı başlığı paylaşıyorsa '.../ustklasor' veya sekmeler devre dışı ise göreli çalışma alanı yolu", - "editorTabCloseButton": "Düzenleyici sekmelerinin kapat butonlarının konumunu denetler veya 'off' olarak ayarlandığında devre dışı bırakır.", + "editorTabCloseButton": "Düzenleyici sekmelerinin kapat butonlarının konumunu denetler veya 'off' değeri atandığında devre dışı bırakır.", "tabSizing": "Düzenleyici sekmelerinin boyutlarını denetler. Sekmelerin her zaman tam düzenleyici etiketini gösterecek kadar büyük tutmak için 'fit' olarak ayarlayın. Mevcut alan bir seferde tüm sekmeleri göstermek için yeterli olmadığında sekmelerin küçülmesini sağlamak için 'shrink' olarak ayarlayın.", "showIcons": "Açık düzenleyicilerin bir simge ile gösterilip gösterilmemelerini denetler. Bu, bir simge temasının etkinleştirilmesini de gerektirir.", "enablePreview": "Açık düzenleyicilerin önizleme olarak gösterilip gösterilmeyeceğini denetler. Önizleme düzenleyicileri kalıcı olarak açılana kadar (ör. çift tıklama veya düzenleme ile) tekrar kullanılırlar ve italik yazı tipiyle gösterilirler.", @@ -45,12 +45,17 @@ "windowConfigurationTitle": "Pencere", "window.openFilesInNewWindow.on": "Dosyalar yeni bir pencerede açılacak", "window.openFilesInNewWindow.off": "Dosyalar, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak", - "window.openFilesInNewWindow.default": "Dosyalar, Dock veya Finder ile açılmadıkça (sadece macOS için) dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak", - "openFilesInNewWindow": "Dosyaların yeni bir pencerede açılıp açılmayacağını denetler.\n- default: dosyalar, Dock veya Finder ile açılmadıkça (sadece macOS için) dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak\n- on: dosyalar yeni bir pencerede açılacak\n- off: dosyalar, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak\nBu ayarın halen yok sayılacağı durumlar olabilir (ör. -new-window veya -reuse-window komut satırı seçenekleri kullanılırken).", + "window.openFilesInNewWindow.defaultMac": "Dosyalar, Dock veya Finder'dan açılmadıkça, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak", + "window.openFilesInNewWindow.default": "Dosyalar, uygulama içinden seçilmedikçe (ör. Dosya menüsünden) yeni bir pencerede açılır", + "openFilesInNewWindowMac": "Dosyaların yeni bir pencerede açılıp açılmayacağını denetler.\n- default: dosyalar, Dock veya Finder'dan açılmadıkça, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak\n- on: dosyalar yeni bir pencerede açılacak\n- off: dosyalar, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak\nBu ayarın halen yok sayılacağı durumlar olabilir (ör. -new-window veya -reuse-window komut satırı seçenekleri kullanılırken).", + "openFilesInNewWindow": "Dosyaların yeni bir pencerede açılıp açılmayacağını denetler.\n- default: dosyalar, uygulama içinden seçilmedikçe (ör. Dosya menüsünden) yeni bir pencerede açılır\n- on: dosyalar yeni bir pencerede açılır\n- off: dosyalar, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılır\nBu ayarın halen yok sayılacağı durumlar olabilir (ör. -new-window veya -reuse-window komut satırı seçenekleri kullanılırken).", "window.openFoldersInNewWindow.on": "Klasörler yeni bir pencerede açılacak", "window.openFoldersInNewWindow.off": "Klasörler son aktif pencereyi değiştirir", "window.openFoldersInNewWindow.default": "Klasörler, bir klasör uygulama içinden seçilmedikçe (ör. Dosya menüsünden) yeni bir pencerede açılır", "openFoldersInNewWindow": "Klasörlerin yeni bir pencerede mi açılacağını yoksa son aktif pencereyi mi değiştireceğini denetler.\n- default: klasörler, bir klasör uygulama içinden seçilmedikçe (ör. Dosya menüsünden) yeni bir pencerede açılır\n- on: klasörler yeni bir pencerede açılır\n- off: klasörler son aktif pencereyi değiştirir\nBu ayarın halen yok sayılacağı durumlar olabilir (ör. -new-window veya -reuse-window komut satırı seçenekleri kullanılırken).", + "window.openWithoutArgumentsInNewWindow.on": "Yeni bir pencere aç", + "window.openWithoutArgumentsInNewWindow.off": "Son aktif çalışan örneğe odakla", + "openWithoutArgumentsInNewWindow": "Yeni bir örnek argümansız olarak başlatılırken boş bir yeni pencerenin açılıp açılmamasını veya son çalışan örneğe odaklanıp odaklanmamasını denetler.\n- on: boş bir yeni pencere aç\n- off: son çalışan örneğe odakla\nBu ayarın halen yok sayılacağı durumlar olabilir (ör. -new-window veya -reuse-window komut satırı seçenekleri kullanılırken).", "window.reopenFolders.all": "Tüm pencereleri yeniden aç.", "window.reopenFolders.folders": "Tüm klasörleri yeniden aç. Boş çalışma alanları geri yüklenmeyecektir.", "window.reopenFolders.one": "Son aktif pencereyi yeniden aç.", @@ -58,12 +63,12 @@ "restoreWindows": "Pencerelerin, bir yeniden başlatma sonrası nasıl yeniden açılacağını denetler. Her zaman boş bir çalışma alanı ile başlamak için 'none', üzerinde çalıştığınız son pencereyi yeniden açmak için 'one', açık klasör bulunduran tüm pencereleri yeniden açmak için 'folders' veya son oturumunuzdaki tüm pencereleri yeniden açmak için 'all' seçeneğini seçin.", "restoreFullscreen": "Bir pencere tam ekran modundayken çıkıldıysa, bu pencerenin tam ekran moduna geri dönüp dönmeyeceğini denetler.", "zoomLevel": "Pencerenin yakınlaştırma düzeyini ayarlayın. Orijinal boyut 0'dır ve üstündeki (ör. 1) veya altındaki (ör. -1) her artırma 20% daha fazla veya az yakınlaştırmayı temsil eder. Yakınlaştırma düzeyini daha ince ayrıntılarla ayarlamak için ondalık değerler de girebilirsiniz.", - "title": "Pencere başlığını aktif düzenleyiciye bağlı olarak denetler. Değişkenler, bağlama göre değiştirilir:\n${activeEditorShort}: dosyanın adı (ör. myFile.txt)\n${activeEditorMedium}: çalışma alanı klasörüne göreli dosyanın yolu (ör. myFolder/myFile.txt)\n${activeEditorLong}: dosyanın tam yolu (ör. /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: dosyayı içeren çalışma alanı klasörünün adı (ör. myFolder)\n${folderPath}: dosyayı içeren çalışma alanı klasörünün yolu (ör. /Users/Development/myFolder)\n${rootName}: çalışma alanının adı (ör. myFolder veya myWorkspace)\n${rootPath}: çalışma alanının yolu (ör. /Users/Development/myWorkspace)\n${appName}: ör. VS Code\n${dirty}: etkin düzenleyici kaydedilmemiş değişiklikler içeriyorsa, değişiklik göstergesi\n${separator}: şartlı ayırıcı (\" - \") yalnızca değer içeren değişkenlerle çevrili olduğunda gösterilir", + "title": "Pencere başlığını aktif düzenleyiciye bağlı olarak denetler. Değişkenler, bağlama göre değiştirilir:\n${activeEditorShort}: dosyanın adı (ör. myFile.txt)\n${activeEditorMedium}: çalışma alanı klasörüne göreli dosyanın yolu (ör. myFolder/myFile.txt)\n${activeEditorLong}: dosyanın tam yolu (ör. /Users/Development/myProject/myFolder/myFile.txt)\n${folderName}: dosyayı içeren çalışma alanı klasörünün adı (ör. myFolder)\n${folderPath}: dosyayı içeren çalışma alanı klasörünün yolu (ör. /Users/Development/myFolder)\n${rootName}: çalışma alanının adı (ör. myFolder veya myWorkspace)\n${rootPath}: çalışma alanının yolu (ör. /Users/Development/myWorkspace)\n${appName}: ör. VS Code\n${dirty}: etkin düzenleyici kaydedilmemiş değişiklikler içeriyorsa, değişiklik göstergesi\n${separator}: şartlı ayırıcı (\" - \") yalnızca değer veya statik metin içeren değişkenlerle çevrili olduğunda gösterilir", "window.newWindowDimensions.default": "Yeni pencereleri ekranın ortasında açın.", "window.newWindowDimensions.inherit": "Yeni pencereleri son aktif pencere ile aynı ölçülerde açın.", "window.newWindowDimensions.maximized": "Yeni pencereleri ekranı kapla modunda açın.", "window.newWindowDimensions.fullscreen": "Yeni pencereleri tam ekran modunda açın.", - "newWindowDimensions": "En az bir pencere açıkken, açılacak yeni bir pencerenin boyutlarını denetler. Varsayılan olarak; yeni pencere ekranın ortasında küçük bir boyutta açılır. 'inherit' olarak ayarlandığında, pencere aktif olan son pencere ile aynı boyutları alacaktır. 'maximized' olarak ayarlandığında, ekranı kaplar biçimde açılır ve 'fullscreen' olarak yapılandırılmışsa, tam ekran olarak açılır. Bu ayarın açılan ilk pencere üzerinde bir etkisi olmadığını unutmayın. İlk pencere, daima boyutunu ve konumunu kapanmadan önce bıraktığınız şekilde geri yükler.", + "newWindowDimensions": "En az bir pencere açıkken, açılacak yeni bir pencerenin boyutlarını denetler. Varsayılan olarak; yeni pencere ekranın ortasında küçük bir boyutta açılır. 'inherit' değeri atandığında, pencere aktif olan son pencere ile aynı boyutları alacaktır. 'maximized' değeri atandığında, ekranı kaplar biçimde açılır ve 'fullscreen' değeri atandığında, tam ekran olarak açılır. Bu ayarın açılan ilk pencere üzerinde bir etkisi olmadığını unutmayın. İlk pencere, daima boyutunu ve konumunu kapanmadan önce bıraktığınız şekilde geri yükler.", "closeWhenEmpty": "Son düzenleyiciyi kapatmanın pencereyi de kapatıp kapatmayacağını denetler. Bu ayar sadece klasör göstermeyen pencereler için uygulanır.", "window.menuBarVisibility.default": "Menü, sadece tam ekran modunda gizlenir.", "window.menuBarVisibility.visible": "Menü, tam ekran modunda bile daima görünür.", @@ -74,6 +79,8 @@ "autoDetectHighContrast": "Etkinleştirilirse; eğer Windows bir yüksek karşıtlık teması kullanıyorsa, otomatik olarak yüksek karşıtlık temasına geçiş yapılır; ve Windows, yüksek karşıtlık temasını kullanmayı bıraktığında koyu temaya geçiş yapılır.", "titleBarStyle": "Pencere başlık çubuğunun görünümünü ayarlayın. Değişikliklerin uygulanması için tam yeniden başlatma gerekir.", "window.nativeTabs": "macOS Sierra pencere sekmelerini etkinleştirir. Değişikliklerin uygulanması için tam yeniden başlatma gerekeceğini ve yerel sekmelerin, eğer yapılandırılmışsa özel başlık çubuğu stilini devre dışı bıracağını unutmayın.", + "window.smoothScrollingWorkaround": "Simge durumuna küçültülmüş bir VS Code penceresini tekrar açtıktan sonra kaydırma artık pürüzsüz değilse bu geçici çözümü etkinleştirin. Bu, Microsoft'un Surface cihazları gibi hassas trackpad'ler içeren cihazlarda yaşanan kaydırma gecikmesi sorunu (https://github.com/Microsoft/vscode/issues/13612) için geçici bir çözümdür.", + "window.clickThroughInactive": "Etkinleştirilirse, aktif olmayan bir pencereye tıklandığında hem pencere etkinleştirilir hem de farenin üzerinde bulunduğu öge tıklanabilir durumdaysa tetiklenir. Devre dışı bırakılırsa, aktif olmayan bir pencerenin herhangi bir yerine tıklandığında sadece o pencere etkinleştirilir ve öge için ikinci bir tıklama gerekir.", "zenModeConfigurationTitle": "Zen Modu", "zenMode.fullScreen": "Zen Moduna geçmenin ayrıca çalışma ekranını tam ekran moduna geçirip geçirmeyeceğini denetler.", "zenMode.centerLayout": "Zen Modu'nun aktif edilmesinin düzeni ortalayıp ortalamayacağını denetler.", diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json index 0363bac67d..896aab5629 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/breakpointsView.i18n.json @@ -2,11 +2,14 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "editConditionalBreakpoint": "Kesme Noktasını Düzenle...", + "logPoint": "Günlük Noktası", + "breakpoint": "Kesme Noktası", + "editBreakpoint": "Düzenle: {0}...", + "removeBreakpoint": "Kaldır: {0}", "functionBreakpointsNotSupported": "Fonksiyon kesme noktaları bu hata ayıklama türü tarafından desteklenmiyor", "functionBreakpointPlaceholder": "Mola verilecek fonksiyon", "functionBreakPointInputAriaLabel": "Fonksiyon kesme noktasını girin", @@ -14,6 +17,7 @@ "breakpointUnverifieddHover": "Doğrulanmamış kesme noktası", "functionBreakpointUnsupported": "Fonksiyon kesme noktaları bu hata ayıklama türü tarafından desteklenmiyor", "breakpointDirtydHover": "Doğrulanmamış Kesme Noktası Dosya düzenlendi, lütfen hata ayıklama oturumunu yeniden başlatın.", + "logBreakpointUnsupported": "Günlük noktaları bu hata ayıklama türü tarafından desteklenmiyor", "conditionalBreakpointUnsupported": "Koşullu kesme noktaları bu hata ayıklama türü tarafından desteklenmiyor", "hitBreakpointUnsupported": "Koşullu kesme noktalarına isabet etme bu hata ayıklama türü tarafından desteklenmiyor" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 72c0b139ec..bf42a32abf 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -21,19 +21,16 @@ "disconnectDebug": "Bağlantıyı Kes", "continueDebug": "Devam Et", "pauseDebug": "Duraklat", + "terminateThread": "İş Parçacığını Sonlandır", "restartFrame": "Çerçeveyi Yeniden Başlat", "removeBreakpoint": "Kesme Noktasını Kaldır", "removeAllBreakpoints": "Tüm Kesme Noktalarını Kaldır", - "enableBreakpoint": "Kesme Noktasını Etkinleştir", - "disableBreakpoint": "Kesme Noktasını Devre Dışı Bırak", "enableAllBreakpoints": "Tüm Kesme Noktalarını Etkinleştir", "disableAllBreakpoints": "Tüm Kesme Noktalarını Devre Dışı Bırak", "activateBreakpoints": "Kesme Noktalarını Etkinleştir", "deactivateBreakpoints": "Kesme Noktalarını Devre Dışı Bırak", "reapplyAllBreakpoints": "Tüm Kesme Noktalarını Yeniden Uygula", "addFunctionBreakpoint": "Fonksiyon Kesme Noktası Ekle", - "addConditionalBreakpoint": "Koşullu Kesme Noktası Ekle...", - "editConditionalBreakpoint": "Kesme Noktasını Düzenle...", "setValue": "Değeri Ayarla", "addWatchExpression": "İfade Ekle", "editWatchExpression": "İfadeyi Düzenle", diff --git a/i18n/trk/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json index 53c58b81f9..5f05d35542 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/browser/debugEditorActions.i18n.json @@ -8,6 +8,7 @@ ], "toggleBreakpointAction": "Hata Ayıklama: Kesme Noktası Ekle/Kaldır", "conditionalBreakpointEditorAction": "Hata Ayıklama: Koşullu Kesme Noktası Ekle...", + "logPointEditorAction": "Hata Ayıklama: Günlük Noktası Ekle...", "runToCursor": "İmlece Kadar Çalıştır", "debugEvaluate": "Hata Ayıklama: Değerlendir", "debugAddToWatch": "Hata Ayıklama: İzlemeye Ekle", diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json new file mode 100644 index 0000000000..d8d0b352bf --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "breakpointWidgetHitCountPlaceholder": "İsabet sayısı koşulu sağlandığında mola ver. Kabul etmek için 'Enter', iptal etmek için 'Esc' tuşuna basın.", + "breakpointWidgetExpressionPlaceholder": "İfade değerlendirmesi doğru olduğunda mola ver. Kabul etmek için 'Enter', iptal etmek için 'Esc' tuşuna basın.", + "expression": "İfade", + "hitCount": "İsabet Sayısı", + "logMessage": "Günlük Mesajı" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 4e55be50b8..01b1df13d2 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -35,7 +35,7 @@ "useUniqueNames": "Lütfen benzersiz yapılandırma adları kullanın.", "app.launch.json.compound.folder": "Bileşiğin bulunduğu klasörün adı.", "app.launch.json.compounds.configurations": "Bu bileşiğin parçası olarak başlatılacak yapılandırmaların adları.", - "debugNoType": "Hata ayıklama bağdaştırıcısının 'type' ögesi atlanabilir veya 'dize' türünde olmalıdır.", + "debugNoType": "Hata ayıklayıcının 'type' ögesi atlanamaz ve 'dize' türünde olmalıdır.", "selectDebug": "Ortam Seçin", "DebugConfig.failed": " '.vscode' klasörü içinde 'launch.json' dosyası oluşturulamıyor ({0}).", "workspace": "çalışma alanı", diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json index 7002c70148..0744bfd32d 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.i18n.json @@ -6,6 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "logPoint": "Günlük Noktası", + "breakpoint": "Kesme Noktası", + "removeBreakpoint": "Kaldır: {0}", + "editBreakpoint": "Düzenle: {0}...", + "disableBreakpoint": "Devre Dışı Bırak: {0}", + "enableBreakpoint": "Etkinleştir: {0}", "removeBreakpoints": "Kesme Noktalarını Kaldır", "removeBreakpointOnColumn": "{0}. Sütundaki Kesme Noktasını Kaldır", "removeLineBreakpoint": "Satır Kesme Noktasını Kaldır", @@ -18,5 +24,12 @@ "enableBreakpoints": "{0}. Sütundaki Kesme Noktasını Etkinleştir", "enableBreakpointOnLine": "Satır Kesme Noktasını Etkinleştir", "addBreakpoint": "Kesme Noktası Ekle", + "addConditionalBreakpoint": "Koşullu Kesme Noktası Ekle...", + "addLogPoint": "Günlük Noktası Ekle...", + "message": "mesaj", + "condition": "koşul", + "removeLogPoint": "Kaldır: {0}", + "disableLogPoint": "Devre Dışı Bırak: {0}", + "cancel": "İptal", "addConfiguration": "Yapılandırma Ekle..." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json index 60dabedfd9..9f4a85e0c7 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugService.i18n.json @@ -29,6 +29,6 @@ "showErrors": "Hataları Göster", "noFolderWorkspaceDebugError": "Aktif dosyada hata ayıklama yapılamıyor. Lütfen, dosyanın diskte kayıtlı olduğundan ve bu dosya türü için hata ayıklama eklentinizin olduğundan emin olun.", "cancel": "İptal", - "DebugTaskNotFound": "'{0}' ön başlatma görevi bulunamadı.", - "taskNotTracked": "'{0}' başlatma öncesi görevi izlenemez." + "DebugTaskNotFound": "'{0}' görevi bulunamadı.", + "taskNotTracked": "'{0}' görevi izlenemez." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json index ee6896ad12..08ad713c83 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.i18n.json @@ -7,8 +7,5 @@ "Do not edit this file. It is machine generated." ], "moreInfo": "Daha Fazla Bilgi", - "unableToLaunchDebugAdapter": "'{0}' tarafından hata ayıklama bağdaştırıcısı başlatılamadı.", - "unableToLaunchDebugAdapterNoArgs": "Hata ayıklama bağdaştırıcısı başlatılamıyor.", - "stoppingDebugAdapter": "{0}. Hata ayıklama bağdaştırıcısı durduruluyor.", "debugAdapterCrash": "Hata ayıklama bağdaştırıcısı beklenmeyen biçimde sonlandırıldı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json index 016c6649b8..38c29dbf3a 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/node/debugAdapter.i18n.json @@ -8,18 +8,6 @@ ], "debugAdapterBinNotFound": "Hata ayıklama bağdaştırıcısı yürütülebilir dosyası '{0}', mevcut değil.", "debugAdapterCannotDetermineExecutable": "Hata ayıklama bağdaştırıcısı yürütülebilir dosyası '{0}' belirlenemedi.", - "launch.config.comment1": "Olası öznitelikler hakkında bilgi edinmek için IntelliSense kullanın.", - "launch.config.comment2": "Mevcut özniteliklerin açıklamalarını görmek için fare ile üzerine gelin.", - "launch.config.comment3": "Daha fazla bilgi için ziyaret edin: {0}", - "debugType": "Yapılandırma türü.", - "debugTypeNotRecognised": "Hata ayıklama türü tanınmıyor. Karşılık gelen hata ayıklama uzantısı yüklemiş olduğunuzdan ve etkinleştirildiğinden emin olun.", - "node2NotSupported": "\"node2\" artık desteklenmiyor, bunun yerine \"node\" kullanın ve \"protocol\" özniteliğini \"inspector\" olarak ayarlayın.", - "debugName": "Yapılandırmanın adı; başlatma yapılandırması açılır kutu menüsünde görünür.", - "debugRequest": "Yapılandırmanın istek türü. \"launch\" veya \"attach\" olabilir.", - "debugServer": "Sadece eklenti geliştirme hata ayıklaması için: eğer port belirtildiyse; Vs Code, bir hata ayıklama bağdaştırıcısına sunucu modunda bağlanmayı dener", - "debugPrelaunchTask": "Hata ayıklama oturumu başlamadan önce çalıştırılacak görev.", - "debugWindowsConfiguration": "Windows'a özel başlangıç yapılandırması öznitelikleri.", - "debugOSXConfiguration": "OS X'e özel başlangıç yapılandırması öznitelikleri.", - "debugLinuxConfiguration": "Linux'a özel başlangıç yapılandırması öznitelikleri.", - "deprecatedVariables": "'env.', 'config.' ve 'command.' kullanım dışıdır, bunların yerine 'env:', 'config:' ve 'command:' kulanın." + "unableToLaunchDebugAdapter": "'{0}' tarafından hata ayıklama bağdaştırıcısı başlatılamadı.", + "unableToLaunchDebugAdapterNoArgs": "Hata ayıklama bağdaştırıcısı başlatılamıyor." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/node/debugger.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/node/debugger.i18n.json new file mode 100644 index 0000000000..7c6fe0bcc3 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/debug/node/debugger.i18n.json @@ -0,0 +1,23 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "launch.config.comment1": "Olası öznitelikler hakkında bilgi edinmek için IntelliSense kullanın.", + "launch.config.comment2": "Mevcut özniteliklerin açıklamalarını görmek için fare ile üzerine gelin.", + "launch.config.comment3": "Daha fazla bilgi için ziyaret edin: {0}", + "debugType": "Yapılandırma türü.", + "debugTypeNotRecognised": "Hata ayıklama türü tanınmıyor. Karşılık gelen hata ayıklama uzantısı yüklemiş olduğunuzdan ve etkinleştirildiğinden emin olun.", + "node2NotSupported": "\"node2\" artık desteklenmiyor, bunun yerine \"node\" kullanın ve \"protocol\" özniteliğini \"inspector\" olarak ayarlayın.", + "debugName": "Yapılandırmanın adı; başlatma yapılandırması açılır kutu menüsünde görünür.", + "debugRequest": "Yapılandırmanın istek türü. \"launch\" veya \"attach\" olabilir.", + "debugServer": "Sadece eklenti geliştirme hata ayıklaması için: eğer port belirtildiyse; Vs Code, bir hata ayıklama bağdaştırıcısına sunucu modunda bağlanmayı dener", + "debugPrelaunchTask": "Hata ayıklama oturumu başlamadan önce çalıştırılacak görev.", + "debugWindowsConfiguration": "Windows'a özel başlangıç yapılandırması öznitelikleri.", + "debugOSXConfiguration": "OS X'e özel başlangıç yapılandırması öznitelikleri.", + "debugLinuxConfiguration": "Linux'a özel başlangıç yapılandırması öznitelikleri.", + "deprecatedVariables": "'env.', 'config.' ve 'command.' kullanım dışıdır, bunların yerine 'env:', 'config:' ve 'command:' kulanın." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/node/terminals.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/node/terminals.i18n.json new file mode 100644 index 0000000000..4fbca0dfa7 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/debug/node/terminals.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "console.title": "VS Code Konsolu", + "mac.terminal.script.failed": "'{0}' betiği, {1} çıkış koduyla başarısız oldu", + "mac.terminal.type.not.supported": "'{0}' desteklenmiyor", + "press.any.key": "Devam etmek için bir tuşa basın ...", + "linux.term.failed": "'{0}', {1} çıkış koduyla başarısız oldu" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json index f1d1c3143a..7112aa9c0b 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/browser/extensionsActions.i18n.json @@ -27,7 +27,7 @@ "enableAutoUpdate": "Eklentileri Otomatik Olarak Güncelleştirmeyi Etkinleştir", "disableAutoUpdate": "Eklentileri Otomatik Olarak Güncelleştirmeyi Devre Dışı Bırak", "updateAll": "Tüm Eklentileri Güncelle", - "reloadAction": "Yeniden Yükle", + "reloadAction": "Pencereyi Yeniden Yükle", "postUpdateTooltip": "Güncellemek için yeniden yükleyin", "postUpdateMessage": "Güncellenen '{0}' eklentisini etkinleştirmek için bu pencere yeniden yüklensin mi?", "postEnableTooltip": "Etkinleştirmek için yeniden yükleyin", @@ -58,6 +58,9 @@ "configureWorkspaceFolderRecommendedExtensions": "Tavsiye Edilen Eklentileri Yapılandır (Çalışma Alanı Klasörü)", "malicious tooltip": "Bu eklentinin sorunlu olduğu bildirildi.", "malicious": "Kötü amaçlı", + "disabled": "Devre Dışı", + "disabled globally": "Devre Dışı", + "disabled workspace": "Bu Çalışma Alanı için Devre Dışı Bırakılmış", "disableAll": "Yüklü Tüm Eklentileri Devre Dışı Bırak", "disableAllWorkspace": "Bu Çalışma Alanı için Yüklü Tüm Eklentileri Devre Dışı Bırak", "enableAll": "Tüm Eklentileri Etkinleştir", diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json new file mode 100644 index 0000000000..fc22fcd9e4 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.i18n.json @@ -0,0 +1,61 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "name": "Eklenti adı", + "extension id": "Eklenti tanımlayıcısı", + "preview": "Önizleme", + "builtin": "Yerleşik", + "publisher": "Yayıncı adı", + "install count": "Yüklenme sayısı", + "rating": "Derecelendirme", + "repository": "Depo", + "license": "Lisans", + "details": "Detaylar", + "contributions": "Eklemeler", + "changelog": "Değişim Günlüğü", + "dependencies": "Bağımlılıklar", + "noReadme": "README dosyası yok.", + "noChangelog": "Değişim günlüğü yok.", + "noContributions": "Hiçbir Ekleme Yapmıyor", + "noDependencies": "Bağımlılık Yok", + "settings": "Ayarlar ({0})", + "setting name": "Adı", + "description": "Açıklama", + "default": "Varsayılan", + "debuggers": "Hata Ayıklayıcılar ({0})", + "debugger name": "Adı", + "debugger type": "Tür", + "views": "Görünümler ({0})", + "view id": "ID", + "view name": "Adı", + "view location": "Yeri", + "localizations": "Çeviriler ({0})", + "localizations language id": "Dil Id'si", + "localizations language name": "Dil Adı", + "localizations localized language name": "Dil Adı (Yerelleştirilmiş)", + "colorThemes": "Renk Temaları ({0})", + "iconThemes": "Simge Temaları ({0})", + "colors": "Renkler ({0})", + "colorId": "Id", + "defaultDark": "Koyu Varsayılan", + "defaultLight": "Açık Varsayılan", + "defaultHC": "Yüksek Karşıtlık Varsayılan", + "JSON Validation": "JSON Doğrulama ({0})", + "fileMatch": "Dosya Eşleşmesi", + "schema": "Şema", + "commands": "Komutlar ({0})", + "command name": "Adı", + "keyboard shortcuts": "Klavye Kısayolları", + "menuContexts": "Menü Bağlamları", + "languages": "Diller ({0})", + "language id": "ID", + "language name": "Adı", + "file extensions": "Dosya Uzantıları", + "grammar": "Gramer", + "snippets": "Parçacıklar" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 065063eee8..e2418ac41c 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -15,8 +15,8 @@ "workspaceRecommendation": "Bu eklenti geçerli çalışma alanı kullanıcıları tarafından tavsiye ediliyor.", "reallyRecommended2": "'{0}' eklentisi bu dosya türü için tavsiye edilir.", "reallyRecommendedExtensionPack": "'{0}' eklenti paketi bu dosya türü için tavsiye edilir.", - "showRecommendations": "Tavsiyeleri Göster", "install": "Yükle", + "showRecommendations": "Tavsiyeleri Göster", "showLanguageExtensions": "Markette '.{0}' dosyaları için yardımcı olabilecek eklentiler bulunuyor", "workspaceRecommended": "Bu çalışma alanı bazı eklentileri tavsiye ediyor.", "installAll": "Tümünü Yükle", diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.i18n.json index 2282322944..85e9f33569 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -15,6 +15,6 @@ "developer": "Geliştirici", "extensionsConfigurationTitle": "Eklentiler", "extensionsAutoUpdate": "Eklentileri otomatik olarak güncelle", - "extensionsIgnoreRecommendations": "\"Doğru\" olarak ayarlanırsa, eklenti tavsiyeleri bildirimleri artık gösterilmez.", - "extensionsShowRecommendationsOnlyOnDemand": "Doğru olarak ayarlanırsa, kullanıcı tarafından özel olarak istenmedikçe tavsiyeler alınmaz ve gösterilmez." + "extensionsIgnoreRecommendations": "\"true\" değeri atanırsa, eklenti tavsiyeleri bildirimleri artık gösterilmez.", + "extensionsShowRecommendationsOnlyOnDemand": "\"true\" değeri atanırsa, kullanıcı tarafından özel olarak istenmedikçe tavsiyeler alınmaz ve gösterilmez." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json index 1faa921840..894c92fefe 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.i18n.json @@ -8,7 +8,5 @@ ], "disableOtherKeymapsConfirmation": "Tuş bağlamlarında çakışmalardan kaçınmak için diğer tuş haritaları ({0}) devre dışı bırakılsın mı?", "yes": "Evet", - "no": "Hayır", - "betterMergeDisabled": "\"Better Merge\" artık yerleşik bir eklenti, yüklenen eklendi devre dışı bırakıldı ve kaldırılabilir.", - "uninstall": "Kaldır" + "no": "Hayır" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json index 18b765e09e..059c3d6e6d 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.i18n.json @@ -2,7 +2,7 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], @@ -12,7 +12,9 @@ "recommendedExtensions": "Tavsiye Edilen", "otherRecommendedExtensions": "Diğer Tavsiyeler", "workspaceRecommendedExtensions": "Çalışma Alanı Tavsiyeleri", - "builtInExtensions": "Yerleşik", + "builtInExtensions": "Özellikler", + "builtInThemesExtensions": "Temalar", + "builtInBasicsExtensions": "Programlama Dilleri", "searchExtensions": "Markette Eklenti Ara", "sort by installs": "Sırala: Yüklenme Sayısına Göre", "sort by rating": "Sırala: Derecelendirmeye Göre", diff --git a/i18n/trk/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json b/i18n/trk/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json index a5dd6a4789..a43f38fbef 100644 --- a/i18n/trk/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/browser/editors/textFileEditor.i18n.json @@ -8,6 +8,8 @@ ], "textFileEditor": "Metin Dosyası Düzenleyicisi", "createFile": "Dosya Oluştur", + "relaunchWithIncreasedMemoryLimit": "{0} MB ile Yeniden Başlat", + "configureMemoryLimit": "Bellek Sınırını Yapılandır", "fileEditorWithInputAriaLabel": "{0}. Metin dosyası düzenleyici.", "fileEditorAriaLabel": "Metin dosyası düzenleyici." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 14fca5167e..dce58d397e 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -24,19 +24,25 @@ "dirtyMessageFolderDelete": "{0} dosyada kaydedilmemiş değişiklik barındıran bir klasörü siliyorsunuz. Devam etmek istiyor musunuz?", "dirtyMessageFileDelete": "Kaydedilmemiş değişiklik barındıran bir dosyayı siliyorsunuz. Devam etmek istiyor musunuz?", "dirtyWarning": "Değişiklikleriniz, kaydetmezseniz kaybolur.", + "undoBin": "Geri Dönüşüm Kutusu'ndan geri alabilirsiniz.", + "undoTrash": "Çöp Kutusu'ndan geri alabilirsiniz.", + "doNotAskAgain": "Bir daha sorma", + "irreversible": "Bu eylem geri döndürülemez!", + "binFailed": "Geri Dönüşüm Kutusu'nu kullanarak silme başarısız oldu. Bunun yerine, kalıcı olarak silmek ister misiniz?", + "trashFailed": "Çöp Kutusu'nu kullanarak silme başarısız oldu. Bunun yerine, kalıcı olarak silmek ister misiniz?", + "deletePermanentlyButtonLabel": "&&Kalıcı Olarak Sil", + "retryButtonLabel": "&&Yeniden Dene", + "confirmMoveTrashMessageFilesAndDirectories": "Aşağıdaki {0} dosyayı/dizini ve içindekileri silmek istediğinizden emin misiniz?", + "confirmMoveTrashMessageMultipleDirectories": "Aşağıdaki {0} dizini ve içindekileri silmek istediğinizden emin misiniz?", "confirmMoveTrashMessageMultiple": "Aşağıdaki {0} dosyayı silmek istediğinizden emin misiniz?", "confirmMoveTrashMessageFolder": "'{0}' ve içindekileri silmek istediğinizden emin misiniz?", "confirmMoveTrashMessageFile": "'{0}' öğesini silmek istediğinize emin misiniz?", - "undoBin": "Geri dönüşüm kutusundan geri alabilirsiniz.", - "undoTrash": "Çöp kutusundan geri alabilirsiniz.", - "doNotAskAgain": "Bir daha sorma", + "confirmDeleteMessageFilesAndDirectories": "Aşağıdaki {0} dosyayı/dizini ve içindekileri kalıcı olarak silmek istediğinizden emin misiniz?", + "confirmDeleteMessageMultipleDirectories": "Aşağıdaki {0} dizini ve içindekileri kalıcı olarak silmek istediğinizden emin misiniz?", "confirmDeleteMessageMultiple": "Aşağıdaki {0} dosyayı kalıcı olarak silmek istediğinizden emin misiniz?", "confirmDeleteMessageFolder": "'{0}' öğesini ve içindekileri kalıcı olarak silmek istediğinizden emin misiniz?", "confirmDeleteMessageFile": "'{0}' öğesini kalıcı olarak silmek istediğinizden emin misiniz?", - "irreversible": "Bu eylem geri döndürülemez!", - "cancel": "İptal", - "permDelete": "Kalıcı Olarak Sil", - "importFiles": "Dosya İçe Aktar", + "addFiles": "Dosya Ekle", "confirmOverwrite": "Hedef klasörde aynı ada sahip bir dosya veya klasör zaten var. Değiştirmek istiyor musunuz?", "replaceButtonLabel": "&&Değiştir", "fileIsAncestor": "Yapıştırılacak dosya hedef klasörün atalarından biridir", @@ -56,6 +62,7 @@ "openFileToShowInNewWindow": "Yeni pencerede açmak için ilk olarak bir dosya açın", "copyPath": "Yolu Kopyala", "emptyFileNameError": "Bir dosya veya klasör adı sağlanması gerekiyor.", + "fileNameStartsWithSlashError": "Bir dosya veya klasör adı eğik çizgi(slash) ile başlayamaz.", "fileNameExistsError": "Bu konumda bir **{0}** dosyası veya klasörü zaten mevcut. Lütfen başka bir ad seçin.", "invalidFileNameError": "**{0}** adı, bir dosya veya klasör adı olarak geçerli değildir. Lütfen başka bir ad seçin.", "filePathTooLongError": "**{0}** adı çok uzun bir yol ile sonuçlanıyor. Lütfen daha kısa bir ad seçin.", diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 6b26ae5f2c..21c84bf545 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -37,6 +37,7 @@ "defaultLanguage": "Yeni dosyalara atanan varsayılan dil modu.", "editorConfigurationTitle": "Düzenleyici", "formatOnSave": "Dosyayı kaydederken biçimlendir. Bir biçimlendirici mevcut olmalıdır, dosya otomatik olarak kaydedilmemelidir, ve düzenleyici kapanmıyor olmalıdır.", + "formatOnSaveTimeout": "Dosyayı kaydederken biçimlendirme zaman aşımı. formatOnSave komutlarında kullanılacak milisaniye cinsinden zaman limiti. Belirtilen zaman aşımından daha uzun süren komutlar iptal edilecektir.", "explorerConfigurationTitle": "Dosya Gezgini", "openEditorsVisible": "Açık Düzenleyiciler bölmesinde gösterilen düzenleyici sayısı.", "autoReveal": "Gezginin dosyaları açarken, onları otomatik olarak ortaya çıkartmasını ve seçmesini denetler.", diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index d273bb6926..d5d15cb8ed 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -13,7 +13,9 @@ "dropFolder": "Klasörü çalışma alanına eklemek istiyor musunuz?", "addFolders": "Klasörleri &&Ekle", "addFolder": "Klasörü &&Ekle", + "confirmRootsMove": "Çalışma alanınızdaki birden çok kök dizinin sırasını değiştirmek istediğinizden emin misiniz?", "confirmMultiMove": "Aşağıdaki {0} dosyayı taşımak istediğinizden emin misiniz?", + "confirmRootMove": "Çalışma alanınızdaki '{0}' kök dizininin sırasını değiştirmek istediğinizden emin misiniz?", "confirmMove": "'{0}' ögesini taşımak istediğinizden emin misiniz?", "doNotAskAgain": "Bir daha sorma", "moveButtonLabel": "&&Taşı", diff --git a/i18n/trk/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json new file mode 100644 index 0000000000..7c90e93cdd --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/html/electron-browser/html.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.editor.label": "Html Önizlemesi" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json b/i18n/trk/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json new file mode 100644 index 0000000000..a11acc3979 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "html.voidInput": "Geçersiz düzenleyici girdisi." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..af6d69fa60 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/html/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "developer": "Geliştirici" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json b/i18n/trk/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..13712f3e4c --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/html/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Web Görünümü Geliştirici Araçlarını Aç", + "refreshWebviewLabel": "Web Görünümlerini Yeniden Yükle" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json index a7b2974e7b..dc30e353cd 100644 --- a/i18n/trk/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/localizations/browser/localizations.contribution.i18n.json @@ -6,13 +6,17 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "updateLocale": "VS Code'un kullanıcı arayüzü dilini {0} olarak değiştirip yeniden başlatmak ister misiniz?", + "yes": "Evet", + "no": "Hayır", + "neverAgain": "Tekrar Gösterme", "JsonSchema.locale": "Kullanılacak Kullanıcı Arayüzü Dili.", "vscode.extension.contributes.localizations": "Düzenleyiciye yerelleştirmeleri ekler", - "vscode.extension.contributes.localizations.languageId": "Görüntülenen dizelerin çevrileceği dilin kimliği.", + "vscode.extension.contributes.localizations.languageId": "Görüntülenen dizelerin çevrileceği dilin id'si.", "vscode.extension.contributes.localizations.languageName": "Dilin İngilizcedeki adı.", "vscode.extension.contributes.localizations.languageNameLocalized": "Dilin eklenen dildeki adı.", "vscode.extension.contributes.localizations.translations": "Bu dille ilişkili çevirilerin listesi.", - "vscode.extension.contributes.localizations.translations.id": "Bu çevirinin ekleneceği VS Code veya Eklenti kimliği. VS Code kimliği her zaman `vscode` şeklindedir ve eklenti ise `yayinciAdi.eklentiAdi` biçiminde olmalıdır.", - "vscode.extension.contributes.localizations.translations.id.pattern": "Kimlik, VS Code çevirisi için `vscode` olmalı veya eklenti çevirisi için `yayinciAdi.eklentiAdi` biçiminde olmalıdır.", + "vscode.extension.contributes.localizations.translations.id": "Bu çevirinin ekleneceği VS Code veya Eklenti id'si. VS Code id'si her zaman`vscode` şeklindedir ve eklenti `yayinciAdi.eklentiAdi` formatında olmalıdır.", + "vscode.extension.contributes.localizations.translations.id.pattern": "Id, VS Code çevirisi için `vscode` olmalı veya eklenti çevirisi için `yayinciAdi.eklentiAdi` biçiminde olmalıdır.", "vscode.extension.contributes.localizations.translations.path": "Dilin çevirilerini içeren dosyaya göreli yol." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json new file mode 100644 index 0000000000..60cd3a5c2b --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.i18n.json @@ -0,0 +1,25 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "updateLocale": "VS Code'un kullanıcı arayüzü dilini {0} olarak değiştirip yeniden başlatmak ister misiniz?", + "yes": "Evet", + "no": "Hayır", + "neverAgain": "Tekrar Gösterme", + "install language pack": "Yakın gelecekte, VS Code dil paketlerini sadece Market uzantısı biçiminde destekleyecektir. Şu an yapılandırmada yer alan dili kullanmaya devam etmek için lütfen '{0}' eklentisini yükleyin.", + "install": "Yükle", + "more information": "Daha Fazla Bilgi...", + "JsonSchema.locale": "Kullanılacak Kullanıcı Arayüzü Dili.", + "vscode.extension.contributes.localizations": "Düzenleyiciye yerelleştirmeleri ekler", + "vscode.extension.contributes.localizations.languageId": "Görüntülenen dizelerin çevrileceği dilin id'si.", + "vscode.extension.contributes.localizations.languageName": "Dilin İngilizcedeki adı.", + "vscode.extension.contributes.localizations.languageNameLocalized": "Dilin eklenen dildeki adı.", + "vscode.extension.contributes.localizations.translations": "Bu dille ilişkili çevirilerin listesi.", + "vscode.extension.contributes.localizations.translations.id": "Bu çevirinin ekleneceği VS Code veya Eklenti id'si. VS Code id'si her zaman`vscode` şeklindedir ve eklenti `yayinciAdi.eklentiAdi` formatında olmalıdır.", + "vscode.extension.contributes.localizations.translations.id.pattern": "Id, VS Code çevirisi için `vscode` olmalı veya eklenti çevirisi için `yayinciAdi.eklentiAdi` biçiminde olmalıdır.", + "vscode.extension.contributes.localizations.translations.path": "Dilin çevirilerini içeren dosyaya göreli yol." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json b/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json new file mode 100644 index 0000000000..9cd3515ce9 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.i18n.json @@ -0,0 +1,14 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "configureLocale": "Dili Yapılandır", + "displayLanguage": "VSCode'un görüntüleme dilini tanımlar.", + "doc": "Desteklenen dillerin listesi için göz atın: {0}", + "restart": "Değeri değiştirirseniz VSCode'u yeniden başlatmanız gerekir.", + "fail.createSettings": " '{0}' oluşturulamadı ({1})." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json new file mode 100644 index 0000000000..45570f731d --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "copyMarker": "Kopyala", + "copyMessage": "Mesajı Kopyala" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json new file mode 100644 index 0000000000..a84cf939af --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markers.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "totalProblems": "Toplam {0} Sorun" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json new file mode 100644 index 0000000000..a2b9d4cb87 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.i18n.json @@ -0,0 +1,13 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "label": "Sorunlar", + "tooltip.1": "Bu dosyada 1 sorun var", + "tooltip.N": "Bu dosyada {0} sorun var", + "markers.showOnFile": "Dosya ve klasörlerde Hata & Uyarıları göster." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json new file mode 100644 index 0000000000..9f3ba8354e --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanel.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "disableFilesExclude": "Dosya Hariç Tutma Filtresini Devre Dışı Bırak.", + "clearFilter": "Filtreyi Temizle." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json new file mode 100644 index 0000000000..c04a09e8c0 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "showing filtered problems": "{0}/{1} gösteriliyor" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json new file mode 100644 index 0000000000..45e5f83680 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/markers/electron-browser/messages.i18n.json @@ -0,0 +1,48 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "viewCategory": "Görüntüle", + "problems.view.toggle.label": "Sorunları Aç/Kapat (Hatalar, Uyarılar, Bilgiler)", + "problems.view.focus.label": "Sorunlara Odakla (Hatalar, Uyarılar, Bilgiler)", + "problems.panel.configuration.title": "Sorunlar Görünümü", + "problems.panel.configuration.autoreveal": "Sorunlar görünümünün; dosyalar açılırken, dosyaları otomatik olarak ortaya çıkarıp çıkarmayacağını denetler.", + "markers.panel.title.problems": "Sorunlar", + "markers.panel.aria.label.problems.tree": "Dosyalara göre gruplandırılmış sorunlar", + "markers.panel.no.problems.build": "Şu ana kadar çalışma alanında herhangi bir sorun tespit edilmedi.", + "markers.panel.no.problems.filters": "Belirtilen filtre ölçütleriyle sonuç bulunamadı.", + "markers.panel.no.problems.file.exclusions": "Dosya hariç tutma filtresi etkinleştirildiği için tüm sorunlar gizlenmiştir.", + "markers.panel.action.useFilesExclude": "Dosya Hariç Tutma Ayarını kullanarak filtrele", + "markers.panel.action.donotUseFilesExclude": "Dosya Hariç Tutma Ayarını kullanma", + "markers.panel.action.filter": "Sorunları Filtrele", + "markers.panel.filter.ariaLabel": "Sorunları Filtrele", + "markers.panel.filter.placeholder": "Filtre. Ör: metin, **/*.ts, !**/node_modules/**", + "markers.panel.filter.errors": "hatalar", + "markers.panel.filter.warnings": "uyarılar", + "markers.panel.filter.infos": "bilgilendirmeler", + "markers.panel.single.error.label": "1 Hata", + "markers.panel.multiple.errors.label": "{0} Hata", + "markers.panel.single.warning.label": "1 Uyarı", + "markers.panel.multiple.warnings.label": "{0} Uyarı", + "markers.panel.single.info.label": "1 Bilgilendirme", + "markers.panel.multiple.infos.label": "{0} Bilgilendirme", + "markers.panel.single.unknown.label": "1 Bilinmeyen", + "markers.panel.multiple.unknowns.label": "{0} Bilinmeyen", + "markers.panel.at.ln.col.number": "({0}, {1})", + "problems.tree.aria.label.resource": "{0} {1} sorun içeriyor", + "problems.tree.aria.label.marker.relatedInformation": "Bu sorun {0} konumla ilişkilidir.", + "problems.tree.aria.label.error.marker": "{0} tarafından oluşturulan hata: {2}. satırın {3}. karakterinde {1}.{4}", + "problems.tree.aria.label.error.marker.nosource": "Hata: {1}. satırın {2}. karakterinde {0}.{3}", + "problems.tree.aria.label.warning.marker": "{0} tarafından oluşturulan uyarı: {2}. satırın {3}. karakterinde {1}.{4}", + "problems.tree.aria.label.warning.marker.nosource": "Uyarı: {1}. satırın {2}. karakterinde {0}.{3}", + "problems.tree.aria.label.info.marker": "{0} tarafından oluşturulan bilgilendirme: {2}. satırın {3}. karakterinde {1}.{4}", + "problems.tree.aria.label.info.marker.nosource": "Bilgilendirme: {1}. satırın {2}. karakterinde {0}.{3}", + "problems.tree.aria.label.marker": "{0} tarafından oluşturulan sorun: {2}. satırın {3}. karakterinde {1}.{4}", + "problems.tree.aria.label.marker.nosource": "Sorun: {1}. satırın {2}. karakterinde {0}.{3}", + "problems.tree.aria.label.relatedinfo.message": "{3} dosyasının {1}. satırın {2}. karakterinde {0}", + "errors.warnings.show.label": "Hataları ve Uyarıları Göster" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/output/browser/outputActions.i18n.json b/i18n/trk/src/vs/workbench/parts/output/browser/outputActions.i18n.json index 6dc2f007e8..4bb32634b6 100644 --- a/i18n/trk/src/vs/workbench/parts/output/browser/outputActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/output/browser/outputActions.i18n.json @@ -9,5 +9,6 @@ "toggleOutput": "Çıktıyı Aç/Kapat", "clearOutput": "Çıktıyı Temizle", "toggleOutputScrollLock": "Çıktı Kaydırma Kilidini Aç/Kapat", - "switchToOutput.label": "Çıktıya Geçiş Yap" + "switchToOutput.label": "Çıktıya Geçiş Yap", + "openInLogViewer": "Günlük Dosyasını Aç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json index 2b4be21bf3..f16b14837e 100644 --- a/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -9,5 +9,6 @@ "output": "Çıktı", "logViewer": "Günlük Görüntüleyici", "viewCategory": "Görüntüle", - "clearOutput.label": "Çıktıyı Temizle" + "clearOutput.label": "Çıktıyı Temizle", + "openActiveLogOutputFile": "Görüntüle: Aktif Günlük Dosyasını Aç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index f4843b1734..a08a5968e7 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -6,7 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "keybindingsInputName": "Klavye Kısayolları", + "showDefaultKeybindings": "Varsayılan Tuş Bağlarını Göster", + "showUserKeybindings": "Kullanıcı Tuş Bağlarını Göster", "SearchKeybindings.AriaLabel": "Tuş bağlarını ara", "SearchKeybindings.Placeholder": "Tuş bağlarını ara", "sortByPrecedene": "Önceliğe Göre Sırala", diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json index 4e3e2cfef1..d6cb9139a7 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesActions.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "openRawDefaultSettings": "Ham Varsayılan Ayarları Aç", + "openSettings": "Ayarları Aç", "openGlobalSettings": "Kullanıcı Ayarlarını Aç", "openGlobalKeybindings": "Klavye Kısayollarını Aç", "openGlobalKeybindingsFile": "Klavye Kısayolları Dosyasını Aç", diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 47bfc93225..7291a98ea0 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "settingsEditorName": "Varsayılan Ayarlar", "SearchSettingsWidget.AriaLabel": "Ayarları ara", "SearchSettingsWidget.Placeholder": "Ayarları Ara", "noSettingsFound": "Sonuç Yok", @@ -16,6 +15,8 @@ "nlpResult": "Doğal Dil Sonuçları", "filterResult": "Filtrelenmiş Sonuçlar", "defaultSettings": "Varsayılan Ayarlar", + "defaultUserSettings": "Varsayılan Kullanıcı Ayarları", + "defaultWorkspaceSettings": "Varsayılan Çalışma Alanı Ayarları", "defaultFolderSettings": "Varsayılan Klasör Ayarları", "defaultEditorReadonly": "Varsayılan ayarları geçersiz kılmak için sağ taraftaki düzeyicide düzenleme yapın.", "preferencesAriaLabel": "Varsayılan tercihler. Salt okunabilir metin editörü." diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json index 47e3ef1158..8a26fb1cc5 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesRenderers.i18n.json @@ -13,9 +13,5 @@ "newExtensionLabel": "\"{0}\" Eklentisini Göster", "editTtile": "Düzenle", "replaceDefaultValue": "Ayarlarda Değiştir", - "copyDefaultValue": "Ayarlara Kopyala", - "unsupportedPHPExecutablePathSetting": "Bu ayar, bir Kullanıcı Ayarı olmalıdır. PHP'yi çalışma alanı için yapılandırmak için bir PHP dosyasını açın ve durum çubuğundaki 'PHP Yolu'na tıklayın.", - "unsupportedWorkspaceSetting": "Bu ayar, bir Kullanıcı Ayarı olmalıdır.", - "unsupportedWorkbenchSetting": "Bu ayar şu an uygulanamıyor. Ayar, bu klasörü açtığınızda uygulanacaktır.", - "unsupportedWorkbenchSettingDevMode": "Bu ayar şu an uygulanamıyor. Ayar, kaydederken kapsamını 'resource' olarak tanımladığınızda veya bu klasörü direkt olarak açtığınızda uygulanacaktır." + "copyDefaultValue": "Ayarlara Kopyala" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 57c80db601..52bddf418e 100644 --- a/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -11,5 +11,6 @@ "installAdditionalSCMProviders": "Ek SCM Sağlayıcıları Yükle...", "no open repo": "Aktif bir kaynak kontrolü sağlayıcısı yok.", "source control": "Kaynak Kontrolü", - "viewletTitle": "{0}: {1}" + "viewletTitle": "{0}: {1}", + "hideView": "Gizle" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json index ddea3c4eb0..0166981722 100644 --- a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,7 +12,6 @@ "previousSearchExcludePattern": "Önceki Aramada Hariç Tutulan Kalıbı Göster", "nextSearchTerm": "Sonraki Arama Terimini Göster", "previousSearchTerm": "Önceki Arama Terimini Göster", - "showSearchViewlet": "Aramayı Göster", "findInFiles": "Dosyalarda Bul", "replaceInFiles": "Dosyalardakileri Değiştir", "RefreshAction.label": "Yenile", diff --git a/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 88c462ec48..33b0d22cf5 100644 --- a/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -2,15 +2,20 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "search": "Ara", + "copyMatchLabel": "Kopyala", + "copyPathLabel": "Yolu Kopyala", + "copyAllLabel": "Tümünü Kopyala", + "clearSearchHistoryLabel": "Arama Geçmişini Temizle", + "toggleSearchViewPositionLabel": "Arama Görünümü Konumunu Değiştir", "findInFolder": "Klasörde Bul...", "findInWorkspace": "Çalışma Alanında Bul...", "showTriggerActions": "Çalışma Alanında Sembole Git...", "name": "Ara", - "search": "Ara", "showSearchViewl": "Aramayı Göster", "view": "Görüntüle", "findInFiles": "Dosyalarda Bul", @@ -25,6 +30,5 @@ "search.quickOpen.includeSymbols": "Dosya sonuçlarındaki bir global sembol aramasının sonuçlarının Hızlı Aç'a dahil edilip edilmeyeceğini yapılandırın.", "search.followSymlinks": "Arama yaparken sembolik linklerin takip edilip edilmeyeceğini denetler.", "search.smartCase": "Örüntü tamamen küçük harflerden oluşuyorsa büyük küçük harf duyarlılığı olmadan arar, diğer durumda ise büyük küçük harf duyarlılığı ile arar", - "search.globalFindClipboard": "macOS'de arama görünümünün paylaşılan panoyu okuyup okumamasını veya değiştirip değiştirmemesini denetler", - "search.location": "Önizleme: aramanın kenar çubuğunda bir görünüm olarak mı yoksa daha fazla yatay boşluk için panel alanında bir panel olarak mı gösterileceğini denetler. Bir sonraki sürümde paneldeki arama, geliştirilmiş yatay düzene sahip olacak ve bu bir önizleme olmaktan çıkacaktır." + "search.globalFindClipboard": "macOS'de arama görünümünün paylaşılan panoyu okuyup okumamasını veya değiştirip değiştirmemesini denetler" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json index e605334cde..a9d5a16144 100644 --- a/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "helpUs": "{0} için hizmetimizi iyileştirmemize yardımcı olun", "takeShortSurvey": "Kısa Ankete Katıl", "remindLater": "Daha Sonra Hatırlat", - "neverAgain": "Tekrar Gösterme", - "helpUs": "{0} için hizmetimizi iyileştirmemize yardımcı olun" + "neverAgain": "Tekrar Gösterme" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json index 7dbb8344f2..3d83a91fb2 100644 --- a/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.i18n.json @@ -6,8 +6,8 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "surveyQuestion": "Hızlı bir geri bildirim anketine katılmak ister misiniz?", "takeSurvey": "Ankete Katıl", "remindLater": "Daha Sonra Hatırlat", - "neverAgain": "Tekrar Gösterme", - "surveyQuestion": "Hızlı bir geri bildirim anketine katılmak ister misiniz?" + "neverAgain": "Tekrar Gösterme" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json index 09f3d20de3..6cce3760b9 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/common/problemMatcher.i18n.json @@ -45,16 +45,17 @@ "PatternTypeSchema.description": "Bir sorun modeli veya bir katkıda bulunulan veya ön tanımlı sorun modelinin adı. Temel model belirtildiyse atlanabilir.", "ProblemMatcherSchema.base": "Kullanılacak temel sorun eşleştiricisinin adı.", "ProblemMatcherSchema.owner": "Code'un içindeki sorunun sahibi. Temel model belirtildiyse atlanabilir. Atlanırsa ve temel belirtilmemişse 'external' varsayılır.", + "ProblemMatcherSchema.source": "Bu tanılama bilgilerinin kaynağını açıklayan insan tarafından okunabilir bir dize, ör. 'typescript' veya 'super lint'.", "ProblemMatcherSchema.severity": "Sorun yakalamanın varsayılan önem derecesi. Model, önem derecesi için bir eşleme grubu tanımlamazsa kullanılır.", "ProblemMatcherSchema.applyTo": "Bir metin belgesinde bildirilen bir sorunun sadece açık, kapalı veya tüm belgelere uygulanıp uygulanmadığını denetler.", "ProblemMatcherSchema.fileLocation": "Bir sorun modelinde bildirilen dosya adlarının nasıl yorumlanacağını tanımlar.", "ProblemMatcherSchema.background": "Bir arka plan görevinde aktif bir eşleştiricinin başlangıcını ve sonunu izlemek için kullanılan kalıplar.", - "ProblemMatcherSchema.background.activeOnStart": "\"true\" olarak ayarlanırsa, görev başladığında arka plan izleyicisi etkin modda olur. Bu, beginsPattern ile başlayan bir satırın verilmesi demektir", + "ProblemMatcherSchema.background.activeOnStart": "\"true\" değeri atanırsa, görev başladığında arka plan izleyicisi etkin modda olur. Bu, beginsPattern ile başlayan bir satırın verilmesi demektir", "ProblemMatcherSchema.background.beginsPattern": "Çıktıda eşleşmesi halinde, arka plan görevinin başlatılması sinyali verilir.", "ProblemMatcherSchema.background.endsPattern": "Çıktıda eşleşmesi halinde, arka plan görevinin sonu sinyali verilir.", "ProblemMatcherSchema.watching.deprecated": "İzleme özelliği kullanım dışıdır. Onun yerine arka planı kullanın.", "ProblemMatcherSchema.watching": "Bir izleme eşleştiricisinin başlangıcını ve sonunu izlemek için kullanılan kalıplar.", - "ProblemMatcherSchema.watching.activeOnStart": "\"true\" olarak ayarlanırsa, görev başladığında izleyici etkin modda olur. Bu, beginsPattern ile başlayan bir satırın verilmesi demektir", + "ProblemMatcherSchema.watching.activeOnStart": "\"true\" değeri atanırsa, görev başladığında izleyici etkin modda olur. Bu, beginsPattern ile başlayan bir satırın verilmesi demektir", "ProblemMatcherSchema.watching.beginsPattern": "Çıktıda eşleşmesi halinde, izleme görevinin başlatılması sinyali verilir.", "ProblemMatcherSchema.watching.endsPattern": "Çıktıda eşleşmesi halinde, izleme görevinin sonu sinyali verilir.", "LegacyProblemMatcherSchema.watchedBegin.deprecated": "Bu özellik kullanım dışıdır. Bunun yerine 'watching' özelliğini kullanın.", diff --git a/i18n/trk/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json index 8bde9754c4..0af21b9e00 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.i18n.json @@ -6,7 +6,6 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "TaskDefinition.description": "Gerçek görev türü", "TaskDefinition.properties": "Görev türünün ek özellikleri", "TaskTypeConfiguration.noType": "Görev türü yapılandırmasında gerekli olan 'taskType' özelliği eksik", "TaskDefinitionExtPoint": "Görev türlerine ekleme yapar" diff --git a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json index a9962df1dc..34253cc9bd 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.i18n.json @@ -12,7 +12,7 @@ "JsonSchema.tasks.dependsOn.array": "Bu görevin bağlı olduğu diğer görevler.", "JsonSchema.tasks.presentation": "Görevin çıktısını gösterip, girdisini okumak için kullanılacak paneli yapılandırır.", "JsonSchema.tasks.presentation.echo": "Çalıştırılan komutun panele yazdırılıp yazdırılmayacağını denetler. Varsayılan olarak açıktır.", - "JsonSchema.tasks.presentation.focus": "Panelin, kendisine odaklanmaya izin verip vermeyeceğini denetler. Varsayılan olarak kapalıdır. Eğer \"true\" olarak ayarlanırsa panel de açığa çıkar.", + "JsonSchema.tasks.presentation.focus": "Panelin, kendisine odaklanmaya izin verip vermeyeceğini denetler. Varsayılan olarak kapalıdır. Eğer \"true\" değeri atanırsa panel de açığa çıkar.", "JsonSchema.tasks.presentation.reveal.always": "Bu görev yürütülürken terminali her zaman ortaya çıkarır.", "JsonSchema.tasks.presentation.reveal.silent": "Sadece hiçbir sorun eşleştiricisi görevle ilişkilendirilmemiş ve görev çalıştırılırken hata oluşuyorsa terminali ortaya çıkar.", "JsonSchema.tasks.presentation.reveal.never": "Bu görev yürütülürken terminali hiçbir zaman ortaya çıkarmaz.", @@ -28,6 +28,15 @@ "JsonSchema.tasks.group.none": "Görevi grupsuz olarak atar", "JsonSchema.tasks.group": "Bu görevin ait olduğu çalıştırma grubunu tanımlar. Derleme grubuna eklemek için \"build\"ı ve test grubuna eklemek için \"test\"i destekler.", "JsonSchema.tasks.type": "Görevin bir işlem olarak veya bir kabukta komut olarak çalıştırılıp çalıştırılmayacağını tanımlar.", + "JsonSchema.command.quotedString.value": "Gerçek komut değeri", + "JsonSchema.tasks.quoting.escape": "Kaçış karakteri olarak kabuğun kaçış karakterini kullanır (ör. PowerShell için ` ve bash için \\).", + "JsonSchema.tasks.quoting.strong": "Argümanı kabuğun güçlü alıntı karakteri ile alıntı haline getirir (ör. PowerShell ve bash için \").", + "JsonSchema.tasks.quoting.weak": "Argümanı kabuğun zayıf alıntı karakteri ile alıntı haline getirir (ör. PowerShell ve bash için ').", + "JsonSchema.command.quotesString.quote": "Komut değerinin tırnak içine nasıl alınacağı.", + "JsonSchema.command": "Çalıştırılacak komut. Harici bir program veya bir kabuk komutu olabilir.", + "JsonSchema.args.quotedString.value": "Gerçek argüman değeri", + "JsonSchema.args.quotesString.quote": "Gerçek argüman değerinin tırnak içine nasıl alınacağı.", + "JsonSchema.tasks.args": "Bu görev çağrıldığında, komuta iletilecek argümanlar.", "JsonSchema.tasks.label": "Görevin kullanıcı arayüzü etiketi", "JsonSchema.version": "Yapılandırmanın sürüm numarası.", "JsonSchema.tasks.identifier": "launch.json veya dependsOn maddesindeki göreve atıfta başvuracak, kullanıcı tanımlı bir tanımlayıcı.", diff --git a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json index ef67a9ef5f..19ebebef07 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/task.contribution.i18n.json @@ -2,15 +2,18 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], "tasksCategory": "Görevler", "ConfigureTaskRunnerAction.label": "Görevi Yapılandır", + "totalErrors": "{0} Hata", + "totalWarnings": "{0} Uyarı", + "totalInfos": "{0} Bilgilendirme", "problems": "Sorunlar", "building": "Derleniyor...", - "manyMarkers": "99+", + "manyProblems": "10b+", "runningTasks": "Çalışan Görevleri Göster", "tasks": "Görevler", "TaskSystem.noHotSwap": "Aktif bir görev çalıştıran görev yürütme motorunu değiştirmek pencereyi yeniden yüklemeyi gerektirir", @@ -28,8 +31,8 @@ "selectProblemMatcher": "Görev çıktısında taranacak hata ve uyarı türlerini seçin", "customizeParseErrors": "Geçerli görev yapılandırmasında hatalar var. Lütfen, bir görevi özelleştirmeden önce ilk olarak hataları düzeltin.", "moreThanOneBuildTask": "tasks.json dosyasında tanımlı çok fazla derleme görevi var. İlk görev çalıştırılıyor.", - "TaskSystem.activeSame.background": "'{0}' görevi zaten aktif ve arka plan modunda. Görevi sonlandırmak için Görevler menüsünden 'Görevi Sonlandır...'ı kullanın.", - "TaskSystem.activeSame.noBackground": " '{0}' görevi zaten aktif. Görevi sonlandırmak için Görevler menüsünden 'Görevi Sonlandır...'ı kullanın. ", + "terminateTask": "Görevi Sonlandır", + "restartTask": "Görevi Yeniden Başlat", "TaskSystem.active": "Çalışan bir görev zaten var. Bir başkasını çalıştırmadan önce bu görevi sonlandırın.", "TaskSystem.restartFailed": "{0} görevini sonlandırma ve yeniden başlatma başarısız oldu", "TaskService.noConfiguration": "Hata: {0} görev algılaması aşağıdaki yapılandırma için bir görev eklemesi yapmıyor:\n{1}\nYapılandırma yok sayılacaktır.\n", diff --git a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json index 6cbcfc76e0..f5dc1a78d4 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.i18n.json @@ -11,6 +11,5 @@ "TerminalTaskSystem.terminalName": "Görev - {0}", "closeTerminal": "Terminali kapatmak için lütfen bir tuşa basın.", "reuseTerminal": "Terminal görevler tarafından tekrar kullanılacak, kapatmak için herhangi bir tuşa basın.", - "TerminalTaskSystem": "UNC sürücüsünde kabuk komutu yürütülemez.", "unkownProblemMatcher": "{0} sorun eşleştirici çözümlenemiyor. Eşleştirici yok sayılacaktır." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json b/i18n/trk/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json index ab55379a9d..4e26faf6ea 100644 --- a/i18n/trk/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/tasks/node/taskConfiguration.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "ConfigurationParser.invalidCWD": "Uyarı: options.cwd dize türünde olmalıdır. {0} değeri yok sayıldı.\n", + "ConfigurationParser.inValidArg": "Hata: komut argümanı bir dize veya tırnak içinde bir dize olmalıdır. Belirtilen değer:\n{0}", "ConfigurationParser.noargs": "Hata: komut argümanları dizelerden oluşan bir dizi olmalıdır. Belirtilen değer:\n{0}", "ConfigurationParser.noShell": "Uyarı: kabuk yapılandırması sadece görevler terminalde çalıştırılırken desteklenir.", "ConfigurationParser.noName": "Hata: Kapsam bildiriminde Sorun Eşleştirici'nin bir adı olmalıdır:\n{0}\n", @@ -17,7 +18,6 @@ "ConfigurationParser.missingRequiredProperty": "Hata: ihtiyaç duyulan '{1}' özelliği, '{0}' görev yapılandırmasında eksik. Görev yapılandırması yok sayılacaktır.", "ConfigurationParser.notCustom": "Hata: 'tasks' bir özel görev olarak tanımlanmamış. Yapılandırma yok sayılacaktır.\n{0}\n", "ConfigurationParser.noTaskName": "Hata: bir görev, bir 'label' özelliği belirtmelidir. Görev yok sayılacaktır.\n{0}\n", - "taskConfiguration.shellArgs": "Uyarı: '{0}' görevi bir kabuk komutudur ve argümanlarından biri kaçış karakteri içermeyen boşluklar içeriyor olabilir. Doğru komut satırı alıntısını sağlamak için lütfen argümanları komutlarla birleştirin.", "taskConfiguration.noCommandOrDependsOn": "Hata: '{0}' görevi bir komut veya dependsOn özelliği belirtmiyor. Görev yok sayılacaktır. Görevin tanımı:\n{1}", "taskConfiguration.noCommand": "Hata: '{0}' görevi bir komut tanımlamıyor. Görev yok sayılacaktır. Görevin tanımı:\n{1}", "TaskParse.noOsSpecificGlobalTasks": "2.0.0 görev sürümü genel işletim sistemi özel görevlerini desteklemiyor. Bunları işletim sistemine özel komut içeren bir göreve çevirin. Etkilenen görevler:\n{0}" diff --git a/i18n/trk/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json new file mode 100644 index 0000000000..9ae8066e17 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/terminal/common/terminalColorRegistry.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "terminal.background": "Terminalin arka plan rengi; bu, terminalin panelden farklı olarak renklendirilmesini sağlar.", + "terminal.foreground": "Terminalin ön plan rengi.", + "terminalCursor.foreground": "Terminal imlecinin ön plan rengi.", + "terminalCursor.background": "Terminal imlecinin arka plan rengi. Bir blok imlecinin kapladığı bir karakterin rengini özelleştirmeyi sağlar.", + "terminal.selectionBackground": "Terminalin seçim arkaplanı rengi.", + "terminal.border": "Terminaldeki bölmeleri ayıran kenarlığın rengi. panel.border bunun için varsayılan olarak kullanılır.", + "terminal.ansiColor": "Terminalde '{0}' ANSI rengi." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 4a95cff7bc..b6b76fec0b 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -43,6 +43,7 @@ "workbench.action.terminal.scrollUpPage": "Yukarı Kaydır (Sayfa)", "workbench.action.terminal.scrollToTop": "En Üste Kaydır", "workbench.action.terminal.clear": "Temizle", + "workbench.action.terminal.clearSelection": "Seçimi Temizle", "workbench.action.terminal.allowWorkspaceShell": "Çalışma Alanı Kabuk Yapılandırmasına İzin Ver", "workbench.action.terminal.disallowWorkspaceShell": "Çalışma Alanı Kabuk Yapılandırmasına İzin Verme", "workbench.action.terminal.rename": "Yeniden Adlandır", @@ -51,5 +52,9 @@ "workbench.action.terminal.hideFindWidget": "Bulma Aracını Gizle", "nextTerminalFindTerm": "Sonraki Arama Terimini Göster", "previousTerminalFindTerm": "Önceki Arama Terimini Göster", - "quickOpenTerm": "Aktif Terminali Değiştir" + "quickOpenTerm": "Aktif Terminali Değiştir", + "workbench.action.terminal.scrollToPreviousCommand": "Önceki Komuta Kadar Kaydır", + "workbench.action.terminal.scrollToNextCommand": "Sonraki Komuta Kadar Kaydır", + "workbench.action.terminal.selectToPreviousCommand": "Önceki Komuta Kadar Seç", + "workbench.action.terminal.selectToNextCommand": "Sonraki Komuta Kadar Seç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json index 1feb9e2653..1a6d3d9b9b 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.i18n.json @@ -7,6 +7,7 @@ "Do not edit this file. It is machine generated." ], "copy": "Kopyala", + "split": "Böl", "paste": "Yapıştır", "selectAll": "Tümünü Seç", "clear": "Temizle", diff --git a/i18n/trk/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json index fceacee58e..930a02cde2 100644 --- a/i18n/trk/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.i18n.json @@ -6,6 +6,7 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "unsupportedWorkspaceSettings": "Bu çalışma alanı sadece Kullanıcı Ayarları'nda ayarlanabilen ayarlar içeriyor. ({0}). Daha fazla bilgi almak için [buraya]({0}) tıklayın.", "openWorkspaceSettings": "Çalışma Alanı Ayarlarını Aç", "dontShowAgain": "Tekrar Gösterme", "unsupportedWorkspaceSettings": "Bu çalışma alanı sadece Kullanıcı Ayarları'nda ayarlanabilen ayarlar içeriyor. ({0}). Daha fazla bilgi almak için [buraya]({0}) tıklayın." diff --git a/i18n/trk/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json b/i18n/trk/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json new file mode 100644 index 0000000000..2cfd79cc9e --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "releaseNotesInputName": "Sürüm Notları: {0}", + "unassigned": "atanmamış" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json index c5de3ffd27..f7e01d490d 100644 --- a/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -2,12 +2,10 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], - "later": "Daha Sonra", - "unassigned": "atanmamış", "releaseNotes": "Sürüm Notları", "showReleaseNotes": "Sürüm Notlarını Göster", "read the release notes": "{0} v{1} uygulamasına hoş geldiniz! Sürüm Notları'nı okumak ister misiniz?", @@ -17,13 +15,14 @@ "updateIsReady": "Yeni {0} güncellemesi var.", "noUpdatesAvailable": "Şu anda mevcut herhangi bir güncelleme yok.", "ok": "Tamam", - "download now": "Şimdi İndir", "thereIsUpdateAvailable": "Bir güncelleştirme var.", - "installUpdate": "Güncelleştirmeyi Yükle", + "download now": "Şimdi İndir", + "later": "Daha Sonra", "updateAvailable": "Bir güncelleştirme var: {0} {1}", + "installUpdate": "Güncelleştirmeyi Yükle", "updateInstalling": "{0} {1} arka planda yükleniyor, bittiğinde bilgi vereceğiz.", + "updateAvailableAfterRestart": "En son güncellemeyi uygulamak için {0} uygulamasını yeniden başlatın.", "updateNow": "Şimdi Güncelle", - "updateAvailableAfterRestart": "{0} yeniden başlatıldıktan sonra güncellenecektir.", "commandPalette": "Komut Paleti...", "settings": "Ayarlar", "keyboardShortcuts": "Klavye Kısayolları", diff --git a/i18n/trk/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json new file mode 100644 index 0000000000..b2ceac0c29 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/url/electron-browser/url.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openUrl": "URL Aç", + "developer": "Geliştirici" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json new file mode 100644 index 0000000000..402fef291e --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webview.contribution.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "webview.editor.label": "web görünümü düzenleyicisi", + "developer": "Geliştirici" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json b/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json new file mode 100644 index 0000000000..13712f3e4c --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/webview/electron-browser/webviewCommands.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "openToolsLabel": "Web Görünümü Geliştirici Araçlarını Aç", + "refreshWebviewLabel": "Web Görünümlerini Yeniden Yükle" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json b/i18n/trk/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json new file mode 100644 index 0000000000..06a856662b --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.i18n.json @@ -0,0 +1,12 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "telemetryOptOut.optOutNotice": "Microsoft'un kullanım verilerini toplamasına izin vererek VS Code'u geliştirin. [Gizlilik beyanımızı]({0}) okuyun ve nasıl [vazgeçebileceğinizi]({1}) öğrenin.", + "telemetryOptOut.optInNotice": "Microsoft'un kullanım verilerini toplamasına izin vererek VS Code'u geliştirin. [Gizlilik beyanımızı]({0}) okuyun ve nasıl [etkinleştirebileceğinizi]({1}) öğrenin.", + "telemetryOptOut.readMore": "Devamını oku" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json b/i18n/trk/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json index dfd7e8539d..0e89f70038 100644 --- a/i18n/trk/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.i18n.json @@ -13,6 +13,7 @@ "welcomeOverlay.extensions": "Eklentileri yönet", "welcomeOverlay.problems": "Hataları ve uyarıları görüntüle", "welcomeOverlay.commandPalette": "Tüm komutları bul ve çalıştır", + "welcomeOverlay.notifications": "Bildirimleri göster", "welcomeOverlay": "Kullanıcı Arayüzüne Genel Bakış", "hideWelcomeOverlay": "Arayüz Genel Bakışını Gizle", "help": "Yardım" diff --git a/i18n/trk/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/trk/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index d5976e331c..b535a535f3 100644 --- a/i18n/trk/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -27,8 +27,8 @@ "welcomePage.installExtensionPacks": "Araçlar ve diller", "welcomePage.installExtensionPacksDescription": "{0} ve {1} için destek yükle", "welcomePage.moreExtensions": "fazlası", - "welcomePage.installKeymapDescription": "Klavye kısayolları yükle", - "welcomePage.installKeymapExtension": "{0} ve {1} için klavye kısayolları yükle", + "welcomePage.installKeymapDescription": "Ayarlar ve tuş bağları", + "welcomePage.installKeymapExtension": "{0} ve {1} için ayarları ve klavye kısayollarını yükle", "welcomePage.others": "diğerleri", "welcomePage.colorTheme": "Renk teması", "welcomePage.colorThemeDescription": "Düzenleyici ve kodlarınız sevdiğiniz şekilde görünsün", diff --git a/i18n/trk/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json index 004bd87b9d..f9c3d99bfb 100644 --- a/i18n/trk/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/trk/src/vs/workbench/services/actions/electron-browser/menusExtensionPoint.i18n.json @@ -11,7 +11,7 @@ "optstring": "`{0}` özelliği atlanabilir veya `string` türünde olmalıdır", "vscode.extension.contributes.menuItem.command": "Yürütülecek komutun tanımlayıcısı. Komut 'commands' bölümünde tanımlanmalıdır", "vscode.extension.contributes.menuItem.alt": "Yürütülecek alternatif bir komutun tanımlayıcısı. Komut 'commands' bölümünde tanımlanmalıdır", - "vscode.extension.contributes.menuItem.when": "Bu ögeyi göstermek için doğru olması gereken koşul", + "vscode.extension.contributes.menuItem.when": "Bu ögeyi göstermek için gereken koşul", "vscode.extension.contributes.menuItem.group": "Bu komutun ait olduğu gruba ekle", "vscode.extension.contributes.menus": "Düzenleyiciye menü ögeleri ekler", "menus.commandPalette": "Komut Paleti", diff --git a/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json index 2ff189e0b6..dff454ac71 100644 --- a/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json +++ b/i18n/trk/src/vs/workbench/services/configuration/common/configurationExtensionPoint.i18n.json @@ -8,6 +8,7 @@ ], "vscode.extension.contributes.configuration.title": "Ayarların bir özeti. Bu etiket ayar dosyasında ayırıcı yorum olarak kullanılacaktır.", "vscode.extension.contributes.configuration.properties": "Yapılandırma özelliklerinin açıklaması.", + "scope.application.description": "Sadece kullanıcı ayarlarında yapılandırılabilen, uygulamaya özel yapılandırma.", "scope.window.description": "Kullanıcı veya çalışma alanında yapılandırılabilen Windows'a özel yapılandırma.", "scope.resource.description": "Kullanıcı veya çalışma alanında yapılandırılabilen kaynağa özel yapılandırma.", "scope.description": "Yapılandırmanın uygulanabilir olduğu kapsam. Mevcut kapsamlar 'window' ve 'resource'tır.", diff --git a/i18n/trk/src/vs/workbench/services/configuration/node/configurationService.i18n.json b/i18n/trk/src/vs/workbench/services/configuration/node/configurationService.i18n.json new file mode 100644 index 0000000000..67d3a3db21 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/configuration/node/configurationService.i18n.json @@ -0,0 +1,10 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "unsupportedWindowSetting": "Bu ayar şu an uygulanamıyor. Ayar, bu klasörü açtığınızda uygulanacaktır." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json b/i18n/trk/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json new file mode 100644 index 0000000000..35229bd669 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.i18n.json @@ -0,0 +1,9 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ] +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json b/i18n/trk/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json new file mode 100644 index 0000000000..c8bec6ed14 --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/configurationResolver/node/variableResolver.i18n.json @@ -0,0 +1,16 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "missingEnvVarName": "Hiçbir ortam değişkeni adı belirtilmediği için '{0}' çözümlenemiyor.", + "configNotFound": "'{1}' ayarı bulunamadığı için '{0}' çözümlenemiyor.", + "configNoString": "'{1}' yapılandırılmış bir değer olduğu için '{0}' çözümlenemiyor.", + "missingConfigName": "Hiçbir ayar adı belirtilmediği için '{0}' çözümlenemiyor.", + "canNotFindFolder": "'{0}' çözümlenemiyor. '{1}' klasörü yok.", + "canNotResolveWorkspaceFolder": "'{0}' çözümlenemiyor. Lütfen bir klasör açın.", + "canNotResolveFile": "'{0}' çözümlenemiyor. Lütfen bir düzenleyici açın." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json b/i18n/trk/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json new file mode 100644 index 0000000000..c9b9ed878f --- /dev/null +++ b/i18n/trk/src/vs/workbench/services/dialogs/electron-browser/dialogService.i18n.json @@ -0,0 +1,11 @@ +{ + "": [ + "--------------------------------------------------------------------------------------------", + "Copyright (c) Microsoft Corporation. All rights reserved.", + "Licensed under the MIT License. See License.txt in the project root for license information.", + "--------------------------------------------------------------------------------------------", + "Do not edit this file. It is machine generated." + ], + "yesButton": "&&Evet", + "cancelButton": "İptal" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json b/i18n/trk/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json index 070421baf9..fe49bf93f4 100644 --- a/i18n/trk/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json +++ b/i18n/trk/src/vs/workbench/services/extensions/common/extensionsRegistry.i18n.json @@ -6,10 +6,12 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "vscode.extension.engines": "Motor uyumluluğu.", "vscode.extension.engines.vscode": "Eklentinin uyumlu olduğu VS Code sürümünü belirten VS Code eklentileri için. * olamaz. Örneğin: ^0.10.5 uyumlu olduğu minimum VS Code sürümünün 0.10.5 olduğunu gösterir.", "vscode.extension.publisher": "VS Code eklentisinin yayıncısı.", "vscode.extension.displayName": "VS Code galerisinde kullanılan eklentinin görünen adı.", "vscode.extension.categories": "Bu eklentiyi kategorize etmek için VS Code galerisi tarafından kullanılan kategoriler.", + "vscode.extension.category.languages.deprecated": "Bunun yerine 'Programlama Dilleri'ni kullan", "vscode.extension.galleryBanner": "VS Code markette kullanılan afiş.", "vscode.extension.galleryBanner.color": "VS Code marketteki sayfa başlığındaki afiş rengi.", "vscode.extension.galleryBanner.theme": "Afişte kullanılan yazı tipi için renk teması.", diff --git a/i18n/trk/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json b/i18n/trk/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json index 256ad2a9c6..e07436cbb8 100644 --- a/i18n/trk/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/extensions/electron-browser/extensionService.i18n.json @@ -6,9 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "extensionsDisabled": "Tüm eklentiler devre dışı.", "extensionHostProcess.crash": "Eklenti sunucusu beklenmeyen biçimde sonlandırıldı.", "extensionHostProcess.unresponsiveCrash": "Eklenti sunucusu yanıt vermediğinden sonlandırıldı.", - "devTools": "Geliştirici Araçları", + "devTools": "Geliştirici Araçlarını Aç", "restart": "Eklenti Sunucusunu Yeniden Başlat", "overwritingExtension": "{0} eklentisinin üzerine {1} yazılıyor.", "extensionUnderDevelopment": "{0} konumundaki geliştirme eklentisi yükleniyor", diff --git a/i18n/trk/src/vs/workbench/services/files/electron-browser/fileService.i18n.json b/i18n/trk/src/vs/workbench/services/files/electron-browser/fileService.i18n.json index 0d83f251a1..844478e063 100644 --- a/i18n/trk/src/vs/workbench/services/files/electron-browser/fileService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/files/electron-browser/fileService.i18n.json @@ -2,15 +2,28 @@ "": [ "--------------------------------------------------------------------------------------------", "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 MIT License. See License.txt in the project root for license information.", "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "netVersionError": "Microsoft .NET Framework 4.5 gerekli. Yüklemek için bağlantıyı izleyin.", "installNet": ".NET Framework 4.5'i İndir", "neverShowAgain": "Tekrar Gösterme", - "netVersionError": "Microsoft .NET Framework 4.5 gerekli. Yüklemek için bağlantıyı izleyin.", + "enospcError": "{0}, bu büyük çalışma alanındaki dosya değişikliklerini izleyemiyor. Bu sorunu çözmek için lütfen yönerge bağlantısını izleyin.", "learnMore": "Talimatlar", - "enospcError": "{0} için dosya işleçleri bitiyor. Bu sorunu çözmek için lütfen yönerge bağlantısını izleyin.", + "fileInvalidPath": "Geçersiz dosya kaynağı ({0})", + "fileIsDirectoryError": "Dosya bir dizindir", + "fileNotModifiedError": "Dosya şu tarihten beri değiştirilmemiş:", + "fileTooLargeForHeapError": "Bu büyüklükte bir dosyayı açmak için, VS Code'u yeniden başlatmanız ve daha fazla bellek kullanmasına izin vermeniz gerekir", + "fileTooLargeError": "Dosya, açmak için çok büyük", + "fileNotFoundError": "Dosya bulunamadı ({0})", + "fileBinaryError": "Dosya ikili olarak görünüyor ve metin olarak açılamıyor", + "filePermission": "Dosya için yazma izni reddedildi ({0})", + "fileExists": "Oluşturulacak dosya zaten mevcut ({0})", + "fileModifiedError": "Dosya Şu Tarihten Beri Değiştiriliyor", + "fileReadOnlyError": "Dosya Salt Okunur", + "fileMoveConflict": "Taşıma/kopyalama yapılamadı. Dosya, hedefte zaten mevcut.", + "unableToMoveCopyError": "Taşıma/kopyalama yapılamadı. Dosya, içinde bulunduğu klasörü değiştiriyor.", "binFailed": "'{0}' geri dönüşüm kutusuna taşınamadı", "trashFailed": "'{0}' çöpe taşınamadı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 7451690f9a..c973084e79 100644 --- a/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -6,7 +6,10 @@ "--------------------------------------------------------------------------------------------", "Do not edit this file. It is machine generated." ], + "fileNotFoundError": "Dosya bulunamadı ({0})", "fileIsDirectoryError": "Dosya bir dizindir", "fileNotModifiedError": "Dosya şu tarihten beri değiştirilmemiş:", - "fileBinaryError": "Dosya ikili olarak görünüyor ve metin olarak açılamıyor" + "fileBinaryError": "Dosya ikili olarak görünüyor ve metin olarak açılamıyor", + "err.create": "{0} dosyası oluşturulamadı", + "fileMoveConflict": "Taşıma/kopyalama yapılamadı. Dosya, hedefte zaten mevcut." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/progress/browser/progressService2.i18n.json b/i18n/trk/src/vs/workbench/services/progress/browser/progressService2.i18n.json index c0f80db1a1..4ed84d7e0c 100644 --- a/i18n/trk/src/vs/workbench/services/progress/browser/progressService2.i18n.json +++ b/i18n/trk/src/vs/workbench/services/progress/browser/progressService2.i18n.json @@ -7,5 +7,6 @@ "Do not edit this file. It is machine generated." ], "progress.subtitle": "{0} - {1}", - "progress.title": "{0}: {1}" + "progress.title": "{0}: {1}", + "cancel": "İptal" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json b/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json index e2c285e50c..a5a88e4099 100644 --- a/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json +++ b/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMGrammars.i18n.json @@ -10,6 +10,7 @@ "vscode.extension.contributes.grammars.language": "Bu söz diziminin ekleneceği dil tanımlayıcısı.", "vscode.extension.contributes.grammars.scopeName": "tmLanguage dosyası tarafından kullanılan Textmate kapsam adı.", "vscode.extension.contributes.grammars.path": "tmLanguage dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './syntaxes/' ile başlar.", - "vscode.extension.contributes.grammars.embeddedLanguages": "Bu dil bilgisinin gömülü dilleri içermesi durumundaki bir dil kimliğinin kapsam adı haritası.", + "vscode.extension.contributes.grammars.embeddedLanguages": "Bu dil bilgisinin gömülü dilleri içermesi durumundaki bir dil id'sinin kapsam adı haritası.", + "vscode.extension.contributes.grammars.tokenTypes": "Kapsam adından anahtar türüne kadar olan bir harita.", "vscode.extension.contributes.grammars.injectTo": "Bu dil bilgisinin yerleştirileceği dil kapsam adları listesi." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json b/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json index a5d49ddfe4..bbc6bb2224 100644 --- a/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json +++ b/i18n/trk/src/vs/workbench/services/textMate/electron-browser/TMSyntax.i18n.json @@ -11,6 +11,7 @@ "invalid.path.0": "`contributes.{0}.path` ögesinde dize bekleniyor. Sağlanan değer: {1}", "invalid.injectTo": "`contributes.{0}.injectTo` ögesinde geçersiz değer. Dil kapsam adlarından oluşan bir dizi olmalıdır. Sağlanan değer: {1}", "invalid.embeddedLanguages": "`contributes.{0}.embeddedLanguages` ögesinde geçersiz değer. Kapsam adından dile kadar olan bir nesne haritası olmalıdır. Sağlanan değer: {1}", + "invalid.tokenTypes": "`contributes.{0}.tokenTypes` ögesinde geçersiz değer. Kapsam adından anahtar türüne kadar olan bir nesne haritası olmalıdır. Sağlanan değer: {1}", "invalid.path.1": "`contributes.{0}.path` ögesinin ({1}) eklentinin klasöründe ({2}) yer alması bekleniyor. Bu, eklentiyi taşınamaz yapabilir.", "no-tm-grammar": "Bu dil için kayıtlı bir TM Grameri yok." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json b/i18n/trk/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json index 1ed6bdb35c..314fabbe4a 100644 --- a/i18n/trk/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json +++ b/i18n/trk/src/vs/workbench/services/themes/common/fileIconThemeSchema.i18n.json @@ -8,7 +8,7 @@ ], "schema.folderExpanded": "Genişletilmiş klasörler için klasör simgesi. Genişletilmiş klasör simgesi isteğe bağlıdır. Ayarlanmazsa, klasör için tanımlanan simge gösterilir.", "schema.folder": "Daraltılmış klasörler için klasör simgesi; eğer folderExpanded ayarlanmamışsa, genişletilen klasörler için de kullanılır.", - "schema.file": "Varsayılan dosya simgesi, bir uzantı, dosya adı veya dil kimliği ile eşleşmeyen tüm dosyalar için gösterilir.", + "schema.file": "Varsayılan dosya simgesi, bir uzantı, dosya adı veya dil id'si ile eşleşmeyen tüm dosyalar için gösterilir.", "schema.folderNames": "Klasör adlarını simgelerle ilişkilendirir. Nesne anahtarı, herhangi bir yol parçası içermeyen klasör adıdır. Örüntüler veya joker karakterlere izin verilmez. Klasör adı eşleştirme büyük/küçük harfe duyarlı değildir.", "schema.folderName": "İlişkilendirilecek simge tanımı ID'si.", "schema.folderNamesExpanded": "Klasör adlarını genişletilmiş klasör simgeleriyle ilişkilendirir. Nesne anahtarı, herhangi bir yol parçası içermeyen klasör adıdır. Örüntüler veya joker karakterlere izin verilmez. Klasör adı eşleştirme büyük/küçük harfe duyarlı değildir.", @@ -17,7 +17,7 @@ "schema.fileExtension": "İlişkilendirilecek simge tanımı ID'si.", "schema.fileNames": "Dosya adlarını simgelerle ilişkilendirir. Nesne anahtarı, herhangi bir yol parçası içermeyen tam dosya adıdır. Dosya adı noktalar ve olası bir dosya uzantısı içerebilir. Örüntüler veya joker karakterlere izin verilmez. Dosya adı eşleştirme büyük/küçük harfe duyarlı değildir.", "schema.fileName": "İlişkilendirilecek simge tanımı ID'si.", - "schema.languageIds": "Dilleri simgelerle ilişkilendirir. Nesne anahtarı, dil ekleme noktasında tanımlanan dil kimliğidir.", + "schema.languageIds": "Dilleri simgelerle ilişkilendirir. Nesne anahtarı, dil ekleme noktasında tanımlanan dil id'sidir.", "schema.languageId": "İlişkilendirilecek simge tanımı ID'si.", "schema.fonts": "Simge tanımlarında kullanılacak yazı tipleri.", "schema.id": "Yazı tipinin ID'si.", @@ -33,7 +33,7 @@ "schema.fontCharacter": "Glif yazı tipi kullanırken: Kullanılacak yazı tipindeki karakter.", "schema.fontColor": "Glif yazı tipi kullanırken: Kullanılacak renk.", "schema.fontSize": "Yazı tipi kullanırken: Metin yazı tipi yüzdesine göre yazı tipi boyutu. Ayarlanmazsa, yazı tipi tanımındaki boyut kullanılır.", - "schema.fontId": "Yazı tipi kullanırken: Yazı tipinin kimliği. Ayarlanmazsa, ilk yazı tipi tanımı varsayılan olarak kullanılır.", + "schema.fontId": "Yazı tipi kullanırken: Yazı tipinin id'si. Ayarlanmazsa, ilk yazı tipi tanımı varsayılan olarak kullanılır.", "schema.light": "Açık renk temalarındaki dosya simgeleri için isteğe bağlı ilişkilendirmeler.", "schema.highContrast": "Yüksek karşıtlık renk temalarındaki dosya simgeleri için isteğe bağlı ilişkilendirmeler.", "schema.hidesExplorerArrows": "Bu tema aktif olduğunda dosya gezgini ok işaretlerinin gizli olup olmayacağını yapılandırır." diff --git a/package.json b/package.json index fad96c278d..88d53a818d 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "7z": "7z", "update-grammars": "node build/npm/update-all-grammars.js", "update-localization-extension": "node build/npm/update-localization-extension.js", - "smoketest": "cd test/smoke && mocha" + "smoketest": "cd test/smoke && mocha", + "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit" }, "dependencies": { "@angular/animations": "~4.1.3", @@ -61,14 +62,15 @@ "semver": "4.3.6", "slickgrid": "github:anthonydresser/SlickGrid#2.3.17", "spdlog": "0.6.0", - "svg.js": "^2.2.5", "sudo-prompt": "^8.0.0", + "svg.js": "^2.2.5", "v8-inspect-profiler": "^0.0.7", "vscode-chokidar": "1.6.2", - "vscode-debugprotocol": "1.27.0", - "vscode-ripgrep": "0.7.1-patch.0.1", - "vscode-textmate": "^3.2.0", - "vscode-xterm": "3.2.0-beta7", + "vscode-debugprotocol": "1.28.0", + "vscode-nsfw": "1.0.17", + "vscode-ripgrep": "^0.8.1", + "vscode-textmate": "^3.3.3", + "vscode-xterm": "3.4.0-beta3", "winreg": "1.2.0", "yauzl": "2.8.0", "zone.js": "^0.8.4" @@ -93,10 +95,9 @@ "eslint": "^3.4.0", "event-stream": "^3.1.7", "express": "^4.13.1", - "flatpak-bundler": "^0.1.1", "glob": "^5.0.13", "gulp": "^3.9.1", - "gulp-atom-electron": "1.15.1", + "gulp-atom-electron": "^1.16.1", "gulp-azure-storage": "^0.7.0", "gulp-bom": "^1.0.0", "gulp-buffer": "0.0.2", @@ -109,6 +110,7 @@ "gulp-image-resize": "^0.10.0", "gulp-json-editor": "^2.2.1", "gulp-mocha": "^2.1.3", + "gulp-plumber": "^1.2.0", "gulp-remote-src": "^0.4.0", "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.4", @@ -141,8 +143,8 @@ "source-map": "^0.4.4", "tslint": "^5.9.1", "typemoq": "^0.3.2", - "typescript": "2.6.1", - "typescript-formatter": "4.0.1", + "typescript": "2.8.1", + "typescript-formatter": "7.1.0", "uglify-es": "^3.0.18", "underscore": "^1.8.3", "vinyl": "^0.4.5", @@ -160,6 +162,6 @@ "optionalDependencies": { "windows-foreground-love": "0.1.0", "windows-mutex": "^0.2.0", - "windows-process-tree": "0.1.6" + "windows-process-tree": "0.2.2" } } diff --git a/resources/linux/code.desktop b/resources/linux/code.desktop index 005f850f11..b877a6061c 100644 --- a/resources/linux/code.desktop +++ b/resources/linux/code.desktop @@ -15,4 +15,4 @@ Keywords=sqlops; [Desktop Action new-empty-window] Name=New Empty Window Exec=/usr/share/@@NAME@@/@@NAME@@ --new-window %F -Icon=@@NAME@@ +Icon=@@ICON@@ diff --git a/scripts/env.ps1 b/scripts/env.ps1 index 4f2d411c5c..72e094d0a6 100644 --- a/scripts/env.ps1 +++ b/scripts/env.ps1 @@ -1,3 +1,3 @@ $env:npm_config_disturl="https://atom.io/download/electron" -$env:npm_config_target=(node "build/lib/electron.js") -$env:npm_config_runtime="electron" \ No newline at end of file +$env:npm_config_target=(node -p "require('./build/lib/electron').getElectronVersion();") +$env:npm_config_runtime="electron" diff --git a/scripts/env.sh b/scripts/env.sh index aa4acdf94e..8f641759b2 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -1,6 +1,6 @@ #!/bin/bash export npm_config_disturl=https://atom.io/download/electron -export npm_config_target=$(node "build/lib/electron.js") +export npm_config_target=$(node -p "require('./build/lib/electron').getElectronVersion();") export npm_config_runtime=electron export npm_config_cache="$HOME/.npm-electron" -mkdir -p "$npm_config_cache" \ No newline at end of file +mkdir -p "$npm_config_cache" diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index f62b80f5f7..11bddffa8d 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -11,13 +11,17 @@ set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5% :: Tests in the extension host call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% -call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + +call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% . +if %errorlevel% neq 0 exit /b %errorlevel% :: Integration & performance tests in AMD call .\scripts\test.bat --runGlob **\*.integrationTest.js %* -:: Tests in commonJS (language servers tests...) -call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\html\server\out\test\ +# Tests in commonJS (HTML, CSS, JSON language server tests...) +call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\*\server\out\test\**\*.test.js +if %errorlevel% neq 0 exit /b %errorlevel% rmdir /s /q %VSCODEUSERDATADIR% diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index 6159dc88aa..070c972cb4 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -15,12 +15,14 @@ cd $ROOT # Tests in the extension host ./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started ./scripts/code.sh $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started -./scripts/code.sh $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started +mkdir $ROOT/extensions/emmet/test-fixtures +./scripts/code.sh $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started . +rm -r $ROOT/extensions/emmet/test-fixtures # Integration tests in AMD ./scripts/test.sh --runGlob **/*.integrationTest.js "$@" -# Tests in commonJS (language server tests...) -./scripts/node-electron.sh ./node_modules/mocha/bin/_mocha ./extensions/html/server/out/test/ +# Tests in commonJS (HTML, CSS, JSON language server tests...) +./scripts/node-electron.sh ./node_modules/mocha/bin/_mocha ./extensions/*/server/out/test/ rm -r $VSCODEUSERDATADIR diff --git a/scripts/test.sh b/scripts/test.sh index e7c9ad1997..8e3d3d9046 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -26,6 +26,7 @@ node build/lib/electron.js || ./node_modules/.bin/gulp electron # Unit Tests export ELECTRON_ENABLE_LOGGING=1 +export ELECTRON_RUN_AS_NODE=1 if [[ "$OSTYPE" == "darwin"* ]]; then cd $ROOT ; ulimit -n 4096 ; \ "$CODE" \ diff --git a/src/bootstrap-amd.js b/src/bootstrap-amd.js index 1edd620fd0..193b752e42 100644 --- a/src/bootstrap-amd.js +++ b/src/bootstrap-amd.js @@ -18,8 +18,8 @@ function uriFromPath(_path) { } function readFile(file) { - return new Promise(function(resolve, reject) { - fs.readFile(file, 'utf8', function(err, data) { + return new Promise(function (resolve, reject) { + fs.readFile(file, 'utf8', function (err, data) { if (err) { reject(err); return; @@ -35,7 +35,7 @@ var nlsConfig = rawNlsConfig ? JSON.parse(rawNlsConfig) : { availableLanguages: // We have a special location of the nls files. They come from a language pack if (nlsConfig._resolvedLanguagePackCoreLocation) { let bundles = Object.create(null); - nlsConfig.loadBundle = function(bundle, language, cb) { + nlsConfig.loadBundle = function (bundle, language, cb) { let result = bundles[bundle]; if (result) { cb(undefined, result); @@ -47,7 +47,7 @@ if (nlsConfig._resolvedLanguagePackCoreLocation) { bundles[bundle] = json; cb(undefined, json); }) - .catch(cb); + .catch(cb); }; } @@ -66,10 +66,13 @@ if (nlsConfig.pseudo) { }); } -exports.bootstrap = function (entrypoint) { +exports.bootstrap = function (entrypoint, onLoad, onError) { if (!entrypoint) { return; } - loader([entrypoint], function () { }, function (err) { console.error(err); }); + onLoad = onLoad || function () { }; + onError = onError || function (err) { console.error(err); }; + + loader([entrypoint], onLoad, onError); }; diff --git a/src/bootstrap.js b/src/bootstrap.js index f47c478d28..e89f83b102 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -11,10 +11,10 @@ const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); diff --git a/src/cli.js b/src/cli.js index 274c677d7e..4adcbe0a7e 100644 --- a/src/cli.js +++ b/src/cli.js @@ -11,10 +11,10 @@ const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); diff --git a/src/main.js b/src/main.js index 1b6f31b3d5..c16a4bde95 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,8 @@ perf.mark('main:started'); // Perf measurements global.perfStartTime = Date.now(); +Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) + //#region Add support for using node_modules.asar (function () { const path = require('path'); @@ -18,10 +20,10 @@ global.perfStartTime = Date.now(); const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); @@ -278,111 +280,112 @@ function getNLSConfiguration(locale) { return undefined; } - let isCoreLangaguage = true; - if (locale) { - isCoreLangaguage = ['de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-cn', 'zh-tw'].some((language) => { - return locale === language || locale.startsWith(language + '-'); - }); - } - - if (isCoreLangaguage) { - return Promise.resolve(resolveLocale(locale)); - } else { - perf.mark('nlsGeneration:start'); - let defaultResult = function() { + perf.mark('nlsGeneration:start'); + let defaultResult = function(locale) { + let isCoreLanguage = true; + if (locale) { + isCoreLanguage = ['de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-cn', 'zh-tw'].some((language) => { + return locale === language || locale.startsWith(language + '-'); + }); + } + if (isCoreLanguage) { + let result = resolveLocale(locale); + perf.mark('nlsGeneration:end'); + return Promise.resolve(result); + } else { perf.mark('nlsGeneration:end'); return Promise.resolve({ locale: locale, availableLanguages: {} }); - }; - try { - let commit = getCommit(); - if (!commit) { - return defaultResult(); + } + }; + try { + let commit = getCommit(); + if (!commit) { + return defaultResult(locale); + } + let configs = getLanguagePackConfigurations(); + if (!configs) { + return defaultResult(locale); + } + let initialLocale = locale; + locale = resolveLanguagePackLocale(configs, locale); + if (!locale) { + return defaultResult(initialLocale); + } + let packConfig = configs[locale]; + let mainPack; + if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') { + return defaultResult(locale); + } + return exists(mainPack).then((fileExists) => { + if (!fileExists) { + return defaultResult(locale); } - let configs = getLanguagePackConfigurations(); - if (!configs) { - return defaultResult(); - } - let initialLocale = locale; - locale = resolveLanguagePackLocale(configs, locale); - if (!locale) { - return defaultResult(); - } - let packConfig = configs[locale]; - let mainPack; - if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') { - return defaultResult(); - } - return exists(mainPack).then((fileExists) => { - if (!fileExists) { - return defaultResult(); + let packId = packConfig.hash + '.' + locale; + let cacheRoot = path.join(userData, 'clp', packId); + let coreLocation = path.join(cacheRoot, commit); + let translationsConfigFile = path.join(cacheRoot, 'tcf.json'); + let result = { + locale: initialLocale, + availableLanguages: { '*': locale }, + _languagePackId: packId, + _translationsConfigFile: translationsConfigFile, + _cacheRoot: cacheRoot, + _resolvedLanguagePackCoreLocation: coreLocation + }; + return exists(coreLocation).then((fileExists) => { + if (fileExists) { + // We don't wait for this. No big harm if we can't touch + touch(coreLocation).catch(() => {}); + perf.mark('nlsGeneration:end'); + return result; } - let packId = packConfig.hash + '.' + locale; - let cacheRoot = path.join(userData, 'clp', packId); - let coreLocation = path.join(cacheRoot, commit); - let translationsConfigFile = path.join(cacheRoot, 'tcf.json'); - let result = { - locale: initialLocale, - availableLanguages: { '*': locale }, - _languagePackId: packId, - _translationsConfigFile: translationsConfigFile, - _cacheRoot: cacheRoot, - _resolvedLanguagePackCoreLocation: coreLocation - }; - return exists(coreLocation).then((fileExists) => { - if (fileExists) { - // We don't wait for this. No big harm if we can't touch - touch(coreLocation).catch(() => {}); - perf.mark('nlsGeneration:end'); - return result; - } - return mkdirp(coreLocation).then(() => { - return Promise.all([readFile(path.join(__dirname, 'nls.metadata.json')), readFile(mainPack)]); - }).then((values) => { - let metadata = JSON.parse(values[0]); - let packData = JSON.parse(values[1]).contents; - let bundles = Object.keys(metadata.bundles); - let writes = []; - for (let bundle of bundles) { - let modules = metadata.bundles[bundle]; - let target = Object.create(null); - for (let module of modules) { - let keys = metadata.keys[module]; - let defaultMessages = metadata.messages[module]; - let translations = packData[module]; - let targetStrings; - if (translations) { - targetStrings = []; - for (let i = 0; i < keys.length; i++) { - let elem = keys[i]; - let key = typeof elem === 'string' ? elem : elem.key; - let translatedMessage = translations[key]; - if (translatedMessage === undefined) { - translatedMessage = defaultMessages[i]; - } - targetStrings.push(translatedMessage); + return mkdirp(coreLocation).then(() => { + return Promise.all([readFile(path.join(__dirname, 'nls.metadata.json')), readFile(mainPack)]); + }).then((values) => { + let metadata = JSON.parse(values[0]); + let packData = JSON.parse(values[1]).contents; + let bundles = Object.keys(metadata.bundles); + let writes = []; + for (let bundle of bundles) { + let modules = metadata.bundles[bundle]; + let target = Object.create(null); + for (let module of modules) { + let keys = metadata.keys[module]; + let defaultMessages = metadata.messages[module]; + let translations = packData[module]; + let targetStrings; + if (translations) { + targetStrings = []; + for (let i = 0; i < keys.length; i++) { + let elem = keys[i]; + let key = typeof elem === 'string' ? elem : elem.key; + let translatedMessage = translations[key]; + if (translatedMessage === undefined) { + translatedMessage = defaultMessages[i]; } - } else { - targetStrings = defaultMessages; + targetStrings.push(translatedMessage); } - target[module] = targetStrings; + } else { + targetStrings = defaultMessages; } - writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g,'!') + '.nls.json'), JSON.stringify(target))); + target[module] = targetStrings; } - writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations))); - return Promise.all(writes); - }).then(() => { - perf.mark('nlsGeneration:end'); - return result; - }).catch((err) => { - console.error('Generating translation files failed.', err); - return defaultResult(); - }); + writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target))); + } + writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations))); + return Promise.all(writes); + }).then(() => { + perf.mark('nlsGeneration:end'); + return result; + }).catch((err) => { + console.error('Generating translation files failed.', err); + return defaultResult(locale); }); }); - } catch (err) { - console.error('Generating translation files failed.', err); - return defaultResult(); - } + }); + } catch (err) { + console.error('Generating translation files failed.', err); + return defaultResult(locale); } } @@ -446,7 +449,6 @@ global.getOpenUrls = function () { return openUrls; }; - // use '<UserData>/CachedData'-directory to store // node/v8 cached data. let nodeCachedDataDir = getNodeCachedDataDir().then(function (value) { diff --git a/src/sql/base/browser/ui/checkbox/checkbox.ts b/src/sql/base/browser/ui/checkbox/checkbox.ts index 4403c395ce..cba070a280 100644 --- a/src/sql/base/browser/ui/checkbox/checkbox.ts +++ b/src/sql/base/browser/ui/checkbox/checkbox.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Widget } from 'vs/base/browser/ui/widget'; diff --git a/src/sql/base/browser/ui/dropdownList/dropdownList.ts b/src/sql/base/browser/ui/dropdownList/dropdownList.ts index c547e79bf2..92938bea70 100644 --- a/src/sql/base/browser/ui/dropdownList/dropdownList.ts +++ b/src/sql/base/browser/ui/dropdownList/dropdownList.ts @@ -15,6 +15,7 @@ import { EventType as GestureEventType } from 'vs/base/browser/touch'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; +import { Builder } from 'vs/base/browser/builder'; import { Button } from 'sql/base/browser/ui/button/button'; import { attachButtonStyler } from 'sql/common/theme/styler'; @@ -58,9 +59,9 @@ export class DropdownList extends Dropdown { attachButtonStyler(button, this._themeService); } - DOM.append(this.element.getHTMLElement(), DOM.$('div.dropdown-icon')); + DOM.append(this.element, DOM.$('div.dropdown-icon')); - this.toDispose.push(this.element.on([DOM.EventType.CLICK, DOM.EventType.MOUSE_DOWN, GestureEventType.Tap], (e: Event) => { + this.toDispose.push(new Builder(this.element).on([DOM.EventType.CLICK, DOM.EventType.MOUSE_DOWN, GestureEventType.Tap], (e: Event) => { DOM.EventHelper.stop(e, true); // prevent default click behaviour to trigger }).on([DOM.EventType.MOUSE_DOWN, GestureEventType.Tap], (e: Event) => { // We want to show the context menu on dropdown so that as a user you can press and hold the @@ -82,11 +83,11 @@ export class DropdownList extends Dropdown { this.toDispose.push(this._list.onSelectionChange(() => { // focus on the dropdown label then hide the dropdown list - this.element.getHTMLElement().focus(); + this.element.focus(); this.hide(); })); - this.element.getHTMLElement().setAttribute('tabindex', '0'); + this.element.setAttribute('tabindex', '0'); } /** @@ -94,7 +95,7 @@ export class DropdownList extends Dropdown { */ protected renderContents(container: HTMLElement): IDisposable { let div = DOM.append(container, this._contentContainer); - div.style.width = DOM.getTotalWidth(this.element.getHTMLElement()) + 'px'; + div.style.width = DOM.getTotalWidth(this.element) + 'px'; return null; } @@ -103,22 +104,22 @@ export class DropdownList extends Dropdown { */ public renderLabel(): void { if (this._options.labelRenderer) { - this._options.labelRenderer(this.label.getHTMLElement()); + this._options.labelRenderer(this.label); } } protected onEvent(e: Event, activeElement: HTMLElement): void { // If there is an event outside dropdown label and dropdown list, hide the dropdown list - if (!DOM.isAncestor(<HTMLElement>e.target, this.element.getHTMLElement()) && !DOM.isAncestor(<HTMLElement>e.target, this._contentContainer)) { + if (!DOM.isAncestor(<HTMLElement>e.target, this.element) && !DOM.isAncestor(<HTMLElement>e.target, this._contentContainer)) { // focus on the dropdown label then hide the dropdown list - this.element.getHTMLElement().focus(); + this.element.focus(); this.hide(); // If there is an keyboard event inside the list and key code is escape, hide the dropdown list } else if (DOM.isAncestor(<HTMLElement>e.target, this._list.getHTMLElement()) && e instanceof KeyboardEvent) { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Escape)) { // focus on the dropdown label then hide the dropdown list - this.element.getHTMLElement().focus(); + this.element.focus(); this.hide(); e.stopPropagation(); } @@ -138,7 +139,7 @@ export class DropdownList extends Dropdown { const border = this.borderColor ? this.borderColor.toString() : null; this.applyStylesOnElement(this._contentContainer, background, foreground, border); if (this.label) { - this.applyStylesOnElement(this.element.getHTMLElement(), background, foreground, border); + this.applyStylesOnElement(this.element, background, foreground, border); } } diff --git a/src/sql/base/browser/ui/dropdownList/media/dropdownList.css b/src/sql/base/browser/ui/dropdownList/media/dropdownList.css index e1b4c44eb8..5029721487 100644 --- a/src/sql/base/browser/ui/dropdownList/media/dropdownList.css +++ b/src/sql/base/browser/ui/dropdownList/media/dropdownList.css @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.dropdown { +.monaco-dropdown { width: 100%; /* TODO: Determine a more permanent fix; vs/dropdown is overwriting this selector in packaged builds */ display: flex !important; @@ -11,15 +11,15 @@ cursor: pointer; } -.dropdown > .dropdown-label { +.monaco-dropdown > .dropdown-label { width: 100%; } -.dropdown > .dropdown-label:not(:empty) { +.monaco-dropdown > .dropdown-label:not(:empty) { padding: 0px; } -.dropdown > .dropdown-icon { +.monaco-dropdown > .dropdown-icon { flex: 0 0 15px; height: 10px; width: 10px; @@ -28,7 +28,7 @@ padding-right: 10px; } -.vs-dark .dropdown > .dropdown-icon, -.hc-black .dropdown > .dropdown-icon { +.vs-dark .monaco-dropdown > .dropdown-icon, +.hc-black .monaco-dropdown > .dropdown-icon { content: url("dropdownarrow_inverse.svg"); } \ No newline at end of file diff --git a/src/sql/base/browser/ui/editableDropdown/dropdown.ts b/src/sql/base/browser/ui/editableDropdown/dropdown.ts index 37a89184dc..2c26e9db5d 100644 --- a/src/sql/base/browser/ui/editableDropdown/dropdown.ts +++ b/src/sql/base/browser/ui/editableDropdown/dropdown.ts @@ -19,7 +19,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Disposable } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import * as nls from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; @@ -110,14 +110,14 @@ export class Dropdown extends Disposable { super(); this._contextView = new ContextView(document.body); this._options = mixin(opt, defaults, false) as IDropdownOptions; - this.$el = $('.dropdown').style('width', '100%').appendTo(container); + this.$el = $('.monaco-dropdown').style('width', '100%').appendTo(container); this.$input = $('.dropdown-input').style('width', '100%').appendTo(this.$el); this.$treeContainer = $('.dropdown-tree'); this._toggleAction = new ToggleDropdownAction(() => { this._showList(); - this._tree.DOMFocus(); + this._tree.domFocus(); this._tree.focusFirst(); }); @@ -168,7 +168,7 @@ export class Dropdown extends Disposable { if (!this.$treeContainer.getHTMLElement().parentElement) { this._showList(); } - this._tree.DOMFocus(); + this._tree.domFocus(); this._tree.focusFirst(); e.stopPropagation(); e.preventDefault(); @@ -195,17 +195,7 @@ export class Dropdown extends Disposable { this._input.onDidChange(e => { if (this._dataSource.options) { this._filter.filterString = e; - let filteredLength = this._dataSource.options.reduce((p, i) => { - if (this._filter.isVisible(undefined, i)) { - return p + 1; - } else { - return p; - } - }, 0); - let height = filteredLength * this._renderer.getHeight(undefined, undefined) > this._options.maxHeight ? this._options.maxHeight : filteredLength * this._renderer.getHeight(undefined, undefined); - this.$treeContainer.style('height', height + 'px').style('width', DOM.getContentWidth(this.$input.getHTMLElement()) - 2 + 'px'); - this._tree.layout(parseInt(this.$treeContainer.style('height'))); - this._tree.refresh(); + this._layoutTree(); } }); @@ -221,11 +211,12 @@ export class Dropdown extends Disposable { private _showList(): void { if (this._input.isEnabled) { this._onFocus.fire(); + this._filter.filterString = ''; this._contextView.show({ getAnchor: () => this.$input.getHTMLElement(), render: container => { this.$treeContainer.appendTo(container); - this._tree.layout(parseInt(this.$treeContainer.style('height'))); + this._layoutTree(); return { dispose: () => { } }; }, onDOMEvent: (e, activeElement) => { @@ -239,6 +230,20 @@ export class Dropdown extends Disposable { } } + private _layoutTree(): void { + let filteredLength = this._dataSource.options.reduce((p, i) => { + if (this._filter.isVisible(undefined, i)) { + return p + 1; + } else { + return p; + } + }, 0); + let height = filteredLength * this._renderer.getHeight(undefined, undefined) > this._options.maxHeight ? this._options.maxHeight : filteredLength * this._renderer.getHeight(undefined, undefined); + this.$treeContainer.style('height', height + 'px').style('width', DOM.getContentWidth(this.$input.getHTMLElement()) - 2 + 'px'); + this._tree.layout(parseInt(this.$treeContainer.style('height'))); + this._tree.refresh(); + } + public set values(vals: string[]) { if (vals) { this._filter.filterString = ''; diff --git a/src/sql/base/browser/ui/editableDropdown/dropdownTree.ts b/src/sql/base/browser/ui/editableDropdown/dropdownTree.ts index a0ddc0c12a..390a9ecd85 100644 --- a/src/sql/base/browser/ui/editableDropdown/dropdownTree.ts +++ b/src/sql/base/browser/ui/editableDropdown/dropdownTree.ts @@ -9,7 +9,7 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base'; import { generateUuid } from 'vs/base/common/uuid'; import * as DOM from 'vs/base/browser/dom'; import { $ } from 'vs/base/browser/builder'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; export interface Template { diff --git a/src/sql/base/browser/ui/editableDropdown/media/dropdownList.css b/src/sql/base/browser/ui/editableDropdown/media/dropdownList.css index 157ea38c2c..42c423744d 100644 --- a/src/sql/base/browser/ui/editableDropdown/media/dropdownList.css +++ b/src/sql/base/browser/ui/editableDropdown/media/dropdownList.css @@ -12,13 +12,13 @@ background-image: url("dropdownarrow_inverse.svg"); } -.dropdown .monaco-action-bar .action-label.icon.dropdown-arrow { +.monaco-dropdown .monaco-action-bar .action-label.icon.dropdown-arrow { padding: 0; background-size: 10px; background-position: 50%; } -.dropdown .monaco-action-bar .action-item { +.monaco-dropdown .monaco-action-bar .action-item { margin: 0; } @@ -38,7 +38,7 @@ overflow: hidden; } -.connection-input .dropdown .monaco-action-bar .action-label.icon.dropdown-arrow { +.connection-input .monaco-dropdown .monaco-action-bar .action-label.icon.dropdown-arrow { background-position: 50%; background-size: cover; } diff --git a/src/sql/base/browser/ui/inputBox/inputBox.ts b/src/sql/base/browser/ui/inputBox/inputBox.ts index 74c1cbac1c..e13df70934 100644 --- a/src/sql/base/browser/ui/inputBox/inputBox.ts +++ b/src/sql/base/browser/ui/inputBox/inputBox.ts @@ -7,7 +7,7 @@ import { InputBox as vsInputBox, IInputOptions, IInputBoxStyles as vsIInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { Color } from 'vs/base/common/color'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface OnLoseFocusParams { value: string; diff --git a/src/sql/base/browser/ui/listBox/listBox.ts b/src/sql/base/browser/ui/listBox/listBox.ts index 7ff4c25a86..223e5204df 100644 --- a/src/sql/base/browser/ui/listBox/listBox.ts +++ b/src/sql/base/browser/ui/listBox/listBox.ts @@ -144,13 +144,11 @@ export class ListBox extends SelectBox { for (let i = 0; i < indexes.length; i++) { this.selectElement.remove(indexes[i]); - this.options.splice(indexes[i], 1); } } public add(option: string): void { this.selectElement.add(this.createOption(option)); - this.options.push(option); } // Allow copy to clipboard diff --git a/src/sql/base/browser/ui/modal/media/modal.css b/src/sql/base/browser/ui/modal/media/modal.css index 50031183db..90b1a2d131 100644 --- a/src/sql/base/browser/ui/modal/media/modal.css +++ b/src/sql/base/browser/ui/modal/media/modal.css @@ -119,7 +119,8 @@ color: #3C3C3C; } -.modal .select-box { +.modal .select-box, +.modal .monaco-select-box { width: 100%; height: 25px; color: #6C6C6C; diff --git a/src/sql/base/browser/ui/modal/modal.ts b/src/sql/base/browser/ui/modal/modal.ts index 81f0671b49..c5bc51a7fa 100644 --- a/src/sql/base/browser/ui/modal/modal.ts +++ b/src/sql/base/browser/ui/modal/modal.ts @@ -11,7 +11,7 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { mixin } from 'vs/base/common/objects'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { Builder, $, withElementById } from 'vs/base/browser/builder'; +import { Builder, $ } from 'vs/base/browser/builder'; import * as DOM from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { generateUuid } from 'vs/base/common/uuid'; @@ -285,7 +285,7 @@ export abstract class Modal extends Disposable implements IThemable { */ protected show() { this._modalShowingContext.get().push(this._staticKey); - this._builder.appendTo(withElementById(this._partService.getWorkbenchElementId()).getHTMLElement().parentElement); + this._builder.appendTo(document.getElementById(this._partService.getWorkbenchElementId()).parentElement); this.setFocusableElements(); diff --git a/src/sql/base/browser/ui/modal/optionsDialog.ts b/src/sql/base/browser/ui/modal/optionsDialog.ts index 0e811206f5..27f7a23deb 100644 --- a/src/sql/base/browser/ui/modal/optionsDialog.ts +++ b/src/sql/base/browser/ui/modal/optionsDialog.ts @@ -16,7 +16,7 @@ import { attachButtonStyler, attachModalDialogStyler } from 'sql/common/theme/st import * as sqlops from 'sqlops'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/sql/base/browser/ui/modal/optionsDialogHelper.ts b/src/sql/base/browser/ui/modal/optionsDialogHelper.ts index 55cb7fb46c..aeb60d6af5 100644 --- a/src/sql/base/browser/ui/modal/optionsDialogHelper.ts +++ b/src/sql/base/browser/ui/modal/optionsDialogHelper.ts @@ -25,7 +25,7 @@ export interface IOptionElement { export function createOptionElement(option: sqlops.ServiceOption, rowContainer: Builder, options: { [name: string]: any }, optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): void { let possibleInputs: string[] = []; - let optionValue = this.getOptionValueAndCategoryValues(option, options, possibleInputs); + let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs); let optionWidget: any; let inputElement: HTMLElement; let missingErrorMessage = localize('optionsDialog.missingRequireField', ' is required.'); @@ -47,11 +47,11 @@ export function createOptionElement(option: sqlops.ServiceOption, rowContainer: ariaLabel: option.displayName }); optionWidget.value = optionValue; - inputElement = this.findElement(rowContainer, 'input'); + inputElement = findElement(rowContainer, 'input'); } else if (option.valueType === ServiceOptionType.category || option.valueType === ServiceOptionType.boolean) { optionWidget = new SelectBox(possibleInputs, optionValue.toString(), contextViewService); DialogHelper.appendInputSelectBox(rowContainer, optionWidget); - inputElement = this.findElement(rowContainer, 'select-box'); + inputElement = findElement(rowContainer, 'monaco-select-box'); } else if (option.valueType === ServiceOptionType.string || option.valueType === ServiceOptionType.password) { optionWidget = new InputBox(rowContainer.getHTMLElement(), contextViewService, { validationOptions: { @@ -63,7 +63,7 @@ export function createOptionElement(option: sqlops.ServiceOption, rowContainer: if (option.valueType === ServiceOptionType.password) { optionWidget.inputElement.type = 'password'; } - inputElement = this.findElement(rowContainer, 'input'); + inputElement = findElement(rowContainer, 'input'); } optionsMap[option.name] = { optionWidget: optionWidget, option: option, optionValue: optionValue }; inputElement.onfocus = () => onFocus(option.name); @@ -74,10 +74,10 @@ export function getOptionValueAndCategoryValues(option: sqlops.ServiceOption, op if (options[option.name]) { // if the value type is boolean, the option value can be either boolean or string if (option.valueType === ServiceOptionType.boolean) { - if (options[option.name] === true || options[option.name] === this.trueInputValue) { - optionValue = this.trueInputValue; + if (options[option.name] === true || options[option.name] === trueInputValue) { + optionValue = trueInputValue; } else { - optionValue = this.falseInputValue; + optionValue = falseInputValue; } } else { optionValue = options[option.name]; @@ -91,7 +91,7 @@ export function getOptionValueAndCategoryValues(option: sqlops.ServiceOption, op } if (option.valueType === ServiceOptionType.boolean) { - possibleInputs.push(this.trueInputValue, this.falseInputValue); + possibleInputs.push(trueInputValue, falseInputValue); } else { option.categoryValues.map(c => possibleInputs.push(c.name)); } @@ -136,7 +136,7 @@ export function updateOptions(options: { [optionName: string]: any }, optionsMap } if (optionElement.optionWidget.value) { if (optionElement.option.valueType === ServiceOptionType.boolean) { - options[optionName] = (optionElement.optionWidget.value === this.trueInputValue) ? true : false; + options[optionName] = (optionElement.optionWidget.value === trueInputValue) ? true : false; } else { options[optionName] = optionElement.optionWidget.value; } diff --git a/src/sql/base/browser/ui/modal/webViewDialog.ts b/src/sql/base/browser/ui/modal/webViewDialog.ts index d3d474057b..bc9d854074 100644 --- a/src/sql/base/browser/ui/modal/webViewDialog.ts +++ b/src/sql/base/browser/ui/modal/webViewDialog.ts @@ -13,15 +13,15 @@ import { attachButtonStyler, attachModalDialogStyler } from 'sql/common/theme/st import { Builder } from 'vs/base/browser/builder'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { localize } from 'vs/nls'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; export class WebViewDialog extends Modal { @@ -29,7 +29,7 @@ export class WebViewDialog extends Modal { private _okButton: Button; private _okLabel: string; private _closeLabel: string; - private _webview: Webview; + private _webview: WebviewElement; private _html: string; private _headerTitle: string; @@ -89,8 +89,7 @@ export class WebViewDialog extends Modal { protected renderBody(container: HTMLElement) { new Builder(container).div({ 'class': 'webview-dialog' }, (bodyBuilder) => { this._body = bodyBuilder.getHTMLElement(); - this._webview = new Webview( - this._body, + this._webview = new WebviewElement( this._webViewPartService.getContainer(Parts.EDITOR_PART), this._themeService, this._environmentService, @@ -102,6 +101,7 @@ export class WebViewDialog extends Modal { enableWrappedPostMessage: true } ); + this._webview.mountTo(this._body); this._webview.style(this._themeService.getTheme()); diff --git a/src/sql/base/browser/ui/panel/panel.ts b/src/sql/base/browser/ui/panel/panel.ts index b4b858adb4..94f3339c4c 100644 --- a/src/sql/base/browser/ui/panel/panel.ts +++ b/src/sql/base/browser/ui/panel/panel.ts @@ -5,8 +5,9 @@ import { IThemable } from 'vs/platform/theme/common/styler'; import * as objects from 'sql/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Dimension, $, Builder } from 'vs/base/browser/builder'; +import { Event, Emitter } from 'vs/base/common/event'; +import { Dimension } from 'vs/base/browser/dom'; +import { $, Builder } from 'vs/base/browser/builder'; import { EventType } from 'vs/base/browser/dom'; import { IAction } from 'vs/base/common/actions'; import { IActionOptions, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -62,7 +63,7 @@ export class TabbedPanel extends Disposable implements IThemable { this.$tabList.style('height', this.headersize + 'px'); this.$header.append(this.$tabList); let actionbarcontainer = $('.title-actions'); - this._actionbar = new ActionBar(actionbarcontainer); + this._actionbar = new ActionBar(actionbarcontainer.getHTMLElement()); this.$header.append(actionbarcontainer); this.$parent.append(this.$header); this.$body = $('tabBody'); diff --git a/src/sql/base/browser/ui/radioButton/radioButton.ts b/src/sql/base/browser/ui/radioButton/radioButton.ts index 3324f0b620..5a436581ae 100644 --- a/src/sql/base/browser/ui/radioButton/radioButton.ts +++ b/src/sql/base/browser/ui/radioButton/radioButton.ts @@ -8,7 +8,7 @@ import * as DOM from 'vs/base/browser/dom'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { Color } from 'vs/base/common/color'; import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Widget } from 'vs/base/browser/ui/widget'; export interface IRadioButtonOptions { diff --git a/src/sql/base/browser/ui/splitview/splitview.ts b/src/sql/base/browser/ui/splitview/splitview.ts index 1f3fa3ad24..169f0115ae 100644 --- a/src/sql/base/browser/ui/splitview/splitview.ts +++ b/src/sql/base/browser/ui/splitview/splitview.ts @@ -14,7 +14,7 @@ import numbers = require('vs/base/common/numbers'); import sash = require('vs/base/browser/ui/sash/sash'); import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Color } from 'vs/base/common/color'; export enum Orientation { diff --git a/src/sql/base/browser/ui/table/table.ts b/src/sql/base/browser/ui/table/table.ts index ba7d399d89..0150c887d1 100644 --- a/src/sql/base/browser/ui/table/table.ts +++ b/src/sql/base/browser/ui/table/table.ts @@ -12,7 +12,6 @@ import * as DOM from 'vs/base/browser/dom'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { Dimension } from 'vs/base/browser/builder'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { Widget } from 'vs/base/browser/ui/widget'; @@ -136,7 +135,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl onSelectedRowsChanged(fn: any): IDisposable { this._grid.onSelectedRowsChanged.subscribe(fn); return { - dispose() { + dispose: () => { if (this._grid && this._grid.onSelectedRowsChanged) { this._grid.onSelectedRowsChanged.unsubscribe(fn); } @@ -149,7 +148,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl onContextMenu(fn: any): IDisposable { this._grid.onContextMenu.subscribe(fn); return { - dispose() { + dispose: () => { this._grid.onContextMenu.unsubscribe(fn); } }; @@ -186,10 +185,10 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl this._grid.resizeCanvas(); } - layout(dimension: Dimension): void; + layout(dimension: DOM.Dimension): void; layout(size: number, orientation: Orientation): void; - layout(sizing: number | Dimension, orientation?: Orientation): void { - if (sizing instanceof Dimension) { + layout(sizing: number | DOM.Dimension, orientation?: Orientation): void { + if (sizing instanceof DOM.Dimension) { this._container.style.width = sizing.width + 'px'; this._container.style.height = sizing.height + 'px'; this._tableContainer.style.width = sizing.width + 'px'; diff --git a/src/sql/base/browser/ui/table/tableDataView.ts b/src/sql/base/browser/ui/table/tableDataView.ts index c1b8398fe8..25682b6e1c 100644 --- a/src/sql/base/browser/ui/table/tableDataView.ts +++ b/src/sql/base/browser/ui/table/tableDataView.ts @@ -5,7 +5,7 @@ import { Observable } from 'rxjs/Observable'; import { Observer } from 'rxjs/Observer'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import * as types from 'vs/base/common/types'; diff --git a/src/sql/base/browser/ui/views/browser/views.ts b/src/sql/base/browser/ui/views/browser/views.ts index f8a137fb57..bad1e0f04f 100644 --- a/src/sql/base/browser/ui/views/browser/views.ts +++ b/src/sql/base/browser/ui/views/browser/views.ts @@ -280,7 +280,7 @@ export abstract class CollapsibleView extends AbstractCollapsibleView implements } // Pass Focus to Viewer - this.tree.DOMFocus(); + this.tree.domFocus(); } } diff --git a/src/sql/base/browser/ui/views/common/views.ts b/src/sql/base/browser/ui/views/common/views.ts index dfdd0b2e0b..1707780b94 100644 --- a/src/sql/base/browser/ui/views/common/views.ts +++ b/src/sql/base/browser/ui/views/common/views.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { Command } from 'vs/editor/common/modes'; export type TreeViewItemHandleArg = { diff --git a/src/sql/parts/accountManagement/accountDialog/accountDialog.ts b/src/sql/parts/accountManagement/accountDialog/accountDialog.ts index e78988b01d..54ffac92a6 100644 --- a/src/sql/parts/accountManagement/accountDialog/accountDialog.ts +++ b/src/sql/parts/accountManagement/accountDialog/accountDialog.ts @@ -12,7 +12,7 @@ import { SplitView } from 'sql/base/browser/ui/splitview/splitview'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { IListService, ListService } from 'vs/platform/list/browser/listService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachListStyler } from 'vs/platform/theme/common/styler'; diff --git a/src/sql/parts/accountManagement/accountDialog/accountViewModel.ts b/src/sql/parts/accountManagement/accountDialog/accountViewModel.ts index bfcb3524d4..9154ff830d 100644 --- a/src/sql/parts/accountManagement/accountDialog/accountViewModel.ts +++ b/src/sql/parts/accountManagement/accountDialog/accountViewModel.ts @@ -6,7 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; diff --git a/src/sql/parts/accountManagement/accountPicker/accountPicker.ts b/src/sql/parts/accountManagement/accountPicker/accountPicker.ts index 61cf36cc36..e79f15a31e 100644 --- a/src/sql/parts/accountManagement/accountPicker/accountPicker.ts +++ b/src/sql/parts/accountManagement/accountPicker/accountPicker.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/accountPicker'; import { Builder } from 'vs/base/browser/builder'; import * as DOM from 'vs/base/browser/dom'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { IDropdownOptions } from 'vs/base/browser/ui/dropdown/dropdown'; import { IListEvent } from 'vs/base/browser/ui/list/list'; diff --git a/src/sql/parts/accountManagement/accountPicker/accountPickerService.ts b/src/sql/parts/accountManagement/accountPicker/accountPickerService.ts index 72ff584783..58c54df2b1 100644 --- a/src/sql/parts/accountManagement/accountPicker/accountPickerService.ts +++ b/src/sql/parts/accountManagement/accountPicker/accountPickerService.ts @@ -5,7 +5,7 @@ 'use strict'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import { IAccountPickerService } from 'sql/parts/accountManagement/common/interfaces'; diff --git a/src/sql/parts/accountManagement/accountPicker/accountPickerViewModel.ts b/src/sql/parts/accountManagement/accountPicker/accountPickerViewModel.ts index 1f644a4140..065dfae127 100644 --- a/src/sql/parts/accountManagement/accountPicker/accountPickerViewModel.ts +++ b/src/sql/parts/accountManagement/accountPicker/accountPickerViewModel.ts @@ -5,7 +5,7 @@ 'use strict'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; diff --git a/src/sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog.ts b/src/sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog.ts index df9e33c144..3c2788bad3 100644 --- a/src/sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog.ts +++ b/src/sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog.ts @@ -9,7 +9,7 @@ import { Builder, $ } from 'vs/base/browser/builder'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; diff --git a/src/sql/parts/accountManagement/common/accountActions.ts b/src/sql/parts/accountManagement/common/accountActions.ts index ed46ffcc6b..b35b980d58 100644 --- a/src/sql/parts/accountManagement/common/accountActions.ts +++ b/src/sql/parts/accountManagement/common/accountActions.ts @@ -6,7 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; @@ -14,7 +14,7 @@ import { Action } from 'vs/base/common/actions'; import { error } from 'sql/base/common/log'; import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement'; -import { IConfirmationService, IConfirmation } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService, IConfirmation } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import Severity from 'vs/base/common/severity'; @@ -81,7 +81,7 @@ export class RemoveAccountAction extends Action { constructor( private _account: sqlops.Account, - @IConfirmationService private _confirmationService: IConfirmationService, + @IDialogService private _dialogService: IDialogService, @INotificationService private _notificationService: INotificationService, @IErrorMessageService private _errorMessageService: IErrorMessageService, @IAccountManagementService private _accountManagementService: IAccountManagementService @@ -100,7 +100,7 @@ export class RemoveAccountAction extends Action { type: 'question' }; - return this._confirmationService.confirm(confirm).then(result => { + return this._dialogService.confirm(confirm).then(result => { if (!result) { return TPromise.as(false); } else { diff --git a/src/sql/parts/accountManagement/common/interfaces.ts b/src/sql/parts/accountManagement/common/interfaces.ts index 943df55c7f..53e0d4a8cc 100644 --- a/src/sql/parts/accountManagement/common/interfaces.ts +++ b/src/sql/parts/accountManagement/common/interfaces.ts @@ -6,7 +6,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; diff --git a/src/sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog.ts b/src/sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog.ts index d05ab92caf..e4ab23b432 100644 --- a/src/sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog.ts +++ b/src/sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog.ts @@ -9,7 +9,7 @@ import 'vs/css!./media/firewallRuleDialog'; import { Builder, $ } from 'vs/base/browser/builder'; import * as DOM from 'vs/base/browser/dom'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { localize } from 'vs/nls'; import { buttonBackground } from 'vs/platform/theme/common/colorRegistry'; diff --git a/src/sql/parts/admin/security/createLoginEditor.ts b/src/sql/parts/admin/security/createLoginEditor.ts index 7ab04e106e..94c9f409a4 100644 --- a/src/sql/parts/admin/security/createLoginEditor.ts +++ b/src/sql/parts/admin/security/createLoginEditor.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!sql/parts/query/editor/media/queryEditor'; +import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -37,9 +37,9 @@ export class CreateLoginEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { } /** @@ -52,7 +52,7 @@ export class CreateLoginEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { } public setInput(input: CreateLoginInput, options: EditorOptions): TPromise<void> { @@ -63,7 +63,7 @@ export class CreateLoginEditor extends BaseEditor { if (!input.hasInitialized) { this.bootstrapAngular(input); } - this.revealElementWithTagName(input.uniqueSelector, this.getContainer().getHTMLElement()); + this.revealElementWithTagName(input.uniqueSelector, this.getContainer()); return super.setInput(input, options); } @@ -100,7 +100,7 @@ export class CreateLoginEditor extends BaseEditor { }; let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular, CreateLoginModule, - this.getContainer().getHTMLElement(), + this.getContainer(), CREATELOGIN_SELECTOR, params); input.setUniqueSelector(uniqueSelector); diff --git a/src/sql/parts/connection/common/connectionActions.ts b/src/sql/parts/connection/common/connectionActions.ts index fa10033384..cde70fc610 100644 --- a/src/sql/parts/connection/common/connectionActions.ts +++ b/src/sql/parts/connection/common/connectionActions.ts @@ -6,13 +6,13 @@ import nls = require('vs/nls'); import { Action } from 'vs/base/common/actions'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { INotificationService, INotificationActions } from 'vs/platform/notification/common/notification'; import Severity from 'vs/base/common/severity'; -import { IConfirmationService, IChoiceService, IConfirmation, IConfirmationResult, Choice } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; /** * Workbench action to clear the recent connnections list @@ -34,7 +34,7 @@ export class ClearRecentConnectionsAction extends Action { @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @INotificationService private _notificationService: INotificationService, @IQuickOpenService private _quickOpenService: IQuickOpenService, - @IConfirmationService private _confirmationService: IConfirmationService, + @IDialogService private _dialogService: IDialogService, ) { super(id, label, ClearRecentConnectionsAction.ICON); this.enabled = true; @@ -47,7 +47,7 @@ export class ClearRecentConnectionsAction extends Action { public run(): TPromise<void> { if (this._useConfirmationMessage) { return this.promptConfirmationMessage().then(result => { - if (result) { + if (result.confirmed) { this._connectionManagementService.clearRecentConnectionsList(); this._onRecentConnectionsRemoved.fire(); } @@ -84,7 +84,7 @@ export class ClearRecentConnectionsAction extends Action { }); } - private promptConfirmationMessage(): TPromise<boolean> { + private promptConfirmationMessage(): TPromise<IConfirmationResult> { let confirm: IConfirmation = { message: nls.localize('clearRecentConnectionMessage', 'Are you sure you want to delete all the connections from the list?'), primaryButton: nls.localize('connectionDialog.yes', 'Yes'), @@ -92,8 +92,8 @@ export class ClearRecentConnectionsAction extends Action { type: 'question' }; - return new TPromise<boolean>((resolve, reject) => { - this._confirmationService.confirm(confirm).then((confirmed) => { + return new TPromise<IConfirmationResult>((resolve, reject) => { + this._dialogService.confirm(confirm).then((confirmed) => { resolve(confirmed); }); }); diff --git a/src/sql/parts/connection/common/connectionManagement.ts b/src/sql/parts/connection/common/connectionManagement.ts index b6997f6ab4..bc31d01c02 100644 --- a/src/sql/parts/connection/common/connectionManagement.ts +++ b/src/sql/parts/connection/common/connectionManagement.ts @@ -8,7 +8,7 @@ import { IViewlet } from 'vs/workbench/common/viewlet'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IAction } from 'vs/base/common/actions'; import Severity from 'vs/base/common/severity'; import * as sqlops from 'sqlops'; diff --git a/src/sql/parts/connection/common/connectionManagementService.ts b/src/sql/parts/connection/common/connectionManagementService.ts index e6259b4e57..93ab6259d1 100644 --- a/src/sql/parts/connection/common/connectionManagementService.ts +++ b/src/sql/parts/connection/common/connectionManagementService.ts @@ -51,7 +51,7 @@ import { ConnectionProfileGroup, IConnectionProfileGroup } from './connectionPro import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; diff --git a/src/sql/parts/connection/connectionDialog/connectionDialogService.ts b/src/sql/parts/connection/connectionDialog/connectionDialogService.ts index 81fb1e2697..06e66d1eba 100644 --- a/src/sql/parts/connection/connectionDialog/connectionDialogService.ts +++ b/src/sql/parts/connection/connectionDialog/connectionDialogService.ts @@ -22,7 +22,6 @@ import { entries } from 'sql/base/common/objects'; import * as sqlops from 'sqlops'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { withElementById } from 'vs/base/browser/builder'; import { TPromise } from 'vs/base/common/winjs.base'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import * as platform from 'vs/base/common/platform'; @@ -306,7 +305,7 @@ export class ConnectionDialogService implements IConnectionDialogService { private doShowDialog(params: INewConnectionParams): TPromise<void> { if (!this._connectionDialog) { - let container = withElementById(this._partService.getWorkbenchElementId()).getHTMLElement().parentElement; + let container = document.getElementById(this._partService.getWorkbenchElementId()).parentElement; this._container = container; this._connectionDialog = this._instantiationService.createInstance(ConnectionDialogWidget, this._providerTypes, this._providerNameToDisplayNameMap[this._model.providerName]); this._connectionDialog.onCancel(() => { diff --git a/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts b/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts index c9f11e9d3c..e9698a3b76 100644 --- a/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts +++ b/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts @@ -24,7 +24,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Builder, $ } from 'vs/base/browser/builder'; import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -36,7 +36,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import * as styler from 'vs/platform/theme/common/styler'; import { TPromise } from 'vs/base/common/winjs.base'; import * as DOM from 'vs/base/browser/dom'; -import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogs'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; export interface OnShowUIResponse { @@ -266,7 +265,7 @@ export class ConnectionDialogWidget extends Modal { recentTitle.innerHtml(recentHistoryLabel); }); container.div({ class: 'connection-history-actions' }, (actionsContainer) => { - this._actionbar = this._register(new ActionBar(actionsContainer, { animated: false })); + this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false })); let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL); clearAction.useConfirmationMessage = true; clearAction.onRecentConnectionsRemoved(() => this.open(false)); diff --git a/src/sql/parts/connection/connectionDialog/recentConnectionTreeController.ts b/src/sql/parts/connection/connectionDialog/recentConnectionTreeController.ts index 9fcbc0efd9..62cd648898 100644 --- a/src/sql/parts/connection/connectionDialog/recentConnectionTreeController.ts +++ b/src/sql/parts/connection/connectionDialog/recentConnectionTreeController.ts @@ -15,7 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile'; import { IAction } from 'vs/base/common/actions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import mouse = require('vs/base/browser/mouseEvent'); import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; @@ -129,7 +129,7 @@ export class RecentConnectionTreeController extends DefaultController { getActions: () => this.actionProvider.getActions(tree, element), onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, getActionsContext: () => (actionContext) diff --git a/src/sql/parts/dashboard/common/actions.ts b/src/sql/parts/dashboard/common/actions.ts index 8ca2a224db..f965e5e73e 100644 --- a/src/sql/parts/dashboard/common/actions.ts +++ b/src/sql/parts/dashboard/common/actions.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IAngularEventingService, AngularEventType, IAngularEvent } from 'sql/services/angularEventing/angularEventingService'; import { INewDashboardTabDialogService } from 'sql/parts/dashboard/newDashboardTabDialog/interface'; diff --git a/src/sql/parts/dashboard/common/dashboardPage.component.ts b/src/sql/parts/dashboard/common/dashboardPage.component.ts index ad3895c183..812e31ecf3 100644 --- a/src/sql/parts/dashboard/common/dashboardPage.component.ts +++ b/src/sql/parts/dashboard/common/dashboardPage.component.ts @@ -35,7 +35,7 @@ import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeS import * as colors from 'vs/platform/theme/common/colorRegistry'; import * as themeColors from 'vs/workbench/common/theme'; import * as objects from 'vs/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Action } from 'vs/base/common/actions'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import Severity from 'vs/base/common/severity'; diff --git a/src/sql/parts/dashboard/common/interfaces.ts b/src/sql/parts/dashboard/common/interfaces.ts index 6f9ba0de7b..e95c9e2fff 100644 --- a/src/sql/parts/dashboard/common/interfaces.ts +++ b/src/sql/parts/dashboard/common/interfaces.ts @@ -5,7 +5,7 @@ import { OnDestroy } from '@angular/core'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { AngularDisposable } from 'sql/base/common/lifecycle'; diff --git a/src/sql/parts/dashboard/containers/dashboardControlHostContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardControlHostContainer.component.ts index 6b66a06bac..9436458b97 100644 --- a/src/sql/parts/dashboard/containers/dashboardControlHostContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardControlHostContainer.component.ts @@ -6,7 +6,7 @@ import 'vs/css!./dashboardControlHostContainer'; import { Component, forwardRef, Input, AfterContentInit, ViewChild, OnChanges } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; diff --git a/src/sql/parts/dashboard/containers/dashboardErrorContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardErrorContainer.component.ts index 897441d7a3..898214a4dd 100644 --- a/src/sql/parts/dashboard/containers/dashboardErrorContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardErrorContainer.component.ts @@ -11,7 +11,7 @@ import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { TabChild } from 'sql/base/browser/ui/panel/tab.component'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as nls from 'vs/nls'; @Component({ diff --git a/src/sql/parts/dashboard/containers/dashboardGridContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardGridContainer.component.ts index 3c9c0538ef..b128bf1046 100644 --- a/src/sql/parts/dashboard/containers/dashboardGridContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardGridContainer.component.ts @@ -21,7 +21,7 @@ import { TabChild } from 'sql/base/browser/ui/panel/tab.component'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import * as objects from 'vs/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface GridCellConfig { id?: string; diff --git a/src/sql/parts/dashboard/containers/dashboardModelViewContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardModelViewContainer.component.ts index 18b128a678..ac32f04644 100644 --- a/src/sql/parts/dashboard/containers/dashboardModelViewContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardModelViewContainer.component.ts @@ -6,7 +6,7 @@ import 'vs/css!./dashboardWebviewContainer'; import { Component, forwardRef, Input, AfterContentInit, ViewChild } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; diff --git a/src/sql/parts/dashboard/containers/dashboardNavSection.component.ts b/src/sql/parts/dashboard/containers/dashboardNavSection.component.ts index b9f76c32e8..6f5873c22d 100644 --- a/src/sql/parts/dashboard/containers/dashboardNavSection.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardNavSection.component.ts @@ -18,7 +18,7 @@ import { GRID_CONTAINER } from 'sql/parts/dashboard/containers/dashboardGridCont import * as dashboardHelper from 'sql/parts/dashboard/common/dashboardHelper'; import { Registry } from 'vs/platform/registry/common/platform'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as nls from 'vs/nls'; @Component({ diff --git a/src/sql/parts/dashboard/containers/dashboardWebviewContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardWebviewContainer.component.ts index 7c10b7df2d..dc19c04ae6 100644 --- a/src/sql/parts/dashboard/containers/dashboardWebviewContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardWebviewContainer.component.ts @@ -6,7 +6,7 @@ import 'vs/css!./dashboardWebviewContainer'; import { Component, forwardRef, Input, AfterContentInit, ViewChild } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { DashboardTab } from 'sql/parts/dashboard/common/interfaces'; import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; diff --git a/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts b/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts index 43209668bb..1705848d5b 100644 --- a/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts +++ b/src/sql/parts/dashboard/containers/dashboardWidgetContainer.component.ts @@ -19,7 +19,7 @@ import { TabChild } from 'sql/base/browser/ui/panel/tab.component'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import * as objects from 'vs/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; @Component({ selector: 'dashboard-widget-container', diff --git a/src/sql/parts/dashboard/contents/controlHostContent.component.ts b/src/sql/parts/dashboard/contents/controlHostContent.component.ts index 2e684ff1ce..5041cbf87d 100644 --- a/src/sql/parts/dashboard/contents/controlHostContent.component.ts +++ b/src/sql/parts/dashboard/contents/controlHostContent.component.ts @@ -6,7 +6,7 @@ import 'vs/css!./controlHostContent'; import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, ElementRef, ViewChild } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Parts } from 'vs/workbench/services/part/common/partService'; import { IDisposable } from 'vs/base/common/lifecycle'; diff --git a/src/sql/parts/dashboard/contents/webviewContent.component.ts b/src/sql/parts/dashboard/contents/webviewContent.component.ts index a91e47e13f..609568fb2c 100644 --- a/src/sql/parts/dashboard/contents/webviewContent.component.ts +++ b/src/sql/parts/dashboard/contents/webviewContent.component.ts @@ -6,8 +6,7 @@ import 'vs/css!./webviewContent'; import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, ElementRef } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; +import { Event, Emitter } from 'vs/base/common/event'; import { Parts, IPartService } from 'vs/workbench/services/part/common/partService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; @@ -15,6 +14,7 @@ import { memoize } from 'vs/base/common/decorators'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; @@ -37,7 +37,7 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo public readonly onMessage: Event<string> = this._onMessage.event; private _onMessageDisposable: IDisposable; - private _webview: Webview; + private _webview: WebviewElement; private _html: string; constructor( @@ -108,7 +108,7 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo this._onMessageDisposable.dispose(); } - this._webview = new Webview(this._el.nativeElement, + this._webview = new WebviewElement( this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, @@ -120,7 +120,7 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo enableWrappedPostMessage: true } ); - + this._webview.mountTo(this._el.nativeElement); this._onMessageDisposable = this._webview.onMessage(e => { this._onMessage.fire(e); diff --git a/src/sql/parts/dashboard/contents/widgetContent.component.ts b/src/sql/parts/dashboard/contents/widgetContent.component.ts index 1498f691fb..167c6592db 100644 --- a/src/sql/parts/dashboard/contents/widgetContent.component.ts +++ b/src/sql/parts/dashboard/contents/widgetContent.component.ts @@ -17,7 +17,7 @@ import { subscriptionToDisposable, AngularDisposable } from 'sql/base/common/lif import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import * as objects from 'vs/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { getContentHeight, addDisposableListener, EventType } from 'vs/base/browser/dom'; diff --git a/src/sql/parts/dashboard/dashboardEditor.ts b/src/sql/parts/dashboard/dashboardEditor.ts index 28ee422748..1feb447fa2 100644 --- a/src/sql/parts/dashboard/dashboardEditor.ts +++ b/src/sql/parts/dashboard/dashboardEditor.ts @@ -5,7 +5,7 @@ import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; +import { $ } from 'vs/base/browser/builder'; import { EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -46,9 +46,9 @@ export class DashboardEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { } /** @@ -70,7 +70,7 @@ export class DashboardEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { } public setInput(input: DashboardInput, options: EditorOptions): TPromise<void> { @@ -78,7 +78,7 @@ export class DashboardEditor extends BaseEditor { return TPromise.as(undefined); } - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); super.setInput(input, options); diff --git a/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabDialog.ts b/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabDialog.ts index 449aca526b..42e5ad8ff3 100644 --- a/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabDialog.ts +++ b/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabDialog.ts @@ -11,7 +11,7 @@ import * as DOM from 'vs/base/browser/dom'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { IListService, ListService } from 'vs/platform/list/browser/listService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachListStyler } from 'vs/platform/theme/common/styler'; diff --git a/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabViewModel.ts b/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabViewModel.ts index 0d800210b4..26cafaa6cf 100644 --- a/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabViewModel.ts +++ b/src/sql/parts/dashboard/newDashboardTabDialog/newDashboardTabViewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry'; diff --git a/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts b/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts index 44bcb36a51..249ffe96b3 100644 --- a/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts +++ b/src/sql/parts/dashboard/services/dashboardServiceInterface.service.ts @@ -40,7 +40,7 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur import { ConfigurationEditingService, IConfigurationValue } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; import * as nls from 'vs/nls'; import { IPartService } from 'vs/workbench/services/part/common/partService'; diff --git a/src/sql/parts/dashboard/widgets/insights/views/tableInsight.component.ts b/src/sql/parts/dashboard/widgets/insights/views/tableInsight.component.ts index afa7949c84..d7755ea3bd 100644 --- a/src/sql/parts/dashboard/widgets/insights/views/tableInsight.component.ts +++ b/src/sql/parts/dashboard/widgets/insights/views/tableInsight.component.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, OnInit } from '@angular/core'; -import { getContentHeight, getContentWidth } from 'vs/base/browser/dom'; -import { Dimension } from 'vs/base/browser/builder'; +import { getContentHeight, getContentWidth, Dimension } from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; diff --git a/src/sql/parts/dashboard/widgets/webview/webviewWidget.component.ts b/src/sql/parts/dashboard/widgets/webview/webviewWidget.component.ts index 339aebab53..f6235f96fe 100644 --- a/src/sql/parts/dashboard/widgets/webview/webviewWidget.component.ts +++ b/src/sql/parts/dashboard/widgets/webview/webviewWidget.component.ts @@ -5,9 +5,8 @@ import { Component, Inject, forwardRef, ChangeDetectorRef, OnInit, ViewChild, ElementRef } from '@angular/core'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; import { Parts, IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { memoize } from 'vs/base/common/decorators'; @@ -20,6 +19,7 @@ import * as sqlops from 'sqlops'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; interface IWebviewWidgetConfig { id: string; @@ -34,7 +34,7 @@ const selector = 'webview-widget'; export class WebviewWidget extends DashboardWidget implements IDashboardWidget, OnInit, IDashboardWebview { private _id: string; - private _webview: Webview; + private _webview: WebviewElement; private _html: string; private _onMessage = new Emitter<string>(); public readonly onMessage: Event<string> = this._onMessage.event; @@ -105,8 +105,7 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget, if (this._onMessageDisposable) { this._onMessageDisposable.dispose(); } - this._webview = new Webview( - this._el.nativeElement, + this._webview = new WebviewElement( this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, @@ -118,6 +117,7 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget, enableWrappedPostMessage: true } ); + this._webview.mountTo(this._el.nativeElement); this._onMessageDisposable = this._webview.onMessage(e => { this._onMessage.fire(e); }); diff --git a/src/sql/parts/disasterRecovery/backup/common/backupService.ts b/src/sql/parts/disasterRecovery/backup/common/backupService.ts index 3624335795..dc8fc5bb18 100644 --- a/src/sql/parts/disasterRecovery/backup/common/backupService.ts +++ b/src/sql/parts/disasterRecovery/backup/common/backupService.ts @@ -6,7 +6,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams'; diff --git a/src/sql/parts/disasterRecovery/backup/common/backupServiceImp.ts b/src/sql/parts/disasterRecovery/backup/common/backupServiceImp.ts index f4f0b73b6a..35591576b7 100644 --- a/src/sql/parts/disasterRecovery/backup/common/backupServiceImp.ts +++ b/src/sql/parts/disasterRecovery/backup/common/backupServiceImp.ts @@ -13,7 +13,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IBackupService, TaskExecutionMode, IBackupUiService } from 'sql/parts/disasterRecovery/backup/common/backupService'; import { BackupDialog } from 'sql/parts/disasterRecovery/backup/backupDialog'; import { OptionsDialog } from 'sql/base/browser/ui/modal/optionsDialog'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IPartService } from 'vs/workbench/services/part/common/partService'; diff --git a/src/sql/parts/disasterRecovery/backup/constants.ts b/src/sql/parts/disasterRecovery/backup/constants.ts index 9774c23020..29710668ca 100644 --- a/src/sql/parts/disasterRecovery/backup/constants.ts +++ b/src/sql/parts/disasterRecovery/backup/constants.ts @@ -42,7 +42,7 @@ export const tripleDES = 'Triple DES'; export const serverCertificate = "Server Certificate"; export const asymmetricKey = "Asymmetric Key"; -export const fileFiltersSet: [ {label: string, filters: string[]} ] = [ +export const fileFiltersSet: {label: string, filters: string[]}[] = [ { label: localize('backup.filterBackupFiles', "Backup Files"), filters: ['*.bak', '*.trn', '*.log'] }, { label: localize('backup.allFiles', "All Files"), filters: ['*'] } ]; \ No newline at end of file diff --git a/src/sql/parts/disasterRecovery/restore/restoreDialog.ts b/src/sql/parts/disasterRecovery/restore/restoreDialog.ts index a4641373bd..c0b4cfaa39 100644 --- a/src/sql/parts/disasterRecovery/restore/restoreDialog.ts +++ b/src/sql/parts/disasterRecovery/restore/restoreDialog.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/restoreDialog'; import { Builder, $ } from 'vs/base/browser/builder'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Widget } from 'vs/base/browser/ui/widget'; import { MessageType, IInputOptions } from 'vs/base/browser/ui/inputbox/inputBox'; diff --git a/src/sql/parts/disasterRecovery/restore/restoreViewModel.ts b/src/sql/parts/disasterRecovery/restore/restoreViewModel.ts index 52f8749461..a98d195f5b 100644 --- a/src/sql/parts/disasterRecovery/restore/restoreViewModel.ts +++ b/src/sql/parts/disasterRecovery/restore/restoreViewModel.ts @@ -8,7 +8,7 @@ import * as sqlops from 'sqlops'; import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper'; import * as types from 'vs/base/common/types'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes'; export interface RestoreOptionsElement { diff --git a/src/sql/parts/editData/common/editDataInput.ts b/src/sql/parts/editData/common/editDataInput.ts index 5c5f4c214a..386e22cf88 100644 --- a/src/sql/parts/editData/common/editDataInput.ts +++ b/src/sql/parts/editData/common/editDataInput.ts @@ -8,7 +8,7 @@ import { EditorInput, EditorModel, ConfirmResult, EncodingMode } from 'vs/workbe import { IConnectionManagementService, IConnectableInput, INewConnectionParams } from 'sql/parts/connection/common/connectionManagement'; import { IQueryModelService } from 'sql/parts/query/execution/queryModel'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { EditSessionReadyParams, ISelectionData } from 'sqlops'; import URI from 'vs/base/common/uri'; import nls = require('vs/nls'); diff --git a/src/sql/parts/editData/editor/editDataEditor.ts b/src/sql/parts/editData/editor/editDataEditor.ts index 54375775b0..1fe38fc8d1 100644 --- a/src/sql/parts/editData/editor/editDataEditor.ts +++ b/src/sql/parts/editData/editor/editDataEditor.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as strings from 'vs/base/common/strings'; import * as DOM from 'vs/base/browser/dom'; import * as nls from 'vs/nls'; -import { Builder, Dimension, withElementById } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { EditorOptions, EditorInput } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; @@ -58,7 +58,7 @@ export class EditDataEditor extends BaseEditor { private readonly _minEditorSize: number = 220; private _sash: IFlexibleSash; - private _dimension: Dimension; + private _dimension: DOM.Dimension; private _resultsEditor: EditDataResultsEditor; private _resultsEditorContainer: HTMLElement; @@ -142,10 +142,10 @@ export class EditDataEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { - const parentElement = parent.getHTMLElement(); + public createEditor(parent: HTMLElement): void { + const parentElement = parent; DOM.addClass(parentElement, 'side-by-side-editor'); this._createTaskbar(parentElement); } @@ -197,7 +197,7 @@ export class EditDataEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this._dimension = dimension; if (this._sash) { @@ -274,7 +274,7 @@ export class EditDataEditor extends BaseEditor { } let editor = descriptor.instantiate(this._instantiationService); - editor.create(new Builder(container)); + editor.create(container); editor.setVisible(this.isVisible(), this.position); return TPromise.as(editor); } @@ -287,7 +287,7 @@ export class EditDataEditor extends BaseEditor { private _createResultsEditorContainer() { this._createSash(); - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); let input = <EditDataInput>this.input; if (!input.results.container) { @@ -305,7 +305,7 @@ export class EditDataEditor extends BaseEditor { */ private _createSash(): void { if (!this._sash) { - let parentElement: HTMLElement = this.getContainer().getHTMLElement(); + let parentElement: HTMLElement = this.getContainer(); this._sash = this._register(new HorizontalFlexibleSash(parentElement, this._minEditorSize)); this._setSashDimension(); @@ -320,7 +320,7 @@ export class EditDataEditor extends BaseEditor { * Appends the HTML for the SQL editor. Creates new HTML every time. */ private _createSqlEditorContainer() { - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); this._sqlEditorContainer = DOM.append(parentElement, DOM.$('.details-editor-container')); this._sqlEditorContainer.style.position = 'absolute'; } @@ -382,7 +382,7 @@ export class EditDataEditor extends BaseEditor { this._resultsEditor = null; } - let thisEditorParent: HTMLElement = this.getContainer().getHTMLElement(); + let thisEditorParent: HTMLElement = this.getContainer(); if (this._sqlEditorContainer) { let sqlEditorParent: HTMLElement = this._sqlEditorContainer.parentElement; @@ -420,7 +420,7 @@ export class EditDataEditor extends BaseEditor { private _doLayoutHorizontal(): void { let splitPointTop: number = this._sash.getSplitPoint(); - let parent: ClientRect = this.getContainer().getHTMLElement().getBoundingClientRect(); + let parent: ClientRect = this.getContainer().getBoundingClientRect(); let sqlEditorHeight: number; let sqlEditorTop: number; @@ -431,7 +431,7 @@ export class EditDataEditor extends BaseEditor { this._resultsEditorContainer.hidden = false; - let titleBar = withElementById('workbench.parts.titlebar'); + let titleBar = document.getElementById('workbench.parts.titlebar'); if (this.queryPaneEnabled()) { this._sqlEditorContainer.hidden = false; @@ -442,7 +442,7 @@ export class EditDataEditor extends BaseEditor { resultsEditorHeight = parent.bottom - resultsEditorTop; if (titleBar) { - sqlEditorHeight += DOM.getContentHeight(titleBar.getHTMLElement()); + sqlEditorHeight += DOM.getContentHeight(titleBar); } } else { this._sqlEditorContainer.hidden = true; @@ -454,7 +454,7 @@ export class EditDataEditor extends BaseEditor { resultsEditorHeight = parent.bottom - resultsEditorTop; if (titleBar) { - resultsEditorHeight += DOM.getContentHeight(titleBar.getHTMLElement()); + resultsEditorHeight += DOM.getContentHeight(titleBar); } } @@ -466,8 +466,8 @@ export class EditDataEditor extends BaseEditor { this._resultsEditorContainer.style.width = `${this._dimension.width}px`; this._resultsEditorContainer.style.top = `${resultsEditorTop}px`; - this._sqlEditor.layout(new Dimension(this._dimension.width, sqlEditorHeight)); - this._resultsEditor.layout(new Dimension(this._dimension.width, resultsEditorHeight)); + this._sqlEditor.layout(new DOM.Dimension(this._dimension.width, sqlEditorHeight)); + this._resultsEditor.layout(new DOM.Dimension(this._dimension.width, resultsEditorHeight)); } private _doLayoutSql() { @@ -492,7 +492,7 @@ export class EditDataEditor extends BaseEditor { this._sqlEditorContainer.style.height = `${sqlEditorHeight}px`; this._sqlEditorContainer.style.width = `${this._dimension.width}px`; - this._sqlEditor.layout(new Dimension(this._dimension.width, sqlEditorHeight)); + this._sqlEditor.layout(new DOM.Dimension(this._dimension.width, sqlEditorHeight)); } } diff --git a/src/sql/parts/editData/editor/editDataResultsEditor.ts b/src/sql/parts/editData/editor/editDataResultsEditor.ts index d9c28c8b86..5e47427263 100644 --- a/src/sql/parts/editData/editor/editDataResultsEditor.ts +++ b/src/sql/parts/editData/editor/editDataResultsEditor.ts @@ -3,8 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as DOM from 'vs/base/browser/dom'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { Dimension, Builder } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { EditorOptions } from 'vs/workbench/common/editor'; import { TPromise } from 'vs/base/common/winjs.base'; import { getZoomLevel } from 'vs/base/browser/browser'; @@ -13,7 +14,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import * as dom from 'vs/base/browser/dom'; import * as types from 'vs/base/common/types'; import { IQueryModelService } from 'sql/parts/query/execution/queryModel'; @@ -52,14 +52,14 @@ export class EditDataResultsEditor extends BaseEditor { return this._input; } - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { } public dispose(): void { super.dispose(); } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { } public setInput(input: EditDataResultsInput, options: EditorOptions): TPromise<void> { @@ -73,9 +73,9 @@ export class EditDataResultsEditor extends BaseEditor { private _applySettings() { if (this.input && this.input.container) { - Configuration.applyFontInfoSlow(this.getContainer().getHTMLElement(), this._rawOptions); + Configuration.applyFontInfoSlow(this.getContainer(), this._rawOptions); if (!this.input.css) { - this.input.css = dom.createStyleSheet(this.input.container); + this.input.css = DOM.createStyleSheet(this.input.container); } let cssRuleText = ''; if (types.isNumber(this._rawOptions.cellPadding)) { diff --git a/src/sql/parts/extensions/sqlExtensionsHelper.ts b/src/sql/parts/extensions/sqlExtensionsHelper.ts index ce9c913409..ed230c9560 100644 --- a/src/sql/parts/extensions/sqlExtensionsHelper.ts +++ b/src/sql/parts/extensions/sqlExtensionsHelper.ts @@ -5,7 +5,7 @@ 'use strict'; -import 'vs/css!vs/workbench/parts/extensions/browser/media/extensionEditor'; +import 'vs/css!vs/workbench/parts/extensions/electron-browser/media/extensionEditor'; import { IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; diff --git a/src/sql/parts/fileBrowser/common/fileBrowserService.ts b/src/sql/parts/fileBrowser/common/fileBrowserService.ts index ad315a62bd..c2698246d2 100644 --- a/src/sql/parts/fileBrowser/common/fileBrowserService.ts +++ b/src/sql/parts/fileBrowser/common/fileBrowserService.ts @@ -12,7 +12,7 @@ import { FileNode } from 'sql/parts/fileBrowser/common/fileNode'; import { IFileBrowserService } from 'sql/parts/fileBrowser/common/interfaces'; import * as Constants from 'sql/common/constants'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; import { localize } from 'vs/nls'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/sql/parts/fileBrowser/common/interfaces.ts b/src/sql/parts/fileBrowser/common/interfaces.ts index fe01d6782c..bd9c6596ac 100644 --- a/src/sql/parts/fileBrowser/common/interfaces.ts +++ b/src/sql/parts/fileBrowser/common/interfaces.ts @@ -8,7 +8,7 @@ import * as sqlops from 'sqlops'; import { FileBrowserTree } from 'sql/parts/fileBrowser/common/fileBrowserTree'; import { FileNode } from 'sql/parts/fileBrowser/common/fileNode'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const IFileBrowserDialogController = createDecorator<IFileBrowserDialogController>('fileBrowserDialogService'); @@ -19,7 +19,7 @@ export interface IFileBrowserDialogController { */ showDialog(ownerUri: string, expandPath: string, - fileFilters: [{ label: string, filters: string[] }], + fileFilters: { label: string, filters: string[] }[], fileValidationServiceType: string, isWide: boolean, handleOnOk: (path: string) => void): void; diff --git a/src/sql/parts/fileBrowser/fileBrowserController.ts b/src/sql/parts/fileBrowser/fileBrowserController.ts index ac7c9de5f0..fce63715a8 100644 --- a/src/sql/parts/fileBrowser/fileBrowserController.ts +++ b/src/sql/parts/fileBrowser/fileBrowserController.ts @@ -31,7 +31,7 @@ export class FileBrowserController extends treedefaults.DefaultController { event.preventDefault(); // we cannot preventDefault onMouseDown because this would break DND otherwise } event.stopPropagation(); - tree.DOMFocus(); + tree.domFocus(); tree.setSelection([element], payload); } return true; diff --git a/src/sql/parts/fileBrowser/fileBrowserDialog.ts b/src/sql/parts/fileBrowser/fileBrowserDialog.ts index bb647c6edd..f92fc09ad1 100644 --- a/src/sql/parts/fileBrowser/fileBrowserDialog.ts +++ b/src/sql/parts/fileBrowser/fileBrowserDialog.ts @@ -22,7 +22,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Builder } from 'vs/base/browser/builder'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { localize } from 'vs/nls'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; diff --git a/src/sql/parts/fileBrowser/fileBrowserRenderer.ts b/src/sql/parts/fileBrowser/fileBrowserRenderer.ts index 95f6038752..c747f4dc86 100644 --- a/src/sql/parts/fileBrowser/fileBrowserRenderer.ts +++ b/src/sql/parts/fileBrowser/fileBrowserRenderer.ts @@ -11,6 +11,7 @@ import URI from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { FileLabel } from 'vs/workbench/browser/labels'; import { IFileTemplateData } from 'vs/workbench/parts/files/electron-browser/views/explorerViewer'; +import { empty as EmptyDisposable } from 'vs/base/common/lifecycle'; /** * Renders the tree items. @@ -43,8 +44,9 @@ export class FileBrowserRenderer implements IRenderer { * Render template in a dom element based on template id */ public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): IFileTemplateData { + const elementDisposable = EmptyDisposable; const label = this.instantiationService.createInstance(FileLabel, container, void 0); - return { label, container }; + return { elementDisposable, label, container }; } /** diff --git a/src/sql/parts/fileBrowser/fileBrowserTreeView.ts b/src/sql/parts/fileBrowser/fileBrowserTreeView.ts index 551e6db1df..c5e537aba4 100644 --- a/src/sql/parts/fileBrowser/fileBrowserTreeView.ts +++ b/src/sql/parts/fileBrowser/fileBrowserTreeView.ts @@ -45,7 +45,7 @@ export class FileBrowserTreeView { this._toDispose.push(this._tree.onDidChangeSelection((event) => this.onSelected(event))); this._toDispose.push(this._fileBrowserService.onExpandFolder(fileNode => this._tree.refresh(fileNode))); this._toDispose.push(attachListStyler(this._tree, this._themeService)); - this._tree.DOMFocus(); + this._tree.domFocus(); } if (rootNode) { @@ -91,7 +91,7 @@ export class FileBrowserTreeView { let targetsToExpand: any[]; // Focus - this._tree.DOMFocus(); + this._tree.domFocus(); if (this._tree) { let selection = this._tree.getSelection(); diff --git a/src/sql/parts/insights/common/insightsDialogModel.ts b/src/sql/parts/insights/common/insightsDialogModel.ts index 0b78fc5a85..491f6790b6 100644 --- a/src/sql/parts/insights/common/insightsDialogModel.ts +++ b/src/sql/parts/insights/common/insightsDialogModel.ts @@ -7,7 +7,7 @@ import { IInsightsDialogModel, ListResource } from './interfaces'; import { IInsightsConfigDetails, IInsightsLabel } from 'sql/parts/dashboard/widgets/insights/interfaces'; import { Conditional } from 'sql/parts/dashboard/common/interfaces'; -import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent } from 'vs/base/common/event'; export class InsightsDialogModel implements IInsightsDialogModel { private _rows: string[][]; diff --git a/src/sql/parts/insights/common/interfaces.ts b/src/sql/parts/insights/common/interfaces.ts index 72d63a46da..7f9ba5294d 100644 --- a/src/sql/parts/insights/common/interfaces.ts +++ b/src/sql/parts/insights/common/interfaces.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IInsightsConfigDetails, IInsightsConfig } from 'sql/parts/dashboard/widgets/insights/interfaces'; diff --git a/src/sql/parts/jobManagement/views/jobHistoryTree.ts b/src/sql/parts/jobManagement/views/jobHistoryTree.ts index 501c603857..4e5b47fc96 100644 --- a/src/sql/parts/jobManagement/views/jobHistoryTree.ts +++ b/src/sql/parts/jobManagement/views/jobHistoryTree.ts @@ -25,7 +25,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { generateUuid } from 'vs/base/common/uuid'; import * as DOM from 'vs/base/browser/dom'; import { OEAction } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions'; -import { Builder, $, withElementById } from 'vs/base/browser/builder'; +import { $ } from 'vs/base/browser/builder'; import { AgentJobHistoryInfo } from 'sqlops'; import { Agent } from 'vs/base/node/request'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; diff --git a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts index c048f3fc0f..a1d9f81231 100644 --- a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts +++ b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts @@ -24,7 +24,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { generateUuid } from 'vs/base/common/uuid'; import * as DOM from 'vs/base/browser/dom'; import { OEAction } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions'; -import { Builder, $, withElementById } from 'vs/base/browser/builder'; import { AgentJobHistoryInfo } from 'sqlops'; import { Agent } from 'vs/base/node/request'; import { AgentJobUtilities } from 'sql/parts/jobManagement/common/agentJobUtilities'; diff --git a/src/sql/parts/modelComponents/button.component.ts b/src/sql/parts/modelComponents/button.component.ts index 307bc68883..bf7c4c5468 100644 --- a/src/sql/parts/modelComponents/button.component.ts +++ b/src/sql/parts/modelComponents/button.component.ts @@ -9,7 +9,7 @@ import { } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; diff --git a/src/sql/parts/modelComponents/checkbox.component.ts b/src/sql/parts/modelComponents/checkbox.component.ts index 53f26fc35f..dce4381fca 100644 --- a/src/sql/parts/modelComponents/checkbox.component.ts +++ b/src/sql/parts/modelComponents/checkbox.component.ts @@ -9,7 +9,7 @@ import { } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; diff --git a/src/sql/parts/modelComponents/componentBase.ts b/src/sql/parts/modelComponents/componentBase.ts index 16bf75252c..c25bc33f8a 100644 --- a/src/sql/parts/modelComponents/componentBase.ts +++ b/src/sql/parts/modelComponents/componentBase.ts @@ -15,7 +15,7 @@ import { IComponent, IComponentDescriptor, IModelStore, IComponentEventArgs, Com import { FlexLayout, FlexItemLayout } from 'sqlops'; import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost.directive'; import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component'; diff --git a/src/sql/parts/modelComponents/dropdown.component.ts b/src/sql/parts/modelComponents/dropdown.component.ts index a72dda3396..28b38117c0 100644 --- a/src/sql/parts/modelComponents/dropdown.component.ts +++ b/src/sql/parts/modelComponents/dropdown.component.ts @@ -19,7 +19,7 @@ import { attachEditableDropdownStyler , attachSelectBoxStyler} from 'sql/common/ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { attachListStyler } from 'vs/platform/theme/common/styler'; @Component({ diff --git a/src/sql/parts/modelComponents/inputbox.component.ts b/src/sql/parts/modelComponents/inputbox.component.ts index 3d8099097e..a881731edd 100644 --- a/src/sql/parts/modelComponents/inputbox.component.ts +++ b/src/sql/parts/modelComponents/inputbox.component.ts @@ -18,7 +18,7 @@ import { IInputOptions, MessageType } from 'vs/base/browser/ui/inputbox/inputBox import { attachInputBoxStyler, attachListStyler } from 'vs/platform/theme/common/styler'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as nls from 'vs/nls'; @Component({ diff --git a/src/sql/parts/modelComponents/interfaces.ts b/src/sql/parts/modelComponents/interfaces.ts index 5dd904f709..aa34231f1e 100644 --- a/src/sql/parts/modelComponents/interfaces.ts +++ b/src/sql/parts/modelComponents/interfaces.ts @@ -5,7 +5,7 @@ import { InjectionToken } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; /** diff --git a/src/sql/parts/modelComponents/modelEditor/modelViewEditor.ts b/src/sql/parts/modelComponents/modelEditor/modelViewEditor.ts index 565855ca3b..596966832f 100644 --- a/src/sql/parts/modelComponents/modelEditor/modelViewEditor.ts +++ b/src/sql/parts/modelComponents/modelEditor/modelViewEditor.ts @@ -9,7 +9,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { Dimension } from 'vs/workbench/services/part/common/partService'; import { EditorOptions } from 'vs/workbench/common/editor'; import * as DOM from 'vs/base/browser/dom'; import { Position } from 'vs/platform/editor/common/editor'; @@ -31,10 +30,10 @@ export class ModelViewEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { - this._editorFrame = parent.getHTMLElement(); + public createEditor(parent: HTMLElement): void { + this._editorFrame = parent; } /** @@ -93,7 +92,7 @@ export class ModelViewEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { if (this.input instanceof ModelViewInput) { if (this.input.container && this.input.dialogPane) { this.doUpdateContainer(); diff --git a/src/sql/parts/modelComponents/modelViewContent.component.ts b/src/sql/parts/modelComponents/modelViewContent.component.ts index 6a6100c7ba..8fd10a7d5a 100644 --- a/src/sql/parts/modelComponents/modelViewContent.component.ts +++ b/src/sql/parts/modelComponents/modelViewContent.component.ts @@ -6,7 +6,7 @@ import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, ElementRef } from '@angular/core'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Parts } from 'vs/workbench/services/part/common/partService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; diff --git a/src/sql/parts/modelComponents/radioButton.component.ts b/src/sql/parts/modelComponents/radioButton.component.ts index cbd065c086..80e98ae987 100644 --- a/src/sql/parts/modelComponents/radioButton.component.ts +++ b/src/sql/parts/modelComponents/radioButton.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; diff --git a/src/sql/parts/modelComponents/table.component.ts b/src/sql/parts/modelComponents/table.component.ts index 58d0dc1575..3299488095 100644 --- a/src/sql/parts/modelComponents/table.component.ts +++ b/src/sql/parts/modelComponents/table.component.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { - Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver, - ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList, AfterViewInit + Component, Input, Inject, ChangeDetectorRef, forwardRef, ViewChild, ElementRef, OnDestroy, AfterViewInit } from '@angular/core'; import * as sqlops from 'sqlops'; @@ -18,10 +17,7 @@ import { TableDataView } from 'sql/base/browser/ui/table/tableDataView'; import { attachTableStyler } from 'sql/common/theme/styler'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Dimension } from 'vs/base/browser/builder'; -import * as nls from 'vs/nls'; -import { getContentHeight, getContentWidth } from 'vs/base/browser/dom'; +import { getContentHeight, getContentWidth, Dimension } from 'vs/base/browser/dom'; import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectionModel.plugin'; @Component({ @@ -40,9 +36,7 @@ export default class TableComponent extends ComponentBase implements IComponent, @ViewChild('table', { read: ElementRef }) private _inputContainer: ElementRef; constructor( @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef, - @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService, - @Inject(IContextViewService) private contextViewService: IContextViewService - ) { + @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService) { super(changeRef); } @@ -140,7 +134,7 @@ export default class TableComponent extends ComponentBase implements IComponent, this._changeRef.detectChanges(); } - public setLayout(layout: any): void { + public setLayout(): void { // TODO allow configuring the look and feel this.layout(); } diff --git a/src/sql/parts/modelComponents/text.component.ts b/src/sql/parts/modelComponents/text.component.ts index 924b9b090c..404eebf373 100644 --- a/src/sql/parts/modelComponents/text.component.ts +++ b/src/sql/parts/modelComponents/text.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; diff --git a/src/sql/parts/modelComponents/viewBase.ts b/src/sql/parts/modelComponents/viewBase.ts index 1352477429..8a9a16ec49 100644 --- a/src/sql/parts/modelComponents/viewBase.ts +++ b/src/sql/parts/modelComponents/viewBase.ts @@ -16,7 +16,7 @@ import { IModelView } from 'sql/services/model/modelViewService'; import { Extensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry'; import { AngularDisposable } from 'sql/base/common/lifecycle'; import { ModelStore } from 'sql/parts/modelComponents/modelStore'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; const componentRegistry = <IComponentRegistry>Registry.as(Extensions.ComponentContribution); diff --git a/src/sql/parts/modelComponents/webview.component.ts b/src/sql/parts/modelComponents/webview.component.ts index a0050e4dea..584c9c1f21 100644 --- a/src/sql/parts/modelComponents/webview.component.ts +++ b/src/sql/parts/modelComponents/webview.component.ts @@ -9,14 +9,14 @@ import { } from '@angular/core'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; +import { Event, Emitter } from 'vs/base/common/event'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; import { Parts, IPartService } from 'vs/workbench/services/part/common/partService'; import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; @@ -29,7 +29,7 @@ export default class WebViewComponent extends ComponentBase implements IComponen @Input() descriptor: IComponentDescriptor; @Input() modelStore: IModelStore; - private _webview: Webview; + private _webview: WebviewElement; private _onMessage = new Emitter<any>(); private _renderedHtml: string; @@ -54,7 +54,7 @@ export default class WebViewComponent extends ComponentBase implements IComponen } private _createWebview(): void { - this._webview = this._register(new Webview(this._el.nativeElement, + this._webview = this._register(new WebviewElement( this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, @@ -66,7 +66,7 @@ export default class WebViewComponent extends ComponentBase implements IComponen enableWrappedPostMessage: true } )); - + this._webview.mountTo(this._el.nativeElement); this._register(this._webview.onMessage(e => { this._onEventEmitter.fire({ diff --git a/src/sql/parts/objectExplorer/common/objectExplorerService.ts b/src/sql/parts/objectExplorer/common/objectExplorerService.ts index bc8c5fc721..a4ac817ca1 100644 --- a/src/sql/parts/objectExplorer/common/objectExplorerService.ts +++ b/src/sql/parts/objectExplorer/common/objectExplorerService.ts @@ -11,7 +11,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import * as nls from 'vs/nls'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; diff --git a/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts b/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts index 129d85a5d4..7006bd36f6 100644 --- a/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts +++ b/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts @@ -14,7 +14,7 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler, attachCheckboxStyler } from 'vs/platform/theme/common/styler'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; diff --git a/src/sql/parts/objectExplorer/viewlet/connectionViewlet.ts b/src/sql/parts/objectExplorer/viewlet/connectionViewlet.ts index 4e44d953f0..68eafbfe4e 100644 --- a/src/sql/parts/objectExplorer/viewlet/connectionViewlet.ts +++ b/src/sql/parts/objectExplorer/viewlet/connectionViewlet.ts @@ -6,13 +6,13 @@ 'use strict'; import 'vs/css!./media/connectionViewlet'; +import * as DOM from 'vs/base/browser/dom'; import { ThrottledDelayer } from 'vs/base/common/async'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, Dimension } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { Viewlet } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IAction } from 'vs/base/common/actions'; -import { toggleClass } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; @@ -81,11 +81,12 @@ export class ConnectionViewlet extends Viewlet implements IConnectionsViewlet { }); } - public create(parent: Builder): TPromise<void> { + public create(parent: HTMLElement): TPromise<void> { return new TPromise<void>((resolve) => { super.create(parent); - this._root = parent.getHTMLElement(); - parent.div({ class: 'server-explorer-viewlet' }, (viewletContainer) => { + this._root = parent; + let parentBuilder = new Builder(parent); + parentBuilder.div({ class: 'server-explorer-viewlet' }, (viewletContainer) => { this._viewletContainer = viewletContainer; viewletContainer.div({ class: 'search-box' }, (searchBoxContainer) => { this._searchBoxContainer = searchBoxContainer; @@ -147,10 +148,10 @@ export class ConnectionViewlet extends Viewlet implements IConnectionsViewlet { super.focus(); } - public layout({ height, width }: Dimension): void { + public layout({ height, width }: DOM.Dimension): void { this._searchBox.layout(); this._serverTreeView.layout(height - 36); // account for search box - toggleClass(this._root, 'narrow', width <= 350); + DOM.toggleClass(this._root, 'narrow', width <= 350); } public getOptimalWidth(): number { diff --git a/src/sql/parts/objectExplorer/viewlet/serverTreeController.ts b/src/sql/parts/objectExplorer/viewlet/serverTreeController.ts index 4ea1db04ab..23c3b13e9c 100644 --- a/src/sql/parts/objectExplorer/viewlet/serverTreeController.ts +++ b/src/sql/parts/objectExplorer/viewlet/serverTreeController.ts @@ -103,7 +103,7 @@ export class ServerTreeController extends treedefaults.DefaultController { getKeyBinding: (action) => this.keybindingService.lookupKeybinding(action.id), onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, getActionsContext: () => (actionContext) diff --git a/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts b/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts index 0b1391997b..a584e64572 100644 --- a/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts +++ b/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts @@ -27,7 +27,7 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; import { Button } from 'sql/base/browser/ui/button/button'; import { attachButtonStyler } from 'sql/common/theme/styler'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { SERVER_GROUP_CONFIG, SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroup.contribution'; diff --git a/src/sql/parts/objectExplorer/viewlet/treeUpdateUtils.ts b/src/sql/parts/objectExplorer/viewlet/treeUpdateUtils.ts index 2bf748f510..9a5b4114e6 100644 --- a/src/sql/parts/objectExplorer/viewlet/treeUpdateUtils.ts +++ b/src/sql/parts/objectExplorer/viewlet/treeUpdateUtils.ts @@ -63,7 +63,7 @@ export class TreeUpdateUtils { let targetsToExpand: any[]; // Focus - tree.DOMFocus(); + tree.domFocus(); if (tree) { let selection = tree.getSelection(); diff --git a/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts b/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts index f40c084c4a..8724558c87 100644 --- a/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts +++ b/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts @@ -22,7 +22,7 @@ import * as DOM from 'vs/base/browser/dom'; import { IDataSource, ITree, IRenderer } from 'vs/base/parts/tree/browser/tree'; import { TPromise } from 'vs/base/common/winjs.base'; import { attachListStyler } from 'vs/platform/theme/common/styler'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; diff --git a/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts b/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts index c6756a5ba6..5bd6478919 100644 --- a/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts +++ b/src/sql/parts/profiler/editor/controller/profilerTableEditor.ts @@ -21,11 +21,12 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IEditorAction } from 'vs/editor/common/editorCommon'; import { IOverlayWidget } from 'vs/editor/browser/editorBrowser'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState'; -import { Dimension, Builder } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { Dimension } from 'vs/base/browser/dom'; export class ProfilerTableEditor extends BaseEditor implements IProfilerController, ITableController { @@ -57,15 +58,15 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll this._actionMap[ACTION_IDS.FIND_PREVIOUS] = this._instantiationService.createInstance(ProfilerFindPrevious, this); } - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { this._overlay = document.createElement('div'); this._overlay.className = 'overlayWidgets'; this._overlay.style.width = '100%'; this._overlay.style.zIndex = '4'; - parent.getHTMLElement().appendChild(this._overlay); + parent.appendChild(this._overlay); - this._profilerTable = new Table(parent.getHTMLElement()); + this._profilerTable = new Table(parent); this._profilerTable.setSelectionModel(new RowSelectionModel()); attachTableStyler(this._profilerTable, this._themeService); diff --git a/src/sql/parts/profiler/editor/profilerEditor.ts b/src/sql/parts/profiler/editor/profilerEditor.ts index b0bb74c586..148f217b26 100644 --- a/src/sql/parts/profiler/editor/profilerEditor.ts +++ b/src/sql/parts/profiler/editor/profilerEditor.ts @@ -19,7 +19,7 @@ import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox'; import * as DOM from 'vs/base/browser/dom'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { Dimension, Builder } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { TPromise } from 'vs/base/common/winjs.base'; import { EditorOptions } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -138,13 +138,13 @@ export class ProfilerEditor extends BaseEditor { this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService); } - protected createEditor(parent: Builder): void { + protected createEditor(parent: HTMLElement): void { // test backend //this._profilerService.registerProvider('default', this._instantiationService.createInstance(ProfilerTestBackend)); this._container = document.createElement('div'); this._container.className = 'carbon-profiler'; - parent.append(this._container); + parent.appendChild(this._container); this._createHeader(); @@ -159,7 +159,7 @@ export class ProfilerEditor extends BaseEditor { 300, tableContainer, () => this._profilerTableEditor.focus(), - size => this._profilerTableEditor.layout(new Dimension(parseFloat(DOM.getComputedStyle(this._body).width), size)), + size => this._profilerTableEditor.layout(new DOM.Dimension(parseFloat(DOM.getComputedStyle(this._body).width), size)), {} )); @@ -167,7 +167,7 @@ export class ProfilerEditor extends BaseEditor { 300, paneContainer, () => this._tabbedPanel.focus(), - size => this._tabbedPanel.layout(new Dimension(DOM.getTotalWidth(this._body), size)), + size => this._tabbedPanel.layout(new DOM.Dimension(DOM.getTotalWidth(this._body), size)), { minimumSize: 35 } ); this._panelView.headerSize = 35; @@ -222,7 +222,7 @@ export class ProfilerEditor extends BaseEditor { profilerTableContainer.style.overflow = 'hidden'; profilerTableContainer.style.position = 'relative'; this._profilerTableEditor = this._instantiationService.createInstance(ProfilerTableEditor); - this._profilerTableEditor.createEditor(new Builder(profilerTableContainer)); + this._profilerTableEditor.createEditor(profilerTableContainer); this._profilerTableEditor.onSelectedRowsChanged((e, args) => { let data = this.input.data.getItem(args.rows[0]); if (data) { @@ -302,7 +302,7 @@ export class ProfilerEditor extends BaseEditor { this._editor = this._instantiationService.createInstance(ProfilerResourceEditor); let editorContainer = document.createElement('div'); editorContainer.className = 'profiler-editor'; - this._editor.create(new Builder(editorContainer)); + this._editor.create(editorContainer); this._editor.setVisible(true); this._editorInput = this._instantiationService.createInstance(UntitledEditorInput, URI.from({ scheme: Schemas.untitled }), false, 'sql', '', ''); this._editor.setInput(this._editorInput, undefined); @@ -410,7 +410,7 @@ export class ProfilerEditor extends BaseEditor { } } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this._container.style.width = dimension.width + 'px'; this._container.style.height = dimension.height + 'px'; this._body.style.width = dimension.width + 'px'; diff --git a/src/sql/parts/profiler/editor/profilerInput.ts b/src/sql/parts/profiler/editor/profilerInput.ts index 4a261f03f7..d9df54032a 100644 --- a/src/sql/parts/profiler/editor/profilerInput.ts +++ b/src/sql/parts/profiler/editor/profilerInput.ts @@ -14,7 +14,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { EditorInput } from 'vs/workbench/common/editor'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { generateUuid } from 'vs/base/common/uuid'; import * as nls from 'vs/nls'; diff --git a/src/sql/parts/profiler/editor/profilerResourceEditor.ts b/src/sql/parts/profiler/editor/profilerResourceEditor.ts index 7a65c74c26..91b70f34a9 100644 --- a/src/sql/parts/profiler/editor/profilerResourceEditor.ts +++ b/src/sql/parts/profiler/editor/profilerResourceEditor.ts @@ -5,7 +5,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import * as nls from 'vs/nls'; -import { Dimension, Builder } from 'vs/base/browser/builder'; +import * as DOM from 'vs/base/browser/dom'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { TPromise } from 'vs/base/common/winjs.base'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; @@ -56,8 +56,8 @@ export class ProfilerResourceEditor extends BaseTextEditor { super(ProfilerResourceEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorGroupService); } - public createEditorControl(parent: Builder, configuration: IEditorOptions): editorCommon.IEditor { - return this.instantiationService.createInstance(ProfilerResourceCodeEditor, parent.getHTMLElement(), configuration); + public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): editorCommon.IEditor { + return this.instantiationService.createInstance(ProfilerResourceCodeEditor, parent, configuration); } protected getConfigurationOverrides(): IEditorOptions { @@ -90,7 +90,7 @@ export class ProfilerResourceEditor extends BaseTextEditor { return nls.localize('profilerTextEditorAriaLabel', 'Profiler editor for event text. Readonly'); } - public layout(dimension: Dimension) { + public layout(dimension: DOM.Dimension) { this.getControl().layout(dimension); } } diff --git a/src/sql/parts/query/common/queryInput.ts b/src/sql/parts/query/common/queryInput.ts index 0ac06c3fb5..b65f959a14 100644 --- a/src/sql/parts/query/common/queryInput.ts +++ b/src/sql/parts/query/common/queryInput.ts @@ -10,7 +10,7 @@ import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorIn import { QueryResultsInput } from 'sql/parts/query/common/queryResultsInput'; import { IQueryModelService } from 'sql/parts/query/execution/queryModel'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { ISelectionData, ExecutionPlanOptions } from 'sqlops'; import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService'; diff --git a/src/sql/parts/query/editor/queryEditor.ts b/src/sql/parts/query/editor/queryEditor.ts index 9febd258bb..29c47890f4 100644 --- a/src/sql/parts/query/editor/queryEditor.ts +++ b/src/sql/parts/query/editor/queryEditor.ts @@ -7,7 +7,6 @@ import 'vs/css!sql/parts/query/editor/media/queryEditor'; import { TPromise } from 'vs/base/common/winjs.base'; import * as strings from 'vs/base/common/strings'; import * as DOM from 'vs/base/browser/dom'; -import { Builder, Dimension, withElementById } from 'vs/base/browser/builder'; import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; @@ -65,7 +64,7 @@ export class QueryEditor extends BaseEditor { private _sash: IFlexibleSash; private _editorTopOffset: number; private _orientation: Orientation; - private _dimension: Dimension; + private _dimension: DOM.Dimension; private _resultsEditor: QueryResultsEditor; private _resultsEditorContainer: HTMLElement; @@ -137,10 +136,10 @@ export class QueryEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { - const parentElement = parent.getHTMLElement(); + public createEditor(parent: HTMLElement): void { + const parentElement = parent; DOM.addClass(parentElement, 'side-by-side-editor'); this._createTaskbar(parentElement); } @@ -244,7 +243,7 @@ export class QueryEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this._dimension = dimension; if (this._sash) { @@ -301,7 +300,7 @@ export class QueryEditor extends BaseEditor { this._createEditor(<QueryResultsInput>input.results, this._resultsEditorContainer) .then(result => { - this._onResultsEditorCreated(<QueryResultsEditor>result, input.results, this.options); + this._onResultsEditorCreated(<any>result, input.results, this.options); this.resultsEditorVisibility = true; this.hideQueryResultsView = false; this._doLayout(true); @@ -571,7 +570,7 @@ export class QueryEditor extends BaseEditor { } let editor = descriptor.instantiate(this._instantiationService); - editor.create(new Builder(container)); + editor.create(container); editor.setVisible(this.isVisible(), this.position); return TPromise.as(editor); } @@ -596,7 +595,7 @@ export class QueryEditor extends BaseEditor { * Appends the HTML for the SQL editor. Creates new HTML every time. */ private _createSqlEditorContainer() { - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); this._sqlEditorContainer = DOM.append(parentElement, DOM.$('.details-editor-container')); this._sqlEditorContainer.style.position = 'absolute'; } @@ -609,7 +608,7 @@ export class QueryEditor extends BaseEditor { private _createResultsEditorContainer() { this._createSash(); - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); let input = <QueryInput>this.input; if (!input.results.container) { @@ -632,7 +631,7 @@ export class QueryEditor extends BaseEditor { */ private _createSash(): void { if (!this._sash) { - let parentElement: HTMLElement = this.getContainer().getHTMLElement(); + let parentElement: HTMLElement = this.getContainer(); if (this._orientation === Orientation.HORIZONTAL) { this._sash = this._register(new HorizontalFlexibleSash(parentElement, this._minEditorSize)); @@ -655,7 +654,7 @@ export class QueryEditor extends BaseEditor { if (this._orientation === Orientation.HORIZONTAL) { this._sash.setDimenesion(this._dimension); } else { - this._sash.setDimenesion(new Dimension(this._dimension.width, this._dimension.height - this.getTaskBarHeight())); + this._sash.setDimenesion(new DOM.Dimension(this._dimension.width, this._dimension.height - this.getTaskBarHeight())); } } @@ -692,13 +691,13 @@ export class QueryEditor extends BaseEditor { private _doLayoutHorizontal(): void { let splitPointTop: number = this._sash.getSplitPoint(); - let parent: ClientRect = this.getContainer().getHTMLElement().getBoundingClientRect(); + let parent: ClientRect = this.getContainer().getBoundingClientRect(); let sqlEditorHeight = splitPointTop - (parent.top + this.getTaskBarHeight()); - let titleBar = withElementById('workbench.parts.titlebar'); + let titleBar = document.getElementById('workbench.parts.titlebar'); if (titleBar) { - sqlEditorHeight += DOM.getContentHeight(titleBar.getHTMLElement()); + sqlEditorHeight += DOM.getContentHeight(titleBar); } let queryResultsEditorHeight = parent.bottom - splitPointTop; @@ -711,13 +710,13 @@ export class QueryEditor extends BaseEditor { this._resultsEditorContainer.style.width = `${this._dimension.width}px`; this._resultsEditorContainer.style.top = `${splitPointTop}px`; - this._sqlEditor.layout(new Dimension(this._dimension.width, sqlEditorHeight)); - this._resultsEditor.layout(new Dimension(this._dimension.width, queryResultsEditorHeight)); + this._sqlEditor.layout(new DOM.Dimension(this._dimension.width, sqlEditorHeight)); + this._resultsEditor.layout(new DOM.Dimension(this._dimension.width, queryResultsEditorHeight)); } private _doLayoutVertical(): void { let splitPointLeft: number = this._sash.getSplitPoint(); - let parent: ClientRect = this.getContainer().getHTMLElement().getBoundingClientRect(); + let parent: ClientRect = this.getContainer().getBoundingClientRect(); let sqlEditorWidth = splitPointLeft; let queryResultsEditorWidth = parent.width - splitPointLeft; @@ -732,8 +731,8 @@ export class QueryEditor extends BaseEditor { this._resultsEditorContainer.style.height = `${this._dimension.height - taskbarHeight}px`; this._resultsEditorContainer.style.left = `${splitPointLeft}px`; - this._sqlEditor.layout(new Dimension(sqlEditorWidth, this._dimension.height - taskbarHeight)); - this._resultsEditor.layout(new Dimension(queryResultsEditorWidth, this._dimension.height - taskbarHeight)); + this._sqlEditor.layout(new DOM.Dimension(sqlEditorWidth, this._dimension.height - taskbarHeight)); + this._resultsEditor.layout(new DOM.Dimension(queryResultsEditorWidth, this._dimension.height - taskbarHeight)); } private _doLayoutSql() { @@ -745,7 +744,7 @@ export class QueryEditor extends BaseEditor { } if (this._dimension) { - this._sqlEditor.layout(new Dimension(this._dimension.width, this._dimension.height - this.getTaskBarHeight())); + this._sqlEditor.layout(new DOM.Dimension(this._dimension.width, this._dimension.height - this.getTaskBarHeight())); } } @@ -769,7 +768,7 @@ export class QueryEditor extends BaseEditor { this._resultsEditor = null; } - let thisEditorParent: HTMLElement = this.getContainer().getHTMLElement(); + let thisEditorParent: HTMLElement = this.getContainer(); if (this._sqlEditorContainer) { let sqlEditorParent: HTMLElement = this._sqlEditorContainer.parentElement; diff --git a/src/sql/parts/query/editor/queryResultsEditor.ts b/src/sql/parts/query/editor/queryResultsEditor.ts index 3fb2e21d38..0b9e7c0a2e 100644 --- a/src/sql/parts/query/editor/queryResultsEditor.ts +++ b/src/sql/parts/query/editor/queryResultsEditor.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, Dimension } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { EditorOptions } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -16,7 +16,7 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { getZoomLevel } from 'vs/base/browser/browser'; import { Configuration } from 'vs/editor/browser/config/configuration'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import * as dom from 'vs/base/browser/dom'; +import * as DOM from 'vs/base/browser/dom'; import * as types from 'vs/base/common/types'; import { QueryResultsInput } from 'sql/parts/query/common/queryResultsInput'; @@ -120,7 +120,7 @@ export class QueryResultsEditor extends BaseEditor { private applySettings() { if (this.input && this.input.container) { if (!this.input.css) { - this.input.css = dom.createStyleSheet(this.input.container); + this.input.css = DOM.createStyleSheet(this.input.container); } let cssRuleText = ''; if (types.isNumber(this._rawOptions.cellPadding)) { @@ -134,10 +134,10 @@ export class QueryResultsEditor extends BaseEditor { } } - createEditor(parent: Builder): void { + createEditor(parent: HTMLElement): void { } - layout(dimension: Dimension): void { + layout(dimension: DOM.Dimension): void { } setInput(input: QueryResultsInput, options: EditorOptions): TPromise<void> { @@ -172,7 +172,7 @@ export class QueryResultsEditor extends BaseEditor { let params: IQueryComponentParams = { dataService: dataService }; this._instantiationService.invokeFunction(bootstrapAngular, QueryOutputModule, - this.getContainer().getHTMLElement(), + this.getContainer(), QUERY_OUTPUT_SELECTOR, params, input); diff --git a/src/sql/parts/query/execution/queryModel.ts b/src/sql/parts/query/execution/queryModel.ts index 089a450830..17f45b83c2 100644 --- a/src/sql/parts/query/execution/queryModel.ts +++ b/src/sql/parts/query/execution/queryModel.ts @@ -7,7 +7,7 @@ import QueryRunner from 'sql/parts/query/execution/queryRunner'; import { DataService } from 'sql/parts/grid/services/dataService'; import { ISlickRange } from 'angular2-slickgrid'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { QueryInput } from 'sql/parts/query/common/queryInput'; import { ISelectionData, diff --git a/src/sql/parts/query/execution/queryModelService.ts b/src/sql/parts/query/execution/queryModelService.ts index 14d521c345..9250ba134c 100644 --- a/src/sql/parts/query/execution/queryModelService.ts +++ b/src/sql/parts/query/execution/queryModelService.ts @@ -21,7 +21,7 @@ import * as nls from 'vs/nls'; import * as statusbar from 'vs/workbench/browser/parts/statusbar/statusbar'; import * as platform from 'vs/platform/registry/common/platform'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import * as strings from 'vs/base/common/strings'; import * as types from 'vs/base/common/types'; diff --git a/src/sql/parts/query/services/queryEditorService.ts b/src/sql/parts/query/services/queryEditorService.ts index 7fd2b81cf5..42298b0dcc 100644 --- a/src/sql/parts/query/services/queryEditorService.ts +++ b/src/sql/parts/query/services/queryEditorService.ts @@ -245,7 +245,7 @@ export class QueryEditorService implements IQueryEditorService { let index: number = group.indexOf(editor.input); let position: Position = editor.position; let options: IQueryEditorOptions = editor.options ? editor.options : {}; - options.index = index; + options = Object.assign(options, { index: index }); options.pinned = group.isPinned(index); // Return a promise that will resovle when the old editor has been replaced by a new editor diff --git a/src/sql/parts/query/views/flexibleSash.ts b/src/sql/parts/query/views/flexibleSash.ts index 081429b045..8db12640d1 100644 --- a/src/sql/parts/query/views/flexibleSash.ts +++ b/src/sql/parts/query/views/flexibleSash.ts @@ -5,9 +5,9 @@ 'use strict'; +import { Dimension } from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; -import { Dimension } from 'vs/base/browser/builder'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider, ISashEvent, Orientation, VSash, Sash } from 'vs/base/browser/ui/sash/sash'; // There is no need to import the sash CSS - 'vs/base/browser/ui/sash/sash' already includes it diff --git a/src/sql/parts/queryPlan/planXmlParser.ts b/src/sql/parts/queryPlan/planXmlParser.ts index 2a86a83142..8d367755d9 100644 --- a/src/sql/parts/queryPlan/planXmlParser.ts +++ b/src/sql/parts/queryPlan/planXmlParser.ts @@ -150,7 +150,7 @@ export class PlanXmlParser { this.doc = this.parser.parseFromString(planXml, 'application/xml'); this.planXml = planXml; - let queryPlanNode = this.findChildren(this.doc.childNodes[0], 'QueryPlan'); + let queryPlanNode = this.findChildren(this.doc.children[0], 'QueryPlan'); if (queryPlanNode && queryPlanNode.length > 0) { this.root = new PlanNode(); let ops = this.createPlanNodes(queryPlanNode[0], 'RelOp', this.root); @@ -192,25 +192,25 @@ export class PlanXmlParser { return list; } - private findChildren(node: Node, elementName: string, untilNode: string = undefined): Node[] { - let nodes: Node[] = []; - if (node === undefined) { + private findChildren(element: Element, elementName: string, untilNode: string = undefined): Element[] { + let elements: Element[] = []; + if (element === undefined) { return undefined; } - for (var index = 0; index < node.childNodes.length; index++) { - if (node.childNodes[index].nodeName.toLocaleLowerCase() === elementName.toLocaleLowerCase()) { - nodes = nodes.concat(node.childNodes[index]); + for (var index = 0; index < element.childNodes.length; index++) { + if (element.childNodes[index].nodeName.toLocaleLowerCase() === elementName.toLocaleLowerCase()) { + elements = elements.concat(element.children[index]); } } - if (nodes.length > 0) { - return nodes; + if (elements.length > 0) { + return elements; } - for (var index = 0; index < node.childNodes.length; index++) { - if (untilNode && node.childNodes[index].nodeName === untilNode) { + for (var index = 0; index < element.childNodes.length; index++) { + if (untilNode && element.childNodes[index].nodeName === untilNode) { continue; } - let result = this.findChildren(node.childNodes[index], elementName, untilNode); + let result = this.findChildren(element.children[index], elementName, untilNode); if (result !== undefined) { return result; } @@ -219,10 +219,10 @@ export class PlanXmlParser { return undefined; } - private createPlanNodes(node: Node, elementName: string, root: PlanNode): PlanNode[] { + private createPlanNodes(element: Element, elementName: string, root: PlanNode): PlanNode[] { let nodePlans: PlanNode[] = []; - let children = this.findChildren(node, elementName); + let children = this.findChildren(element, elementName); if (children) { for (var index = 0; index < children.length; index++) { let childNode = children[index]; @@ -249,38 +249,38 @@ export class PlanXmlParser { return nodePlans; } - private convertToPlanNode(node: Node): PlanNode { + private convertToPlanNode(element: Element): PlanNode { let planNode = new PlanNode(); - planNode.id = this.findAttribute(node.attributes, 'NodeId'); - planNode.logicalOp = this.findAttribute(node.attributes, 'LogicalOp'); - planNode.physicalOp = this.findAttribute(node.attributes, 'PhysicalOp'); - planNode.subtreeCost = +this.findAttribute(node.attributes, 'EstimatedTotalSubtreeCost'); - planNode.estimateRows = this.findAttribute(node.attributes, 'EstimateRows'); - planNode.estimateCpu = this.findAttribute(node.attributes, 'EstimateCPU'); - planNode.estimateIo = this.findAttribute(node.attributes, 'EstimateIO'); - planNode.estimateRebinds = this.findAttribute(node.attributes, 'EstimateRebinds'); - planNode.estimateRewinds = this.findAttribute(node.attributes, 'EstimateRewinds'); - planNode.parallel = this.findAttribute(node.attributes, 'Parallel') === '1'; - planNode.partitioned = this.findAttribute(node.attributes, 'Partitioned') === '1'; + planNode.id = this.findAttribute(element.attributes, 'NodeId'); + planNode.logicalOp = this.findAttribute(element.attributes, 'LogicalOp'); + planNode.physicalOp = this.findAttribute(element.attributes, 'PhysicalOp'); + planNode.subtreeCost = +this.findAttribute(element.attributes, 'EstimatedTotalSubtreeCost'); + planNode.estimateRows = this.findAttribute(element.attributes, 'EstimateRows'); + planNode.estimateCpu = this.findAttribute(element.attributes, 'EstimateCPU'); + planNode.estimateIo = this.findAttribute(element.attributes, 'EstimateIO'); + planNode.estimateRebinds = this.findAttribute(element.attributes, 'EstimateRebinds'); + planNode.estimateRewinds = this.findAttribute(element.attributes, 'EstimateRewinds'); + planNode.parallel = this.findAttribute(element.attributes, 'Parallel') === '1'; + planNode.partitioned = this.findAttribute(element.attributes, 'Partitioned') === '1'; return planNode; } - private convertToRuntimeInfo(node: Node): RuntimePerThread { + private convertToRuntimeInfo(element: Element): RuntimePerThread { let runtimeNode = new RuntimePerThread(); - runtimeNode.actualExecutionMode = this.findAttribute(node.attributes, 'ActualExecutionMode'); - runtimeNode.actualExecutions = +this.findAttribute(node.attributes, 'ActualExecutions'); - runtimeNode.actualRow = +this.findAttribute(node.attributes, 'ActualRows'); - runtimeNode.threadId = +this.findAttribute(node.attributes, 'Thread'); + runtimeNode.actualExecutionMode = this.findAttribute(element.attributes, 'ActualExecutionMode'); + runtimeNode.actualExecutions = +this.findAttribute(element.attributes, 'ActualExecutions'); + runtimeNode.actualRow = +this.findAttribute(element.attributes, 'ActualRows'); + runtimeNode.threadId = +this.findAttribute(element.attributes, 'Thread'); return runtimeNode; } - private convertToObject(node: Node): IndexObject { + private convertToObject(element: Element): IndexObject { let objectNode = new IndexObject(); - objectNode.database = this.findAttribute(node.attributes, 'Database'); - objectNode.index = this.findAttribute(node.attributes, 'Index'); - objectNode.indexKind = this.findAttribute(node.attributes, 'IndexKind'); - objectNode.schema = this.findAttribute(node.attributes, 'Schema'); - objectNode.table = this.findAttribute(node.attributes, 'Table'); + objectNode.database = this.findAttribute(element.attributes, 'Database'); + objectNode.index = this.findAttribute(element.attributes, 'Index'); + objectNode.indexKind = this.findAttribute(element.attributes, 'IndexKind'); + objectNode.schema = this.findAttribute(element.attributes, 'Schema'); + objectNode.table = this.findAttribute(element.attributes, 'Table'); return objectNode; } diff --git a/src/sql/parts/queryPlan/queryPlanEditor.ts b/src/sql/parts/queryPlan/queryPlanEditor.ts index 7a28acfaa3..bc9972f9bb 100644 --- a/src/sql/parts/queryPlan/queryPlanEditor.ts +++ b/src/sql/parts/queryPlan/queryPlanEditor.ts @@ -6,7 +6,6 @@ import 'vs/css!sql/parts/query/editor/media/queryEditor'; import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -41,11 +40,11 @@ export class QueryPlanEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { //Enable scrollbars when drawing area is larger than viewport - parent.overflow('auto'); + parent.style.overflow = 'auto'; //Set background of parent to white (same as .qp-root from src\sql\parts\grid\load\css\qp.css) //This is because the bottom-most tooltips can extend past the drawing area, which causes the //scrolling area to have gaps on the bottom and left. So if the colors aren't matched then @@ -54,7 +53,7 @@ export class QueryPlanEditor extends BaseEditor { //during the load - but changing the background color was the simplest and least error prone //(plus it's probable that we won't be using this control in the future anyways if development) //continues on the Query plan feature - parent.background('#fff'); + parent.style.background = '#fff'; } /** @@ -67,7 +66,7 @@ export class QueryPlanEditor extends BaseEditor { * Updates the internal variable keeping track of the editor's size, and re-calculates the sash position. * To be called when the container of this editor changes size. */ - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { } public setInput(input: QueryPlanInput, options: EditorOptions): TPromise<void> { @@ -78,7 +77,7 @@ export class QueryPlanEditor extends BaseEditor { if (!input.hasInitialized) { this.bootstrapAngular(input); } - this.revealElementWithTagName(input.uniqueSelector, this.getContainer().getHTMLElement()); + this.revealElementWithTagName(input.uniqueSelector, this.getContainer()); return super.setInput(input, options); } @@ -114,7 +113,7 @@ export class QueryPlanEditor extends BaseEditor { let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular, QueryPlanModule, - this.getContainer().getHTMLElement(), + this.getContainer(), QUERYPLAN_SELECTOR, params); input.setUniqueSelector(uniqueSelector); diff --git a/src/sql/parts/taskHistory/common/taskService.ts b/src/sql/parts/taskHistory/common/taskService.ts index 67e62bbcb2..01f9460cd6 100644 --- a/src/sql/parts/taskHistory/common/taskService.ts +++ b/src/sql/parts/taskHistory/common/taskService.ts @@ -8,12 +8,12 @@ import * as sqlops from 'sqlops'; import { TaskNode, TaskStatus, TaskExecutionMode } from 'sql/parts/taskHistory/common/taskNode'; import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { localize } from 'vs/nls'; import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export const SERVICE_ID = 'taskHistoryService'; export const ITaskService = createDecorator<ITaskService>(SERVICE_ID); @@ -51,7 +51,7 @@ export class TaskService implements ITaskService { constructor( @ILifecycleService lifecycleService: ILifecycleService, - @IChoiceService private choiceService: IChoiceService, + @IDialogService private dialogService: IDialogService, @IQueryEditorService private queryEditorService: IQueryEditorService ) { this._taskQueue = new TaskNode('Root', undefined, undefined); @@ -134,7 +134,7 @@ export class TaskService implements ITaskService { return new TPromise<boolean>((resolve, reject) => { let numOfInprogressTasks = this.getNumberOfInProgressTasks(); if (numOfInprogressTasks > 0) { - this.choiceService.choose(Severity.Warning, message, options, 0, false).done(choice => { + this.dialogService.show(Severity.Warning, message, options).done(choice => { switch (choice) { case 0: let timeoutId: number; diff --git a/src/sql/parts/taskHistory/viewlet/taskHistoryController.ts b/src/sql/parts/taskHistory/viewlet/taskHistoryController.ts index 57a7f2afb9..dce22e4845 100644 --- a/src/sql/parts/taskHistory/viewlet/taskHistoryController.ts +++ b/src/sql/parts/taskHistory/viewlet/taskHistoryController.ts @@ -73,7 +73,7 @@ export class TaskHistoryController extends treedefaults.DefaultController { getKeyBinding: (action) => this.keybindingService.lookupKeybinding(action.id), onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, getActionsContext: () => (element) diff --git a/src/sql/parts/taskHistory/viewlet/taskHistoryView.ts b/src/sql/parts/taskHistory/viewlet/taskHistoryView.ts index 480415cede..1c2fc7f5d2 100644 --- a/src/sql/parts/taskHistory/viewlet/taskHistoryView.ts +++ b/src/sql/parts/taskHistory/viewlet/taskHistoryView.ts @@ -107,7 +107,7 @@ export class TaskHistoryView { let targetsToExpand: any[]; // Focus - this._tree.DOMFocus(); + this._tree.domFocus(); if (this._tree) { let selection = this._tree.getSelection(); diff --git a/src/sql/parts/taskHistory/viewlet/taskHistoryViewlet.ts b/src/sql/parts/taskHistory/viewlet/taskHistoryViewlet.ts index 7b450dce68..4667432e65 100644 --- a/src/sql/parts/taskHistory/viewlet/taskHistoryViewlet.ts +++ b/src/sql/parts/taskHistory/viewlet/taskHistoryViewlet.ts @@ -7,10 +7,9 @@ import 'vs/css!sql/media/icons/common-icons'; import 'vs/css!./media/taskHistoryViewlet'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, Dimension } from 'vs/base/browser/builder'; import { Viewlet } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { toggleClass } from 'vs/base/browser/dom'; +import { toggleClass, Dimension } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -52,11 +51,11 @@ export class TaskHistoryViewlet extends Viewlet { }); } - public create(parent: Builder): TPromise<void> { + public create(parent: HTMLElement): TPromise<void> { super.create(parent); - this._root = parent.getHTMLElement(); + this._root = parent; this._taskHistoryView = this._instantiationService.createInstance(TaskHistoryView); - this._taskHistoryView.renderBody(parent.getHTMLElement()); + this._taskHistoryView.renderBody(parent); return TPromise.as(null); } diff --git a/src/sql/parts/tasks/dialog/taskDialogEditor.ts b/src/sql/parts/tasks/dialog/taskDialogEditor.ts index 37abbbbb49..434f59969b 100644 --- a/src/sql/parts/tasks/dialog/taskDialogEditor.ts +++ b/src/sql/parts/tasks/dialog/taskDialogEditor.ts @@ -6,7 +6,7 @@ import 'vs/css!sql/parts/query/editor/media/queryEditor'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder } from 'vs/base/browser/builder'; +import { Dimension } from 'vs/base/browser/dom'; import { EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -32,9 +32,9 @@ export class TaskDialogEditor extends BaseEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent element. */ - public createEditor(parent: Builder): void { + public createEditor(parent: HTMLElement): void { } /** @@ -58,7 +58,7 @@ export class TaskDialogEditor extends BaseEditor { if (!input.hasInitialized) { this.bootstrapAngular(input); } - this.revealElementWithTagName(input.uniqueSelector, this.getContainer().getHTMLElement()); + this.revealElementWithTagName(input.uniqueSelector, this.getContainer()); return super.setInput(input, options); } @@ -94,7 +94,7 @@ export class TaskDialogEditor extends BaseEditor { }; let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular, TaskDialogModule, - this.getContainer().getHTMLElement(), + this.getContainer(), TASKDIALOG_SELECTOR, params); input.setUniqueSelector(uniqueSelector); diff --git a/src/sql/platform/dialog/dialogContainer.component.ts b/src/sql/platform/dialog/dialogContainer.component.ts index 479f28bc15..68716c2130 100644 --- a/src/sql/platform/dialog/dialogContainer.component.ts +++ b/src/sql/platform/dialog/dialogContainer.component.ts @@ -9,7 +9,7 @@ import 'vs/css!./media/dialogModal'; import { Component, AfterContentInit, ViewChild, Input, Inject, forwardRef, ElementRef } from '@angular/core'; import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component'; import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ComponentEventType } from '../../parts/modelComponents/interfaces'; export interface DialogComponentParams extends IBootstrapParams { diff --git a/src/sql/platform/dialog/dialogModal.ts b/src/sql/platform/dialog/dialogModal.ts index 50e2972153..3633dabf97 100644 --- a/src/sql/platform/dialog/dialogModal.ts +++ b/src/sql/platform/dialog/dialogModal.ts @@ -21,7 +21,7 @@ import { attachButtonStyler } from 'vs/platform/theme/common/styler'; import { Button } from 'vs/base/browser/ui/button/button'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { localize } from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Emitter } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/sql/platform/dialog/dialogPane.ts b/src/sql/platform/dialog/dialogPane.ts index 026f882fae..1994e8afda 100644 --- a/src/sql/platform/dialog/dialogPane.ts +++ b/src/sql/platform/dialog/dialogPane.ts @@ -17,10 +17,10 @@ import { DialogModule } from 'sql/platform/dialog/dialog.module'; import { DialogComponentParams } from 'sql/platform/dialog/dialogContainer.component'; import * as DOM from 'vs/base/browser/dom'; -import { Builder, Dimension } from 'vs/base/browser/builder'; +import { Builder } from 'vs/base/browser/builder'; import { IThemable } from 'vs/platform/theme/common/styler'; import { Disposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; export class DialogPane extends Disposable implements IThemable { @@ -82,7 +82,7 @@ export class DialogPane extends Disposable implements IThemable { } public layout(): void { - this._tabbedPanel.layout(new Dimension(DOM.getContentWidth(this._body), DOM.getContentHeight(this._body))); + this._tabbedPanel.layout(new DOM.Dimension(DOM.getContentWidth(this._body), DOM.getContentHeight(this._body))); } /** diff --git a/src/sql/platform/dialog/dialogTypes.ts b/src/sql/platform/dialog/dialogTypes.ts index 33f59ea0d8..e60d8ade58 100644 --- a/src/sql/platform/dialog/dialogTypes.ts +++ b/src/sql/platform/dialog/dialogTypes.ts @@ -7,7 +7,7 @@ import * as sqlops from 'sqlops'; import { localize } from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export class ModelViewPane { private _valid: boolean = true; @@ -99,7 +99,7 @@ export class DialogButton implements sqlops.window.modelviewdialog.Button { /** * Register an event that notifies the button that it has been clicked */ - public registerClickEvent(clickEvent: Event<void>): void { + public registerClickEvent(clickEvent: Event<any>): void { clickEvent(() => this._onClick.fire()); } } diff --git a/src/sql/platform/tasks/common/tasks.ts b/src/sql/platform/tasks/common/tasks.ts index 0ac784f7fe..b92445f092 100644 --- a/src/sql/platform/tasks/common/tasks.ts +++ b/src/sql/platform/tasks/common/tasks.ts @@ -12,7 +12,7 @@ import { Action } from 'vs/base/common/actions'; import { IConstructorSignature3, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import * as nls from 'vs/nls'; import { ILocalizedString, IMenuItem, MenuRegistry, ICommandAction } from 'vs/platform/actions/common/actions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { LinkedList } from 'vs/base/common/linkedList'; diff --git a/src/sql/services/accountManagement/accountManagementService.ts b/src/sql/services/accountManagement/accountManagementService.ts index 017a43c02a..53bfe884c1 100644 --- a/src/sql/services/accountManagement/accountManagementService.ts +++ b/src/sql/services/accountManagement/accountManagementService.ts @@ -10,7 +10,7 @@ import * as nls from 'vs/nls'; import * as platform from 'vs/platform/registry/common/platform'; import * as statusbar from 'vs/workbench/browser/parts/statusbar/statusbar'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { Memento, Scope as MementoScope } from 'vs/workbench/common/memento'; diff --git a/src/sql/services/accountManagement/interfaces.ts b/src/sql/services/accountManagement/interfaces.ts index b2b5e00d8e..b965f64dbd 100644 --- a/src/sql/services/accountManagement/interfaces.ts +++ b/src/sql/services/accountManagement/interfaces.ts @@ -6,7 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { AccountAdditionResult, AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/sql/services/capabilities/capabilitiesService.ts b/src/sql/services/capabilities/capabilitiesService.ts index 21db808cbf..7db1917b17 100644 --- a/src/sql/services/capabilities/capabilitiesService.ts +++ b/src/sql/services/capabilities/capabilitiesService.ts @@ -13,7 +13,7 @@ import { toObject } from 'sql/base/common/map'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IAction } from 'vs/base/common/actions'; import { Memento } from 'vs/workbench/common/memento'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/sql/services/dashboard/common/dashboardService.ts b/src/sql/services/dashboard/common/dashboardService.ts index 936a72434c..efe786e788 100644 --- a/src/sql/services/dashboard/common/dashboardService.ts +++ b/src/sql/services/dashboard/common/dashboardService.ts @@ -5,7 +5,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; diff --git a/src/sql/services/dashboard/common/dashboardServiceImpl.ts b/src/sql/services/dashboard/common/dashboardServiceImpl.ts index 75a2d6e9fd..1b1d00a933 100644 --- a/src/sql/services/dashboard/common/dashboardServiceImpl.ts +++ b/src/sql/services/dashboard/common/dashboardServiceImpl.ts @@ -6,7 +6,7 @@ import { IDashboardService } from './dashboardService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; diff --git a/src/sql/services/dashboard/common/dashboardViewService.ts b/src/sql/services/dashboard/common/dashboardViewService.ts index fd42c382ac..eb0ad98735 100644 --- a/src/sql/services/dashboard/common/dashboardViewService.ts +++ b/src/sql/services/dashboard/common/dashboardViewService.ts @@ -6,7 +6,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import { IItemConfig, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes'; diff --git a/src/sql/services/dashboard/common/dashboardViewServiceImpl.ts b/src/sql/services/dashboard/common/dashboardViewServiceImpl.ts index 3da1f0f1fd..d8920e00e5 100644 --- a/src/sql/services/dashboard/common/dashboardViewServiceImpl.ts +++ b/src/sql/services/dashboard/common/dashboardViewServiceImpl.ts @@ -6,7 +6,7 @@ 'use strict'; import { IDashboardViewService, IDashboardWebview } from 'sql/services/dashboard/common/dashboardViewService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IModelView } from 'sql/services/model/modelViewService'; export class DashboardViewService implements IDashboardViewService { diff --git a/src/sql/services/model/modelViewService.ts b/src/sql/services/model/modelViewService.ts index c74b96236b..d4c21e83e3 100644 --- a/src/sql/services/model/modelViewService.ts +++ b/src/sql/services/model/modelViewService.ts @@ -6,7 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; import { IItemConfig, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface IView { readonly id: string; diff --git a/src/sql/services/modelComponents/modelViewService.ts b/src/sql/services/modelComponents/modelViewService.ts index 44d8c5f5e5..8fc4e5a162 100644 --- a/src/sql/services/modelComponents/modelViewService.ts +++ b/src/sql/services/modelComponents/modelViewService.ts @@ -6,7 +6,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; import { IItemConfig, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes'; diff --git a/src/sql/services/modelComponents/modelViewServiceImpl.ts b/src/sql/services/modelComponents/modelViewServiceImpl.ts index 21cfb07631..62648056f4 100644 --- a/src/sql/services/modelComponents/modelViewServiceImpl.ts +++ b/src/sql/services/modelComponents/modelViewServiceImpl.ts @@ -6,7 +6,7 @@ 'use strict'; import { IModelViewService } from 'sql/services/modelComponents/modelViewService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IModelView } from 'sql/services/model/modelViewService'; export class ModelViewService implements IModelViewService { diff --git a/src/sql/workbench/api/node/extHostDashboard.ts b/src/sql/workbench/api/node/extHostDashboard.ts index 0254cbc747..b1ebd740a0 100644 --- a/src/sql/workbench/api/node/extHostDashboard.ts +++ b/src/sql/workbench/api/node/extHostDashboard.ts @@ -5,7 +5,7 @@ 'use strict'; import { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as sqlops from 'sqlops'; diff --git a/src/sql/workbench/api/node/extHostDataProtocol.ts b/src/sql/workbench/api/node/extHostDataProtocol.ts index 7c7e9527ac..13eb89c295 100644 --- a/src/sql/workbench/api/node/extHostDataProtocol.ts +++ b/src/sql/workbench/api/node/extHostDataProtocol.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; import { Disposable } from 'vs/workbench/api/node/extHostTypes'; import { SqlMainContext, MainThreadDataProtocolShape, ExtHostDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol'; diff --git a/src/sql/workbench/api/node/extHostModelViewDialog.ts b/src/sql/workbench/api/node/extHostModelViewDialog.ts index 9ecfa71895..c351c349de 100644 --- a/src/sql/workbench/api/node/extHostModelViewDialog.ts +++ b/src/sql/workbench/api/node/extHostModelViewDialog.ts @@ -5,7 +5,7 @@ 'use strict'; import { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { deepClone } from 'vs/base/common/objects'; import * as nls from 'vs/nls'; diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index 81b8f13738..88750b69ae 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -21,7 +21,7 @@ import { IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails, IModelViewWizardDetails, IModelViewWizardPageDetails } from 'sql/workbench/api/common/sqlExtHostTypes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export abstract class ExtHostAccountManagementShape { $autoOAuthCancelled(handle: number): Thenable<void> { throw ni(); } diff --git a/src/sql/workbench/errorMessageDialog/errorMessageDialog.ts b/src/sql/workbench/errorMessageDialog/errorMessageDialog.ts index 8eecda50cf..db7bf4f8ce 100644 --- a/src/sql/workbench/errorMessageDialog/errorMessageDialog.ts +++ b/src/sql/workbench/errorMessageDialog/errorMessageDialog.ts @@ -16,7 +16,7 @@ import Severity from 'vs/base/common/severity'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; diff --git a/src/sql/workbench/parts/connection/common/connectionProviderExtension.ts b/src/sql/workbench/parts/connection/common/connectionProviderExtension.ts index 95ef47463a..7fa67880b9 100644 --- a/src/sql/workbench/parts/connection/common/connectionProviderExtension.ts +++ b/src/sql/workbench/parts/connection/common/connectionProviderExtension.ts @@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionPointUser, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { localize } from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { deepClone } from 'vs/base/common/objects'; import * as sqlops from 'sqlops'; diff --git a/src/sql/workbench/update/releaseNotes.ts b/src/sql/workbench/update/releaseNotes.ts index bcb9ab6d12..72dd258154 100644 --- a/src/sql/workbench/update/releaseNotes.ts +++ b/src/sql/workbench/update/releaseNotes.ts @@ -12,12 +12,11 @@ import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import URI from 'vs/base/common/uri'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { AbstractShowReleaseNotesAction, loadReleaseNotes } from 'vs/workbench/parts/update/electron-browser/update'; +import { AbstractShowReleaseNotesAction } from 'vs/workbench/parts/update/electron-browser/update'; import { INotification, INotificationService, INotificationActions } from 'vs/platform/notification/common/notification'; import Severity from 'vs/base/common/severity'; @@ -43,9 +42,8 @@ export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesActio constructor( id = ShowCurrentReleaseNotesAction.ID, label = ShowCurrentReleaseNotesAction.LABEL, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IInstantiationService instantiationService: IInstantiationService ) { - super(id, label, pkg.version, editorService, instantiationService); + super(id, label, pkg.version, instantiationService); } } diff --git a/src/sqltest/parts/connection/objectExplorerService.test.ts b/src/sqltest/parts/connection/objectExplorerService.test.ts index 595670f8c2..81e6cceaf4 100644 --- a/src/sqltest/parts/connection/objectExplorerService.test.ts +++ b/src/sqltest/parts/connection/objectExplorerService.test.ts @@ -18,7 +18,7 @@ import * as TypeMoq from 'typemoq'; import * as assert from 'assert'; import { ServerTreeView } from 'sql/parts/objectExplorer/viewlet/serverTreeView'; import { ConnectionOptionSpecialType, ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { CapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService'; diff --git a/src/sqltest/parts/query/editor/queryEditor.test.ts b/src/sqltest/parts/query/editor/queryEditor.test.ts index acf425c4f3..28fa89e84e 100644 --- a/src/sqltest/parts/query/editor/queryEditor.test.ts +++ b/src/sqltest/parts/query/editor/queryEditor.test.ts @@ -31,7 +31,7 @@ import * as assert from 'assert'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { INotification, INotificationService } from 'vs/platform/notification/common/notification'; -import { TestNotificationService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; suite('SQL QueryEditor Tests', () => { let queryModelService: QueryModelService; @@ -140,7 +140,7 @@ suite('SQL QueryEditor Tests', () => { test('createEditor creates only the taskbar', (done) => { // If I call createEditor let editor: QueryEditor = getQueryEditor(); - editor.createEditor(parentBuilder); + editor.createEditor(parentBuilder.getHTMLElement()); // The taskbar should be created assert.equal(!!editor.taskbar, true); diff --git a/src/sqltest/stubs/accountManagementStubs.ts b/src/sqltest/stubs/accountManagementStubs.ts index 4bfaa1a492..c30cfb639b 100644 --- a/src/sqltest/stubs/accountManagementStubs.ts +++ b/src/sqltest/stubs/accountManagementStubs.ts @@ -6,7 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; import { TPromise } from 'vs/base/common/winjs.base'; diff --git a/src/sqltest/stubs/capabilitiesTestService.ts b/src/sqltest/stubs/capabilitiesTestService.ts index c9c7b6803c..5a8d2c0635 100644 --- a/src/sqltest/stubs/capabilitiesTestService.ts +++ b/src/sqltest/stubs/capabilitiesTestService.ts @@ -9,7 +9,7 @@ import { ConnectionManagementInfo } from 'sql/parts/connection/common/connection import { ICapabilitiesService, clientCapabilities, ProviderFeatures } from 'sql/services/capabilities/capabilitiesService'; import { ConnectionOptionSpecialType, ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Action } from 'vs/base/common/actions'; export class CapabilitiesTestService implements ICapabilitiesService { diff --git a/src/sqltest/stubs/connectionManagementService.test.ts b/src/sqltest/stubs/connectionManagementService.test.ts index 0d9a09ec78..069bdc7645 100644 --- a/src/sqltest/stubs/connectionManagementService.test.ts +++ b/src/sqltest/stubs/connectionManagementService.test.ts @@ -10,7 +10,7 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile'; import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo'; import * as sqlops from 'sqlops'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; // Test stubs for commonly used objects diff --git a/src/sqltest/stubs/contextKeyServiceStub.ts b/src/sqltest/stubs/contextKeyServiceStub.ts index fd4889044b..b221d1dd84 100644 --- a/src/sqltest/stubs/contextKeyServiceStub.ts +++ b/src/sqltest/stubs/contextKeyServiceStub.ts @@ -5,7 +5,7 @@ import { IContextKeyService, IContextKeyServiceTarget, IContextKey, ContextKeyExpr, IContext, IContextKeyChangeEvent } from 'vs/platform/contextkey/common/contextkey'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export class ContextKeyServiceStub implements IContextKeyService { _serviceBrand: any; diff --git a/src/sqltest/stubs/editorGroupService.ts b/src/sqltest/stubs/editorGroupService.ts index 4679d870c8..1ac98cd6df 100644 --- a/src/sqltest/stubs/editorGroupService.ts +++ b/src/sqltest/stubs/editorGroupService.ts @@ -8,7 +8,7 @@ import { ServiceIdentifier, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Position, IEditorInput } from 'vs/platform/editor/common/editor'; import { IEditorStacksModel, IEditorGroup, EditorInput, IEditorOpeningEvent } from 'vs/workbench/common/editor'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IEditorTabOptions, GroupArrangement, GroupOrientation, IEditorGroupService, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; diff --git a/src/sqltest/stubs/workspaceConfigurationTestService.ts b/src/sqltest/stubs/workspaceConfigurationTestService.ts index 72ced7c311..d603108d1d 100644 --- a/src/sqltest/stubs/workspaceConfigurationTestService.ts +++ b/src/sqltest/stubs/workspaceConfigurationTestService.ts @@ -10,7 +10,7 @@ import { IConfigurationValue } from 'vs/workbench/services/configuration/node/co import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; export class WorkspaceConfigurationTestService implements IWorkspaceConfigurationService { diff --git a/src/tsconfig.json b/src/tsconfig.json index e251d5f45f..ae23a80100 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -10,6 +10,9 @@ "experimentalDecorators": true, "declaration": true, "noImplicitReturns": true, + "noUnusedLocals": false, + "noImplicitThis": true, + "alwaysStrict": true, "baseUrl": ".", "outDir": "../out", "typeRoots": [ diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index ce604fb1bf..daf41dbc73 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -507,7 +507,7 @@ declare namespace Electron { * and macOS, icons depend on the application associated with file mime type. */ getFileIcon(path: string, callback: (error: Error, icon: NativeImage) => void): void; - getGpuFeatureStatus(): GPUFeatureStatus; + getGPUFeatureStatus(): GPUFeatureStatus; getJumpListSettings(): JumpListSettings; /** * Note: When distributing your packaged app, you have to also ship the locales diff --git a/src/typings/gc-signals.d.ts b/src/typings/gc-signals.d.ts index be8992af28..15af041177 100644 --- a/src/typings/gc-signals.d.ts +++ b/src/typings/gc-signals.d.ts @@ -6,7 +6,7 @@ declare module 'gc-signals' { * value is stored for later consumption. */ export const GCSignal: { - new (id: number): GCSignal; + new(id: number): GCSignal; }; /** * Consume ids of garbage collected signals. diff --git a/src/typings/globals/core-js/index.d.ts b/src/typings/globals/core-js/index.d.ts index d878dae79a..4d157729c4 100644 --- a/src/typings/globals/core-js/index.d.ts +++ b/src/typings/globals/core-js/index.d.ts @@ -483,7 +483,7 @@ interface SymbolConstructor { * A method that returns the default iterator for an object. Called by the semantics of the * for-of statement. */ - iterator: symbol; + readonly iterator: symbol; /** * A regular expression method that matches the regular expression against a string. Called diff --git a/src/typings/keytar.d.ts b/src/typings/keytar.d.ts index be122b71ea..e881644eb8 100644 --- a/src/typings/keytar.d.ts +++ b/src/typings/keytar.d.ts @@ -5,44 +5,44 @@ declare module 'keytar' { -/** - * Get the stored password for the service and account. - * - * @param service The string service name. - * @param account The string account name. - * - * @returns A promise for the password string. - */ -export function getPassword(service: string, account: string): Promise<string | null>; + /** + * Get the stored password for the service and account. + * + * @param service The string service name. + * @param account The string account name. + * + * @returns A promise for the password string. + */ + export function getPassword(service: string, account: string): Promise<string | null>; -/** - * Add the password for the service and account to the keychain. - * - * @param service The string service name. - * @param account The string account name. - * @param password The string password. - * - * @returns A promise for the set password completion. - */ -export function setPassword(service: string, account: string, password: string): Promise<void>; + /** + * Add the password for the service and account to the keychain. + * + * @param service The string service name. + * @param account The string account name. + * @param password The string password. + * + * @returns A promise for the set password completion. + */ + export function setPassword(service: string, account: string, password: string): Promise<void>; -/** - * Delete the stored password for the service and account. - * - * @param service The string service name. - * @param account The string account name. - * - * @returns A promise for the deletion status. True on success. - */ -export function deletePassword(service: string, account: string): Promise<boolean>; + /** + * Delete the stored password for the service and account. + * + * @param service The string service name. + * @param account The string account name. + * + * @returns A promise for the deletion status. True on success. + */ + export function deletePassword(service: string, account: string): Promise<boolean>; -/** - * Find a password for the service in the keychain. - * - * @param service The string service name. - * - * @returns A promise for the password string. - */ -export function findPassword(service: string): Promise<string | null>; + /** + * Find a password for the service in the keychain. + * + * @param service The string service name. + * + * @returns A promise for the password string. + */ + export function findPassword(service: string): Promise<string | null>; } \ No newline at end of file diff --git a/src/typings/mocha.d.ts b/src/typings/mocha.d.ts index e4bddbd49b..dfc3367cec 100644 --- a/src/typings/mocha.d.ts +++ b/src/typings/mocha.d.ts @@ -4,29 +4,29 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped interface MochaSetupOptions { - //milliseconds to wait before considering a test slow - slow?: number; + //milliseconds to wait before considering a test slow + slow?: number; - // timeout in milliseconds - timeout?: number; + // timeout in milliseconds + timeout?: number; - // ui name "bdd", "tdd", "exports" etc - ui?: string; + // ui name "bdd", "tdd", "exports" etc + ui?: string; - //array of accepted globals - globals?: any[]; + //array of accepted globals + globals?: any[]; - // reporter instance (function or string), defaults to `mocha.reporters.Spec` - reporter?: any; + // reporter instance (function or string), defaults to `mocha.reporters.Spec` + reporter?: any; - // bail on the first test failure - bail?: boolean; + // bail on the first test failure + bail?: boolean; - // ignore global leaks - ignoreLeaks?: boolean; + // ignore global leaks + ignoreLeaks?: boolean; - // grep string or regexp to filter tests with - grep?: any; + // grep string or regexp to filter tests with + grep?: any; } declare var mocha: Mocha; @@ -46,7 +46,7 @@ declare var specify: Mocha.ITestDefinition; declare function run(): void; interface MochaDone { - (error?: any): any; + (error?: any): any; } declare function setup(callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => any): void; @@ -63,172 +63,172 @@ declare function afterEach(callback: (this: Mocha.IBeforeAndAfterContext, done: declare function afterEach(description: string, callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => any): void; declare class Mocha { - currentTest: Mocha.ITestDefinition; - constructor(options?: { - grep?: RegExp; - ui?: string; - reporter?: string; - timeout?: number; - reporterOptions?: any; - slow?: number; - bail?: boolean; - }); + currentTest: Mocha.ITestDefinition; + constructor(options?: { + grep?: RegExp; + ui?: string; + reporter?: string; + timeout?: number; + reporterOptions?: any; + slow?: number; + bail?: boolean; + }); - /** Setup mocha with the given options. */ - setup(options: MochaSetupOptions): Mocha; - bail(value?: boolean): Mocha; - addFile(file: string): Mocha; - /** Sets reporter by name, defaults to "spec". */ - reporter(name: string): Mocha; - /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ - reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha; - ui(value: string): Mocha; - grep(value: string): Mocha; - grep(value: RegExp): Mocha; - invert(): Mocha; - ignoreLeaks(value: boolean): Mocha; - checkLeaks(): Mocha; + /** Setup mocha with the given options. */ + setup(options: MochaSetupOptions): Mocha; + bail(value?: boolean): Mocha; + addFile(file: string): Mocha; + /** Sets reporter by name, defaults to "spec". */ + reporter(name: string): Mocha; + /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ + reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha; + ui(value: string): Mocha; + grep(value: string): Mocha; + grep(value: RegExp): Mocha; + invert(): Mocha; + ignoreLeaks(value: boolean): Mocha; + checkLeaks(): Mocha; /** * Function to allow assertion libraries to throw errors directly into mocha. * This is useful when running tests in a browser because window.onerror will * only receive the 'message' attribute of the Error. */ - throwError(error: Error): void; - /** Enables growl support. */ - growl(): Mocha; - globals(value: string): Mocha; - globals(values: string[]): Mocha; - useColors(value: boolean): Mocha; - useInlineDiffs(value: boolean): Mocha; - timeout(value: number): Mocha; - slow(value: number): Mocha; - enableTimeouts(value: boolean): Mocha; - asyncOnly(value: boolean): Mocha; - noHighlighting(value: boolean): Mocha; - /** Runs tests and invokes `onComplete()` when finished. */ - run(onComplete?: (failures: number) => void): Mocha.IRunner; + throwError(error: Error): void; + /** Enables growl support. */ + growl(): Mocha; + globals(value: string): Mocha; + globals(values: string[]): Mocha; + useColors(value: boolean): Mocha; + useInlineDiffs(value: boolean): Mocha; + timeout(value: number): Mocha; + slow(value: number): Mocha; + enableTimeouts(value: boolean): Mocha; + asyncOnly(value: boolean): Mocha; + noHighlighting(value: boolean): Mocha; + /** Runs tests and invokes `onComplete()` when finished. */ + run(onComplete?: (failures: number) => void): Mocha.IRunner; } // merge the Mocha class declaration with a module declare namespace Mocha { - interface ISuiteCallbackContext { - timeout(ms: number): this; - retries(n: number): this; - slow(ms: number): this; - } + interface ISuiteCallbackContext { + timeout(ms: number): this; + retries(n: number): this; + slow(ms: number): this; + } - interface IHookCallbackContext { - skip(): this; - timeout(ms: number): this; - [index: string]: any; - } + interface IHookCallbackContext { + skip(): this; + timeout(ms: number): this; + [index: string]: any; + } - interface ITestCallbackContext { - skip(): this; - timeout(ms: number): this; - retries(n: number): this; - slow(ms: number): this; - [index: string]: any; - } + interface ITestCallbackContext { + skip(): this; + timeout(ms: number): this; + retries(n: number): this; + slow(ms: number): this; + [index: string]: any; + } - /** Partial interface for Mocha's `Runnable` class. */ - interface IRunnable { - title: string; - fn: Function; - async: boolean; - sync: boolean; - timedOut: boolean; - timeout(n: number): this; - } + /** Partial interface for Mocha's `Runnable` class. */ + interface IRunnable { + title: string; + fn: Function; + async: boolean; + sync: boolean; + timedOut: boolean; + timeout(n: number): this; + } - /** Partial interface for Mocha's `Suite` class. */ - interface ISuite { - parent: ISuite; - title: string; + /** Partial interface for Mocha's `Suite` class. */ + interface ISuite { + parent: ISuite; + title: string; - fullTitle(): string; - } + fullTitle(): string; + } - /** Partial interface for Mocha's `Test` class. */ - interface ITest extends IRunnable { - parent: ISuite; - pending: boolean; - state: 'failed'|'passed'|undefined; + /** Partial interface for Mocha's `Test` class. */ + interface ITest extends IRunnable { + parent: ISuite; + pending: boolean; + state: 'failed' | 'passed' | undefined; - fullTitle(): string; - } + fullTitle(): string; + } - interface IBeforeAndAfterContext extends IHookCallbackContext { - currentTest: ITest; - } + interface IBeforeAndAfterContext extends IHookCallbackContext { + currentTest: ITest; + } - /** Partial interface for Mocha's `Runner` class. */ - interface IRunner { } + /** Partial interface for Mocha's `Runner` class. */ + interface IRunner { } - interface IContextDefinition { - (description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - only(description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - skip(description: string, callback: (this: ISuiteCallbackContext) => void): void; - timeout(ms: number): void; - } + interface IContextDefinition { + (description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; + only(description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; + skip(description: string, callback: (this: ISuiteCallbackContext) => void): void; + timeout(ms: number): void; + } - interface ITestDefinition { - (expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): ITest; - only(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): ITest; - skip(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): void; - timeout(ms: number): void; - state: "failed" | "passed"; - } + interface ITestDefinition { + (expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): ITest; + only(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): ITest; + skip(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => any): void; + timeout(ms: number): void; + state: "failed" | "passed"; + } - export module reporters { - export class Base { - stats: { - suites: number; - tests: number; - passes: number; - pending: number; - failures: number; - }; + export module reporters { + export class Base { + stats: { + suites: number; + tests: number; + passes: number; + pending: number; + failures: number; + }; - constructor(runner: IRunner); - } + constructor(runner: IRunner); + } - export class Doc extends Base { } - export class Dot extends Base { } - export class HTML extends Base { } - export class HTMLCov extends Base { } - export class JSON extends Base { } - export class JSONCov extends Base { } - export class JSONStream extends Base { } - export class Landing extends Base { } - export class List extends Base { } - export class Markdown extends Base { } - export class Min extends Base { } - export class Nyan extends Base { } - export class Progress extends Base { + export class Doc extends Base { } + export class Dot extends Base { } + export class HTML extends Base { } + export class HTMLCov extends Base { } + export class JSON extends Base { } + export class JSONCov extends Base { } + export class JSONStream extends Base { } + export class Landing extends Base { } + export class List extends Base { } + export class Markdown extends Base { } + export class Min extends Base { } + export class Nyan extends Base { } + export class Progress extends Base { /** * @param options.open String used to indicate the start of the progress bar. * @param options.complete String used to indicate a complete test on the progress bar. * @param options.incomplete String used to indicate an incomplete test on the progress bar. * @param options.close String used to indicate the end of the progress bar. */ - constructor(runner: IRunner, options?: { - open?: string; - complete?: string; - incomplete?: string; - close?: string; - }); - } - export class Spec extends Base { } - export class TAP extends Base { } - export class XUnit extends Base { - constructor(runner: IRunner, options?: any); - } - } + constructor(runner: IRunner, options?: { + open?: string; + complete?: string; + incomplete?: string; + close?: string; + }); + } + export class Spec extends Base { } + export class TAP extends Base { } + export class XUnit extends Base { + constructor(runner: IRunner, options?: any); + } + } } declare module "mocha" { - export = Mocha; + export = Mocha; } \ No newline at end of file diff --git a/src/typings/node-pty.d.ts b/src/typings/node-pty.d.ts index b2004a9935..e3ee561a60 100644 --- a/src/typings/node-pty.d.ts +++ b/src/typings/node-pty.d.ts @@ -1,27 +1,81 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +/** + * Copyright (c) 2017, Daniel Imms (MIT License). + */ declare module 'node-pty' { - export function fork(file: string, args: string[], options: any): Terminal; - export function spawn(file: string, args: string[], options: any): Terminal; - export function createTerminal(file: string, args: string[], options: any): Terminal; + /** + * Forks a process as a pseudoterminal. + * @param file The file to launch. + * @param args The file's arguments as argv (string[]) or in a pre-escaped CommandLine format + * (string). Note that the CommandLine option is only available on Windows and is expected to be + * escaped properly. + * @param options The options of the terminal. + * @see CommandLineToArgvW https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx + * @see Parsing C++ Comamnd-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx + * @see GetCommandLine https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156.aspx + */ + export function spawn(file: string, args: string[] | string, options: IPtyForkOptions): IPty; - export interface Terminal { - pid: number; - - /** - * The title of the active process. - */ - process: string; - - on(event: string, callback: (data: any) => void): void; - - resize(columns: number, rows: number): void; - - write(data: string): void; - - kill(): void; + export interface IPtyForkOptions { + name?: string; + cols?: number; + rows?: number; + cwd?: string; + env?: { [key: string]: string }; + uid?: number; + gid?: number; + encoding?: string; } -} \ No newline at end of file + + /** + * An interface representing a pseudoterminal, on Windows this is emulated via the winpty library. + */ + export interface IPty { + /** + * The process ID of the outer process. + */ + pid: number; + + /** + * The title of the active process. + */ + process: string; + + /** + * Adds a listener to the data event, fired when data is returned from the pty. + * @param event The name of the event. + * @param listener The callback function. + */ + on(event: 'data', listener: (data: string) => void): void; + + /** + * Adds a listener to the exit event, fired when the pty exits. + * @param event The name of the event. + * @param listener The callback function, exitCode is the exit code of the process and signal is + * the signal that triggered the exit. signal is not supported on Windows. + */ + on(event: 'exit', listener: (exitCode: number, signal?: number) => void): void; + + /** + * Resizes the dimensions of the pty. + * @param columns THe number of columns to use. + * @param rows The number of rows to use. + */ + resize(columns: number, rows: number): void; + + /** + * Writes data to the pty. + * @param data The data to write. + */ + write(data: string): void; + + /** + * Kills the pty. + * @param signal The signal to use, defaults to SIGHUP. If the TIOCSIG/TIOCSIGNAL ioctl is not + * supported then the process will be killed instead. This parameter is not supported on + * Windows. + * @throws Will throw when signal is used on Windows. + */ + kill(signal?: string): void; + } + } \ No newline at end of file diff --git a/src/typings/node.d.ts b/src/typings/node.d.ts index ba2ed0d5d0..1b6661edd7 100644 --- a/src/typings/node.d.ts +++ b/src/typings/node.d.ts @@ -17,25 +17,25 @@ // This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build interface Console { - Console: NodeJS.ConsoleConstructor; - assert(value: any, message?: string, ...optionalParams: any[]): void; - dir(obj: any, options?: NodeJS.InspectOptions): void; - error(message?: any, ...optionalParams: any[]): void; - info(message?: any, ...optionalParams: any[]): void; - log(message?: any, ...optionalParams: any[]): void; - time(label: string): void; - timeEnd(label: string): void; - trace(message?: any, ...optionalParams: any[]): void; - warn(message?: any, ...optionalParams: any[]): void; + Console: NodeJS.ConsoleConstructor; + assert(value: any, message?: string, ...optionalParams: any[]): void; + dir(obj: any, options?: NodeJS.InspectOptions): void; + error(message?: any, ...optionalParams: any[]): void; + info(message?: any, ...optionalParams: any[]): void; + log(message?: any, ...optionalParams: any[]): void; + time(label: string): void; + timeEnd(label: string): void; + trace(message?: any, ...optionalParams: any[]): void; + warn(message?: any, ...optionalParams: any[]): void; } interface Error { - stack?: string; + stack?: string; } interface ErrorConstructor { - captureStackTrace(targetObject: Object, constructorOpt?: Function): void; - stackTraceLimit: number; + captureStackTrace(targetObject: Object, constructorOpt?: Function): void; + stackTraceLimit: number; } // compat for TypeScript 1.8 @@ -49,13 +49,13 @@ interface WeakSetConstructor { } // Forward-declare needed types from lib.es2015.d.ts (in case users are using `--lib es5`) interface Iterable<T> { } interface Iterator<T> { - next(value?: any): IteratorResult<T>; + next(value?: any): IteratorResult<T>; } interface IteratorResult<T> { } -// interface SymbolConstructor { -// readonly iterator: symbol; -// } -// declare var Symbol: SymbolConstructor; +interface SymbolConstructor { + readonly iterator: symbol; +} +declare var Symbol: SymbolConstructor; /************************************************ * * @@ -78,7 +78,7 @@ declare function setImmediate(callback: (...args: any[]) => void, ...args: any[] declare function clearImmediate(immediateId: any): void; interface NodeRequireFunction { - (id: string): any; + (id: string): any; } // interface NodeRequire extends NodeRequireFunction { @@ -91,13 +91,13 @@ interface NodeRequireFunction { // declare var require: NodeRequire; interface NodeModule { - exports: any; - require: NodeRequireFunction; - id: string; - filename: string; - loaded: boolean; - parent: NodeModule | null; - children: NodeModule[]; + exports: any; + require: NodeRequireFunction; + id: string; + filename: string; + loaded: boolean; + parent: NodeModule | null; + children: NodeModule[]; } declare var module: NodeModule; @@ -105,14 +105,14 @@ declare var module: NodeModule; // Same as module.exports declare var exports: any; declare var SlowBuffer: { - new(str: string, encoding?: string): Buffer; - new(size: number): Buffer; - new(size: Uint8Array): Buffer; - new(array: any[]): Buffer; - prototype: Buffer; - isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; - concat(list: Buffer[], totalLength?: number): Buffer; + new(str: string, encoding?: string): Buffer; + new(size: number): Buffer; + new(size: Uint8Array): Buffer; + new(array: any[]): Buffer; + prototype: Buffer; + isBuffer(obj: any): boolean; + byteLength(string: string, encoding?: string): number; + concat(list: Buffer[], totalLength?: number): Buffer; }; @@ -132,19 +132,19 @@ declare var Buffer: { * @param str String to store in buffer. * @param encoding encoding to use, optional. Default is 'utf8' */ - new(str: string, encoding?: string): Buffer; + new(str: string, encoding?: string): Buffer; /** * Allocates a new buffer of {size} octets. * * @param size count of octets to allocate. */ - new(size: number): Buffer; + new(size: number): Buffer; /** * Allocates a new buffer containing the given {array} of octets. * * @param array The octets to store. */ - new(array: Uint8Array): Buffer; + new(array: Uint8Array): Buffer; /** * Produces a Buffer backed by the same allocated memory as * the given {ArrayBuffer}. @@ -152,26 +152,26 @@ declare var Buffer: { * * @param arrayBuffer The ArrayBuffer with which to share memory. */ - new(arrayBuffer: ArrayBuffer): Buffer; + new(arrayBuffer: ArrayBuffer): Buffer; /** * Allocates a new buffer containing the given {array} of octets. * * @param array The octets to store. */ - new(array: any[]): Buffer; + new(array: any[]): Buffer; /** * Copies the passed {buffer} data onto a new {Buffer} instance. * * @param buffer The buffer to copy. */ - new(buffer: Buffer): Buffer; - prototype: Buffer; + new(buffer: Buffer): Buffer; + prototype: Buffer; /** * Allocates a new Buffer using an {array} of octets. * * @param array */ - from(array: any[]): Buffer; + from(array: any[]): Buffer; /** * When passed a reference to the .buffer property of a TypedArray instance, * the newly created Buffer will share the same allocated memory as the TypedArray. @@ -182,13 +182,13 @@ declare var Buffer: { * @param byteOffset * @param length */ - from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; /** * Copies the passed {buffer} data onto a new Buffer instance. * * @param buffer */ - from(buffer: Buffer): Buffer; + from(buffer: Buffer): Buffer; /** * Creates a new Buffer containing the given JavaScript string {str}. * If provided, the {encoding} parameter identifies the character encoding. @@ -196,20 +196,20 @@ declare var Buffer: { * * @param str */ - from(str: string, encoding?: string): Buffer; + from(str: string, encoding?: string): Buffer; /** * Returns true if {obj} is a Buffer * * @param obj object to test. */ - isBuffer(obj: any): obj is Buffer; + isBuffer(obj: any): obj is Buffer; /** * Returns true if {encoding} is a valid encoding argument. * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' * * @param encoding string to test. */ - isEncoding(encoding: string): boolean; + isEncoding(encoding: string): boolean; /** * Gives the actual byte length of a string. encoding defaults to 'utf8'. * This is not the same as String.prototype.length since that returns the number of characters in a string. @@ -217,7 +217,7 @@ declare var Buffer: { * @param string string to test. * @param encoding encoding used to evaluate (defaults to 'utf8') */ - byteLength(string: string, encoding?: string): number; + byteLength(string: string, encoding?: string): number; /** * Returns a buffer which is the result of concatenating all the buffers in the list together. * @@ -229,11 +229,11 @@ declare var Buffer: { * @param totalLength Total length of the buffers when concatenated. * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. */ - concat(list: Buffer[], totalLength?: number): Buffer; + concat(list: Buffer[], totalLength?: number): Buffer; /** * The same as buf1.compare(buf2). */ - compare(buf1: Buffer, buf2: Buffer): number; + compare(buf1: Buffer, buf2: Buffer): number; /** * Allocates a new buffer of {size} octets. * @@ -242,21 +242,21 @@ declare var Buffer: { * If parameter is omitted, buffer will be filled with zeros. * @param encoding encoding used for call to buf.fill while initalizing */ - alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; /** * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents * of the newly created Buffer are unknown and may contain sensitive data. * * @param size count of octets to allocate */ - allocUnsafe(size: number): Buffer; + allocUnsafe(size: number): Buffer; /** * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents * of the newly created Buffer are unknown and may contain sensitive data. * * @param size count of octets to allocate */ - allocUnsafeSlow(size: number): Buffer; + allocUnsafeSlow(size: number): Buffer; }; /************************************************ @@ -265,273 +265,273 @@ declare var Buffer: { * * ************************************************/ declare namespace NodeJS { - export interface InspectOptions { - showHidden?: boolean; - depth?: number | null; - colors?: boolean; - customInspect?: boolean; - showProxy?: boolean; - maxArrayLength?: number | null; - breakLength?: number; - } + export interface InspectOptions { + showHidden?: boolean; + depth?: number | null; + colors?: boolean; + customInspect?: boolean; + showProxy?: boolean; + maxArrayLength?: number | null; + breakLength?: number; + } - export interface ConsoleConstructor { - prototype: Console; - new(stdout: WritableStream, stderr?: WritableStream): Console; - } + export interface ConsoleConstructor { + prototype: Console; + new(stdout: WritableStream, stderr?: WritableStream): Console; + } - export interface ErrnoException extends Error { - errno?: number; - code?: string; - path?: string; - syscall?: string; - stack?: string; - } + export interface ErrnoException extends Error { + errno?: number; + code?: string; + path?: string; + syscall?: string; + stack?: string; + } - export class EventEmitter { - addListener(event: string | symbol, listener: Function): this; - on(event: string | symbol, listener: Function): this; - once(event: string | symbol, listener: Function): this; - removeListener(event: string | symbol, listener: Function): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - listenerCount(type: string | symbol): number; - // Added in Node 6... - prependListener(event: string | symbol, listener: Function): this; - prependOnceListener(event: string | symbol, listener: Function): this; - eventNames(): (string | symbol)[]; - } + export class EventEmitter { + addListener(event: string | symbol, listener: Function): this; + on(event: string | symbol, listener: Function): this; + once(event: string | symbol, listener: Function): this; + removeListener(event: string | symbol, listener: Function): this; + removeAllListeners(event?: string | symbol): this; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string | symbol): Function[]; + emit(event: string | symbol, ...args: any[]): boolean; + listenerCount(type: string | symbol): number; + // Added in Node 6... + prependListener(event: string | symbol, listener: Function): this; + prependOnceListener(event: string | symbol, listener: Function): this; + eventNames(): (string | symbol)[]; + } - export interface ReadableStream extends EventEmitter { - readable: boolean; - read(size?: number): string | Buffer; - setEncoding(encoding: string | null): this; - pause(): this; - resume(): this; - isPaused(): boolean; - pipe<T extends WritableStream>(destination: T, options?: { end?: boolean; }): T; - unpipe<T extends WritableStream>(destination?: T): this; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: ReadableStream): ReadableStream; - } + export interface ReadableStream extends EventEmitter { + readable: boolean; + read(size?: number): string | Buffer; + setEncoding(encoding: string | null): this; + pause(): this; + resume(): this; + isPaused(): boolean; + pipe<T extends WritableStream>(destination: T, options?: { end?: boolean; }): T; + unpipe<T extends WritableStream>(destination?: T): this; + unshift(chunk: string): void; + unshift(chunk: Buffer): void; + wrap(oldStream: ReadableStream): ReadableStream; + } - export interface WritableStream extends EventEmitter { - writable: boolean; - write(buffer: Buffer | string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } + export interface WritableStream extends EventEmitter { + writable: boolean; + write(buffer: Buffer | string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + } - export interface ReadWriteStream extends ReadableStream, WritableStream { } + export interface ReadWriteStream extends ReadableStream, WritableStream { } - export interface Events extends EventEmitter { } + export interface Events extends EventEmitter { } - export interface Domain extends Events { - run(fn: Function): void; - add(emitter: Events): void; - remove(emitter: Events): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; + export interface Domain extends Events { + run(fn: Function): void; + add(emitter: Events): void; + remove(emitter: Events): void; + bind(cb: (err: Error, data: any) => any): any; + intercept(cb: (data: any) => any): any; + dispose(): void; - addListener(event: string, listener: Function): this; - on(event: string, listener: Function): this; - once(event: string, listener: Function): this; - removeListener(event: string, listener: Function): this; - removeAllListeners(event?: string): this; - } + addListener(event: string, listener: Function): this; + on(event: string, listener: Function): this; + once(event: string, listener: Function): this; + removeListener(event: string, listener: Function): this; + removeAllListeners(event?: string): this; + } - export interface MemoryUsage { - rss: number; - heapTotal: number; - heapUsed: number; - } + export interface MemoryUsage { + rss: number; + heapTotal: number; + heapUsed: number; + } - export interface CpuUsage { - user: number; - system: number; - } + export interface CpuUsage { + user: number; + system: number; + } - export interface ProcessVersions { - http_parser: string; - node: string; - v8: string; - ares: string; - uv: string; - zlib: string; - modules: string; - openssl: string; - } + export interface ProcessVersions { + http_parser: string; + node: string; + v8: string; + ares: string; + uv: string; + zlib: string; + modules: string; + openssl: string; + } - type Platform = 'aix' - | 'android' - | 'darwin' - | 'freebsd' - | 'linux' - | 'openbsd' - | 'sunos' - | 'win32'; + type Platform = 'aix' + | 'android' + | 'darwin' + | 'freebsd' + | 'linux' + | 'openbsd' + | 'sunos' + | 'win32'; - export interface Socket extends ReadWriteStream { - isTTY?: true; - } + export interface Socket extends ReadWriteStream { + isTTY?: true; + } - export interface WriteStream extends Socket { - columns?: number; - rows?: number; - } - export interface ReadStream extends Socket { - isRaw?: boolean; - setRawMode?(mode: boolean): void; - } + export interface WriteStream extends Socket { + columns?: number; + rows?: number; + } + export interface ReadStream extends Socket { + isRaw?: boolean; + setRawMode?(mode: boolean): void; + } - export interface Process extends EventEmitter { - stdout: WriteStream; - stderr: WriteStream; - stdin: ReadStream; - openStdin(): Socket; - argv: string[]; - argv0: string; - execArgv: string[]; - execPath: string; - abort(): void; - chdir(directory: string): void; - cwd(): string; - emitWarning(warning: string | Error, name?: string, ctor?: Function): void; - env: any; - exit(code?: number): void; - exitCode: number; - getgid(): number; - setgid(id: number): void; - setgid(id: string): void; - getuid(): number; - setuid(id: number): void; - setuid(id: string): void; - version: string; - versions: ProcessVersions; - config: { - target_defaults: { - cflags: any[]; - default_configuration: string; - defines: string[]; - include_dirs: string[]; - libraries: string[]; - }; - variables: { - clang: number; - host_arch: string; - node_install_npm: boolean; - node_install_waf: boolean; - node_prefix: string; - node_shared_openssl: boolean; - node_shared_v8: boolean; - node_shared_zlib: boolean; - node_use_dtrace: boolean; - node_use_etw: boolean; - node_use_openssl: boolean; - target_arch: string; - v8_no_strict_aliasing: number; - v8_use_snapshot: boolean; - visibility: string; - }; - }; - kill(pid: number, signal?: string | number): void; - pid: number; - title: string; - arch: string; - platform: Platform; - mainModule?: NodeModule; - memoryUsage(): MemoryUsage; - cpuUsage(previousValue?: CpuUsage): CpuUsage; - nextTick(callback: Function, ...args: any[]): void; - umask(mask?: number): number; - uptime(): number; - hrtime(time?: [number, number]): [number, number]; - domain: Domain; + export interface Process extends EventEmitter { + stdout: WriteStream; + stderr: WriteStream; + stdin: ReadStream; + openStdin(): Socket; + argv: string[]; + argv0: string; + execArgv: string[]; + execPath: string; + abort(): void; + chdir(directory: string): void; + cwd(): string; + emitWarning(warning: string | Error, name?: string, ctor?: Function): void; + env: any; + exit(code?: number): void; + exitCode: number; + getgid(): number; + setgid(id: number): void; + setgid(id: string): void; + getuid(): number; + setuid(id: number): void; + setuid(id: string): void; + version: string; + versions: ProcessVersions; + config: { + target_defaults: { + cflags: any[]; + default_configuration: string; + defines: string[]; + include_dirs: string[]; + libraries: string[]; + }; + variables: { + clang: number; + host_arch: string; + node_install_npm: boolean; + node_install_waf: boolean; + node_prefix: string; + node_shared_openssl: boolean; + node_shared_v8: boolean; + node_shared_zlib: boolean; + node_use_dtrace: boolean; + node_use_etw: boolean; + node_use_openssl: boolean; + target_arch: string; + v8_no_strict_aliasing: number; + v8_use_snapshot: boolean; + visibility: string; + }; + }; + kill(pid: number, signal?: string | number): void; + pid: number; + title: string; + arch: string; + platform: Platform; + mainModule?: NodeModule; + memoryUsage(): MemoryUsage; + cpuUsage(previousValue?: CpuUsage): CpuUsage; + nextTick(callback: Function, ...args: any[]): void; + umask(mask?: number): number; + uptime(): number; + hrtime(time?: [number, number]): [number, number]; + domain: Domain; - // Worker - send?(message: any, sendHandle?: any): void; - disconnect(): void; - connected: boolean; - } + // Worker + send?(message: any, sendHandle?: any): void; + disconnect(): void; + connected: boolean; + } - export interface Global { - Array: typeof Array; - ArrayBuffer: typeof ArrayBuffer; - Boolean: typeof Boolean; - Buffer: typeof Buffer; - DataView: typeof DataView; - Date: typeof Date; - Error: typeof Error; - EvalError: typeof EvalError; - Float32Array: typeof Float32Array; - Float64Array: typeof Float64Array; - Function: typeof Function; - GLOBAL: Global; - Infinity: typeof Infinity; - Int16Array: typeof Int16Array; - Int32Array: typeof Int32Array; - Int8Array: typeof Int8Array; - Intl: typeof Intl; - JSON: typeof JSON; - Map: MapConstructor; - Math: typeof Math; - NaN: typeof NaN; - Number: typeof Number; - Object: typeof Object; - Promise: Function; - RangeError: typeof RangeError; - ReferenceError: typeof ReferenceError; - RegExp: typeof RegExp; - Set: SetConstructor; - String: typeof String; - Symbol: Function; - SyntaxError: typeof SyntaxError; - TypeError: typeof TypeError; - URIError: typeof URIError; - Uint16Array: typeof Uint16Array; - Uint32Array: typeof Uint32Array; - Uint8Array: typeof Uint8Array; - Uint8ClampedArray: Function; - WeakMap: WeakMapConstructor; - WeakSet: WeakSetConstructor; - clearImmediate: (immediateId: any) => void; - clearInterval: (intervalId: NodeJS.Timer) => void; - clearTimeout: (timeoutId: NodeJS.Timer) => void; - console: typeof console; - decodeURI: typeof decodeURI; - decodeURIComponent: typeof decodeURIComponent; - encodeURI: typeof encodeURI; - encodeURIComponent: typeof encodeURIComponent; - escape: (str: string) => string; - eval: typeof eval; - global: Global; - isFinite: typeof isFinite; - isNaN: typeof isNaN; - parseFloat: typeof parseFloat; - parseInt: typeof parseInt; - process: Process; - root: Global; - setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; - setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - undefined: typeof undefined; - unescape: (str: string) => string; - gc: () => void; - v8debug?: any; - } + export interface Global { + Array: typeof Array; + ArrayBuffer: typeof ArrayBuffer; + Boolean: typeof Boolean; + Buffer: typeof Buffer; + DataView: typeof DataView; + Date: typeof Date; + Error: typeof Error; + EvalError: typeof EvalError; + Float32Array: typeof Float32Array; + Float64Array: typeof Float64Array; + Function: typeof Function; + GLOBAL: Global; + Infinity: typeof Infinity; + Int16Array: typeof Int16Array; + Int32Array: typeof Int32Array; + Int8Array: typeof Int8Array; + Intl: typeof Intl; + JSON: typeof JSON; + Map: MapConstructor; + Math: typeof Math; + NaN: typeof NaN; + Number: typeof Number; + Object: typeof Object; + Promise: Function; + RangeError: typeof RangeError; + ReferenceError: typeof ReferenceError; + RegExp: typeof RegExp; + Set: SetConstructor; + String: typeof String; + Symbol: Function; + SyntaxError: typeof SyntaxError; + TypeError: typeof TypeError; + URIError: typeof URIError; + Uint16Array: typeof Uint16Array; + Uint32Array: typeof Uint32Array; + Uint8Array: typeof Uint8Array; + Uint8ClampedArray: Function; + WeakMap: WeakMapConstructor; + WeakSet: WeakSetConstructor; + clearImmediate: (immediateId: any) => void; + clearInterval: (intervalId: NodeJS.Timer) => void; + clearTimeout: (timeoutId: NodeJS.Timer) => void; + console: typeof console; + decodeURI: typeof decodeURI; + decodeURIComponent: typeof decodeURIComponent; + encodeURI: typeof encodeURI; + encodeURIComponent: typeof encodeURIComponent; + escape: (str: string) => string; + eval: typeof eval; + global: Global; + isFinite: typeof isFinite; + isNaN: typeof isNaN; + parseFloat: typeof parseFloat; + parseInt: typeof parseInt; + process: Process; + root: Global; + setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; + setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; + setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; + undefined: typeof undefined; + unescape: (str: string) => string; + gc: () => void; + v8debug?: any; + } - export interface Timer { - ref(): void; - unref(): void; - } + export interface Timer { + ref(): void; + unref(): void; + } } interface IterableIterator<T> { } @@ -540,59 +540,59 @@ interface IterableIterator<T> { } * @deprecated */ interface NodeBuffer extends Uint8Array { - write(string: string, offset?: number, length?: number, encoding?: string): number; - toString(encoding?: string, start?: number, end?: number): string; - toJSON(): { type: 'Buffer', data: any[] }; - equals(otherBuffer: Buffer): boolean; - compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; - copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; - slice(start?: number, end?: number): Buffer; - writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readUInt8(offset: number, noAssert?: boolean): number; - readUInt16LE(offset: number, noAssert?: boolean): number; - readUInt16BE(offset: number, noAssert?: boolean): number; - readUInt32LE(offset: number, noAssert?: boolean): number; - readUInt32BE(offset: number, noAssert?: boolean): number; - readInt8(offset: number, noAssert?: boolean): number; - readInt16LE(offset: number, noAssert?: boolean): number; - readInt16BE(offset: number, noAssert?: boolean): number; - readInt32LE(offset: number, noAssert?: boolean): number; - readInt32BE(offset: number, noAssert?: boolean): number; - readFloatLE(offset: number, noAssert?: boolean): number; - readFloatBE(offset: number, noAssert?: boolean): number; - readDoubleLE(offset: number, noAssert?: boolean): number; - readDoubleBE(offset: number, noAssert?: boolean): number; - swap16(): Buffer; - swap32(): Buffer; - swap64(): Buffer; - writeUInt8(value: number, offset: number, noAssert?: boolean): number; - writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeInt8(value: number, offset: number, noAssert?: boolean): number; - writeInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeFloatLE(value: number, offset: number, noAssert?: boolean): number; - writeFloatBE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; - fill(value: any, offset?: number, end?: number): this; - indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - entries(): IterableIterator<[number, number]>; - includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; - keys(): IterableIterator<number>; - values(): IterableIterator<number>; + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + entries(): IterableIterator<[number, number]>; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + keys(): IterableIterator<number>; + values(): IterableIterator<number>; } /************************************************ @@ -601,205 +601,205 @@ interface NodeBuffer extends Uint8Array { * * ************************************************/ declare module "buffer" { - export var INSPECT_MAX_BYTES: number; - var BuffType: typeof Buffer; - var SlowBuffType: typeof SlowBuffer; - export { BuffType as Buffer, SlowBuffType as SlowBuffer }; + export var INSPECT_MAX_BYTES: number; + var BuffType: typeof Buffer; + var SlowBuffType: typeof SlowBuffer; + export { BuffType as Buffer, SlowBuffType as SlowBuffer }; } declare module "querystring" { - export interface StringifyOptions { - encodeURIComponent?: Function; - } + export interface StringifyOptions { + encodeURIComponent?: Function; + } - export interface ParseOptions { - maxKeys?: number; - decodeURIComponent?: Function; - } + export interface ParseOptions { + maxKeys?: number; + decodeURIComponent?: Function; + } - export function stringify<T>(obj: T, sep?: string, eq?: string, options?: StringifyOptions): string; - export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): any; - export function parse<T extends {}>(str: string, sep?: string, eq?: string, options?: ParseOptions): T; - export function escape(str: string): string; - export function unescape(str: string): string; + export function stringify<T>(obj: T, sep?: string, eq?: string, options?: StringifyOptions): string; + export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): any; + export function parse<T extends {}>(str: string, sep?: string, eq?: string, options?: ParseOptions): T; + export function escape(str: string): string; + export function unescape(str: string): string; } declare module "events" { - class internal extends NodeJS.EventEmitter { } + class internal extends NodeJS.EventEmitter { } - namespace internal { - export class EventEmitter extends internal { - static listenerCount(emitter: EventEmitter, event: string | symbol): number; // deprecated - static defaultMaxListeners: number; + namespace internal { + export class EventEmitter extends internal { + static listenerCount(emitter: EventEmitter, event: string | symbol): number; // deprecated + static defaultMaxListeners: number; - addListener(event: string | symbol, listener: Function): this; - on(event: string | symbol, listener: Function): this; - once(event: string | symbol, listener: Function): this; - prependListener(event: string | symbol, listener: Function): this; - prependOnceListener(event: string | symbol, listener: Function): this; - removeListener(event: string | symbol, listener: Function): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - eventNames(): (string | symbol)[]; - listenerCount(type: string | symbol): number; - } - } + addListener(event: string | symbol, listener: Function): this; + on(event: string | symbol, listener: Function): this; + once(event: string | symbol, listener: Function): this; + prependListener(event: string | symbol, listener: Function): this; + prependOnceListener(event: string | symbol, listener: Function): this; + removeListener(event: string | symbol, listener: Function): this; + removeAllListeners(event?: string | symbol): this; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string | symbol): Function[]; + emit(event: string | symbol, ...args: any[]): boolean; + eventNames(): (string | symbol)[]; + listenerCount(type: string | symbol): number; + } + } - export = internal; + export = internal; } declare module "http" { - import * as events from "events"; - import * as net from "net"; - import * as stream from "stream"; + import * as events from "events"; + import * as net from "net"; + import * as stream from "stream"; - export interface RequestOptions { - protocol?: string; - host?: string; - hostname?: string; - family?: number; - port?: number; - localAddress?: string; - socketPath?: string; - method?: string; - path?: string; - headers?: { [key: string]: any }; - auth?: string; - agent?: Agent | boolean; - timeout?: number; - } + export interface RequestOptions { + protocol?: string; + host?: string; + hostname?: string; + family?: number; + port?: number; + localAddress?: string; + socketPath?: string; + method?: string; + path?: string; + headers?: { [key: string]: any }; + auth?: string; + agent?: Agent | boolean; + timeout?: number; + } - export interface Server extends net.Server { - setTimeout(msecs: number, callback: Function): void; - maxHeadersCount: number; - timeout: number; - listening: boolean; - } + export interface Server extends net.Server { + setTimeout(msecs: number, callback: Function): void; + maxHeadersCount: number; + timeout: number; + listening: boolean; + } /** * @deprecated Use IncomingMessage */ - export interface ServerRequest extends IncomingMessage { - connection: net.Socket; - } - export interface ServerResponse extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; + export interface ServerRequest extends IncomingMessage { + connection: net.Socket; + } + export interface ServerResponse extends stream.Writable { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; - writeContinue(): void; - writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; - writeHead(statusCode: number, headers?: any): void; - statusCode: number; - statusMessage: string; - headersSent: boolean; - setHeader(name: string, value: string | string[]): void; - setTimeout(msecs: number, callback: Function): ServerResponse; - sendDate: boolean; - getHeader(name: string): string; - removeHeader(name: string): void; - write(chunk: any, encoding?: string): any; - addTrailers(headers: any): void; - finished: boolean; + writeContinue(): void; + writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; + writeHead(statusCode: number, headers?: any): void; + statusCode: number; + statusMessage: string; + headersSent: boolean; + setHeader(name: string, value: string | string[]): void; + setTimeout(msecs: number, callback: Function): ServerResponse; + sendDate: boolean; + getHeader(name: string): string; + removeHeader(name: string): void; + write(chunk: any, encoding?: string): any; + addTrailers(headers: any): void; + finished: boolean; - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface ClientRequest extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; + } + export interface ClientRequest extends stream.Writable { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; - write(chunk: any, encoding?: string): void; - abort(): void; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; + write(chunk: any, encoding?: string): void; + abort(): void; + setTimeout(timeout: number, callback?: Function): void; + setNoDelay(noDelay?: boolean): void; + setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; - setHeader(name: string, value: string | string[]): void; - getHeader(name: string): string; - removeHeader(name: string): void; - addTrailers(headers: any): void; + setHeader(name: string, value: string | string[]): void; + getHeader(name: string): string; + removeHeader(name: string): void; + addTrailers(headers: any): void; - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface IncomingMessage extends stream.Readable { - httpVersion: string; - httpVersionMajor: number; - httpVersionMinor: number; - connection: net.Socket; - headers: any; - rawHeaders: string[]; - trailers: any; - rawTrailers: any; - setTimeout(msecs: number, callback: Function): NodeJS.Timer; + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; + } + export interface IncomingMessage extends stream.Readable { + httpVersion: string; + httpVersionMajor: number; + httpVersionMinor: number; + connection: net.Socket; + headers: any; + rawHeaders: string[]; + trailers: any; + rawTrailers: any; + setTimeout(msecs: number, callback: Function): NodeJS.Timer; /** * Only valid for request obtained from http.Server. */ - method?: string; + method?: string; /** * Only valid for request obtained from http.Server. */ - url?: string; + url?: string; /** * Only valid for response obtained from http.ClientRequest. */ - statusCode?: number; + statusCode?: number; /** * Only valid for response obtained from http.ClientRequest. */ - statusMessage?: string; - socket: net.Socket; - destroy(error?: Error): void; - } + statusMessage?: string; + socket: net.Socket; + destroy(error?: Error): void; + } /** * @deprecated Use IncomingMessage */ - export interface ClientResponse extends IncomingMessage { } + export interface ClientResponse extends IncomingMessage { } - export interface AgentOptions { + export interface AgentOptions { /** * Keep sockets around in a pool to be used by other requests in the future. Default = false */ - keepAlive?: boolean; + keepAlive?: boolean; /** * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. * Only relevant if keepAlive is set to true. */ - keepAliveMsecs?: number; + keepAliveMsecs?: number; /** * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity */ - maxSockets?: number; + maxSockets?: number; /** * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. */ - maxFreeSockets?: number; - } + maxFreeSockets?: number; + } - export class Agent { - maxSockets: number; - sockets: any; - requests: any; + export class Agent { + maxSockets: number; + sockets: any; + requests: any; - constructor(opts?: AgentOptions); + constructor(opts?: AgentOptions); /** * Destroy any sockets that are currently in use by the agent. @@ -807,62 +807,62 @@ declare module "http" { * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, * sockets may hang open for quite a long time before the server terminates them. */ - destroy(): void; - } + destroy(): void; + } - export var METHODS: string[]; + export var METHODS: string[]; - export var STATUS_CODES: { - [errorCode: number]: string; - [errorCode: string]: string; - }; - export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) => void): Server; - export function createClient(port?: number, host?: string): any; - export function request(options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; - export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; - export var globalAgent: Agent; + export var STATUS_CODES: { + [errorCode: number]: string; + [errorCode: string]: string; + }; + export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) => void): Server; + export function createClient(port?: number, host?: string): any; + export function request(options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; + export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; + export var globalAgent: Agent; } declare module "cluster" { - import * as child from "child_process"; - import * as events from "events"; - import * as net from "net"; + import * as child from "child_process"; + import * as events from "events"; + import * as net from "net"; - // interfaces - export interface ClusterSettings { - execArgv?: string[]; // default: process.execArgv - exec?: string; - args?: string[]; - silent?: boolean; - stdio?: any[]; - uid?: number; - gid?: number; - } + // interfaces + export interface ClusterSettings { + execArgv?: string[]; // default: process.execArgv + exec?: string; + args?: string[]; + silent?: boolean; + stdio?: any[]; + uid?: number; + gid?: number; + } - export interface ClusterSetupMasterSettings { - exec?: string; // default: process.argv[1] - args?: string[]; // default: process.argv.slice(2) - silent?: boolean; // default: false - stdio?: any[]; - } + export interface ClusterSetupMasterSettings { + exec?: string; // default: process.argv[1] + args?: string[]; // default: process.argv.slice(2) + silent?: boolean; // default: false + stdio?: any[]; + } - export interface Address { - address: string; - port: number; - addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6" - } + export interface Address { + address: string; + port: number; + addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6" + } - export class Worker extends events.EventEmitter { - id: string; - process: child.ChildProcess; - suicide: boolean; - send(message: any, sendHandle?: any, callback?: (error: Error) => void): boolean; - kill(signal?: string): void; - destroy(signal?: string): void; - disconnect(): void; - isConnected(): boolean; - isDead(): boolean; - exitedAfterDisconnect: boolean; + export class Worker extends events.EventEmitter { + id: string; + process: child.ChildProcess; + suicide: boolean; + send(message: any, sendHandle?: any, callback?: (error: Error) => void): boolean; + kill(signal?: string): void; + destroy(signal?: string): void; + disconnect(): void; + isConnected(): boolean; + isDead(): boolean; + exitedAfterDisconnect: boolean; /** * events.EventEmitter @@ -873,68 +873,68 @@ declare module "cluster" { * 5. message * 6. online */ - addListener(event: string, listener: Function): this; - addListener(event: "disconnect", listener: () => void): this; - addListener(event: "error", listener: (error: Error) => void): this; - addListener(event: "exit", listener: (code: number, signal: string) => void): this; - addListener(event: "listening", listener: (address: Address) => void): this; - addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - addListener(event: "online", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "disconnect", listener: () => void): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "exit", listener: (code: number, signal: string) => void): this; + addListener(event: "listening", listener: (address: Address) => void): this; + addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + addListener(event: "online", listener: () => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "disconnect", listener: () => void): boolean - emit(event: "error", listener: (error: Error) => void): boolean - emit(event: "exit", listener: (code: number, signal: string) => void): boolean - emit(event: "listening", listener: (address: Address) => void): boolean - emit(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): boolean - emit(event: "online", listener: () => void): boolean + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "disconnect", listener: () => void): boolean + emit(event: "error", listener: (error: Error) => void): boolean + emit(event: "exit", listener: (code: number, signal: string) => void): boolean + emit(event: "listening", listener: (address: Address) => void): boolean + emit(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): boolean + emit(event: "online", listener: () => void): boolean - on(event: string, listener: Function): this; - on(event: "disconnect", listener: () => void): this; - on(event: "error", listener: (error: Error) => void): this; - on(event: "exit", listener: (code: number, signal: string) => void): this; - on(event: "listening", listener: (address: Address) => void): this; - on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - on(event: "online", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "disconnect", listener: () => void): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "exit", listener: (code: number, signal: string) => void): this; + on(event: "listening", listener: (address: Address) => void): this; + on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + on(event: "online", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "disconnect", listener: () => void): this; - once(event: "error", listener: (error: Error) => void): this; - once(event: "exit", listener: (code: number, signal: string) => void): this; - once(event: "listening", listener: (address: Address) => void): this; - once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - once(event: "online", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "disconnect", listener: () => void): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "exit", listener: (code: number, signal: string) => void): this; + once(event: "listening", listener: (address: Address) => void): this; + once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + once(event: "online", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "disconnect", listener: () => void): this; - prependListener(event: "error", listener: (error: Error) => void): this; - prependListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependListener(event: "listening", listener: (address: Address) => void): this; - prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependListener(event: "online", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "disconnect", listener: () => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependListener(event: "listening", listener: (address: Address) => void): this; + prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependListener(event: "online", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "disconnect", listener: () => void): this; - prependOnceListener(event: "error", listener: (error: Error) => void): this; - prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependOnceListener(event: "listening", listener: (address: Address) => void): this; - prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependOnceListener(event: "online", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "disconnect", listener: () => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependOnceListener(event: "listening", listener: (address: Address) => void): this; + prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependOnceListener(event: "online", listener: () => void): this; + } - export interface Cluster extends events.EventEmitter { - Worker: Worker; - disconnect(callback?: Function): void; - fork(env?: any): Worker; - isMaster: boolean; - isWorker: boolean; - // TODO: cluster.schedulingPolicy - settings: ClusterSettings; - setupMaster(settings?: ClusterSetupMasterSettings): void; - worker: Worker; - workers: { - [index: string]: Worker - }; + export interface Cluster extends events.EventEmitter { + Worker: Worker; + disconnect(callback?: Function): void; + fork(env?: any): Worker; + isMaster: boolean; + isWorker: boolean; + // TODO: cluster.schedulingPolicy + settings: ClusterSettings; + setupMaster(settings?: ClusterSetupMasterSettings): void; + worker: Worker; + workers: { + [index: string]: Worker + }; /** * events.EventEmitter @@ -946,73 +946,73 @@ declare module "cluster" { * 6. online * 7. setup */ - addListener(event: string, listener: Function): this; - addListener(event: "disconnect", listener: (worker: Worker) => void): this; - addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - addListener(event: "fork", listener: (worker: Worker) => void): this; - addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - addListener(event: "online", listener: (worker: Worker) => void): this; - addListener(event: "setup", listener: (settings: any) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "disconnect", listener: (worker: Worker) => void): this; + addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + addListener(event: "fork", listener: (worker: Worker) => void): this; + addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + addListener(event: "online", listener: (worker: Worker) => void): this; + addListener(event: "setup", listener: (settings: any) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "disconnect", listener: (worker: Worker) => void): boolean; - emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; - emit(event: "fork", listener: (worker: Worker) => void): boolean; - emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; - emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; - emit(event: "online", listener: (worker: Worker) => void): boolean; - emit(event: "setup", listener: (settings: any) => void): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "disconnect", listener: (worker: Worker) => void): boolean; + emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; + emit(event: "fork", listener: (worker: Worker) => void): boolean; + emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; + emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; + emit(event: "online", listener: (worker: Worker) => void): boolean; + emit(event: "setup", listener: (settings: any) => void): boolean; - on(event: string, listener: Function): this; - on(event: "disconnect", listener: (worker: Worker) => void): this; - on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - on(event: "fork", listener: (worker: Worker) => void): this; - on(event: "listening", listener: (worker: Worker, address: Address) => void): this; - on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - on(event: "online", listener: (worker: Worker) => void): this; - on(event: "setup", listener: (settings: any) => void): this; + on(event: string, listener: Function): this; + on(event: "disconnect", listener: (worker: Worker) => void): this; + on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + on(event: "fork", listener: (worker: Worker) => void): this; + on(event: "listening", listener: (worker: Worker, address: Address) => void): this; + on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + on(event: "online", listener: (worker: Worker) => void): this; + on(event: "setup", listener: (settings: any) => void): this; - once(event: string, listener: Function): this; - once(event: "disconnect", listener: (worker: Worker) => void): this; - once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - once(event: "fork", listener: (worker: Worker) => void): this; - once(event: "listening", listener: (worker: Worker, address: Address) => void): this; - once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - once(event: "online", listener: (worker: Worker) => void): this; - once(event: "setup", listener: (settings: any) => void): this; + once(event: string, listener: Function): this; + once(event: "disconnect", listener: (worker: Worker) => void): this; + once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + once(event: "fork", listener: (worker: Worker) => void): this; + once(event: "listening", listener: (worker: Worker, address: Address) => void): this; + once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + once(event: "online", listener: (worker: Worker) => void): this; + once(event: "setup", listener: (settings: any) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "disconnect", listener: (worker: Worker) => void): this; - prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - prependListener(event: "fork", listener: (worker: Worker) => void): this; - prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependListener(event: "online", listener: (worker: Worker) => void): this; - prependListener(event: "setup", listener: (settings: any) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "disconnect", listener: (worker: Worker) => void): this; + prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + prependListener(event: "fork", listener: (worker: Worker) => void): this; + prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependListener(event: "online", listener: (worker: Worker) => void): this; + prependListener(event: "setup", listener: (settings: any) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this; - prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; - prependOnceListener(event: "fork", listener: (worker: Worker) => void): this; - prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; - prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. - prependOnceListener(event: "online", listener: (worker: Worker) => void): this; - prependOnceListener(event: "setup", listener: (settings: any) => void): this; + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this; + prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this; + prependOnceListener(event: "fork", listener: (worker: Worker) => void): this; + prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this; + prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined. + prependOnceListener(event: "online", listener: (worker: Worker) => void): this; + prependOnceListener(event: "setup", listener: (settings: any) => void): this; - } + } - export function disconnect(callback?: Function): void; - export function fork(env?: any): Worker; - export var isMaster: boolean; - export var isWorker: boolean; - // TODO: cluster.schedulingPolicy - export var settings: ClusterSettings; - export function setupMaster(settings?: ClusterSetupMasterSettings): void; - export var worker: Worker; - export var workers: { - [index: string]: Worker - }; + export function disconnect(callback?: Function): void; + export function fork(env?: any): Worker; + export var isMaster: boolean; + export var isWorker: boolean; + // TODO: cluster.schedulingPolicy + export var settings: ClusterSettings; + export function setupMaster(settings?: ClusterSetupMasterSettings): void; + export var worker: Worker; + export var workers: { + [index: string]: Worker + }; /** * events.EventEmitter @@ -1024,444 +1024,444 @@ declare module "cluster" { * 6. online * 7. setup */ - export function addListener(event: string, listener: Function): Cluster; - export function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function addListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function addListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function addListener(event: "setup", listener: (settings: any) => void): Cluster; + export function addListener(event: string, listener: Function): Cluster; + export function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + export function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + export function addListener(event: "fork", listener: (worker: Worker) => void): Cluster; + export function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + export function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + export function addListener(event: "online", listener: (worker: Worker) => void): Cluster; + export function addListener(event: "setup", listener: (settings: any) => void): Cluster; - export function emit(event: string | symbol, ...args: any[]): boolean; - export function emit(event: "disconnect", listener: (worker: Worker) => void): boolean; - export function emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; - export function emit(event: "fork", listener: (worker: Worker) => void): boolean; - export function emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; - export function emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; - export function emit(event: "online", listener: (worker: Worker) => void): boolean; - export function emit(event: "setup", listener: (settings: any) => void): boolean; + export function emit(event: string | symbol, ...args: any[]): boolean; + export function emit(event: "disconnect", listener: (worker: Worker) => void): boolean; + export function emit(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): boolean; + export function emit(event: "fork", listener: (worker: Worker) => void): boolean; + export function emit(event: "listening", listener: (worker: Worker, address: Address) => void): boolean; + export function emit(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): boolean; + export function emit(event: "online", listener: (worker: Worker) => void): boolean; + export function emit(event: "setup", listener: (settings: any) => void): boolean; - export function on(event: string, listener: Function): Cluster; - export function on(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function on(event: "fork", listener: (worker: Worker) => void): Cluster; - export function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function on(event: "online", listener: (worker: Worker) => void): Cluster; - export function on(event: "setup", listener: (settings: any) => void): Cluster; + export function on(event: string, listener: Function): Cluster; + export function on(event: "disconnect", listener: (worker: Worker) => void): Cluster; + export function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + export function on(event: "fork", listener: (worker: Worker) => void): Cluster; + export function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + export function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + export function on(event: "online", listener: (worker: Worker) => void): Cluster; + export function on(event: "setup", listener: (settings: any) => void): Cluster; - export function once(event: string, listener: Function): Cluster; - export function once(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function once(event: "fork", listener: (worker: Worker) => void): Cluster; - export function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function once(event: "online", listener: (worker: Worker) => void): Cluster; - export function once(event: "setup", listener: (settings: any) => void): Cluster; + export function once(event: string, listener: Function): Cluster; + export function once(event: "disconnect", listener: (worker: Worker) => void): Cluster; + export function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + export function once(event: "fork", listener: (worker: Worker) => void): Cluster; + export function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + export function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + export function once(event: "online", listener: (worker: Worker) => void): Cluster; + export function once(event: "setup", listener: (settings: any) => void): Cluster; - export function removeListener(event: string, listener: Function): Cluster; - export function removeAllListeners(event?: string): Cluster; - export function setMaxListeners(n: number): Cluster; - export function getMaxListeners(): number; - export function listeners(event: string): Function[]; - export function listenerCount(type: string): number; + export function removeListener(event: string, listener: Function): Cluster; + export function removeAllListeners(event?: string): Cluster; + export function setMaxListeners(n: number): Cluster; + export function getMaxListeners(): number; + export function listeners(event: string): Function[]; + export function listenerCount(type: string): number; - export function prependListener(event: string, listener: Function): Cluster; - export function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function prependListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function prependListener(event: "setup", listener: (settings: any) => void): Cluster; + export function prependListener(event: string, listener: Function): Cluster; + export function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + export function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + export function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster; + export function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + export function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + export function prependListener(event: "online", listener: (worker: Worker) => void): Cluster; + export function prependListener(event: "setup", listener: (settings: any) => void): Cluster; - export function prependOnceListener(event: string, listener: Function): Cluster; - export function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; - export function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; - export function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. - export function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster; - export function prependOnceListener(event: "setup", listener: (settings: any) => void): Cluster; + export function prependOnceListener(event: string, listener: Function): Cluster; + export function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster; + export function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster; + export function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster; + export function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster; + export function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined. + export function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster; + export function prependOnceListener(event: "setup", listener: (settings: any) => void): Cluster; - export function eventNames(): string[]; + export function eventNames(): string[]; } declare module "zlib" { - import * as stream from "stream"; + import * as stream from "stream"; - export interface ZlibOptions { - flush?: number; // default: zlib.constants.Z_NO_FLUSH - finishFlush?: number; // default: zlib.constants.Z_FINISH - chunkSize?: number; // default: 16*1024 - windowBits?: number; - level?: number; // compression only - memLevel?: number; // compression only - strategy?: number; // compression only - dictionary?: any; // deflate/inflate only, empty dictionary by default - } + export interface ZlibOptions { + flush?: number; // default: zlib.constants.Z_NO_FLUSH + finishFlush?: number; // default: zlib.constants.Z_FINISH + chunkSize?: number; // default: 16*1024 + windowBits?: number; + level?: number; // compression only + memLevel?: number; // compression only + strategy?: number; // compression only + dictionary?: any; // deflate/inflate only, empty dictionary by default + } - export interface Gzip extends stream.Transform { } - export interface Gunzip extends stream.Transform { } - export interface Deflate extends stream.Transform { } - export interface Inflate extends stream.Transform { } - export interface DeflateRaw extends stream.Transform { } - export interface InflateRaw extends stream.Transform { } - export interface Unzip extends stream.Transform { } + export interface Gzip extends stream.Transform { } + export interface Gunzip extends stream.Transform { } + export interface Deflate extends stream.Transform { } + export interface Inflate extends stream.Transform { } + export interface DeflateRaw extends stream.Transform { } + export interface InflateRaw extends stream.Transform { } + export interface Unzip extends stream.Transform { } - export function createGzip(options?: ZlibOptions): Gzip; - export function createGunzip(options?: ZlibOptions): Gunzip; - export function createDeflate(options?: ZlibOptions): Deflate; - export function createInflate(options?: ZlibOptions): Inflate; - export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; - export function createInflateRaw(options?: ZlibOptions): InflateRaw; - export function createUnzip(options?: ZlibOptions): Unzip; + export function createGzip(options?: ZlibOptions): Gzip; + export function createGunzip(options?: ZlibOptions): Gunzip; + export function createDeflate(options?: ZlibOptions): Deflate; + export function createInflate(options?: ZlibOptions): Inflate; + export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; + export function createInflateRaw(options?: ZlibOptions): InflateRaw; + export function createUnzip(options?: ZlibOptions): Unzip; - export function deflate(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function deflate(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function deflateSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function deflateRaw(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function deflateRaw(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function deflateRawSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function gzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function gzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function gzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function gunzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function gunzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function gunzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function inflate(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function inflate(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function inflateSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function inflateRaw(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function inflateRaw(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function inflateRawSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export function unzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; - export function unzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; - export function unzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function deflate(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function deflate(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function deflateSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function deflateRaw(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function deflateRaw(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function deflateRawSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function gzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function gzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function gzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function gunzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function gunzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function gunzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function inflate(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function inflate(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function inflateSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function inflateRaw(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function inflateRaw(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function inflateRawSync(buf: Buffer | string, options?: ZlibOptions): Buffer; + export function unzip(buf: Buffer | string, callback: (error: Error, result: Buffer) => void): void; + export function unzip(buf: Buffer | string, options: ZlibOptions, callback: (error: Error, result: Buffer) => void): void; + export function unzipSync(buf: Buffer | string, options?: ZlibOptions): Buffer; - export namespace constants { - // Allowed flush values. + export namespace constants { + // Allowed flush values. - export const Z_NO_FLUSH: number; - export const Z_PARTIAL_FLUSH: number; - export const Z_SYNC_FLUSH: number; - export const Z_FULL_FLUSH: number; - export const Z_FINISH: number; - export const Z_BLOCK: number; - export const Z_TREES: number; + export const Z_NO_FLUSH: number; + export const Z_PARTIAL_FLUSH: number; + export const Z_SYNC_FLUSH: number; + export const Z_FULL_FLUSH: number; + export const Z_FINISH: number; + export const Z_BLOCK: number; + export const Z_TREES: number; - // Return codes for the compression/decompression functions. Negative values are errors, positive values are used for special but normal events. + // Return codes for the compression/decompression functions. Negative values are errors, positive values are used for special but normal events. - export const Z_OK: number; - export const Z_STREAM_END: number; - export const Z_NEED_DICT: number; - export const Z_ERRNO: number; - export const Z_STREAM_ERROR: number; - export const Z_DATA_ERROR: number; - export const Z_MEM_ERROR: number; - export const Z_BUF_ERROR: number; - export const Z_VERSION_ERROR: number; + export const Z_OK: number; + export const Z_STREAM_END: number; + export const Z_NEED_DICT: number; + export const Z_ERRNO: number; + export const Z_STREAM_ERROR: number; + export const Z_DATA_ERROR: number; + export const Z_MEM_ERROR: number; + export const Z_BUF_ERROR: number; + export const Z_VERSION_ERROR: number; - // Compression levels. + // Compression levels. - export const Z_NO_COMPRESSION: number; - export const Z_BEST_SPEED: number; - export const Z_BEST_COMPRESSION: number; - export const Z_DEFAULT_COMPRESSION: number; + export const Z_NO_COMPRESSION: number; + export const Z_BEST_SPEED: number; + export const Z_BEST_COMPRESSION: number; + export const Z_DEFAULT_COMPRESSION: number; - // Compression strategy. + // Compression strategy. - export const Z_FILTERED: number; - export const Z_HUFFMAN_ONLY: number; - export const Z_RLE: number; - export const Z_FIXED: number; - export const Z_DEFAULT_STRATEGY: number; - } + export const Z_FILTERED: number; + export const Z_HUFFMAN_ONLY: number; + export const Z_RLE: number; + export const Z_FIXED: number; + export const Z_DEFAULT_STRATEGY: number; + } - // Constants - export var Z_NO_FLUSH: number; - export var Z_PARTIAL_FLUSH: number; - export var Z_SYNC_FLUSH: number; - export var Z_FULL_FLUSH: number; - export var Z_FINISH: number; - export var Z_BLOCK: number; - export var Z_TREES: number; - export var Z_OK: number; - export var Z_STREAM_END: number; - export var Z_NEED_DICT: number; - export var Z_ERRNO: number; - export var Z_STREAM_ERROR: number; - export var Z_DATA_ERROR: number; - export var Z_MEM_ERROR: number; - export var Z_BUF_ERROR: number; - export var Z_VERSION_ERROR: number; - export var Z_NO_COMPRESSION: number; - export var Z_BEST_SPEED: number; - export var Z_BEST_COMPRESSION: number; - export var Z_DEFAULT_COMPRESSION: number; - export var Z_FILTERED: number; - export var Z_HUFFMAN_ONLY: number; - export var Z_RLE: number; - export var Z_FIXED: number; - export var Z_DEFAULT_STRATEGY: number; - export var Z_BINARY: number; - export var Z_TEXT: number; - export var Z_ASCII: number; - export var Z_UNKNOWN: number; - export var Z_DEFLATED: number; + // Constants + export var Z_NO_FLUSH: number; + export var Z_PARTIAL_FLUSH: number; + export var Z_SYNC_FLUSH: number; + export var Z_FULL_FLUSH: number; + export var Z_FINISH: number; + export var Z_BLOCK: number; + export var Z_TREES: number; + export var Z_OK: number; + export var Z_STREAM_END: number; + export var Z_NEED_DICT: number; + export var Z_ERRNO: number; + export var Z_STREAM_ERROR: number; + export var Z_DATA_ERROR: number; + export var Z_MEM_ERROR: number; + export var Z_BUF_ERROR: number; + export var Z_VERSION_ERROR: number; + export var Z_NO_COMPRESSION: number; + export var Z_BEST_SPEED: number; + export var Z_BEST_COMPRESSION: number; + export var Z_DEFAULT_COMPRESSION: number; + export var Z_FILTERED: number; + export var Z_HUFFMAN_ONLY: number; + export var Z_RLE: number; + export var Z_FIXED: number; + export var Z_DEFAULT_STRATEGY: number; + export var Z_BINARY: number; + export var Z_TEXT: number; + export var Z_ASCII: number; + export var Z_UNKNOWN: number; + export var Z_DEFLATED: number; } declare module "os" { - export interface CpuInfo { - model: string; - speed: number; - times: { - user: number; - nice: number; - sys: number; - idle: number; - irq: number; - }; - } + export interface CpuInfo { + model: string; + speed: number; + times: { + user: number; + nice: number; + sys: number; + idle: number; + irq: number; + }; + } - export interface NetworkInterfaceInfo { - address: string; - netmask: string; - family: string; - mac: string; - internal: boolean; - } + export interface NetworkInterfaceInfo { + address: string; + netmask: string; + family: string; + mac: string; + internal: boolean; + } - export function hostname(): string; - export function loadavg(): number[]; - export function uptime(): number; - export function freemem(): number; - export function totalmem(): number; - export function cpus(): CpuInfo[]; - export function type(): string; - export function release(): string; - export function networkInterfaces(): { [index: string]: NetworkInterfaceInfo[] }; - export function homedir(): string; - export function userInfo(options?: { encoding: string }): { username: string, uid: number, gid: number, shell: any, homedir: string } - export var constants: { - UV_UDP_REUSEADDR: number, - signals: { - SIGHUP: number; - SIGINT: number; - SIGQUIT: number; - SIGILL: number; - SIGTRAP: number; - SIGABRT: number; - SIGIOT: number; - SIGBUS: number; - SIGFPE: number; - SIGKILL: number; - SIGUSR1: number; - SIGSEGV: number; - SIGUSR2: number; - SIGPIPE: number; - SIGALRM: number; - SIGTERM: number; - SIGCHLD: number; - SIGSTKFLT: number; - SIGCONT: number; - SIGSTOP: number; - SIGTSTP: number; - SIGTTIN: number; - SIGTTOU: number; - SIGURG: number; - SIGXCPU: number; - SIGXFSZ: number; - SIGVTALRM: number; - SIGPROF: number; - SIGWINCH: number; - SIGIO: number; - SIGPOLL: number; - SIGPWR: number; - SIGSYS: number; - SIGUNUSED: number; - }, - errno: { - E2BIG: number; - EACCES: number; - EADDRINUSE: number; - EADDRNOTAVAIL: number; - EAFNOSUPPORT: number; - EAGAIN: number; - EALREADY: number; - EBADF: number; - EBADMSG: number; - EBUSY: number; - ECANCELED: number; - ECHILD: number; - ECONNABORTED: number; - ECONNREFUSED: number; - ECONNRESET: number; - EDEADLK: number; - EDESTADDRREQ: number; - EDOM: number; - EDQUOT: number; - EEXIST: number; - EFAULT: number; - EFBIG: number; - EHOSTUNREACH: number; - EIDRM: number; - EILSEQ: number; - EINPROGRESS: number; - EINTR: number; - EINVAL: number; - EIO: number; - EISCONN: number; - EISDIR: number; - ELOOP: number; - EMFILE: number; - EMLINK: number; - EMSGSIZE: number; - EMULTIHOP: number; - ENAMETOOLONG: number; - ENETDOWN: number; - ENETRESET: number; - ENETUNREACH: number; - ENFILE: number; - ENOBUFS: number; - ENODATA: number; - ENODEV: number; - ENOENT: number; - ENOEXEC: number; - ENOLCK: number; - ENOLINK: number; - ENOMEM: number; - ENOMSG: number; - ENOPROTOOPT: number; - ENOSPC: number; - ENOSR: number; - ENOSTR: number; - ENOSYS: number; - ENOTCONN: number; - ENOTDIR: number; - ENOTEMPTY: number; - ENOTSOCK: number; - ENOTSUP: number; - ENOTTY: number; - ENXIO: number; - EOPNOTSUPP: number; - EOVERFLOW: number; - EPERM: number; - EPIPE: number; - EPROTO: number; - EPROTONOSUPPORT: number; - EPROTOTYPE: number; - ERANGE: number; - EROFS: number; - ESPIPE: number; - ESRCH: number; - ESTALE: number; - ETIME: number; - ETIMEDOUT: number; - ETXTBSY: number; - EWOULDBLOCK: number; - EXDEV: number; - }, - }; - export function arch(): string; - export function platform(): NodeJS.Platform; - export function tmpdir(): string; - export var EOL: string; - export function endianness(): "BE" | "LE"; + export function hostname(): string; + export function loadavg(): number[]; + export function uptime(): number; + export function freemem(): number; + export function totalmem(): number; + export function cpus(): CpuInfo[]; + export function type(): string; + export function release(): string; + export function networkInterfaces(): { [index: string]: NetworkInterfaceInfo[] }; + export function homedir(): string; + export function userInfo(options?: { encoding: string }): { username: string, uid: number, gid: number, shell: any, homedir: string } + export var constants: { + UV_UDP_REUSEADDR: number, + signals: { + SIGHUP: number; + SIGINT: number; + SIGQUIT: number; + SIGILL: number; + SIGTRAP: number; + SIGABRT: number; + SIGIOT: number; + SIGBUS: number; + SIGFPE: number; + SIGKILL: number; + SIGUSR1: number; + SIGSEGV: number; + SIGUSR2: number; + SIGPIPE: number; + SIGALRM: number; + SIGTERM: number; + SIGCHLD: number; + SIGSTKFLT: number; + SIGCONT: number; + SIGSTOP: number; + SIGTSTP: number; + SIGTTIN: number; + SIGTTOU: number; + SIGURG: number; + SIGXCPU: number; + SIGXFSZ: number; + SIGVTALRM: number; + SIGPROF: number; + SIGWINCH: number; + SIGIO: number; + SIGPOLL: number; + SIGPWR: number; + SIGSYS: number; + SIGUNUSED: number; + }, + errno: { + E2BIG: number; + EACCES: number; + EADDRINUSE: number; + EADDRNOTAVAIL: number; + EAFNOSUPPORT: number; + EAGAIN: number; + EALREADY: number; + EBADF: number; + EBADMSG: number; + EBUSY: number; + ECANCELED: number; + ECHILD: number; + ECONNABORTED: number; + ECONNREFUSED: number; + ECONNRESET: number; + EDEADLK: number; + EDESTADDRREQ: number; + EDOM: number; + EDQUOT: number; + EEXIST: number; + EFAULT: number; + EFBIG: number; + EHOSTUNREACH: number; + EIDRM: number; + EILSEQ: number; + EINPROGRESS: number; + EINTR: number; + EINVAL: number; + EIO: number; + EISCONN: number; + EISDIR: number; + ELOOP: number; + EMFILE: number; + EMLINK: number; + EMSGSIZE: number; + EMULTIHOP: number; + ENAMETOOLONG: number; + ENETDOWN: number; + ENETRESET: number; + ENETUNREACH: number; + ENFILE: number; + ENOBUFS: number; + ENODATA: number; + ENODEV: number; + ENOENT: number; + ENOEXEC: number; + ENOLCK: number; + ENOLINK: number; + ENOMEM: number; + ENOMSG: number; + ENOPROTOOPT: number; + ENOSPC: number; + ENOSR: number; + ENOSTR: number; + ENOSYS: number; + ENOTCONN: number; + ENOTDIR: number; + ENOTEMPTY: number; + ENOTSOCK: number; + ENOTSUP: number; + ENOTTY: number; + ENXIO: number; + EOPNOTSUPP: number; + EOVERFLOW: number; + EPERM: number; + EPIPE: number; + EPROTO: number; + EPROTONOSUPPORT: number; + EPROTOTYPE: number; + ERANGE: number; + EROFS: number; + ESPIPE: number; + ESRCH: number; + ESTALE: number; + ETIME: number; + ETIMEDOUT: number; + ETXTBSY: number; + EWOULDBLOCK: number; + EXDEV: number; + }, + }; + export function arch(): string; + export function platform(): NodeJS.Platform; + export function tmpdir(): string; + export var EOL: string; + export function endianness(): "BE" | "LE"; } declare module "https" { - import * as tls from "tls"; - import * as events from "events"; - import * as http from "http"; + import * as tls from "tls"; + import * as events from "events"; + import * as http from "http"; - export interface ServerOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - crl?: any; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: any; - SNICallback?: (servername: string, cb: (err: Error, ctx: tls.SecureContext) => any) => any; - } + export interface ServerOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + crl?: any; + ciphers?: string; + honorCipherOrder?: boolean; + requestCert?: boolean; + rejectUnauthorized?: boolean; + NPNProtocols?: any; + SNICallback?: (servername: string, cb: (err: Error, ctx: tls.SecureContext) => any) => any; + } - export interface RequestOptions extends http.RequestOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - } + export interface RequestOptions extends http.RequestOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + ciphers?: string; + rejectUnauthorized?: boolean; + secureProtocol?: string; + } - export interface Agent extends http.Agent { } + export interface Agent extends http.Agent { } - export interface AgentOptions extends http.AgentOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - maxCachedSessions?: number; - } + export interface AgentOptions extends http.AgentOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + ciphers?: string; + rejectUnauthorized?: boolean; + secureProtocol?: string; + maxCachedSessions?: number; + } - export var Agent: { - new(options?: AgentOptions): Agent; - }; - export interface Server extends tls.Server { } - export function createServer(options: ServerOptions, requestListener?: Function): Server; - export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export var globalAgent: Agent; + export var Agent: { + new(options?: AgentOptions): Agent; + }; + export interface Server extends tls.Server { } + export function createServer(options: ServerOptions, requestListener?: Function): Server; + export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + export var globalAgent: Agent; } declare module "punycode" { - export function decode(string: string): string; - export function encode(string: string): string; - export function toUnicode(domain: string): string; - export function toASCII(domain: string): string; - export var ucs2: ucs2; - interface ucs2 { - decode(string: string): number[]; - encode(codePoints: number[]): string; - } - export var version: any; + export function decode(string: string): string; + export function encode(string: string): string; + export function toUnicode(domain: string): string; + export function toASCII(domain: string): string; + export var ucs2: ucs2; + interface ucs2 { + decode(string: string): number[]; + encode(codePoints: number[]): string; + } + export var version: any; } declare module "repl" { - import * as stream from "stream"; - import * as readline from "readline"; + import * as stream from "stream"; + import * as readline from "readline"; - export interface ReplOptions { - prompt?: string; - input?: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - eval?: Function; - useColors?: boolean; - useGlobal?: boolean; - ignoreUndefined?: boolean; - writer?: Function; - completer?: Function; - replMode?: any; - breakEvalOnSigint?: any; - } + export interface ReplOptions { + prompt?: string; + input?: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + terminal?: boolean; + eval?: Function; + useColors?: boolean; + useGlobal?: boolean; + ignoreUndefined?: boolean; + writer?: Function; + completer?: Function; + replMode?: any; + breakEvalOnSigint?: any; + } - export interface REPLServer extends readline.ReadLine { - context: any; - defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void; - displayPrompt(preserveCursor?: boolean): void; + export interface REPLServer extends readline.ReadLine { + context: any; + defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void; + displayPrompt(preserveCursor?: boolean): void; /** * events.EventEmitter @@ -1469,54 +1469,54 @@ declare module "repl" { * 2. reset **/ - addListener(event: string, listener: Function): this; - addListener(event: "exit", listener: () => void): this; - addListener(event: "reset", listener: Function): this; + addListener(event: string, listener: Function): this; + addListener(event: "exit", listener: () => void): this; + addListener(event: "reset", listener: Function): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "exit"): boolean; - emit(event: "reset", context: any): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "exit"): boolean; + emit(event: "reset", context: any): boolean; - on(event: string, listener: Function): this; - on(event: "exit", listener: () => void): this; - on(event: "reset", listener: Function): this; + on(event: string, listener: Function): this; + on(event: "exit", listener: () => void): this; + on(event: "reset", listener: Function): this; - once(event: string, listener: Function): this; - once(event: "exit", listener: () => void): this; - once(event: "reset", listener: Function): this; + once(event: string, listener: Function): this; + once(event: "exit", listener: () => void): this; + once(event: "reset", listener: Function): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "exit", listener: () => void): this; - prependListener(event: "reset", listener: Function): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "exit", listener: () => void): this; + prependListener(event: "reset", listener: Function): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "exit", listener: () => void): this; - prependOnceListener(event: "reset", listener: Function): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "exit", listener: () => void): this; + prependOnceListener(event: "reset", listener: Function): this; + } - export function start(options?: string | ReplOptions): REPLServer; + export function start(options?: string | ReplOptions): REPLServer; } declare module "readline" { - import * as events from "events"; - import * as stream from "stream"; + import * as events from "events"; + import * as stream from "stream"; - export interface Key { - sequence?: string; - name?: string; - ctrl?: boolean; - meta?: boolean; - shift?: boolean; - } + export interface Key { + sequence?: string; + name?: string; + ctrl?: boolean; + meta?: boolean; + shift?: boolean; + } - export interface ReadLine extends events.EventEmitter { - setPrompt(prompt: string): void; - prompt(preserveCursor?: boolean): void; - question(query: string, callback: (answer: string) => void): void; - pause(): ReadLine; - resume(): ReadLine; - close(): void; - write(data: string | Buffer, key?: Key): void; + export interface ReadLine extends events.EventEmitter { + setPrompt(prompt: string): void; + prompt(preserveCursor?: boolean): void; + question(query: string, callback: (answer: string) => void): void; + pause(): ReadLine; + resume(): ReadLine; + close(): void; + write(data: string | Buffer, key?: Key): void; /** * events.EventEmitter @@ -1529,136 +1529,136 @@ declare module "readline" { * 7. SIGTSTP **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "line", listener: (input: any) => void): this; - addListener(event: "pause", listener: () => void): this; - addListener(event: "resume", listener: () => void): this; - addListener(event: "SIGCONT", listener: () => void): this; - addListener(event: "SIGINT", listener: () => void): this; - addListener(event: "SIGTSTP", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "line", listener: (input: any) => void): this; + addListener(event: "pause", listener: () => void): this; + addListener(event: "resume", listener: () => void): this; + addListener(event: "SIGCONT", listener: () => void): this; + addListener(event: "SIGINT", listener: () => void): this; + addListener(event: "SIGTSTP", listener: () => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "line", input: any): boolean; - emit(event: "pause"): boolean; - emit(event: "resume"): boolean; - emit(event: "SIGCONT"): boolean; - emit(event: "SIGINT"): boolean; - emit(event: "SIGTSTP"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "line", input: any): boolean; + emit(event: "pause"): boolean; + emit(event: "resume"): boolean; + emit(event: "SIGCONT"): boolean; + emit(event: "SIGINT"): boolean; + emit(event: "SIGTSTP"): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "line", listener: (input: any) => void): this; - on(event: "pause", listener: () => void): this; - on(event: "resume", listener: () => void): this; - on(event: "SIGCONT", listener: () => void): this; - on(event: "SIGINT", listener: () => void): this; - on(event: "SIGTSTP", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "line", listener: (input: any) => void): this; + on(event: "pause", listener: () => void): this; + on(event: "resume", listener: () => void): this; + on(event: "SIGCONT", listener: () => void): this; + on(event: "SIGINT", listener: () => void): this; + on(event: "SIGTSTP", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "line", listener: (input: any) => void): this; - once(event: "pause", listener: () => void): this; - once(event: "resume", listener: () => void): this; - once(event: "SIGCONT", listener: () => void): this; - once(event: "SIGINT", listener: () => void): this; - once(event: "SIGTSTP", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "line", listener: (input: any) => void): this; + once(event: "pause", listener: () => void): this; + once(event: "resume", listener: () => void): this; + once(event: "SIGCONT", listener: () => void): this; + once(event: "SIGINT", listener: () => void): this; + once(event: "SIGTSTP", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "line", listener: (input: any) => void): this; - prependListener(event: "pause", listener: () => void): this; - prependListener(event: "resume", listener: () => void): this; - prependListener(event: "SIGCONT", listener: () => void): this; - prependListener(event: "SIGINT", listener: () => void): this; - prependListener(event: "SIGTSTP", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "line", listener: (input: any) => void): this; + prependListener(event: "pause", listener: () => void): this; + prependListener(event: "resume", listener: () => void): this; + prependListener(event: "SIGCONT", listener: () => void): this; + prependListener(event: "SIGINT", listener: () => void): this; + prependListener(event: "SIGTSTP", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "line", listener: (input: any) => void): this; - prependOnceListener(event: "pause", listener: () => void): this; - prependOnceListener(event: "resume", listener: () => void): this; - prependOnceListener(event: "SIGCONT", listener: () => void): this; - prependOnceListener(event: "SIGINT", listener: () => void): this; - prependOnceListener(event: "SIGTSTP", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "line", listener: (input: any) => void): this; + prependOnceListener(event: "pause", listener: () => void): this; + prependOnceListener(event: "resume", listener: () => void): this; + prependOnceListener(event: "SIGCONT", listener: () => void): this; + prependOnceListener(event: "SIGINT", listener: () => void): this; + prependOnceListener(event: "SIGTSTP", listener: () => void): this; + } - type Completer = (line: string) => CompleterResult; - type AsyncCompleter = (line: string, callback: (err: any, result: CompleterResult) => void) => any; + type Completer = (line: string) => CompleterResult; + type AsyncCompleter = (line: string, callback: (err: any, result: CompleterResult) => void) => any; - export type CompleterResult = [string[], string]; + export type CompleterResult = [string[], string]; - export interface ReadLineOptions { - input: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - completer?: Completer | AsyncCompleter; - terminal?: boolean; - historySize?: number; - prompt?: string; - crlfDelay?: number; - removeHistoryDuplicates?: boolean; - } + export interface ReadLineOptions { + input: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + completer?: Completer | AsyncCompleter; + terminal?: boolean; + historySize?: number; + prompt?: string; + crlfDelay?: number; + removeHistoryDuplicates?: boolean; + } - export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): ReadLine; - export function createInterface(options: ReadLineOptions): ReadLine; + export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): ReadLine; + export function createInterface(options: ReadLineOptions): ReadLine; - export function cursorTo(stream: NodeJS.WritableStream, x: number, y: number): void; - export function moveCursor(stream: NodeJS.WritableStream, dx: number | string, dy: number | string): void; - export function clearLine(stream: NodeJS.WritableStream, dir: number): void; - export function clearScreenDown(stream: NodeJS.WritableStream): void; + export function cursorTo(stream: NodeJS.WritableStream, x: number, y: number): void; + export function moveCursor(stream: NodeJS.WritableStream, dx: number | string, dy: number | string): void; + export function clearLine(stream: NodeJS.WritableStream, dir: number): void; + export function clearScreenDown(stream: NodeJS.WritableStream): void; } declare module "vm" { - export interface Context { } - export interface ScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - cachedData?: Buffer; - produceCachedData?: boolean; - } - export interface RunningScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - } - export class Script { - constructor(code: string, options?: ScriptOptions); - runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; - runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; - runInThisContext(options?: RunningScriptOptions): any; - } - export function createContext(sandbox?: Context): Context; - export function isContext(sandbox: Context): boolean; - export function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions): any; - export function runInDebugContext(code: string): any; - export function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions): any; - export function runInThisContext(code: string, options?: RunningScriptOptions): any; + export interface Context { } + export interface ScriptOptions { + filename?: string; + lineOffset?: number; + columnOffset?: number; + displayErrors?: boolean; + timeout?: number; + cachedData?: Buffer; + produceCachedData?: boolean; + } + export interface RunningScriptOptions { + filename?: string; + lineOffset?: number; + columnOffset?: number; + displayErrors?: boolean; + timeout?: number; + } + export class Script { + constructor(code: string, options?: ScriptOptions); + runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; + runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; + runInThisContext(options?: RunningScriptOptions): any; + } + export function createContext(sandbox?: Context): Context; + export function isContext(sandbox: Context): boolean; + export function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions): any; + export function runInDebugContext(code: string): any; + export function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions): any; + export function runInThisContext(code: string, options?: RunningScriptOptions): any; } declare module "child_process" { - import * as events from "events"; - import * as stream from "stream"; - import * as net from "net"; + import * as events from "events"; + import * as stream from "stream"; + import * as net from "net"; - export interface ChildProcess extends events.EventEmitter { - stdin: stream.Writable; - stdout: stream.Readable; - stderr: stream.Readable; - stdio: [stream.Writable, stream.Readable, stream.Readable]; - killed: boolean; - pid: number; - kill(signal?: string): void; - send(message: any, sendHandle?: any): boolean; - connected: boolean; - disconnect(): void; - unref(): void; - ref(): void; + export interface ChildProcess extends events.EventEmitter { + stdin: stream.Writable; + stdout: stream.Readable; + stderr: stream.Readable; + stdio: [stream.Writable, stream.Readable, stream.Readable]; + killed: boolean; + pid: number; + kill(signal?: string): void; + send(message: any, sendHandle?: any): boolean; + connected: boolean; + disconnect(): void; + unref(): void; + ref(): void; /** * events.EventEmitter @@ -1669,462 +1669,462 @@ declare module "child_process" { * 5. message **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: (code: number, signal: string) => void): this; - addListener(event: "disconnect", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "exit", listener: (code: number, signal: string) => void): this; - addListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: (code: number, signal: string) => void): this; + addListener(event: "disconnect", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "exit", listener: (code: number, signal: string) => void): this; + addListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close", code: number, signal: string): boolean; - emit(event: "disconnect"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "exit", code: number, signal: string): boolean; - emit(event: "message", message: any, sendHandle: net.Socket | net.Server): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close", code: number, signal: string): boolean; + emit(event: "disconnect"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "exit", code: number, signal: string): boolean; + emit(event: "message", message: any, sendHandle: net.Socket | net.Server): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: (code: number, signal: string) => void): this; - on(event: "disconnect", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "exit", listener: (code: number, signal: string) => void): this; - on(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: (code: number, signal: string) => void): this; + on(event: "disconnect", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "exit", listener: (code: number, signal: string) => void): this; + on(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: (code: number, signal: string) => void): this; - once(event: "disconnect", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "exit", listener: (code: number, signal: string) => void): this; - once(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: (code: number, signal: string) => void): this; + once(event: "disconnect", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "exit", listener: (code: number, signal: string) => void): this; + once(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: (code: number, signal: string) => void): this; - prependListener(event: "disconnect", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: (code: number, signal: string) => void): this; + prependListener(event: "disconnect", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: (code: number, signal: string) => void): this; - prependOnceListener(event: "disconnect", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; - prependOnceListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: (code: number, signal: string) => void): this; + prependOnceListener(event: "disconnect", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this; + prependOnceListener(event: "message", listener: (message: any, sendHandle: net.Socket | net.Server) => void): this; + } - export interface SpawnOptions { - cwd?: string; - env?: any; - stdio?: any; - detached?: boolean; - uid?: number; - gid?: number; - shell?: boolean | string; - windowsVerbatimArguments?: boolean; - } - export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; + export interface SpawnOptions { + cwd?: string; + env?: any; + stdio?: any; + detached?: boolean; + uid?: number; + gid?: number; + shell?: boolean | string; + windowsVerbatimArguments?: boolean; + } + export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; - export interface ExecOptions { - cwd?: string; - env?: any; - shell?: string; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecOptionsWithStringEncoding extends ExecOptions { - encoding: BufferEncoding; - } - export interface ExecOptionsWithBufferEncoding extends ExecOptions { - encoding: string; // specify `null`. - } - export function exec(command: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function exec(command: string, options: ExecOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.exec("tsc", {encoding: null as string}, (err, stdout, stderr) => {}); - export function exec(command: string, options: ExecOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function exec(command: string, options: ExecOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export interface ExecOptions { + cwd?: string; + env?: any; + shell?: string; + timeout?: number; + maxBuffer?: number; + killSignal?: string; + uid?: number; + gid?: number; + } + export interface ExecOptionsWithStringEncoding extends ExecOptions { + encoding: BufferEncoding; + } + export interface ExecOptionsWithBufferEncoding extends ExecOptions { + encoding: string; // specify `null`. + } + export function exec(command: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function exec(command: string, options: ExecOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.exec("tsc", {encoding: null as string}, (err, stdout, stderr) => {}); + export function exec(command: string, options: ExecOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function exec(command: string, options: ExecOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export interface ExecFileOptions { - cwd?: string; - env?: any; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { - encoding: BufferEncoding; - } - export interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { - encoding: string; // specify `null`. - } - export function execFile(file: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", ["foo"], {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export interface ExecFileOptions { + cwd?: string; + env?: any; + timeout?: number; + maxBuffer?: number; + killSignal?: string; + uid?: number; + gid?: number; + } + export interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { + encoding: BufferEncoding; + } + export interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { + encoding: string; // specify `null`. + } + export function execFile(file: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.execFile("file.sh", {encoding: null as string}, (err, stdout, stderr) => {}); + export function execFile(file: string, options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function execFile(file: string, options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, args?: string[], callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.execFile("file.sh", ["foo"], {encoding: null as string}, (err, stdout, stderr) => {}); + export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function execFile(file: string, args?: string[], options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export interface ForkOptions { - cwd?: string; - env?: any; - execPath?: string; - execArgv?: string[]; - silent?: boolean; - stdio?: any[]; - uid?: number; - gid?: number; - } - export function fork(modulePath: string, args?: string[], options?: ForkOptions): ChildProcess; + export interface ForkOptions { + cwd?: string; + env?: any; + execPath?: string; + execArgv?: string[]; + silent?: boolean; + stdio?: any[]; + uid?: number; + gid?: number; + } + export function fork(modulePath: string, args?: string[], options?: ForkOptions): ChildProcess; - export interface SpawnSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - shell?: boolean | string; - } - export interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { - encoding: BufferEncoding; - } - export interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { - encoding: string; // specify `null`. - } - export interface SpawnSyncReturns<T> { - pid: number; - output: string[]; - stdout: T; - stderr: T; - status: number; - signal: string; - error: Error; - } - export function spawnSync(command: string): SpawnSyncReturns<Buffer>; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns<string>; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns<Buffer>; - export function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns<Buffer>; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns<string>; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns<Buffer>; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptions): SpawnSyncReturns<Buffer>; + export interface SpawnSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + shell?: boolean | string; + } + export interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { + encoding: BufferEncoding; + } + export interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { + encoding: string; // specify `null`. + } + export interface SpawnSyncReturns<T> { + pid: number; + output: string[]; + stdout: T; + stderr: T; + status: number; + signal: string; + error: Error; + } + export function spawnSync(command: string): SpawnSyncReturns<Buffer>; + export function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns<string>; + export function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns<Buffer>; + export function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns<Buffer>; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns<string>; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns<Buffer>; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptions): SpawnSyncReturns<Buffer>; - export interface ExecSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - shell?: string; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { - encoding: BufferEncoding; - } - export interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { - encoding: string; // specify `null`. - } - export function execSync(command: string): Buffer; - export function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; - export function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; - export function execSync(command: string, options?: ExecSyncOptions): Buffer; + export interface ExecSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + shell?: string; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + } + export interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { + encoding: BufferEncoding; + } + export interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { + encoding: string; // specify `null`. + } + export function execSync(command: string): Buffer; + export function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; + export function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; + export function execSync(command: string, options?: ExecSyncOptions): Buffer; - export interface ExecFileSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { - encoding: BufferEncoding; - } - export interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { - encoding: string; // specify `null`. - } - export function execFileSync(command: string): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptions): Buffer; + export interface ExecFileSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + } + export interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { + encoding: BufferEncoding; + } + export interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { + encoding: string; // specify `null`. + } + export function execFileSync(command: string): Buffer; + export function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; + export function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + export function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithStringEncoding): string; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptions): Buffer; } declare module "url" { - export interface Url { - href?: string; - protocol?: string; - auth?: string; - hostname?: string; - port?: string; - host?: string; - pathname?: string; - search?: string; - query?: string | any; - slashes?: boolean; - hash?: string; - path?: string; - } + export interface Url { + href?: string; + protocol?: string; + auth?: string; + hostname?: string; + port?: string; + host?: string; + pathname?: string; + search?: string; + query?: string | any; + slashes?: boolean; + hash?: string; + path?: string; + } - export interface UrlObject { - protocol?: string; - slashes?: boolean; - auth?: string; - host?: string; - hostname?: string; - port?: string | number; - pathname?: string; - search?: string; - query?: { [key: string]: any; }; - hash?: string; - } + export interface UrlObject { + protocol?: string; + slashes?: boolean; + auth?: string; + host?: string; + hostname?: string; + port?: string | number; + pathname?: string; + search?: string; + query?: { [key: string]: any; }; + hash?: string; + } - export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url; - export function format(URL: URL, options?: URLFormatOptions): string; - export function format(urlObject: UrlObject): string; - export function resolve(from: string, to: string): string; + export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url; + export function format(URL: URL, options?: URLFormatOptions): string; + export function format(urlObject: UrlObject): string; + export function resolve(from: string, to: string): string; - export interface URLFormatOptions { - auth?: boolean; - fragment?: boolean; - search?: boolean; - unicode?: boolean; - } + export interface URLFormatOptions { + auth?: boolean; + fragment?: boolean; + search?: boolean; + unicode?: boolean; + } - export class URLSearchParams implements Iterable<string[]> { - constructor(init?: URLSearchParams | string | { [key: string]: string | string[] } | Iterable<string[]>); - append(name: string, value: string): void; - delete(name: string): void; - entries(): Iterator<string[]>; - forEach(callback: (value: string, name: string) => void): void; - get(name: string): string | null; - getAll(name: string): string[]; - has(name: string): boolean; - keys(): Iterator<string>; - set(name: string, value: string): void; - sort(): void; - toString(): string; - values(): Iterator<string>; - [Symbol.iterator](): Iterator<string[]>; - } + export class URLSearchParams implements Iterable<string[]> { + constructor(init?: URLSearchParams | string | { [key: string]: string | string[] } | Iterable<string[]>); + append(name: string, value: string): void; + delete(name: string): void; + entries(): Iterator<string[]>; + forEach(callback: (value: string, name: string) => void): void; + get(name: string): string | null; + getAll(name: string): string[]; + has(name: string): boolean; + keys(): Iterator<string>; + set(name: string, value: string): void; + sort(): void; + toString(): string; + values(): Iterator<string>; + [Symbol.iterator](): Iterator<string[]>; + } - export class URL { - constructor(input: string, base?: string | URL); - hash: string; - host: string; - hostname: string; - href: string; - readonly origin: string; - password: string; - pathname: string; - port: string; - protocol: string; - search: string; - readonly searchParams: URLSearchParams; - username: string; - toString(): string; - toJSON(): string; - } + export class URL { + constructor(input: string, base?: string | URL); + hash: string; + host: string; + hostname: string; + href: string; + readonly origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + readonly searchParams: URLSearchParams; + username: string; + toString(): string; + toJSON(): string; + } } declare module "dns" { - // Supported getaddrinfo flags. - export const ADDRCONFIG: number; - export const V4MAPPED: number; + // Supported getaddrinfo flags. + export const ADDRCONFIG: number; + export const V4MAPPED: number; - export interface LookupOptions { - family?: number; - hints?: number; - all?: boolean; - } + export interface LookupOptions { + family?: number; + hints?: number; + all?: boolean; + } - export interface LookupOneOptions extends LookupOptions { - all?: false; - } + export interface LookupOneOptions extends LookupOptions { + all?: false; + } - export interface LookupAllOptions extends LookupOptions { - all: true; - } + export interface LookupAllOptions extends LookupOptions { + all: true; + } - export interface LookupAddress { - address: string; - family: number; - } + export interface LookupAddress { + address: string; + family: number; + } - export function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; - export function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; - export function lookup(hostname: string, options: LookupAllOptions, callback: (err: NodeJS.ErrnoException, addresses: LookupAddress[]) => void): void; - export function lookup(hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException, address: string | LookupAddress[], family: number) => void): void; - export function lookup(hostname: string, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; + export function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; + export function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; + export function lookup(hostname: string, options: LookupAllOptions, callback: (err: NodeJS.ErrnoException, addresses: LookupAddress[]) => void): void; + export function lookup(hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException, address: string | LookupAddress[], family: number) => void): void; + export function lookup(hostname: string, callback: (err: NodeJS.ErrnoException, address: string, family: number) => void): void; - export interface ResolveOptions { - ttl: boolean; - } + export interface ResolveOptions { + ttl: boolean; + } - export interface ResolveWithTtlOptions extends ResolveOptions { - ttl: true; - } + export interface ResolveWithTtlOptions extends ResolveOptions { + ttl: true; + } - export interface RecordWithTtl { - address: string; - ttl: number; - } + export interface RecordWithTtl { + address: string; + ttl: number; + } - export interface MxRecord { - priority: number; - exchange: string; - } + export interface MxRecord { + priority: number; + exchange: string; + } - export interface NaptrRecord { - flags: string; - service: string; - regexp: string; - replacement: string; - order: number; - preference: number; - } + export interface NaptrRecord { + flags: string; + service: string; + regexp: string; + replacement: string; + order: number; + preference: number; + } - export interface SoaRecord { - nsname: string; - hostmaster: string; - serial: number; - refresh: number; - retry: number; - expire: number; - minttl: number; - } + export interface SoaRecord { + nsname: string; + hostmaster: string; + serial: number; + refresh: number; + retry: number; + expire: number; + minttl: number; + } - export interface SrvRecord { - priority: number; - weight: number; - port: number; - name: string; - } + export interface SrvRecord { + priority: number; + weight: number; + port: number; + name: string; + } - export function resolve(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "A", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "AAAA", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "CNAME", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "MX", callback: (err: NodeJS.ErrnoException, addresses: MxRecord[]) => void): void; - export function resolve(hostname: string, rrtype: "NAPTR", callback: (err: NodeJS.ErrnoException, addresses: NaptrRecord[]) => void): void; - export function resolve(hostname: string, rrtype: "NS", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "PTR", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve(hostname: string, rrtype: "SOA", callback: (err: NodeJS.ErrnoException, addresses: SoaRecord) => void): void; - export function resolve(hostname: string, rrtype: "SRV", callback: (err: NodeJS.ErrnoException, addresses: SrvRecord[]) => void): void; - export function resolve(hostname: string, rrtype: "TXT", callback: (err: NodeJS.ErrnoException, addresses: string[][]) => void): void; - export function resolve(hostname: string, rrtype: string, callback: (err: NodeJS.ErrnoException, addresses: string[] | MxRecord[] | NaptrRecord[] | SoaRecord | SrvRecord[] | string[][]) => void): void; + export function resolve(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "A", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "AAAA", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "CNAME", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "MX", callback: (err: NodeJS.ErrnoException, addresses: MxRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "NAPTR", callback: (err: NodeJS.ErrnoException, addresses: NaptrRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "NS", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "PTR", callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve(hostname: string, rrtype: "SOA", callback: (err: NodeJS.ErrnoException, addresses: SoaRecord) => void): void; + export function resolve(hostname: string, rrtype: "SRV", callback: (err: NodeJS.ErrnoException, addresses: SrvRecord[]) => void): void; + export function resolve(hostname: string, rrtype: "TXT", callback: (err: NodeJS.ErrnoException, addresses: string[][]) => void): void; + export function resolve(hostname: string, rrtype: string, callback: (err: NodeJS.ErrnoException, addresses: string[] | MxRecord[] | NaptrRecord[] | SoaRecord | SrvRecord[] | string[][]) => void): void; - export function resolve4(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve4(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException, addresses: RecordWithTtl[]) => void): void; - export function resolve4(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException, addresses: string[] | RecordWithTtl[]) => void): void; + export function resolve4(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve4(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException, addresses: RecordWithTtl[]) => void): void; + export function resolve4(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException, addresses: string[] | RecordWithTtl[]) => void): void; - export function resolve6(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolve6(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException, addresses: RecordWithTtl[]) => void): void; - export function resolve6(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException, addresses: string[] | RecordWithTtl[]) => void): void; + export function resolve6(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolve6(hostname: string, options: ResolveWithTtlOptions, callback: (err: NodeJS.ErrnoException, addresses: RecordWithTtl[]) => void): void; + export function resolve6(hostname: string, options: ResolveOptions, callback: (err: NodeJS.ErrnoException, addresses: string[] | RecordWithTtl[]) => void): void; - export function resolveCname(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolveMx(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: MxRecord[]) => void): void; - export function resolveNaptr(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: NaptrRecord[]) => void): void; - export function resolveNs(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolvePtr(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; - export function resolveSoa(hostname: string, callback: (err: NodeJS.ErrnoException, address: SoaRecord) => void): void; - export function resolveSrv(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: SrvRecord[]) => void): void; - export function resolveTxt(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[][]) => void): void; + export function resolveCname(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolveMx(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: MxRecord[]) => void): void; + export function resolveNaptr(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: NaptrRecord[]) => void): void; + export function resolveNs(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolvePtr(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[]) => void): void; + export function resolveSoa(hostname: string, callback: (err: NodeJS.ErrnoException, address: SoaRecord) => void): void; + export function resolveSrv(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: SrvRecord[]) => void): void; + export function resolveTxt(hostname: string, callback: (err: NodeJS.ErrnoException, addresses: string[][]) => void): void; - export function reverse(ip: string, callback: (err: NodeJS.ErrnoException, hostnames: string[]) => void): void; - export function setServers(servers: string[]): void; + export function reverse(ip: string, callback: (err: NodeJS.ErrnoException, hostnames: string[]) => void): void; + export function setServers(servers: string[]): void; - //Error codes - export var NODATA: string; - export var FORMERR: string; - export var SERVFAIL: string; - export var NOTFOUND: string; - export var NOTIMP: string; - export var REFUSED: string; - export var BADQUERY: string; - export var BADNAME: string; - export var BADFAMILY: string; - export var BADRESP: string; - export var CONNREFUSED: string; - export var TIMEOUT: string; - export var EOF: string; - export var FILE: string; - export var NOMEM: string; - export var DESTRUCTION: string; - export var BADSTR: string; - export var BADFLAGS: string; - export var NONAME: string; - export var BADHINTS: string; - export var NOTINITIALIZED: string; - export var LOADIPHLPAPI: string; - export var ADDRGETNETWORKPARAMS: string; - export var CANCELLED: string; + //Error codes + export var NODATA: string; + export var FORMERR: string; + export var SERVFAIL: string; + export var NOTFOUND: string; + export var NOTIMP: string; + export var REFUSED: string; + export var BADQUERY: string; + export var BADNAME: string; + export var BADFAMILY: string; + export var BADRESP: string; + export var CONNREFUSED: string; + export var TIMEOUT: string; + export var EOF: string; + export var FILE: string; + export var NOMEM: string; + export var DESTRUCTION: string; + export var BADSTR: string; + export var BADFLAGS: string; + export var NONAME: string; + export var BADHINTS: string; + export var NOTINITIALIZED: string; + export var LOADIPHLPAPI: string; + export var ADDRGETNETWORKPARAMS: string; + export var CANCELLED: string; } declare module "net" { - import * as stream from "stream"; - import * as events from "events"; + import * as stream from "stream"; + import * as events from "events"; - export interface Socket extends stream.Duplex { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; + export interface Socket extends stream.Duplex { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; - connect(port: number, host?: string, connectionListener?: Function): void; - connect(path: string, connectionListener?: Function): void; - bufferSize: number; - setEncoding(encoding?: string): this; - write(data: any, encoding?: string, callback?: Function): void; - destroy(err?: any): void; - pause(): this; - resume(): this; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setKeepAlive(enable?: boolean, initialDelay?: number): void; - address(): { port: number; family: string; address: string; }; - unref(): void; - ref(): void; + connect(port: number, host?: string, connectionListener?: Function): void; + connect(path: string, connectionListener?: Function): void; + bufferSize: number; + setEncoding(encoding?: string): this; + write(data: any, encoding?: string, callback?: Function): void; + destroy(err?: any): void; + pause(): this; + resume(): this; + setTimeout(timeout: number, callback?: Function): void; + setNoDelay(noDelay?: boolean): void; + setKeepAlive(enable?: boolean, initialDelay?: number): void; + address(): { port: number; family: string; address: string; }; + unref(): void; + ref(): void; - remoteAddress: string; - remoteFamily: string; - remotePort: number; - localAddress: string; - localPort: number; - bytesRead: number; - bytesWritten: number; - connecting: boolean; - destroyed: boolean; + remoteAddress: string; + remoteFamily: string; + remotePort: number; + localAddress: string; + localPort: number; + bytesRead: number; + bytesWritten: number; + connecting: boolean; + destroyed: boolean; - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; /** * events.EventEmitter @@ -2137,97 +2137,97 @@ declare module "net" { * 7. lookup * 8. timeout */ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: (had_error: boolean) => void): this; - addListener(event: "connect", listener: () => void): this; - addListener(event: "data", listener: (data: Buffer) => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - addListener(event: "timeout", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: (had_error: boolean) => void): this; + addListener(event: "connect", listener: () => void): this; + addListener(event: "data", listener: (data: Buffer) => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + addListener(event: "timeout", listener: () => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close", had_error: boolean): boolean; - emit(event: "connect"): boolean; - emit(event: "data", data: Buffer): boolean; - emit(event: "drain"): boolean; - emit(event: "end"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "lookup", err: Error, address: string, family: string | number, host: string): boolean; - emit(event: "timeout"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close", had_error: boolean): boolean; + emit(event: "connect"): boolean; + emit(event: "data", data: Buffer): boolean; + emit(event: "drain"): boolean; + emit(event: "end"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "lookup", err: Error, address: string, family: string | number, host: string): boolean; + emit(event: "timeout"): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: (had_error: boolean) => void): this; - on(event: "connect", listener: () => void): this; - on(event: "data", listener: (data: Buffer) => void): this; - on(event: "drain", listener: () => void): this; - on(event: "end", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - on(event: "timeout", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: (had_error: boolean) => void): this; + on(event: "connect", listener: () => void): this; + on(event: "data", listener: (data: Buffer) => void): this; + on(event: "drain", listener: () => void): this; + on(event: "end", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + on(event: "timeout", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: (had_error: boolean) => void): this; - once(event: "connect", listener: () => void): this; - once(event: "data", listener: (data: Buffer) => void): this; - once(event: "drain", listener: () => void): this; - once(event: "end", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - once(event: "timeout", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: (had_error: boolean) => void): this; + once(event: "connect", listener: () => void): this; + once(event: "data", listener: (data: Buffer) => void): this; + once(event: "drain", listener: () => void): this; + once(event: "end", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + once(event: "timeout", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: (had_error: boolean) => void): this; - prependListener(event: "connect", listener: () => void): this; - prependListener(event: "data", listener: (data: Buffer) => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - prependListener(event: "timeout", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: (had_error: boolean) => void): this; + prependListener(event: "connect", listener: () => void): this; + prependListener(event: "data", listener: (data: Buffer) => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + prependListener(event: "timeout", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: (had_error: boolean) => void): this; - prependOnceListener(event: "connect", listener: () => void): this; - prependOnceListener(event: "data", listener: (data: Buffer) => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; - prependOnceListener(event: "timeout", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: (had_error: boolean) => void): this; + prependOnceListener(event: "connect", listener: () => void): this; + prependOnceListener(event: "data", listener: (data: Buffer) => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "lookup", listener: (err: Error, address: string, family: string | number, host: string) => void): this; + prependOnceListener(event: "timeout", listener: () => void): this; + } - export var Socket: { - new(options?: { fd?: number; allowHalfOpen?: boolean; readable?: boolean; writable?: boolean; }): Socket; - }; + export var Socket: { + new(options?: { fd?: number; allowHalfOpen?: boolean; readable?: boolean; writable?: boolean; }): Socket; + }; - export interface ListenOptions { - port?: number; - host?: string; - backlog?: number; - path?: string; - exclusive?: boolean; - } + export interface ListenOptions { + port?: number; + host?: string; + backlog?: number; + path?: string; + exclusive?: boolean; + } - export interface Server extends events.EventEmitter { - listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): Server; - listen(port: number, hostname?: string, listeningListener?: Function): Server; - listen(port: number, backlog?: number, listeningListener?: Function): Server; - listen(port: number, listeningListener?: Function): Server; - listen(path: string, backlog?: number, listeningListener?: Function): Server; - listen(path: string, listeningListener?: Function): Server; - listen(options: ListenOptions, listeningListener?: Function): Server; - listen(handle: any, backlog?: number, listeningListener?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - close(callback?: Function): Server; - address(): { port: number; family: string; address: string; }; - getConnections(cb: (error: Error, count: number) => void): void; - ref(): Server; - unref(): Server; - maxConnections: number; - connections: number; - listening: boolean; + export interface Server extends events.EventEmitter { + listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): Server; + listen(port: number, hostname?: string, listeningListener?: Function): Server; + listen(port: number, backlog?: number, listeningListener?: Function): Server; + listen(port: number, listeningListener?: Function): Server; + listen(path: string, backlog?: number, listeningListener?: Function): Server; + listen(path: string, listeningListener?: Function): Server; + listen(options: ListenOptions, listeningListener?: Function): Server; + listen(handle: any, backlog?: number, listeningListener?: Function): Server; + listen(handle: any, listeningListener?: Function): Server; + close(callback?: Function): Server; + address(): { port: number; family: string; address: string; }; + getConnections(cb: (error: Error, count: number) => void): void; + ref(): Server; + unref(): Server; + maxConnections: number; + connections: number; + listening: boolean; /** * events.EventEmitter @@ -2236,101 +2236,101 @@ declare module "net" { * 3. error * 4. listening */ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "connection", listener: (socket: Socket) => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "listening", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "connection", listener: (socket: Socket) => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "listening", listener: () => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "connection", socket: Socket): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "listening"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "connection", socket: Socket): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "listening"): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "connection", listener: (socket: Socket) => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "listening", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "connection", listener: (socket: Socket) => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "listening", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "connection", listener: (socket: Socket) => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "listening", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "connection", listener: (socket: Socket) => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "listening", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "connection", listener: (socket: Socket) => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "listening", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "connection", listener: (socket: Socket) => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "listening", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "connection", listener: (socket: Socket) => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "listening", listener: () => void): this; - } - export function createServer(connectionListener?: (socket: Socket) => void): Server; - export function createServer(options?: { allowHalfOpen?: boolean, pauseOnConnect?: boolean }, connectionListener?: (socket: Socket) => void): Server; - export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function connect(port: number, host?: string, connectionListener?: Function): Socket; - export function connect(path: string, connectionListener?: Function): Socket; - export function createConnection(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; - export function createConnection(path: string, connectionListener?: Function): Socket; - export function isIP(input: string): number; - export function isIPv4(input: string): boolean; - export function isIPv6(input: string): boolean; + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "connection", listener: (socket: Socket) => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "listening", listener: () => void): this; + } + export function createServer(connectionListener?: (socket: Socket) => void): Server; + export function createServer(options?: { allowHalfOpen?: boolean, pauseOnConnect?: boolean }, connectionListener?: (socket: Socket) => void): Server; + export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; + export function connect(port: number, host?: string, connectionListener?: Function): Socket; + export function connect(path: string, connectionListener?: Function): Socket; + export function createConnection(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; + export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; + export function createConnection(path: string, connectionListener?: Function): Socket; + export function isIP(input: string): number; + export function isIPv4(input: string): boolean; + export function isIPv6(input: string): boolean; } declare module "dgram" { - import * as events from "events"; + import * as events from "events"; - interface RemoteInfo { - address: string; - family: string; - port: number; - } + interface RemoteInfo { + address: string; + family: string; + port: number; + } - interface AddressInfo { - address: string; - family: string; - port: number; - } + interface AddressInfo { + address: string; + family: string; + port: number; + } - interface BindOptions { - port: number; - address?: string; - exclusive?: boolean; - } + interface BindOptions { + port: number; + address?: string; + exclusive?: boolean; + } - type SocketType = "udp4" | "udp6"; + type SocketType = "udp4" | "udp6"; - interface SocketOptions { - type: SocketType; - reuseAddr?: boolean; - } + interface SocketOptions { + type: SocketType; + reuseAddr?: boolean; + } - export function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - export function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + export function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + export function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - export interface Socket extends events.EventEmitter { - send(msg: Buffer | String | any[], port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - send(msg: Buffer | String | any[], offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - bind(port?: number, address?: string, callback?: () => void): void; - bind(options: BindOptions, callback?: Function): void; - close(callback?: () => void): void; - address(): AddressInfo; - setBroadcast(flag: boolean): void; - setTTL(ttl: number): void; - setMulticastTTL(ttl: number): void; - setMulticastLoopback(flag: boolean): void; - addMembership(multicastAddress: string, multicastInterface?: string): void; - dropMembership(multicastAddress: string, multicastInterface?: string): void; - ref(): this; - unref(): this; + export interface Socket extends events.EventEmitter { + send(msg: Buffer | String | any[], port: number, address: string, callback?: (error: Error, bytes: number) => void): void; + send(msg: Buffer | String | any[], offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; + bind(port?: number, address?: string, callback?: () => void): void; + bind(options: BindOptions, callback?: Function): void; + close(callback?: () => void): void; + address(): AddressInfo; + setBroadcast(flag: boolean): void; + setTTL(ttl: number): void; + setMulticastTTL(ttl: number): void; + setMulticastLoopback(flag: boolean): void; + addMembership(multicastAddress: string, multicastInterface?: string): void; + dropMembership(multicastAddress: string, multicastInterface?: string): void; + ref(): this; + unref(): this; /** * events.EventEmitter @@ -2339,163 +2339,163 @@ declare module "dgram" { * 3. listening * 4. message **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "listening", listener: () => void): this; - addListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "listening", listener: () => void): this; + addListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "listening"): boolean; - emit(event: "message", msg: Buffer, rinfo: AddressInfo): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "listening"): boolean; + emit(event: "message", msg: Buffer, rinfo: AddressInfo): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "listening", listener: () => void): this; - on(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "listening", listener: () => void): this; + on(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "listening", listener: () => void): this; - once(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "listening", listener: () => void): this; + once(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "listening", listener: () => void): this; - prependListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "listening", listener: () => void): this; + prependListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "listening", listener: () => void): this; - prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "listening", listener: () => void): this; + prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: AddressInfo) => void): this; + } } declare module "fs" { - import * as stream from "stream"; - import * as events from "events"; + import * as stream from "stream"; + import * as events from "events"; - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } + interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } - interface FSWatcher extends events.EventEmitter { - close(): void; + interface FSWatcher extends events.EventEmitter { + close(): void; /** * events.EventEmitter * 1. change * 2. error */ - addListener(event: string, listener: Function): this; - addListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + addListener(event: "error", listener: (error: Error) => void): this; - on(event: string, listener: Function): this; - on(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - on(event: "error", listener: (error: Error) => void): this; + on(event: string, listener: Function): this; + on(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + on(event: "error", listener: (error: Error) => void): this; - once(event: string, listener: Function): this; - once(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - once(event: "error", listener: (error: Error) => void): this; + once(event: string, listener: Function): this; + once(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + once(event: "error", listener: (error: Error) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependListener(event: "error", listener: (error: Error) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; - prependOnceListener(event: "error", listener: (error: Error) => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "change", listener: (eventType: string, filename: string | Buffer) => void): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + } - export interface ReadStream extends stream.Readable { - close(): void; - destroy(): void; - bytesRead: number; - path: string | Buffer; + export interface ReadStream extends stream.Readable { + close(): void; + destroy(): void; + bytesRead: number; + path: string | Buffer; /** * events.EventEmitter * 1. open * 2. close */ - addListener(event: string, listener: Function): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "close", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "open", listener: (fd: number) => void): this; + addListener(event: "close", listener: () => void): this; - on(event: string, listener: Function): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "close", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "open", listener: (fd: number) => void): this; + on(event: "close", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "close", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "open", listener: (fd: number) => void): this; + once(event: "close", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "close", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "open", listener: (fd: number) => void): this; + prependListener(event: "close", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "open", listener: (fd: number) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + } - export interface WriteStream extends stream.Writable { - close(): void; - bytesWritten: number; - path: string | Buffer; + export interface WriteStream extends stream.Writable { + close(): void; + bytesWritten: number; + path: string | Buffer; /** * events.EventEmitter * 1. open * 2. close */ - addListener(event: string, listener: Function): this; - addListener(event: "open", listener: (fd: number) => void): this; - addListener(event: "close", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "open", listener: (fd: number) => void): this; + addListener(event: "close", listener: () => void): this; - on(event: string, listener: Function): this; - on(event: "open", listener: (fd: number) => void): this; - on(event: "close", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "open", listener: (fd: number) => void): this; + on(event: "close", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "open", listener: (fd: number) => void): this; - once(event: "close", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "open", listener: (fd: number) => void): this; + once(event: "close", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "open", listener: (fd: number) => void): this; - prependListener(event: "close", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "open", listener: (fd: number) => void): this; + prependListener(event: "close", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "open", listener: (fd: number) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "open", listener: (fd: number) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + } /** * Asynchronous rename. @@ -2503,85 +2503,85 @@ declare module "fs" { * @param newPath * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Synchronous rename * @param oldPath * @param newPath */ - export function renameSync(oldPath: string, newPath: string): void; - export function truncate(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncate(path: string | Buffer, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncateSync(path: string | Buffer, len?: number): void; - export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncateSync(fd: number, len?: number): void; - export function chown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chownSync(path: string | Buffer, uid: number, gid: number): void; - export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchownSync(fd: number, uid: number, gid: number): void; - export function lchown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchownSync(path: string | Buffer, uid: number, gid: number): void; - export function chmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmodSync(path: string | Buffer, mode: number): void; - export function chmodSync(path: string | Buffer, mode: string): void; - export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmodSync(fd: number, mode: number): void; - export function fchmodSync(fd: number, mode: string): void; - export function lchmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmodSync(path: string | Buffer, mode: number): void; - export function lchmodSync(path: string | Buffer, mode: string): void; - export function stat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function lstat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function statSync(path: string | Buffer): Stats; - export function lstatSync(path: string | Buffer): Stats; - export function fstatSync(fd: number): Stats; - export function link(srcpath: string | Buffer, dstpath: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function linkSync(srcpath: string | Buffer, dstpath: string | Buffer): void; - export function symlink(srcpath: string | Buffer, dstpath: string | Buffer, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function symlinkSync(srcpath: string | Buffer, dstpath: string | Buffer, type?: string): void; - export function readlink(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; - export function readlinkSync(path: string | Buffer): string; - export function realpath(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpath(path: string | Buffer, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpathSync(path: string | Buffer, cache?: { [path: string]: string }): string; + export function renameSync(oldPath: string, newPath: string): void; + export function truncate(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function truncate(path: string | Buffer, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function truncateSync(path: string | Buffer, len?: number): void; + export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function ftruncateSync(fd: number, len?: number): void; + export function chown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chownSync(path: string | Buffer, uid: number, gid: number): void; + export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchownSync(fd: number, uid: number, gid: number): void; + export function lchown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchownSync(path: string | Buffer, uid: number, gid: number): void; + export function chmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chmodSync(path: string | Buffer, mode: number): void; + export function chmodSync(path: string | Buffer, mode: string): void; + export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchmodSync(fd: number, mode: number): void; + export function fchmodSync(fd: number, mode: string): void; + export function lchmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchmodSync(path: string | Buffer, mode: number): void; + export function lchmodSync(path: string | Buffer, mode: string): void; + export function stat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function lstat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function statSync(path: string | Buffer): Stats; + export function lstatSync(path: string | Buffer): Stats; + export function fstatSync(fd: number): Stats; + export function link(srcpath: string | Buffer, dstpath: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function linkSync(srcpath: string | Buffer, dstpath: string | Buffer): void; + export function symlink(srcpath: string | Buffer, dstpath: string | Buffer, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function symlinkSync(srcpath: string | Buffer, dstpath: string | Buffer, type?: string): void; + export function readlink(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; + export function readlinkSync(path: string | Buffer): string; + export function realpath(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; + export function realpath(path: string | Buffer, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; + export function realpathSync(path: string | Buffer, cache?: { [path: string]: string }): string; /** * Asynchronous unlink - deletes the file specified in {path} * * @param path * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function unlink(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function unlink(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Synchronous unlink - deletes the file specified in {path} * * @param path */ - export function unlinkSync(path: string | Buffer): void; + export function unlinkSync(path: string | Buffer): void; /** * Asynchronous rmdir - removes the directory specified in {path} * * @param path * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function rmdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function rmdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Synchronous rmdir - removes the directory specified in {path} * * @param path */ - export function rmdirSync(path: string | Buffer): void; + export function rmdirSync(path: string | Buffer): void; /** * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. * * @param path * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function mkdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function mkdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. * @@ -2589,7 +2589,7 @@ declare module "fs" { * @param mode * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function mkdir(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function mkdir(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. * @@ -2597,7 +2597,7 @@ declare module "fs" { * @param mode * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function mkdir(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function mkdir(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; /** * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. * @@ -2605,7 +2605,7 @@ declare module "fs" { * @param mode * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function mkdirSync(path: string | Buffer, mode?: number): void; + export function mkdirSync(path: string | Buffer, mode?: number): void; /** * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. * @@ -2613,48 +2613,48 @@ declare module "fs" { * @param mode * @param callback No arguments other than a possible exception are given to the completion callback. */ - export function mkdirSync(path: string | Buffer, mode?: string): void; + export function mkdirSync(path: string | Buffer, mode?: string): void; /** * Asynchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * * @param prefix * @param callback The created folder path is passed as a string to the callback's second parameter. */ - export function mkdtemp(prefix: string, callback?: (err: NodeJS.ErrnoException, folder: string) => void): void; + export function mkdtemp(prefix: string, callback?: (err: NodeJS.ErrnoException, folder: string) => void): void; /** * Synchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. * * @param prefix * @returns Returns the created folder path. */ - export function mkdtempSync(prefix: string): string; - export function readdir(path: string | Buffer, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; - export function readdir(path: string | Buffer, options: string | {}, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; - export function readdirSync(path: string | Buffer, options?: string | {}): string[]; - export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function closeSync(fd: number): void; - export function open(path: string | Buffer, flags: string | number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function open(path: string | Buffer, flags: string | number, mode: number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function openSync(path: string | Buffer, flags: string | number, mode?: number): number; - export function utimes(path: string | Buffer, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimes(path: string | Buffer, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimesSync(path: string | Buffer, atime: number, mtime: number): void; - export function utimesSync(path: string | Buffer, atime: Date, mtime: Date): void; - export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimesSync(fd: number, atime: number, mtime: number): void; - export function futimesSync(fd: number, atime: Date, mtime: Date): void; - export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fsyncSync(fd: number): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number | null, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, encoding: string, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number | null): number; - export function writeSync(fd: number, data: any, position?: number | null, enconding?: string): number; - export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number | null, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; - export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number | null): number; + export function mkdtempSync(prefix: string): string; + export function readdir(path: string | Buffer, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; + export function readdir(path: string | Buffer, options: string | {}, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; + export function readdirSync(path: string | Buffer, options?: string | {}): string[]; + export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function closeSync(fd: number): void; + export function open(path: string | Buffer, flags: string | number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; + export function open(path: string | Buffer, flags: string | number, mode: number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; + export function openSync(path: string | Buffer, flags: string | number, mode?: number): number; + export function utimes(path: string | Buffer, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function utimes(path: string | Buffer, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function utimesSync(path: string | Buffer, atime: number, mtime: number): void; + export function utimesSync(path: string | Buffer, atime: Date, mtime: Date): void; + export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function futimesSync(fd: number, atime: number, mtime: number): void; + export function futimesSync(fd: number, atime: Date, mtime: Date): void; + export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fsyncSync(fd: number): void; + export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number | null, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; + export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; + export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function write(fd: number, data: any, offset: number, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function write(fd: number, data: any, offset: number, encoding: string, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number | null): number; + export function writeSync(fd: number, data: any, position?: number | null, enconding?: string): number; + export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number | null, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; + export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number | null): number; /** * Asynchronous readFile - Asynchronously reads the entire contents of a file. * @@ -2662,9 +2662,9 @@ declare module "fs" { * @param encoding * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. */ - export function readFile(filename: string, encoding: null, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - export function readFile(filename: string, encoding: string | null, callback: (err: NodeJS.ErrnoException, data: string | Buffer) => void): void; + export function readFile(filename: string, encoding: null, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; + export function readFile(filename: string, encoding: string | null, callback: (err: NodeJS.ErrnoException, data: string | Buffer) => void): void; /** * Asynchronous readFile - Asynchronously reads the entire contents of a file. * @@ -2672,9 +2672,9 @@ declare module "fs" { * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. */ - export function readFile(filename: string, options: { encoding: null; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - export function readFile(filename: string, options: { encoding: string | null; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string | Buffer) => void): void; + export function readFile(filename: string, options: { encoding: null; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; + export function readFile(filename: string, options: { encoding: string | null; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string | Buffer) => void): void; /** * Asynchronous readFile - Asynchronously reads the entire contents of a file. * @@ -2682,213 +2682,213 @@ declare module "fs" { * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. */ - export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; /** * Asynchronous readFile - Asynchronously reads the entire contents of a file. * * @param fileName * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. */ - export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; /** * Synchronous readFile - Synchronously reads the entire contents of a file. * * @param fileName * @param encoding */ - export function readFileSync(filename: string, encoding: null): Buffer; - export function readFileSync(filename: string, encoding: string): string; - export function readFileSync(filename: string, encoding: string | null): string | Buffer; + export function readFileSync(filename: string, encoding: null): Buffer; + export function readFileSync(filename: string, encoding: string): string; + export function readFileSync(filename: string, encoding: string | null): string | Buffer; /** * Synchronous readFile - Synchronously reads the entire contents of a file. * * @param fileName * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. */ - export function readFileSync(filename: string, options: { encoding: null; flag?: string; }): Buffer; - export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; - export function readFileSync(filename: string, options: { encoding: string | null; flag?: string; }): string | Buffer; + export function readFileSync(filename: string, options: { encoding: null; flag?: string; }): Buffer; + export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; + export function readFileSync(filename: string, options: { encoding: string | null; flag?: string; }): string | Buffer; /** * Synchronous readFile - Synchronously reads the entire contents of a file. * * @param fileName * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. */ - export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; - export function writeFile(filename: string | number, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string | number, data: any, encoding: string, callback: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string | number, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string | number, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFileSync(filename: string | number, data: any, encoding: string): void; - export function writeFileSync(filename: string | number, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function writeFileSync(filename: string | number, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function appendFile(filename: string, data: any, encoding: string, callback: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFileSync(filename: string, data: any, encoding: string): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; - export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; - export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; - export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; - export function watch(filename: string, encoding: string, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function watch(filename: string, options: { persistent?: boolean; recursive?: boolean; encoding?: string }, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function exists(path: string | Buffer, callback?: (exists: boolean) => void): void; - export function existsSync(path: string | Buffer): boolean; + export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; + export function writeFile(filename: string | number, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFile(filename: string | number, data: any, encoding: string, callback: (err: NodeJS.ErrnoException) => void): void; + export function writeFile(filename: string | number, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFile(filename: string | number, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFileSync(filename: string | number, data: any, encoding: string): void; + export function writeFileSync(filename: string | number, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; + export function writeFileSync(filename: string | number, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; + export function appendFile(filename: string, data: any, encoding: string, callback: (err: NodeJS.ErrnoException) => void): void; + export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFileSync(filename: string, data: any, encoding: string): void; + export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; + export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; + export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; + export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; + export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; + export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; + export function watch(filename: string, encoding: string, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; + export function watch(filename: string, options: { persistent?: boolean; recursive?: boolean; encoding?: string }, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; + export function exists(path: string | Buffer, callback?: (exists: boolean) => void): void; + export function existsSync(path: string | Buffer): boolean; - export namespace constants { - // File Access Constants + export namespace constants { + // File Access Constants - /** Constant for fs.access(). File is visible to the calling process. */ - export const F_OK: number; + /** Constant for fs.access(). File is visible to the calling process. */ + export const F_OK: number; - /** Constant for fs.access(). File can be read by the calling process. */ - export const R_OK: number; + /** Constant for fs.access(). File can be read by the calling process. */ + export const R_OK: number; - /** Constant for fs.access(). File can be written by the calling process. */ - export const W_OK: number; + /** Constant for fs.access(). File can be written by the calling process. */ + export const W_OK: number; - /** Constant for fs.access(). File can be executed by the calling process. */ - export const X_OK: number; + /** Constant for fs.access(). File can be executed by the calling process. */ + export const X_OK: number; - // File Open Constants + // File Open Constants - /** Constant for fs.open(). Flag indicating to open a file for read-only access. */ - export const O_RDONLY: number; + /** Constant for fs.open(). Flag indicating to open a file for read-only access. */ + export const O_RDONLY: number; - /** Constant for fs.open(). Flag indicating to open a file for write-only access. */ - export const O_WRONLY: number; + /** Constant for fs.open(). Flag indicating to open a file for write-only access. */ + export const O_WRONLY: number; - /** Constant for fs.open(). Flag indicating to open a file for read-write access. */ - export const O_RDWR: number; + /** Constant for fs.open(). Flag indicating to open a file for read-write access. */ + export const O_RDWR: number; - /** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ - export const O_CREAT: number; + /** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ + export const O_CREAT: number; - /** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ - export const O_EXCL: number; + /** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ + export const O_EXCL: number; - /** Constant for fs.open(). Flag indicating that if path identifies a terminal device, opening the path shall not cause that terminal to become the controlling terminal for the process (if the process does not already have one). */ - export const O_NOCTTY: number; + /** Constant for fs.open(). Flag indicating that if path identifies a terminal device, opening the path shall not cause that terminal to become the controlling terminal for the process (if the process does not already have one). */ + export const O_NOCTTY: number; - /** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ - export const O_TRUNC: number; + /** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ + export const O_TRUNC: number; - /** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ - export const O_APPEND: number; + /** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ + export const O_APPEND: number; - /** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ - export const O_DIRECTORY: number; + /** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ + export const O_DIRECTORY: number; - /** Constant for fs.open(). Flag indicating reading accesses to the file system will no longer result in an update to the atime information associated with the file. This flag is available on Linux operating systems only. */ - export const O_NOATIME: number; + /** Constant for fs.open(). Flag indicating reading accesses to the file system will no longer result in an update to the atime information associated with the file. This flag is available on Linux operating systems only. */ + export const O_NOATIME: number; - /** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ - export const O_NOFOLLOW: number; + /** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ + export const O_NOFOLLOW: number; - /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ - export const O_SYNC: number; + /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ + export const O_SYNC: number; - /** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ - export const O_SYMLINK: number; + /** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ + export const O_SYMLINK: number; - /** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ - export const O_DIRECT: number; + /** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ + export const O_DIRECT: number; - /** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ - export const O_NONBLOCK: number; + /** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ + export const O_NONBLOCK: number; - // File Type Constants + // File Type Constants - /** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ - export const S_IFMT: number; + /** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ + export const S_IFMT: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ - export const S_IFREG: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ + export const S_IFREG: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ - export const S_IFDIR: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ + export const S_IFDIR: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ - export const S_IFCHR: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ + export const S_IFCHR: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ - export const S_IFBLK: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ + export const S_IFBLK: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ - export const S_IFIFO: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ + export const S_IFIFO: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ - export const S_IFLNK: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ + export const S_IFLNK: number; - /** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ - export const S_IFSOCK: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ + export const S_IFSOCK: number; - // File Mode Constants + // File Mode Constants - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ - export const S_IRWXU: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ + export const S_IRWXU: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ - export const S_IRUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ + export const S_IRUSR: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ - export const S_IWUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ + export const S_IWUSR: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ - export const S_IXUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ + export const S_IXUSR: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ - export const S_IRWXG: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ + export const S_IRWXG: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ - export const S_IRGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ + export const S_IRGRP: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ - export const S_IWGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ + export const S_IWGRP: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ - export const S_IXGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ + export const S_IXGRP: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ - export const S_IRWXO: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ + export const S_IRWXO: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ - export const S_IROTH: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ + export const S_IROTH: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ - export const S_IWOTH: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ + export const S_IWOTH: number; - /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ - export const S_IXOTH: number; - } + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ + export const S_IXOTH: number; + } - /** Tests a user's permissions for the file specified by path. */ - export function access(path: string | Buffer, callback: (err: NodeJS.ErrnoException) => void): void; - export function access(path: string | Buffer, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; - /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ - export function accessSync(path: string | Buffer, mode?: number): void; - export function createReadStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - autoClose?: boolean; - start?: number; - end?: number; - }): ReadStream; - export function createWriteStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - autoClose?: boolean; - start?: number; - }): WriteStream; - export function fdatasync(fd: number, callback: Function): void; - export function fdatasyncSync(fd: number): void; + /** Tests a user's permissions for the file specified by path. */ + export function access(path: string | Buffer, callback: (err: NodeJS.ErrnoException) => void): void; + export function access(path: string | Buffer, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; + /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ + export function accessSync(path: string | Buffer, mode?: number): void; + export function createReadStream(path: string | Buffer, options?: { + flags?: string; + encoding?: string; + fd?: number; + mode?: number; + autoClose?: boolean; + start?: number; + end?: number; + }): ReadStream; + export function createWriteStream(path: string | Buffer, options?: { + flags?: string; + encoding?: string; + fd?: number; + mode?: number; + autoClose?: boolean; + start?: number; + }): WriteStream; + export function fdatasync(fd: number, callback: Function): void; + export function fdatasyncSync(fd: number): void; } declare module "path" { @@ -2896,28 +2896,28 @@ declare module "path" { /** * A parsed path object generated by path.parse() or consumed by path.format(). */ - export interface ParsedPath { + export interface ParsedPath { /** * The root of the path such as '/' or 'c:\' */ - root: string; + root: string; /** * The full directory path such as '/home/user/dir' or 'c:\path\dir' */ - dir: string; + dir: string; /** * The file name including extension (if any) such as 'index.html' */ - base: string; + base: string; /** * The file extension (if any) such as '.html' */ - ext: string; + ext: string; /** * The file name without extension (if any) such as 'index' */ - name: string; - } + name: string; + } /** * Normalize a string path, reducing '..' and '.' parts. @@ -2925,14 +2925,14 @@ declare module "path" { * * @param p string path to normalize. */ - export function normalize(p: string): string; + export function normalize(p: string): string; /** * Join all arguments together and normalize the resulting path. * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. * * @param paths paths to join. */ - export function join(...paths: string[]): string; + export function join(...paths: string[]): string; /** * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. * @@ -2942,13 +2942,13 @@ declare module "path" { * * @param pathSegments string paths to join. Non-string arguments are ignored. */ - export function resolve(...pathSegments: any[]): string; + export function resolve(...pathSegments: any[]): string; /** * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. * * @param path path to test. */ - export function isAbsolute(path: string): boolean; + export function isAbsolute(path: string): boolean; /** * Solve the relative path from {from} to {to}. * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. @@ -2956,13 +2956,13 @@ declare module "path" { * @param from * @param to */ - export function relative(from: string, to: string): string; + export function relative(from: string, to: string): string; /** * Return the directory name of a path. Similar to the Unix dirname command. * * @param p the path to evaluate. */ - export function dirname(p: string): string; + export function dirname(p: string): string; /** * Return the last portion of a path. Similar to the Unix basename command. * Often used to extract the file name from a fully qualified path. @@ -2970,176 +2970,176 @@ declare module "path" { * @param p the path to evaluate. * @param ext optionally, an extension to remove from the result. */ - export function basename(p: string, ext?: string): string; + export function basename(p: string, ext?: string): string; /** * Return the extension of the path, from the last '.' to end of string in the last portion of the path. * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string * * @param p the path to evaluate. */ - export function extname(p: string): string; + export function extname(p: string): string; /** * The platform-specific file separator. '\\' or '/'. */ - export var sep: string; + export var sep: string; /** * The platform-specific file delimiter. ';' or ':'. */ - export var delimiter: string; + export var delimiter: string; /** * Returns an object from a path string - the opposite of format(). * * @param pathString path to evaluate. */ - export function parse(pathString: string): ParsedPath; + export function parse(pathString: string): ParsedPath; /** * Returns a path string from an object - the opposite of parse(). * * @param pathString path to evaluate. */ - export function format(pathObject: ParsedPath): string; + export function format(pathObject: ParsedPath): string; - export module posix { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } + export module posix { + export function normalize(p: string): string; + export function join(...paths: any[]): string; + export function resolve(...pathSegments: any[]): string; + export function isAbsolute(p: string): boolean; + export function relative(from: string, to: string): string; + export function dirname(p: string): string; + export function basename(p: string, ext?: string): string; + export function extname(p: string): string; + export var sep: string; + export var delimiter: string; + export function parse(p: string): ParsedPath; + export function format(pP: ParsedPath): string; + } - export module win32 { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } + export module win32 { + export function normalize(p: string): string; + export function join(...paths: any[]): string; + export function resolve(...pathSegments: any[]): string; + export function isAbsolute(p: string): boolean; + export function relative(from: string, to: string): string; + export function dirname(p: string): string; + export function basename(p: string, ext?: string): string; + export function extname(p: string): string; + export var sep: string; + export var delimiter: string; + export function parse(p: string): ParsedPath; + export function format(pP: ParsedPath): string; + } } declare module "string_decoder" { - export interface NodeStringDecoder { - write(buffer: Buffer): string; - end(buffer?: Buffer): string; - } - export var StringDecoder: { - new(encoding?: string): NodeStringDecoder; - }; + export interface NodeStringDecoder { + write(buffer: Buffer): string; + end(buffer?: Buffer): string; + } + export var StringDecoder: { + new(encoding?: string): NodeStringDecoder; + }; } declare module "tls" { - import * as crypto from "crypto"; - import * as net from "net"; - import * as stream from "stream"; + import * as crypto from "crypto"; + import * as net from "net"; + import * as stream from "stream"; - var CLIENT_RENEG_LIMIT: number; - var CLIENT_RENEG_WINDOW: number; + var CLIENT_RENEG_LIMIT: number; + var CLIENT_RENEG_WINDOW: number; - export interface Certificate { + export interface Certificate { /** * Country code. */ - C: string; + C: string; /** * Street. */ - ST: string; + ST: string; /** * Locality. */ - L: string; + L: string; /** * Organization. */ - O: string; + O: string; /** * Organizational unit. */ - OU: string; + OU: string; /** * Common name. */ - CN: string; - } + CN: string; + } - export interface PeerCertificate { - subject: Certificate; - issuer: Certificate; - subjectaltname: string; - infoAccess: { [index: string]: string[] }; - modulus: string; - exponent: string; - valid_from: string; - valid_to: string; - fingerprint: string; - ext_key_usage: string[]; - serialNumber: string; - raw: Buffer; - } + export interface PeerCertificate { + subject: Certificate; + issuer: Certificate; + subjectaltname: string; + infoAccess: { [index: string]: string[] }; + modulus: string; + exponent: string; + valid_from: string; + valid_to: string; + fingerprint: string; + ext_key_usage: string[]; + serialNumber: string; + raw: Buffer; + } - export interface DetailedPeerCertificate extends PeerCertificate { - issuerCertificate: DetailedPeerCertificate; - } + export interface DetailedPeerCertificate extends PeerCertificate { + issuerCertificate: DetailedPeerCertificate; + } - export interface CipherNameAndProtocol { + export interface CipherNameAndProtocol { /** * The cipher name. */ - name: string; + name: string; /** * SSL/TLS protocol version. */ - version: string; - } + version: string; + } - export class TLSSocket extends net.Socket { + export class TLSSocket extends net.Socket { /** * Construct a new tls.TLSSocket object from an existing TCP socket. */ - constructor(socket: net.Socket, options?: { + constructor(socket: net.Socket, options?: { /** * An optional TLS context object from tls.createSecureContext() */ - secureContext?: SecureContext, + secureContext?: SecureContext, /** * If true the TLS socket will be instantiated in server-mode. * Defaults to false. */ - isServer?: boolean, + isServer?: boolean, /** * An optional net.Server instance. */ - server?: net.Server, + server?: net.Server, /** * If true the server will request a certificate from clients that * connect and attempt to verify that certificate. Defaults to * false. */ - requestCert?: boolean, + requestCert?: boolean, /** * If true the server will reject any connection which is not * authorized with the list of supplied CAs. This option only has an * effect if requestCert is true. Defaults to false. */ - rejectUnauthorized?: boolean, + rejectUnauthorized?: boolean, /** * An array of strings or a Buffer naming possible NPN protocols. * (Protocols should be ordered by their priority.) */ - NPNProtocols?: string[] | Buffer, + NPNProtocols?: string[] | Buffer, /** * An array of strings or a Buffer naming possible ALPN protocols. * (Protocols should be ordered by their priority.) When the server @@ -3147,7 +3147,7 @@ declare module "tls" { * precedence over NPN and the server does not send an NPN extension * to the client. */ - ALPNProtocols?: string[] | Buffer, + ALPNProtocols?: string[] | Buffer, /** * SNICallback(servername, cb) <Function> A function that will be * called if the client supports SNI TLS extension. Two arguments @@ -3157,44 +3157,44 @@ declare module "tls" { * SecureContext.) If SNICallback wasn't provided the default callback * with high-level API will be used (see below). */ - SNICallback?: Function, + SNICallback?: Function, /** * An optional Buffer instance containing a TLS session. */ - session?: Buffer, + session?: Buffer, /** * If true, specifies that the OCSP status request extension will be * added to the client hello and an 'OCSPResponse' event will be * emitted on the socket before establishing a secure communication */ - requestOCSP?: boolean - }); + requestOCSP?: boolean + }); /** * Returns the bound address, the address family name and port of the underlying socket as reported by * the operating system. * @returns {any} - An object with three properties, e.g. { port: 12346, family: 'IPv4', address: '127.0.0.1' }. */ - address(): { port: number; family: string; address: string }; + address(): { port: number; family: string; address: string }; /** * A boolean that is true if the peer certificate was signed by one of the specified CAs, otherwise false. */ - authorized: boolean; + authorized: boolean; /** * The reason why the peer's certificate has not been verified. * This property becomes available only when tlsSocket.authorized === false. */ - authorizationError: Error; + authorizationError: Error; /** * Static boolean value, always true. * May be used to distinguish TLS sockets from regular ones. */ - encrypted: boolean; + encrypted: boolean; /** * Returns an object representing the cipher name and the SSL/TLS protocol version of the current connection. * @returns {CipherNameAndProtocol} - Returns an object representing the cipher name * and the SSL/TLS protocol version of the current connection. */ - getCipher(): CipherNameAndProtocol; + getCipher(): CipherNameAndProtocol; /** * Returns an object representing the peer's certificate. * The returned object has some properties corresponding to the field of the certificate. @@ -3204,41 +3204,41 @@ declare module "tls" { * @param {boolean} detailed - If true; the full chain with issuer property will be returned. * @returns {PeerCertificate | DetailedPeerCertificate} - An object representing the peer's certificate. */ - getPeerCertificate(detailed: true): DetailedPeerCertificate; - getPeerCertificate(detailed?: false): PeerCertificate; - getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate; + getPeerCertificate(detailed: true): DetailedPeerCertificate; + getPeerCertificate(detailed?: false): PeerCertificate; + getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate; /** * Could be used to speed up handshake establishment when reconnecting to the server. * @returns {any} - ASN.1 encoded TLS session or undefined if none was negotiated. */ - getSession(): any; + getSession(): any; /** * NOTE: Works only with client TLS sockets. * Useful only for debugging, for session reuse provide session option to tls.connect(). * @returns {any} - TLS session ticket or undefined if none was negotiated. */ - getTLSTicket(): any; + getTLSTicket(): any; /** * The string representation of the local IP address. */ - localAddress: string; + localAddress: string; /** * The numeric representation of the local port. */ - localPort: number; + localPort: number; /** * The string representation of the remote IP address. * For example, '74.125.127.100' or '2001:4860:a005::68'. */ - remoteAddress: string; + remoteAddress: string; /** * The string representation of the remote IP family. 'IPv4' or 'IPv6'. */ - remoteFamily: string; + remoteFamily: string; /** * The numeric representation of the remote port. For example, 443. */ - remotePort: number; + remotePort: number; /** * Initiate TLS renegotiation process. * @@ -3249,7 +3249,7 @@ declare module "tls" { * @param {Function} callback - callback(err) will be executed with null as err, once the renegotiation * is successfully completed. */ - renegotiate(options: TlsOptions, callback: (err: Error) => any): any; + renegotiate(options: TlsOptions, callback: (err: Error) => any): any; /** * Set maximum TLS fragment size (default and maximum value is: 16384, minimum is: 512). * Smaller fragment size decreases buffering latency on the client: large fragments are buffered by @@ -3260,94 +3260,94 @@ declare module "tls" { * @param {number} size - TLS fragment size (default and maximum value is: 16384, minimum is: 512). * @returns {boolean} - Returns true on success, false otherwise. */ - setMaxSendFragment(size: number): boolean; + setMaxSendFragment(size: number): boolean; /** * events.EventEmitter * 1. OCSPResponse * 2. secureConnect **/ - addListener(event: string, listener: Function): this; - addListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - addListener(event: "secureConnect", listener: () => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + addListener(event: "secureConnect", listener: () => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "OCSPResponse", response: Buffer): boolean; - emit(event: "secureConnect"): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "OCSPResponse", response: Buffer): boolean; + emit(event: "secureConnect"): boolean; - on(event: string, listener: Function): this; - on(event: "OCSPResponse", listener: (response: Buffer) => void): this; - on(event: "secureConnect", listener: () => void): this; + on(event: string, listener: Function): this; + on(event: "OCSPResponse", listener: (response: Buffer) => void): this; + on(event: "secureConnect", listener: () => void): this; - once(event: string, listener: Function): this; - once(event: "OCSPResponse", listener: (response: Buffer) => void): this; - once(event: "secureConnect", listener: () => void): this; + once(event: string, listener: Function): this; + once(event: "OCSPResponse", listener: (response: Buffer) => void): this; + once(event: "secureConnect", listener: () => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - prependListener(event: "secureConnect", listener: () => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + prependListener(event: "secureConnect", listener: () => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; - prependOnceListener(event: "secureConnect", listener: () => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; + prependOnceListener(event: "secureConnect", listener: () => void): this; + } - export interface TlsOptions { - host?: string; - port?: number; - pfx?: string | Buffer[]; - key?: string | string[] | Buffer | any[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | string[] | Buffer | Buffer[]; - crl?: string | string[]; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: string[] | Buffer; - SNICallback?: (servername: string, cb: (err: Error, ctx: SecureContext) => any) => any; - ecdhCurve?: string; - dhparam?: string | Buffer; - handshakeTimeout?: number; - ALPNProtocols?: string[] | Buffer; - sessionTimeout?: number; - ticketKeys?: any; - sessionIdContext?: string; - secureProtocol?: string; - } + export interface TlsOptions { + host?: string; + port?: number; + pfx?: string | Buffer[]; + key?: string | string[] | Buffer | any[]; + passphrase?: string; + cert?: string | string[] | Buffer | Buffer[]; + ca?: string | string[] | Buffer | Buffer[]; + crl?: string | string[]; + ciphers?: string; + honorCipherOrder?: boolean; + requestCert?: boolean; + rejectUnauthorized?: boolean; + NPNProtocols?: string[] | Buffer; + SNICallback?: (servername: string, cb: (err: Error, ctx: SecureContext) => any) => any; + ecdhCurve?: string; + dhparam?: string | Buffer; + handshakeTimeout?: number; + ALPNProtocols?: string[] | Buffer; + sessionTimeout?: number; + ticketKeys?: any; + sessionIdContext?: string; + secureProtocol?: string; + } - export interface ConnectionOptions { - host?: string; - port?: number; - socket?: net.Socket; - pfx?: string | Buffer - key?: string | string[] | Buffer | Buffer[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | Buffer | (string | Buffer)[]; - rejectUnauthorized?: boolean; - NPNProtocols?: (string | Buffer)[]; - servername?: string; - path?: string; - ALPNProtocols?: (string | Buffer)[]; - checkServerIdentity?: (servername: string, cert: string | Buffer | (string | Buffer)[]) => any; - secureProtocol?: string; - secureContext?: Object; - session?: Buffer; - minDHSize?: number; - } + export interface ConnectionOptions { + host?: string; + port?: number; + socket?: net.Socket; + pfx?: string | Buffer + key?: string | string[] | Buffer | Buffer[]; + passphrase?: string; + cert?: string | string[] | Buffer | Buffer[]; + ca?: string | Buffer | (string | Buffer)[]; + rejectUnauthorized?: boolean; + NPNProtocols?: (string | Buffer)[]; + servername?: string; + path?: string; + ALPNProtocols?: (string | Buffer)[]; + checkServerIdentity?: (servername: string, cert: string | Buffer | (string | Buffer)[]) => any; + secureProtocol?: string; + secureContext?: Object; + session?: Buffer; + minDHSize?: number; + } - export interface Server extends net.Server { - close(callback?: Function): Server; - address(): { port: number; family: string; address: string; }; - addContext(hostName: string, credentials: { - key: string; - cert: string; - ca: string; - }): void; - maxConnections: number; - connections: number; + export interface Server extends net.Server { + close(callback?: Function): Server; + address(): { port: number; family: string; address: string; }; + addContext(hostName: string, credentials: { + key: string; + cert: string; + ca: string; + }): void; + maxConnections: number; + connections: number; /** * events.EventEmitter @@ -3357,286 +3357,286 @@ declare module "tls" { * 4. resumeSession * 5. secureConnection **/ - addListener(event: string, listener: Function): this; - addListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - addListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - addListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - addListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - addListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + addListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; + addListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; + addListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; + addListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "tlsClientError", err: Error, tlsSocket: TLSSocket): boolean; - emit(event: "newSession", sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void): boolean; - emit(event: "OCSPRequest", certificate: Buffer, issuer: Buffer, callback: Function): boolean; - emit(event: "resumeSession", sessionId: any, callback: (err: Error, sessionData: any) => void): boolean; - emit(event: "secureConnection", tlsSocket: TLSSocket): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "tlsClientError", err: Error, tlsSocket: TLSSocket): boolean; + emit(event: "newSession", sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void): boolean; + emit(event: "OCSPRequest", certificate: Buffer, issuer: Buffer, callback: Function): boolean; + emit(event: "resumeSession", sessionId: any, callback: (err: Error, sessionData: any) => void): boolean; + emit(event: "secureConnection", tlsSocket: TLSSocket): boolean; - on(event: string, listener: Function): this; - on(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - on(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - on(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - on(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - on(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + on(event: string, listener: Function): this; + on(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + on(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; + on(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; + on(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; + on(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - once(event: string, listener: Function): this; - once(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - once(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - once(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - once(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - once(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + once(event: string, listener: Function): this; + once(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + once(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; + once(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; + once(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; + once(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - prependListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - prependListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - prependListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - prependListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + prependListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; + prependListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; + prependListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; + prependListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; - prependOnceListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; - prependOnceListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; - prependOnceListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; - prependOnceListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; - } + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "tlsClientError", listener: (err: Error, tlsSocket: TLSSocket) => void): this; + prependOnceListener(event: "newSession", listener: (sessionId: any, sessionData: any, callback: (err: Error, resp: Buffer) => void) => void): this; + prependOnceListener(event: "OCSPRequest", listener: (certificate: Buffer, issuer: Buffer, callback: Function) => void): this; + prependOnceListener(event: "resumeSession", listener: (sessionId: any, callback: (err: Error, sessionData: any) => void) => void): this; + prependOnceListener(event: "secureConnection", listener: (tlsSocket: TLSSocket) => void): this; + } - export interface ClearTextStream extends stream.Duplex { - authorized: boolean; - authorizationError: Error; - getPeerCertificate(): any; - getCipher: { - name: string; - version: string; - }; - address: { - port: number; - family: string; - address: string; - }; - remoteAddress: string; - remotePort: number; - } + export interface ClearTextStream extends stream.Duplex { + authorized: boolean; + authorizationError: Error; + getPeerCertificate(): any; + getCipher: { + name: string; + version: string; + }; + address: { + port: number; + family: string; + address: string; + }; + remoteAddress: string; + remotePort: number; + } - export interface SecurePair { - encrypted: any; - cleartext: any; - } + export interface SecurePair { + encrypted: any; + cleartext: any; + } - export interface SecureContextOptions { - pfx?: string | Buffer; - key?: string | Buffer; - passphrase?: string; - cert?: string | Buffer; - ca?: string | Buffer; - crl?: string | string[] - ciphers?: string; - honorCipherOrder?: boolean; - } + export interface SecureContextOptions { + pfx?: string | Buffer; + key?: string | Buffer; + passphrase?: string; + cert?: string | Buffer; + ca?: string | Buffer; + crl?: string | string[] + ciphers?: string; + honorCipherOrder?: boolean; + } - export interface SecureContext { - context: any; - } + export interface SecureContext { + context: any; + } - export function createServer(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void): Server; - export function connect(options: ConnectionOptions, secureConnectionListener?: () => void): TLSSocket; - export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; - export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; - export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; - export function createSecureContext(details: SecureContextOptions): SecureContext; + export function createServer(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void): Server; + export function connect(options: ConnectionOptions, secureConnectionListener?: () => void): TLSSocket; + export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; + export function createSecureContext(details: SecureContextOptions): SecureContext; } declare module "crypto" { - export interface Certificate { - exportChallenge(spkac: string | Buffer): Buffer; - exportPublicKey(spkac: string | Buffer): Buffer; - verifySpkac(spkac: Buffer): boolean; - } - export var Certificate: { - new(): Certificate; - (): Certificate; - } + export interface Certificate { + exportChallenge(spkac: string | Buffer): Buffer; + exportPublicKey(spkac: string | Buffer): Buffer; + verifySpkac(spkac: Buffer): boolean; + } + export var Certificate: { + new(): Certificate; + (): Certificate; + } - export var fips: boolean; + export var fips: boolean; - export interface CredentialDetails { - pfx: string; - key: string; - passphrase: string; - cert: string; - ca: string | string[]; - crl: string | string[]; - ciphers: string; - } - export interface Credentials { context?: any; } - export function createCredentials(details: CredentialDetails): Credentials; - export function createHash(algorithm: string): Hash; - export function createHmac(algorithm: string, key: string | Buffer): Hmac; + export interface CredentialDetails { + pfx: string; + key: string; + passphrase: string; + cert: string; + ca: string | string[]; + crl: string | string[]; + ciphers: string; + } + export interface Credentials { context?: any; } + export function createCredentials(details: CredentialDetails): Credentials; + export function createHash(algorithm: string): Hash; + export function createHmac(algorithm: string, key: string | Buffer): Hmac; - type Utf8AsciiLatin1Encoding = "utf8" | "ascii" | "latin1"; - type HexBase64Latin1Encoding = "latin1" | "hex" | "base64"; - type Utf8AsciiBinaryEncoding = "utf8" | "ascii" | "binary"; - type HexBase64BinaryEncoding = "binary" | "base64" | "hex"; - type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; + type Utf8AsciiLatin1Encoding = "utf8" | "ascii" | "latin1"; + type HexBase64Latin1Encoding = "latin1" | "hex" | "base64"; + type Utf8AsciiBinaryEncoding = "utf8" | "ascii" | "binary"; + type HexBase64BinaryEncoding = "binary" | "base64" | "hex"; + type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; - export interface Hash extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hash; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hash; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export interface Hmac extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hmac; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hmac; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export function createCipher(algorithm: string, password: any): Cipher; - export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; - export interface Cipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: HexBase64BinaryEncoding): string; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding, output_encoding: HexBase64BinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - getAuthTag(): Buffer; - setAAD(buffer: Buffer): void; - } - export function createDecipher(algorithm: string, password: any): Decipher; - export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; - export interface Decipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: HexBase64BinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: Utf8AsciiBinaryEncoding): string; - update(data: string, input_encoding: HexBase64BinaryEncoding, output_encoding: Utf8AsciiBinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - setAuthTag(tag: Buffer): void; - setAAD(buffer: Buffer): void; - } - export function createSign(algorithm: string): Signer; - export interface Signer extends NodeJS.WritableStream { - update(data: string | Buffer): Signer; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Signer; - sign(private_key: string | { key: string; passphrase: string }): Buffer; - sign(private_key: string | { key: string; passphrase: string }, output_format: HexBase64Latin1Encoding): string; - } - export function createVerify(algorith: string): Verify; - export interface Verify extends NodeJS.WritableStream { - update(data: string | Buffer): Verify; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Verify; - verify(object: string, signature: Buffer): boolean; - verify(object: string, signature: string, signature_format: HexBase64Latin1Encoding): boolean; - } - export function createDiffieHellman(prime_length: number, generator?: number): DiffieHellman; - export function createDiffieHellman(prime: Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: number | Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: string, generator_encoding: HexBase64Latin1Encoding): DiffieHellman; - export interface DiffieHellman { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrime(): Buffer; - getPrime(encoding: HexBase64Latin1Encoding): string; - getGenerator(): Buffer; - getGenerator(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - setPublicKey(public_key: Buffer): void; - setPublicKey(public_key: string, encoding: string): void; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: string): void; - verifyError: number; - } - export function getDiffieHellman(group_name: string): DiffieHellman; - export function pbkdf2(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; - export function pbkdf2Sync(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string): Buffer; - export function randomBytes(size: number): Buffer; - export function randomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export function pseudoRandomBytes(size: number): Buffer; - export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export function randomFillSync(buffer: Buffer | Uint8Array, offset?: number, size?: number): Buffer; - export function randomFill(buffer: Buffer, callback: (err: Error, buf: Buffer) => void): void; - export function randomFill(buffer: Uint8Array, callback: (err: Error, buf: Uint8Array) => void): void; - export function randomFill(buffer: Buffer, offset: number, callback: (err: Error, buf: Buffer) => void): void; - export function randomFill(buffer: Uint8Array, offset: number, callback: (err: Error, buf: Uint8Array) => void): void; - export function randomFill(buffer: Buffer, offset: number, size: number, callback: (err: Error, buf: Buffer) => void): void; - export function randomFill(buffer: Uint8Array, offset: number, size: number, callback: (err: Error, buf: Uint8Array) => void): void; - export interface RsaPublicKey { - key: string; - padding?: number; - } - export interface RsaPrivateKey { - key: string; - passphrase?: string, - padding?: number; - } - export function publicEncrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function privateDecrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function privateEncrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function publicDecrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function getCiphers(): string[]; - export function getCurves(): string[]; - export function getHashes(): string[]; - export interface ECDH { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - generateKeys(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: HexBase64Latin1Encoding): void; - } - export function createECDH(curve_name: string): ECDH; - export function timingSafeEqual(a: Buffer, b: Buffer): boolean; - export var DEFAULT_ENCODING: string; + export interface Hash extends NodeJS.ReadWriteStream { + update(data: string | Buffer): Hash; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hash; + digest(): Buffer; + digest(encoding: HexBase64Latin1Encoding): string; + } + export interface Hmac extends NodeJS.ReadWriteStream { + update(data: string | Buffer): Hmac; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hmac; + digest(): Buffer; + digest(encoding: HexBase64Latin1Encoding): string; + } + export function createCipher(algorithm: string, password: any): Cipher; + export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; + export interface Cipher extends NodeJS.ReadWriteStream { + update(data: Buffer): Buffer; + update(data: string, input_encoding: Utf8AsciiBinaryEncoding): Buffer; + update(data: Buffer, input_encoding: any, output_encoding: HexBase64BinaryEncoding): string; + update(data: string, input_encoding: Utf8AsciiBinaryEncoding, output_encoding: HexBase64BinaryEncoding): string; + final(): Buffer; + final(output_encoding: string): string; + setAutoPadding(auto_padding?: boolean): void; + getAuthTag(): Buffer; + setAAD(buffer: Buffer): void; + } + export function createDecipher(algorithm: string, password: any): Decipher; + export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; + export interface Decipher extends NodeJS.ReadWriteStream { + update(data: Buffer): Buffer; + update(data: string, input_encoding: HexBase64BinaryEncoding): Buffer; + update(data: Buffer, input_encoding: any, output_encoding: Utf8AsciiBinaryEncoding): string; + update(data: string, input_encoding: HexBase64BinaryEncoding, output_encoding: Utf8AsciiBinaryEncoding): string; + final(): Buffer; + final(output_encoding: string): string; + setAutoPadding(auto_padding?: boolean): void; + setAuthTag(tag: Buffer): void; + setAAD(buffer: Buffer): void; + } + export function createSign(algorithm: string): Signer; + export interface Signer extends NodeJS.WritableStream { + update(data: string | Buffer): Signer; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Signer; + sign(private_key: string | { key: string; passphrase: string }): Buffer; + sign(private_key: string | { key: string; passphrase: string }, output_format: HexBase64Latin1Encoding): string; + } + export function createVerify(algorith: string): Verify; + export interface Verify extends NodeJS.WritableStream { + update(data: string | Buffer): Verify; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Verify; + verify(object: string, signature: Buffer): boolean; + verify(object: string, signature: string, signature_format: HexBase64Latin1Encoding): boolean; + } + export function createDiffieHellman(prime_length: number, generator?: number): DiffieHellman; + export function createDiffieHellman(prime: Buffer): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: number | Buffer): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: string, generator_encoding: HexBase64Latin1Encoding): DiffieHellman; + export interface DiffieHellman { + generateKeys(): Buffer; + generateKeys(encoding: HexBase64Latin1Encoding): string; + computeSecret(other_public_key: Buffer): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; + getPrime(): Buffer; + getPrime(encoding: HexBase64Latin1Encoding): string; + getGenerator(): Buffer; + getGenerator(encoding: HexBase64Latin1Encoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: HexBase64Latin1Encoding): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: HexBase64Latin1Encoding): string; + setPublicKey(public_key: Buffer): void; + setPublicKey(public_key: string, encoding: string): void; + setPrivateKey(private_key: Buffer): void; + setPrivateKey(private_key: string, encoding: string): void; + verifyError: number; + } + export function getDiffieHellman(group_name: string): DiffieHellman; + export function pbkdf2(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; + export function pbkdf2Sync(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string): Buffer; + export function randomBytes(size: number): Buffer; + export function randomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; + export function pseudoRandomBytes(size: number): Buffer; + export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; + export function randomFillSync(buffer: Buffer | Uint8Array, offset?: number, size?: number): Buffer; + export function randomFill(buffer: Buffer, callback: (err: Error, buf: Buffer) => void): void; + export function randomFill(buffer: Uint8Array, callback: (err: Error, buf: Uint8Array) => void): void; + export function randomFill(buffer: Buffer, offset: number, callback: (err: Error, buf: Buffer) => void): void; + export function randomFill(buffer: Uint8Array, offset: number, callback: (err: Error, buf: Uint8Array) => void): void; + export function randomFill(buffer: Buffer, offset: number, size: number, callback: (err: Error, buf: Buffer) => void): void; + export function randomFill(buffer: Uint8Array, offset: number, size: number, callback: (err: Error, buf: Uint8Array) => void): void; + export interface RsaPublicKey { + key: string; + padding?: number; + } + export interface RsaPrivateKey { + key: string; + passphrase?: string, + padding?: number; + } + export function publicEncrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer + export function privateDecrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer + export function privateEncrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer + export function publicDecrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer + export function getCiphers(): string[]; + export function getCurves(): string[]; + export function getHashes(): string[]; + export interface ECDH { + generateKeys(): Buffer; + generateKeys(encoding: HexBase64Latin1Encoding): string; + generateKeys(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; + computeSecret(other_public_key: Buffer): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: HexBase64Latin1Encoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: HexBase64Latin1Encoding): string; + getPublicKey(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; + setPrivateKey(private_key: Buffer): void; + setPrivateKey(private_key: string, encoding: HexBase64Latin1Encoding): void; + } + export function createECDH(curve_name: string): ECDH; + export function timingSafeEqual(a: Buffer, b: Buffer): boolean; + export var DEFAULT_ENCODING: string; } declare module "stream" { - import * as events from "events"; + import * as events from "events"; - class internal extends events.EventEmitter { - pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T; - } + class internal extends events.EventEmitter { + pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T; + } - namespace internal { + namespace internal { - export class Stream extends internal { } + export class Stream extends internal { } - export interface ReadableOptions { - highWaterMark?: number; - encoding?: string; - objectMode?: boolean; - read?: (this: Readable, size?: number) => any; - } + export interface ReadableOptions { + highWaterMark?: number; + encoding?: string; + objectMode?: boolean; + read?: (this: Readable, size?: number) => any; + } - export class Readable extends Stream implements NodeJS.ReadableStream { - readable: boolean; - constructor(opts?: ReadableOptions); - _read(size: number): void; - read(size?: number): any; - setEncoding(encoding: string): this; - pause(): this; - resume(): this; - isPaused(): boolean; - pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T; - unpipe<T extends NodeJS.WritableStream>(destination?: T): this; - unshift(chunk: any): void; - wrap(oldStream: NodeJS.ReadableStream): Readable; - push(chunk: any, encoding?: string): boolean; + export class Readable extends Stream implements NodeJS.ReadableStream { + readable: boolean; + constructor(opts?: ReadableOptions); + _read(size: number): void; + read(size?: number): any; + setEncoding(encoding: string): this; + pause(): this; + resume(): this; + isPaused(): boolean; + pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T; + unpipe<T extends NodeJS.WritableStream>(destination?: T): this; + unshift(chunk: any): void; + wrap(oldStream: NodeJS.ReadableStream): Readable; + push(chunk: any, encoding?: string): boolean; /** * Event emitter @@ -3647,75 +3647,75 @@ declare module "stream" { * 4. readable * 5. error **/ - addListener(event: string, listener: Function): this; - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: Buffer | string) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: Buffer | string) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "data", chunk: Buffer | string): boolean; - emit(event: "end"): boolean; - emit(event: "readable"): boolean; - emit(event: "error", err: Error): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "data", chunk: Buffer | string): boolean; + emit(event: "end"): boolean; + emit(event: "readable"): boolean; + emit(event: "error", err: Error): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: Buffer | string) => void): this; - on(event: "end", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: Buffer | string) => void): this; + on(event: "end", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: Buffer | string) => void): this; - once(event: "end", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: Buffer | string) => void): this; + once(event: "end", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - } + removeListener(event: string, listener: Function): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; + removeListener(event: "end", listener: () => void): this; + removeListener(event: "readable", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + } - export interface WritableOptions { - highWaterMark?: number; - decodeStrings?: boolean; - objectMode?: boolean; - write?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - writev?: (chunks: { chunk: string | Buffer, encoding: string }[], callback: Function) => any; - } + export interface WritableOptions { + highWaterMark?: number; + decodeStrings?: boolean; + objectMode?: boolean; + write?: (chunk: string | Buffer, encoding: string, callback: Function) => any; + writev?: (chunks: { chunk: string | Buffer, encoding: string }[], callback: Function) => any; + } - export class Writable extends Stream implements NodeJS.WritableStream { - writable: boolean; - constructor(opts?: WritableOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - setDefaultEncoding(encoding: string): this; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; + export class Writable extends Stream implements NodeJS.WritableStream { + writable: boolean; + constructor(opts?: WritableOptions); + _write(chunk: any, encoding: string, callback: Function): void; + write(chunk: any, cb?: Function): boolean; + write(chunk: any, encoding?: string, cb?: Function): boolean; + setDefaultEncoding(encoding: string): this; + end(): void; + end(chunk: any, cb?: Function): void; + end(chunk: any, encoding?: string, cb?: Function): void; /** * Event emitter @@ -3727,526 +3727,526 @@ declare module "stream" { * 5. pipe * 6. unpipe **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "pipe", listener: (src: Readable) => void): this; - addListener(event: "unpipe", listener: (src: Readable) => void): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "pipe", listener: (src: Readable) => void): this; + addListener(event: "unpipe", listener: (src: Readable) => void): this; - emit(event: string | symbol, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "drain", chunk: Buffer | string): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "finish"): boolean; - emit(event: "pipe", src: Readable): boolean; - emit(event: "unpipe", src: Readable): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "drain", chunk: Buffer | string): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "pipe", src: Readable): boolean; + emit(event: "unpipe", src: Readable): boolean; - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "pipe", listener: (src: Readable) => void): this; - on(event: "unpipe", listener: (src: Readable) => void): this; + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "pipe", listener: (src: Readable) => void): this; + on(event: "unpipe", listener: (src: Readable) => void): this; - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "pipe", listener: (src: Readable) => void): this; - once(event: "unpipe", listener: (src: Readable) => void): this; + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "pipe", listener: (src: Readable) => void): this; + once(event: "unpipe", listener: (src: Readable) => void): this; - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "pipe", listener: (src: Readable) => void): this; - prependListener(event: "unpipe", listener: (src: Readable) => void): this; + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "pipe", listener: (src: Readable) => void): this; + prependListener(event: "unpipe", listener: (src: Readable) => void): this; - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; - prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "pipe", listener: (src: Readable) => void): this; - removeListener(event: "unpipe", listener: (src: Readable) => void): this; - } + removeListener(event: string, listener: Function): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "drain", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "finish", listener: () => void): this; + removeListener(event: "pipe", listener: (src: Readable) => void): this; + removeListener(event: "unpipe", listener: (src: Readable) => void): this; + } - export interface DuplexOptions extends ReadableOptions, WritableOptions { - allowHalfOpen?: boolean; - readableObjectMode?: boolean; - writableObjectMode?: boolean; - } + export interface DuplexOptions extends ReadableOptions, WritableOptions { + allowHalfOpen?: boolean; + readableObjectMode?: boolean; + writableObjectMode?: boolean; + } - // Note: Duplex extends both Readable and Writable. - export class Duplex extends Readable implements Writable { - writable: boolean; - constructor(opts?: DuplexOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - setDefaultEncoding(encoding: string): this; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - } + // Note: Duplex extends both Readable and Writable. + export class Duplex extends Readable implements Writable { + writable: boolean; + constructor(opts?: DuplexOptions); + _write(chunk: any, encoding: string, callback: Function): void; + write(chunk: any, cb?: Function): boolean; + write(chunk: any, encoding?: string, cb?: Function): boolean; + setDefaultEncoding(encoding: string): this; + end(): void; + end(chunk: any, cb?: Function): void; + end(chunk: any, encoding?: string, cb?: Function): void; + } - export interface TransformOptions extends DuplexOptions { - transform?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - flush?: (callback: Function) => any; - } + export interface TransformOptions extends DuplexOptions { + transform?: (chunk: string | Buffer, encoding: string, callback: Function) => any; + flush?: (callback: Function) => any; + } - export class Transform extends Duplex { - constructor(opts?: TransformOptions); - _transform(chunk: any, encoding: string, callback: Function): void; - } + export class Transform extends Duplex { + constructor(opts?: TransformOptions); + _transform(chunk: any, encoding: string, callback: Function): void; + } - export class PassThrough extends Transform { } - } + export class PassThrough extends Transform { } + } - export = internal; + export = internal; } declare module "util" { - export interface InspectOptions extends NodeJS.InspectOptions { } - export function format(format: any, ...param: any[]): string; - export function debug(string: string): void; - export function error(...param: any[]): void; - export function puts(...param: any[]): void; - export function print(...param: any[]): void; - export function log(string: string): void; - export function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string; - export function inspect(object: any, options: InspectOptions): string; - export function isArray(object: any): object is any[]; - export function isRegExp(object: any): object is RegExp; - export function isDate(object: any): object is Date; - export function isError(object: any): object is Error; - export function inherits(constructor: any, superConstructor: any): void; - export function debuglog(key: string): (msg: string, ...param: any[]) => void; - export function isBoolean(object: any): object is boolean; - export function isBuffer(object: any): object is Buffer; - export function isFunction(object: any): boolean; - export function isNull(object: any): object is null; - export function isNullOrUndefined(object: any): object is null | undefined; - export function isNumber(object: any): object is number; - export function isObject(object: any): boolean; - export function isPrimitive(object: any): boolean; - export function isString(object: any): object is string; - export function isSymbol(object: any): object is symbol; - export function isUndefined(object: any): object is undefined; - export function deprecate<T extends Function>(fn: T, message: string): T; + export interface InspectOptions extends NodeJS.InspectOptions { } + export function format(format: any, ...param: any[]): string; + export function debug(string: string): void; + export function error(...param: any[]): void; + export function puts(...param: any[]): void; + export function print(...param: any[]): void; + export function log(string: string): void; + export function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string; + export function inspect(object: any, options: InspectOptions): string; + export function isArray(object: any): object is any[]; + export function isRegExp(object: any): object is RegExp; + export function isDate(object: any): object is Date; + export function isError(object: any): object is Error; + export function inherits(constructor: any, superConstructor: any): void; + export function debuglog(key: string): (msg: string, ...param: any[]) => void; + export function isBoolean(object: any): object is boolean; + export function isBuffer(object: any): object is Buffer; + export function isFunction(object: any): boolean; + export function isNull(object: any): object is null; + export function isNullOrUndefined(object: any): object is null | undefined; + export function isNumber(object: any): object is number; + export function isObject(object: any): boolean; + export function isPrimitive(object: any): boolean; + export function isString(object: any): object is string; + export function isSymbol(object: any): object is symbol; + export function isUndefined(object: any): object is undefined; + export function deprecate<T extends Function>(fn: T, message: string): T; } declare module "assert" { - function internal(value: any, message?: string): void; - namespace internal { - export class AssertionError implements Error { - name: string; - message: string; - actual: any; - expected: any; - operator: string; - generatedMessage: boolean; + function internal(value: any, message?: string): void; + namespace internal { + export class AssertionError implements Error { + name: string; + message: string; + actual: any; + expected: any; + operator: string; + generatedMessage: boolean; - constructor(options?: { - message?: string; actual?: any; expected?: any; - operator?: string; stackStartFunction?: Function - }); - } + constructor(options?: { + message?: string; actual?: any; expected?: any; + operator?: string; stackStartFunction?: Function + }); + } - export function fail(actual?: any, expected?: any, message?: string, operator?: string): void; - export function ok(value: any, message?: string): void; - export function equal(actual: any, expected: any, message?: string): void; - export function notEqual(actual: any, expected: any, message?: string): void; - export function deepEqual(actual: any, expected: any, message?: string): void; - export function notDeepEqual(acutal: any, expected: any, message?: string): void; - export function strictEqual(actual: any, expected: any, message?: string): void; - export function notStrictEqual(actual: any, expected: any, message?: string): void; - export function deepStrictEqual(actual: any, expected: any, message?: string): void; - export function notDeepStrictEqual(actual: any, expected: any, message?: string): void; + export function fail(actual?: any, expected?: any, message?: string, operator?: string): void; + export function ok(value: any, message?: string): void; + export function equal(actual: any, expected: any, message?: string): void; + export function notEqual(actual: any, expected: any, message?: string): void; + export function deepEqual(actual: any, expected: any, message?: string): void; + export function notDeepEqual(acutal: any, expected: any, message?: string): void; + export function strictEqual(actual: any, expected: any, message?: string): void; + export function notStrictEqual(actual: any, expected: any, message?: string): void; + export function deepStrictEqual(actual: any, expected: any, message?: string): void; + export function notDeepStrictEqual(actual: any, expected: any, message?: string): void; - export function throws(block: Function, message?: string): void; - export function throws(block: Function, error: Function, message?: string): void; - export function throws(block: Function, error: RegExp, message?: string): void; - export function throws(block: Function, error: (err: any) => boolean, message?: string): void; + export function throws(block: Function, message?: string): void; + export function throws(block: Function, error: Function, message?: string): void; + export function throws(block: Function, error: RegExp, message?: string): void; + export function throws(block: Function, error: (err: any) => boolean, message?: string): void; - export function doesNotThrow(block: Function, message?: string): void; - export function doesNotThrow(block: Function, error: Function, message?: string): void; - export function doesNotThrow(block: Function, error: RegExp, message?: string): void; - export function doesNotThrow(block: Function, error: (err: any) => boolean, message?: string): void; + export function doesNotThrow(block: Function, message?: string): void; + export function doesNotThrow(block: Function, error: Function, message?: string): void; + export function doesNotThrow(block: Function, error: RegExp, message?: string): void; + export function doesNotThrow(block: Function, error: (err: any) => boolean, message?: string): void; - export function ifError(value: any): void; - } + export function ifError(value: any): void; + } - export = internal; + export = internal; } declare module "tty" { - import * as net from "net"; + import * as net from "net"; - export function isatty(fd: number): boolean; - export interface ReadStream extends net.Socket { - isRaw: boolean; - setRawMode(mode: boolean): void; - isTTY: boolean; - } - export interface WriteStream extends net.Socket { - columns: number; - rows: number; - isTTY: boolean; - } + export function isatty(fd: number): boolean; + export interface ReadStream extends net.Socket { + isRaw: boolean; + setRawMode(mode: boolean): void; + isTTY: boolean; + } + export interface WriteStream extends net.Socket { + columns: number; + rows: number; + isTTY: boolean; + } } declare module "domain" { - import * as events from "events"; + import * as events from "events"; - export class Domain extends events.EventEmitter implements NodeJS.Domain { - run(fn: Function): void; - add(emitter: events.EventEmitter): void; - remove(emitter: events.EventEmitter): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - members: any[]; - enter(): void; - exit(): void; - } + export class Domain extends events.EventEmitter implements NodeJS.Domain { + run(fn: Function): void; + add(emitter: events.EventEmitter): void; + remove(emitter: events.EventEmitter): void; + bind(cb: (err: Error, data: any) => any): any; + intercept(cb: (data: any) => any): any; + dispose(): void; + members: any[]; + enter(): void; + exit(): void; + } - export function create(): Domain; + export function create(): Domain; } declare module "constants" { - export var E2BIG: number; - export var EACCES: number; - export var EADDRINUSE: number; - export var EADDRNOTAVAIL: number; - export var EAFNOSUPPORT: number; - export var EAGAIN: number; - export var EALREADY: number; - export var EBADF: number; - export var EBADMSG: number; - export var EBUSY: number; - export var ECANCELED: number; - export var ECHILD: number; - export var ECONNABORTED: number; - export var ECONNREFUSED: number; - export var ECONNRESET: number; - export var EDEADLK: number; - export var EDESTADDRREQ: number; - export var EDOM: number; - export var EEXIST: number; - export var EFAULT: number; - export var EFBIG: number; - export var EHOSTUNREACH: number; - export var EIDRM: number; - export var EILSEQ: number; - export var EINPROGRESS: number; - export var EINTR: number; - export var EINVAL: number; - export var EIO: number; - export var EISCONN: number; - export var EISDIR: number; - export var ELOOP: number; - export var EMFILE: number; - export var EMLINK: number; - export var EMSGSIZE: number; - export var ENAMETOOLONG: number; - export var ENETDOWN: number; - export var ENETRESET: number; - export var ENETUNREACH: number; - export var ENFILE: number; - export var ENOBUFS: number; - export var ENODATA: number; - export var ENODEV: number; - export var ENOENT: number; - export var ENOEXEC: number; - export var ENOLCK: number; - export var ENOLINK: number; - export var ENOMEM: number; - export var ENOMSG: number; - export var ENOPROTOOPT: number; - export var ENOSPC: number; - export var ENOSR: number; - export var ENOSTR: number; - export var ENOSYS: number; - export var ENOTCONN: number; - export var ENOTDIR: number; - export var ENOTEMPTY: number; - export var ENOTSOCK: number; - export var ENOTSUP: number; - export var ENOTTY: number; - export var ENXIO: number; - export var EOPNOTSUPP: number; - export var EOVERFLOW: number; - export var EPERM: number; - export var EPIPE: number; - export var EPROTO: number; - export var EPROTONOSUPPORT: number; - export var EPROTOTYPE: number; - export var ERANGE: number; - export var EROFS: number; - export var ESPIPE: number; - export var ESRCH: number; - export var ETIME: number; - export var ETIMEDOUT: number; - export var ETXTBSY: number; - export var EWOULDBLOCK: number; - export var EXDEV: number; - export var WSAEINTR: number; - export var WSAEBADF: number; - export var WSAEACCES: number; - export var WSAEFAULT: number; - export var WSAEINVAL: number; - export var WSAEMFILE: number; - export var WSAEWOULDBLOCK: number; - export var WSAEINPROGRESS: number; - export var WSAEALREADY: number; - export var WSAENOTSOCK: number; - export var WSAEDESTADDRREQ: number; - export var WSAEMSGSIZE: number; - export var WSAEPROTOTYPE: number; - export var WSAENOPROTOOPT: number; - export var WSAEPROTONOSUPPORT: number; - export var WSAESOCKTNOSUPPORT: number; - export var WSAEOPNOTSUPP: number; - export var WSAEPFNOSUPPORT: number; - export var WSAEAFNOSUPPORT: number; - export var WSAEADDRINUSE: number; - export var WSAEADDRNOTAVAIL: number; - export var WSAENETDOWN: number; - export var WSAENETUNREACH: number; - export var WSAENETRESET: number; - export var WSAECONNABORTED: number; - export var WSAECONNRESET: number; - export var WSAENOBUFS: number; - export var WSAEISCONN: number; - export var WSAENOTCONN: number; - export var WSAESHUTDOWN: number; - export var WSAETOOMANYREFS: number; - export var WSAETIMEDOUT: number; - export var WSAECONNREFUSED: number; - export var WSAELOOP: number; - export var WSAENAMETOOLONG: number; - export var WSAEHOSTDOWN: number; - export var WSAEHOSTUNREACH: number; - export var WSAENOTEMPTY: number; - export var WSAEPROCLIM: number; - export var WSAEUSERS: number; - export var WSAEDQUOT: number; - export var WSAESTALE: number; - export var WSAEREMOTE: number; - export var WSASYSNOTREADY: number; - export var WSAVERNOTSUPPORTED: number; - export var WSANOTINITIALISED: number; - export var WSAEDISCON: number; - export var WSAENOMORE: number; - export var WSAECANCELLED: number; - export var WSAEINVALIDPROCTABLE: number; - export var WSAEINVALIDPROVIDER: number; - export var WSAEPROVIDERFAILEDINIT: number; - export var WSASYSCALLFAILURE: number; - export var WSASERVICE_NOT_FOUND: number; - export var WSATYPE_NOT_FOUND: number; - export var WSA_E_NO_MORE: number; - export var WSA_E_CANCELLED: number; - export var WSAEREFUSED: number; - export var SIGHUP: number; - export var SIGINT: number; - export var SIGILL: number; - export var SIGABRT: number; - export var SIGFPE: number; - export var SIGKILL: number; - export var SIGSEGV: number; - export var SIGTERM: number; - export var SIGBREAK: number; - export var SIGWINCH: number; - export var SSL_OP_ALL: number; - export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; - export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; - export var SSL_OP_CISCO_ANYCONNECT: number; - export var SSL_OP_COOKIE_EXCHANGE: number; - export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; - export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; - export var SSL_OP_EPHEMERAL_RSA: number; - export var SSL_OP_LEGACY_SERVER_CONNECT: number; - export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; - export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; - export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; - export var SSL_OP_NETSCAPE_CA_DN_BUG: number; - export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; - export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NO_COMPRESSION: number; - export var SSL_OP_NO_QUERY_MTU: number; - export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; - export var SSL_OP_NO_SSLv2: number; - export var SSL_OP_NO_SSLv3: number; - export var SSL_OP_NO_TICKET: number; - export var SSL_OP_NO_TLSv1: number; - export var SSL_OP_NO_TLSv1_1: number; - export var SSL_OP_NO_TLSv1_2: number; - export var SSL_OP_PKCS1_CHECK_1: number; - export var SSL_OP_PKCS1_CHECK_2: number; - export var SSL_OP_SINGLE_DH_USE: number; - export var SSL_OP_SINGLE_ECDH_USE: number; - export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; - export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; - export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; - export var SSL_OP_TLS_D5_BUG: number; - export var SSL_OP_TLS_ROLLBACK_BUG: number; - export var ENGINE_METHOD_DSA: number; - export var ENGINE_METHOD_DH: number; - export var ENGINE_METHOD_RAND: number; - export var ENGINE_METHOD_ECDH: number; - export var ENGINE_METHOD_ECDSA: number; - export var ENGINE_METHOD_CIPHERS: number; - export var ENGINE_METHOD_DIGESTS: number; - export var ENGINE_METHOD_STORE: number; - export var ENGINE_METHOD_PKEY_METHS: number; - export var ENGINE_METHOD_PKEY_ASN1_METHS: number; - export var ENGINE_METHOD_ALL: number; - export var ENGINE_METHOD_NONE: number; - export var DH_CHECK_P_NOT_SAFE_PRIME: number; - export var DH_CHECK_P_NOT_PRIME: number; - export var DH_UNABLE_TO_CHECK_GENERATOR: number; - export var DH_NOT_SUITABLE_GENERATOR: number; - export var NPN_ENABLED: number; - export var RSA_PKCS1_PADDING: number; - export var RSA_SSLV23_PADDING: number; - export var RSA_NO_PADDING: number; - export var RSA_PKCS1_OAEP_PADDING: number; - export var RSA_X931_PADDING: number; - export var RSA_PKCS1_PSS_PADDING: number; - export var POINT_CONVERSION_COMPRESSED: number; - export var POINT_CONVERSION_UNCOMPRESSED: number; - export var POINT_CONVERSION_HYBRID: number; - export var O_RDONLY: number; - export var O_WRONLY: number; - export var O_RDWR: number; - export var S_IFMT: number; - export var S_IFREG: number; - export var S_IFDIR: number; - export var S_IFCHR: number; - export var S_IFBLK: number; - export var S_IFIFO: number; - export var S_IFSOCK: number; - export var S_IRWXU: number; - export var S_IRUSR: number; - export var S_IWUSR: number; - export var S_IXUSR: number; - export var S_IRWXG: number; - export var S_IRGRP: number; - export var S_IWGRP: number; - export var S_IXGRP: number; - export var S_IRWXO: number; - export var S_IROTH: number; - export var S_IWOTH: number; - export var S_IXOTH: number; - export var S_IFLNK: number; - export var O_CREAT: number; - export var O_EXCL: number; - export var O_NOCTTY: number; - export var O_DIRECTORY: number; - export var O_NOATIME: number; - export var O_NOFOLLOW: number; - export var O_SYNC: number; - export var O_SYMLINK: number; - export var O_DIRECT: number; - export var O_NONBLOCK: number; - export var O_TRUNC: number; - export var O_APPEND: number; - export var F_OK: number; - export var R_OK: number; - export var W_OK: number; - export var X_OK: number; - export var UV_UDP_REUSEADDR: number; - export var SIGQUIT: number; - export var SIGTRAP: number; - export var SIGIOT: number; - export var SIGBUS: number; - export var SIGUSR1: number; - export var SIGUSR2: number; - export var SIGPIPE: number; - export var SIGALRM: number; - export var SIGCHLD: number; - export var SIGSTKFLT: number; - export var SIGCONT: number; - export var SIGSTOP: number; - export var SIGTSTP: number; - export var SIGTTIN: number; - export var SIGTTOU: number; - export var SIGURG: number; - export var SIGXCPU: number; - export var SIGXFSZ: number; - export var SIGVTALRM: number; - export var SIGPROF: number; - export var SIGIO: number; - export var SIGPOLL: number; - export var SIGPWR: number; - export var SIGSYS: number; - export var SIGUNUSED: number; - export var defaultCoreCipherList: string; - export var defaultCipherList: string; - export var ENGINE_METHOD_RSA: number; - export var ALPN_ENABLED: number; + export var E2BIG: number; + export var EACCES: number; + export var EADDRINUSE: number; + export var EADDRNOTAVAIL: number; + export var EAFNOSUPPORT: number; + export var EAGAIN: number; + export var EALREADY: number; + export var EBADF: number; + export var EBADMSG: number; + export var EBUSY: number; + export var ECANCELED: number; + export var ECHILD: number; + export var ECONNABORTED: number; + export var ECONNREFUSED: number; + export var ECONNRESET: number; + export var EDEADLK: number; + export var EDESTADDRREQ: number; + export var EDOM: number; + export var EEXIST: number; + export var EFAULT: number; + export var EFBIG: number; + export var EHOSTUNREACH: number; + export var EIDRM: number; + export var EILSEQ: number; + export var EINPROGRESS: number; + export var EINTR: number; + export var EINVAL: number; + export var EIO: number; + export var EISCONN: number; + export var EISDIR: number; + export var ELOOP: number; + export var EMFILE: number; + export var EMLINK: number; + export var EMSGSIZE: number; + export var ENAMETOOLONG: number; + export var ENETDOWN: number; + export var ENETRESET: number; + export var ENETUNREACH: number; + export var ENFILE: number; + export var ENOBUFS: number; + export var ENODATA: number; + export var ENODEV: number; + export var ENOENT: number; + export var ENOEXEC: number; + export var ENOLCK: number; + export var ENOLINK: number; + export var ENOMEM: number; + export var ENOMSG: number; + export var ENOPROTOOPT: number; + export var ENOSPC: number; + export var ENOSR: number; + export var ENOSTR: number; + export var ENOSYS: number; + export var ENOTCONN: number; + export var ENOTDIR: number; + export var ENOTEMPTY: number; + export var ENOTSOCK: number; + export var ENOTSUP: number; + export var ENOTTY: number; + export var ENXIO: number; + export var EOPNOTSUPP: number; + export var EOVERFLOW: number; + export var EPERM: number; + export var EPIPE: number; + export var EPROTO: number; + export var EPROTONOSUPPORT: number; + export var EPROTOTYPE: number; + export var ERANGE: number; + export var EROFS: number; + export var ESPIPE: number; + export var ESRCH: number; + export var ETIME: number; + export var ETIMEDOUT: number; + export var ETXTBSY: number; + export var EWOULDBLOCK: number; + export var EXDEV: number; + export var WSAEINTR: number; + export var WSAEBADF: number; + export var WSAEACCES: number; + export var WSAEFAULT: number; + export var WSAEINVAL: number; + export var WSAEMFILE: number; + export var WSAEWOULDBLOCK: number; + export var WSAEINPROGRESS: number; + export var WSAEALREADY: number; + export var WSAENOTSOCK: number; + export var WSAEDESTADDRREQ: number; + export var WSAEMSGSIZE: number; + export var WSAEPROTOTYPE: number; + export var WSAENOPROTOOPT: number; + export var WSAEPROTONOSUPPORT: number; + export var WSAESOCKTNOSUPPORT: number; + export var WSAEOPNOTSUPP: number; + export var WSAEPFNOSUPPORT: number; + export var WSAEAFNOSUPPORT: number; + export var WSAEADDRINUSE: number; + export var WSAEADDRNOTAVAIL: number; + export var WSAENETDOWN: number; + export var WSAENETUNREACH: number; + export var WSAENETRESET: number; + export var WSAECONNABORTED: number; + export var WSAECONNRESET: number; + export var WSAENOBUFS: number; + export var WSAEISCONN: number; + export var WSAENOTCONN: number; + export var WSAESHUTDOWN: number; + export var WSAETOOMANYREFS: number; + export var WSAETIMEDOUT: number; + export var WSAECONNREFUSED: number; + export var WSAELOOP: number; + export var WSAENAMETOOLONG: number; + export var WSAEHOSTDOWN: number; + export var WSAEHOSTUNREACH: number; + export var WSAENOTEMPTY: number; + export var WSAEPROCLIM: number; + export var WSAEUSERS: number; + export var WSAEDQUOT: number; + export var WSAESTALE: number; + export var WSAEREMOTE: number; + export var WSASYSNOTREADY: number; + export var WSAVERNOTSUPPORTED: number; + export var WSANOTINITIALISED: number; + export var WSAEDISCON: number; + export var WSAENOMORE: number; + export var WSAECANCELLED: number; + export var WSAEINVALIDPROCTABLE: number; + export var WSAEINVALIDPROVIDER: number; + export var WSAEPROVIDERFAILEDINIT: number; + export var WSASYSCALLFAILURE: number; + export var WSASERVICE_NOT_FOUND: number; + export var WSATYPE_NOT_FOUND: number; + export var WSA_E_NO_MORE: number; + export var WSA_E_CANCELLED: number; + export var WSAEREFUSED: number; + export var SIGHUP: number; + export var SIGINT: number; + export var SIGILL: number; + export var SIGABRT: number; + export var SIGFPE: number; + export var SIGKILL: number; + export var SIGSEGV: number; + export var SIGTERM: number; + export var SIGBREAK: number; + export var SIGWINCH: number; + export var SSL_OP_ALL: number; + export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; + export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; + export var SSL_OP_CISCO_ANYCONNECT: number; + export var SSL_OP_COOKIE_EXCHANGE: number; + export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; + export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; + export var SSL_OP_EPHEMERAL_RSA: number; + export var SSL_OP_LEGACY_SERVER_CONNECT: number; + export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; + export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; + export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; + export var SSL_OP_NETSCAPE_CA_DN_BUG: number; + export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; + export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; + export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; + export var SSL_OP_NO_COMPRESSION: number; + export var SSL_OP_NO_QUERY_MTU: number; + export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; + export var SSL_OP_NO_SSLv2: number; + export var SSL_OP_NO_SSLv3: number; + export var SSL_OP_NO_TICKET: number; + export var SSL_OP_NO_TLSv1: number; + export var SSL_OP_NO_TLSv1_1: number; + export var SSL_OP_NO_TLSv1_2: number; + export var SSL_OP_PKCS1_CHECK_1: number; + export var SSL_OP_PKCS1_CHECK_2: number; + export var SSL_OP_SINGLE_DH_USE: number; + export var SSL_OP_SINGLE_ECDH_USE: number; + export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; + export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; + export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; + export var SSL_OP_TLS_D5_BUG: number; + export var SSL_OP_TLS_ROLLBACK_BUG: number; + export var ENGINE_METHOD_DSA: number; + export var ENGINE_METHOD_DH: number; + export var ENGINE_METHOD_RAND: number; + export var ENGINE_METHOD_ECDH: number; + export var ENGINE_METHOD_ECDSA: number; + export var ENGINE_METHOD_CIPHERS: number; + export var ENGINE_METHOD_DIGESTS: number; + export var ENGINE_METHOD_STORE: number; + export var ENGINE_METHOD_PKEY_METHS: number; + export var ENGINE_METHOD_PKEY_ASN1_METHS: number; + export var ENGINE_METHOD_ALL: number; + export var ENGINE_METHOD_NONE: number; + export var DH_CHECK_P_NOT_SAFE_PRIME: number; + export var DH_CHECK_P_NOT_PRIME: number; + export var DH_UNABLE_TO_CHECK_GENERATOR: number; + export var DH_NOT_SUITABLE_GENERATOR: number; + export var NPN_ENABLED: number; + export var RSA_PKCS1_PADDING: number; + export var RSA_SSLV23_PADDING: number; + export var RSA_NO_PADDING: number; + export var RSA_PKCS1_OAEP_PADDING: number; + export var RSA_X931_PADDING: number; + export var RSA_PKCS1_PSS_PADDING: number; + export var POINT_CONVERSION_COMPRESSED: number; + export var POINT_CONVERSION_UNCOMPRESSED: number; + export var POINT_CONVERSION_HYBRID: number; + export var O_RDONLY: number; + export var O_WRONLY: number; + export var O_RDWR: number; + export var S_IFMT: number; + export var S_IFREG: number; + export var S_IFDIR: number; + export var S_IFCHR: number; + export var S_IFBLK: number; + export var S_IFIFO: number; + export var S_IFSOCK: number; + export var S_IRWXU: number; + export var S_IRUSR: number; + export var S_IWUSR: number; + export var S_IXUSR: number; + export var S_IRWXG: number; + export var S_IRGRP: number; + export var S_IWGRP: number; + export var S_IXGRP: number; + export var S_IRWXO: number; + export var S_IROTH: number; + export var S_IWOTH: number; + export var S_IXOTH: number; + export var S_IFLNK: number; + export var O_CREAT: number; + export var O_EXCL: number; + export var O_NOCTTY: number; + export var O_DIRECTORY: number; + export var O_NOATIME: number; + export var O_NOFOLLOW: number; + export var O_SYNC: number; + export var O_SYMLINK: number; + export var O_DIRECT: number; + export var O_NONBLOCK: number; + export var O_TRUNC: number; + export var O_APPEND: number; + export var F_OK: number; + export var R_OK: number; + export var W_OK: number; + export var X_OK: number; + export var UV_UDP_REUSEADDR: number; + export var SIGQUIT: number; + export var SIGTRAP: number; + export var SIGIOT: number; + export var SIGBUS: number; + export var SIGUSR1: number; + export var SIGUSR2: number; + export var SIGPIPE: number; + export var SIGALRM: number; + export var SIGCHLD: number; + export var SIGSTKFLT: number; + export var SIGCONT: number; + export var SIGSTOP: number; + export var SIGTSTP: number; + export var SIGTTIN: number; + export var SIGTTOU: number; + export var SIGURG: number; + export var SIGXCPU: number; + export var SIGXFSZ: number; + export var SIGVTALRM: number; + export var SIGPROF: number; + export var SIGIO: number; + export var SIGPOLL: number; + export var SIGPWR: number; + export var SIGSYS: number; + export var SIGUNUSED: number; + export var defaultCoreCipherList: string; + export var defaultCipherList: string; + export var ENGINE_METHOD_RSA: number; + export var ALPN_ENABLED: number; } declare module "process" { - export = process; + export = process; } declare module "v8" { - interface HeapSpaceInfo { - space_name: string; - space_size: number; - space_used_size: number; - space_available_size: number; - physical_space_size: number; - } + interface HeapSpaceInfo { + space_name: string; + space_size: number; + space_used_size: number; + space_available_size: number; + physical_space_size: number; + } - //** Signifies if the --zap_code_space option is enabled or not. 1 == enabled, 0 == disabled. */ - type DoesZapCodeSpaceFlag = 0 | 1; + //** Signifies if the --zap_code_space option is enabled or not. 1 == enabled, 0 == disabled. */ + type DoesZapCodeSpaceFlag = 0 | 1; - interface HeapInfo { - total_heap_size: number; - total_heap_size_executable: number; - total_physical_size: number; - total_available_size: number; - used_heap_size: number; - heap_size_limit: number; - malloced_memory: number; - peak_malloced_memory: number; - does_zap_garbage: DoesZapCodeSpaceFlag; - } + interface HeapInfo { + total_heap_size: number; + total_heap_size_executable: number; + total_physical_size: number; + total_available_size: number; + used_heap_size: number; + heap_size_limit: number; + malloced_memory: number; + peak_malloced_memory: number; + does_zap_garbage: DoesZapCodeSpaceFlag; + } - export function getHeapStatistics(): HeapInfo; - export function getHeapSpaceStatistics(): HeapSpaceInfo[]; - export function setFlagsFromString(flags: string): void; + export function getHeapStatistics(): HeapInfo; + export function getHeapSpaceStatistics(): HeapSpaceInfo[]; + export function setFlagsFromString(flags: string): void; } declare module "timers" { - export function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearTimeout(timeoutId: NodeJS.Timer): void; - export function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearInterval(intervalId: NodeJS.Timer): void; - export function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; - export function clearImmediate(immediateId: any): void; + export function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; + export function clearTimeout(timeoutId: NodeJS.Timer): void; + export function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; + export function clearInterval(intervalId: NodeJS.Timer): void; + export function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; + export function clearImmediate(immediateId: any): void; } declare module "console" { - export = console; + export = console; } /** @@ -4254,124 +4254,124 @@ declare module "console" { * Source code is at https://github.com/nodejs/node/blob/master/lib/_debugger.js */ declare module "_debugger" { - export interface Packet { - raw: string; - headers: string[]; - body: Message; - } + export interface Packet { + raw: string; + headers: string[]; + body: Message; + } - export interface Message { - seq: number; - type: string; - } + export interface Message { + seq: number; + type: string; + } - export interface RequestInfo { - command: string; - arguments: any; - } + export interface RequestInfo { + command: string; + arguments: any; + } - export interface Request extends Message, RequestInfo { - } + export interface Request extends Message, RequestInfo { + } - export interface Event extends Message { - event: string; - body?: any; - } + export interface Event extends Message { + event: string; + body?: any; + } - export interface Response extends Message { - request_seq: number; - success: boolean; - /** Contains error message if success === false. */ - message?: string; - /** Contains message body if success === true. */ - body?: any; - } + export interface Response extends Message { + request_seq: number; + success: boolean; + /** Contains error message if success === false. */ + message?: string; + /** Contains message body if success === true. */ + body?: any; + } - export interface BreakpointMessageBody { - type: string; - target: number; - line: number; - } + export interface BreakpointMessageBody { + type: string; + target: number; + line: number; + } - export class Protocol { - res: Packet; - state: string; - execute(data: string): void; - serialize(rq: Request): string; - onResponse: (pkt: Packet) => void; - } + export class Protocol { + res: Packet; + state: string; + execute(data: string): void; + serialize(rq: Request): string; + onResponse: (pkt: Packet) => void; + } - export var NO_FRAME: number; - export var port: number; + export var NO_FRAME: number; + export var port: number; - export interface ScriptDesc { - name: string; - id: number; - isNative?: boolean; - handle?: number; - type: string; - lineOffset?: number; - columnOffset?: number; - lineCount?: number; - } + export interface ScriptDesc { + name: string; + id: number; + isNative?: boolean; + handle?: number; + type: string; + lineOffset?: number; + columnOffset?: number; + lineCount?: number; + } - export interface Breakpoint { - id: number; - scriptId: number; - script: ScriptDesc; - line: number; - condition?: string; - scriptReq?: string; - } + export interface Breakpoint { + id: number; + scriptId: number; + script: ScriptDesc; + line: number; + condition?: string; + scriptReq?: string; + } - export interface RequestHandler { - (err: boolean, body: Message, res: Packet): void; - request_seq?: number; - } + export interface RequestHandler { + (err: boolean, body: Message, res: Packet): void; + request_seq?: number; + } - export interface ResponseBodyHandler { - (err: boolean, body?: any): void; - request_seq?: number; - } + export interface ResponseBodyHandler { + (err: boolean, body?: any): void; + request_seq?: number; + } - export interface ExceptionInfo { - text: string; - } + export interface ExceptionInfo { + text: string; + } - export interface BreakResponse { - script?: ScriptDesc; - exception?: ExceptionInfo; - sourceLine: number; - sourceLineText: string; - sourceColumn: number; - } + export interface BreakResponse { + script?: ScriptDesc; + exception?: ExceptionInfo; + sourceLine: number; + sourceLineText: string; + sourceColumn: number; + } - export function SourceInfo(body: BreakResponse): string; + export function SourceInfo(body: BreakResponse): string; - export interface ClientInstance extends NodeJS.EventEmitter { - protocol: Protocol; - scripts: ScriptDesc[]; - handles: ScriptDesc[]; - breakpoints: Breakpoint[]; - currentSourceLine: number; - currentSourceColumn: number; - currentSourceLineText: string; - currentFrame: number; - currentScript: string; + export interface ClientInstance extends NodeJS.EventEmitter { + protocol: Protocol; + scripts: ScriptDesc[]; + handles: ScriptDesc[]; + breakpoints: Breakpoint[]; + currentSourceLine: number; + currentSourceColumn: number; + currentSourceLineText: string; + currentFrame: number; + currentScript: string; - connect(port: number, host: string): void; - req(req: any, cb: RequestHandler): void; - reqFrameEval(code: string, frame: number, cb: RequestHandler): void; - mirrorObject(obj: any, depth: number, cb: ResponseBodyHandler): void; - setBreakpoint(rq: BreakpointMessageBody, cb: RequestHandler): void; - clearBreakpoint(rq: Request, cb: RequestHandler): void; - listbreakpoints(cb: RequestHandler): void; - reqSource(from: number, to: number, cb: RequestHandler): void; - reqScripts(cb: any): void; - reqContinue(cb: RequestHandler): void; - } + connect(port: number, host: string): void; + req(req: any, cb: RequestHandler): void; + reqFrameEval(code: string, frame: number, cb: RequestHandler): void; + mirrorObject(obj: any, depth: number, cb: ResponseBodyHandler): void; + setBreakpoint(rq: BreakpointMessageBody, cb: RequestHandler): void; + clearBreakpoint(rq: Request, cb: RequestHandler): void; + listbreakpoints(cb: RequestHandler): void; + reqSource(from: number, to: number, cb: RequestHandler): void; + reqScripts(cb: any): void; + reqContinue(cb: RequestHandler): void; + } - export var Client: { - new(): ClientInstance - } + export var Client: { + new(): ClientInstance + } } diff --git a/src/typings/nsfw.d.ts b/src/typings/vscode-nsfw.d.ts similarity index 96% rename from src/typings/nsfw.d.ts rename to src/typings/vscode-nsfw.d.ts index fe18f2f4fe..c9863ca887 100644 --- a/src/typings/nsfw.d.ts +++ b/src/typings/vscode-nsfw.d.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare module 'nsfw' { +declare module 'vscode-nsfw' { interface NsfwWatcher { start(): any; stop(): any; diff --git a/src/typings/vscode-textmate.d.ts b/src/typings/vscode-textmate.d.ts index 83ffe53c03..2237194fac 100644 --- a/src/typings/vscode-textmate.d.ts +++ b/src/typings/vscode-textmate.d.ts @@ -37,12 +37,22 @@ declare module "vscode-textmate" { export interface IEmbeddedLanguagesMap { [scopeName: string]: number; } + /** + * A map from scope name to a token type. + */ + export interface ITokenTypeMap { + [scopeName: string]: StandardTokenType; + } export const enum StandardTokenType { Other = 0, Comment = 1, String = 2, RegEx = 4, } + export interface IGrammarConfiguration { + embeddedLanguages?: IEmbeddedLanguagesMap; + tokenTypes?: ITokenTypeMap; + } /** * The registry that will hold all grammars. */ @@ -63,6 +73,11 @@ declare module "vscode-textmate" { * Please do not use language id 0. */ loadGrammarWithEmbeddedLanguages(initialScopeName: string, initialLanguage: number, embeddedLanguages: IEmbeddedLanguagesMap, callback: (err: any, grammar: IGrammar) => void): void; + /** + * Load the grammar for `scopeName` and all referenced included grammars asynchronously. + * Please do not use language id 0. + */ + loadGrammarWithConfiguration(initialScopeName: string, initialLanguage: number, configuration: IGrammarConfiguration, callback: (err: any, grammar: IGrammar) => void): void; /** * Load the grammar for `scopeName` and all referenced included grammars asynchronously. */ @@ -75,7 +90,7 @@ declare module "vscode-textmate" { /** * Get the grammar for `scopeName`. The grammar must first be created via `loadGrammar` or `loadGrammarFromPathSync`. */ - grammarForScopeName(scopeName: string, initialLanguage?: number, embeddedLanguages?: IEmbeddedLanguagesMap): IGrammar; + grammarForScopeName(scopeName: string, initialLanguage?: number, embeddedLanguages?: IEmbeddedLanguagesMap, tokenTypes?: ITokenTypeMap): IGrammar; } /** * A grammar diff --git a/src/typings/vscode-xterm.d.ts b/src/typings/vscode-xterm.d.ts index 09252b3e5c..2bbcfac4f8 100644 --- a/src/typings/vscode-xterm.d.ts +++ b/src/typings/vscode-xterm.d.ts @@ -17,6 +17,13 @@ declare module 'vscode-xterm' { * An object containing start up options for the terminal. */ export interface ITerminalOptions { + /** + * Whether background should support non-opaque color. It must be set before + * executing open() method and can't be changed later without excuting it again. + * Warning: Enabling this option can reduce performances somewhat. + */ + allowTransparency?: boolean; + /** * A data uri of the sound to use for the bell (needs bellStyle = 'sound'). */ @@ -49,6 +56,8 @@ declare module 'vscode-xterm' { /** * Whether to enable the rendering of bold text. + * + * @deprecated Use fontWeight and fontWeightBold instead. */ enableBold?: boolean; @@ -181,8 +190,8 @@ declare module 'vscode-xterm' { matchIndex?: number; /** - * A callback that validates an individual link, returning true if valid and - * false if invalid. + * A callback that validates whether to create an individual link, pass + * whether the link is valid to the callback. */ validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; @@ -214,29 +223,35 @@ declare module 'vscode-xterm' { } export interface IEventEmitter { - on(type: string, listener: (...args: any[]) => void): void; - off(type: string, listener: (...args: any[]) => void): void; - emit(type: string, data?: any): void; - addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; + on(type: string, listener: (...args: any[]) => void): void; + off(type: string, listener: (...args: any[]) => void): void; + emit(type: string, data?: any): void; + addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; } /** * An object that can be disposed via a dispose function. */ export interface IDisposable { - dispose(): void; + dispose(): void; + } + + export interface IMarker extends IDisposable { + readonly id: number; + readonly isDisposed: boolean; + readonly line: number; } export interface ILocalizableStrings { - blankLine: string; - promptLabel: string; - tooMuchOutput: string; + blankLine: string; + promptLabel: string; + tooMuchOutput: string; } /** * The class that represents an xterm.js terminal. */ - export class Terminal { + export class Terminal implements IEventEmitter { /** * The element containing the terminal. */ @@ -257,6 +272,12 @@ declare module 'vscode-xterm' { */ cols: number; + /** + * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt + * buffer is active this will always return []. + */ + markers: IMarker[]; + /** * Natural language strings that can be localized. */ @@ -290,7 +311,7 @@ declare module 'vscode-xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'data', listener: (data?: string) => void): void; + on(type: 'data', listener: (...args: any[]) => void): void; /** * Registers an event listener. * @param type The type of the event. @@ -308,13 +329,13 @@ declare module 'vscode-xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'refresh', listener: (data?: {start: number, end: number}) => void): void; + on(type: 'refresh', listener: (data?: { start: number, end: number }) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'resize', listener: (data?: {cols: number, rows: number}) => void): void; + on(type: 'resize', listener: (data?: { cols: number, rows: number }) => void): void; /** * Registers an event listener. * @param type The type of the event. @@ -341,6 +362,10 @@ declare module 'vscode-xterm' { */ off(type: 'blur' | 'focus' | 'linefeed' | 'selection' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title' | string, listener: (...args: any[]) => void): void; + emit(type: string, data?: any): void; + + addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; + /** * Resizes the terminal. * @param x The number of columns to resize to. @@ -383,7 +408,7 @@ declare module 'vscode-xterm' { * @param options Options for the link matcher. * @return The ID of the new matcher, this can be used to deregister. */ - registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number; + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number; /** * (EXPERIMENTAL) Deregisters a link matcher if it has been registered. @@ -391,6 +416,13 @@ declare module 'vscode-xterm' { */ deregisterLinkMatcher(matcherId: number): void; + /** + * (EXPERIMENTAL) Adds a marker to the normal buffer and returns it. If the + * alt buffer is active, undefined is returned. + * @param cursorYOffset The y position offset of the marker from the cursor. + */ + addMarker(cursorYOffset: number): IMarker; + /** * Gets whether the terminal has an active selection. */ @@ -412,21 +444,12 @@ declare module 'vscode-xterm' { */ selectAll(): void; - // /** - // * Find the next instance of the term, then scroll to and select it. If it - // * doesn't exist, do nothing. - // * @param term Tne search term. - // * @return Whether a result was found. - // */ - // findNext(term: string): boolean; - - // /** - // * Find the previous instance of the term, then scroll to and select it. If it - // * doesn't exist, do nothing. - // * @param term Tne search term. - // * @return Whether a result was found. - // */ - // findPrevious(term: string): boolean; + /** + * Selects text in the buffer between 2 lines. + * @param start The 0-based line index to select from (inclusive). + * @param end The 0-based line index to select to (inclusive). + */ + selectLines(start: number, end: number): void; /** * Destroys the terminal and detaches it from the DOM. @@ -455,6 +478,12 @@ declare module 'vscode-xterm' { */ scrollToBottom(): void; + /** + * Scrolls to a line within the buffer. + * @param line The 0-based line index to scroll to. + */ + scrollToLine(line: number): void; + /** * Clear the entire buffer, making the prompt line the new first line. */ @@ -470,7 +499,7 @@ declare module 'vscode-xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'termName'): string; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'termName'): string; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -503,6 +532,12 @@ declare module 'vscode-xterm' { * @param value The option value. */ setOption(key: 'fontFamily' | 'termName' | 'bellSound', value: string): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; /** * Sets an option on the terminal. * @param key The option key. @@ -545,6 +580,12 @@ declare module 'vscode-xterm' { * @param value The option value. */ setOption(key: 'theme', value: ITheme): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'cols' | 'rows', value: number): void; /** * Sets an option on the terminal. * @param key The option key. @@ -571,16 +612,17 @@ declare module 'vscode-xterm' { * @param addon The addon to apply. */ static applyAddon(addon: any): void; + } +} - - - // Modifications to official .d.ts below - +// Modifications to official .d.ts below +declare module 'vscode-xterm' { + interface Terminal { buffer: { - /** - * The viewport position. - */ + y: number; + ybase: number; ydisp: number; + x: number; }; /** @@ -606,6 +648,6 @@ declare module 'vscode-xterm' { webLinksInit(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): void; winptyCompatInit(): void; - charMeasure?: { height: number, width: number } + charMeasure?: { height: number, width: number }; } -} \ No newline at end of file +} diff --git a/src/typings/windows-mutex.ts b/src/typings/windows-mutex.d.ts similarity index 99% rename from src/typings/windows-mutex.ts rename to src/typings/windows-mutex.d.ts index 95936a4c5a..86a43c3ce6 100644 --- a/src/typings/windows-mutex.ts +++ b/src/typings/windows-mutex.d.ts @@ -11,4 +11,4 @@ declare module 'windows-mutex' { } export function isActive(name: string): boolean; -} \ No newline at end of file +} diff --git a/src/typings/windows-process-tree.d.ts b/src/typings/windows-process-tree.d.ts index a10a80aeeb..689ddb77d9 100644 --- a/src/typings/windows-process-tree.d.ts +++ b/src/typings/windows-process-tree.d.ts @@ -4,11 +4,60 @@ *--------------------------------------------------------------------------------------------*/ declare module 'windows-process-tree' { - interface ProcessTreeNode { - pid: number, - name: string, - children: ProcessTreeNode[] + export enum ProcessDataFlag { + None = 0, + Memory = 1, + CommandLine = 2 } - function get(rootPid: number, callback: (tree: ProcessTreeNode) => void): void; - export = get; -} \ No newline at end of file + + export interface IProcessInfo { + pid: number; + ppid: number; + name: string; + + /** + * The working set size of the process, in bytes. + */ + memory?: number; + + /** + * The string returned is at most 512 chars, strings exceeding this length are truncated. + */ + commandLine?: string; + } + + export interface IProcessCpuInfo extends IProcessInfo { + cpu?: number; + } + + export interface IProcessTreeNode { + pid: number; + name: string; + memory?: number; + commandLine?: string; + children: IProcessTreeNode[]; + } + + /** + * Returns a tree of processes with the rootPid process as the root. + * @param rootPid - The pid of the process that will be the root of the tree. + * @param callback - The callback to use with the returned list of processes. + * @param flags - The flags for what process data should be included. + */ + export function getProcessTree(rootPid: number, callback: (tree: IProcessTreeNode) => void, flags?: ProcessDataFlag): void; + + /** + * Returns a list of processes containing the rootPid process and all of its descendants. + * @param rootPid - The pid of the process of interest. + * @param callback - The callback to use with the returned set of processes. + * @param flags - The flags for what process data should be included. + */ + export function getProcessList(rootPid: number, callback: (processList: IProcessInfo[]) => void, flags?: ProcessDataFlag): void; + + /** + * Returns the list of processes annotated with cpu usage information. + * @param processList - The list of processes. + * @param callback - The callback to use with the returned list of processes. + */ + export function getProcessCpuUsage(processList: IProcessInfo[], callback: (processListWithCpu: IProcessCpuInfo[]) => void): void; +} diff --git a/src/typings/yauzl.d.ts b/src/typings/yauzl.d.ts index 297449583c..cf8310351a 100644 --- a/src/typings/yauzl.d.ts +++ b/src/typings/yauzl.d.ts @@ -31,6 +31,7 @@ declare module 'yauzl' { } export class ZipFile extends EventEmitter { + readEntry(); openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable) => void); close(); isOpen: boolean; diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 63a46b4954..7215885c8a 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -5,7 +5,7 @@ 'use strict'; import * as Platform from 'vs/base/common/platform'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; class WindowManager { @@ -15,9 +15,9 @@ class WindowManager { // --- Zoom Level private _zoomLevel: number = 0; private _lastZoomLevelChangeTime: number = 0; - private _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>(); + private readonly _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>(); - public onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event; + public readonly onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event; public getZoomLevel(): number { return this._zoomLevel; } @@ -61,9 +61,9 @@ class WindowManager { // --- Fullscreen private _fullscreen: boolean; - private _onDidChangeFullscreen: Emitter<void> = new Emitter<void>(); + private readonly _onDidChangeFullscreen: Emitter<void> = new Emitter<void>(); - public onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event; + public readonly onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event; public setFullscreen(fullscreen: boolean): void { if (this._fullscreen === fullscreen) { return; @@ -78,9 +78,9 @@ class WindowManager { // --- Accessibility private _accessibilitySupport = Platform.AccessibilitySupport.Unknown; - private _onDidChangeAccessibilitySupport: Emitter<void> = new Emitter<void>(); + private readonly _onDidChangeAccessibilitySupport: Emitter<void> = new Emitter<void>(); - public onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event; + public readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event; public setAccessibilitySupport(accessibilitySupport: Platform.AccessibilitySupport): void { if (this._accessibilitySupport === accessibilitySupport) { return; @@ -155,6 +155,7 @@ export const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0); export const isChrome = (userAgent.indexOf('Chrome') >= 0); export const isSafari = (userAgent.indexOf('Chrome') === -1) && (userAgent.indexOf('Safari') >= 0); export const isIPad = (userAgent.indexOf('iPad') >= 0); +export const isEdgeWebView = isEdge && (userAgent.indexOf('WebView/') >= 0); export const isChromev56 = ( userAgent.indexOf('Chrome/56.') >= 0 diff --git a/src/vs/base/browser/builder.css b/src/vs/base/browser/builder.css index 889bc71c06..650e676272 100644 --- a/src/vs/base/browser/builder.css +++ b/src/vs/base/browser/builder.css @@ -3,12 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.builder-hidden { +.monaco-builder-hidden { display: none !important; - visibility: hidden !important; -} - -.builder-visible { - display: inherit; - visibility: visible; -} +} \ No newline at end of file diff --git a/src/vs/base/browser/builder.ts b/src/vs/base/browser/builder.ts index 8fecaf8ad4..d58c74d905 100644 --- a/src/vs/base/browser/builder.ts +++ b/src/vs/base/browser/builder.ts @@ -6,11 +6,11 @@ import 'vs/css!./builder'; import { TPromise } from 'vs/base/common/winjs.base'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import strings = require('vs/base/common/strings'); -import assert = require('vs/base/common/assert'); -import DOM = require('vs/base/browser/dom'); +import * as strings from 'vs/base/common/strings'; +import * as assert from 'vs/base/common/assert'; +import * as DOM from 'vs/base/browser/dom'; /** * Welcome to the monaco builder. The recommended way to use it is: @@ -43,26 +43,6 @@ export interface QuickBuilder { (builder: Builder): Builder; } -/** - * Create a new builder from the element that is uniquely identified by the given identifier. If the - * second parameter "offdom" is set to true, the created elements will only be added to the provided - * element when the build() method is called. - */ -export function withElementById(id: string, offdom?: boolean): Builder { - assert.ok(types.isString(id), 'Expected String as parameter'); - - let element = document.getElementById(id); - if (element) { - return new Builder(element, offdom); - } - - return null; -} - -export const Build = { - withElementById: withElementById -}; - // --- Implementation starts here let MS_DATA_KEY = '_msDataKey'; @@ -70,16 +50,6 @@ let DATA_BINDING_ID = '__$binding'; let LISTENER_BINDING_ID = '__$listeners'; let VISIBILITY_BINDING_ID = '__$visibility'; -export class Dimension { - public width: number; - public height: number; - - constructor(width: number, height: number) { - this.width = width; - this.height = height; - } -} - function data(element: any): any { if (!element[MS_DATA_KEY]) { element[MS_DATA_KEY] = {}; @@ -927,50 +897,6 @@ export class Builder implements IDisposable { return this; } - /** - * Sets the CSS property min-size. - */ - public minSize(size: string): Builder; - public minSize(width: number, height?: number): Builder; - public minSize(width: string, height?: string): Builder; - public minSize(width: any, height?: any): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.minSize.apply(this, width.split(' ')); - } - - if (!types.isUndefinedOrNull(width)) { - this.currentElement.style.minWidth = this.toPixel(width); - } - - if (!types.isUndefinedOrNull(height)) { - this.currentElement.style.minHeight = this.toPixel(height); - } - - return this; - } - - /** - * Sets the CSS property max-size. - */ - public maxSize(size: string): Builder; - public maxSize(width: number, height?: number): Builder; - public maxSize(width: string, height?: string): Builder; - public maxSize(width: any, height?: any): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.maxSize.apply(this, width.split(' ')); - } - - if (!types.isUndefinedOrNull(width)) { - this.currentElement.style.maxWidth = this.toPixel(width); - } - - if (!types.isUndefinedOrNull(height)) { - this.currentElement.style.maxHeight = this.toPixel(height); - } - - return this; - } - /** * Sets the CSS property display. */ @@ -984,8 +910,8 @@ export class Builder implements IDisposable { * Shows the current element of the builder. */ public show(): Builder { - if (this.hasClass('builder-hidden')) { - this.removeClass('builder-hidden'); + if (this.hasClass('monaco-builder-hidden')) { + this.removeClass('monaco-builder-hidden'); } this.attr('aria-hidden', 'false'); @@ -1023,8 +949,8 @@ export class Builder implements IDisposable { * Hides the current element of the builder. */ public hide(): Builder { - if (!this.hasClass('builder-hidden')) { - this.addClass('builder-hidden'); + if (!this.hasClass('monaco-builder-hidden')) { + this.addClass('monaco-builder-hidden'); } this.attr('aria-hidden', 'true'); @@ -1038,7 +964,7 @@ export class Builder implements IDisposable { * Returns true if the current element of the builder is hidden. */ public isHidden(): boolean { - return this.hasClass('builder-hidden') || this.currentElement.style.display === 'none'; + return this.hasClass('monaco-builder-hidden') || this.currentElement.style.display === 'none'; } private cancelVisibilityPromise(): void { @@ -1049,121 +975,6 @@ export class Builder implements IDisposable { } } - /** - * Sets the CSS property border. - */ - public border(border: string): Builder; - public border(width: number, style?: string, color?: string): Builder; - public border(width: any, style?: string, color?: string): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.border.apply(this, width.split(' ')); - } - - this.currentElement.style.borderWidth = this.toPixel(width); - - if (color) { - this.currentElement.style.borderColor = color; - } - - if (style) { - this.currentElement.style.borderStyle = style; - } - - return this; - } - - /** - * Sets the CSS property border-top. - */ - public borderTop(border: string): Builder; - public borderTop(width: number, style: string, color: string): Builder; - public borderTop(width: any, style?: string, color?: string): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.borderTop.apply(this, width.split(' ')); - } - - this.currentElement.style.borderTopWidth = this.toPixel(width); - - if (color) { - this.currentElement.style.borderTopColor = color; - } - - if (style) { - this.currentElement.style.borderTopStyle = style; - } - - return this; - } - - /** - * Sets the CSS property border-bottom. - */ - public borderBottom(border: string): Builder; - public borderBottom(width: number, style: string, color: string): Builder; - public borderBottom(width: any, style?: string, color?: string): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.borderBottom.apply(this, width.split(' ')); - } - - this.currentElement.style.borderBottomWidth = this.toPixel(width); - - if (color) { - this.currentElement.style.borderBottomColor = color; - } - - if (style) { - this.currentElement.style.borderBottomStyle = style; - } - - return this; - } - - /** - * Sets the CSS property border-left. - */ - public borderLeft(border: string): Builder; - public borderLeft(width: number, style: string, color: string): Builder; - public borderLeft(width: any, style?: string, color?: string): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.borderLeft.apply(this, width.split(' ')); - } - - this.currentElement.style.borderLeftWidth = this.toPixel(width); - - if (color) { - this.currentElement.style.borderLeftColor = color; - } - - if (style) { - this.currentElement.style.borderLeftStyle = style; - } - - return this; - } - - /** - * Sets the CSS property border-right. - */ - public borderRight(border: string): Builder; - public borderRight(width: number, style: string, color: string): Builder; - public borderRight(width: any, style?: string, color?: string): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.borderRight.apply(this, width.split(' ')); - } - - this.currentElement.style.borderRightWidth = this.toPixel(width); - - if (color) { - this.currentElement.style.borderRightColor = color; - } - - if (style) { - this.currentElement.style.borderRightStyle = style; - } - - return this; - } - private toPixel(obj: any): string { if (obj.toString().indexOf('px') === -1) { return obj.toString() + 'px'; @@ -1375,39 +1186,18 @@ export class Builder implements IDisposable { /** * Gets the size (in pixels) of an element, including the margin. */ - public getTotalSize(): Dimension { + public getTotalSize(): DOM.Dimension { let totalWidth = DOM.getTotalWidth(this.currentElement); let totalHeight = DOM.getTotalHeight(this.currentElement); - return new Dimension(totalWidth, totalHeight); + return new DOM.Dimension(totalWidth, totalHeight); } /** * Another variant of getting the inner dimensions of an element. */ - public getClientArea(): Dimension { - - // 0.) Try with DOM clientWidth / clientHeight - if (this.currentElement !== document.body) { - return new Dimension(this.currentElement.clientWidth, this.currentElement.clientHeight); - } - - // 1.) Try innerWidth / innerHeight - if (window.innerWidth && window.innerHeight) { - return new Dimension(window.innerWidth, window.innerHeight); - } - - // 2.) Try with document.body.clientWidth / document.body.clientHeigh - if (document.body && document.body.clientWidth && document.body.clientWidth) { - return new Dimension(document.body.clientWidth, document.body.clientHeight); - } - - // 3.) Try with document.documentElement.clientWidth / document.documentElement.clientHeight - if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientHeight) { - return new Dimension(document.documentElement.clientWidth, document.documentElement.clientHeight); - } - - throw new Error('Unable to figure out browser width and height'); + public getClientArea(): DOM.Dimension { + return DOM.getClientArea(this.currentElement); } } @@ -1653,7 +1443,3 @@ export const $: QuickBuilder = function (arg?: any): Builder { throw new Error('Bad use of $'); } }; - -(<any>$).Dimension = Dimension; -(<any>$).Builder = Builder; -(<any>$).Build = Build; diff --git a/src/vs/base/browser/dnd.ts b/src/vs/base/browser/dnd.ts index 6bf816a3b5..73f0f36a77 100644 --- a/src/vs/base/browser/dnd.ts +++ b/src/vs/base/browser/dnd.ts @@ -5,18 +5,19 @@ 'use strict'; -import { $ } from 'vs/base/browser/builder'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { addDisposableListener } from 'vs/base/browser/dom'; /** * A helper that will execute a provided function when the provided HTMLElement receives * dragover event for 800ms. If the drag is aborted before, the callback will not be triggered. */ export class DelayedDragHandler { - + private toDispose: IDisposable[] = []; private timeout: number; constructor(container: HTMLElement, callback: () => void) { - $(container).on('dragover', () => { + this.toDispose.push(addDisposableListener(container, 'dragover', () => { if (!this.timeout) { this.timeout = setTimeout(() => { callback(); @@ -24,9 +25,13 @@ export class DelayedDragHandler { this.timeout = null; }, 800); } - }); + })); - $(container).on(['dragleave', 'drop', 'dragend'], () => this.clearDragTimeout()); + ['dragleave', 'drop', 'dragend'].forEach(type => { + this.toDispose.push(addDisposableListener(container, type, () => { + this.clearDragTimeout(); + })); + }); } private clearDragTimeout(): void { @@ -37,6 +42,7 @@ export class DelayedDragHandler { } public dispose(): void { + this.toDispose = dispose(this.toDispose); this.clearDragTimeout(); } } diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index c7318cbae5..bc41b74fce 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -13,7 +13,7 @@ import * as browser from 'vs/base/browser/browser'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { CharCode } from 'vs/base/common/charCode'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; export function clearNode(node: HTMLElement) { @@ -35,7 +35,9 @@ export function isInDOM(node: Node): boolean { interface IDomClassList { hasClass(node: HTMLElement, className: string): boolean; addClass(node: HTMLElement, className: string): void; + addClasses(node: HTMLElement, ...classNames: string[]): void; removeClass(node: HTMLElement, className: string): void; + removeClasses(node: HTMLElement, ...classNames: string[]): void; toggleClass(node: HTMLElement, className: string, shouldHaveIt?: boolean): void; } @@ -110,6 +112,10 @@ const _manualClassList = new class implements IDomClassList { return this._lastStart !== -1; } + addClasses(node: HTMLElement, ...classNames: string[]): void { + classNames.forEach(nameValue => nameValue.split(' ').forEach(name => this.addClass(node, name))); + } + addClass(node: HTMLElement, className: string): void { if (!node.className) { // doesn't have it for sure node.className = className; @@ -130,6 +136,10 @@ const _manualClassList = new class implements IDomClassList { } } + removeClasses(node: HTMLElement, ...classNames: string[]): void { + classNames.forEach(nameValue => nameValue.split(' ').forEach(name => this.removeClass(node, name))); + } + toggleClass(node: HTMLElement, className: string, shouldHaveIt?: boolean): void { this._findClassName(node, className); if (this._lastStart !== -1 && (shouldHaveIt === void 0 || !shouldHaveIt)) { @@ -146,6 +156,10 @@ const _nativeClassList = new class implements IDomClassList { return className && node.classList && node.classList.contains(className); } + addClasses(node: HTMLElement, ...classNames: string[]): void { + classNames.forEach(nameValue => nameValue.split(' ').forEach(name => this.addClass(node, name))); + } + addClass(node: HTMLElement, className: string): void { if (className && node.classList) { node.classList.add(className); @@ -158,6 +172,10 @@ const _nativeClassList = new class implements IDomClassList { } } + removeClasses(node: HTMLElement, ...classNames: string[]): void { + classNames.forEach(nameValue => nameValue.split(' ').forEach(name => this.removeClass(node, name))); + } + toggleClass(node: HTMLElement, className: string, shouldHaveIt?: boolean): void { if (node.classList) { node.classList.toggle(className, shouldHaveIt); @@ -170,7 +188,9 @@ const _nativeClassList = new class implements IDomClassList { const _classList: IDomClassList = browser.isIE ? _manualClassList : _nativeClassList; export const hasClass: (node: HTMLElement, className: string) => boolean = _classList.hasClass.bind(_classList); export const addClass: (node: HTMLElement, className: string) => void = _classList.addClass.bind(_classList); +export const addClasses: (node: HTMLElement, ...classNames: string[]) => void = _classList.addClasses.bind(_classList); export const removeClass: (node: HTMLElement, className: string) => void = _classList.removeClass.bind(_classList); +export const removeClasses: (node: HTMLElement, ...classNames: string[]) => void = _classList.removeClasses.bind(_classList); export const toggleClass: (node: HTMLElement, className: string, shouldHaveIt?: boolean) => void = _classList.toggleClass.bind(_classList); class DomListener implements IDisposable { @@ -269,7 +289,7 @@ function doRequestAnimationFrame(callback: (time: number) => void): number { || emulatedRequestAnimationFrame ); } - return _animationFrame(callback); + return _animationFrame.call(self, callback); } /** @@ -454,11 +474,39 @@ function getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyN return convertToPixels(element, value); } +export function getClientArea(element: HTMLElement): Dimension { + + // Try with DOM clientWidth / clientHeight + if (element !== document.body) { + return new Dimension(element.clientWidth, element.clientHeight); + } + + // Try innerWidth / innerHeight + if (window.innerWidth && window.innerHeight) { + return new Dimension(window.innerWidth, window.innerHeight); + } + + // Try with document.body.clientWidth / document.body.clientHeigh + if (document.body && document.body.clientWidth && document.body.clientWidth) { + return new Dimension(document.body.clientWidth, document.body.clientHeight); + } + + // Try with document.documentElement.clientWidth / document.documentElement.clientHeight + if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientHeight) { + return new Dimension(document.documentElement.clientWidth, document.documentElement.clientHeight); + } + + throw new Error('Unable to figure out browser width and height'); +} + const sizeUtils = { getBorderLeftWidth: function (element: HTMLElement): number { return getDimension(element, 'border-left-width', 'borderLeftWidth'); }, + getBorderRightWidth: function (element: HTMLElement): number { + return getDimension(element, 'border-right-width', 'borderRightWidth'); + }, getBorderTopWidth: function (element: HTMLElement): number { return getDimension(element, 'border-top-width', 'borderTopWidth'); }, @@ -466,6 +514,12 @@ const sizeUtils = { return getDimension(element, 'border-bottom-width', 'borderBottomWidth'); }, + getPaddingLeft: function (element: HTMLElement): number { + return getDimension(element, 'padding-left', 'paddingLeft'); + }, + getPaddingRight: function (element: HTMLElement): number { + return getDimension(element, 'padding-right', 'paddingRight'); + }, getPaddingTop: function (element: HTMLElement): number { return getDimension(element, 'padding-top', 'paddingTop'); }, @@ -486,25 +540,22 @@ const sizeUtils = { return getDimension(element, 'margin-bottom', 'marginBottom'); }, - - // {{SQL CARBON EDIT}} - getPaddingLeft: function (element: HTMLElement): number { - return getDimension(element, 'padding-left', 'paddingLeft'); - }, - getPaddingRight: function (element: HTMLElement): number { - return getDimension(element, 'padding-right', 'paddingRight'); - }, - getBorderRightWidth: function (element: HTMLElement): number { - return getDimension(element, 'border-right-width', 'borderRightWidth'); - }, - - __commaSentinel: false }; // ---------------------------------------------------------------------------------------- // Position & Dimension +export class Dimension { + public width: number; + public height: number; + + constructor(width: number, height: number) { + this.width = width; + this.height = height; + } +} + export function getTopLeftOffset(element: HTMLElement): { left: number; top: number; } { // Adapted from WinJS.Utilities.getPosition // and added borders to the mix @@ -540,6 +591,36 @@ export interface IDomNodePagePosition { height: number; } +export function size(element: HTMLElement, width: number, height: number): void { + if (typeof width === 'number') { + element.style.width = `${width}px`; + } + + if (typeof height === 'number') { + element.style.height = `${height}px`; + } +} + +export function position(element: HTMLElement, top: number, right?: number, bottom?: number, left?: number, position: string = 'absolute'): void { + if (typeof top === 'number') { + element.style.top = `${top}px`; + } + + if (typeof right === 'number') { + element.style.right = `${right}px`; + } + + if (typeof bottom === 'number') { + element.style.bottom = `${bottom}px`; + } + + if (typeof left === 'number') { + element.style.left = `${left}px`; + } + + element.style.position = position; +} + /** * Returns the position of a dom node relative to the entire page. */ @@ -585,6 +666,12 @@ export function getTotalWidth(element: HTMLElement): number { return element.offsetWidth + margin; } +export function getContentWidth(element: HTMLElement): number { + let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element); + let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element); + return element.offsetWidth - border - padding; +} + export function getTotalScrollWidth(element: HTMLElement): number { let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element); return element.scrollWidth + margin; @@ -598,16 +685,6 @@ export function getContentHeight(element: HTMLElement): number { return element.offsetHeight - border - padding; } -// {{SQL CARBON EDIT}} -// Adapted from WinJS -// Gets the width of the content of the specified element. The content width does not include borders or padding. -export function getContentWidth(element: HTMLElement): number { - let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element); - let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element); - return element.offsetWidth - border - padding; -} - - // Adapted from WinJS // Gets the height of the element, including its margins. export function getTotalHeight(element: HTMLElement): number { @@ -948,12 +1025,14 @@ export function join(nodes: Node[], separator: Node | string): Node[] { export function show(...elements: HTMLElement[]): void { for (let element of elements) { element.style.display = ''; + element.removeAttribute('aria-hidden'); } } export function hide(...elements: HTMLElement[]): void { for (let element of elements) { element.style.display = 'none'; + element.setAttribute('aria-hidden', 'true'); } } @@ -1004,7 +1083,7 @@ export function domContentLoaded(): TPromise<any> { return new TPromise<any>((c, e) => { const readyState = document.readyState; if (readyState === 'complete' || (document && document.body !== null)) { - window.setImmediate(c); + platform.setImmediate(c); } else { window.addEventListener('DOMContentLoaded', c, false); } @@ -1032,13 +1111,14 @@ export function computeScreenAwareSize(cssPx: number): number { * See https://mathiasbynens.github.io/rel-noopener/ */ export function windowOpenNoOpener(url: string): void { - if (platform.isNative) { + if (platform.isNative || browser.isEdgeWebView) { // In VSCode, window.open() always returns null... + // The same is true for a WebView (see https://github.com/Microsoft/monaco-editor/issues/628) window.open(url); } else { let newTab = window.open(); if (newTab) { - newTab.opener = null; + (newTab as any).opener = null; newTab.location.href = url; } } diff --git a/src/vs/base/browser/event.ts b/src/vs/base/browser/event.ts index ac4f0e9a31..f8507db827 100644 --- a/src/vs/base/browser/event.ts +++ b/src/vs/base/browser/event.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import _Event, { Emitter, mapEvent } from 'vs/base/common/event'; +import { Event as _Event, Emitter, mapEvent } from 'vs/base/common/event'; export type EventHandler = HTMLElement | HTMLDocument | Window; @@ -19,7 +19,6 @@ export interface IDomEvent { (element: EventHandler, type: 'MSGotPointerCapture', useCapture?: boolean): _Event<MSPointerEvent>; (element: EventHandler, type: 'MSInertiaStart', useCapture?: boolean): _Event<MSGestureEvent>; (element: EventHandler, type: 'MSLostPointerCapture', useCapture?: boolean): _Event<MSPointerEvent>; - (element: EventHandler, type: 'MSManipulationStateChanged', useCapture?: boolean): _Event<MSManipulationEvent>; (element: EventHandler, type: 'MSPointerCancel', useCapture?: boolean): _Event<MSPointerEvent>; (element: EventHandler, type: 'MSPointerDown', useCapture?: boolean): _Event<MSPointerEvent>; (element: EventHandler, type: 'MSPointerEnter', useCapture?: boolean): _Event<MSPointerEvent>; diff --git a/src/vs/base/browser/keyboardEvent.ts b/src/vs/base/browser/keyboardEvent.ts index c12d8ac0eb..91331bbaea 100644 --- a/src/vs/base/browser/keyboardEvent.ts +++ b/src/vs/base/browser/keyboardEvent.ts @@ -9,149 +9,160 @@ import { KeyCode, KeyCodeUtils, KeyMod, SimpleKeybinding } from 'vs/base/common/ import * as platform from 'vs/base/common/platform'; import * as browser from 'vs/base/browser/browser'; -let KEY_CODE_MAP: { [keyCode: number]: KeyCode } = {}; +let KEY_CODE_MAP: { [keyCode: number]: KeyCode } = new Array(230); +let INVERSE_KEY_CODE_MAP: KeyCode[] = new Array(KeyCode.MAX_VALUE); + (function () { - KEY_CODE_MAP[3] = KeyCode.PauseBreak; // VK_CANCEL 0x03 Control-break processing - KEY_CODE_MAP[8] = KeyCode.Backspace; - KEY_CODE_MAP[9] = KeyCode.Tab; - KEY_CODE_MAP[13] = KeyCode.Enter; - KEY_CODE_MAP[16] = KeyCode.Shift; - KEY_CODE_MAP[17] = KeyCode.Ctrl; - KEY_CODE_MAP[18] = KeyCode.Alt; - KEY_CODE_MAP[19] = KeyCode.PauseBreak; - KEY_CODE_MAP[20] = KeyCode.CapsLock; - KEY_CODE_MAP[27] = KeyCode.Escape; - KEY_CODE_MAP[32] = KeyCode.Space; - KEY_CODE_MAP[33] = KeyCode.PageUp; - KEY_CODE_MAP[34] = KeyCode.PageDown; - KEY_CODE_MAP[35] = KeyCode.End; - KEY_CODE_MAP[36] = KeyCode.Home; - KEY_CODE_MAP[37] = KeyCode.LeftArrow; - KEY_CODE_MAP[38] = KeyCode.UpArrow; - KEY_CODE_MAP[39] = KeyCode.RightArrow; - KEY_CODE_MAP[40] = KeyCode.DownArrow; - KEY_CODE_MAP[45] = KeyCode.Insert; - KEY_CODE_MAP[46] = KeyCode.Delete; + for (let i = 0; i < INVERSE_KEY_CODE_MAP.length; i++) { + INVERSE_KEY_CODE_MAP[i] = -1; + } - KEY_CODE_MAP[48] = KeyCode.KEY_0; - KEY_CODE_MAP[49] = KeyCode.KEY_1; - KEY_CODE_MAP[50] = KeyCode.KEY_2; - KEY_CODE_MAP[51] = KeyCode.KEY_3; - KEY_CODE_MAP[52] = KeyCode.KEY_4; - KEY_CODE_MAP[53] = KeyCode.KEY_5; - KEY_CODE_MAP[54] = KeyCode.KEY_6; - KEY_CODE_MAP[55] = KeyCode.KEY_7; - KEY_CODE_MAP[56] = KeyCode.KEY_8; - KEY_CODE_MAP[57] = KeyCode.KEY_9; + function define(code: number, keyCode: KeyCode): void { + KEY_CODE_MAP[code] = keyCode; + INVERSE_KEY_CODE_MAP[keyCode] = code; + } - KEY_CODE_MAP[65] = KeyCode.KEY_A; - KEY_CODE_MAP[66] = KeyCode.KEY_B; - KEY_CODE_MAP[67] = KeyCode.KEY_C; - KEY_CODE_MAP[68] = KeyCode.KEY_D; - KEY_CODE_MAP[69] = KeyCode.KEY_E; - KEY_CODE_MAP[70] = KeyCode.KEY_F; - KEY_CODE_MAP[71] = KeyCode.KEY_G; - KEY_CODE_MAP[72] = KeyCode.KEY_H; - KEY_CODE_MAP[73] = KeyCode.KEY_I; - KEY_CODE_MAP[74] = KeyCode.KEY_J; - KEY_CODE_MAP[75] = KeyCode.KEY_K; - KEY_CODE_MAP[76] = KeyCode.KEY_L; - KEY_CODE_MAP[77] = KeyCode.KEY_M; - KEY_CODE_MAP[78] = KeyCode.KEY_N; - KEY_CODE_MAP[79] = KeyCode.KEY_O; - KEY_CODE_MAP[80] = KeyCode.KEY_P; - KEY_CODE_MAP[81] = KeyCode.KEY_Q; - KEY_CODE_MAP[82] = KeyCode.KEY_R; - KEY_CODE_MAP[83] = KeyCode.KEY_S; - KEY_CODE_MAP[84] = KeyCode.KEY_T; - KEY_CODE_MAP[85] = KeyCode.KEY_U; - KEY_CODE_MAP[86] = KeyCode.KEY_V; - KEY_CODE_MAP[87] = KeyCode.KEY_W; - KEY_CODE_MAP[88] = KeyCode.KEY_X; - KEY_CODE_MAP[89] = KeyCode.KEY_Y; - KEY_CODE_MAP[90] = KeyCode.KEY_Z; + define(3, KeyCode.PauseBreak); // VK_CANCEL 0x03 Control-break processing + define(8, KeyCode.Backspace); + define(9, KeyCode.Tab); + define(13, KeyCode.Enter); + define(16, KeyCode.Shift); + define(17, KeyCode.Ctrl); + define(18, KeyCode.Alt); + define(19, KeyCode.PauseBreak); + define(20, KeyCode.CapsLock); + define(27, KeyCode.Escape); + define(32, KeyCode.Space); + define(33, KeyCode.PageUp); + define(34, KeyCode.PageDown); + define(35, KeyCode.End); + define(36, KeyCode.Home); + define(37, KeyCode.LeftArrow); + define(38, KeyCode.UpArrow); + define(39, KeyCode.RightArrow); + define(40, KeyCode.DownArrow); + define(45, KeyCode.Insert); + define(46, KeyCode.Delete); - KEY_CODE_MAP[93] = KeyCode.ContextMenu; + define(48, KeyCode.KEY_0); + define(49, KeyCode.KEY_1); + define(50, KeyCode.KEY_2); + define(51, KeyCode.KEY_3); + define(52, KeyCode.KEY_4); + define(53, KeyCode.KEY_5); + define(54, KeyCode.KEY_6); + define(55, KeyCode.KEY_7); + define(56, KeyCode.KEY_8); + define(57, KeyCode.KEY_9); - KEY_CODE_MAP[96] = KeyCode.NUMPAD_0; - KEY_CODE_MAP[97] = KeyCode.NUMPAD_1; - KEY_CODE_MAP[98] = KeyCode.NUMPAD_2; - KEY_CODE_MAP[99] = KeyCode.NUMPAD_3; - KEY_CODE_MAP[100] = KeyCode.NUMPAD_4; - KEY_CODE_MAP[101] = KeyCode.NUMPAD_5; - KEY_CODE_MAP[102] = KeyCode.NUMPAD_6; - KEY_CODE_MAP[103] = KeyCode.NUMPAD_7; - KEY_CODE_MAP[104] = KeyCode.NUMPAD_8; - KEY_CODE_MAP[105] = KeyCode.NUMPAD_9; - KEY_CODE_MAP[106] = KeyCode.NUMPAD_MULTIPLY; - KEY_CODE_MAP[107] = KeyCode.NUMPAD_ADD; - KEY_CODE_MAP[108] = KeyCode.NUMPAD_SEPARATOR; - KEY_CODE_MAP[109] = KeyCode.NUMPAD_SUBTRACT; - KEY_CODE_MAP[110] = KeyCode.NUMPAD_DECIMAL; - KEY_CODE_MAP[111] = KeyCode.NUMPAD_DIVIDE; + define(65, KeyCode.KEY_A); + define(66, KeyCode.KEY_B); + define(67, KeyCode.KEY_C); + define(68, KeyCode.KEY_D); + define(69, KeyCode.KEY_E); + define(70, KeyCode.KEY_F); + define(71, KeyCode.KEY_G); + define(72, KeyCode.KEY_H); + define(73, KeyCode.KEY_I); + define(74, KeyCode.KEY_J); + define(75, KeyCode.KEY_K); + define(76, KeyCode.KEY_L); + define(77, KeyCode.KEY_M); + define(78, KeyCode.KEY_N); + define(79, KeyCode.KEY_O); + define(80, KeyCode.KEY_P); + define(81, KeyCode.KEY_Q); + define(82, KeyCode.KEY_R); + define(83, KeyCode.KEY_S); + define(84, KeyCode.KEY_T); + define(85, KeyCode.KEY_U); + define(86, KeyCode.KEY_V); + define(87, KeyCode.KEY_W); + define(88, KeyCode.KEY_X); + define(89, KeyCode.KEY_Y); + define(90, KeyCode.KEY_Z); - KEY_CODE_MAP[112] = KeyCode.F1; - KEY_CODE_MAP[113] = KeyCode.F2; - KEY_CODE_MAP[114] = KeyCode.F3; - KEY_CODE_MAP[115] = KeyCode.F4; - KEY_CODE_MAP[116] = KeyCode.F5; - KEY_CODE_MAP[117] = KeyCode.F6; - KEY_CODE_MAP[118] = KeyCode.F7; - KEY_CODE_MAP[119] = KeyCode.F8; - KEY_CODE_MAP[120] = KeyCode.F9; - KEY_CODE_MAP[121] = KeyCode.F10; - KEY_CODE_MAP[122] = KeyCode.F11; - KEY_CODE_MAP[123] = KeyCode.F12; - KEY_CODE_MAP[124] = KeyCode.F13; - KEY_CODE_MAP[125] = KeyCode.F14; - KEY_CODE_MAP[126] = KeyCode.F15; - KEY_CODE_MAP[127] = KeyCode.F16; - KEY_CODE_MAP[128] = KeyCode.F17; - KEY_CODE_MAP[129] = KeyCode.F18; - KEY_CODE_MAP[130] = KeyCode.F19; + define(93, KeyCode.ContextMenu); - KEY_CODE_MAP[144] = KeyCode.NumLock; - KEY_CODE_MAP[145] = KeyCode.ScrollLock; + define(96, KeyCode.NUMPAD_0); + define(97, KeyCode.NUMPAD_1); + define(98, KeyCode.NUMPAD_2); + define(99, KeyCode.NUMPAD_3); + define(100, KeyCode.NUMPAD_4); + define(101, KeyCode.NUMPAD_5); + define(102, KeyCode.NUMPAD_6); + define(103, KeyCode.NUMPAD_7); + define(104, KeyCode.NUMPAD_8); + define(105, KeyCode.NUMPAD_9); + define(106, KeyCode.NUMPAD_MULTIPLY); + define(107, KeyCode.NUMPAD_ADD); + define(108, KeyCode.NUMPAD_SEPARATOR); + define(109, KeyCode.NUMPAD_SUBTRACT); + define(110, KeyCode.NUMPAD_DECIMAL); + define(111, KeyCode.NUMPAD_DIVIDE); - KEY_CODE_MAP[186] = KeyCode.US_SEMICOLON; - KEY_CODE_MAP[187] = KeyCode.US_EQUAL; - KEY_CODE_MAP[188] = KeyCode.US_COMMA; - KEY_CODE_MAP[189] = KeyCode.US_MINUS; - KEY_CODE_MAP[190] = KeyCode.US_DOT; - KEY_CODE_MAP[191] = KeyCode.US_SLASH; - KEY_CODE_MAP[192] = KeyCode.US_BACKTICK; - KEY_CODE_MAP[193] = KeyCode.ABNT_C1; - KEY_CODE_MAP[194] = KeyCode.ABNT_C2; - KEY_CODE_MAP[219] = KeyCode.US_OPEN_SQUARE_BRACKET; - KEY_CODE_MAP[220] = KeyCode.US_BACKSLASH; - KEY_CODE_MAP[221] = KeyCode.US_CLOSE_SQUARE_BRACKET; - KEY_CODE_MAP[222] = KeyCode.US_QUOTE; - KEY_CODE_MAP[223] = KeyCode.OEM_8; + define(112, KeyCode.F1); + define(113, KeyCode.F2); + define(114, KeyCode.F3); + define(115, KeyCode.F4); + define(116, KeyCode.F5); + define(117, KeyCode.F6); + define(118, KeyCode.F7); + define(119, KeyCode.F8); + define(120, KeyCode.F9); + define(121, KeyCode.F10); + define(122, KeyCode.F11); + define(123, KeyCode.F12); + define(124, KeyCode.F13); + define(125, KeyCode.F14); + define(126, KeyCode.F15); + define(127, KeyCode.F16); + define(128, KeyCode.F17); + define(129, KeyCode.F18); + define(130, KeyCode.F19); - KEY_CODE_MAP[226] = KeyCode.OEM_102; + define(144, KeyCode.NumLock); + define(145, KeyCode.ScrollLock); + + define(186, KeyCode.US_SEMICOLON); + define(187, KeyCode.US_EQUAL); + define(188, KeyCode.US_COMMA); + define(189, KeyCode.US_MINUS); + define(190, KeyCode.US_DOT); + define(191, KeyCode.US_SLASH); + define(192, KeyCode.US_BACKTICK); + define(193, KeyCode.ABNT_C1); + define(194, KeyCode.ABNT_C2); + define(219, KeyCode.US_OPEN_SQUARE_BRACKET); + define(220, KeyCode.US_BACKSLASH); + define(221, KeyCode.US_CLOSE_SQUARE_BRACKET); + define(222, KeyCode.US_QUOTE); + define(223, KeyCode.OEM_8); + + define(226, KeyCode.OEM_102); /** * https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html * If an Input Method Editor is processing key input and the event is keydown, return 229. */ - KEY_CODE_MAP[229] = KeyCode.KEY_IN_COMPOSITION; + define(229, KeyCode.KEY_IN_COMPOSITION); if (browser.isIE) { - KEY_CODE_MAP[91] = KeyCode.Meta; + define(91, KeyCode.Meta); } else if (browser.isFirefox) { - KEY_CODE_MAP[59] = KeyCode.US_SEMICOLON; - KEY_CODE_MAP[107] = KeyCode.US_EQUAL; - KEY_CODE_MAP[109] = KeyCode.US_MINUS; + define(59, KeyCode.US_SEMICOLON); + define(107, KeyCode.US_EQUAL); + define(109, KeyCode.US_MINUS); if (platform.isMacintosh) { - KEY_CODE_MAP[224] = KeyCode.Meta; + define(224, KeyCode.Meta); } } else if (browser.isWebKit) { - KEY_CODE_MAP[91] = KeyCode.Meta; + define(91, KeyCode.Meta); if (platform.isMacintosh) { // the two meta keys in the Mac have different key codes (91 and 93) - KEY_CODE_MAP[93] = KeyCode.Meta; + define(93, KeyCode.Meta); } else { - KEY_CODE_MAP[92] = KeyCode.Meta; + define(92, KeyCode.Meta); } } })(); @@ -165,6 +176,10 @@ function extractKeyCode(e: KeyboardEvent): KeyCode { return KEY_CODE_MAP[e.keyCode] || KeyCode.Unknown; } +export function getCodeForKeyCode(keyCode: KeyCode): number { + return INVERSE_KEY_CODE_MAP[keyCode]; +} + export interface IKeyboardEvent { readonly browserEvent: KeyboardEvent; readonly target: HTMLElement; diff --git a/src/vs/base/browser/touch.ts b/src/vs/base/browser/touch.ts index 7d1a03d07f..e736cd459f 100644 --- a/src/vs/base/browser/touch.ts +++ b/src/vs/base/browser/touch.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import arrays = require('vs/base/common/arrays'); +import * as arrays from 'vs/base/common/arrays'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import DomUtils = require('vs/base/browser/dom'); +import * as DomUtils from 'vs/base/browser/dom'; import { memoize } from 'vs/base/common/decorators'; export namespace EventType { diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index c4b95b364c..fa77684556 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -6,19 +6,20 @@ 'use strict'; import 'vs/css!./actionbar'; -import nls = require('vs/nls'); -import lifecycle = require('vs/base/common/lifecycle'); +import * as platform from 'vs/base/common/platform'; +import * as nls from 'vs/nls'; +import * as lifecycle from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import { Builder, $ } from 'vs/base/browser/builder'; import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox'; import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, IRunEvent } from 'vs/base/common/actions'; -import DOM = require('vs/base/browser/dom'); -import types = require('vs/base/common/types'); +import * as DOM from 'vs/base/browser/dom'; +import * as types from 'vs/base/common/types'; import { EventType, Gesture } from 'vs/base/browser/touch'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface IActionItem { actionRunner: IActionRunner; @@ -139,7 +140,7 @@ export class BaseActionItem implements IActionItem { if (this.options && this.options.isMenu) { this.onClick(e); } else { - setImmediate(() => this.onClick(e)); + platform.setImmediate(() => this.onClick(e)); } }); @@ -386,7 +387,7 @@ export class ActionBar implements IActionRunner { private _onDidRun = new Emitter<IRunEvent>(); private _onDidBeforeRun = new Emitter<IRunEvent>(); - constructor(container: HTMLElement | Builder, options: IActionBarOptions = defaultOptions) { + constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) { this.options = options; this._context = options.context; this.toDispose = []; @@ -496,7 +497,7 @@ export class ActionBar implements IActionRunner { this.domNode.appendChild(this.actionsList); - ((container instanceof Builder) ? container.getHTMLElement() : container).appendChild(this.domNode); + container.appendChild(this.domNode); } public get onDidBlur(): Event<void> { @@ -553,8 +554,8 @@ export class ActionBar implements IActionRunner { } } - public getContainer(): Builder { - return $(this.domNode); + public getContainer(): HTMLElement { + return this.domNode; } public push(arg: IAction | IAction[], options: IActionOptions = {}): void { @@ -748,7 +749,7 @@ export class ActionBar implements IActionRunner { this.toDispose = lifecycle.dispose(this.toDispose); - this.getContainer().destroy(); + $(this.getContainer()).destroy(); } } @@ -766,8 +767,8 @@ export class SelectActionItem extends BaseActionItem { this.registerListeners(); } - public setOptions(options: string[], selected?: number): void { - this.selectBox.setOptions(options, selected); + public setOptions(options: string[], selected?: number, disabled?: number): void { + this.selectBox.setOptions(options, selected, disabled); } public select(index: number): void { diff --git a/src/vs/base/browser/ui/aria/aria.css b/src/vs/base/browser/ui/aria/aria.css index 00ff78f7a5..e05407ac1c 100644 --- a/src/vs/base/browser/ui/aria/aria.css +++ b/src/vs/base/browser/ui/aria/aria.css @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ .monaco-aria-container { - position: absolute; /* try to hide from workbench but not from screen readers */ + position: absolute; /* try to hide from window but not from screen readers */ left:-999em; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/aria/aria.ts b/src/vs/base/browser/ui/aria/aria.ts index a105657cb5..b29add6b6d 100644 --- a/src/vs/base/browser/ui/aria/aria.ts +++ b/src/vs/base/browser/ui/aria/aria.ts @@ -6,7 +6,7 @@ 'use strict'; import 'vs/css!./aria'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { isMacintosh } from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index dbc086ec86..efc3018e1e 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -6,14 +6,15 @@ 'use strict'; import 'vs/css!./button'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { Builder, $ } from 'vs/base/browser/builder'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event as BaseEvent, Emitter } from 'vs/base/common/event'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { Gesture, EventType } from 'vs/base/browser/touch'; export interface IButtonOptions extends IButtonStyles { title?: boolean; @@ -44,13 +45,11 @@ export class Button { private buttonBorder: Color; private _onDidClick = new Emitter<any>(); - readonly onDidClick: Event<any> = this._onDidClick.event; + readonly onDidClick: BaseEvent<Event> = this._onDidClick.event; private focusTracker: DOM.IFocusTracker; - constructor(container: Builder, options?: IButtonOptions); - constructor(container: HTMLElement, options?: IButtonOptions); - constructor(container: any, options?: IButtonOptions) { + constructor(container: HTMLElement, options?: IButtonOptions) { this.options = options || Object.create(null); mixin(this.options, defaultOptions, false); @@ -64,7 +63,9 @@ export class Button { 'role': 'button' }).appendTo(container); - this.$el.on(DOM.EventType.CLICK, e => { + Gesture.addTarget(this.$el.getHTMLElement()); + + this.$el.on([DOM.EventType.CLICK, EventType.Tap], e => { if (!this.enabled) { DOM.EventHelper.stop(e); return; @@ -196,9 +197,7 @@ export class ButtonGroup { private _buttons: Button[]; private toDispose: IDisposable[]; - constructor(container: Builder, count: number, options?: IButtonOptions); - constructor(container: HTMLElement, count: number, options?: IButtonOptions); - constructor(container: any, count: number, options?: IButtonOptions) { + constructor(container: HTMLElement, count: number, options?: IButtonOptions) { this._buttons = []; this.toDispose = []; @@ -209,9 +208,7 @@ export class ButtonGroup { return this._buttons; } - private create(container: Builder, count: number, options?: IButtonOptions): void; - private create(container: HTMLElement, count: number, options?: IButtonOptions): void; - private create(container: any, count: number, options?: IButtonOptions): void { + private create(container: HTMLElement, count: number, options?: IButtonOptions): void { for (let index = 0; index < count; index++) { const button = new Button(container, options); this._buttons.push(button); diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index 434022b266..895633c515 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -7,7 +7,7 @@ import 'vs/css!./checkbox'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import * as objects from 'vs/base/common/objects'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Widget } from 'vs/base/browser/ui/widget'; @@ -15,11 +15,11 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Color } from 'vs/base/common/color'; export interface ICheckboxOpts extends ICheckboxStyles { - actionClassName: string; - title: string; - isChecked: boolean; - onChange: (viaKeyboard: boolean) => void; - onKeyDown?: (e: IKeyboardEvent) => void; + readonly actionClassName: string; + readonly title: string; + readonly isChecked: boolean; + readonly onChange: (viaKeyboard: boolean) => void; + readonly onKeyDown?: (e: IKeyboardEvent) => void; } export interface ICheckboxStyles { @@ -32,8 +32,8 @@ const defaultOpts = { export class Checkbox extends Widget { - private _opts: ICheckboxOpts; - public domNode: HTMLElement; + private readonly _opts: ICheckboxOpts; + public readonly domNode: HTMLElement; private _checked: boolean; diff --git a/src/vs/base/browser/ui/contextview/contextview.ts b/src/vs/base/browser/ui/contextview/contextview.ts index 49cf63d8b3..f9d67f611d 100644 --- a/src/vs/base/browser/ui/contextview/contextview.ts +++ b/src/vs/base/browser/ui/contextview/contextview.ts @@ -3,12 +3,11 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - 'use strict'; import 'vs/css!./contextview'; import { Builder, $ } from 'vs/base/browser/builder'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; export interface IAnchor { diff --git a/src/vs/base/browser/ui/countBadge/countBadge.ts b/src/vs/base/browser/ui/countBadge/countBadge.ts index 829257e2a7..eaccf20f24 100644 --- a/src/vs/base/browser/ui/countBadge/countBadge.ts +++ b/src/vs/base/browser/ui/countBadge/countBadge.ts @@ -13,6 +13,7 @@ import { mixin } from 'vs/base/common/objects'; export interface ICountBadgeOptions extends ICountBadgetyles { count?: number; + countFormat?: string; titleFormat?: string; } @@ -31,6 +32,7 @@ export class CountBadge { private element: HTMLElement; private count: number; + private countFormat: string; private titleFormat: string; private badgeBackground: Color; @@ -48,6 +50,7 @@ export class CountBadge { this.badgeBorder = this.options.badgeBorder; this.element = append(container, $('.monaco-count-badge')); + this.countFormat = this.options.countFormat || '{0}'; this.titleFormat = this.options.titleFormat || ''; this.setCount(this.options.count || 0); } @@ -57,13 +60,18 @@ export class CountBadge { this.render(); } + setCountFormat(countFormat: string) { + this.countFormat = countFormat; + this.render(); + } + setTitleFormat(titleFormat: string) { this.titleFormat = titleFormat; this.render(); } private render() { - this.element.textContent = '' + this.count; + this.element.textContent = format(this.countFormat, this.count); this.element.title = format(this.titleFormat, this.count); this.applyStyles(); diff --git a/src/vs/base/browser/ui/dropdown/dropdown.css b/src/vs/base/browser/ui/dropdown/dropdown.css index 66c30237bf..4b75f9ac13 100644 --- a/src/vs/base/browser/ui/dropdown/dropdown.css +++ b/src/vs/base/browser/ui/dropdown/dropdown.css @@ -3,30 +3,29 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.dropdown { +.monaco-dropdown { height: 100%; -} - -.dropdown, .dropdown-group { display: inline-block; padding: 0; } -.dropdown > .dropdown-label, .dropdown > .dropdown-action { +.monaco-dropdown > .dropdown-label, +.monaco-dropdown > .dropdown-action { display: inline-block; cursor: pointer; height: 100%; } -.dropdown > .dropdown-action { +.monaco-dropdown > .dropdown-action { vertical-align: top; } -.dropdown > .dropdown-action > .action-label:hover { +.monaco-dropdown > .dropdown-action > .action-label:hover { color: inherit; text-decoration: none; } -.dropdown > .dropdown-action, .dropdown > .dropdown-action > .action-label { +.monaco-dropdown > .dropdown-action, +.monaco-dropdown > .dropdown-action > .action-label { display: inline-block; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/dropdown/dropdown.ts b/src/vs/base/browser/ui/dropdown/dropdown.ts index f8d854705f..43bcae1049 100644 --- a/src/vs/base/browser/ui/dropdown/dropdown.ts +++ b/src/vs/base/browser/ui/dropdown/dropdown.ts @@ -12,10 +12,10 @@ import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch'; import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions'; import { BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; +import { IContextViewProvider, IAnchor } from 'vs/base/browser/ui/contextview/contextview'; import { IMenuOptions } from 'vs/base/browser/ui/menu/menu'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; -import { EventHelper, EventType } from 'vs/base/browser/dom'; +import { EventHelper, EventType, removeClass, addClass } from 'vs/base/browser/dom'; import { IContextMenuDelegate } from 'vs/base/browser/contextmenu'; export interface ILabelRenderer { @@ -33,13 +33,14 @@ export class BaseDropdown extends ActionRunner { private $boxContainer: Builder; private $label: Builder; private $contents: Builder; + private visible: boolean; constructor(container: HTMLElement, options: IBaseDropdownOptions) { super(); this._toDispose = []; - this.$el = $('.dropdown').appendTo(container); + this.$el = $('.monaco-dropdown').appendTo(container); this.$label = $('.dropdown-label'); @@ -58,7 +59,11 @@ export class BaseDropdown extends ActionRunner { return; // prevent multiple clicks to open multiple context menus (https://github.com/Microsoft/vscode/issues/41363) } - this.show(); + if (this.visible) { + this.hide(); + } else { + this.show(); + } }).appendTo(this.$el); let cleanupFn = labelRenderer(this.$label.getHTMLElement()); @@ -74,12 +79,12 @@ export class BaseDropdown extends ActionRunner { return this._toDispose; } - public get element(): Builder { - return this.$el; + public get element(): HTMLElement { + return this.$el.getHTMLElement(); } - public get label(): Builder { - return this.$label; + public get label(): HTMLElement { + return this.$label.getHTMLElement(); } public set tooltip(tooltip: string) { @@ -87,11 +92,11 @@ export class BaseDropdown extends ActionRunner { } public show(): void { - // noop + this.visible = true; } public hide(): void { - // noop + this.visible = false; } protected onEvent(e: Event, activeElement: HTMLElement): void { @@ -135,10 +140,12 @@ export class Dropdown extends BaseDropdown { } public show(): void { - this.element.addClass('active'); + super.show(); + + addClass(this.element, 'active'); this.contextViewProvider.showContextView({ - getAnchor: () => this.element.getHTMLElement(), + getAnchor: () => this.getAnchor(), render: (container) => { return this.renderContents(container); @@ -148,13 +155,21 @@ export class Dropdown extends BaseDropdown { this.onEvent(e, activeElement); }, - onHide: () => { - this.element.removeClass('active'); - } + onHide: () => this.onHide() }); } + protected getAnchor(): HTMLElement | IAnchor { + return this.element; + } + + protected onHide(): void { + removeClass(this.element, 'active'); + } + public hide(): void { + super.hide(); + if (this.contextViewProvider) { this.contextViewProvider.hideContextView(); } @@ -217,22 +232,24 @@ export class DropdownMenu extends BaseDropdown { } public show(): void { - this.element.addClass('active'); + super.show(); + + addClass(this.element, 'active'); this._contextMenuProvider.showContextMenu({ - getAnchor: () => this.element.getHTMLElement(), + getAnchor: () => this.element, getActions: () => TPromise.as(this.actions), getActionsContext: () => this.menuOptions ? this.menuOptions.context : null, getActionItem: (action) => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : null, getKeyBinding: (action: IAction) => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : null, getMenuClassName: () => this.menuClassName, - onHide: () => this.element.removeClass('active'), + onHide: () => removeClass(this.element, 'active'), actionRunner: this.menuOptions ? this.menuOptions.actionRunner : null }); } public hide(): void { - // noop + super.hide(); } } diff --git a/src/vs/base/browser/ui/findinput/findInput.css b/src/vs/base/browser/ui/findinput/findInput.css index de9fb920d6..dae40151ff 100644 --- a/src/vs/base/browser/ui/findinput/findInput.css +++ b/src/vs/base/browser/ui/findinput/findInput.css @@ -14,14 +14,6 @@ height: 25px; } -.fl:after { - clear: both; - content: ''; - display: block; - visibility: hidden; - height: 0; -} - .monaco-findInput > .controls { position: absolute; top: 3px; diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index dca41b59e8..0964818575 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -11,7 +11,7 @@ import * as dom from 'vs/base/browser/dom'; import { IMessage as InputBoxMessage, IInputValidator, InputBox, IInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { Widget } from 'vs/base/browser/ui/widget'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -20,14 +20,14 @@ import { Color } from 'vs/base/common/color'; import { ICheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox'; export interface IFindInputOptions extends IFindInputStyles { - placeholder?: string; - width?: number; - validation?: IInputValidator; - label: string; + readonly placeholder?: string; + readonly width?: number; + readonly validation?: IInputValidator; + readonly label: string; - appendCaseSensitiveLabel?: string; - appendWholeWordsLabel?: string; - appendRegexLabel?: string; + readonly appendCaseSensitiveLabel?: string; + readonly appendWholeWordsLabel?: string; + readonly appendRegexLabel?: string; } export interface IFindInputStyles extends IInputBoxStyles { @@ -38,7 +38,7 @@ const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); export class FindInput extends Widget { - static OPTION_CHANGE: string = 'optionChange'; + static readonly OPTION_CHANGE: string = 'optionChange'; private contextViewProvider: IContextViewProvider; private width: number; @@ -64,23 +64,23 @@ export class FindInput extends Widget { public domNode: HTMLElement; public inputBox: InputBox; - private _onDidOptionChange = this._register(new Emitter<boolean>()); - public onDidOptionChange: Event<boolean /* via keyboard */> = this._onDidOptionChange.event; + private readonly _onDidOptionChange = this._register(new Emitter<boolean>()); + public readonly onDidOptionChange: Event<boolean /* via keyboard */> = this._onDidOptionChange.event; - private _onKeyDown = this._register(new Emitter<IKeyboardEvent>()); - public onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event; + private readonly _onKeyDown = this._register(new Emitter<IKeyboardEvent>()); + public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event; - private _onMouseDown = this._register(new Emitter<IMouseEvent>()); - public onMouseDown: Event<IMouseEvent> = this._onMouseDown.event; + private readonly _onMouseDown = this._register(new Emitter<IMouseEvent>()); + public readonly onMouseDown: Event<IMouseEvent> = this._onMouseDown.event; - private _onInput = this._register(new Emitter<void>()); - public onInput: Event<void> = this._onInput.event; + private readonly _onInput = this._register(new Emitter<void>()); + public readonly onInput: Event<void> = this._onInput.event; - private _onKeyUp = this._register(new Emitter<IKeyboardEvent>()); - public onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event; + private readonly _onKeyUp = this._register(new Emitter<IKeyboardEvent>()); + public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event; private _onCaseSensitiveKeyDown = this._register(new Emitter<IKeyboardEvent>()); - public onCaseSensitiveKeyDown: Event<IKeyboardEvent> = this._onCaseSensitiveKeyDown.event; + public readonly onCaseSensitiveKeyDown: Event<IKeyboardEvent> = this._onCaseSensitiveKeyDown.event; constructor(parent: HTMLElement, contextViewProvider: IContextViewProvider, options?: IFindInputOptions) { super(); diff --git a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts index 041748941a..a013b30f65 100644 --- a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts +++ b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts @@ -12,11 +12,11 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Color } from 'vs/base/common/color'; export interface IFindInputCheckboxOpts { - appendTitle: string; - isChecked: boolean; - onChange: (viaKeyboard: boolean) => void; - onKeyDown?: (e: IKeyboardEvent) => void; - inputActiveOptionBorder?: Color; + readonly appendTitle: string; + readonly isChecked: boolean; + readonly onChange: (viaKeyboard: boolean) => void; + readonly onKeyDown?: (e: IKeyboardEvent) => void; + readonly inputActiveOptionBorder?: Color; } const NLS_CASE_SENSITIVE_CHECKBOX_LABEL = nls.localize('caseDescription', "Match Case"); diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index 7d75f4e7a6..efd36556c3 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -7,7 +7,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import * as dom from 'vs/base/browser/dom'; import * as objects from 'vs/base/common/objects'; -import { render as renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; +import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; export interface IHighlight { start: number; diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 713f4506af..f391edfea3 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -6,11 +6,11 @@ 'use strict'; import 'vs/css!./iconlabel'; -import dom = require('vs/base/browser/dom'); +import * as dom from 'vs/base/browser/dom'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IMatch } from 'vs/base/common/filters'; import uri from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import { IWorkspaceFolderProvider, getPathLabel, IUserHomeProvider, getBaseLabel } from 'vs/base/common/labels'; import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index bc04607cfb..48094be732 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -6,15 +6,15 @@ import 'vs/css!./inputBox'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as Bal from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; import { RenderOptions, renderFormattedText, renderText } from 'vs/base/browser/htmlContentRenderer'; -import aria = require('vs/base/browser/ui/aria/aria'); +import * as aria from 'vs/base/browser/ui/aria/aria'; import { IAction } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IContextViewProvider, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Widget } from 'vs/base/browser/ui/widget'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; @@ -112,10 +112,10 @@ export class InputBox extends Widget { private inputValidationErrorBackground: Color; private _onDidChange = this._register(new Emitter<string>()); - public onDidChange: Event<string> = this._onDidChange.event; + public readonly onDidChange: Event<string> = this._onDidChange.event; private _onDidHeightChange = this._register(new Emitter<number>()); - public onDidHeightChange: Event<number> = this._onDidHeightChange.event; + public readonly onDidHeightChange: Event<number> = this._onDidHeightChange.event; constructor(container: HTMLElement, contextViewProvider: IContextViewProvider, options?: IInputOptions) { super(); @@ -351,30 +351,27 @@ export class InputBox extends Widget { } public validate(): boolean { - let result: IMessage = null; + let errorMsg: IMessage = null; if (this.validation) { - result = this.validation(this.value); + errorMsg = this.validation(this.value); // {{SQL CARBON EDIT}} - if (!result && this.options.useDefaultValidation && this.inputElement.validationMessage) { - result = { + if (!errorMsg && this.options.useDefaultValidation && this.inputElement.validationMessage) { + errorMsg = { content: this.inputElement.validationMessage, type: MessageType.ERROR }; } - if (!result) { + if (!errorMsg) { this.inputElement.removeAttribute('aria-invalid'); this.hideMessage(); - } else { - this.inputElement.setAttribute('aria-invalid', 'true'); - this.showMessage(result); } } // {{SQL CARBON EDIT}} Canidate for addition to vscode - return result ? result.type !== MessageType.ERROR : true; + return errorMsg ? errorMsg.type !== MessageType.ERROR : true; } private stylesForType(type: MessageType): { border: Color; background: Color } { diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index ed6d19a09e..ed71573ef5 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -9,7 +9,7 @@ import { range } from 'vs/base/common/arrays'; import { IDelegate, IRenderer, IListEvent, IListOpenEvent } from './list'; import { List, IListStyles, IListOptions } from './listWidget'; import { IPagedModel } from 'vs/base/common/paging'; -import Event, { mapEvent } from 'vs/base/common/event'; +import { Event, mapEvent } from 'vs/base/common/event'; export interface IPagedRenderer<TElement, TTemplateData> extends IRenderer<TElement, TTemplateData> { renderPlaceholder(index: number, templateData: TTemplateData): void; @@ -58,7 +58,7 @@ class PagedRenderer<TElement, TTemplateData> implements IRenderer<number, ITempl } } -export class PagedList<T> { +export class PagedList<T> implements IDisposable { private list: List<number>; private _model: IPagedModel<T>; @@ -81,6 +81,10 @@ export class PagedList<T> { return this.list.getHTMLElement() === document.activeElement; } + domFocus(): void { + this.list.domFocus(); + } + get onDidFocus(): Event<void> { return this.list.onDidFocus; } @@ -93,6 +97,10 @@ export class PagedList<T> { return this.list; } + get onDidDispose(): Event<void> { + return this.list.onDidDispose; + } + get onFocusChange(): Event<IListEvent<T>> { return mapEvent(this.list.onFocusChange, ({ elements, indexes }) => ({ elements: elements.map(e => this._model.get(e)), indexes })); } @@ -185,4 +193,8 @@ export class PagedList<T> { style(styles: IListStyles): void { this.list.style(styles); } -} \ No newline at end of file + + dispose(): void { + this.list.dispose(); + } +} diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 81ff81f326..2c185f5c8f 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -7,7 +7,7 @@ import { getOrDefault } from 'vs/base/common/objects'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import * as DOM from 'vs/base/browser/dom'; -import Event, { mapEvent, filterEvent } from 'vs/base/common/event'; +import { Event, mapEvent, filterEvent } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollEvent, ScrollbarVisibility } from 'vs/base/common/scrollable'; @@ -360,19 +360,22 @@ export class ListView<T> implements ISpliceable<T>, IDisposable { private toMouseEvent(browserEvent: MouseEvent): IListMouseEvent<T> { const index = this.getItemIndexFromEventTarget(browserEvent.target); - const element = index < 0 ? undefined : this.items[index].element; + const item = index < 0 ? undefined : this.items[index]; + const element = item && item.element; return { browserEvent, index, element }; } private toTouchEvent(browserEvent: TouchEvent): IListTouchEvent<T> { const index = this.getItemIndexFromEventTarget(browserEvent.target); - const element = index < 0 ? undefined : this.items[index].element; + const item = index < 0 ? undefined : this.items[index]; + const element = item && item.element; return { browserEvent, index, element }; } private toGestureEvent(browserEvent: GestureEvent): IListGestureEvent<T> { const index = this.getItemIndexFromEventTarget(browserEvent.initialTarget); - const element = index < 0 ? undefined : this.items[index].element; + const item = index < 0 ? undefined : this.items[index]; + const element = item && item.element; return { browserEvent, index, element }; } diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 7e926bbc9a..797215350f 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -13,7 +13,7 @@ import * as platform from 'vs/base/common/platform'; import { Gesture } from 'vs/base/browser/touch'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import Event, { Emitter, EventBufferer, chain, mapEvent, anyEvent } from 'vs/base/common/event'; +import { Event, Emitter, EventBufferer, chain, mapEvent, anyEvent } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { IDelegate, IRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IListOpenEvent } from './list'; import { ListView, IListViewOptions } from './listView'; @@ -142,7 +142,7 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable { const end = start + deleteCount; const indexes = [ ...this.indexes.filter(i => i < start), - ...elements.reduce((r, hasTrait, i) => hasTrait ? [...r, i + start] : r, []), + ...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1), ...this.indexes.filter(i => i >= end).map(i => i + diff) ]; @@ -388,7 +388,7 @@ const DefaultMultipleSelectionContoller = { isSelectionRangeChangeEvent }; -const DefaultOpenController = { +const DefaultOpenController: IOpenController = { shouldOpen: (event: UIEvent) => { if (event instanceof MouseEvent) { return !isMouseRightClick(event); @@ -396,7 +396,7 @@ const DefaultOpenController = { return true; } -} as IOpenController; +}; class MouseController<T> implements IDisposable { @@ -580,6 +580,89 @@ export interface IOpenController { shouldOpen(event: UIEvent): boolean; } +export interface IStyleController { + style(styles: IListStyles): void; +} + +export class DefaultStyleController implements IStyleController { + + constructor(private styleElement: HTMLStyleElement, private selectorSuffix?: string) { } + + style(styles: IListStyles): void { + const suffix = this.selectorSuffix ? `.${this.selectorSuffix}` : ''; + const content: string[] = []; + + if (styles.listFocusBackground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { background-color: ${styles.listFocusBackground}; }`); + content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused:hover { background-color: ${styles.listFocusBackground}; }`); // overwrite :hover style in this case! + } + + if (styles.listFocusForeground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { color: ${styles.listFocusForeground}; }`); + } + + if (styles.listActiveSelectionBackground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected { background-color: ${styles.listActiveSelectionBackground}; }`); + content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected:hover { background-color: ${styles.listActiveSelectionBackground}; }`); // overwrite :hover style in this case! + } + + if (styles.listActiveSelectionForeground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected { color: ${styles.listActiveSelectionForeground}; }`); + } + + if (styles.listFocusAndSelectionBackground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected.focused { background-color: ${styles.listFocusAndSelectionBackground}; }`); + } + + if (styles.listFocusAndSelectionForeground) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected.focused { color: ${styles.listFocusAndSelectionForeground}; }`); + } + + if (styles.listInactiveFocusBackground) { + content.push(`.monaco-list${suffix} .monaco-list-row.focused { background-color: ${styles.listInactiveFocusBackground}; }`); + content.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { background-color: ${styles.listInactiveFocusBackground}; }`); // overwrite :hover style in this case! + } + + if (styles.listInactiveSelectionBackground) { + content.push(`.monaco-list${suffix} .monaco-list-row.selected { background-color: ${styles.listInactiveSelectionBackground}; }`); + content.push(`.monaco-list${suffix} .monaco-list-row.selected:hover { background-color: ${styles.listInactiveSelectionBackground}; }`); // overwrite :hover style in this case! + } + + if (styles.listInactiveSelectionForeground) { + content.push(`.monaco-list${suffix} .monaco-list-row.selected { color: ${styles.listInactiveSelectionForeground}; }`); + } + + if (styles.listHoverBackground) { + content.push(`.monaco-list${suffix} .monaco-list-row:hover { background-color: ${styles.listHoverBackground}; }`); + } + + if (styles.listHoverForeground) { + content.push(`.monaco-list${suffix} .monaco-list-row:hover { color: ${styles.listHoverForeground}; }`); + } + + if (styles.listSelectionOutline) { + content.push(`.monaco-list${suffix} .monaco-list-row.selected { outline: 1px dotted ${styles.listSelectionOutline}; outline-offset: -1px; }`); + } + + if (styles.listFocusOutline) { + content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }`); + } + + if (styles.listInactiveFocusOutline) { + content.push(`.monaco-list${suffix} .monaco-list-row.focused { outline: 1px dotted ${styles.listInactiveFocusOutline}; outline-offset: -1px; }`); + } + + if (styles.listHoverOutline) { + content.push(`.monaco-list${suffix} .monaco-list-row:hover { outline: 1px dashed ${styles.listHoverOutline}; outline-offset: -1px; }`); + } + + const newStyles = content.join('\n'); + if (newStyles !== this.styleElement.innerHTML) { + this.styleElement.innerHTML = newStyles; + } + } +} + export interface IListOptions<T> extends IListViewOptions, IListStyles { identityProvider?: IIdentityProvider<T>; ariaLabel?: string; @@ -591,6 +674,7 @@ export interface IListOptions<T> extends IListViewOptions, IListStyles { multipleSelectionSupport?: boolean; multipleSelectionController?: IMultipleSelectionController<T>; openController?: IOpenController; + styleController?: IStyleController; } export interface IListStyles { @@ -737,7 +821,7 @@ class PipelineRenderer<T> implements IRenderer<T, any> { let i = 0; for (const renderer of this.renderers) { - renderer.disposeTemplate(templateData[i]); + renderer.disposeTemplate(templateData[i++]); } } } @@ -754,6 +838,7 @@ export class List<T> implements ISpliceable<T>, IDisposable { private spliceable: ISpliceable<T>; protected disposables: IDisposable[]; private styleElement: HTMLStyleElement; + private styleController: IStyleController; private mouseController: MouseController<T>; @memoize get onFocusChange(): Event<IListEvent<T>> { @@ -767,9 +852,7 @@ export class List<T> implements ISpliceable<T>, IDisposable { readonly onContextMenu: Event<IListContextMenuEvent<T>> = Event.None; private _onOpen = new Emitter<IListOpenEvent<T>>(); - @memoize get onOpen(): Event<IListOpenEvent<T>> { - return this._onOpen.event; - } + readonly onOpen: Event<IListOpenEvent<T>> = this._onOpen.event; private _onPin = new Emitter<number[]>(); @memoize get onPin(): Event<IListEvent<T>> { @@ -816,6 +899,11 @@ export class List<T> implements ISpliceable<T>, IDisposable { this.styleElement = DOM.createStyleSheet(this.view.domNode); + this.styleController = options.styleController; + if (!this.styleController) { + this.styleController = new DefaultStyleController(this.styleElement, this.idPrefix); + } + this.spliceable = new CombinedSpliceable([ new TraitSpliceable(this.focus, this.view, options.identityProvider), new TraitSpliceable(this.selection, this.view, options.identityProvider), @@ -1087,73 +1175,7 @@ export class List<T> implements ISpliceable<T>, IDisposable { } style(styles: IListStyles): void { - const content: string[] = []; - - if (styles.listFocusBackground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.focused { background-color: ${styles.listFocusBackground}; }`); - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.focused:hover { background-color: ${styles.listFocusBackground}; }`); // overwrite :hover style in this case! - } - - if (styles.listFocusForeground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.focused { color: ${styles.listFocusForeground}; }`); - } - - if (styles.listActiveSelectionBackground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.selected { background-color: ${styles.listActiveSelectionBackground}; }`); - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.selected:hover { background-color: ${styles.listActiveSelectionBackground}; }`); // overwrite :hover style in this case! - } - - if (styles.listActiveSelectionForeground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.selected { color: ${styles.listActiveSelectionForeground}; }`); - } - - if (styles.listFocusAndSelectionBackground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.selected.focused { background-color: ${styles.listFocusAndSelectionBackground}; }`); - } - - if (styles.listFocusAndSelectionForeground) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.selected.focused { color: ${styles.listFocusAndSelectionForeground}; }`); - } - - if (styles.listInactiveFocusBackground) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.focused { background-color: ${styles.listInactiveFocusBackground}; }`); - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.focused:hover { background-color: ${styles.listInactiveFocusBackground}; }`); // overwrite :hover style in this case! - } - - if (styles.listInactiveSelectionBackground) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.selected { background-color: ${styles.listInactiveSelectionBackground}; }`); - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.selected:hover { background-color: ${styles.listInactiveSelectionBackground}; }`); // overwrite :hover style in this case! - } - - if (styles.listInactiveSelectionForeground) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.selected { color: ${styles.listInactiveSelectionForeground}; }`); - } - - if (styles.listHoverBackground) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row:hover { background-color: ${styles.listHoverBackground}; }`); - } - - if (styles.listHoverForeground) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row:hover { color: ${styles.listHoverForeground}; }`); - } - - if (styles.listSelectionOutline) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.selected { outline: 1px dotted ${styles.listSelectionOutline}; outline-offset: -1px; }`); - } - - if (styles.listFocusOutline) { - content.push(`.monaco-list.${this.idPrefix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }`); - } - - if (styles.listInactiveFocusOutline) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row.focused { outline: 1px dotted ${styles.listInactiveFocusOutline}; outline-offset: -1px; }`); - } - - if (styles.listHoverOutline) { - content.push(`.monaco-list.${this.idPrefix} .monaco-list-row:hover { outline: 1px dashed ${styles.listHoverOutline}; outline-offset: -1px; }`); - } - - this.styleElement.innerHTML = content.join('\n'); + this.styleController.style(styles); } private toListEvent({ indexes }: ITraitChangeEvent) { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 256bc7822f..09d9c6f14b 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -7,11 +7,11 @@ import 'vs/css!./menu'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { $ } from 'vs/base/browser/builder'; import { IActionRunner, IAction } from 'vs/base/common/actions'; import { ActionBar, IActionItemProvider, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; +import { addClass } from 'vs/base/browser/dom'; export interface IMenuOptions { context?: any; @@ -26,11 +26,13 @@ export class Menu { private listener: IDisposable; constructor(container: HTMLElement, actions: IAction[], options: IMenuOptions = {}) { - $(container).addClass('monaco-menu-container'); + addClass(container, 'monaco-menu-container'); - let $menu = $('.monaco-menu').appendTo(container); + let menuContainer = document.createElement('div'); + addClass(menuContainer, 'monaco-menu'); + container.appendChild(menuContainer); - this.actionBar = new ActionBar($menu, { + this.actionBar = new ActionBar(menuContainer, { orientation: ActionsOrientation.VERTICAL, actionItemProvider: options.actionItemProvider, context: options.context, diff --git a/src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts b/src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts index f0f7a38e0c..17677a0303 100644 --- a/src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts +++ b/src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import octiconLabel = require('vs/base/browser/ui/octiconLabel/octiconLabel'); + import { escape } from 'vs/base/common/strings'; -function render(text: string): string { +export function renderOcticons(text: string): string { return escape(text); } -class MockOcticonLabel { +export class OcticonLabel { private _container: HTMLElement; @@ -18,13 +18,7 @@ class MockOcticonLabel { } set text(text: string) { - this._container.innerHTML = render(text || ''); + this._container.innerHTML = renderOcticons(text || ''); } } - -var mock: typeof octiconLabel = { - render: render, - OcticonLabel: <any>MockOcticonLabel -}; -export = mock; \ No newline at end of file diff --git a/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts b/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts index 156d92c038..5faca97140 100644 --- a/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts +++ b/src/vs/base/browser/ui/octiconLabel/octiconLabel.ts @@ -14,20 +14,20 @@ function expand(text: string): string { }); } -export function render(label: string): string { +export function renderOcticons(label: string): string { return expand(escape(label)); } export class OcticonLabel { - private _container: HTMLElement; + private readonly _container: HTMLElement; constructor(container: HTMLElement) { this._container = container; } set text(text: string) { - this._container.innerHTML = render(text || ''); + this._container.innerHTML = renderOcticons(text || ''); } set title(title: string) { diff --git a/src/vs/base/browser/ui/progressbar/progressbar.css b/src/vs/base/browser/ui/progressbar/progressbar.css index 48b4dadfee..599e3566a9 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.css +++ b/src/vs/base/browser/ui/progressbar/progressbar.css @@ -2,12 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.progress-container { + +.monaco-progress-container { width: 100%; height: 5px; + overflow: hidden; /* keep progress bit in bounds */ } -.progress-container .progress-bit { +.monaco-progress-container .progress-bit { width: 2%; height: 5px; position: absolute; @@ -15,11 +17,11 @@ display: none; } -.progress-container.active .progress-bit { +.monaco-progress-container.active .progress-bit { display: inherit; } -.progress-container.discrete .progress-bit { +.monaco-progress-container.discrete .progress-bit { left: 0; transition: width 100ms linear; -webkit-transition: width 100ms linear; @@ -28,11 +30,11 @@ -ms-transition: width 100ms linear; } -.progress-container.discrete.done .progress-bit { +.monaco-progress-container.discrete.done .progress-bit { width: 100%; } -.progress-container.infinite .progress-bit { +.monaco-progress-container.infinite .progress-bit { animation-name: progress; animation-duration: 4s; animation-iteration-count: infinite; @@ -49,11 +51,17 @@ -moz-animation-duration: 4s; -moz-animation-iteration-count: infinite; -moz-animation-timing-function: linear; + will-change: transform; } -@keyframes progress { from { left: 0; width: 2%; } 50% { left: 50%; width: 5%; } to { left: 98%; width: 2%; } } -@-ms-keyframes progress { from { left: 0; width: 2%; } 50% { left: 50%; width: 5%; } to { left: 98%; width: 2%; } } -@-webkit-keyframes progress { from { left: 0; width: 2%; } 50% { left: 50%; width: 5%; } to { left: 98%; width: 2%; } } -@-moz-keyframes progress { from { left: 0; width: 2%; } 50% { left: 50%; width: 5%; } to { left: 98%; width: 2%; } } - - +/** + * The progress bit has a width: 2% (1/50) of the parent container. The animation moves it from 0% to 100% of + * that container. Since translateX is relative to the progress bit size, we have to multiple it with + * its relative size to the parent container: + * 50%: 50 * 50 = 2500% + * 100%: 50 * 100 - 50 (do not overflow): 4950% + */ +@keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } } +@-ms-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } } +@-webkit-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } } +@-moz-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } } \ No newline at end of file diff --git a/src/vs/base/browser/ui/progressbar/progressbar.ts b/src/vs/base/browser/ui/progressbar/progressbar.ts index 61640d5e16..1e87c908d0 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.ts +++ b/src/vs/base/browser/ui/progressbar/progressbar.ts @@ -7,9 +7,9 @@ import 'vs/css!./progressbar'; import { TPromise, ValueCallback } from 'vs/base/common/winjs.base'; -import assert = require('vs/base/common/assert'); +import * as assert from 'vs/base/common/assert'; import { Builder, $ } from 'vs/base/browser/builder'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; @@ -18,7 +18,7 @@ const css_done = 'done'; const css_active = 'active'; const css_infinite = 'infinite'; const css_discrete = 'discrete'; -const css_progress_container = 'progress-container'; +const css_progress_container = 'monaco-progress-container'; const css_progress_bit = 'progress-bit'; export interface IProgressBarOptions extends IProgressBarStyles { @@ -45,9 +45,7 @@ export class ProgressBar { private animationStopToken: ValueCallback; private progressBarBackground: Color; - constructor(container: Builder, options?: IProgressBarOptions); - constructor(container: HTMLElement, options?: IProgressBarOptions); - constructor(container: any, options?: IProgressBarOptions) { + constructor(container: HTMLElement, options?: IProgressBarOptions) { this.options = options || Object.create(null); mixin(this.options, defaultOpts, false); @@ -59,10 +57,8 @@ export class ProgressBar { this.create(container); } - private create(container: Builder): void; - private create(container: HTMLElement): void; - private create(container: any): void { - $(container).div({ 'class': css_progress_container }, (builder) => { + private create(container: HTMLElement): void { + $(container).div({ 'class': css_progress_container }, builder => { this.element = builder.clone(); builder.div({ 'class': css_progress_bit }).on([DOM.EventType.ANIMATION_START, DOM.EventType.ANIMATION_END, DOM.EventType.ANIMATION_ITERATION], (e: Event) => { @@ -201,11 +197,20 @@ export class ProgressBar { return this; } - /** - * Returns the builder this progress bar is building in. - */ - public getContainer(): Builder { - return $(this.element); + public getContainer(): HTMLElement { + return this.element.getHTMLElement(); + } + + public show(delay?: number): void { + if (typeof delay === 'number') { + this.element.showDelayed(delay); + } else { + this.element.show(); + } + } + + public hide(): void { + this.element.hide(); } public style(styles: IProgressBarStyles): void { diff --git a/src/vs/base/browser/ui/sash/sash.css b/src/vs/base/browser/ui/sash/sash.css index d55dca1cc9..287fea64c1 100644 --- a/src/vs/base/browser/ui/sash/sash.css +++ b/src/vs/base/browser/ui/sash/sash.css @@ -25,22 +25,12 @@ cursor: default !important; } -.vertical-cursor-container { - cursor: ew-resize; -} - -.horizontal-cursor-container { - cursor: ns-resize; -} - /** Custom Mac Cursor */ -.monaco-sash.mac.vertical, -.vertical-cursor-container-mac { +.monaco-sash.mac.vertical { cursor: col-resize; } -.monaco-sash.mac.horizontal, -.horizontal-cursor-container-mac { +.monaco-sash.mac.horizontal { cursor: row-resize; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 497eabe645..94c7d4530b 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -7,14 +7,14 @@ import 'vs/css!./sash'; import { IDisposable, Disposable, dispose } from 'vs/base/common/lifecycle'; -import { Builder, $, Dimension } from 'vs/base/browser/builder'; +import { Builder, $ } from 'vs/base/browser/builder'; import { isIPad } from 'vs/base/browser/browser'; import { isMacintosh } from 'vs/base/common/platform'; -import types = require('vs/base/common/types'); -import DOM = require('vs/base/browser/dom'); +import * as types from 'vs/base/common/types'; import { EventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; +import { getElementsByTagName, EventHelper, EventType as DOMEventType, createStyleSheet, addDisposableListener, Dimension } from 'vs/base/browser/dom'; export interface ISashLayoutProvider { } @@ -63,15 +63,14 @@ export class Sash { private _onDidEnd = new Emitter<void>(); constructor(container: HTMLElement, layoutProvider: ISashLayoutProvider, options: ISashOptions = {}) { - this.$e = $('.monaco-sash').appendTo(container); if (isMacintosh) { this.$e.addClass('mac'); } - this.$e.on(DOM.EventType.MOUSE_DOWN, (e) => { this.onMouseDown(e as MouseEvent); }); - this.$e.on(DOM.EventType.DBLCLICK, (e) => this._onDidReset.fire()); + this.$e.on(DOMEventType.MOUSE_DOWN, (e) => { this.onMouseDown(e as MouseEvent); }); + this.$e.on(DOMEventType.DBLCLICK, (e) => this._onDidReset.fire()); Gesture.addTarget(this.$e.getHTMLElement()); this.$e.on(EventType.Start, (e) => { this.onTouchStart(e as GestureEvent); }); @@ -127,23 +126,23 @@ export class Sash { } private onMouseDown(e: MouseEvent): void { - DOM.EventHelper.stop(e, false); + EventHelper.stop(e, false); if (this.isDisabled) { return; } - const iframes = $(DOM.getElementsByTagName('iframe')); + const iframes = $(getElementsByTagName('iframe')); if (iframes) { iframes.style('pointer-events', 'none'); // disable mouse events on iframes as long as we drag the sash } - let mouseDownEvent = new StandardMouseEvent(e); - let startX = mouseDownEvent.posx; - let startY = mouseDownEvent.posy; + const mouseDownEvent = new StandardMouseEvent(e); + const startX = mouseDownEvent.posx; + const startY = mouseDownEvent.posy; const altKey = mouseDownEvent.altKey; - let startEvent: ISashEvent = { + const startEvent: ISashEvent = { startX: startX, currentX: startX, startY: startY, @@ -154,14 +153,21 @@ export class Sash { this.$e.addClass('active'); this._onDidStart.fire(startEvent); - let $window = $(window); - let containerCSSClass = `${this.getOrientation()}-cursor-container${isMacintosh ? '-mac' : ''}`; + const $window = $(window); + + // fix https://github.com/Microsoft/vscode/issues/21675 + const globalStyle = createStyleSheet(this.$e.getHTMLElement()); + if (this.orientation === Orientation.HORIZONTAL) { + globalStyle.innerHTML = `* { cursor: ${isMacintosh ? 'row-resize' : 'ns-resize'}; }`; + } else { + globalStyle.innerHTML = `* { cursor: ${isMacintosh ? 'col-resize' : 'ew-resize'}; }`; + } $window.on('mousemove', (e) => { - DOM.EventHelper.stop(e, false); - let mouseMoveEvent = new StandardMouseEvent(e as MouseEvent); + EventHelper.stop(e, false); + const mouseMoveEvent = new StandardMouseEvent(e as MouseEvent); - let event: ISashEvent = { + const event: ISashEvent = { startX: startX, currentX: mouseMoveEvent.posx, startY: startY, @@ -171,29 +177,29 @@ export class Sash { this._onDidChange.fire(event); }).once('mouseup', (e) => { - DOM.EventHelper.stop(e, false); + EventHelper.stop(e, false); + + this.$e.getHTMLElement().removeChild(globalStyle); + this.$e.removeClass('active'); this._onDidEnd.fire(); $window.off('mousemove'); - document.body.classList.remove(containerCSSClass); - const iframes = $(DOM.getElementsByTagName('iframe')); + const iframes = $(getElementsByTagName('iframe')); if (iframes) { iframes.style('pointer-events', 'auto'); } }); - - document.body.classList.add(containerCSSClass); } private onTouchStart(event: GestureEvent): void { - DOM.EventHelper.stop(event); + EventHelper.stop(event); - let listeners: IDisposable[] = []; + const listeners: IDisposable[] = []; - let startX = event.pageX; - let startY = event.pageY; + const startX = event.pageX; + const startY = event.pageY; const altKey = event.altKey; @@ -205,7 +211,7 @@ export class Sash { altKey }); - listeners.push(DOM.addDisposableListener(this.$e.getHTMLElement(), EventType.Change, (event: GestureEvent) => { + listeners.push(addDisposableListener(this.$e.getHTMLElement(), EventType.Change, (event: GestureEvent) => { if (types.isNumber(event.pageX) && types.isNumber(event.pageY)) { this._onDidChange.fire({ startX: startX, @@ -217,7 +223,7 @@ export class Sash { } })); - listeners.push(DOM.addDisposableListener(this.$e.getHTMLElement(), EventType.End, (event: GestureEvent) => { + listeners.push(addDisposableListener(this.$e.getHTMLElement(), EventType.End, (event: GestureEvent) => { this._onDidEnd.fire(); dispose(listeners); })); @@ -227,7 +233,7 @@ export class Sash { let style: { top?: string; left?: string; height?: string; width?: string; }; if (this.orientation === Orientation.VERTICAL) { - let verticalProvider = (<IVerticalSashLayoutProvider>this.layoutProvider); + const verticalProvider = (<IVerticalSashLayoutProvider>this.layoutProvider); style = { left: verticalProvider.getVerticalSashLeft(this) - (this.size / 2) + 'px' }; if (verticalProvider.getVerticalSashTop) { @@ -238,7 +244,7 @@ export class Sash { style.height = verticalProvider.getVerticalSashHeight(this) + 'px'; } } else { - let horizontalProvider = (<IHorizontalSashLayoutProvider>this.layoutProvider); + const horizontalProvider = (<IHorizontalSashLayoutProvider>this.layoutProvider); style = { top: horizontalProvider.getHorizontalSashTop(this) - (this.size / 2) + 'px' }; if (horizontalProvider.getHorizontalSashLeft) { @@ -294,18 +300,18 @@ export class Sash { * Triggers onPositionChange event when the position is changed */ export class VSash extends Disposable implements IVerticalSashLayoutProvider { - private sash: Sash; private ratio: number; private startPosition: number; private position: number; private dimension: Dimension; - private _onPositionChange: Emitter<number> = new Emitter<number>(); + private readonly _onPositionChange: Emitter<number> = new Emitter<number>(); public get onPositionChange(): Event<number> { return this._onPositionChange.event; } constructor(container: HTMLElement, private minWidth: number) { super(); + this.ratio = 0.5; this.sash = new Sash(container, this); @@ -357,9 +363,9 @@ export class VSash extends Disposable implements IVerticalSashLayoutProvider { } private computeSashPosition(sashRatio: number = this.ratio) { - let contentWidth = this.dimension.width; + const contentWidth = this.dimension.width; let sashPosition = Math.floor((sashRatio || 0.5) * contentWidth); - let midPoint = Math.floor(0.5 * contentWidth); + const midPoint = Math.floor(0.5 * contentWidth); if (contentWidth > this.minWidth * 2) { if (sashPosition < this.minWidth) { diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 987a812178..d48b29cee7 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -18,7 +18,7 @@ import { Widget } from 'vs/base/browser/ui/widget'; import { TimeoutTimer } from 'vs/base/common/async'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; import { ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; const HIDE_TIMEOUT = 500; const SCROLL_WHEEL_SENSITIVITY = 50; @@ -164,7 +164,7 @@ export abstract class AbstractScrollableElement extends Widget { private _shouldRender: boolean; private readonly _onScroll = this._register(new Emitter<ScrollEvent>()); - public onScroll: Event<ScrollEvent> = this._onScroll.event; + public readonly onScroll: Event<ScrollEvent> = this._onScroll.event; protected constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable?: Scrollable) { super(); @@ -336,16 +336,6 @@ export abstract class AbstractScrollableElement extends Widget { deltaY = 0; } - if (Platform.isMacintosh) { - // Give preference to vertical scrolling - if (deltaY && Math.abs(deltaX) < 0.2) { - deltaX = 0; - } - if (Math.abs(deltaY) > Math.abs(deltaX) * 0.5) { - deltaX = 0; - } - } - const futureScrollPosition = this._scrollable.getFutureScrollPosition(); let desiredScrollPosition: INewScrollPosition = {}; diff --git a/src/vs/base/browser/ui/selectBox/selectBox.css b/src/vs/base/browser/ui/selectBox/selectBox.css index 7db02fc7ec..bfea4cce66 100644 --- a/src/vs/base/browser/ui/selectBox/selectBox.css +++ b/src/vs/base/browser/ui/selectBox/selectBox.css @@ -3,7 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-workbench .select-box { +.monaco-select-box { width: 100%; - height: 20px; -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/selectBox/selectBox.ts b/src/vs/base/browser/ui/selectBox/selectBox.ts index e993715218..16fcb2ca7b 100644 --- a/src/vs/base/browser/ui/selectBox/selectBox.ts +++ b/src/vs/base/browser/ui/selectBox/selectBox.ts @@ -6,7 +6,7 @@ import 'vs/css!./selectBox'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { Widget } from 'vs/base/browser/ui/widget'; import { Color } from 'vs/base/common/color'; import { deepClone, mixin } from 'vs/base/common/objects'; @@ -34,6 +34,10 @@ export interface ISelectBoxDelegate { applyStyles(): void; } +export interface ISelectBoxOptions { + minBottomMargin?: number; +} + export interface ISelectBoxStyles extends IListStyles { selectBackground?: Color; selectListBackground?: Color; @@ -54,21 +58,16 @@ export interface ISelectData { } export class SelectBox extends Widget implements ISelectBoxDelegate { - protected options: string[]; - private selected: number; - private _onDidSelect: Emitter<ISelectData>; - // {{SQL CARBON EDIT}} protected selectElement: HTMLSelectElement; protected selectBackground: Color; protected selectForeground: Color; protected selectBorder: Color; private toDispose: IDisposable[]; - private styles: ISelectBoxStyles; private selectBoxDelegate: ISelectBoxDelegate; - constructor(options: string[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles)) { + constructor(options: string[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) { super(); this.toDispose = []; @@ -79,7 +78,7 @@ export class SelectBox extends Widget implements ISelectBoxDelegate { if (isMacintosh) { this.selectBoxDelegate = new SelectBoxNative(options, selected, styles); } else { - this.selectBoxDelegate = new SelectBoxList(options, selected, contextViewProvider, styles); + this.selectBoxDelegate = new SelectBoxList(options, selected, contextViewProvider, styles, selectBoxOptions); } // {{SQL CARBON EDIT}} diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css index 7d3acdd927..e9e8010616 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css @@ -3,13 +3,11 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/* Require .monaco-shell for ContextView dropdown */ - -.monaco-shell .select-box-dropdown-container { +.monaco-select-box-dropdown-container { display: none; } -.monaco-shell .select-box-dropdown-container.visible { +.monaco-select-box-dropdown-container.visible { display: flex; flex-direction: column; text-align: left; @@ -17,7 +15,7 @@ overflow: hidden; } -.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container { +.monaco-select-box-dropdown-container > .select-box-dropdown-list-container { flex: 0 0 auto; align-self: flex-start; padding-bottom: 1px; @@ -33,30 +31,30 @@ box-sizing: border-box; } -.monaco-shell.hc-black .select-box-dropdown-container > .select-box-dropdown-list-container { +.hc-black .monaco-select-box-dropdown-container > .select-box-dropdown-list-container { padding-bottom: 4px; padding-top: 3px; } -.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .option-text { +.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .option-text { text-overflow: ellipsis; overflow: hidden; padding-left: 3.5px; white-space: nowrap; } -.monaco-shell .select-box-dropdown-container > .select-box-dropdown-container-width-control { +.monaco-select-box-dropdown-container > .select-box-dropdown-container-width-control { flex: 1 1 auto; align-self: flex-start; opacity: 0; } -.monaco-shell .select-box-dropdown-container > .select-box-dropdown-container-width-control > .width-control-div { +.monaco-select-box-dropdown-container > .select-box-dropdown-container-width-control > .width-control-div { overflow: hidden; max-height: 0px; } -.monaco-shell .select-box-dropdown-container > .select-box-dropdown-container-width-control > .width-control-div > .option-text-width-control { +.monaco-select-box-dropdown-container > .select-box-dropdown-container-width-control > .width-control-div > .option-text-width-control { padding-left: 4px; padding-right: 8px; white-space: nowrap; diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index c2acdb5c86..00d68c6b85 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -7,7 +7,7 @@ import 'vs/css!./selectBoxCustom'; import * as nls from 'vs/nls'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter, chain } from 'vs/base/common/event'; +import { Event, Emitter, chain } from 'vs/base/common/event'; import { KeyCode, KeyCodeUtils } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import * as dom from 'vs/base/browser/dom'; @@ -17,7 +17,7 @@ import { List } from 'vs/base/browser/ui/list/listWidget'; import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; import { domEvent } from 'vs/base/browser/event'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { ISelectBoxDelegate, ISelectBoxStyles, ISelectData } from 'vs/base/browser/ui/selectBox/selectBox'; +import { ISelectBoxDelegate, ISelectBoxOptions, ISelectBoxStyles, ISelectData } from 'vs/base/browser/ui/selectBox/selectBox'; import { isMacintosh } from 'vs/base/common/platform'; const $ = dom.$; @@ -61,6 +61,9 @@ class SelectListRenderer implements IRenderer<ISelectOptionItem, ISelectListTemp // pseudo-select disabled option if (optionDisabled) { dom.addClass((<HTMLElement>data.root), 'option-disabled'); + } else { + // Make sure we do class removal from prior template rendering + dom.removeClass((<HTMLElement>data.root), 'option-disabled'); } } @@ -71,15 +74,16 @@ class SelectListRenderer implements IRenderer<ISelectOptionItem, ISelectListTemp export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptionItem> { - private static SELECT_DROPDOWN_BOTTOM_MARGIN = 10; + private static readonly DEFAULT_DROPDOWN_MINIMUM_BOTTOM_MARGIN = 32; private _isVisible: boolean; + private selectBoxOptions: ISelectBoxOptions; // {{SQL CARBON EDIT}} public selectElement: HTMLSelectElement; private options: string[]; private selected: number; private disabledOptionIndex: number; - private _onDidSelect: Emitter<ISelectData>; + private readonly _onDidSelect: Emitter<ISelectData>; private toDispose: IDisposable[]; private styles: ISelectBoxStyles; private listRenderer: SelectListRenderer; @@ -91,13 +95,20 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio private widthControlElement: HTMLElement; private _currentSelection: number; - constructor(options: string[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles) { + constructor(options: string[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) { this.toDispose = []; this._isVisible = false; + this.selectBoxOptions = selectBoxOptions || Object.create(null); + + if (typeof this.selectBoxOptions.minBottomMargin !== 'number') { + this.selectBoxOptions.minBottomMargin = SelectBoxList.DEFAULT_DROPDOWN_MINIMUM_BOTTOM_MARGIN; + } else if (this.selectBoxOptions.minBottomMargin < 0) { + this.selectBoxOptions.minBottomMargin = 0; + } this.selectElement = document.createElement('select'); - this.selectElement.className = 'select-box'; + this.selectElement.className = 'monaco-select-box'; this._onDidSelect = new Emitter<ISelectData>(); this.styles = styles; @@ -122,7 +133,7 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio // SetUp ContextView container to hold select Dropdown this.contextViewProvider = contextViewProvider; - this.selectDropDownContainer = dom.$('.select-box-dropdown-container'); + this.selectDropDownContainer = dom.$('.monaco-select-box-dropdown-container'); // Setup list for drop-down select this.createSelectList(this.selectDropDownContainer); @@ -235,6 +246,10 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio if (index >= 0 && index < this.options.length) { this.selected = index; + } else if (index > this.options.length - 1) { + // Adjust index to end of list + // This could make client out of sync with the select + this.select(this.options.length - 1); } else if (this.selected < 0) { this.selected = 0; } @@ -271,33 +286,33 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio // Style non-native select mode if (this.styles.listFocusBackground) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { background-color: ${this.styles.listFocusBackground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { background-color: ${this.styles.listFocusBackground} !important; }`); } if (this.styles.listFocusForeground) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused:not(:hover) { color: ${this.styles.listFocusForeground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused:not(:hover) { color: ${this.styles.listFocusForeground} !important; }`); } // Hover foreground - ignore for disabled options if (this.styles.listHoverForeground) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:hover { color: ${this.styles.listHoverForeground} !important; }`); - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: ${this.styles.listActiveSelectionForeground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:hover { color: ${this.styles.listHoverForeground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: ${this.styles.listActiveSelectionForeground} !important; }`); } // Hover background - ignore for disabled options if (this.styles.listHoverBackground) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.option-disabled):not(.focused):hover { background-color: ${this.styles.listHoverBackground} !important; }`); - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: ${this.styles.selectBackground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.option-disabled):not(.focused):hover { background-color: ${this.styles.listHoverBackground} !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: ${this.styles.selectBackground} !important; }`); } // Match quickOpen outline styles - ignore for disabled options if (this.styles.listFocusOutline) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { outline: 1.6px dotted ${this.styles.listFocusOutline} !important; outline-offset: -1.6px !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { outline: 1.6px dotted ${this.styles.listFocusOutline} !important; outline-offset: -1.6px !important; }`); } if (this.styles.listHoverOutline) { - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:hover:not(.focused) { outline: 1.6px dashed ${this.styles.listHoverOutline} !important; outline-offset: -1.6px !important; }`); - content.push(`.monaco-shell .select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { outline: none !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:hover:not(.focused) { outline: 1.6px dashed ${this.styles.listHoverOutline} !important; outline-offset: -1.6px !important; }`); + content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { outline: none !important; }`); } this.styleElement.innerHTML = content.join('\n'); @@ -379,9 +394,12 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio } private renderSelectDropDown(container: HTMLElement): IDisposable { - dom.append(container, this.selectDropDownContainer); + container.appendChild(this.selectDropDownContainer); + this.layoutSelectDropDown(); - return null; + return { + dispose: () => container.removeChild(this.selectDropDownContainer) // remove to take out the CSS rules we add + }; } private layoutSelectDropDown() { @@ -395,9 +413,12 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio const selectWidth = dom.getTotalWidth(this.selectElement); const selectPosition = dom.getDomNodePagePosition(this.selectElement); - // Set container height to max from select bottom to margin above status bar - const statusBarHeight = dom.getTotalHeight(document.getElementById('workbench.parts.statusbar')); - const maxSelectDropDownHeight = (window.innerHeight - selectPosition.top - selectPosition.height - statusBarHeight - SelectBoxList.SELECT_DROPDOWN_BOTTOM_MARGIN); + // Set container height to max from select bottom to margin (default/minBottomMargin) + let maxSelectDropDownHeight = (window.innerHeight - selectPosition.top - selectPosition.height - this.selectBoxOptions.minBottomMargin); + + if (maxSelectDropDownHeight < 0) { + maxSelectDropDownHeight = 0; + } // SetUp list dimensions and layout - account for container padding if (this.selectList) { diff --git a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts index bf96c58774..45b6d8c6a5 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; @@ -17,7 +17,7 @@ export class SelectBoxNative implements ISelectBoxDelegate { public selectElement: HTMLSelectElement; private options: string[]; private selected: number; - private _onDidSelect: Emitter<ISelectData>; + private readonly _onDidSelect: Emitter<ISelectData>; private toDispose: IDisposable[]; private styles: ISelectBoxStyles; @@ -26,7 +26,7 @@ export class SelectBoxNative implements ISelectBoxDelegate { this.toDispose = []; this.selectElement = document.createElement('select'); - this.selectElement.className = 'select-box'; + this.selectElement.className = 'monaco-select-box'; this._onDidSelect = new Emitter<ISelectData>(); @@ -92,6 +92,10 @@ export class SelectBoxNative implements ISelectBoxDelegate { public select(index: number): void { if (index >= 0 && index < this.options.length) { this.selected = index; + } else if (index > this.options.length - 1) { + // Adjust index to end of list + // This could make client out of sync with the select + this.select(this.options.length - 1); } else if (this.selected < 0) { this.selected = 0; } diff --git a/src/vs/base/browser/ui/splitview/grid.ts b/src/vs/base/browser/ui/splitview/grid.ts index 0c915cbf9b..2502285804 100644 --- a/src/vs/base/browser/ui/splitview/grid.ts +++ b/src/vs/base/browser/ui/splitview/grid.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { anyEvent } from 'vs/base/common/event'; +import { Event, anyEvent } from 'vs/base/common/event'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; import { append, $ } from 'vs/base/browser/dom'; import { SplitView, IView } from 'vs/base/browser/ui/splitview/splitview'; diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 88f218ab32..e6de8ed798 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -7,7 +7,7 @@ import 'vs/css!./panelview'; import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter, chain } from 'vs/base/common/event'; +import { Event, Emitter, chain } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -239,7 +239,7 @@ class PanelDraggable implements IDisposable { private _onDidDrop = new Emitter<{ from: Panel, to: Panel }>(); readonly onDidDrop = this._onDidDrop.event; - constructor(private panel: Panel, private context: IDndContext) { + constructor(private panel: Panel, private dnd: IPanelDndController, private context: IDndContext) { panel.draggableElement.draggable = true; domEvent(panel.draggableElement, 'dragstart')(this.onDragStart, this, this.disposables); domEvent(panel.dropTargetElement, 'dragenter')(this.onDragEnter, this, this.disposables); @@ -249,6 +249,12 @@ class PanelDraggable implements IDisposable { } private onDragStart(e: DragEvent): void { + if (!this.dnd.canDrag(this.panel)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + e.dataTransfer.effectAllowed = 'move'; const dragImage = append(document.body, $('.monaco-panel-drag-image', {}, this.panel.draggableElement.textContent)); @@ -263,6 +269,10 @@ class PanelDraggable implements IDisposable { return; } + if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) { + return; + } + this.dragOverCounter++; this.render(); } @@ -272,6 +282,10 @@ class PanelDraggable implements IDisposable { return; } + if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) { + return; + } + this.dragOverCounter--; if (this.dragOverCounter === 0) { @@ -297,7 +311,7 @@ class PanelDraggable implements IDisposable { this.dragOverCounter = 0; this.render(); - if (this.context.draggable !== this) { + if (this.dnd.canDrop(this.context.draggable.panel, this.panel) && this.context.draggable !== this) { this._onDidDrop.fire({ from: this.context.draggable.panel, to: this.panel }); } @@ -319,8 +333,24 @@ class PanelDraggable implements IDisposable { } } -export class IPanelViewOptions { - dnd?: boolean; +export interface IPanelDndController { + canDrag(panel: Panel): boolean; + canDrop(panel: Panel, overPanel: Panel): boolean; +} + +export class DefaultPanelDndController implements IPanelDndController { + + canDrag(panel: Panel): boolean { + return true; + } + + canDrop(panel: Panel, overPanel: Panel): boolean { + return true; + } +} + +export interface IPanelViewOptions { + dnd?: IPanelDndController; } interface IPanelItem { @@ -330,7 +360,7 @@ interface IPanelItem { export class PanelView implements IDisposable { - private dnd: boolean; + private dnd: IPanelDndController | null; private dndContext: IDndContext = { draggable: null }; private el: HTMLElement; private panelItems: IPanelItem[] = []; @@ -343,7 +373,7 @@ export class PanelView implements IDisposable { readonly onDidSashChange: Event<void>; constructor(container: HTMLElement, options: IPanelViewOptions = {}) { - this.dnd = !!options.dnd; + this.dnd = options.dnd; this.el = append(container, $('.monaco-panel-view')); this.splitview = new SplitView(this.el); this.onDidSashChange = this.splitview.onDidSashChange; @@ -358,7 +388,7 @@ export class PanelView implements IDisposable { this.splitview.addView(panel, size, index); if (this.dnd) { - const draggable = new PanelDraggable(panel, this.dndContext); + const draggable = new PanelDraggable(panel, this.dnd, this.dndContext); disposables.push(draggable); draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop, disposables); } diff --git a/src/vs/base/browser/ui/splitview/splitview.css b/src/vs/base/browser/ui/splitview/splitview.css index bd8765cf3c..6d068b0de7 100644 --- a/src/vs/base/browser/ui/splitview/splitview.css +++ b/src/vs/base/browser/ui/splitview/splitview.css @@ -10,15 +10,20 @@ height: 100%; } -.monaco-split-view2 > .split-view-view { +.monaco-split-view2 > .split-view-container { + width: 100%; + height: 100%; +} + +.monaco-split-view2 > .split-view-container > .split-view-view { overflow: hidden; } -.monaco-split-view2.vertical > .split-view-view { +.monaco-split-view2.vertical > .split-view-container > .split-view-view { width: 100%; } -.monaco-split-view2.horizontal > .split-view-view { +.monaco-split-view2.horizontal > .split-view-container > .split-view-view { height: 100%; display: inline-block; } diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index 5fb5e76c46..4153b0aa2a 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -7,9 +7,9 @@ import 'vs/css!./splitview'; import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import Event, { mapEvent, Emitter } from 'vs/base/common/event'; -import types = require('vs/base/common/types'); -import dom = require('vs/base/browser/dom'); +import { Event, mapEvent, Emitter } from 'vs/base/common/event'; +import * as types from 'vs/base/common/types'; +import * as dom from 'vs/base/browser/dom'; import { clamp } from 'vs/base/common/numbers'; import { range, firstIndex } from 'vs/base/common/arrays'; import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; @@ -82,6 +82,7 @@ export class SplitView implements IDisposable { private orientation: Orientation; private el: HTMLElement; + private viewContainer: HTMLElement; private size = 0; private contentSize = 0; private viewItems: IViewItem[] = []; @@ -105,6 +106,10 @@ export class SplitView implements IDisposable { dom.addClass(this.el, 'monaco-split-view2'); dom.addClass(this.el, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal'); container.appendChild(this.el); + + this.viewContainer = document.createElement('div'); + dom.addClass(this.viewContainer, 'split-view-container'); + this.el.appendChild(this.viewContainer); } addView(view: IView, size: number, index = this.viewItems.length): void { @@ -118,13 +123,13 @@ export class SplitView implements IDisposable { const container = dom.$('.split-view-view'); if (index === this.viewItems.length) { - this.el.appendChild(container); + this.viewContainer.appendChild(container); } else { - this.el.insertBefore(container, this.el.children.item(index)); + this.viewContainer.insertBefore(container, this.viewContainer.children.item(index)); } const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size)); - const containerDisposable = toDisposable(() => this.el.removeChild(container)); + const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container)); const disposable = combinedDisposable([onChangeDisposable, containerDisposable]); const layoutContainer = this.orientation === Orientation.VERTICAL @@ -218,9 +223,9 @@ export class SplitView implements IDisposable { this.viewItems.splice(to, 0, viewItem); if (to + 1 < this.viewItems.length) { - this.el.insertBefore(viewItem.container, this.viewItems[to + 1].container); + this.viewContainer.insertBefore(viewItem.container, this.viewItems[to + 1].container); } else { - this.el.appendChild(viewItem.container); + this.viewContainer.appendChild(viewItem.container); } this.layoutViews(); diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index 06cd87ddf2..addb80e3b0 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -6,9 +6,8 @@ 'use strict'; import 'vs/css!./toolbar'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, $ } from 'vs/base/browser/builder'; import { Action, IActionRunner, IAction } from 'vs/base/common/actions'; import { ActionBar, ActionsOrientation, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; import { IContextMenuProvider, DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown'; @@ -45,7 +44,7 @@ export class ToolBar { element.className = 'monaco-toolbar'; container.appendChild(element); - this.actionBar = new ActionBar($(element), { + this.actionBar = new ActionBar(element, { orientation: options.orientation, ariaLabel: options.ariaLabel, actionRunner: options.actionRunner, @@ -94,10 +93,18 @@ export class ToolBar { } } - public getContainer(): Builder { + public getContainer(): HTMLElement { return this.actionBar.getContainer(); } + public getItemsWidth(): number { + let itemsWidth = 0; + for (let i = 0; i < this.actionBar.length(); i++) { + itemsWidth += this.actionBar.getWidth(i); + } + return itemsWidth; + } + public setAriaLabel(label: string): void { this.actionBar.setAriaLabel(label); } diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index f80d1921b5..9756373084 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface ITelemetryData { from?: string; diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 1699b52ceb..7ac7cce54a 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -53,7 +53,7 @@ export function binarySearch<T>(array: T[], key: T, comparator: (op1: T, op2: T) * are located before all elements where p(x) is true. * @returns the least x for which p(x) is true or array.length if no element fullfills the given function. */ -export function findFirst<T>(array: T[], p: (x: T) => boolean): number { +export function findFirstInSorted<T>(array: T[], p: (x: T) => boolean): number { let low = 0, high = array.length; if (high === 0) { return 0; // no children @@ -267,7 +267,7 @@ function topStep<T>(array: T[], compare: (a: T, b: T) => number, result: T[], i: const element = array[i]; if (compare(element, result[n - 1]) < 0) { result.pop(); - const j = findFirst(result, e => compare(element, e) < 0); + const j = findFirstInSorted(result, e => compare(element, e) < 0); result.splice(j, 0, element); } } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index 1a90e0e0fa..68516bde36 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -9,7 +9,7 @@ import * as errors from 'vs/base/common/errors'; import { Promise, TPromise, ValueCallback, ErrorCallback, ProgressCallback } from 'vs/base/common/winjs.base'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; export function isThenable<T>(obj: any): obj is Thenable<T> { @@ -29,10 +29,23 @@ export function asWinJsPromise<T>(callback: (token: CancellationToken) => T | TP return new TPromise<T>((resolve, reject, progress) => { let item = callback(source.token); if (item instanceof TPromise) { - item.then(resolve, reject, progress); + item.then(result => { + source.dispose(); + resolve(result); + }, err => { + source.dispose(); + reject(err); + }, progress); } else if (isThenable<T>(item)) { - item.then(resolve, reject); + item.then(result => { + source.dispose(); + resolve(result); + }, err => { + source.dispose(); + reject(err); + }); } else { + source.dispose(); resolve(item); } }, () => { @@ -320,6 +333,10 @@ export function timeout(n: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, n)); } +function isWinJSPromise(candidate: any): candidate is TPromise { + return TPromise.is(candidate) && typeof (<TPromise>candidate).done === 'function'; +} + /** * Returns a new promise that joins the provided promise. Upon completion of * the provided promise the provided function will always be called. This @@ -327,28 +344,37 @@ export function timeout(n: number): Promise<void> { * @param promise a promise * @param f a function that will be call in the success and error case. */ -export function always<T>(promise: TPromise<T>, f: Function): TPromise<T> { - return new TPromise<T>((c, e, p) => { - promise.done((result) => { - try { - f(result); - } catch (e1) { - errors.onUnexpectedError(e1); - } - c(result); - }, (err) => { - try { - f(err); - } catch (e1) { - errors.onUnexpectedError(e1); - } - e(err); - }, (progress) => { - p(progress); +export function always<T>(thenable: TPromise<T>, f: Function): TPromise<T>; +export function always<T>(promise: Thenable<T>, f: Function): Thenable<T>; +export function always<T>(winjsPromiseOrThenable: Thenable<T> | TPromise<T>, f: Function): TPromise<T> | Thenable<T> { + if (isWinJSPromise(winjsPromiseOrThenable)) { + return new TPromise<T>((c, e, p) => { + winjsPromiseOrThenable.done((result) => { + try { + f(result); + } catch (e1) { + errors.onUnexpectedError(e1); + } + c(result); + }, (err) => { + try { + f(err); + } catch (e1) { + errors.onUnexpectedError(e1); + } + e(err); + }, (progress) => { + p(progress); + }); + }, () => { + winjsPromiseOrThenable.cancel(); }); - }, () => { - promise.cancel(); - }); + + } else { + // simple + winjsPromiseOrThenable.then(_ => f(), _ => f()); + return winjsPromiseOrThenable; + } } /** @@ -424,7 +450,7 @@ export class Limiter<T> { private runningPromises: number; private maxDegreeOfParalellism: number; private outstandingPromises: ILimitedTaskFactory[]; - private _onFinished: Emitter<void>; + private readonly _onFinished: Emitter<void>; constructor(maxDegreeOfParalellism: number) { this.maxDegreeOfParalellism = maxDegreeOfParalellism; diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index b14264dda8..365e2fa548 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; export interface CancellationToken { @@ -45,7 +45,7 @@ class MutableToken implements CancellationToken { this._isCancelled = true; if (this._emitter) { this._emitter.fire(undefined); - this._emitter = undefined; + this.dispose(); } } } @@ -63,6 +63,13 @@ class MutableToken implements CancellationToken { } return this._emitter.event; } + + public dispose(): void { + if (this._emitter) { + this._emitter.dispose(); + this._emitter = undefined; + } + } } export class CancellationTokenSource { @@ -92,6 +99,13 @@ export class CancellationTokenSource { } dispose(): void { - this.cancel(); + if (!this._token) { + // ensure to initialize with an empty token if we had none + this._token = CancellationToken.None; + + } else if (this._token instanceof MutableToken) { + // actually dispose + this._token.dispose(); + } } } diff --git a/src/vs/base/common/decorators.ts b/src/vs/base/common/decorators.ts index f06ad06528..40263f86c7 100644 --- a/src/vs/base/common/decorators.ts +++ b/src/vs/base/common/decorators.ts @@ -33,6 +33,10 @@ export function memoize(target: any, key: string, descriptor: any) { if (typeof descriptor.value === 'function') { fnKey = 'value'; fn = descriptor.value; + + if (fn.length !== 0) { + console.warn('Memoize should only be used in functions with zero parameters'); + } } else if (typeof descriptor.get === 'function') { fnKey = 'get'; fn = descriptor.get; @@ -58,13 +62,27 @@ export function memoize(target: any, key: string, descriptor: any) { }; } -export function debounce(delay: number): Function { +export interface IDebouceReducer<T> { + (previousValue: T, ...args: any[]): T; +} + +export function debounce<T>(delay: number, reducer?: IDebouceReducer<T>, initialValueProvider?: () => T): Function { return createDecorator((fn, key) => { const timerKey = `$debounce$${key}`; + let result = initialValueProvider ? initialValueProvider() : void 0; return function (this: any, ...args: any[]) { clearTimeout(this[timerKey]); - this[timerKey] = setTimeout(() => fn.apply(this, args), delay); + + if (reducer) { + result = reducer(result, ...args); + args = [result]; + } + + this[timerKey] = setTimeout(() => { + fn.apply(this, args); + result = initialValueProvider ? initialValueProvider() : void 0; + }, delay); }; }); } \ No newline at end of file diff --git a/src/vs/base/common/errorMessage.ts b/src/vs/base/common/errorMessage.ts index d9bc18e6a0..198d24f754 100644 --- a/src/vs/base/common/errorMessage.ts +++ b/src/vs/base/common/errorMessage.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); -import types = require('vs/base/common/types'); -import arrays = require('vs/base/common/arrays'); +import * as nls from 'vs/nls'; +import * as types from 'vs/base/common/types'; +import * as arrays from 'vs/base/common/arrays'; function exceptionToErrorMessage(exception: any, verbose: boolean): string { if (exception.message) { diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index ea0f005a45..905a14fb96 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -14,17 +14,15 @@ import { LinkedList } from 'vs/base/common/linkedList'; * To an event a function with one or zero parameters * can be subscribed. The event is the subscriber function itself. */ -interface Event<T> { +export interface Event<T> { (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable; } -namespace Event { +export namespace Event { const _disposable = { dispose() { } }; export const None: Event<any> = function () { return _disposable; }; } -export default Event; - type Listener = [Function, any] | Function; export interface EmitterOptions { @@ -163,7 +161,7 @@ export class Emitter<T> { export class EventMultiplexer<T> implements IDisposable { - private emitter: Emitter<T>; + private readonly emitter: Emitter<T>; private hasListeners = false; private events: { event: Event<T>; listener: IDisposable; }[] = []; @@ -281,7 +279,7 @@ export function debounceEvent<I, O>(event: Event<I>, merger: (last: O, event: I) let subscription: IDisposable; let output: O = undefined; - let handle: number = undefined; + let handle: any = undefined; let numDebouncedCalls = 0; const emitter = new Emitter<O>({ @@ -367,6 +365,7 @@ export interface IChainableEvent<T> { map<O>(fn: (i: T) => O): IChainableEvent<O>; forEach(fn: (i: T) => void): IChainableEvent<T>; filter(fn: (e: T) => boolean): IChainableEvent<T>; + latch(): IChainableEvent<T>; on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable; } @@ -400,6 +399,10 @@ class ChainableEvent<T> implements IChainableEvent<T> { return new ChainableEvent(filterEvent(this._event, fn)); } + latch(): IChainableEvent<T> { + return new ChainableEvent(latch(this._event)); + } + on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) { return this._event(listener, thisArgs, disposables); } @@ -536,3 +539,15 @@ export function fromNodeEventEmitter<T>(emitter: NodeEventEmitter, eventName: st return result.event; } + +export function latch<T>(event: Event<T>): Event<T> { + let firstCall = true; + let cache: T; + + return filterEvent(event, value => { + let shouldEmit = firstCall || value !== cache; + firstCall = false; + cache = value; + return shouldEmit; + }); +} \ No newline at end of file diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index 525727bff2..fbd14dce7c 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import strings = require('vs/base/common/strings'); +import * as strings from 'vs/base/common/strings'; import { LRUCache } from 'vs/base/common/map'; import { CharCode } from 'vs/base/common/charCode'; @@ -50,7 +50,7 @@ function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: s let matches: boolean; if (ignoreCase) { - matches = strings.beginsWithIgnoreCase(wordToMatchAgainst, word); + matches = strings.startsWithIgnoreCase(wordToMatchAgainst, word); } else { matches = wordToMatchAgainst.indexOf(word) === 0; } diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index 490564f755..91720fcad0 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import arrays = require('vs/base/common/arrays'); -import strings = require('vs/base/common/strings'); -import paths = require('vs/base/common/paths'); +import * as arrays from 'vs/base/common/arrays'; +import * as strings from 'vs/base/common/strings'; +import * as paths from 'vs/base/common/paths'; import { LRUCache } from 'vs/base/common/map'; import { CharCode } from 'vs/base/common/charCode'; import { TPromise } from 'vs/base/common/winjs.base'; diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index cbdc9f6624..ce55554d65 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -65,6 +65,11 @@ export class HistoryNavigator<T> implements INavigator<T> { return this._navigator.last(); } + public clear(): void { + this._initialize([]); + this._onChange(); + } + private _onChange() { this._reduceToLimit(); this._navigator = new ArrayNavigator(this._elements); diff --git a/src/vs/base/common/jsonFormatter.ts b/src/vs/base/common/jsonFormatter.ts index 7c3e808c0c..d7d844dd0b 100644 --- a/src/vs/base/common/jsonFormatter.ts +++ b/src/vs/base/common/jsonFormatter.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Json = require('./json'); +import * as Json from './json'; export interface FormattingOptions { /** diff --git a/src/vs/base/common/keybindingLabels.ts b/src/vs/base/common/keybindingLabels.ts index c31bcf079e..16ec6fbd8e 100644 --- a/src/vs/base/common/keybindingLabels.ts +++ b/src/vs/base/common/keybindingLabels.ts @@ -54,10 +54,10 @@ export const UILabelProvider = new ModifierLabelProvider( separator: '', }, { - ctrlKey: nls.localize('ctrlKey', "Ctrl"), - shiftKey: nls.localize('shiftKey', "Shift"), - altKey: nls.localize('altKey', "Alt"), - metaKey: nls.localize('windowsKey', "Windows"), + ctrlKey: nls.localize({ key: 'ctrlKey', comment: ['This is the short form for the Control key on the keyboard'] }, "Ctrl"), + shiftKey: nls.localize({ key: 'shiftKey', comment: ['This is the short form for the Shift key on the keyboard'] }, "Shift"), + altKey: nls.localize({ key: 'altKey', comment: ['This is the short form for the Alt key on the keyboard'] }, "Alt"), + metaKey: nls.localize({ key: 'windowsKey', comment: ['This is the short form for the Windows key on the keyboard'] }, "Windows"), separator: '+', } ); @@ -67,17 +67,17 @@ export const UILabelProvider = new ModifierLabelProvider( */ export const AriaLabelProvider = new ModifierLabelProvider( { - ctrlKey: nls.localize('ctrlKey.long', "Control"), - shiftKey: nls.localize('shiftKey.long', "Shift"), - altKey: nls.localize('altKey.long', "Alt"), - metaKey: nls.localize('cmdKey.long', "Command"), + ctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, "Control"), + shiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, "Shift"), + altKey: nls.localize({ key: 'altKey.long', comment: ['This is the long form for the Alt key on the keyboard'] }, "Alt"), + metaKey: nls.localize({ key: 'cmdKey.long', comment: ['This is the long form for the Command key on the keyboard'] }, "Command"), separator: '+', }, { - ctrlKey: nls.localize('ctrlKey.long', "Control"), - shiftKey: nls.localize('shiftKey.long', "Shift"), - altKey: nls.localize('altKey.long', "Alt"), - metaKey: nls.localize('windowsKey.long', "Windows"), + ctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, "Control"), + shiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, "Shift"), + altKey: nls.localize({ key: 'altKey.long', comment: ['This is the long form for the Alt key on the keyboard'] }, "Alt"), + metaKey: nls.localize({ key: 'windowsKey.long', comment: ['This is the long form for the Windows key on the keyboard'] }, "Windows"), separator: '+', } ); diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 6d8a898c5c..13f7759658 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -5,10 +5,10 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import platform = require('vs/base/common/platform'); -import { nativeSep, normalize, isEqualOrParent, isEqual, basename as pathsBasename, join } from 'vs/base/common/paths'; -import { endsWith, ltrim } from 'vs/base/common/strings'; +import { nativeSep, normalize, basename as pathsBasename, join, sep } from 'vs/base/common/paths'; +import { endsWith, ltrim, equalsIgnoreCase, startsWithIgnoreCase, rtrim, startsWith } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; +import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform'; export interface IWorkspaceFolderProvider { getWorkspaceFolder(resource: URI): { uri: URI }; @@ -30,6 +30,7 @@ export function getPathLabel(resource: URI | string, rootProvider?: IWorkspaceFo resource = URI.file(resource); } + // return early if the resource is neither file:// nor untitled:// if (resource.scheme !== Schemas.file && resource.scheme !== Schemas.untitled) { return resource.with({ query: null, fragment: null }).toString(true); } @@ -40,7 +41,7 @@ export function getPathLabel(resource: URI | string, rootProvider?: IWorkspaceFo const hasMultipleRoots = rootProvider.getWorkspace().folders.length > 1; let pathLabel: string; - if (isEqual(baseResource.uri.fsPath, resource.fsPath, !platform.isLinux /* ignorecase */)) { + if (isLinux ? baseResource.uri.fsPath === resource.fsPath : equalsIgnoreCase(baseResource.uri.fsPath, resource.fsPath)) { pathLabel = ''; // no label if pathes are identical } else { pathLabel = normalize(ltrim(resource.fsPath.substr(baseResource.uri.fsPath.length), nativeSep), true); @@ -61,7 +62,7 @@ export function getPathLabel(resource: URI | string, rootProvider?: IWorkspaceFo // normalize and tildify (macOS, Linux only) let res = normalize(resource.fsPath, true); - if (!platform.isWindows && userHomeProvider) { + if (!isWindows && userHomeProvider) { res = tildify(res, userHomeProvider.userHome); } @@ -88,7 +89,7 @@ export function getBaseLabel(resource: URI | string): string { } function hasDriveLetter(path: string): boolean { - return platform.isWindows && path && path[1] === ':'; + return isWindows && path && path[1] === ':'; } export function normalizeDriveLetter(path: string): string { @@ -99,9 +100,22 @@ export function normalizeDriveLetter(path: string): string { return path; } +let normalizedUserHomeCached: { original: string; normalized: string } = Object.create(null); export function tildify(path: string, userHome: string): string { - if (path && (platform.isMacintosh || platform.isLinux) && isEqualOrParent(path, userHome, !platform.isLinux /* ignorecase */)) { - path = `~${path.substr(userHome.length)}`; + if (isWindows || !path || !userHome) { + return path; // unsupported + } + + // Keep a normalized user home path as cache to prevent accumulated string creation + let normalizedUserHome = normalizedUserHomeCached.original === userHome ? normalizedUserHomeCached.normalized : void 0; + if (!normalizedUserHome) { + normalizedUserHome = `${rtrim(userHome, sep)}${sep}`; + normalizedUserHomeCached = { original: userHome, normalized: normalizedUserHome }; + } + + // Linux: case sensitive, macOS: case insensitive + if (isLinux ? startsWith(path, normalizedUserHome) : startsWithIgnoreCase(path, normalizedUserHome)) { + path = `~/${path.substr(normalizedUserHome.length)}`; } return path; @@ -325,7 +339,7 @@ export function template(template: string, values: { [key: string]: string | ISe const left = segments[index - 1]; const right = segments[index + 1]; - return [left, right].every(segment => segment && segment.type === Type.VARIABLE && segment.value.length > 0); + return [left, right].every(segment => segment && (segment.type === Type.VARIABLE || segment.type === Type.TEXT) && segment.value.length > 0); } // accept any TEXT and VARIABLE @@ -340,7 +354,7 @@ export function template(template: string, values: { [key: string]: string | ISe * - macOS: Unsupported (replace && with empty string) */ export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean): string { - if (platform.isMacintosh || forceDisableMnemonics) { + if (isMacintosh || forceDisableMnemonics) { return label.replace(/\(&&\w\)|&&/g, ''); } @@ -354,11 +368,11 @@ export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean * - macOS: Unsupported (replace && with empty string) */ export function mnemonicButtonLabel(label: string): string { - if (platform.isMacintosh) { + if (isMacintosh) { return label.replace(/\(&&\w\)|&&/g, ''); } - return label.replace(/&&/g, platform.isWindows ? '&' : '_'); + return label.replace(/&&/g, isWindows ? '&' : '_'); } export function unmnemonicLabel(label: string): string { diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 9b689d9996..f24bc0959f 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -368,10 +368,12 @@ export class TernarySearchTree<E> { export class ResourceMap<T> { - protected map: Map<string, T>; + protected readonly map: Map<string, T>; + protected readonly ignoreCase?: boolean; - constructor(private ignoreCase?: boolean) { + constructor() { this.map = new Map<string, T>(); + this.ignoreCase = false; // in the future this should be an uri-comparator } public set(resource: URI, value: T): void { @@ -414,18 +416,10 @@ export class ResourceMap<T> { return key; } -} - -export class StrictResourceMap<T> extends ResourceMap<T> { - - constructor() { - super(); - } public keys(): URI[] { - return keys(this.map).map(key => URI.parse(key)); + return keys(this.map).map(URI.parse); } - } // We should fold BoundedMap and LinkedMap. See https://github.com/Microsoft/vscode/issues/28496 @@ -743,6 +737,24 @@ export class LinkedMap<K, V> { this._tail = item; } } + + public toJSON(): [K, V][] { + const data: [K, V][] = []; + + this.forEach((value, key) => { + data.push([key, value]); + }); + + return data; + } + + public fromJSON(data: [K, V][]): void { + this.clear(); + + for (const [key, value] of data) { + this.set(key, value); + } + } } export class LRUCache<K, V> extends LinkedMap<K, V> { diff --git a/src/vs/base/common/marked/OSSREADME.json b/src/vs/base/common/marked/OSSREADME.json index 010e42bd7b..42d526944b 100644 --- a/src/vs/base/common/marked/OSSREADME.json +++ b/src/vs/base/common/marked/OSSREADME.json @@ -3,6 +3,6 @@ [{ "name": "chjj-marked", "repositoryURL": "https://github.com/npmcomponent/chjj-marked", - "version": "0.3.12", + "version": "0.3.18", "license": "MIT" }] diff --git a/src/vs/base/common/marked/marked.d.ts b/src/vs/base/common/marked/marked.d.ts index c2ccb5d127..dd4bd8f05d 100644 --- a/src/vs/base/common/marked/marked.d.ts +++ b/src/vs/base/common/marked/marked.d.ts @@ -73,7 +73,7 @@ export interface MarkedStatic { export interface Renderer { prototype: MarkedRenderer; - new (): MarkedRenderer; + new(): MarkedRenderer; } export interface MarkedRenderer { diff --git a/src/vs/base/common/marked/marked.js b/src/vs/base/common/marked/marked.js index 332f187454..ca72ea8d6d 100644 --- a/src/vs/base/common/marked/marked.js +++ b/src/vs/base/common/marked/marked.js @@ -1,10 +1,1406 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ -define(['./raw.marked'], function (marked) { - return { - marked: marked - }; -}); \ No newline at end of file +var __marked_exports; + +;(function(root) { +'use strict'; + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + table: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/, + text: /^[^\n]+/ +}; + +block._label = /(?:\\[\[\]]|[^\[\]])+/; +block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/; +block.def = edit(block.def) + .replace('label', block._label) + .replace('title', block._title) + .getRegex(); + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = edit(block.item, 'gm') + .replace(/bull/g, block.bullet) + .getRegex(); + +block.list = edit(block.list) + .replace(/bull/g, block.bullet) + .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') + .replace('def', '\\n+(?=' + block.def.source + ')') + .getRegex(); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b'; + +block.html = edit(block.html) + .replace('comment', /<!--[\s\S]*?-->/) + .replace('closed', /<(tag)[\s\S]+?<\/\1>/) + .replace('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>\s]*)*?\/?>/) + .replace(/tag/g, block._tag) + .getRegex(); + +block.paragraph = edit(block.paragraph) + .replace('hr', block.hr) + .replace('heading', block.heading) + .replace('lheading', block.lheading) + .replace('tag', '<' + block._tag) + .getRegex(); + +block.blockquote = edit(block.blockquote) + .replace('paragraph', block.paragraph) + .getRegex(); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ +}); + +block.gfm.paragraph = edit(block.paragraph) + .replace('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + .getRegex(); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top) { + src = src.replace(/^ +$/gm, ''); + var next, + loose, + cap, + bull, + b, + item, + space, + i, + tag, + l, + isordered; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + isordered = bull.length > 1; + + this.tokens.push({ + type: 'list_start', + ordered: isordered, + start: isordered ? +bull : '' + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } + + // def + if (top && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); + tag = cap[1].toLowerCase(); + if (!this.tokens.links[tag]) { + this.tokens.links[tag] = { + href: cap[2], + title: cap[3] + }; + } + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noop, + tag: /^<!--[\s\S]*?-->|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/\s]*)*?\/?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/ +}; + +inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; +inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; + +inline.autolink = edit(inline.autolink) + .replace('scheme', inline._scheme) + .replace('email', inline._email) + .getRegex() + +inline._inside = /(?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/; +inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; + +inline.link = edit(inline.link) + .replace('inside', inline._inside) + .replace('href', inline._href) + .getRegex(); + +inline.reflink = edit(inline.reflink) + .replace('inside', inline._inside) + .getRegex(); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: edit(inline.escape).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) + .replace('email', inline._email) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: edit(inline.text) + .replace(']|', '~]|') + .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') + .getRegex() +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: edit(inline.br).replace('{2,}', '*').getRegex(), + text: edit(inline.gfm.text).replace('{2,}', '*').getRegex() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer(); + this.renderer.options = this.options; + + if (!this.links) { + throw new Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '', + link, + text, + href, + cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(this.mangle(cap[1])); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + cap[0] = this.rules._backpedal.exec(cap[0])[0]; + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(cap[0]); + href = 'mailto:' + text; + } else { + text = escape(cap[0]); + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^<a /i.test(cap[0])) { + this.inLink = true; + } else if (this.inLink && /^<\/a>/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2].trim(), true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href), + title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; + var out = '', + l = text.length, + i = 0, + ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || {}; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '<pre><code>' + + (escaped ? code : escape(code, true)) + + '\n</code></pre>'; + } + + return '<pre><code class="' + + this.options.langPrefix + + escape(lang, true) + + '">' + + (escaped ? code : escape(code, true)) + + '\n</code></pre>\n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '<blockquote>\n' + quote + '</blockquote>\n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '<h' + + level + + ' id="' + + this.options.headerPrefix + + raw.toLowerCase().replace(/[^\w]+/g, '-') + + '">' + + text + + '</h' + + level + + '>\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '<hr/>\n' : '<hr>\n'; +}; + +Renderer.prototype.list = function(body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startatt + '>\n' + body + '</' + type + '>\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '<li>' + text + '</li>\n'; +}; + +Renderer.prototype.paragraph = function(text) { + return '<p>' + text + '</p>\n'; +}; + +Renderer.prototype.table = function(header, body) { + return '<table>\n' + + '<thead>\n' + + header + + '</thead>\n' + + '<tbody>\n' + + body + + '</tbody>\n' + + '</table>\n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '<tr>\n' + content + '</tr>\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '</' + type + '>\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '<strong>' + text + '</strong>'; +}; + +Renderer.prototype.em = function(text) { + return '<em>' + text + '</em>'; +}; + +Renderer.prototype.codespan = function(text) { + return '<code>' + text + '</code>'; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '<br/>' : '<br>'; +}; + +Renderer.prototype.del = function(text) { + return '<del>' + text + '</del>'; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return text; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return text; + } + } + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '<a href="' + href + '"'; + if (title) { + out += ' title="' + title + '"'; + } + out += '>' + text + '</a>'; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '<img src="' + href + '" alt="' + text + '"'; + if (title) { + out += ' title="' + title + '"'; + } + out += this.options.xhtml ? '/>' : '>'; + return out; +}; + +Renderer.prototype.text = function(text) { + return text; +}; + +/** + * TextRenderer + * returns only the textual part of the token + */ + +function TextRenderer() {} + +// no need for block level renderers + +TextRenderer.prototype.strong = +TextRenderer.prototype.em = +TextRenderer.prototype.codespan = +TextRenderer.prototype.del = +TextRenderer.prototype.text = function (text) { + return text; +} + +TextRenderer.prototype.link = +TextRenderer.prototype.image = function(href, title, text) { + return '' + text; +} + +TextRenderer.prototype.br = function() { + return ''; +} + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options) { + var parser = new Parser(options); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options); + // use an InlineLexer with a TextRenderer to extract pure text + this.inlineText = new InlineLexer( + src.links, + merge({}, this.options, {renderer: new TextRenderer()}) + ); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + unescape(this.inlineText.output(this.token.text))); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '', + body = '', + i, + row, + cell, + j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + body = ''; + var ordered = this.token.ordered, + start = this.token.start; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered, start); + } + case 'list_item_start': { + body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function edit(regex, opt) { + regex = regex.source; + opt = opt || ''; + return { + replace: function(name, val) { + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return this; + }, + getRegex: function() { + return new RegExp(regex, opt); + } + }; +} + +function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (/^[^:]+:\/*[^/]*$/.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); + } + } + base = baseUrls[' ' + base]; + + if (href.slice(0, 2) === '//') { + return base.replace(/:[\s\S]*/, ':') + href; + } else if (href.charAt(0) === '/') { + return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; + } else { + return base + href; + } +} +var baseUrls = {}; +var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1, + target, + key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + +/** + * Marked + */ + +function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected'); + } + + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight, + tokens, + pending, + i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if ((opt || marked.defaults).silent) { + return '<p>An error occurred:</p><pre>' + + escape(e.message + '', true) + + '</pre>'; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer(), + xhtml: false, + baseUrl: null +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; +marked.TextRenderer = TextRenderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +__marked_exports = marked; + +}).call(this); + +// ESM-comment-begin +define([], function() { + return { + marked: __marked_exports + }; +}); +// ESM-comment-end + +// ESM-uncomment-begin +// export var marked = __marked_exports; +// export var Parser = __marked_exports.Parser; +// export var parser = __marked_exports.parser; +// export var Renderer = __marked_exports.Renderer; +// export var TextRenderer = __marked_exports.TextRenderer; +// export var Lexer = __marked_exports.Lexer; +// export var lexer = __marked_exports.lexer; +// export var InlineLexer = __marked_exports.InlineLexer; +// export var inlineLexer = __marked_exports.inlineLexer; +// export var parse = __marked_exports.parse; +// ESM-uncomment-end diff --git a/src/vs/base/common/marked/raw.marked.js b/src/vs/base/common/marked/raw.marked.js deleted file mode 100644 index d00c4e2bb5..0000000000 --- a/src/vs/base/common/marked/raw.marked.js +++ /dev/null @@ -1,1388 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - */ - -// TODO MonacoChange: we have our own way of defining modules -// ;(function() { -// END MonacoChange - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^( {4}[^\n]+\n*)+/, - fences: noop, - hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - nptable: noop, - blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, - list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, - table: noop, - lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, - paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/, - text: /^[^\n]+/ -}; - -block._label = /(?:\\[\[\]]|[^\[\]])+/; -block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/; -block.def = replace(block.def) - ('label', block._label) - ('title', block._title) - (); - -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; -block.item = replace(block.item, 'gm') - (/bull/g, block.bullet) - (); - -block.list = replace(block.list) - (/bull/g, block.bullet) - ('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') - ('def', '\\n+(?=' + block.def.source + ')') - (); - -block._tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b'; - -block.html = replace(block.html) - ('comment', /<!--[\s\S]*?-->/) - ('closed', /<(tag)[\s\S]+?<\/\1>/) - ('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>]*)*?\/?>/) - (/tag/g, block._tag) - (); - -block.paragraph = replace(block.paragraph) - ('hr', block.hr) - ('heading', block.heading) - ('lheading', block.lheading) - ('tag', '<' + block._tag) - (); - -block.blockquote = replace(block.blockquote) - ('paragraph', block.paragraph) - (); - -/** - * Normal Block Grammar - */ - -block.normal = merge({}, block); - -/** - * GFM Block Grammar - */ - -block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, - paragraph: /^/, - heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ -}); - -block.gfm.paragraph = replace(block.paragraph) - ('(?!', '(?!' - + block.gfm.fences.source.replace('\\1', '\\2') + '|' - + block.list.source.replace('\\1', '\\3') + '|') - (); - -/** - * GFM + Tables Block Grammar - */ - -block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ -}); - -/** - * Block Lexer - */ - -function Lexer(options) { - this.tokens = []; - this.tokens.links = {}; - this.options = options || marked.defaults; - this.rules = block.normal; - - if (this.options.gfm) { - if (this.options.tables) { - this.rules = block.tables; - } else { - this.rules = block.gfm; - } - } -} - -/** - * Expose Block Rules - */ - -Lexer.rules = block; - -/** - * Static Lex Method - */ - -Lexer.lex = function (src, options) { - var lexer = new Lexer(options); - return lexer.lex(src); -}; - -/** - * Preprocessing - */ - -Lexer.prototype.lex = function (src) { - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' ') - .replace(/\u00a0/g, ' ') - .replace(/\u2424/g, '\n'); - - return this.token(src, true); -}; - -/** - * Lexing - */ - -Lexer.prototype.token = function (src, top) { - var src = src.replace(/^ +$/gm, '') - , next - , loose - , cap - , bull - , b - , item - , space - , i - , tag - , l; - - while (src) { - // newline - if (cap = this.rules.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: !this.options.pedantic - ? cap.replace(/\n+$/, '') - : cap - }); - continue; - } - - // fences (gfm) - if (cap = this.rules.fences.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] || '' - }); - continue; - } - - // heading - if (cap = this.rules.heading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // hr - if (cap = this.rules.hr.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - if (cap = this.rules.blockquote.exec(src)) { - src = src.substring(cap[0].length); - - this.tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top); - - this.tokens.push({ - type: 'blockquote_end' - }); - - continue; - } - - // list - if (cap = this.rules.list.exec(src)) { - src = src.substring(cap[0].length); - bull = cap[2]; - - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); - - // Get each top-level item. - cap = cap[0].match(this.rules.item); - - next = false; - l = cap.length; - i = 0; - - for (; i < l; i++) { - item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = !this.options.pedantic - ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') - : item.replace(/^ {1,4}/gm, ''); - } - - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - b = block.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; - } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item.charAt(item.length - 1) === '\n'; - if (!loose) loose = next; - } - - this.tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); - - // Recurse. - this.token(item, false); - - this.tokens.push({ - type: 'list_item_end' - }); - } - - this.tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - if (cap = this.rules.html.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize - ? 'paragraph' - : 'html', - pre: !this.options.sanitizer - && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] - }); - continue; - } - - // def - if (top && (cap = this.rules.def.exec(src))) { - src = src.substring(cap[0].length); - if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); - tag = cap[1].toLowerCase(); - if (!this.tokens.links[tag]) { - this.tokens.links[tag] = { - href: cap[2], - title: cap[3] - }; - } - continue; - } - - // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i] - .replace(/^ *\| *| *\| *$/g, '') - .split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // lheading - if (cap = this.rules.lheading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // top-level paragraph - if (top && (cap = this.rules.paragraph.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1].charAt(cap[1].length - 1) === '\n' - ? cap[1].slice(0, -1) - : cap[1] - }); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return this.tokens; -}; - -/** - * Inline-Level Grammar - */ - -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, - url: noop, - tag: /^<!--[\s\S]*?-->|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/]*)*?\/?>/, - link: /^!?\[(inside)\]\(href\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|\\[\[\]]|[^\[\]])*)\]/, - strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/, - code: /^(`+)(\s*)([\s\S]*?[^`]?)\2\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - del: noop, - text: /^[\s\S]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/ -}; - -inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; -inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; - -inline.autolink = replace(inline.autolink) - ('scheme', inline._scheme) - ('email', inline._email) - () - -inline._inside = /(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/; -inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; - -inline.link = replace(inline.link) - ('inside', inline._inside) - ('href', inline._href) - (); - -inline.reflink = replace(inline.reflink) - ('inside', inline._inside) - (); - -/** - * Normal Inline Grammar - */ - -inline.normal = merge({}, inline); - -/** - * Pedantic Inline Grammar - */ - -inline.pedantic = merge({}, inline.normal, { - strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, - em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ -}); - -/** - * GFM Inline Grammar - */ - -inline.gfm = merge({}, inline.normal, { - escape: replace(inline.escape)('])', '~|])')(), - url: replace(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) - ('email', inline._email) - (), - _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, - del: /^~~(?=\S)([\s\S]*?\S)~~/, - text: replace(inline.text) - (']|', '~]|') - ('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') - () -}); - -/** - * GFM + Line Breaks Inline Grammar - */ - -inline.breaks = merge({}, inline.gfm, { - br: replace(inline.br)('{2,}', '*')(), - text: replace(inline.gfm.text)('{2,}', '*')() -}); - -/** - * Inline Lexer & Compiler - */ - -function InlineLexer(links, options) { - this.options = options || marked.defaults; - this.links = links; - this.rules = inline.normal; - this.renderer = this.options.renderer || new Renderer; - this.renderer.options = this.options; - - if (!this.links) { - throw new - Error('Tokens array requires a `links` property.'); - } - - if (this.options.gfm) { - if (this.options.breaks) { - this.rules = inline.breaks; - } else { - this.rules = inline.gfm; - } - } else if (this.options.pedantic) { - this.rules = inline.pedantic; - } -} - -/** - * Expose Inline Rules - */ - -InlineLexer.rules = inline; - -/** - * Static Lexing/Compiling Method - */ - -InlineLexer.output = function (src, links, options) { - var inline = new InlineLexer(links, options); - return inline.output(src); -}; - -/** - * Lexing/Compiling - */ - -InlineLexer.prototype.output = function (src) { - var out = '' - , link - , text - , href - , cap; - - while (src) { - // escape - if (cap = this.rules.escape.exec(src)) { - src = src.substring(cap[0].length); - out += cap[1]; - continue; - } - - // autolink - if (cap = this.rules.autolink.exec(src)) { - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = escape(this.mangle(cap[1])); - href = 'mailto:' + text; - } else { - text = escape(cap[1]); - href = text; - } - out += this.renderer.link(href, null, text); - continue; - } - - // url (gfm) - if (!this.inLink && (cap = this.rules.url.exec(src))) { - cap[0] = this.rules._backpedal.exec(cap[0])[0]; - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = escape(cap[0]); - href = 'mailto:' + text; - } else { - text = escape(cap[0]); - if (cap[1] === 'www.') { - href = 'http://' + text; - } else { - href = text; - } - } - out += this.renderer.link(href, null, text); - continue; - } - - // tag - if (cap = this.rules.tag.exec(src)) { - if (!this.inLink && /^<a /i.test(cap[0])) { - this.inLink = true; - } else if (this.inLink && /^<\/a>/i.test(cap[0])) { - this.inLink = false; - } - src = src.substring(cap[0].length); - out += this.options.sanitize - ? this.options.sanitizer - ? this.options.sanitizer(cap[0]) - : escape(cap[0]) - : cap[0] - continue; - } - - // link - if (cap = this.rules.link.exec(src)) { - src = src.substring(cap[0].length); - this.inLink = true; - out += this.outputLink(cap, { - href: cap[2], - title: cap[3] - }); - this.inLink = false; - continue; - } - - // reflink, nolink - if ((cap = this.rules.reflink.exec(src)) - || (cap = this.rules.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = this.links[link.toLowerCase()]; - if (!link || !link.href) { - out += cap[0].charAt(0); - src = cap[0].substring(1) + src; - continue; - } - this.inLink = true; - out += this.outputLink(cap, link); - this.inLink = false; - continue; - } - - // strong - if (cap = this.rules.strong.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.strong(this.output(cap[2] || cap[1])); - continue; - } - - // em - if (cap = this.rules.em.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.em(this.output(cap[2] || cap[1])); - continue; - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.codespan(escape(cap[3].trim(), true)); - continue; - } - - // br - if (cap = this.rules.br.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.br(); - continue; - } - - // del (gfm) - if (cap = this.rules.del.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.del(this.output(cap[1])); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.text(escape(this.smartypants(cap[0]))); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return out; -}; - -/** - * Compile Link - */ - -InlineLexer.prototype.outputLink = function (cap, link) { - var href = escape(link.href) - , title = link.title ? escape(link.title) : null; - - return cap[0].charAt(0) !== '!' - ? this.renderer.link(href, title, this.output(cap[1])) - : this.renderer.image(href, title, escape(cap[1])); -}; - -/** - * Smartypants Transformations - */ - -InlineLexer.prototype.smartypants = function (text) { - if (!this.options.smartypants) return text; - return text - // em-dashes - .replace(/---/g, '\u2014') - // en-dashes - .replace(/--/g, '\u2013') - // opening singles - .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') - // closing singles & apostrophes - .replace(/'/g, '\u2019') - // opening doubles - .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') - // closing doubles - .replace(/"/g, '\u201d') - // ellipses - .replace(/\.{3}/g, '\u2026'); -}; - -/** - * Mangle Links - */ - -InlineLexer.prototype.mangle = function (text) { - if (!this.options.mangle) return text; - var out = '' - , l = text.length - , i = 0 - , ch; - - for (; i < l; i++) { - ch = text.charCodeAt(i); - if (Math.random() > 0.5) { - ch = 'x' + ch.toString(16); - } - out += '&#' + ch + ';'; - } - - return out; -}; - -/** - * Renderer - */ - -function Renderer(options) { - this.options = options || {}; -} - -Renderer.prototype.code = function (code, lang, escaped) { - if (this.options.highlight) { - var out = this.options.highlight(code, lang); - if (out != null && out !== code) { - escaped = true; - code = out; - } - } - - if (!lang) { - return '<pre><code>' - + (escaped ? code : escape(code, true)) - + '\n</code></pre>'; - } - - return '<pre><code class="' - + this.options.langPrefix - + escape(lang, true) - + '">' - + (escaped ? code : escape(code, true)) - + '\n</code></pre>\n'; -}; - -Renderer.prototype.blockquote = function (quote) { - return '<blockquote>\n' + quote + '</blockquote>\n'; -}; - -Renderer.prototype.html = function (html) { - return html; -}; - -Renderer.prototype.heading = function (text, level, raw) { - return '<h' - + level - + ' id="' - + this.options.headerPrefix - + raw.toLowerCase().replace(/[^\w]+/g, '-') - + '">' - + text - + '</h' - + level - + '>\n'; -}; - -Renderer.prototype.hr = function () { - return this.options.xhtml ? '<hr/>\n' : '<hr>\n'; -}; - -Renderer.prototype.list = function (body, ordered) { - var type = ordered ? 'ol' : 'ul'; - return '<' + type + '>\n' + body + '</' + type + '>\n'; -}; - -Renderer.prototype.listitem = function (text) { - return '<li>' + text + '</li>\n'; -}; - -Renderer.prototype.paragraph = function (text) { - return '<p>' + text + '</p>\n'; -}; - -Renderer.prototype.table = function (header, body) { - return '<table>\n' - + '<thead>\n' - + header - + '</thead>\n' - + '<tbody>\n' - + body - + '</tbody>\n' - + '</table>\n'; -}; - -Renderer.prototype.tablerow = function (content) { - return '<tr>\n' + content + '</tr>\n'; -}; - -Renderer.prototype.tablecell = function (content, flags) { - var type = flags.header ? 'th' : 'td'; - var tag = flags.align - ? '<' + type + ' style="text-align:' + flags.align + '">' - : '<' + type + '>'; - return tag + content + '</' + type + '>\n'; -}; - -// span level renderer -Renderer.prototype.strong = function (text) { - return '<strong>' + text + '</strong>'; -}; - -Renderer.prototype.em = function (text) { - return '<em>' + text + '</em>'; -}; - -Renderer.prototype.codespan = function (text) { - return '<code>' + text + '</code>'; -}; - -Renderer.prototype.br = function () { - return this.options.xhtml ? '<br/>' : '<br>'; -}; - -Renderer.prototype.del = function (text) { - return '<del>' + text + '</del>'; -}; - -Renderer.prototype.link = function (href, title, text) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)) - .replace(/[^\w:]/g, '') - .toLowerCase(); - } catch (e) { - return text; - } - if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { - return text; - } - } - if (this.options.baseUrl && !originIndependentUrl.test(href)) { - href = resolveUrl(this.options.baseUrl, href); - } - var out = '<a href="' + href + '"'; - if (title) { - out += ' title="' + title + '"'; - } - out += '>' + text + '</a>'; - return out; -}; - -Renderer.prototype.image = function (href, title, text) { - if (this.options.baseUrl && !originIndependentUrl.test(href)) { - href = resolveUrl(this.options.baseUrl, href); - } - var out = '<img src="' + href + '" alt="' + text + '"'; - if (title) { - out += ' title="' + title + '"'; - } - out += this.options.xhtml ? '/>' : '>'; - return out; -}; - -Renderer.prototype.text = function (text) { - return text; -}; - -/** - * TextRenderer - * returns only the textual part of the token - */ - -function TextRenderer() { } - -// no need for block level renderers - -TextRenderer.prototype.strong = - TextRenderer.prototype.em = - TextRenderer.prototype.codespan = - TextRenderer.prototype.del = - TextRenderer.prototype.text = function (text) { - return text; - } - -TextRenderer.prototype.link = - TextRenderer.prototype.image = function (href, title, text) { - return '' + text; - } - -TextRenderer.prototype.br = function () { - return ''; -} - -/** - * Parsing & Compiling - */ - -function Parser(options) { - this.tokens = []; - this.token = null; - this.options = options || marked.defaults; - this.options.renderer = this.options.renderer || new Renderer; - this.renderer = this.options.renderer; - this.renderer.options = this.options; -} - -/** - * Static Parse Method - */ - -Parser.parse = function (src, options) { - var parser = new Parser(options); - return parser.parse(src); -}; - -/** - * Parse Loop - */ - -Parser.prototype.parse = function (src) { - this.inline = new InlineLexer(src.links, this.options); - // use an InlineLexer with a TextRenderer to extract pure text - this.inlineText = new InlineLexer(src.links, merge({}, this.options, { renderer: new TextRenderer })); - this.tokens = src.reverse(); - - var out = ''; - while (this.next()) { - out += this.tok(); - } - - return out; -}; - -/** - * Next Token - */ - -Parser.prototype.next = function () { - return this.token = this.tokens.pop(); -}; - -/** - * Preview Next Token - */ - -Parser.prototype.peek = function () { - return this.tokens[this.tokens.length - 1] || 0; -}; - -/** - * Parse Text Tokens - */ - -Parser.prototype.parseText = function () { - var body = this.token.text; - - while (this.peek().type === 'text') { - body += '\n' + this.next().text; - } - - return this.inline.output(body); -}; - -/** - * Parse Current Token - */ - -Parser.prototype.tok = function () { - switch (this.token.type) { - case 'space': { - return ''; - } - case 'hr': { - return this.renderer.hr(); - } - case 'heading': { - return this.renderer.heading( - this.inline.output(this.token.text), - this.token.depth, - unescape(this.inlineText.output(this.token.text))); - } - case 'code': { - return this.renderer.code(this.token.text, - this.token.lang, - this.token.escaped); - } - case 'table': { - var header = '' - , body = '' - , i - , row - , cell - , j; - - // header - cell = ''; - for (i = 0; i < this.token.header.length; i++) { - cell += this.renderer.tablecell( - this.inline.output(this.token.header[i]), - { header: true, align: this.token.align[i] } - ); - } - header += this.renderer.tablerow(cell); - - for (i = 0; i < this.token.cells.length; i++) { - row = this.token.cells[i]; - - cell = ''; - for (j = 0; j < row.length; j++) { - cell += this.renderer.tablecell( - this.inline.output(row[j]), - { header: false, align: this.token.align[j] } - ); - } - - body += this.renderer.tablerow(cell); - } - return this.renderer.table(header, body); - } - case 'blockquote_start': { - var body = ''; - - while (this.next().type !== 'blockquote_end') { - body += this.tok(); - } - - return this.renderer.blockquote(body); - } - case 'list_start': { - var body = '' - , ordered = this.token.ordered; - - while (this.next().type !== 'list_end') { - body += this.tok(); - } - - return this.renderer.list(body, ordered); - } - case 'list_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.token.type === 'text' - ? this.parseText() - : this.tok(); - } - - return this.renderer.listitem(body); - } - case 'loose_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.tok(); - } - - return this.renderer.listitem(body); - } - case 'html': { - var html = !this.token.pre && !this.options.pedantic - ? this.inline.output(this.token.text) - : this.token.text; - return this.renderer.html(html); - } - case 'paragraph': { - return this.renderer.paragraph(this.inline.output(this.token.text)); - } - case 'text': { - return this.renderer.paragraph(this.parseText()); - } - } -}; - -/** - * Helpers - */ - -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function unescape(html) { - // explicitly match decimal, hex, and named HTML entities - return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function (_, n) { - n = n.toLowerCase(); - if (n === 'colon') return ':'; - if (n.charAt(0) === '#') { - return n.charAt(1) === 'x' - ? String.fromCharCode(parseInt(n.substring(2), 16)) - : String.fromCharCode(+n.substring(1)); - } - return ''; - }); -} - -function replace(regex, opt) { - regex = regex.source; - opt = opt || ''; - return function self(name, val) { - if (!name) return new RegExp(regex, opt); - val = val.source || val; - val = val.replace(/(^|[^\[])\^/g, '$1'); - regex = regex.replace(name, val); - return self; - }; -} - -function resolveUrl(base, href) { - if (!baseUrls[' ' + base]) { - // we can ignore everything in base after the last slash of its path component, - // but we might need to add _that_ - // https://tools.ietf.org/html/rfc3986#section-3 - if (/^[^:]+:\/*[^/]*$/.test(base)) { - baseUrls[' ' + base] = base + '/'; - } else { - baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); - } - } - base = baseUrls[' ' + base]; - - if (href.slice(0, 2) === '//') { - return base.replace(/:[\s\S]*/, ':') + href; - } else if (href.charAt(0) === '/') { - return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; - } else { - return base + href; - } -} -var baseUrls = {}; -var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; - -function noop() { } -noop.exec = noop; - -function merge(obj) { - var i = 1 - , target - , key; - - for (; i < arguments.length; i++) { - target = arguments[i]; - for (key in target) { - if (Object.prototype.hasOwnProperty.call(target, key)) { - obj[key] = target[key]; - } - } - } - - return obj; -} - - -/** - * Marked - */ - -function marked(src, opt, callback) { - // throw error in case of non string input - if (typeof src == 'undefined' || src === null) - throw new Error('marked(): input parameter is undefined or null'); - if (typeof src != 'string') - throw new Error('marked(): input parameter is of type ' + - Object.prototype.toString.call(src) + ', string expected'); - - - if (callback || typeof opt === 'function') { - if (!callback) { - callback = opt; - opt = null; - } - - opt = merge({}, marked.defaults, opt || {}); - - var highlight = opt.highlight - , tokens - , pending - , i = 0; - - try { - tokens = Lexer.lex(src, opt) - } catch (e) { - return callback(e); - } - - pending = tokens.length; - - var done = function (err) { - if (err) { - opt.highlight = highlight; - return callback(err); - } - - var out; - - try { - out = Parser.parse(tokens, opt); - } catch (e) { - err = e; - } - - opt.highlight = highlight; - - return err - ? callback(err) - : callback(null, out); - }; - - if (!highlight || highlight.length < 3) { - return done(); - } - - delete opt.highlight; - - if (!pending) return done(); - - for (; i < tokens.length; i++) { - (function (token) { - if (token.type !== 'code') { - return --pending || done(); - } - return highlight(token.text, token.lang, function (err, code) { - if (err) return done(err); - if (code == null || code === token.text) { - return --pending || done(); - } - token.text = code; - token.escaped = true; - --pending || done(); - }); - })(tokens[i]); - } - - return; - } - try { - if (opt) opt = merge({}, marked.defaults, opt); - return Parser.parse(Lexer.lex(src, opt), opt); - } catch (e) { - e.message += '\nPlease report this to https://github.com/chjj/marked.'; - if ((opt || marked.defaults).silent) { - return '<p>An error occurred:</p><pre>' - + escape(e.message + '', true) - + '</pre>'; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = - marked.setOptions = function (opt) { - merge(marked.defaults, opt); - return marked; - }; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - sanitizer: null, - mangle: true, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - headerPrefix: '', - renderer: new Renderer, - xhtml: false, - baseUrl: null -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Renderer = Renderer; -marked.TextRenderer = TextRenderer; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -// TODO MonacoChange: we have our own way of defining modules -define([], function() { - return marked; -}); -//if (typeof module !== 'undefined' && typeof exports === 'object') { -// module.exports = marked; -//} else if (typeof define === 'function' && define.amd) { -// define(function() { return marked; }); -//} else { -// this.marked = marked; -//} -// -//}).call(function() { -// return this || (typeof window !== 'undefined' ? window : global); -//}()); -// END MonacoChange \ No newline at end of file diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index f1f4994ae3..01ded4ff68 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -16,7 +16,7 @@ export function parse(text: string): any { return data; } -interface MarshalledObject { +export interface MarshalledObject { $mid: number; } diff --git a/src/vs/base/common/mime.ts b/src/vs/base/common/mime.ts index 6d046e57e7..ba91726ded 100644 --- a/src/vs/base/common/mime.ts +++ b/src/vs/base/common/mime.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import paths = require('vs/base/common/paths'); -import strings = require('vs/base/common/strings'); +import * as paths from 'vs/base/common/paths'; +import * as strings from 'vs/base/common/strings'; import { match } from 'vs/base/common/glob'; export const MIME_TEXT = 'text/plain'; diff --git a/src/vs/base/common/paths.ts b/src/vs/base/common/paths.ts index 14a59a8d49..d4d3d57e66 100644 --- a/src/vs/base/common/paths.ts +++ b/src/vs/base/common/paths.ts @@ -5,7 +5,7 @@ 'use strict'; import { isWindows } from 'vs/base/common/platform'; -import { beginsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings'; +import { startsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; /** @@ -27,6 +27,8 @@ export function dirname(path: string): string { return '.'; } else if (~idx === 0) { return path[0]; + } else if (~idx === path.length - 1) { + return dirname(path.substring(0, path.length - 1)); } else { let res = path.substring(0, ~idx); if (isWindows && res[res.length - 1] === ':') { @@ -340,7 +342,7 @@ export function isEqualOrParent(path: string, candidate: string, ignoreCase?: bo } if (ignoreCase) { - const beginsWith = beginsWithIgnoreCase(path, candidate); + const beginsWith = startsWithIgnoreCase(path, candidate); if (!beginsWith) { return false; } @@ -395,4 +397,4 @@ export function isAbsolute_win32(path: string): boolean { export function isAbsolute_posix(path: string): boolean { return path && path.charCodeAt(0) === CharCode.Slash; -} \ No newline at end of file +} diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index b851693254..8649ad67a2 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -42,7 +42,7 @@ declare let self: any; export const LANGUAGE_DEFAULT = 'en'; // OS detection -if (typeof process === 'object' && typeof process.nextTick === 'function') { +if (typeof process === 'object' && typeof process.nextTick === 'function' && typeof process.platform === 'string') { _isWindows = (process.platform === 'win32'); _isMacintosh = (process.platform === 'darwin'); _isLinux = (process.platform === 'linux'); @@ -120,6 +120,20 @@ export const translationsConfigFile = _translationsConfigFile; const _globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {} as any); export const globals: any = _globals; +let _setImmediate: (callback: (...args: any[]) => void) => number = null; +export function setImmediate(callback: (...args: any[]) => void): number { + if (_setImmediate === null) { + if (globals.setImmediate) { + _setImmediate = globals.setImmediate.bind(globals); + } else if (typeof process !== 'undefined' && typeof process.nextTick === 'function') { + _setImmediate = process.nextTick.bind(process); + } else { + _setImmediate = globals.setTimeout.bind(globals); + } + } + return _setImmediate(callback); +} + export const enum OperatingSystem { Windows = 1, Macintosh = 2, diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 5ca4fdf10c..03799b6d16 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -9,12 +9,16 @@ import uri from 'vs/base/common/uri'; import { equalsIgnoreCase } from 'vs/base/common/strings'; export function basenameOrAuthority(resource: uri): string { - return paths.basename(resource.fsPath) || resource.authority; + return paths.basename(resource.path) || resource.authority; } export function isEqualOrParent(resource: uri, candidate: uri, ignoreCase?: boolean): boolean { if (resource.scheme === candidate.scheme && resource.authority === candidate.authority) { - return paths.isEqualOrParent(resource.fsPath, candidate.fsPath, ignoreCase); + if (resource.scheme === 'file') { + return paths.isEqualOrParent(resource.fsPath, candidate.fsPath, ignoreCase); + } + + return paths.isEqualOrParent(resource.path, candidate.path, ignoreCase); } return false; @@ -66,4 +70,4 @@ export function distinctParents<T>(items: T[], resourceAccessor: (item: T) => ur } return distinctParents; -} \ No newline at end of file +} diff --git a/src/vs/base/common/scrollable.ts b/src/vs/base/common/scrollable.ts index fa6c07a316..b23cd10ca3 100644 --- a/src/vs/base/common/scrollable.ts +++ b/src/vs/base/common/scrollable.ts @@ -5,7 +5,7 @@ 'use strict'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export enum ScrollbarVisibility { Auto = 1, @@ -186,7 +186,7 @@ export class Scrollable extends Disposable { private _smoothScrolling: SmoothScrollingOperation; private _onScroll = this._register(new Emitter<ScrollEvent>()); - public onScroll: Event<ScrollEvent> = this._onScroll.event; + public readonly onScroll: Event<ScrollEvent> = this._onScroll.event; constructor(smoothScrollDuration: number, scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable) { super(); diff --git a/src/vs/base/common/sequence.ts b/src/vs/base/common/sequence.ts index 772cd48d80..61c3b9a5a3 100644 --- a/src/vs/base/common/sequence.ts +++ b/src/vs/base/common/sequence.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface ISplice<T> { readonly start: number; diff --git a/src/vs/base/common/severity.ts b/src/vs/base/common/severity.ts index 4e16ee8df0..f593f66464 100644 --- a/src/vs/base/common/severity.ts +++ b/src/vs/base/common/severity.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); -import strings = require('vs/base/common/strings'); +import * as nls from 'vs/nls'; +import * as strings from 'vs/base/common/strings'; enum Severity { Ignore = 0, @@ -46,17 +46,8 @@ namespace Severity { if (strings.equalsIgnoreCase(_info, value)) { return Severity.Info; } - return Severity.Ignore; } - - export function toString(value: Severity): string { - return _displayStrings[value] || strings.empty; - } - - export function compare(a: Severity, b: Severity): number { - return b - a; - } } -export default Severity; \ No newline at end of file +export default Severity; diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index 7b93252b20..431c8618d6 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -159,6 +159,10 @@ export function startsWith(haystack: string, needle: string): boolean { return false; } + if (haystack === needle) { + return true; + } + for (let i = 0; i < needle.length; i++) { if (haystack[i] !== needle[i]) { return false; @@ -427,7 +431,7 @@ function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean { return true; } -export function beginsWithIgnoreCase(str: string, candidate: string): boolean { +export function startsWithIgnoreCase(str: string, candidate: string): boolean { const candidateLength = candidate.length; if (candidate.length > str.length) { return false; diff --git a/src/vs/base/common/winjs.base.js b/src/vs/base/common/winjs.base.js index 21babed029..ca6c787e58 100644 --- a/src/vs/base/common/winjs.base.js +++ b/src/vs/base/common/winjs.base.js @@ -1,13 +1,2090 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +/** + * Extracted from https://github.com/winjs/winjs + * Version: 4.4.0(ec3258a9f3a36805a187848984e3bb938044178d) + * Copyright (c) Microsoft Corporation. + * All Rights Reserved. + * Licensed under the Source EULA. + */ +var __winjs_exports; -define(['./winjs.base.raw'], function (winjs) { - 'use strict'; - return { - Promise: winjs.Promise, - TPromise: winjs.Promise, - PPromise: winjs.Promise - }; +(function() { + +var _modules = Object.create(null);//{}; +_modules["WinJS/Core/_WinJS"] = {}; + +var _winjs = function(moduleId, deps, factory) { + var exports = {}; + var exportsPassedIn = false; + + var depsValues = deps.map(function(dep) { + if (dep === 'exports') { + exportsPassedIn = true; + return exports; + } + return _modules[dep]; + }); + + var result = factory.apply({}, depsValues); + + _modules[moduleId] = exportsPassedIn ? exports : result; +}; + + +_winjs("WinJS/Core/_Global", [], function () { + "use strict"; + + // Appease jshint + /* global window, self, global */ + + var globalObject = + typeof window !== 'undefined' ? window : + typeof self !== 'undefined' ? self : + typeof global !== 'undefined' ? global : + {}; + return globalObject; }); + +_winjs("WinJS/Core/_BaseCoreUtils", ["WinJS/Core/_Global"], function baseCoreUtilsInit(_Global) { + "use strict"; + + var hasWinRT = !!_Global.Windows; + + function markSupportedForProcessing(func) { + /// <signature helpKeyword="WinJS.Utilities.markSupportedForProcessing"> + /// <summary locid="WinJS.Utilities.markSupportedForProcessing"> + /// Marks a function as being compatible with declarative processing, such as WinJS.UI.processAll + /// or WinJS.Binding.processAll. + /// </summary> + /// <param name="func" type="Function" locid="WinJS.Utilities.markSupportedForProcessing_p:func"> + /// The function to be marked as compatible with declarative processing. + /// </param> + /// <returns type="Function" locid="WinJS.Utilities.markSupportedForProcessing_returnValue"> + /// The input function. + /// </returns> + /// </signature> + func.supportedForProcessing = true; + return func; + } + + var actualSetImmediate = null; + + return { + hasWinRT: hasWinRT, + markSupportedForProcessing: markSupportedForProcessing, + _setImmediate: function (callback) { + // BEGIN monaco change + if (actualSetImmediate === null) { + if (_Global.setImmediate) { + actualSetImmediate = _Global.setImmediate.bind(_Global); + } else if (typeof process !== 'undefined' && typeof process.nextTick === 'function') { + actualSetImmediate = process.nextTick.bind(process); + } else { + actualSetImmediate = _Global.setTimeout.bind(_Global); + } + } + actualSetImmediate(callback); + // END monaco change + } + }; +}); +_winjs("WinJS/Core/_WriteProfilerMark", ["WinJS/Core/_Global"], function profilerInit(_Global) { + "use strict"; + + return _Global.msWriteProfilerMark || function () { }; +}); +_winjs("WinJS/Core/_Base", ["WinJS/Core/_WinJS","WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_WriteProfilerMark"], function baseInit(_WinJS, _Global, _BaseCoreUtils, _WriteProfilerMark) { + "use strict"; + + function initializeProperties(target, members, prefix) { + var keys = Object.keys(members); + var isArray = Array.isArray(target); + var properties; + var i, len; + for (i = 0, len = keys.length; i < len; i++) { + var key = keys[i]; + var enumerable = key.charCodeAt(0) !== /*_*/95; + var member = members[key]; + if (member && typeof member === 'object') { + if (member.value !== undefined || typeof member.get === 'function' || typeof member.set === 'function') { + if (member.enumerable === undefined) { + member.enumerable = enumerable; + } + if (prefix && member.setName && typeof member.setName === 'function') { + member.setName(prefix + "." + key); + } + properties = properties || {}; + properties[key] = member; + continue; + } + } + if (!enumerable) { + properties = properties || {}; + properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true }; + continue; + } + if (isArray) { + target.forEach(function (target) { + target[key] = member; + }); + } else { + target[key] = member; + } + } + if (properties) { + if (isArray) { + target.forEach(function (target) { + Object.defineProperties(target, properties); + }); + } else { + Object.defineProperties(target, properties); + } + } + } + + (function () { + + var _rootNamespace = _WinJS; + if (!_rootNamespace.Namespace) { + _rootNamespace.Namespace = Object.create(Object.prototype); + } + + function createNamespace(parentNamespace, name) { + var currentNamespace = parentNamespace || {}; + if (name) { + var namespaceFragments = name.split("."); + if (currentNamespace === _Global && namespaceFragments[0] === "WinJS") { + currentNamespace = _WinJS; + namespaceFragments.splice(0, 1); + } + for (var i = 0, len = namespaceFragments.length; i < len; i++) { + var namespaceName = namespaceFragments[i]; + if (!currentNamespace[namespaceName]) { + Object.defineProperty(currentNamespace, namespaceName, + { value: {}, writable: false, enumerable: true, configurable: true } + ); + } + currentNamespace = currentNamespace[namespaceName]; + } + } + return currentNamespace; + } + + function defineWithParent(parentNamespace, name, members) { + /// <signature helpKeyword="WinJS.Namespace.defineWithParent"> + /// <summary locid="WinJS.Namespace.defineWithParent"> + /// Defines a new namespace with the specified name under the specified parent namespace. + /// </summary> + /// <param name="parentNamespace" type="Object" locid="WinJS.Namespace.defineWithParent_p:parentNamespace"> + /// The parent namespace. + /// </param> + /// <param name="name" type="String" locid="WinJS.Namespace.defineWithParent_p:name"> + /// The name of the new namespace. + /// </param> + /// <param name="members" type="Object" locid="WinJS.Namespace.defineWithParent_p:members"> + /// The members of the new namespace. + /// </param> + /// <returns type="Object" locid="WinJS.Namespace.defineWithParent_returnValue"> + /// The newly-defined namespace. + /// </returns> + /// </signature> + var currentNamespace = createNamespace(parentNamespace, name); + + if (members) { + initializeProperties(currentNamespace, members, name || "<ANONYMOUS>"); + } + + return currentNamespace; + } + + function define(name, members) { + /// <signature helpKeyword="WinJS.Namespace.define"> + /// <summary locid="WinJS.Namespace.define"> + /// Defines a new namespace with the specified name. + /// </summary> + /// <param name="name" type="String" locid="WinJS.Namespace.define_p:name"> + /// The name of the namespace. This could be a dot-separated name for nested namespaces. + /// </param> + /// <param name="members" type="Object" locid="WinJS.Namespace.define_p:members"> + /// The members of the new namespace. + /// </param> + /// <returns type="Object" locid="WinJS.Namespace.define_returnValue"> + /// The newly-defined namespace. + /// </returns> + /// </signature> + return defineWithParent(_Global, name, members); + } + + var LazyStates = { + uninitialized: 1, + working: 2, + initialized: 3, + }; + + function lazy(f) { + var name; + var state = LazyStates.uninitialized; + var result; + return { + setName: function (value) { + name = value; + }, + get: function () { + switch (state) { + case LazyStates.initialized: + return result; + + case LazyStates.uninitialized: + state = LazyStates.working; + try { + _WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StartTM"); + result = f(); + } finally { + _WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StopTM"); + state = LazyStates.uninitialized; + } + f = null; + state = LazyStates.initialized; + return result; + + case LazyStates.working: + throw "Illegal: reentrancy on initialization"; + + default: + throw "Illegal"; + } + }, + set: function (value) { + switch (state) { + case LazyStates.working: + throw "Illegal: reentrancy on initialization"; + + default: + state = LazyStates.initialized; + result = value; + break; + } + }, + enumerable: true, + configurable: true, + }; + } + + // helper for defining AMD module members + function moduleDefine(exports, name, members) { + var target = [exports]; + var publicNS = null; + if (name) { + publicNS = createNamespace(_Global, name); + target.push(publicNS); + } + initializeProperties(target, members, name || "<ANONYMOUS>"); + return publicNS; + } + + // Establish members of the "WinJS.Namespace" namespace + Object.defineProperties(_rootNamespace.Namespace, { + + defineWithParent: { value: defineWithParent, writable: true, enumerable: true, configurable: true }, + + define: { value: define, writable: true, enumerable: true, configurable: true }, + + _lazy: { value: lazy, writable: true, enumerable: true, configurable: true }, + + _moduleDefine: { value: moduleDefine, writable: true, enumerable: true, configurable: true } + + }); + + })(); + + (function () { + + function define(constructor, instanceMembers, staticMembers) { + /// <signature helpKeyword="WinJS.Class.define"> + /// <summary locid="WinJS.Class.define"> + /// Defines a class using the given constructor and the specified instance members. + /// </summary> + /// <param name="constructor" type="Function" locid="WinJS.Class.define_p:constructor"> + /// A constructor function that is used to instantiate this class. + /// </param> + /// <param name="instanceMembers" type="Object" locid="WinJS.Class.define_p:instanceMembers"> + /// The set of instance fields, properties, and methods made available on the class. + /// </param> + /// <param name="staticMembers" type="Object" locid="WinJS.Class.define_p:staticMembers"> + /// The set of static fields, properties, and methods made available on the class. + /// </param> + /// <returns type="Function" locid="WinJS.Class.define_returnValue"> + /// The newly-defined class. + /// </returns> + /// </signature> + constructor = constructor || function () { }; + _BaseCoreUtils.markSupportedForProcessing(constructor); + if (instanceMembers) { + initializeProperties(constructor.prototype, instanceMembers); + } + if (staticMembers) { + initializeProperties(constructor, staticMembers); + } + return constructor; + } + + function derive(baseClass, constructor, instanceMembers, staticMembers) { + /// <signature helpKeyword="WinJS.Class.derive"> + /// <summary locid="WinJS.Class.derive"> + /// Creates a sub-class based on the supplied baseClass parameter, using prototypal inheritance. + /// </summary> + /// <param name="baseClass" type="Function" locid="WinJS.Class.derive_p:baseClass"> + /// The class to inherit from. + /// </param> + /// <param name="constructor" type="Function" locid="WinJS.Class.derive_p:constructor"> + /// A constructor function that is used to instantiate this class. + /// </param> + /// <param name="instanceMembers" type="Object" locid="WinJS.Class.derive_p:instanceMembers"> + /// The set of instance fields, properties, and methods to be made available on the class. + /// </param> + /// <param name="staticMembers" type="Object" locid="WinJS.Class.derive_p:staticMembers"> + /// The set of static fields, properties, and methods to be made available on the class. + /// </param> + /// <returns type="Function" locid="WinJS.Class.derive_returnValue"> + /// The newly-defined class. + /// </returns> + /// </signature> + if (baseClass) { + constructor = constructor || function () { }; + var basePrototype = baseClass.prototype; + constructor.prototype = Object.create(basePrototype); + _BaseCoreUtils.markSupportedForProcessing(constructor); + Object.defineProperty(constructor.prototype, "constructor", { value: constructor, writable: true, configurable: true, enumerable: true }); + if (instanceMembers) { + initializeProperties(constructor.prototype, instanceMembers); + } + if (staticMembers) { + initializeProperties(constructor, staticMembers); + } + return constructor; + } else { + return define(constructor, instanceMembers, staticMembers); + } + } + + function mix(constructor) { + /// <signature helpKeyword="WinJS.Class.mix"> + /// <summary locid="WinJS.Class.mix"> + /// Defines a class using the given constructor and the union of the set of instance members + /// specified by all the mixin objects. The mixin parameter list is of variable length. + /// </summary> + /// <param name="constructor" locid="WinJS.Class.mix_p:constructor"> + /// A constructor function that is used to instantiate this class. + /// </param> + /// <returns type="Function" locid="WinJS.Class.mix_returnValue"> + /// The newly-defined class. + /// </returns> + /// </signature> + constructor = constructor || function () { }; + var i, len; + for (i = 1, len = arguments.length; i < len; i++) { + initializeProperties(constructor.prototype, arguments[i]); + } + return constructor; + } + + // Establish members of "WinJS.Class" namespace + _WinJS.Namespace.define("WinJS.Class", { + define: define, + derive: derive, + mix: mix + }); + + })(); + + return { + Namespace: _WinJS.Namespace, + Class: _WinJS.Class + }; + +}); +_winjs("WinJS/Core/_ErrorFromName", ["WinJS/Core/_Base"], function errorsInit(_Base) { + "use strict"; + + var ErrorFromName = _Base.Class.derive(Error, function (name, message) { + /// <signature helpKeyword="WinJS.ErrorFromName"> + /// <summary locid="WinJS.ErrorFromName"> + /// Creates an Error object with the specified name and message properties. + /// </summary> + /// <param name="name" type="String" locid="WinJS.ErrorFromName_p:name">The name of this error. The name is meant to be consumed programmatically and should not be localized.</param> + /// <param name="message" type="String" optional="true" locid="WinJS.ErrorFromName_p:message">The message for this error. The message is meant to be consumed by humans and should be localized.</param> + /// <returns type="Error" locid="WinJS.ErrorFromName_returnValue">Error instance with .name and .message properties populated</returns> + /// </signature> + this.name = name; + this.message = message || name; + }, { + /* empty */ + }, { + supportedForProcessing: false, + }); + + _Base.Namespace.define("WinJS", { + // ErrorFromName establishes a simple pattern for returning error codes. + // + ErrorFromName: ErrorFromName + }); + + return ErrorFromName; + +}); + + +_winjs("WinJS/Core/_Events", ["exports","WinJS/Core/_Base"], function eventsInit(exports, _Base) { + "use strict"; + + + function createEventProperty(name) { + var eventPropStateName = "_on" + name + "state"; + + return { + get: function () { + var state = this[eventPropStateName]; + return state && state.userHandler; + }, + set: function (handler) { + var state = this[eventPropStateName]; + if (handler) { + if (!state) { + state = { wrapper: function (evt) { return state.userHandler(evt); }, userHandler: handler }; + Object.defineProperty(this, eventPropStateName, { value: state, enumerable: false, writable:true, configurable: true }); + this.addEventListener(name, state.wrapper, false); + } + state.userHandler = handler; + } else if (state) { + this.removeEventListener(name, state.wrapper, false); + this[eventPropStateName] = null; + } + }, + enumerable: true + }; + } + + function createEventProperties() { + /// <signature helpKeyword="WinJS.Utilities.createEventProperties"> + /// <summary locid="WinJS.Utilities.createEventProperties"> + /// Creates an object that has one property for each name passed to the function. + /// </summary> + /// <param name="events" locid="WinJS.Utilities.createEventProperties_p:events"> + /// A variable list of property names. + /// </param> + /// <returns type="Object" locid="WinJS.Utilities.createEventProperties_returnValue"> + /// The object with the specified properties. The names of the properties are prefixed with 'on'. + /// </returns> + /// </signature> + var props = {}; + for (var i = 0, len = arguments.length; i < len; i++) { + var name = arguments[i]; + props["on" + name] = createEventProperty(name); + } + return props; + } + + var EventMixinEvent = _Base.Class.define( + function EventMixinEvent_ctor(type, detail, target) { + this.detail = detail; + this.target = target; + this.timeStamp = Date.now(); + this.type = type; + }, + { + bubbles: { value: false, writable: false }, + cancelable: { value: false, writable: false }, + currentTarget: { + get: function () { return this.target; } + }, + defaultPrevented: { + get: function () { return this._preventDefaultCalled; } + }, + trusted: { value: false, writable: false }, + eventPhase: { value: 0, writable: false }, + target: null, + timeStamp: null, + type: null, + + preventDefault: function () { + this._preventDefaultCalled = true; + }, + stopImmediatePropagation: function () { + this._stopImmediatePropagationCalled = true; + }, + stopPropagation: function () { + } + }, { + supportedForProcessing: false, + } + ); + + var eventMixin = { + _listeners: null, + + addEventListener: function (type, listener, useCapture) { + /// <signature helpKeyword="WinJS.Utilities.eventMixin.addEventListener"> + /// <summary locid="WinJS.Utilities.eventMixin.addEventListener"> + /// Adds an event listener to the control. + /// </summary> + /// <param name="type" locid="WinJS.Utilities.eventMixin.addEventListener_p:type"> + /// The type (name) of the event. + /// </param> + /// <param name="listener" locid="WinJS.Utilities.eventMixin.addEventListener_p:listener"> + /// The listener to invoke when the event is raised. + /// </param> + /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.addEventListener_p:useCapture"> + /// if true initiates capture, otherwise false. + /// </param> + /// </signature> + useCapture = useCapture || false; + this._listeners = this._listeners || {}; + var eventListeners = (this._listeners[type] = this._listeners[type] || []); + for (var i = 0, len = eventListeners.length; i < len; i++) { + var l = eventListeners[i]; + if (l.useCapture === useCapture && l.listener === listener) { + return; + } + } + eventListeners.push({ listener: listener, useCapture: useCapture }); + }, + dispatchEvent: function (type, details) { + /// <signature helpKeyword="WinJS.Utilities.eventMixin.dispatchEvent"> + /// <summary locid="WinJS.Utilities.eventMixin.dispatchEvent"> + /// Raises an event of the specified type and with the specified additional properties. + /// </summary> + /// <param name="type" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:type"> + /// The type (name) of the event. + /// </param> + /// <param name="details" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:details"> + /// The set of additional properties to be attached to the event object when the event is raised. + /// </param> + /// <returns type="Boolean" locid="WinJS.Utilities.eventMixin.dispatchEvent_returnValue"> + /// true if preventDefault was called on the event. + /// </returns> + /// </signature> + var listeners = this._listeners && this._listeners[type]; + if (listeners) { + var eventValue = new EventMixinEvent(type, details, this); + // Need to copy the array to protect against people unregistering while we are dispatching + listeners = listeners.slice(0, listeners.length); + for (var i = 0, len = listeners.length; i < len && !eventValue._stopImmediatePropagationCalled; i++) { + listeners[i].listener(eventValue); + } + return eventValue.defaultPrevented || false; + } + return false; + }, + removeEventListener: function (type, listener, useCapture) { + /// <signature helpKeyword="WinJS.Utilities.eventMixin.removeEventListener"> + /// <summary locid="WinJS.Utilities.eventMixin.removeEventListener"> + /// Removes an event listener from the control. + /// </summary> + /// <param name="type" locid="WinJS.Utilities.eventMixin.removeEventListener_p:type"> + /// The type (name) of the event. + /// </param> + /// <param name="listener" locid="WinJS.Utilities.eventMixin.removeEventListener_p:listener"> + /// The listener to remove. + /// </param> + /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.removeEventListener_p:useCapture"> + /// Specifies whether to initiate capture. + /// </param> + /// </signature> + useCapture = useCapture || false; + var listeners = this._listeners && this._listeners[type]; + if (listeners) { + for (var i = 0, len = listeners.length; i < len; i++) { + var l = listeners[i]; + if (l.listener === listener && l.useCapture === useCapture) { + listeners.splice(i, 1); + if (listeners.length === 0) { + delete this._listeners[type]; + } + // Only want to remove one element for each call to removeEventListener + break; + } + } + } + } + }; + + _Base.Namespace._moduleDefine(exports, "WinJS.Utilities", { + _createEventProperty: createEventProperty, + createEventProperties: createEventProperties, + eventMixin: eventMixin + }); + +}); + + +_winjs("WinJS/Core/_Trace", ["WinJS/Core/_Global"], function traceInit(_Global) { + "use strict"; + + function nop(v) { + return v; + } + + return { + _traceAsyncOperationStarting: (_Global.Debug && _Global.Debug.msTraceAsyncOperationStarting && _Global.Debug.msTraceAsyncOperationStarting.bind(_Global.Debug)) || nop, + _traceAsyncOperationCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncOperationCompleted && _Global.Debug.msTraceAsyncOperationCompleted.bind(_Global.Debug)) || nop, + _traceAsyncCallbackStarting: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackStarting && _Global.Debug.msTraceAsyncCallbackStarting.bind(_Global.Debug)) || nop, + _traceAsyncCallbackCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackCompleted && _Global.Debug.msTraceAsyncCallbackCompleted.bind(_Global.Debug)) || nop + }; +}); +_winjs("WinJS/Promise/_StateMachine", ["WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_Base","WinJS/Core/_ErrorFromName","WinJS/Core/_Events","WinJS/Core/_Trace"], function promiseStateMachineInit(_Global, _BaseCoreUtils, _Base, _ErrorFromName, _Events, _Trace) { + "use strict"; + + _Global.Debug && (_Global.Debug.setNonUserCodeExceptions = true); + + var ListenerType = _Base.Class.mix(_Base.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), _Events.eventMixin); + var promiseEventListeners = new ListenerType(); + // make sure there is a listeners collection so that we can do a more trivial check below + promiseEventListeners._listeners = {}; + var errorET = "error"; + var canceledName = "Canceled"; + var tagWithStack = false; + var tag = { + promise: 0x01, + thenPromise: 0x02, + errorPromise: 0x04, + exceptionPromise: 0x08, + completePromise: 0x10, + }; + tag.all = tag.promise | tag.thenPromise | tag.errorPromise | tag.exceptionPromise | tag.completePromise; + + // + // Global error counter, for each error which enters the system we increment this once and then + // the error number travels with the error as it traverses the tree of potential handlers. + // + // When someone has registered to be told about errors (WinJS.Promise.callonerror) promises + // which are in error will get tagged with a ._errorId field. This tagged field is the + // contract by which nested promises with errors will be identified as chaining for the + // purposes of the callonerror semantics. If a nested promise in error is encountered without + // a ._errorId it will be assumed to be foreign and treated as an interop boundary and + // a new error id will be minted. + // + var error_number = 1; + + // + // The state machine has a interesting hiccup in it with regards to notification, in order + // to flatten out notification and avoid recursion for synchronous completion we have an + // explicit set of *_notify states which are responsible for notifying their entire tree + // of children. They can do this because they know that immediate children are always + // ThenPromise instances and we can therefore reach into their state to access the + // _listeners collection. + // + // So, what happens is that a Promise will be fulfilled through the _completed or _error + // messages at which point it will enter a *_notify state and be responsible for to move + // its children into an (as appropriate) success or error state and also notify that child's + // listeners of the state transition, until leaf notes are reached. + // + + var state_created, // -> working + state_working, // -> error | error_notify | success | success_notify | canceled | waiting + state_waiting, // -> error | error_notify | success | success_notify | waiting_canceled + state_waiting_canceled, // -> error | error_notify | success | success_notify | canceling + state_canceled, // -> error | error_notify | success | success_notify | canceling + state_canceling, // -> error_notify + state_success_notify, // -> success + state_success, // -> . + state_error_notify, // -> error + state_error; // -> . + + // Noop function, used in the various states to indicate that they don't support a given + // message. Named with the somewhat cute name '_' because it reads really well in the states. + + function _() { } + + // Initial state + // + state_created = { + name: "created", + enter: function (promise) { + promise._setState(state_working); + }, + cancel: _, + done: _, + then: _, + _completed: _, + _error: _, + _notify: _, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // Ready state, waiting for a message (completed/error/progress), able to be canceled + // + state_working = { + name: "working", + enter: _, + cancel: function (promise) { + promise._setState(state_canceled); + }, + done: done, + then: then, + _completed: completed, + _error: error, + _notify: _, + _progress: progress, + _setCompleteValue: setCompleteValue, + _setErrorValue: setErrorValue + }; + + // Waiting state, if a promise is completed with a value which is itself a promise + // (has a then() method) it signs up to be informed when that child promise is + // fulfilled at which point it will be fulfilled with that value. + // + state_waiting = { + name: "waiting", + enter: function (promise) { + var waitedUpon = promise._value; + // We can special case our own intermediate promises which are not in a + // terminal state by just pushing this promise as a listener without + // having to create new indirection functions + if (waitedUpon instanceof ThenPromise && + waitedUpon._state !== state_error && + waitedUpon._state !== state_success) { + pushListener(waitedUpon, { promise: promise }); + } else { + var error = function (value) { + if (waitedUpon._errorId) { + promise._chainedError(value, waitedUpon); + } else { + // Because this is an interop boundary we want to indicate that this + // error has been handled by the promise infrastructure before we + // begin a new handling chain. + // + callonerror(promise, value, detailsForHandledError, waitedUpon, error); + promise._error(value); + } + }; + error.handlesOnError = true; + waitedUpon.then( + promise._completed.bind(promise), + error, + promise._progress.bind(promise) + ); + } + }, + cancel: function (promise) { + promise._setState(state_waiting_canceled); + }, + done: done, + then: then, + _completed: completed, + _error: error, + _notify: _, + _progress: progress, + _setCompleteValue: setCompleteValue, + _setErrorValue: setErrorValue + }; + + // Waiting canceled state, when a promise has been in a waiting state and receives a + // request to cancel its pending work it will forward that request to the child promise + // and then waits to be informed of the result. This promise moves itself into the + // canceling state but understands that the child promise may instead push it to a + // different state. + // + state_waiting_canceled = { + name: "waiting_canceled", + enter: function (promise) { + // Initiate a transition to canceling. Triggering a cancel on the promise + // that we are waiting upon may result in a different state transition + // before the state machine pump runs again. + promise._setState(state_canceling); + var waitedUpon = promise._value; + if (waitedUpon.cancel) { + waitedUpon.cancel(); + } + }, + cancel: _, + done: done, + then: then, + _completed: completed, + _error: error, + _notify: _, + _progress: progress, + _setCompleteValue: setCompleteValue, + _setErrorValue: setErrorValue + }; + + // Canceled state, moves to the canceling state and then tells the promise to do + // whatever it might need to do on cancelation. + // + state_canceled = { + name: "canceled", + enter: function (promise) { + // Initiate a transition to canceling. The _cancelAction may change the state + // before the state machine pump runs again. + promise._setState(state_canceling); + promise._cancelAction(); + }, + cancel: _, + done: done, + then: then, + _completed: completed, + _error: error, + _notify: _, + _progress: progress, + _setCompleteValue: setCompleteValue, + _setErrorValue: setErrorValue + }; + + // Canceling state, commits to the promise moving to an error state with an error + // object whose 'name' and 'message' properties contain the string "Canceled" + // + state_canceling = { + name: "canceling", + enter: function (promise) { + var error = new Error(canceledName); + error.name = error.message; + promise._value = error; + promise._setState(state_error_notify); + }, + cancel: _, + done: _, + then: _, + _completed: _, + _error: _, + _notify: _, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // Success notify state, moves a promise to the success state and notifies all children + // + state_success_notify = { + name: "complete_notify", + enter: function (promise) { + promise.done = CompletePromise.prototype.done; + promise.then = CompletePromise.prototype.then; + if (promise._listeners) { + var queue = [promise]; + var p; + while (queue.length) { + p = queue.shift(); + p._state._notify(p, queue); + } + } + promise._setState(state_success); + }, + cancel: _, + done: null, /*error to get here */ + then: null, /*error to get here */ + _completed: _, + _error: _, + _notify: notifySuccess, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // Success state, moves a promise to the success state and does NOT notify any children. + // Some upstream promise is owning the notification pass. + // + state_success = { + name: "success", + enter: function (promise) { + promise.done = CompletePromise.prototype.done; + promise.then = CompletePromise.prototype.then; + promise._cleanupAction(); + }, + cancel: _, + done: null, /*error to get here */ + then: null, /*error to get here */ + _completed: _, + _error: _, + _notify: notifySuccess, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // Error notify state, moves a promise to the error state and notifies all children + // + state_error_notify = { + name: "error_notify", + enter: function (promise) { + promise.done = ErrorPromise.prototype.done; + promise.then = ErrorPromise.prototype.then; + if (promise._listeners) { + var queue = [promise]; + var p; + while (queue.length) { + p = queue.shift(); + p._state._notify(p, queue); + } + } + promise._setState(state_error); + }, + cancel: _, + done: null, /*error to get here*/ + then: null, /*error to get here*/ + _completed: _, + _error: _, + _notify: notifyError, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // Error state, moves a promise to the error state and does NOT notify any children. + // Some upstream promise is owning the notification pass. + // + state_error = { + name: "error", + enter: function (promise) { + promise.done = ErrorPromise.prototype.done; + promise.then = ErrorPromise.prototype.then; + promise._cleanupAction(); + }, + cancel: _, + done: null, /*error to get here*/ + then: null, /*error to get here*/ + _completed: _, + _error: _, + _notify: notifyError, + _progress: _, + _setCompleteValue: _, + _setErrorValue: _ + }; + + // + // The statemachine implementation follows a very particular pattern, the states are specified + // as static stateless bags of functions which are then indirected through the state machine + // instance (a Promise). As such all of the functions on each state have the promise instance + // passed to them explicitly as a parameter and the Promise instance members do a little + // dance where they indirect through the state and insert themselves in the argument list. + // + // We could instead call directly through the promise states however then every caller + // would have to remember to do things like pumping the state machine to catch state transitions. + // + + var PromiseStateMachine = _Base.Class.define(null, { + _listeners: null, + _nextState: null, + _state: null, + _value: null, + + cancel: function () { + /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> + /// <summary locid="WinJS.PromiseStateMachine.cancel"> + /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't + /// already been fulfilled and cancellation is supported, the promise enters + /// the error state with a value of Error("Canceled"). + /// </summary> + /// </signature> + this._state.cancel(this); + this._run(); + }, + done: function Promise_done(onComplete, onError, onProgress) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> + /// <summary locid="WinJS.PromiseStateMachine.done"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// + /// After the handlers have finished executing, this function throws any error that would have been returned + /// from then() as a promise in the error state. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The fulfilled value is passed as the single argument. If the value is null, + /// the fulfilled value is returned. The value returned + /// from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while executing the function, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function is the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> + /// the function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// </signature> + this._state.done(this, onComplete, onError, onProgress); + }, + then: function Promise_then(onComplete, onError, onProgress) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> + /// <summary locid="WinJS.PromiseStateMachine.then"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The value is passed as the single argument. If the value is null, the value is returned. + /// The value returned from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while this function is being executed, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function becomes the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> + /// The function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> + /// The promise whose value is the result of executing the complete or + /// error function. + /// </returns> + /// </signature> + return this._state.then(this, onComplete, onError, onProgress); + }, + + _chainedError: function (value, context) { + var result = this._state._error(this, value, detailsForChainedError, context); + this._run(); + return result; + }, + _completed: function (value) { + var result = this._state._completed(this, value); + this._run(); + return result; + }, + _error: function (value) { + var result = this._state._error(this, value, detailsForError); + this._run(); + return result; + }, + _progress: function (value) { + this._state._progress(this, value); + }, + _setState: function (state) { + this._nextState = state; + }, + _setCompleteValue: function (value) { + this._state._setCompleteValue(this, value); + this._run(); + }, + _setChainedErrorValue: function (value, context) { + var result = this._state._setErrorValue(this, value, detailsForChainedError, context); + this._run(); + return result; + }, + _setExceptionValue: function (value) { + var result = this._state._setErrorValue(this, value, detailsForException); + this._run(); + return result; + }, + _run: function () { + while (this._nextState) { + this._state = this._nextState; + this._nextState = null; + this._state.enter(this); + } + } + }, { + supportedForProcessing: false + }); + + // + // Implementations of shared state machine code. + // + + function completed(promise, value) { + var targetState; + if (value && typeof value === "object" && typeof value.then === "function") { + targetState = state_waiting; + } else { + targetState = state_success_notify; + } + promise._value = value; + promise._setState(targetState); + } + function createErrorDetails(exception, error, promise, id, parent, handler) { + return { + exception: exception, + error: error, + promise: promise, + handler: handler, + id: id, + parent: parent + }; + } + function detailsForHandledError(promise, errorValue, context, handler) { + var exception = context._isException; + var errorId = context._errorId; + return createErrorDetails( + exception ? errorValue : null, + exception ? null : errorValue, + promise, + errorId, + context, + handler + ); + } + function detailsForChainedError(promise, errorValue, context) { + var exception = context._isException; + var errorId = context._errorId; + setErrorInfo(promise, errorId, exception); + return createErrorDetails( + exception ? errorValue : null, + exception ? null : errorValue, + promise, + errorId, + context + ); + } + function detailsForError(promise, errorValue) { + var errorId = ++error_number; + setErrorInfo(promise, errorId); + return createErrorDetails( + null, + errorValue, + promise, + errorId + ); + } + function detailsForException(promise, exceptionValue) { + var errorId = ++error_number; + setErrorInfo(promise, errorId, true); + return createErrorDetails( + exceptionValue, + null, + promise, + errorId + ); + } + function done(promise, onComplete, onError, onProgress) { + var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.done"); + pushListener(promise, { c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); + } + function error(promise, value, onerrorDetails, context) { + promise._value = value; + callonerror(promise, value, onerrorDetails, context); + promise._setState(state_error_notify); + } + function notifySuccess(promise, queue) { + var value = promise._value; + var listeners = promise._listeners; + if (!listeners) { + return; + } + promise._listeners = null; + var i, len; + for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { + var listener = len === 1 ? listeners : listeners[i]; + var onComplete = listener.c; + var target = listener.promise; + + _Trace._traceAsyncOperationCompleted(listener.asyncOpID, _Global.Debug && _Global.Debug.MS_ASYNC_OP_STATUS_SUCCESS); + + if (target) { + _Trace._traceAsyncCallbackStarting(listener.asyncOpID); + try { + target._setCompleteValue(onComplete ? onComplete(value) : value); + } catch (ex) { + target._setExceptionValue(ex); + } finally { + _Trace._traceAsyncCallbackCompleted(); + } + if (target._state !== state_waiting && target._listeners) { + queue.push(target); + } + } else { + CompletePromise.prototype.done.call(promise, onComplete); + } + } + } + function notifyError(promise, queue) { + var value = promise._value; + var listeners = promise._listeners; + if (!listeners) { + return; + } + promise._listeners = null; + var i, len; + for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { + var listener = len === 1 ? listeners : listeners[i]; + var onError = listener.e; + var target = listener.promise; + + var errorID = _Global.Debug && (value && value.name === canceledName ? _Global.Debug.MS_ASYNC_OP_STATUS_CANCELED : _Global.Debug.MS_ASYNC_OP_STATUS_ERROR); + _Trace._traceAsyncOperationCompleted(listener.asyncOpID, errorID); + + if (target) { + var asyncCallbackStarted = false; + try { + if (onError) { + _Trace._traceAsyncCallbackStarting(listener.asyncOpID); + asyncCallbackStarted = true; + if (!onError.handlesOnError) { + callonerror(target, value, detailsForHandledError, promise, onError); + } + target._setCompleteValue(onError(value)); + } else { + target._setChainedErrorValue(value, promise); + } + } catch (ex) { + target._setExceptionValue(ex); + } finally { + if (asyncCallbackStarted) { + _Trace._traceAsyncCallbackCompleted(); + } + } + if (target._state !== state_waiting && target._listeners) { + queue.push(target); + } + } else { + ErrorPromise.prototype.done.call(promise, null, onError); + } + } + } + function callonerror(promise, value, onerrorDetailsGenerator, context, handler) { + if (promiseEventListeners._listeners[errorET]) { + if (value instanceof Error && value.message === canceledName) { + return; + } + promiseEventListeners.dispatchEvent(errorET, onerrorDetailsGenerator(promise, value, context, handler)); + } + } + function progress(promise, value) { + var listeners = promise._listeners; + if (listeners) { + var i, len; + for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { + var listener = len === 1 ? listeners : listeners[i]; + var onProgress = listener.p; + if (onProgress) { + try { onProgress(value); } catch (ex) { } + } + if (!(listener.c || listener.e) && listener.promise) { + listener.promise._progress(value); + } + } + } + } + function pushListener(promise, listener) { + var listeners = promise._listeners; + if (listeners) { + // We may have either a single listener (which will never be wrapped in an array) + // or 2+ listeners (which will be wrapped). Since we are now adding one more listener + // we may have to wrap the single listener before adding the second. + listeners = Array.isArray(listeners) ? listeners : [listeners]; + listeners.push(listener); + } else { + listeners = listener; + } + promise._listeners = listeners; + } + // The difference beween setCompleteValue()/setErrorValue() and complete()/error() is that setXXXValue() moves + // a promise directly to the success/error state without starting another notification pass (because one + // is already ongoing). + function setErrorInfo(promise, errorId, isException) { + promise._isException = isException || false; + promise._errorId = errorId; + } + function setErrorValue(promise, value, onerrorDetails, context) { + promise._value = value; + callonerror(promise, value, onerrorDetails, context); + promise._setState(state_error); + } + function setCompleteValue(promise, value) { + var targetState; + if (value && typeof value === "object" && typeof value.then === "function") { + targetState = state_waiting; + } else { + targetState = state_success; + } + promise._value = value; + promise._setState(targetState); + } + function then(promise, onComplete, onError, onProgress) { + var result = new ThenPromise(promise); + var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.then"); + pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); + return result; + } + + // + // Internal implementation detail promise, ThenPromise is created when a promise needs + // to be returned from a then() method. + // + var ThenPromise = _Base.Class.derive(PromiseStateMachine, + function (creator) { + + if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) { + this._stack = Promise._getStack(); + } + + this._creator = creator; + this._setState(state_created); + this._run(); + }, { + _creator: null, + + _cancelAction: function () { if (this._creator) { this._creator.cancel(); } }, + _cleanupAction: function () { this._creator = null; } + }, { + supportedForProcessing: false + } + ); + + // + // Slim promise implementations for already completed promises, these are created + // under the hood on synchronous completion paths as well as by WinJS.Promise.wrap + // and WinJS.Promise.wrapError. + // + + var ErrorPromise = _Base.Class.define( + function ErrorPromise_ctor(value) { + + if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) { + this._stack = Promise._getStack(); + } + + this._value = value; + callonerror(this, value, detailsForError); + }, { + cancel: function () { + /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> + /// <summary locid="WinJS.PromiseStateMachine.cancel"> + /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't + /// already been fulfilled and cancellation is supported, the promise enters + /// the error state with a value of Error("Canceled"). + /// </summary> + /// </signature> + }, + done: function ErrorPromise_done(unused, onError) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> + /// <summary locid="WinJS.PromiseStateMachine.done"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// + /// After the handlers have finished executing, this function throws any error that would have been returned + /// from then() as a promise in the error state. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The fulfilled value is passed as the single argument. If the value is null, + /// the fulfilled value is returned. The value returned + /// from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while executing the function, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function is the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> + /// the function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// </signature> + var value = this._value; + if (onError) { + try { + if (!onError.handlesOnError) { + callonerror(null, value, detailsForHandledError, this, onError); + } + var result = onError(value); + if (result && typeof result === "object" && typeof result.done === "function") { + // If a promise is returned we need to wait on it. + result.done(); + } + return; + } catch (ex) { + value = ex; + } + } + if (value instanceof Error && value.message === canceledName) { + // suppress cancel + return; + } + // force the exception to be thrown asyncronously to avoid any try/catch blocks + // + Promise._doneHandler(value); + }, + then: function ErrorPromise_then(unused, onError) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> + /// <summary locid="WinJS.PromiseStateMachine.then"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The value is passed as the single argument. If the value is null, the value is returned. + /// The value returned from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while this function is being executed, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function becomes the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> + /// The function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> + /// The promise whose value is the result of executing the complete or + /// error function. + /// </returns> + /// </signature> + + // If the promise is already in a error state and no error handler is provided + // we optimize by simply returning the promise instead of creating a new one. + // + if (!onError) { return this; } + var result; + var value = this._value; + try { + if (!onError.handlesOnError) { + callonerror(null, value, detailsForHandledError, this, onError); + } + result = new CompletePromise(onError(value)); + } catch (ex) { + // If the value throw from the error handler is the same as the value + // provided to the error handler then there is no need for a new promise. + // + if (ex === value) { + result = this; + } else { + result = new ExceptionPromise(ex); + } + } + return result; + } + }, { + supportedForProcessing: false + } + ); + + var ExceptionPromise = _Base.Class.derive(ErrorPromise, + function ExceptionPromise_ctor(value) { + + if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) { + this._stack = Promise._getStack(); + } + + this._value = value; + callonerror(this, value, detailsForException); + }, { + /* empty */ + }, { + supportedForProcessing: false + } + ); + + var CompletePromise = _Base.Class.define( + function CompletePromise_ctor(value) { + + if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) { + this._stack = Promise._getStack(); + } + + if (value && typeof value === "object" && typeof value.then === "function") { + var result = new ThenPromise(null); + result._setCompleteValue(value); + return result; + } + this._value = value; + }, { + cancel: function () { + /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> + /// <summary locid="WinJS.PromiseStateMachine.cancel"> + /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't + /// already been fulfilled and cancellation is supported, the promise enters + /// the error state with a value of Error("Canceled"). + /// </summary> + /// </signature> + }, + done: function CompletePromise_done(onComplete) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> + /// <summary locid="WinJS.PromiseStateMachine.done"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// + /// After the handlers have finished executing, this function throws any error that would have been returned + /// from then() as a promise in the error state. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The fulfilled value is passed as the single argument. If the value is null, + /// the fulfilled value is returned. The value returned + /// from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while executing the function, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function is the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> + /// the function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// </signature> + if (!onComplete) { return; } + try { + var result = onComplete(this._value); + if (result && typeof result === "object" && typeof result.done === "function") { + result.done(); + } + } catch (ex) { + // force the exception to be thrown asynchronously to avoid any try/catch blocks + Promise._doneHandler(ex); + } + }, + then: function CompletePromise_then(onComplete) { + /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> + /// <summary locid="WinJS.PromiseStateMachine.then"> + /// Allows you to specify the work to be done on the fulfillment of the promised value, + /// the error handling to be performed if the promise fails to fulfill + /// a value, and the handling of progress notifications along the way. + /// </summary> + /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> + /// The function to be called if the promise is fulfilled successfully with a value. + /// The value is passed as the single argument. If the value is null, the value is returned. + /// The value returned from the function becomes the fulfilled value of the promise returned by + /// then(). If an exception is thrown while this function is being executed, the promise returned + /// by then() moves into the error state. + /// </param> + /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. If it is null, the error is forwarded. + /// The value returned from the function becomes the fulfilled value of the promise returned by then(). + /// </param> + /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> + /// The function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> + /// The promise whose value is the result of executing the complete or + /// error function. + /// </returns> + /// </signature> + try { + // If the value returned from the completion handler is the same as the value + // provided to the completion handler then there is no need for a new promise. + // + var newValue = onComplete ? onComplete(this._value) : this._value; + return newValue === this._value ? this : new CompletePromise(newValue); + } catch (ex) { + return new ExceptionPromise(ex); + } + } + }, { + supportedForProcessing: false + } + ); + + // + // Promise is the user-creatable WinJS.Promise object. + // + + function timeout(timeoutMS) { + var id; + return new Promise( + function (c) { + if (timeoutMS) { + id = _Global.setTimeout(c, timeoutMS); + } else { + _BaseCoreUtils._setImmediate(c); + } + }, + function () { + if (id) { + _Global.clearTimeout(id); + } + } + ); + } + + function timeoutWithPromise(timeout, promise) { + var cancelPromise = function () { promise.cancel(); }; + var cancelTimeout = function () { timeout.cancel(); }; + timeout.then(cancelPromise); + promise.then(cancelTimeout, cancelTimeout); + return promise; + } + + var staticCanceledPromise; + + var Promise = _Base.Class.derive(PromiseStateMachine, + function Promise_ctor(init, oncancel) { + /// <signature helpKeyword="WinJS.Promise"> + /// <summary locid="WinJS.Promise"> + /// A promise provides a mechanism to schedule work to be done on a value that + /// has not yet been computed. It is a convenient abstraction for managing + /// interactions with asynchronous APIs. + /// </summary> + /// <param name="init" type="Function" locid="WinJS.Promise_p:init"> + /// The function that is called during construction of the promise. The function + /// is given three arguments (complete, error, progress). Inside this function + /// you should add event listeners for the notifications supported by this value. + /// </param> + /// <param name="oncancel" optional="true" locid="WinJS.Promise_p:oncancel"> + /// The function to call if a consumer of this promise wants + /// to cancel its undone work. Promises are not required to + /// support cancellation. + /// </param> + /// </signature> + + if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.promise))) { + this._stack = Promise._getStack(); + } + + this._oncancel = oncancel; + this._setState(state_created); + this._run(); + + try { + var complete = this._completed.bind(this); + var error = this._error.bind(this); + var progress = this._progress.bind(this); + init(complete, error, progress); + } catch (ex) { + this._setExceptionValue(ex); + } + }, { + _oncancel: null, + + _cancelAction: function () { + // BEGIN monaco change + try { + if (this._oncancel) { + this._oncancel(); + } else { + throw new Error('Promise did not implement oncancel'); + } + } catch (ex) { + // Access fields to get them created + var msg = ex.message; + var stack = ex.stack; + promiseEventListeners.dispatchEvent('error', ex); + } + // END monaco change + }, + _cleanupAction: function () { this._oncancel = null; } + }, { + + addEventListener: function Promise_addEventListener(eventType, listener, capture) { + /// <signature helpKeyword="WinJS.Promise.addEventListener"> + /// <summary locid="WinJS.Promise.addEventListener"> + /// Adds an event listener to the control. + /// </summary> + /// <param name="eventType" locid="WinJS.Promise.addEventListener_p:eventType"> + /// The type (name) of the event. + /// </param> + /// <param name="listener" locid="WinJS.Promise.addEventListener_p:listener"> + /// The listener to invoke when the event is raised. + /// </param> + /// <param name="capture" locid="WinJS.Promise.addEventListener_p:capture"> + /// Specifies whether or not to initiate capture. + /// </param> + /// </signature> + promiseEventListeners.addEventListener(eventType, listener, capture); + }, + any: function Promise_any(values) { + /// <signature helpKeyword="WinJS.Promise.any"> + /// <summary locid="WinJS.Promise.any"> + /// Returns a promise that is fulfilled when one of the input promises + /// has been fulfilled. + /// </summary> + /// <param name="values" type="Array" locid="WinJS.Promise.any_p:values"> + /// An array that contains promise objects or objects whose property + /// values include promise objects. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.any_returnValue"> + /// A promise that on fulfillment yields the value of the input (complete or error). + /// </returns> + /// </signature> + return new Promise( + function (complete, error) { + var keys = Object.keys(values); + if (keys.length === 0) { + complete(); + } + var canceled = 0; + keys.forEach(function (key) { + Promise.as(values[key]).then( + function () { complete({ key: key, value: values[key] }); }, + function (e) { + if (e instanceof Error && e.name === canceledName) { + if ((++canceled) === keys.length) { + complete(Promise.cancel); + } + return; + } + error({ key: key, value: values[key] }); + } + ); + }); + }, + function () { + var keys = Object.keys(values); + keys.forEach(function (key) { + var promise = Promise.as(values[key]); + if (typeof promise.cancel === "function") { + promise.cancel(); + } + }); + } + ); + }, + as: function Promise_as(value) { + /// <signature helpKeyword="WinJS.Promise.as"> + /// <summary locid="WinJS.Promise.as"> + /// Returns a promise. If the object is already a promise it is returned; + /// otherwise the object is wrapped in a promise. + /// </summary> + /// <param name="value" locid="WinJS.Promise.as_p:value"> + /// The value to be treated as a promise. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.as_returnValue"> + /// A promise. + /// </returns> + /// </signature> + if (value && typeof value === "object" && typeof value.then === "function") { + return value; + } + return new CompletePromise(value); + }, + /// <field type="WinJS.Promise" helpKeyword="WinJS.Promise.cancel" locid="WinJS.Promise.cancel"> + /// Canceled promise value, can be returned from a promise completion handler + /// to indicate cancelation of the promise chain. + /// </field> + cancel: { + get: function () { + return (staticCanceledPromise = staticCanceledPromise || new ErrorPromise(new _ErrorFromName(canceledName))); + } + }, + dispatchEvent: function Promise_dispatchEvent(eventType, details) { + /// <signature helpKeyword="WinJS.Promise.dispatchEvent"> + /// <summary locid="WinJS.Promise.dispatchEvent"> + /// Raises an event of the specified type and properties. + /// </summary> + /// <param name="eventType" locid="WinJS.Promise.dispatchEvent_p:eventType"> + /// The type (name) of the event. + /// </param> + /// <param name="details" locid="WinJS.Promise.dispatchEvent_p:details"> + /// The set of additional properties to be attached to the event object. + /// </param> + /// <returns type="Boolean" locid="WinJS.Promise.dispatchEvent_returnValue"> + /// Specifies whether preventDefault was called on the event. + /// </returns> + /// </signature> + return promiseEventListeners.dispatchEvent(eventType, details); + }, + is: function Promise_is(value) { + /// <signature helpKeyword="WinJS.Promise.is"> + /// <summary locid="WinJS.Promise.is"> + /// Determines whether a value fulfills the promise contract. + /// </summary> + /// <param name="value" locid="WinJS.Promise.is_p:value"> + /// A value that may be a promise. + /// </param> + /// <returns type="Boolean" locid="WinJS.Promise.is_returnValue"> + /// true if the specified value is a promise, otherwise false. + /// </returns> + /// </signature> + return value && typeof value === "object" && typeof value.then === "function"; + }, + join: function Promise_join(values) { + /// <signature helpKeyword="WinJS.Promise.join"> + /// <summary locid="WinJS.Promise.join"> + /// Creates a promise that is fulfilled when all the values are fulfilled. + /// </summary> + /// <param name="values" type="Object" locid="WinJS.Promise.join_p:values"> + /// An object whose fields contain values, some of which may be promises. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.join_returnValue"> + /// A promise whose value is an object with the same field names as those of the object in the values parameter, where + /// each field value is the fulfilled value of a promise. + /// </returns> + /// </signature> + return new Promise( + function (complete, error, progress) { + var keys = Object.keys(values); + var errors = Array.isArray(values) ? [] : {}; + var results = Array.isArray(values) ? [] : {}; + var undefineds = 0; + var pending = keys.length; + var argDone = function (key) { + if ((--pending) === 0) { + var errorCount = Object.keys(errors).length; + if (errorCount === 0) { + complete(results); + } else { + var canceledCount = 0; + keys.forEach(function (key) { + var e = errors[key]; + if (e instanceof Error && e.name === canceledName) { + canceledCount++; + } + }); + if (canceledCount === errorCount) { + complete(Promise.cancel); + } else { + error(errors); + } + } + } else { + progress({ Key: key, Done: true }); + } + }; + keys.forEach(function (key) { + var value = values[key]; + if (value === undefined) { + undefineds++; + } else { + Promise.then(value, + function (value) { results[key] = value; argDone(key); }, + function (value) { errors[key] = value; argDone(key); } + ); + } + }); + pending -= undefineds; + if (pending === 0) { + complete(results); + return; + } + }, + function () { + Object.keys(values).forEach(function (key) { + var promise = Promise.as(values[key]); + if (typeof promise.cancel === "function") { + promise.cancel(); + } + }); + } + ); + }, + removeEventListener: function Promise_removeEventListener(eventType, listener, capture) { + /// <signature helpKeyword="WinJS.Promise.removeEventListener"> + /// <summary locid="WinJS.Promise.removeEventListener"> + /// Removes an event listener from the control. + /// </summary> + /// <param name='eventType' locid="WinJS.Promise.removeEventListener_eventType"> + /// The type (name) of the event. + /// </param> + /// <param name='listener' locid="WinJS.Promise.removeEventListener_listener"> + /// The listener to remove. + /// </param> + /// <param name='capture' locid="WinJS.Promise.removeEventListener_capture"> + /// Specifies whether or not to initiate capture. + /// </param> + /// </signature> + promiseEventListeners.removeEventListener(eventType, listener, capture); + }, + supportedForProcessing: false, + then: function Promise_then(value, onComplete, onError, onProgress) { + /// <signature helpKeyword="WinJS.Promise.then"> + /// <summary locid="WinJS.Promise.then"> + /// A static version of the promise instance method then(). + /// </summary> + /// <param name="value" locid="WinJS.Promise.then_p:value"> + /// the value to be treated as a promise. + /// </param> + /// <param name="onComplete" type="Function" locid="WinJS.Promise.then_p:complete"> + /// The function to be called if the promise is fulfilled with a value. + /// If it is null, the promise simply + /// returns the value. The value is passed as the single argument. + /// </param> + /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.then_p:error"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. + /// </param> + /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.then_p:progress"> + /// The function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.then_returnValue"> + /// A promise whose value is the result of executing the provided complete function. + /// </returns> + /// </signature> + return Promise.as(value).then(onComplete, onError, onProgress); + }, + thenEach: function Promise_thenEach(values, onComplete, onError, onProgress) { + /// <signature helpKeyword="WinJS.Promise.thenEach"> + /// <summary locid="WinJS.Promise.thenEach"> + /// Performs an operation on all the input promises and returns a promise + /// that has the shape of the input and contains the result of the operation + /// that has been performed on each input. + /// </summary> + /// <param name="values" locid="WinJS.Promise.thenEach_p:values"> + /// A set of values (which could be either an array or an object) of which some or all are promises. + /// </param> + /// <param name="onComplete" type="Function" locid="WinJS.Promise.thenEach_p:complete"> + /// The function to be called if the promise is fulfilled with a value. + /// If the value is null, the promise returns the value. + /// The value is passed as the single argument. + /// </param> + /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:error"> + /// The function to be called if the promise is fulfilled with an error. The error + /// is passed as the single argument. + /// </param> + /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:progress"> + /// The function to be called if the promise reports progress. Data about the progress + /// is passed as the single argument. Promises are not required to support + /// progress. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.thenEach_returnValue"> + /// A promise that is the result of calling Promise.join on the values parameter. + /// </returns> + /// </signature> + var result = Array.isArray(values) ? [] : {}; + Object.keys(values).forEach(function (key) { + result[key] = Promise.as(values[key]).then(onComplete, onError, onProgress); + }); + return Promise.join(result); + }, + timeout: function Promise_timeout(time, promise) { + /// <signature helpKeyword="WinJS.Promise.timeout"> + /// <summary locid="WinJS.Promise.timeout"> + /// Creates a promise that is fulfilled after a timeout. + /// </summary> + /// <param name="timeout" type="Number" optional="true" locid="WinJS.Promise.timeout_p:timeout"> + /// The timeout period in milliseconds. If this value is zero or not specified + /// setImmediate is called, otherwise setTimeout is called. + /// </param> + /// <param name="promise" type="Promise" optional="true" locid="WinJS.Promise.timeout_p:promise"> + /// A promise that will be canceled if it doesn't complete before the + /// timeout has expired. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.timeout_returnValue"> + /// A promise that is completed asynchronously after the specified timeout. + /// </returns> + /// </signature> + var to = timeout(time); + return promise ? timeoutWithPromise(to, promise) : to; + }, + wrap: function Promise_wrap(value) { + /// <signature helpKeyword="WinJS.Promise.wrap"> + /// <summary locid="WinJS.Promise.wrap"> + /// Wraps a non-promise value in a promise. You can use this function if you need + /// to pass a value to a function that requires a promise. + /// </summary> + /// <param name="value" locid="WinJS.Promise.wrap_p:value"> + /// Some non-promise value to be wrapped in a promise. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrap_returnValue"> + /// A promise that is successfully fulfilled with the specified value + /// </returns> + /// </signature> + return new CompletePromise(value); + }, + wrapError: function Promise_wrapError(error) { + /// <signature helpKeyword="WinJS.Promise.wrapError"> + /// <summary locid="WinJS.Promise.wrapError"> + /// Wraps a non-promise error value in a promise. You can use this function if you need + /// to pass an error to a function that requires a promise. + /// </summary> + /// <param name="error" locid="WinJS.Promise.wrapError_p:error"> + /// A non-promise error value to be wrapped in a promise. + /// </param> + /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrapError_returnValue"> + /// A promise that is in an error state with the specified value. + /// </returns> + /// </signature> + return new ErrorPromise(error); + }, + + _veryExpensiveTagWithStack: { + get: function () { return tagWithStack; }, + set: function (value) { tagWithStack = value; } + }, + _veryExpensiveTagWithStack_tag: tag, + _getStack: function () { + if (_Global.Debug && _Global.Debug.debuggerEnabled) { + try { throw new Error(); } catch (e) { return e.stack; } + } + }, + + _cancelBlocker: function Promise__cancelBlocker(input, oncancel) { + // + // Returns a promise which on cancelation will still result in downstream cancelation while + // protecting the promise 'input' from being canceled which has the effect of allowing + // 'input' to be shared amoung various consumers. + // + if (!Promise.is(input)) { + return Promise.wrap(input); + } + var complete; + var error; + var output = new Promise( + function (c, e) { + complete = c; + error = e; + }, + function () { + complete = null; + error = null; + oncancel && oncancel(); + } + ); + input.then( + function (v) { complete && complete(v); }, + function (e) { error && error(e); } + ); + return output; + }, + + } + ); + Object.defineProperties(Promise, _Events.createEventProperties(errorET)); + + Promise._doneHandler = function (value) { + _BaseCoreUtils._setImmediate(function Promise_done_rethrow() { + throw value; + }); + }; + + return { + PromiseStateMachine: PromiseStateMachine, + Promise: Promise, + state_created: state_created + }; +}); + +_winjs("WinJS/Promise", ["WinJS/Core/_Base","WinJS/Promise/_StateMachine"], function promiseInit( _Base, _StateMachine) { + "use strict"; + + _Base.Namespace.define("WinJS", { + Promise: _StateMachine.Promise + }); + + return _StateMachine.Promise; +}); + +__winjs_exports = _modules["WinJS/Core/_WinJS"]; +__winjs_exports.TPromise = __winjs_exports.Promise; +__winjs_exports.PPromise = __winjs_exports.Promise; + +// ESM-comment-begin +if (typeof exports === 'undefined' && typeof define === 'function' && define.amd) { + define([], __winjs_exports); +} else { + module.exports = __winjs_exports; +} +// ESM-comment-end + +})(); + +// ESM-uncomment-begin +// export var Promise = __winjs_exports.Promise; +// export var TPromise = __winjs_exports.TPromise; +// export var PPromise = __winjs_exports.PPromise; +// ESM-uncomment-end diff --git a/src/vs/base/common/winjs.base.raw.js b/src/vs/base/common/winjs.base.raw.js deleted file mode 100644 index 5ebe1dc10c..0000000000 --- a/src/vs/base/common/winjs.base.raw.js +++ /dev/null @@ -1,2078 +0,0 @@ -/** - * Extracted from https://github.com/winjs/winjs - * Version: 4.4.0(ec3258a9f3a36805a187848984e3bb938044178d) - * Copyright (c) Microsoft Corporation. - * All Rights Reserved. - * Licensed under the Source EULA. - */ -(function() { - -var _modules = Object.create(null);//{}; -_modules["WinJS/Core/_WinJS"] = {}; - -var _winjs = function(moduleId, deps, factory) { - var exports = {}; - var exportsPassedIn = false; - - var depsValues = deps.map(function(dep) { - if (dep === 'exports') { - exportsPassedIn = true; - return exports; - } - return _modules[dep]; - }); - - var result = factory.apply({}, depsValues); - - _modules[moduleId] = exportsPassedIn ? exports : result; -}; - - -_winjs("WinJS/Core/_Global", [], function () { - "use strict"; - - // Appease jshint - /* global window, self, global */ - - var globalObject = - typeof window !== 'undefined' ? window : - typeof self !== 'undefined' ? self : - typeof global !== 'undefined' ? global : - {}; - return globalObject; -}); - -_winjs("WinJS/Core/_BaseCoreUtils", ["WinJS/Core/_Global"], function baseCoreUtilsInit(_Global) { - "use strict"; - - var hasWinRT = !!_Global.Windows; - - function markSupportedForProcessing(func) { - /// <signature helpKeyword="WinJS.Utilities.markSupportedForProcessing"> - /// <summary locid="WinJS.Utilities.markSupportedForProcessing"> - /// Marks a function as being compatible with declarative processing, such as WinJS.UI.processAll - /// or WinJS.Binding.processAll. - /// </summary> - /// <param name="func" type="Function" locid="WinJS.Utilities.markSupportedForProcessing_p:func"> - /// The function to be marked as compatible with declarative processing. - /// </param> - /// <returns type="Function" locid="WinJS.Utilities.markSupportedForProcessing_returnValue"> - /// The input function. - /// </returns> - /// </signature> - func.supportedForProcessing = true; - return func; - } - - var actualSetImmediate = null; - - return { - hasWinRT: hasWinRT, - markSupportedForProcessing: markSupportedForProcessing, - _setImmediate: function (callback) { - // BEGIN monaco change - if (actualSetImmediate === null) { - if (_Global.setImmediate) { - actualSetImmediate = _Global.setImmediate.bind(_Global); - } else if (typeof process !== 'undefined' && typeof process.nextTick === 'function') { - actualSetImmediate = process.nextTick.bind(process); - } else { - actualSetImmediate = _Global.setTimeout.bind(_Global); - } - } - actualSetImmediate(callback); - // END monaco change - } - }; -}); -_winjs("WinJS/Core/_WriteProfilerMark", ["WinJS/Core/_Global"], function profilerInit(_Global) { - "use strict"; - - return _Global.msWriteProfilerMark || function () { }; -}); -_winjs("WinJS/Core/_Base", ["WinJS/Core/_WinJS","WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_WriteProfilerMark"], function baseInit(_WinJS, _Global, _BaseCoreUtils, _WriteProfilerMark) { - "use strict"; - - function initializeProperties(target, members, prefix) { - var keys = Object.keys(members); - var isArray = Array.isArray(target); - var properties; - var i, len; - for (i = 0, len = keys.length; i < len; i++) { - var key = keys[i]; - var enumerable = key.charCodeAt(0) !== /*_*/95; - var member = members[key]; - if (member && typeof member === 'object') { - if (member.value !== undefined || typeof member.get === 'function' || typeof member.set === 'function') { - if (member.enumerable === undefined) { - member.enumerable = enumerable; - } - if (prefix && member.setName && typeof member.setName === 'function') { - member.setName(prefix + "." + key); - } - properties = properties || {}; - properties[key] = member; - continue; - } - } - if (!enumerable) { - properties = properties || {}; - properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true }; - continue; - } - if (isArray) { - target.forEach(function (target) { - target[key] = member; - }); - } else { - target[key] = member; - } - } - if (properties) { - if (isArray) { - target.forEach(function (target) { - Object.defineProperties(target, properties); - }); - } else { - Object.defineProperties(target, properties); - } - } - } - - (function () { - - var _rootNamespace = _WinJS; - if (!_rootNamespace.Namespace) { - _rootNamespace.Namespace = Object.create(Object.prototype); - } - - function createNamespace(parentNamespace, name) { - var currentNamespace = parentNamespace || {}; - if (name) { - var namespaceFragments = name.split("."); - if (currentNamespace === _Global && namespaceFragments[0] === "WinJS") { - currentNamespace = _WinJS; - namespaceFragments.splice(0, 1); - } - for (var i = 0, len = namespaceFragments.length; i < len; i++) { - var namespaceName = namespaceFragments[i]; - if (!currentNamespace[namespaceName]) { - Object.defineProperty(currentNamespace, namespaceName, - { value: {}, writable: false, enumerable: true, configurable: true } - ); - } - currentNamespace = currentNamespace[namespaceName]; - } - } - return currentNamespace; - } - - function defineWithParent(parentNamespace, name, members) { - /// <signature helpKeyword="WinJS.Namespace.defineWithParent"> - /// <summary locid="WinJS.Namespace.defineWithParent"> - /// Defines a new namespace with the specified name under the specified parent namespace. - /// </summary> - /// <param name="parentNamespace" type="Object" locid="WinJS.Namespace.defineWithParent_p:parentNamespace"> - /// The parent namespace. - /// </param> - /// <param name="name" type="String" locid="WinJS.Namespace.defineWithParent_p:name"> - /// The name of the new namespace. - /// </param> - /// <param name="members" type="Object" locid="WinJS.Namespace.defineWithParent_p:members"> - /// The members of the new namespace. - /// </param> - /// <returns type="Object" locid="WinJS.Namespace.defineWithParent_returnValue"> - /// The newly-defined namespace. - /// </returns> - /// </signature> - var currentNamespace = createNamespace(parentNamespace, name); - - if (members) { - initializeProperties(currentNamespace, members, name || "<ANONYMOUS>"); - } - - return currentNamespace; - } - - function define(name, members) { - /// <signature helpKeyword="WinJS.Namespace.define"> - /// <summary locid="WinJS.Namespace.define"> - /// Defines a new namespace with the specified name. - /// </summary> - /// <param name="name" type="String" locid="WinJS.Namespace.define_p:name"> - /// The name of the namespace. This could be a dot-separated name for nested namespaces. - /// </param> - /// <param name="members" type="Object" locid="WinJS.Namespace.define_p:members"> - /// The members of the new namespace. - /// </param> - /// <returns type="Object" locid="WinJS.Namespace.define_returnValue"> - /// The newly-defined namespace. - /// </returns> - /// </signature> - return defineWithParent(_Global, name, members); - } - - var LazyStates = { - uninitialized: 1, - working: 2, - initialized: 3, - }; - - function lazy(f) { - var name; - var state = LazyStates.uninitialized; - var result; - return { - setName: function (value) { - name = value; - }, - get: function () { - switch (state) { - case LazyStates.initialized: - return result; - - case LazyStates.uninitialized: - state = LazyStates.working; - try { - _WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StartTM"); - result = f(); - } finally { - _WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StopTM"); - state = LazyStates.uninitialized; - } - f = null; - state = LazyStates.initialized; - return result; - - case LazyStates.working: - throw "Illegal: reentrancy on initialization"; - - default: - throw "Illegal"; - } - }, - set: function (value) { - switch (state) { - case LazyStates.working: - throw "Illegal: reentrancy on initialization"; - - default: - state = LazyStates.initialized; - result = value; - break; - } - }, - enumerable: true, - configurable: true, - }; - } - - // helper for defining AMD module members - function moduleDefine(exports, name, members) { - var target = [exports]; - var publicNS = null; - if (name) { - publicNS = createNamespace(_Global, name); - target.push(publicNS); - } - initializeProperties(target, members, name || "<ANONYMOUS>"); - return publicNS; - } - - // Establish members of the "WinJS.Namespace" namespace - Object.defineProperties(_rootNamespace.Namespace, { - - defineWithParent: { value: defineWithParent, writable: true, enumerable: true, configurable: true }, - - define: { value: define, writable: true, enumerable: true, configurable: true }, - - _lazy: { value: lazy, writable: true, enumerable: true, configurable: true }, - - _moduleDefine: { value: moduleDefine, writable: true, enumerable: true, configurable: true } - - }); - - })(); - - (function () { - - function define(constructor, instanceMembers, staticMembers) { - /// <signature helpKeyword="WinJS.Class.define"> - /// <summary locid="WinJS.Class.define"> - /// Defines a class using the given constructor and the specified instance members. - /// </summary> - /// <param name="constructor" type="Function" locid="WinJS.Class.define_p:constructor"> - /// A constructor function that is used to instantiate this class. - /// </param> - /// <param name="instanceMembers" type="Object" locid="WinJS.Class.define_p:instanceMembers"> - /// The set of instance fields, properties, and methods made available on the class. - /// </param> - /// <param name="staticMembers" type="Object" locid="WinJS.Class.define_p:staticMembers"> - /// The set of static fields, properties, and methods made available on the class. - /// </param> - /// <returns type="Function" locid="WinJS.Class.define_returnValue"> - /// The newly-defined class. - /// </returns> - /// </signature> - constructor = constructor || function () { }; - _BaseCoreUtils.markSupportedForProcessing(constructor); - if (instanceMembers) { - initializeProperties(constructor.prototype, instanceMembers); - } - if (staticMembers) { - initializeProperties(constructor, staticMembers); - } - return constructor; - } - - function derive(baseClass, constructor, instanceMembers, staticMembers) { - /// <signature helpKeyword="WinJS.Class.derive"> - /// <summary locid="WinJS.Class.derive"> - /// Creates a sub-class based on the supplied baseClass parameter, using prototypal inheritance. - /// </summary> - /// <param name="baseClass" type="Function" locid="WinJS.Class.derive_p:baseClass"> - /// The class to inherit from. - /// </param> - /// <param name="constructor" type="Function" locid="WinJS.Class.derive_p:constructor"> - /// A constructor function that is used to instantiate this class. - /// </param> - /// <param name="instanceMembers" type="Object" locid="WinJS.Class.derive_p:instanceMembers"> - /// The set of instance fields, properties, and methods to be made available on the class. - /// </param> - /// <param name="staticMembers" type="Object" locid="WinJS.Class.derive_p:staticMembers"> - /// The set of static fields, properties, and methods to be made available on the class. - /// </param> - /// <returns type="Function" locid="WinJS.Class.derive_returnValue"> - /// The newly-defined class. - /// </returns> - /// </signature> - if (baseClass) { - constructor = constructor || function () { }; - var basePrototype = baseClass.prototype; - constructor.prototype = Object.create(basePrototype); - _BaseCoreUtils.markSupportedForProcessing(constructor); - Object.defineProperty(constructor.prototype, "constructor", { value: constructor, writable: true, configurable: true, enumerable: true }); - if (instanceMembers) { - initializeProperties(constructor.prototype, instanceMembers); - } - if (staticMembers) { - initializeProperties(constructor, staticMembers); - } - return constructor; - } else { - return define(constructor, instanceMembers, staticMembers); - } - } - - function mix(constructor) { - /// <signature helpKeyword="WinJS.Class.mix"> - /// <summary locid="WinJS.Class.mix"> - /// Defines a class using the given constructor and the union of the set of instance members - /// specified by all the mixin objects. The mixin parameter list is of variable length. - /// </summary> - /// <param name="constructor" locid="WinJS.Class.mix_p:constructor"> - /// A constructor function that is used to instantiate this class. - /// </param> - /// <returns type="Function" locid="WinJS.Class.mix_returnValue"> - /// The newly-defined class. - /// </returns> - /// </signature> - constructor = constructor || function () { }; - var i, len; - for (i = 1, len = arguments.length; i < len; i++) { - initializeProperties(constructor.prototype, arguments[i]); - } - return constructor; - } - - // Establish members of "WinJS.Class" namespace - _WinJS.Namespace.define("WinJS.Class", { - define: define, - derive: derive, - mix: mix - }); - - })(); - - return { - Namespace: _WinJS.Namespace, - Class: _WinJS.Class - }; - -}); -_winjs("WinJS/Core/_ErrorFromName", ["WinJS/Core/_Base"], function errorsInit(_Base) { - "use strict"; - - var ErrorFromName = _Base.Class.derive(Error, function (name, message) { - /// <signature helpKeyword="WinJS.ErrorFromName"> - /// <summary locid="WinJS.ErrorFromName"> - /// Creates an Error object with the specified name and message properties. - /// </summary> - /// <param name="name" type="String" locid="WinJS.ErrorFromName_p:name">The name of this error. The name is meant to be consumed programmatically and should not be localized.</param> - /// <param name="message" type="String" optional="true" locid="WinJS.ErrorFromName_p:message">The message for this error. The message is meant to be consumed by humans and should be localized.</param> - /// <returns type="Error" locid="WinJS.ErrorFromName_returnValue">Error instance with .name and .message properties populated</returns> - /// </signature> - this.name = name; - this.message = message || name; - }, { - /* empty */ - }, { - supportedForProcessing: false, - }); - - _Base.Namespace.define("WinJS", { - // ErrorFromName establishes a simple pattern for returning error codes. - // - ErrorFromName: ErrorFromName - }); - - return ErrorFromName; - -}); - - -_winjs("WinJS/Core/_Events", ["exports","WinJS/Core/_Base"], function eventsInit(exports, _Base) { - "use strict"; - - - function createEventProperty(name) { - var eventPropStateName = "_on" + name + "state"; - - return { - get: function () { - var state = this[eventPropStateName]; - return state && state.userHandler; - }, - set: function (handler) { - var state = this[eventPropStateName]; - if (handler) { - if (!state) { - state = { wrapper: function (evt) { return state.userHandler(evt); }, userHandler: handler }; - Object.defineProperty(this, eventPropStateName, { value: state, enumerable: false, writable:true, configurable: true }); - this.addEventListener(name, state.wrapper, false); - } - state.userHandler = handler; - } else if (state) { - this.removeEventListener(name, state.wrapper, false); - this[eventPropStateName] = null; - } - }, - enumerable: true - }; - } - - function createEventProperties() { - /// <signature helpKeyword="WinJS.Utilities.createEventProperties"> - /// <summary locid="WinJS.Utilities.createEventProperties"> - /// Creates an object that has one property for each name passed to the function. - /// </summary> - /// <param name="events" locid="WinJS.Utilities.createEventProperties_p:events"> - /// A variable list of property names. - /// </param> - /// <returns type="Object" locid="WinJS.Utilities.createEventProperties_returnValue"> - /// The object with the specified properties. The names of the properties are prefixed with 'on'. - /// </returns> - /// </signature> - var props = {}; - for (var i = 0, len = arguments.length; i < len; i++) { - var name = arguments[i]; - props["on" + name] = createEventProperty(name); - } - return props; - } - - var EventMixinEvent = _Base.Class.define( - function EventMixinEvent_ctor(type, detail, target) { - this.detail = detail; - this.target = target; - this.timeStamp = Date.now(); - this.type = type; - }, - { - bubbles: { value: false, writable: false }, - cancelable: { value: false, writable: false }, - currentTarget: { - get: function () { return this.target; } - }, - defaultPrevented: { - get: function () { return this._preventDefaultCalled; } - }, - trusted: { value: false, writable: false }, - eventPhase: { value: 0, writable: false }, - target: null, - timeStamp: null, - type: null, - - preventDefault: function () { - this._preventDefaultCalled = true; - }, - stopImmediatePropagation: function () { - this._stopImmediatePropagationCalled = true; - }, - stopPropagation: function () { - } - }, { - supportedForProcessing: false, - } - ); - - var eventMixin = { - _listeners: null, - - addEventListener: function (type, listener, useCapture) { - /// <signature helpKeyword="WinJS.Utilities.eventMixin.addEventListener"> - /// <summary locid="WinJS.Utilities.eventMixin.addEventListener"> - /// Adds an event listener to the control. - /// </summary> - /// <param name="type" locid="WinJS.Utilities.eventMixin.addEventListener_p:type"> - /// The type (name) of the event. - /// </param> - /// <param name="listener" locid="WinJS.Utilities.eventMixin.addEventListener_p:listener"> - /// The listener to invoke when the event is raised. - /// </param> - /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.addEventListener_p:useCapture"> - /// if true initiates capture, otherwise false. - /// </param> - /// </signature> - useCapture = useCapture || false; - this._listeners = this._listeners || {}; - var eventListeners = (this._listeners[type] = this._listeners[type] || []); - for (var i = 0, len = eventListeners.length; i < len; i++) { - var l = eventListeners[i]; - if (l.useCapture === useCapture && l.listener === listener) { - return; - } - } - eventListeners.push({ listener: listener, useCapture: useCapture }); - }, - dispatchEvent: function (type, details) { - /// <signature helpKeyword="WinJS.Utilities.eventMixin.dispatchEvent"> - /// <summary locid="WinJS.Utilities.eventMixin.dispatchEvent"> - /// Raises an event of the specified type and with the specified additional properties. - /// </summary> - /// <param name="type" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:type"> - /// The type (name) of the event. - /// </param> - /// <param name="details" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:details"> - /// The set of additional properties to be attached to the event object when the event is raised. - /// </param> - /// <returns type="Boolean" locid="WinJS.Utilities.eventMixin.dispatchEvent_returnValue"> - /// true if preventDefault was called on the event. - /// </returns> - /// </signature> - var listeners = this._listeners && this._listeners[type]; - if (listeners) { - var eventValue = new EventMixinEvent(type, details, this); - // Need to copy the array to protect against people unregistering while we are dispatching - listeners = listeners.slice(0, listeners.length); - for (var i = 0, len = listeners.length; i < len && !eventValue._stopImmediatePropagationCalled; i++) { - listeners[i].listener(eventValue); - } - return eventValue.defaultPrevented || false; - } - return false; - }, - removeEventListener: function (type, listener, useCapture) { - /// <signature helpKeyword="WinJS.Utilities.eventMixin.removeEventListener"> - /// <summary locid="WinJS.Utilities.eventMixin.removeEventListener"> - /// Removes an event listener from the control. - /// </summary> - /// <param name="type" locid="WinJS.Utilities.eventMixin.removeEventListener_p:type"> - /// The type (name) of the event. - /// </param> - /// <param name="listener" locid="WinJS.Utilities.eventMixin.removeEventListener_p:listener"> - /// The listener to remove. - /// </param> - /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.removeEventListener_p:useCapture"> - /// Specifies whether to initiate capture. - /// </param> - /// </signature> - useCapture = useCapture || false; - var listeners = this._listeners && this._listeners[type]; - if (listeners) { - for (var i = 0, len = listeners.length; i < len; i++) { - var l = listeners[i]; - if (l.listener === listener && l.useCapture === useCapture) { - listeners.splice(i, 1); - if (listeners.length === 0) { - delete this._listeners[type]; - } - // Only want to remove one element for each call to removeEventListener - break; - } - } - } - } - }; - - _Base.Namespace._moduleDefine(exports, "WinJS.Utilities", { - _createEventProperty: createEventProperty, - createEventProperties: createEventProperties, - eventMixin: eventMixin - }); - -}); - - -_winjs("WinJS/Core/_Trace", ["WinJS/Core/_Global"], function traceInit(_Global) { - "use strict"; - - function nop(v) { - return v; - } - - return { - _traceAsyncOperationStarting: (_Global.Debug && _Global.Debug.msTraceAsyncOperationStarting && _Global.Debug.msTraceAsyncOperationStarting.bind(_Global.Debug)) || nop, - _traceAsyncOperationCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncOperationCompleted && _Global.Debug.msTraceAsyncOperationCompleted.bind(_Global.Debug)) || nop, - _traceAsyncCallbackStarting: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackStarting && _Global.Debug.msTraceAsyncCallbackStarting.bind(_Global.Debug)) || nop, - _traceAsyncCallbackCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackCompleted && _Global.Debug.msTraceAsyncCallbackCompleted.bind(_Global.Debug)) || nop - }; -}); -_winjs("WinJS/Promise/_StateMachine", ["WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_Base","WinJS/Core/_ErrorFromName","WinJS/Core/_Events","WinJS/Core/_Trace"], function promiseStateMachineInit(_Global, _BaseCoreUtils, _Base, _ErrorFromName, _Events, _Trace) { - "use strict"; - - _Global.Debug && (_Global.Debug.setNonUserCodeExceptions = true); - - var ListenerType = _Base.Class.mix(_Base.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), _Events.eventMixin); - var promiseEventListeners = new ListenerType(); - // make sure there is a listeners collection so that we can do a more trivial check below - promiseEventListeners._listeners = {}; - var errorET = "error"; - var canceledName = "Canceled"; - var tagWithStack = false; - var tag = { - promise: 0x01, - thenPromise: 0x02, - errorPromise: 0x04, - exceptionPromise: 0x08, - completePromise: 0x10, - }; - tag.all = tag.promise | tag.thenPromise | tag.errorPromise | tag.exceptionPromise | tag.completePromise; - - // - // Global error counter, for each error which enters the system we increment this once and then - // the error number travels with the error as it traverses the tree of potential handlers. - // - // When someone has registered to be told about errors (WinJS.Promise.callonerror) promises - // which are in error will get tagged with a ._errorId field. This tagged field is the - // contract by which nested promises with errors will be identified as chaining for the - // purposes of the callonerror semantics. If a nested promise in error is encountered without - // a ._errorId it will be assumed to be foreign and treated as an interop boundary and - // a new error id will be minted. - // - var error_number = 1; - - // - // The state machine has a interesting hiccup in it with regards to notification, in order - // to flatten out notification and avoid recursion for synchronous completion we have an - // explicit set of *_notify states which are responsible for notifying their entire tree - // of children. They can do this because they know that immediate children are always - // ThenPromise instances and we can therefore reach into their state to access the - // _listeners collection. - // - // So, what happens is that a Promise will be fulfilled through the _completed or _error - // messages at which point it will enter a *_notify state and be responsible for to move - // its children into an (as appropriate) success or error state and also notify that child's - // listeners of the state transition, until leaf notes are reached. - // - - var state_created, // -> working - state_working, // -> error | error_notify | success | success_notify | canceled | waiting - state_waiting, // -> error | error_notify | success | success_notify | waiting_canceled - state_waiting_canceled, // -> error | error_notify | success | success_notify | canceling - state_canceled, // -> error | error_notify | success | success_notify | canceling - state_canceling, // -> error_notify - state_success_notify, // -> success - state_success, // -> . - state_error_notify, // -> error - state_error; // -> . - - // Noop function, used in the various states to indicate that they don't support a given - // message. Named with the somewhat cute name '_' because it reads really well in the states. - - function _() { } - - // Initial state - // - state_created = { - name: "created", - enter: function (promise) { - promise._setState(state_working); - }, - cancel: _, - done: _, - then: _, - _completed: _, - _error: _, - _notify: _, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Ready state, waiting for a message (completed/error/progress), able to be canceled - // - state_working = { - name: "working", - enter: _, - cancel: function (promise) { - promise._setState(state_canceled); - }, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Waiting state, if a promise is completed with a value which is itself a promise - // (has a then() method) it signs up to be informed when that child promise is - // fulfilled at which point it will be fulfilled with that value. - // - state_waiting = { - name: "waiting", - enter: function (promise) { - var waitedUpon = promise._value; - // We can special case our own intermediate promises which are not in a - // terminal state by just pushing this promise as a listener without - // having to create new indirection functions - if (waitedUpon instanceof ThenPromise && - waitedUpon._state !== state_error && - waitedUpon._state !== state_success) { - pushListener(waitedUpon, { promise: promise }); - } else { - var error = function (value) { - if (waitedUpon._errorId) { - promise._chainedError(value, waitedUpon); - } else { - // Because this is an interop boundary we want to indicate that this - // error has been handled by the promise infrastructure before we - // begin a new handling chain. - // - callonerror(promise, value, detailsForHandledError, waitedUpon, error); - promise._error(value); - } - }; - error.handlesOnError = true; - waitedUpon.then( - promise._completed.bind(promise), - error, - promise._progress.bind(promise) - ); - } - }, - cancel: function (promise) { - promise._setState(state_waiting_canceled); - }, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Waiting canceled state, when a promise has been in a waiting state and receives a - // request to cancel its pending work it will forward that request to the child promise - // and then waits to be informed of the result. This promise moves itself into the - // canceling state but understands that the child promise may instead push it to a - // different state. - // - state_waiting_canceled = { - name: "waiting_canceled", - enter: function (promise) { - // Initiate a transition to canceling. Triggering a cancel on the promise - // that we are waiting upon may result in a different state transition - // before the state machine pump runs again. - promise._setState(state_canceling); - var waitedUpon = promise._value; - if (waitedUpon.cancel) { - waitedUpon.cancel(); - } - }, - cancel: _, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Canceled state, moves to the canceling state and then tells the promise to do - // whatever it might need to do on cancelation. - // - state_canceled = { - name: "canceled", - enter: function (promise) { - // Initiate a transition to canceling. The _cancelAction may change the state - // before the state machine pump runs again. - promise._setState(state_canceling); - promise._cancelAction(); - }, - cancel: _, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Canceling state, commits to the promise moving to an error state with an error - // object whose 'name' and 'message' properties contain the string "Canceled" - // - state_canceling = { - name: "canceling", - enter: function (promise) { - var error = new Error(canceledName); - error.name = error.message; - promise._value = error; - promise._setState(state_error_notify); - }, - cancel: _, - done: _, - then: _, - _completed: _, - _error: _, - _notify: _, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Success notify state, moves a promise to the success state and notifies all children - // - state_success_notify = { - name: "complete_notify", - enter: function (promise) { - promise.done = CompletePromise.prototype.done; - promise.then = CompletePromise.prototype.then; - if (promise._listeners) { - var queue = [promise]; - var p; - while (queue.length) { - p = queue.shift(); - p._state._notify(p, queue); - } - } - promise._setState(state_success); - }, - cancel: _, - done: null, /*error to get here */ - then: null, /*error to get here */ - _completed: _, - _error: _, - _notify: notifySuccess, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Success state, moves a promise to the success state and does NOT notify any children. - // Some upstream promise is owning the notification pass. - // - state_success = { - name: "success", - enter: function (promise) { - promise.done = CompletePromise.prototype.done; - promise.then = CompletePromise.prototype.then; - promise._cleanupAction(); - }, - cancel: _, - done: null, /*error to get here */ - then: null, /*error to get here */ - _completed: _, - _error: _, - _notify: notifySuccess, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Error notify state, moves a promise to the error state and notifies all children - // - state_error_notify = { - name: "error_notify", - enter: function (promise) { - promise.done = ErrorPromise.prototype.done; - promise.then = ErrorPromise.prototype.then; - if (promise._listeners) { - var queue = [promise]; - var p; - while (queue.length) { - p = queue.shift(); - p._state._notify(p, queue); - } - } - promise._setState(state_error); - }, - cancel: _, - done: null, /*error to get here*/ - then: null, /*error to get here*/ - _completed: _, - _error: _, - _notify: notifyError, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Error state, moves a promise to the error state and does NOT notify any children. - // Some upstream promise is owning the notification pass. - // - state_error = { - name: "error", - enter: function (promise) { - promise.done = ErrorPromise.prototype.done; - promise.then = ErrorPromise.prototype.then; - promise._cleanupAction(); - }, - cancel: _, - done: null, /*error to get here*/ - then: null, /*error to get here*/ - _completed: _, - _error: _, - _notify: notifyError, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // - // The statemachine implementation follows a very particular pattern, the states are specified - // as static stateless bags of functions which are then indirected through the state machine - // instance (a Promise). As such all of the functions on each state have the promise instance - // passed to them explicitly as a parameter and the Promise instance members do a little - // dance where they indirect through the state and insert themselves in the argument list. - // - // We could instead call directly through the promise states however then every caller - // would have to remember to do things like pumping the state machine to catch state transitions. - // - - var PromiseStateMachine = _Base.Class.define(null, { - _listeners: null, - _nextState: null, - _state: null, - _value: null, - - cancel: function () { - /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> - /// <summary locid="WinJS.PromiseStateMachine.cancel"> - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// </summary> - /// </signature> - this._state.cancel(this); - this._run(); - }, - done: function Promise_done(onComplete, onError, onProgress) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> - /// <summary locid="WinJS.PromiseStateMachine.done"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// </signature> - this._state.done(this, onComplete, onError, onProgress); - }, - then: function Promise_then(onComplete, onError, onProgress) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> - /// <summary locid="WinJS.PromiseStateMachine.then"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> - /// The promise whose value is the result of executing the complete or - /// error function. - /// </returns> - /// </signature> - return this._state.then(this, onComplete, onError, onProgress); - }, - - _chainedError: function (value, context) { - var result = this._state._error(this, value, detailsForChainedError, context); - this._run(); - return result; - }, - _completed: function (value) { - var result = this._state._completed(this, value); - this._run(); - return result; - }, - _error: function (value) { - var result = this._state._error(this, value, detailsForError); - this._run(); - return result; - }, - _progress: function (value) { - this._state._progress(this, value); - }, - _setState: function (state) { - this._nextState = state; - }, - _setCompleteValue: function (value) { - this._state._setCompleteValue(this, value); - this._run(); - }, - _setChainedErrorValue: function (value, context) { - var result = this._state._setErrorValue(this, value, detailsForChainedError, context); - this._run(); - return result; - }, - _setExceptionValue: function (value) { - var result = this._state._setErrorValue(this, value, detailsForException); - this._run(); - return result; - }, - _run: function () { - while (this._nextState) { - this._state = this._nextState; - this._nextState = null; - this._state.enter(this); - } - } - }, { - supportedForProcessing: false - }); - - // - // Implementations of shared state machine code. - // - - function completed(promise, value) { - var targetState; - if (value && typeof value === "object" && typeof value.then === "function") { - targetState = state_waiting; - } else { - targetState = state_success_notify; - } - promise._value = value; - promise._setState(targetState); - } - function createErrorDetails(exception, error, promise, id, parent, handler) { - return { - exception: exception, - error: error, - promise: promise, - handler: handler, - id: id, - parent: parent - }; - } - function detailsForHandledError(promise, errorValue, context, handler) { - var exception = context._isException; - var errorId = context._errorId; - return createErrorDetails( - exception ? errorValue : null, - exception ? null : errorValue, - promise, - errorId, - context, - handler - ); - } - function detailsForChainedError(promise, errorValue, context) { - var exception = context._isException; - var errorId = context._errorId; - setErrorInfo(promise, errorId, exception); - return createErrorDetails( - exception ? errorValue : null, - exception ? null : errorValue, - promise, - errorId, - context - ); - } - function detailsForError(promise, errorValue) { - var errorId = ++error_number; - setErrorInfo(promise, errorId); - return createErrorDetails( - null, - errorValue, - promise, - errorId - ); - } - function detailsForException(promise, exceptionValue) { - var errorId = ++error_number; - setErrorInfo(promise, errorId, true); - return createErrorDetails( - exceptionValue, - null, - promise, - errorId - ); - } - function done(promise, onComplete, onError, onProgress) { - var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.done"); - pushListener(promise, { c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); - } - function error(promise, value, onerrorDetails, context) { - promise._value = value; - callonerror(promise, value, onerrorDetails, context); - promise._setState(state_error_notify); - } - function notifySuccess(promise, queue) { - var value = promise._value; - var listeners = promise._listeners; - if (!listeners) { - return; - } - promise._listeners = null; - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onComplete = listener.c; - var target = listener.promise; - - _Trace._traceAsyncOperationCompleted(listener.asyncOpID, _Global.Debug && _Global.Debug.MS_ASYNC_OP_STATUS_SUCCESS); - - if (target) { - _Trace._traceAsyncCallbackStarting(listener.asyncOpID); - try { - target._setCompleteValue(onComplete ? onComplete(value) : value); - } catch (ex) { - target._setExceptionValue(ex); - } finally { - _Trace._traceAsyncCallbackCompleted(); - } - if (target._state !== state_waiting && target._listeners) { - queue.push(target); - } - } else { - CompletePromise.prototype.done.call(promise, onComplete); - } - } - } - function notifyError(promise, queue) { - var value = promise._value; - var listeners = promise._listeners; - if (!listeners) { - return; - } - promise._listeners = null; - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onError = listener.e; - var target = listener.promise; - - var errorID = _Global.Debug && (value && value.name === canceledName ? _Global.Debug.MS_ASYNC_OP_STATUS_CANCELED : _Global.Debug.MS_ASYNC_OP_STATUS_ERROR); - _Trace._traceAsyncOperationCompleted(listener.asyncOpID, errorID); - - if (target) { - var asyncCallbackStarted = false; - try { - if (onError) { - _Trace._traceAsyncCallbackStarting(listener.asyncOpID); - asyncCallbackStarted = true; - if (!onError.handlesOnError) { - callonerror(target, value, detailsForHandledError, promise, onError); - } - target._setCompleteValue(onError(value)); - } else { - target._setChainedErrorValue(value, promise); - } - } catch (ex) { - target._setExceptionValue(ex); - } finally { - if (asyncCallbackStarted) { - _Trace._traceAsyncCallbackCompleted(); - } - } - if (target._state !== state_waiting && target._listeners) { - queue.push(target); - } - } else { - ErrorPromise.prototype.done.call(promise, null, onError); - } - } - } - function callonerror(promise, value, onerrorDetailsGenerator, context, handler) { - if (promiseEventListeners._listeners[errorET]) { - if (value instanceof Error && value.message === canceledName) { - return; - } - promiseEventListeners.dispatchEvent(errorET, onerrorDetailsGenerator(promise, value, context, handler)); - } - } - function progress(promise, value) { - var listeners = promise._listeners; - if (listeners) { - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onProgress = listener.p; - if (onProgress) { - try { onProgress(value); } catch (ex) { } - } - if (!(listener.c || listener.e) && listener.promise) { - listener.promise._progress(value); - } - } - } - } - function pushListener(promise, listener) { - var listeners = promise._listeners; - if (listeners) { - // We may have either a single listener (which will never be wrapped in an array) - // or 2+ listeners (which will be wrapped). Since we are now adding one more listener - // we may have to wrap the single listener before adding the second. - listeners = Array.isArray(listeners) ? listeners : [listeners]; - listeners.push(listener); - } else { - listeners = listener; - } - promise._listeners = listeners; - } - // The difference beween setCompleteValue()/setErrorValue() and complete()/error() is that setXXXValue() moves - // a promise directly to the success/error state without starting another notification pass (because one - // is already ongoing). - function setErrorInfo(promise, errorId, isException) { - promise._isException = isException || false; - promise._errorId = errorId; - } - function setErrorValue(promise, value, onerrorDetails, context) { - promise._value = value; - callonerror(promise, value, onerrorDetails, context); - promise._setState(state_error); - } - function setCompleteValue(promise, value) { - var targetState; - if (value && typeof value === "object" && typeof value.then === "function") { - targetState = state_waiting; - } else { - targetState = state_success; - } - promise._value = value; - promise._setState(targetState); - } - function then(promise, onComplete, onError, onProgress) { - var result = new ThenPromise(promise); - var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.then"); - pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); - return result; - } - - // - // Internal implementation detail promise, ThenPromise is created when a promise needs - // to be returned from a then() method. - // - var ThenPromise = _Base.Class.derive(PromiseStateMachine, - function (creator) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) { - this._stack = Promise._getStack(); - } - - this._creator = creator; - this._setState(state_created); - this._run(); - }, { - _creator: null, - - _cancelAction: function () { if (this._creator) { this._creator.cancel(); } }, - _cleanupAction: function () { this._creator = null; } - }, { - supportedForProcessing: false - } - ); - - // - // Slim promise implementations for already completed promises, these are created - // under the hood on synchronous completion paths as well as by WinJS.Promise.wrap - // and WinJS.Promise.wrapError. - // - - var ErrorPromise = _Base.Class.define( - function ErrorPromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) { - this._stack = Promise._getStack(); - } - - this._value = value; - callonerror(this, value, detailsForError); - }, { - cancel: function () { - /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> - /// <summary locid="WinJS.PromiseStateMachine.cancel"> - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// </summary> - /// </signature> - }, - done: function ErrorPromise_done(unused, onError) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> - /// <summary locid="WinJS.PromiseStateMachine.done"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// </signature> - var value = this._value; - if (onError) { - try { - if (!onError.handlesOnError) { - callonerror(null, value, detailsForHandledError, this, onError); - } - var result = onError(value); - if (result && typeof result === "object" && typeof result.done === "function") { - // If a promise is returned we need to wait on it. - result.done(); - } - return; - } catch (ex) { - value = ex; - } - } - if (value instanceof Error && value.message === canceledName) { - // suppress cancel - return; - } - // force the exception to be thrown asyncronously to avoid any try/catch blocks - // - Promise._doneHandler(value); - }, - then: function ErrorPromise_then(unused, onError) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> - /// <summary locid="WinJS.PromiseStateMachine.then"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> - /// The promise whose value is the result of executing the complete or - /// error function. - /// </returns> - /// </signature> - - // If the promise is already in a error state and no error handler is provided - // we optimize by simply returning the promise instead of creating a new one. - // - if (!onError) { return this; } - var result; - var value = this._value; - try { - if (!onError.handlesOnError) { - callonerror(null, value, detailsForHandledError, this, onError); - } - result = new CompletePromise(onError(value)); - } catch (ex) { - // If the value throw from the error handler is the same as the value - // provided to the error handler then there is no need for a new promise. - // - if (ex === value) { - result = this; - } else { - result = new ExceptionPromise(ex); - } - } - return result; - } - }, { - supportedForProcessing: false - } - ); - - var ExceptionPromise = _Base.Class.derive(ErrorPromise, - function ExceptionPromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) { - this._stack = Promise._getStack(); - } - - this._value = value; - callonerror(this, value, detailsForException); - }, { - /* empty */ - }, { - supportedForProcessing: false - } - ); - - var CompletePromise = _Base.Class.define( - function CompletePromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) { - this._stack = Promise._getStack(); - } - - if (value && typeof value === "object" && typeof value.then === "function") { - var result = new ThenPromise(null); - result._setCompleteValue(value); - return result; - } - this._value = value; - }, { - cancel: function () { - /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> - /// <summary locid="WinJS.PromiseStateMachine.cancel"> - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// </summary> - /// </signature> - }, - done: function CompletePromise_done(onComplete) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> - /// <summary locid="WinJS.PromiseStateMachine.done"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// </signature> - if (!onComplete) { return; } - try { - var result = onComplete(this._value); - if (result && typeof result === "object" && typeof result.done === "function") { - result.done(); - } - } catch (ex) { - // force the exception to be thrown asynchronously to avoid any try/catch blocks - Promise._doneHandler(ex); - } - }, - then: function CompletePromise_then(onComplete) { - /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> - /// <summary locid="WinJS.PromiseStateMachine.then"> - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// </summary> - /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// </param> - /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// </param> - /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> - /// The promise whose value is the result of executing the complete or - /// error function. - /// </returns> - /// </signature> - try { - // If the value returned from the completion handler is the same as the value - // provided to the completion handler then there is no need for a new promise. - // - var newValue = onComplete ? onComplete(this._value) : this._value; - return newValue === this._value ? this : new CompletePromise(newValue); - } catch (ex) { - return new ExceptionPromise(ex); - } - } - }, { - supportedForProcessing: false - } - ); - - // - // Promise is the user-creatable WinJS.Promise object. - // - - function timeout(timeoutMS) { - var id; - return new Promise( - function (c) { - if (timeoutMS) { - id = _Global.setTimeout(c, timeoutMS); - } else { - _BaseCoreUtils._setImmediate(c); - } - }, - function () { - if (id) { - _Global.clearTimeout(id); - } - } - ); - } - - function timeoutWithPromise(timeout, promise) { - var cancelPromise = function () { promise.cancel(); }; - var cancelTimeout = function () { timeout.cancel(); }; - timeout.then(cancelPromise); - promise.then(cancelTimeout, cancelTimeout); - return promise; - } - - var staticCanceledPromise; - - var Promise = _Base.Class.derive(PromiseStateMachine, - function Promise_ctor(init, oncancel) { - /// <signature helpKeyword="WinJS.Promise"> - /// <summary locid="WinJS.Promise"> - /// A promise provides a mechanism to schedule work to be done on a value that - /// has not yet been computed. It is a convenient abstraction for managing - /// interactions with asynchronous APIs. - /// </summary> - /// <param name="init" type="Function" locid="WinJS.Promise_p:init"> - /// The function that is called during construction of the promise. The function - /// is given three arguments (complete, error, progress). Inside this function - /// you should add event listeners for the notifications supported by this value. - /// </param> - /// <param name="oncancel" optional="true" locid="WinJS.Promise_p:oncancel"> - /// The function to call if a consumer of this promise wants - /// to cancel its undone work. Promises are not required to - /// support cancellation. - /// </param> - /// </signature> - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.promise))) { - this._stack = Promise._getStack(); - } - - this._oncancel = oncancel; - this._setState(state_created); - this._run(); - - try { - var complete = this._completed.bind(this); - var error = this._error.bind(this); - var progress = this._progress.bind(this); - init(complete, error, progress); - } catch (ex) { - this._setExceptionValue(ex); - } - }, { - _oncancel: null, - - _cancelAction: function () { - // BEGIN monaco change - try { - if (this._oncancel) { - this._oncancel(); - } else { - throw new Error('Promise did not implement oncancel'); - } - } catch (ex) { - // Access fields to get them created - var msg = ex.message; - var stack = ex.stack; - promiseEventListeners.dispatchEvent('error', ex); - } - // END monaco change - }, - _cleanupAction: function () { this._oncancel = null; } - }, { - - addEventListener: function Promise_addEventListener(eventType, listener, capture) { - /// <signature helpKeyword="WinJS.Promise.addEventListener"> - /// <summary locid="WinJS.Promise.addEventListener"> - /// Adds an event listener to the control. - /// </summary> - /// <param name="eventType" locid="WinJS.Promise.addEventListener_p:eventType"> - /// The type (name) of the event. - /// </param> - /// <param name="listener" locid="WinJS.Promise.addEventListener_p:listener"> - /// The listener to invoke when the event is raised. - /// </param> - /// <param name="capture" locid="WinJS.Promise.addEventListener_p:capture"> - /// Specifies whether or not to initiate capture. - /// </param> - /// </signature> - promiseEventListeners.addEventListener(eventType, listener, capture); - }, - any: function Promise_any(values) { - /// <signature helpKeyword="WinJS.Promise.any"> - /// <summary locid="WinJS.Promise.any"> - /// Returns a promise that is fulfilled when one of the input promises - /// has been fulfilled. - /// </summary> - /// <param name="values" type="Array" locid="WinJS.Promise.any_p:values"> - /// An array that contains promise objects or objects whose property - /// values include promise objects. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.any_returnValue"> - /// A promise that on fulfillment yields the value of the input (complete or error). - /// </returns> - /// </signature> - return new Promise( - function (complete, error) { - var keys = Object.keys(values); - if (keys.length === 0) { - complete(); - } - var canceled = 0; - keys.forEach(function (key) { - Promise.as(values[key]).then( - function () { complete({ key: key, value: values[key] }); }, - function (e) { - if (e instanceof Error && e.name === canceledName) { - if ((++canceled) === keys.length) { - complete(Promise.cancel); - } - return; - } - error({ key: key, value: values[key] }); - } - ); - }); - }, - function () { - var keys = Object.keys(values); - keys.forEach(function (key) { - var promise = Promise.as(values[key]); - if (typeof promise.cancel === "function") { - promise.cancel(); - } - }); - } - ); - }, - as: function Promise_as(value) { - /// <signature helpKeyword="WinJS.Promise.as"> - /// <summary locid="WinJS.Promise.as"> - /// Returns a promise. If the object is already a promise it is returned; - /// otherwise the object is wrapped in a promise. - /// </summary> - /// <param name="value" locid="WinJS.Promise.as_p:value"> - /// The value to be treated as a promise. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.as_returnValue"> - /// A promise. - /// </returns> - /// </signature> - if (value && typeof value === "object" && typeof value.then === "function") { - return value; - } - return new CompletePromise(value); - }, - /// <field type="WinJS.Promise" helpKeyword="WinJS.Promise.cancel" locid="WinJS.Promise.cancel"> - /// Canceled promise value, can be returned from a promise completion handler - /// to indicate cancelation of the promise chain. - /// </field> - cancel: { - get: function () { - return (staticCanceledPromise = staticCanceledPromise || new ErrorPromise(new _ErrorFromName(canceledName))); - } - }, - dispatchEvent: function Promise_dispatchEvent(eventType, details) { - /// <signature helpKeyword="WinJS.Promise.dispatchEvent"> - /// <summary locid="WinJS.Promise.dispatchEvent"> - /// Raises an event of the specified type and properties. - /// </summary> - /// <param name="eventType" locid="WinJS.Promise.dispatchEvent_p:eventType"> - /// The type (name) of the event. - /// </param> - /// <param name="details" locid="WinJS.Promise.dispatchEvent_p:details"> - /// The set of additional properties to be attached to the event object. - /// </param> - /// <returns type="Boolean" locid="WinJS.Promise.dispatchEvent_returnValue"> - /// Specifies whether preventDefault was called on the event. - /// </returns> - /// </signature> - return promiseEventListeners.dispatchEvent(eventType, details); - }, - is: function Promise_is(value) { - /// <signature helpKeyword="WinJS.Promise.is"> - /// <summary locid="WinJS.Promise.is"> - /// Determines whether a value fulfills the promise contract. - /// </summary> - /// <param name="value" locid="WinJS.Promise.is_p:value"> - /// A value that may be a promise. - /// </param> - /// <returns type="Boolean" locid="WinJS.Promise.is_returnValue"> - /// true if the specified value is a promise, otherwise false. - /// </returns> - /// </signature> - return value && typeof value === "object" && typeof value.then === "function"; - }, - join: function Promise_join(values) { - /// <signature helpKeyword="WinJS.Promise.join"> - /// <summary locid="WinJS.Promise.join"> - /// Creates a promise that is fulfilled when all the values are fulfilled. - /// </summary> - /// <param name="values" type="Object" locid="WinJS.Promise.join_p:values"> - /// An object whose fields contain values, some of which may be promises. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.join_returnValue"> - /// A promise whose value is an object with the same field names as those of the object in the values parameter, where - /// each field value is the fulfilled value of a promise. - /// </returns> - /// </signature> - return new Promise( - function (complete, error, progress) { - var keys = Object.keys(values); - var errors = Array.isArray(values) ? [] : {}; - var results = Array.isArray(values) ? [] : {}; - var undefineds = 0; - var pending = keys.length; - var argDone = function (key) { - if ((--pending) === 0) { - var errorCount = Object.keys(errors).length; - if (errorCount === 0) { - complete(results); - } else { - var canceledCount = 0; - keys.forEach(function (key) { - var e = errors[key]; - if (e instanceof Error && e.name === canceledName) { - canceledCount++; - } - }); - if (canceledCount === errorCount) { - complete(Promise.cancel); - } else { - error(errors); - } - } - } else { - progress({ Key: key, Done: true }); - } - }; - keys.forEach(function (key) { - var value = values[key]; - if (value === undefined) { - undefineds++; - } else { - Promise.then(value, - function (value) { results[key] = value; argDone(key); }, - function (value) { errors[key] = value; argDone(key); } - ); - } - }); - pending -= undefineds; - if (pending === 0) { - complete(results); - return; - } - }, - function () { - Object.keys(values).forEach(function (key) { - var promise = Promise.as(values[key]); - if (typeof promise.cancel === "function") { - promise.cancel(); - } - }); - } - ); - }, - removeEventListener: function Promise_removeEventListener(eventType, listener, capture) { - /// <signature helpKeyword="WinJS.Promise.removeEventListener"> - /// <summary locid="WinJS.Promise.removeEventListener"> - /// Removes an event listener from the control. - /// </summary> - /// <param name='eventType' locid="WinJS.Promise.removeEventListener_eventType"> - /// The type (name) of the event. - /// </param> - /// <param name='listener' locid="WinJS.Promise.removeEventListener_listener"> - /// The listener to remove. - /// </param> - /// <param name='capture' locid="WinJS.Promise.removeEventListener_capture"> - /// Specifies whether or not to initiate capture. - /// </param> - /// </signature> - promiseEventListeners.removeEventListener(eventType, listener, capture); - }, - supportedForProcessing: false, - then: function Promise_then(value, onComplete, onError, onProgress) { - /// <signature helpKeyword="WinJS.Promise.then"> - /// <summary locid="WinJS.Promise.then"> - /// A static version of the promise instance method then(). - /// </summary> - /// <param name="value" locid="WinJS.Promise.then_p:value"> - /// the value to be treated as a promise. - /// </param> - /// <param name="onComplete" type="Function" locid="WinJS.Promise.then_p:complete"> - /// The function to be called if the promise is fulfilled with a value. - /// If it is null, the promise simply - /// returns the value. The value is passed as the single argument. - /// </param> - /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.then_p:error"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. - /// </param> - /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.then_p:progress"> - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.then_returnValue"> - /// A promise whose value is the result of executing the provided complete function. - /// </returns> - /// </signature> - return Promise.as(value).then(onComplete, onError, onProgress); - }, - thenEach: function Promise_thenEach(values, onComplete, onError, onProgress) { - /// <signature helpKeyword="WinJS.Promise.thenEach"> - /// <summary locid="WinJS.Promise.thenEach"> - /// Performs an operation on all the input promises and returns a promise - /// that has the shape of the input and contains the result of the operation - /// that has been performed on each input. - /// </summary> - /// <param name="values" locid="WinJS.Promise.thenEach_p:values"> - /// A set of values (which could be either an array or an object) of which some or all are promises. - /// </param> - /// <param name="onComplete" type="Function" locid="WinJS.Promise.thenEach_p:complete"> - /// The function to be called if the promise is fulfilled with a value. - /// If the value is null, the promise returns the value. - /// The value is passed as the single argument. - /// </param> - /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:error"> - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. - /// </param> - /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:progress"> - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.thenEach_returnValue"> - /// A promise that is the result of calling Promise.join on the values parameter. - /// </returns> - /// </signature> - var result = Array.isArray(values) ? [] : {}; - Object.keys(values).forEach(function (key) { - result[key] = Promise.as(values[key]).then(onComplete, onError, onProgress); - }); - return Promise.join(result); - }, - timeout: function Promise_timeout(time, promise) { - /// <signature helpKeyword="WinJS.Promise.timeout"> - /// <summary locid="WinJS.Promise.timeout"> - /// Creates a promise that is fulfilled after a timeout. - /// </summary> - /// <param name="timeout" type="Number" optional="true" locid="WinJS.Promise.timeout_p:timeout"> - /// The timeout period in milliseconds. If this value is zero or not specified - /// setImmediate is called, otherwise setTimeout is called. - /// </param> - /// <param name="promise" type="Promise" optional="true" locid="WinJS.Promise.timeout_p:promise"> - /// A promise that will be canceled if it doesn't complete before the - /// timeout has expired. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.timeout_returnValue"> - /// A promise that is completed asynchronously after the specified timeout. - /// </returns> - /// </signature> - var to = timeout(time); - return promise ? timeoutWithPromise(to, promise) : to; - }, - wrap: function Promise_wrap(value) { - /// <signature helpKeyword="WinJS.Promise.wrap"> - /// <summary locid="WinJS.Promise.wrap"> - /// Wraps a non-promise value in a promise. You can use this function if you need - /// to pass a value to a function that requires a promise. - /// </summary> - /// <param name="value" locid="WinJS.Promise.wrap_p:value"> - /// Some non-promise value to be wrapped in a promise. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrap_returnValue"> - /// A promise that is successfully fulfilled with the specified value - /// </returns> - /// </signature> - return new CompletePromise(value); - }, - wrapError: function Promise_wrapError(error) { - /// <signature helpKeyword="WinJS.Promise.wrapError"> - /// <summary locid="WinJS.Promise.wrapError"> - /// Wraps a non-promise error value in a promise. You can use this function if you need - /// to pass an error to a function that requires a promise. - /// </summary> - /// <param name="error" locid="WinJS.Promise.wrapError_p:error"> - /// A non-promise error value to be wrapped in a promise. - /// </param> - /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrapError_returnValue"> - /// A promise that is in an error state with the specified value. - /// </returns> - /// </signature> - return new ErrorPromise(error); - }, - - _veryExpensiveTagWithStack: { - get: function () { return tagWithStack; }, - set: function (value) { tagWithStack = value; } - }, - _veryExpensiveTagWithStack_tag: tag, - _getStack: function () { - if (_Global.Debug && _Global.Debug.debuggerEnabled) { - try { throw new Error(); } catch (e) { return e.stack; } - } - }, - - _cancelBlocker: function Promise__cancelBlocker(input, oncancel) { - // - // Returns a promise which on cancelation will still result in downstream cancelation while - // protecting the promise 'input' from being canceled which has the effect of allowing - // 'input' to be shared amoung various consumers. - // - if (!Promise.is(input)) { - return Promise.wrap(input); - } - var complete; - var error; - var output = new Promise( - function (c, e) { - complete = c; - error = e; - }, - function () { - complete = null; - error = null; - oncancel && oncancel(); - } - ); - input.then( - function (v) { complete && complete(v); }, - function (e) { error && error(e); } - ); - return output; - }, - - } - ); - Object.defineProperties(Promise, _Events.createEventProperties(errorET)); - - Promise._doneHandler = function (value) { - _BaseCoreUtils._setImmediate(function Promise_done_rethrow() { - throw value; - }); - }; - - return { - PromiseStateMachine: PromiseStateMachine, - Promise: Promise, - state_created: state_created - }; -}); - -_winjs("WinJS/Promise", ["WinJS/Core/_Base","WinJS/Promise/_StateMachine"], function promiseInit( _Base, _StateMachine) { - "use strict"; - - _Base.Namespace.define("WinJS", { - Promise: _StateMachine.Promise - }); - - return _StateMachine.Promise; -}); - -var exported = _modules["WinJS/Core/_WinJS"]; - -if (typeof exports === 'undefined' && typeof define === 'function' && define.amd) { - define([], exported); -} else { - module.exports = exported; -} - -})(); diff --git a/src/vs/base/common/winjs.polyfill.promise.ts b/src/vs/base/common/winjs.polyfill.promise.ts index 232e9ec32f..bfcb7b7edb 100644 --- a/src/vs/base/common/winjs.polyfill.promise.ts +++ b/src/vs/base/common/winjs.polyfill.promise.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Promise as WinJSPromise } from './winjs.base'; +import * as platform from 'vs/base/common/platform'; /** * A polyfill for the native promises. The implementation is based on @@ -53,13 +54,13 @@ export class PolyfillPromise<T = any> implements Promise<T> { if (!initializing) { resolve(value); } else { - setImmediate(resolve, value); + platform.setImmediate(() => resolve(value)); } }, function (err) { if (!initializing) { reject(err); } else { - setImmediate(reject, err); + platform.setImmediate(() => reject(err)); } }); initializing = false; @@ -74,14 +75,14 @@ export class PolyfillPromise<T = any> implements Promise<T> { if (!sync) { onFulfilled(value); } else { - setImmediate(onFulfilled, value); + platform.setImmediate(() => onFulfilled(value)); } }, onRejected && function (err) { if (!sync) { - onFulfilled(err); + onRejected(err); } else { - setImmediate(onFulfilled, err); + platform.setImmediate(() => onRejected(err)); } } )); diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index 95f24fcc83..c23ae37e5a 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -116,7 +116,7 @@ class SimpleWorkerProtocol { } catch (e) { // nothing } - if (!message.vsWorker) { + if (!message || !message.vsWorker) { return; } if (this._workerId !== -1 && message.vsWorker !== this._workerId) { @@ -224,10 +224,9 @@ export class SimpleWorkerClient<T> extends Disposable { // Gather loader configuration let loaderConfiguration: any = null; - let globalRequire = (<any>self).require; - if (typeof globalRequire.getConfig === 'function') { + if (typeof (<any>self).require !== 'undefined' && typeof (<any>self).require.getConfig === 'function') { // Get the configuration from the Monaco AMD Loader - loaderConfiguration = globalRequire.getConfig(); + loaderConfiguration = (<any>self).require.getConfig(); } else if (typeof (<any>self).requirejs !== 'undefined') { // Get the configuration from requirejs loaderConfiguration = (<any>self).requirejs.s.contexts._.config; @@ -298,10 +297,11 @@ export interface IRequestHandler { */ export class SimpleWorkerServer { - private _protocol: SimpleWorkerProtocol; private _requestHandler: IRequestHandler; + private _protocol: SimpleWorkerProtocol; - constructor(postSerializedMessage: (msg: string) => void) { + constructor(postSerializedMessage: (msg: string) => void, requestHandler: IRequestHandler) { + this._requestHandler = requestHandler; this._protocol = new SimpleWorkerProtocol({ sendMessage: (msg: string): void => { postSerializedMessage(msg); @@ -333,6 +333,17 @@ export class SimpleWorkerServer { private initialize(workerId: number, moduleId: string, loaderConfig: any): TPromise<any> { this._protocol.setWorkerId(workerId); + if (this._requestHandler) { + // static request handler + let methods: string[] = []; + for (let prop in this._requestHandler) { + if (typeof this._requestHandler[prop] === 'function') { + methods.push(prop); + } + } + return TPromise.as(methods); + } + if (loaderConfig) { // Remove 'baseUrl', handling it is beyond scope for now if (typeof loaderConfig.baseUrl !== 'undefined') { @@ -379,5 +390,5 @@ export class SimpleWorkerServer { * Called on the worker side */ export function create(postMessage: (msg: string) => void): SimpleWorkerServer { - return new SimpleWorkerServer(postMessage); + return new SimpleWorkerServer(postMessage, null); } diff --git a/src/vs/base/node/config.ts b/src/vs/base/node/config.ts index 7aa03cbc53..9dbcf56a36 100644 --- a/src/vs/base/node/config.ts +++ b/src/vs/base/node/config.ts @@ -9,9 +9,10 @@ import * as fs from 'fs'; import { dirname, basename } from 'path'; import * as objects from 'vs/base/common/objects'; import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as json from 'vs/base/common/json'; import * as extfs from 'vs/base/node/extfs'; +import { isWindows } from 'vs/base/common/platform'; export interface IConfigurationChangeEvent<T> { config: T; @@ -49,7 +50,7 @@ export class ConfigWatcher<T> implements IConfigWatcher<T>, IDisposable { private loaded: boolean; private timeoutHandle: NodeJS.Timer; private disposables: IDisposable[]; - private _onDidUpdateConfiguration: Emitter<IConfigurationChangeEvent<T>>; + private readonly _onDidUpdateConfiguration: Emitter<IConfigurationChangeEvent<T>>; private configName: string; constructor(private _path: string, private options: IConfigOptions<T> = { changeBufferDelay: 0, defaultConfig: Object.create(null), onError: error => console.error(error) }) { @@ -165,8 +166,18 @@ export class ConfigWatcher<T> implements IConfigWatcher<T>, IDisposable { } private onConfigFileChange(eventType: string, filename: string, isParentFolder: boolean): void { - if (isParentFolder && filename !== this.configName) { - return; // a change to a sibling file that is not our config file + if (isParentFolder) { + + // Windows: in some cases the filename contains artifacts from the absolute path + // see https://github.com/nodejs/node/issues/19170 + // As such, we have to ensure that the filename basename is used for comparison. + if (isWindows && filename !== this.configName) { + filename = basename(filename); + } + + if (filename !== this.configName) { + return; // a change to a sibling file that is not our config file + } } if (this.timeoutHandle) { diff --git a/src/vs/base/node/decoder.ts b/src/vs/base/node/decoder.ts index 2d8f0b394c..ca88ac07fe 100644 --- a/src/vs/base/node/decoder.ts +++ b/src/vs/base/node/decoder.ts @@ -5,7 +5,7 @@ 'use strict'; -import sd = require('string_decoder'); +import * as sd from 'string_decoder'; import { CharCode } from 'vs/base/common/charCode'; /** diff --git a/src/vs/base/node/encoding.ts b/src/vs/base/node/encoding.ts index 71fb7d494d..d9c5ffe072 100644 --- a/src/vs/base/node/encoding.ts +++ b/src/vs/base/node/encoding.ts @@ -5,17 +5,106 @@ 'use strict'; -import stream = require('vs/base/node/stream'); -import iconv = require('iconv-lite'); +import * as stream from 'vs/base/node/stream'; +import * as iconv from 'iconv-lite'; import { TPromise } from 'vs/base/common/winjs.base'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { exec } from 'child_process'; +import { Readable, Writable, WritableOptions } from 'stream'; export const UTF8 = 'utf8'; export const UTF8_with_bom = 'utf8bom'; export const UTF16be = 'utf16be'; export const UTF16le = 'utf16le'; +export interface IDecodeStreamOptions { + guessEncoding?: boolean; + minBytesRequiredForDetection?: number; + overwriteEncoding?(detectedEncoding: string): string; +} + +export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions): TPromise<{ detected: IDetectedEncodingResult, stream: NodeJS.ReadableStream }> { + + if (!options.minBytesRequiredForDetection) { + options.minBytesRequiredForDetection = options.guessEncoding ? AUTO_GUESS_BUFFER_MAX_LEN : NO_GUESS_BUFFER_MAX_LEN; + } + + if (!options.overwriteEncoding) { + options.overwriteEncoding = detected => detected || UTF8; + } + + return new TPromise<{ detected: IDetectedEncodingResult, stream: NodeJS.ReadableStream }>((resolve, reject) => { + readable.pipe(new class extends Writable { + + private _decodeStream: NodeJS.ReadWriteStream; + private _decodeStreamConstruction: Thenable<any>; + private _buffer: Buffer[] = []; + private _bytesBuffered = 0; + + constructor(opts?: WritableOptions) { + super(opts); + this.once('finish', () => this._finish()); + } + + _write(chunk: any, encoding: string, callback: Function): void { + if (!Buffer.isBuffer(chunk)) { + callback(new Error('data must be a buffer')); + } + + if (this._decodeStream) { + // just a forwarder now + this._decodeStream.write(chunk, callback); + return; + } + + this._buffer.push(chunk); + this._bytesBuffered += chunk.length; + + if (this._decodeStreamConstruction) { + // waiting for the decoder to be ready + this._decodeStreamConstruction.then(_ => callback(), err => callback(err)); + + } else if (this._bytesBuffered >= options.minBytesRequiredForDetection) { + // buffered enough data, create stream and forward data + this._startDecodeStream(callback); + + } else { + // only buffering + callback(); + } + } + + _startDecodeStream(callback: Function): void { + + this._decodeStreamConstruction = TPromise.as(detectEncodingFromBuffer({ + buffer: Buffer.concat(this._buffer), bytesRead: this._bytesBuffered + }, options.guessEncoding)).then(detected => { + detected.encoding = options.overwriteEncoding(detected.encoding); + this._decodeStream = decodeStream(detected.encoding); + for (const buffer of this._buffer) { + this._decodeStream.write(buffer); + } + callback(); + resolve({ detected, stream: this._decodeStream }); + + }, err => { + callback(err); + }); + } + + _finish(): void { + if (this._decodeStream) { + // normal finish + this._decodeStream.end(); + } else { + // we were still waiting for data... + this._startDecodeStream(() => this._decodeStream.end()); + } + } + }); + }); +} + export function bomLength(encoding: string): number { switch (encoding) { case UTF8: @@ -172,6 +261,89 @@ export function toCanonicalName(enc: string): string { } } +const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not +const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough +const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing + +export interface IDetectedEncodingResult { + encoding: string; + seemsBinary: boolean; +} + +export interface DetectEncodingOption { + autoGuessEncoding?: boolean; +} + +export function detectEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: false): IDetectedEncodingResult; +export function detectEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: boolean): TPromise<IDetectedEncodingResult>; +export function detectEncodingFromBuffer({ buffer, bytesRead }: stream.ReadResult, autoGuessEncoding?: boolean): TPromise<IDetectedEncodingResult> | IDetectedEncodingResult { + + // Always first check for BOM to find out about encoding + let encoding = detectEncodingByBOMFromBuffer(buffer, bytesRead); + + // Detect 0 bytes to see if file is binary or UTF-16 LE/BE + // unless we already know that this file has a UTF-16 encoding + let seemsBinary = false; + if (encoding !== UTF16be && encoding !== UTF16le) { + let couldBeUTF16LE = true; // e.g. 0xAA 0x00 + let couldBeUTF16BE = true; // e.g. 0x00 0xAA + let containsZeroByte = false; + + // This is a simplified guess to detect UTF-16 BE or LE by just checking if + // the first 512 bytes have the 0-byte at a specific location. For UTF-16 LE + // this would be the odd byte index and for UTF-16 BE the even one. + // Note: this can produce false positives (a binary file that uses a 2-byte + // encoding of the same format as UTF-16) and false negatives (a UTF-16 file + // that is using 4 bytes to encode a character). + for (let i = 0; i < bytesRead && i < ZERO_BYTE_DETECTION_BUFFER_MAX_LEN; i++) { + const isEndian = (i % 2 === 1); // assume 2-byte sequences typical for UTF-16 + const isZeroByte = (buffer.readInt8(i) === 0); + + if (isZeroByte) { + containsZeroByte = true; + } + + // UTF-16 LE: expect e.g. 0xAA 0x00 + if (couldBeUTF16LE && (isEndian && !isZeroByte || !isEndian && isZeroByte)) { + couldBeUTF16LE = false; + } + + // UTF-16 BE: expect e.g. 0x00 0xAA + if (couldBeUTF16BE && (isEndian && isZeroByte || !isEndian && !isZeroByte)) { + couldBeUTF16BE = false; + } + + // Return if this is neither UTF16-LE nor UTF16-BE and thus treat as binary + if (isZeroByte && !couldBeUTF16LE && !couldBeUTF16BE) { + break; + } + } + + // Handle case of 0-byte included + if (containsZeroByte) { + if (couldBeUTF16LE) { + encoding = UTF16le; + } else if (couldBeUTF16BE) { + encoding = UTF16be; + } else { + seemsBinary = true; + } + } + } + + // Auto guess encoding if configured + if (autoGuessEncoding && !seemsBinary && !encoding) { + return guessEncodingByBuffer(buffer.slice(0, bytesRead)).then(encoding => { + return { + seemsBinary: false, + encoding + }; + }); + } + + return { seemsBinary, encoding }; +} + // https://ss64.com/nt/chcp.html const windowsTerminalEncodings = { '437': 'cp437', // United States diff --git a/src/vs/base/node/flow.ts b/src/vs/base/node/flow.ts index 7964247cb3..1c0aef2802 100644 --- a/src/vs/base/node/flow.ts +++ b/src/vs/base/node/flow.ts @@ -5,7 +5,7 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; /** * Executes the given function (fn) over the given array of items (list) in parallel and returns the resulting errors and results as diff --git a/src/vs/base/node/mime.ts b/src/vs/base/node/mime.ts deleted file mode 100644 index b66ed7cebb..0000000000 --- a/src/vs/base/node/mime.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 mime = require('vs/base/common/mime'); -import { TPromise } from 'vs/base/common/winjs.base'; - -import stream = require('vs/base/node/stream'); -import encoding = require('vs/base/node/encoding'); - -/** - * Lots of binary file types exists where the type can be determined by matching the first few bytes against some "magic patterns". - * E.g. PDF files always start with %PDF- and the rest of the file contains mostly text, but sometimes binary data (for fonts and images). - * In order to detect these types correctly (and independently from the file's extension), the content base mime type detection must be performed - * on any file, not only on text files. - * - * Here is the original mime type detection in pseudocode: - * - * let mimes = []; - * - * read file extension - * - * if (file extension matches) { - * if (file extension is bogus) { - * // ignore. - * // this covers *.manifest files which can contain arbitrary content, so the extension is of no value. - * // a consequence of this is that the content based mime type becomes the most specific type in the array - * } else { - * mimes.push(associated mime type) // first element: most specific - * } - * } - * - * read file contents - * - * if (content based match found) { // this is independent from text or binary - * mimes.push(associated mime type) - * if (a second mime exists for the match) { // should be rare; text/plain should never be included here - * // e.g. for svg: ['image/svg+xml', 'application/xml'] - * mimes.push(second mime) - * } - * } - * - * if (content == text) - * mimes.push('text/plain') // last element: least specific - * else - * mimes.push('application/octet-stream') // last element: least specific - */ - -const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not - -const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough -const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing - -export function maxBufferLen(arg1?: DetectMimesOption | boolean): number { - let autoGuessEncoding: boolean; - if (typeof arg1 === 'boolean') { - autoGuessEncoding = arg1; - } else { - autoGuessEncoding = arg1 && arg1.autoGuessEncoding; - } - - return autoGuessEncoding ? AUTO_GUESS_BUFFER_MAX_LEN : NO_GUESS_BUFFER_MAX_LEN; -} - -export interface IMimeAndEncoding { - encoding: string; - mimes: string[]; -} - -export interface DetectMimesOption { - autoGuessEncoding?: boolean; -} - -export function detectMimeAndEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: false): IMimeAndEncoding; -export function detectMimeAndEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: boolean): TPromise<IMimeAndEncoding>; -export function detectMimeAndEncodingFromBuffer({ buffer, bytesRead }: stream.ReadResult, autoGuessEncoding?: boolean): TPromise<IMimeAndEncoding> | IMimeAndEncoding { - let enc = encoding.detectEncodingByBOMFromBuffer(buffer, bytesRead); - - // Detect 0 bytes to see if file is binary (ignore for UTF 16 though) - let isText = true; - if (enc !== encoding.UTF16be && enc !== encoding.UTF16le) { - for (let i = 0; i < bytesRead && i < ZERO_BYTE_DETECTION_BUFFER_MAX_LEN; i++) { - if (buffer.readInt8(i) === 0) { - isText = false; - break; - } - } - } - - if (autoGuessEncoding && isText && !enc) { - return encoding.guessEncodingByBuffer(buffer.slice(0, bytesRead)).then(enc => { - return { - mimes: isText ? [mime.MIME_TEXT] : [mime.MIME_BINARY], - encoding: enc - }; - }); - } - - return { - mimes: isText ? [mime.MIME_TEXT] : [mime.MIME_BINARY], - encoding: enc - }; -} \ No newline at end of file diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index bd6e68dc0f..49afb117b6 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -82,12 +82,6 @@ export function readlink(path: string): TPromise<string> { return nfcall<string>(fs.readlink, path); } -export function touch(path: string): TPromise<void> { - const now = Date.now() / 1000; // the value should be a Unix timestamp in seconds - - return nfcall(fs.utimes, path, now, now); -} - export function truncate(path: string, len: number): TPromise<void> { return nfcall(fs.truncate, path, len); } @@ -196,3 +190,7 @@ export function whenDeleted(path: string): TPromise<void> { }, 1000); }); } + +export function copy(source: string, target: string): TPromise<void> { + return nfcall(extfs.copy, source, target); +} \ No newline at end of file diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index a7fa28d406..9ce79701bc 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -5,7 +5,7 @@ 'use strict'; -import net = require('net'); +import * as net from 'net'; /** * @returns Returns a random port between 1025 and 65535. diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 49fd4ca4cc..63522e222c 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import path = require('path'); +import * as path from 'path'; import * as cp from 'child_process'; import { fork } from 'vs/base/node/stdFork'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { PPromise, TPromise, TValueCallback, TProgressCallback, ErrorCallback } from 'vs/base/common/winjs.base'; import * as Types from 'vs/base/common/types'; import { IStringDictionary } from 'vs/base/common/collections'; @@ -153,7 +153,7 @@ export abstract class AbstractProcess<TProgressData> { public start(): PPromise<SuccessData, TProgressData> { if (Platform.isWindows && ((this.options && this.options.cwd && TPath.isUNC(this.options.cwd)) || !this.options && !this.options.cwd && TPath.isUNC(process.cwd()))) { - return TPromise.wrapError(new Error(nls.localize('TaskRunner.UNC', 'Can\'t execute a shell command on an UNC drive.'))); + return TPromise.wrapError(new Error(nls.localize('TaskRunner.UNC', 'Can\'t execute a shell command on a UNC drive.'))); } return this.useExec().then((useExec) => { let cc: TValueCallback<SuccessData>; @@ -381,7 +381,7 @@ export interface IQueuedSender { // queue is free again to consume messages. // On Windows we always wait for the send() method to return before sending the next message // to workaround https://github.com/nodejs/node/issues/7657 (IPC can freeze process) -export function createQueuedSender(childProcess: cp.ChildProcess | NodeJS.Process): IQueuedSender { +export function createQueuedSender(childProcess: cp.ChildProcess): IQueuedSender { let msgQueue: string[] = []; let useQueue = false; diff --git a/src/vs/base/node/ps-win.ps1 b/src/vs/base/node/ps-win.ps1 deleted file mode 100644 index 1f58ccdd6a..0000000000 --- a/src/vs/base/node/ps-win.ps1 +++ /dev/null @@ -1,183 +0,0 @@ -################################################################################################ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the Source EULA. See License.txt in the project root for license information. -################################################################################################ - -Param( - [string]$ProcessName = "code.exe", - [int]$MaxSamples = 10 -) - -$processLength = "process(".Length - -function Get-MachineInfo { - $model = (Get-WmiObject -Class Win32_Processor).Name - $memory = (Get-WmiObject -Class Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1MB - $wmi_cs = Get-WmiObject -Class Win32_ComputerSystem - return @{ - "type" = "machineInfo" - "model" = $model - "processors" = $wmi_cs.NumberOfProcessors - "logicalProcessors" = $wmi_cs.NumberOfLogicalProcessors - "totalMemory" = $memory - - } -} -$machineInfo = Get-MachineInfo - -function Get-MachineState { - $proc = Get-WmiObject Win32_Processor - $os = Get-WmiObject win32_OperatingSystem - return @{ - "type" = 'machineState' - "cpuLoad" = $proc.LoadPercentage - "handles" = (Get-Process | Measure-Object Handles -Sum).Sum - "memory" = @{ - "total" = $os.TotalVisibleMemorySize - "free" = $os.FreePhysicalMemory - "swapTotal" = $os.TotalVirtualMemorySize - "swapFree" = $os.FreeVirtualMemory - } - } -} -$machineState = Get-MachineState - -$processId2CpuLoad = @{} -function Get-PerformanceCounters ($logicalProcessors) { - $counterError - # In a first round we get the performance counters and the process ids. - $counters = (Get-Counter ("\Process(*)\% Processor Time", "\Process(*)\ID Process") -ErrorAction SilentlyContinue).CounterSamples - $processKey2Id = @{} - foreach ($counter in $counters) { - if ($counter.Status -ne 0) { - continue - } - $path = $counter.path; - $segments = $path.Split("\"); - $kind = $segments[4]; - $processKey = $segments[3].Substring($processLength, $segments[3].Length - $processLength - 1) - if ($kind -eq "id process") { - $processKey2Id[$processKey] = [uint32]$counter.CookedValue - } - } - foreach ($counter in $counters) { - if ($counter.Status -ne 0) { - continue - } - $path = $counter.path; - $segments = $path.Split("\"); - $kind = $segments[4]; - $processKey = $segments[3].Substring($processLength, $segments[3].Length - $processLength - 1) - if ($kind -eq "% processor time") { - $array = New-Object double[] ($MaxSamples + 1) - $array[0] = ($counter.CookedValue / $logicalProcessors) - $processId = $processKey2Id[$processKey] - if ($processId) { - $processId2CpuLoad[$processId] = $array - } - } - } - # Now lets sample another 10 times but only the processor time - $samples = Get-Counter "\Process(*)\% Processor Time" -SampleInterval 1 -MaxSamples $MaxSamples -ErrorAction SilentlyContinue - for ($s = 0; $s -lt $samples.Count; $s++) { - $counters = $samples[$s].CounterSamples; - foreach ($counter in $counters) { - if ($counter.Status -ne 0) { - continue - } - $path = $counter.path; - $segments = $path.Split("\"); - $processKey = $segments[3].Substring($processLength, $segments[3].Length - $processLength - 1) - $processKey = $processKey2Id[$processKey]; - if ($processKey) { - $processId2CpuLoad[$processKey][$s + 1] = ($counter.CookedValue / $logicalProcessors) - } - } - } -} -Get-PerformanceCounters -logicalProcessors $machineInfo.logicalProcessors - -$topElements = New-Object PSObject[] $processId2CpuLoad.Keys.Count; -$index = 0; -foreach ($key in $processId2CpuLoad.Keys) { - $obj = [PSCustomObject]@{ - ProcessId = $key - Load = ($processId2CpuLoad[$key] | Measure-Object -Sum).Sum / ($MaxSamples + 1) - } - $topElements[$index] = $obj - $index++ -} -$topElements = $topElements | Sort-Object Load -Descending - -# Get all code processes -$codeProcesses = @{} -foreach ($item in Get-WmiObject Win32_Process -Filter "name = '$ProcessName'") { - $codeProcesses[$item.ProcessId] = $item -} -foreach ($item in Get-WmiObject Win32_Process -Filter "name = 'codeHelper.exe'") { - $codeProcesses[$item.ProcessId] = $item -} -$otherProcesses = @{} -foreach ($item in Get-WmiObject Win32_Process -Filter "name Like '%'") { - if (!($codeProcesses.Contains($item.ProcessId))) { - $otherProcesses[$item.ProcessId] = $item - } -} -$modified = $false -do { - $toDelete = @() - $modified = $false - foreach ($item in $otherProcesses.Values) { - if ($codeProcesses.Contains([uint32]$item.ParentProcessId)) { - $codeProcesses[$item.ProcessId] = $item; - $toDelete += $item - } - } - foreach ($item in $toDelete) { - $otherProcesses.Remove([uint32]$item.ProcessId) - $modified = $true - } -} while ($modified) - -$result = New-Object PSObject[] (2 + [math]::Min(5, $topElements.Count) + $codeProcesses.Count) -$result[0] = $machineInfo -$result[1] = $machineState -$index = 2; -for($i = 0; $i -lt 5 -and $i -lt $topElements.Count; $i++) { - $element = $topElements[$i] - $item = $codeProcesses[[uint32]$element.ProcessId] - if (!$item) { - $item = $otherProcesses[[uint32]$element.ProcessId] - } - if ($item) { - $cpuLoad = $processId2CpuLoad[[uint32]$item.ProcessId] | % { [pscustomobject] $_ } - $result[$index] = [pscustomobject]@{ - "type" = "topProcess" - "name" = $item.Name - "processId" = $item.ProcessId - "parentProcessId" = $item.ParentProcessId - "commandLine" = $item.CommandLine - "handles" = $item.HandleCount - "cpuLoad" = $cpuLoad - "workingSetSize" = $item.WorkingSetSize - } - $index++ - } -} -foreach ($item in $codeProcesses.Values) { - # we need to convert this otherwise to JSON with create a value, count object and not an inline array - $cpuLoad = $processId2CpuLoad[[uint32]$item.ProcessId] | % { [pscustomobject] $_ } - $result[$index] = [pscustomobject]@{ - "type" = "processInfo" - "name" = $item.Name - "processId" = $item.ProcessId - "parentProcessId" = $item.ParentProcessId - "commandLine" = $item.CommandLine - "handles" = $item.HandleCount - "cpuLoad" = $cpuLoad - "workingSetSize" = $item.WorkingSetSize - } - $index++ -} - -$result | ConvertTo-Json -Depth 99 diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts index 2413204f99..e74c7ff3b2 100644 --- a/src/vs/base/node/ps.ts +++ b/src/vs/base/node/ps.ts @@ -5,10 +5,7 @@ 'use strict'; -import { spawn, exec } from 'child_process'; -import * as path from 'path'; -import * as nls from 'vs/nls'; -import URI from 'vs/base/common/uri'; +import { exec } from 'child_process'; export interface ProcessItem { name: string; @@ -121,32 +118,6 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> { if (process.platform === 'win32') { - console.log(nls.localize('collecting', 'Collecting CPU and memory information. This might take a couple of seconds.')); - - interface ProcessInfo { - type: 'processInfo'; - name: string; - processId: number; - parentProcessId: number; - commandLine: string; - handles: number; - cpuLoad: number[]; - workingSetSize: number; - } - - interface TopProcess { - type: 'topProcess'; - name: string; - processId: number; - parentProcessId: number; - commandLine: string; - handles: number; - cpuLoad: number[]; - workingSetSize: number; - } - - type Item = ProcessInfo | TopProcess; - const cleanUNCPrefix = (value: string): string => { if (value.indexOf('\\\\?\\') === 0) { return value.substr(4); @@ -161,75 +132,45 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> { } }; - const execMain = path.basename(process.execPath); - const script = URI.parse(require.toUrl('vs/base/node/ps-win.ps1')).fsPath; - const commandLine = `& {& '${script}' -ProcessName '${execMain}' -MaxSamples 3}`; - const cmd = spawn('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', commandLine]); - - let stdout = ''; - let stderr = ''; - cmd.stdout.on('data', data => { - stdout += data.toString(); - }); - - cmd.stderr.on('data', data => { - stderr += data.toString(); - }); - - cmd.on('exit', () => { - if (stderr.length > 0) { - reject(new Error(stderr)); - return; - } - let processItems: Map<number, ProcessItem> = new Map(); - try { - const items: Item[] = JSON.parse(stdout); - for (const item of items) { - if (item.type === 'processInfo') { - let load = 0; - if (item.cpuLoad) { - for (let value of item.cpuLoad) { - load += value; - } - load = load / item.cpuLoad.length; - } else { - load = -1; - } - let commandLine = cleanUNCPrefix(item.commandLine); - processItems.set(item.processId, { + (import('windows-process-tree')).then(windowsProcessTree => { + windowsProcessTree.getProcessList(rootPid, (processList) => { + windowsProcessTree.getProcessCpuUsage(processList, (completeProcessList) => { + const processItems: Map<number, ProcessItem> = new Map(); + completeProcessList.forEach(process => { + const commandLine = cleanUNCPrefix(process.commandLine); + processItems.set(process.pid, { name: findName(commandLine), cmd: commandLine, - pid: item.processId, - ppid: item.parentProcessId, - load: load, - mem: item.workingSetSize + pid: process.pid, + ppid: process.ppid, + load: process.cpu, + mem: process.memory }); - } - } - rootItem = processItems.get(rootPid); - if (rootItem) { - processItems.forEach(item => { - let parent = processItems.get(item.ppid); - if (parent) { - if (!parent.children) { - parent.children = []; + }); + + rootItem = processItems.get(rootPid); + if (rootItem) { + processItems.forEach(item => { + let parent = processItems.get(item.ppid); + if (parent) { + if (!parent.children) { + parent.children = []; + } + parent.children.push(item); } - parent.children.push(item); - } - }); - processItems.forEach(item => { - if (item.children) { - item.children = item.children.sort((a, b) => a.pid - b.pid); - } - }); - resolve(rootItem); - } else { - reject(new Error(`Root process ${rootPid} not found`)); - } - } catch (error) { - console.log(stdout); - reject(error); - } + }); + + processItems.forEach(item => { + if (item.children) { + item.children = item.children.sort((a, b) => a.pid - b.pid); + } + }); + resolve(rootItem); + } else { + reject(new Error(`Root process ${rootPid} not found`)); + } + }); + }, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory); }); } else { // OS X & Linux diff --git a/src/vs/base/node/request.ts b/src/vs/base/node/request.ts index 25d950c7bf..70808f3e71 100644 --- a/src/vs/base/node/request.ts +++ b/src/vs/base/node/request.ts @@ -7,8 +7,8 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { isBoolean, isNumber } from 'vs/base/common/types'; -import https = require('https'); -import http = require('http'); +import * as https from 'https'; +import * as http from 'http'; import { Stream } from 'stream'; import { parse as parseUrl } from 'url'; import { createWriteStream } from 'fs'; @@ -96,7 +96,7 @@ export function request(options: IRequestOptions): TPromise<IRequestContext> { stream = stream.pipe(createGunzip()); } - c({ res, stream }); + c({ res, stream } as IRequestContext); } }); diff --git a/src/vs/base/node/stdFork.ts b/src/vs/base/node/stdFork.ts index 9a93d2b948..21b6a9a3ed 100644 --- a/src/vs/base/node/stdFork.ts +++ b/src/vs/base/node/stdFork.ts @@ -5,10 +5,10 @@ 'use strict'; -import path = require('path'); -import os = require('os'); -import net = require('net'); -import cp = require('child_process'); +import * as path from 'path'; +import * as os from 'os'; +import * as net from 'net'; +import * as cp from 'child_process'; import uri from 'vs/base/common/uri'; export interface IForkOpts { diff --git a/src/vs/base/node/stream.ts b/src/vs/base/node/stream.ts index 68ba6827dd..32e5fc0894 100644 --- a/src/vs/base/node/stream.ts +++ b/src/vs/base/node/stream.ts @@ -5,7 +5,7 @@ 'use strict'; -import fs = require('fs'); +import * as fs from 'fs'; import { TPromise } from 'vs/base/common/winjs.base'; diff --git a/src/vs/base/node/zip.ts b/src/vs/base/node/zip.ts index 0f84259c78..c23657cd03 100644 --- a/src/vs/base/node/zip.ts +++ b/src/vs/base/node/zip.ts @@ -3,14 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as path from 'path'; -import { createWriteStream } from 'fs'; +import { createWriteStream, WriteStream } from 'fs'; import { Readable } from 'stream'; import { nfcall, ninvoke, SimpleThrottler } from 'vs/base/common/async'; import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { TPromise } from 'vs/base/common/winjs.base'; import { open as _openZip, Entry, ZipFile } from 'yauzl'; +import { ILogService } from 'vs/platform/log/common/log'; export interface IExtractOptions { overwrite?: boolean; @@ -26,10 +27,7 @@ interface IOptions { sourcePathRegex: RegExp; } -export enum ExtractErrorType { - Undefined, - CorruptZip -} +export type ExtractErrorType = 'CorruptZip' | 'Incomplete'; export class ExtractError extends Error { @@ -40,7 +38,7 @@ export class ExtractError extends Error { let message = cause.message; switch (type) { - case ExtractErrorType.CorruptZip: message = `Corrupt ZIP: ${message}`; break; + case 'CorruptZip': message = `Corrupt ZIP: ${message}`; break; } super(message); @@ -58,12 +56,14 @@ function modeFromEntry(entry: Entry) { } function toExtractError(err: Error): ExtractError { - let type = ExtractErrorType.CorruptZip; + if (err instanceof ExtractError) { + return err; + } - console.log('WHAT'); + let type: ExtractErrorType = void 0; if (/end of central directory record signature not found/.test(err.message)) { - type = ExtractErrorType.CorruptZip; + type = 'CorruptZip'; } return new ExtractError(type, err); @@ -74,24 +74,51 @@ function extractEntry(stream: Readable, fileName: string, mode: number, targetPa const targetDirName = path.join(targetPath, dirName); const targetFileName = path.join(targetPath, fileName); + let istream: WriteStream; return mkdirp(targetDirName).then(() => new TPromise((c, e) => { - let istream = createWriteStream(targetFileName, { mode }); - istream.once('finish', () => c(null)); + istream = createWriteStream(targetFileName, { mode }); + istream.once('close', () => c(null)); istream.once('error', e); stream.once('error', e); stream.pipe(istream); + }, () => { + if (istream) { + istream.close(); + } })); } -function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions): TPromise<void> { +function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, logService: ILogService): TPromise<void> { + let isCanceled = false; + let last = TPromise.wrap<any>(null); + let extractedEntriesCount = 0; + return new TPromise((c, e) => { const throttler = new SimpleThrottler(); - let last = TPromise.as<any>(null); + + const readNextEntry = () => { + extractedEntriesCount++; + zipfile.readEntry(); + }; zipfile.once('error', e); - zipfile.once('close', () => last.then(c, e)); + zipfile.once('close', () => last.then(() => { + if (isCanceled || zipfile.entryCount === extractedEntriesCount) { + c(null); + } else { + e(new ExtractError('Incomplete', new Error(nls.localize('incompleteExtract', "Incomplete. Found {0} of {1} entries", extractedEntriesCount, zipfile.entryCount)))); + } + }, e)); + zipfile.readEntry(); zipfile.on('entry', (entry: Entry) => { + logService.debug(targetPath, 'Found', entry.fileName); + + if (isCanceled) { + return; + } + if (!options.sourcePathRegex.test(entry.fileName)) { + readNextEntry(); return; } @@ -100,33 +127,38 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions): TP // directory file names end with '/' if (/\/$/.test(fileName)) { const targetFileName = path.join(targetPath, fileName); - last = mkdirp(targetFileName); + last = mkdirp(targetFileName).then(() => readNextEntry()); return; } const stream = ninvoke(zipfile, zipfile.openReadStream, entry); const mode = modeFromEntry(entry); - last = throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options))); + last = throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options).then(() => readNextEntry()))); }); + }, () => { + logService.debug(targetPath, 'Cancelled.'); + isCanceled = true; + last.cancel(); + zipfile.close(); }).then(null, err => TPromise.wrapError(toExtractError(err))); } -function openZip(zipFile: string): TPromise<ZipFile> { - return nfcall<ZipFile>(_openZip, zipFile) +function openZip(zipFile: string, lazy: boolean = false): TPromise<ZipFile> { + return nfcall<ZipFile>(_openZip, zipFile, lazy ? { lazyEntries: true } : void 0) .then(null, err => TPromise.wrapError(toExtractError(err))); } -export function extract(zipPath: string, targetPath: string, options: IExtractOptions = {}): TPromise<void> { +export function extract(zipPath: string, targetPath: string, options: IExtractOptions = {}, logService: ILogService): TPromise<void> { const sourcePathRegex = new RegExp(options.sourcePath ? `^${options.sourcePath}` : ''); - let promise = openZip(zipPath); + let promise = openZip(zipPath, true); if (options.overwrite) { promise = promise.then(zipfile => rimraf(targetPath).then(() => zipfile)); } - return promise.then(zipfile => extractZip(zipfile, targetPath, { sourcePathRegex })); + return promise.then(zipfile => extractZip(zipfile, targetPath, { sourcePathRegex }, logService)); } function read(zipPath: string, filePath: string): TPromise<Readable> { diff --git a/src/vs/base/parts/ipc/common/ipc.electron.ts b/src/vs/base/parts/ipc/common/ipc.electron.ts index ac590c3d48..ac35130e53 100644 --- a/src/vs/base/parts/ipc/common/ipc.electron.ts +++ b/src/vs/base/parts/ipc/common/ipc.electron.ts @@ -5,7 +5,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface Sender { send(channel: string, ...args: any[]): void; diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 04426551d0..711f90a62d 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -7,7 +7,7 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter, once, filterEvent } from 'vs/base/common/event'; +import { Event, Emitter, once, filterEvent } from 'vs/base/common/event'; enum MessageType { RequestCommon, @@ -152,7 +152,7 @@ export class ChannelServer implements IChannelServer, IDisposable { id, data: { message: data.message, name: data.name, - stack: data.stack ? data.stack.split('\n') : void 0 + stack: data.stack ? (data.stack.split ? data.stack.split('\n') : data.stack) : void 0 }, type: MessageType.ResponseError }); } else { diff --git a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts index 11f18a6776..ad10f9b025 100644 --- a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts +++ b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { filterEvent, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event'; +import { Event, filterEvent, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event'; import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc'; import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron'; import { ipcMain } from 'electron'; diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index a309c1b475..3931645d54 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -7,7 +7,7 @@ import { Socket, Server as NetServer, createConnection, createServer } from 'net'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, once, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event'; +import { Event, Emitter, once, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event'; import { IMessagePassingProtocol, ClientConnectionEvent, IPCServer, IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { join } from 'path'; import { tmpdir } from 'os'; diff --git a/src/vs/base/parts/ipc/test/node/ipc.perf.ts b/src/vs/base/parts/ipc/test/node/ipc.perf.ts index ce328d3dc9..15834cbb4c 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.perf.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.perf.ts @@ -106,9 +106,9 @@ suite('IPC performance', () => { assert.strictEqual(hits, batches); assert.strictEqual(count, batches * size); }, err => assert.fail(err), - batch => { - hits++; - count += batch.length; - }); + batch => { + hits++; + count += batch.length; + }); } }); \ No newline at end of file diff --git a/src/vs/base/parts/ipc/test/node/testService.ts b/src/vs/base/parts/ipc/test/node/testService.ts index 40788513d3..98ae58940f 100644 --- a/src/vs/base/parts/ipc/test/node/testService.ts +++ b/src/vs/base/parts/ipc/test/node/testService.ts @@ -6,7 +6,7 @@ import { TPromise, PPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface IMarcoPoloEvent { answer: string; diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts index 1607447677..29ace6252a 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts @@ -5,9 +5,9 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; @@ -16,7 +16,7 @@ import { Action, IAction, IActionRunner } from 'vs/base/common/actions'; import { compareAnything } from 'vs/base/common/comparers'; import { ActionBar, IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { IQuickOpenStyles } from 'vs/base/parts/quickopen/browser/quickOpenWidget'; import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { OS } from 'vs/base/common/platform'; diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 7b9726e4e6..df7784ac7b 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -5,22 +5,22 @@ 'use strict'; import 'vs/css!./quickopen'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import platform = require('vs/base/common/platform'); -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); +import * as platform from 'vs/base/common/platform'; +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; import { IQuickNavigateConfiguration, IAutoFocus, IEntryRunContext, IModel, Mode, IKeyMods } from 'vs/base/parts/quickopen/common/quickOpen'; import { Filter, Renderer, DataSource, IModelProvider, AccessibilityProvider } from 'vs/base/parts/quickopen/browser/quickOpenViewer'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import { ISelectionEvent, IFocusEvent, ITree, ContextMenuEvent, IActionProvider, ITreeStyles, ITreeOptions, ITreeConfiguration } from 'vs/base/parts/tree/browser/tree'; +import { Builder, $ } from 'vs/base/browser/builder'; +import { ITree, ContextMenuEvent, IActionProvider, ITreeStyles, ITreeOptions, ITreeConfiguration } from 'vs/base/parts/tree/browser/tree'; import { InputBox, MessageType, IInputBoxStyles, IRange } from 'vs/base/browser/ui/inputbox/inputBox'; import Severity from 'vs/base/common/severity'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { DefaultController, ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; @@ -113,7 +113,7 @@ export class QuickOpenWidget implements IModelProvider { private container: HTMLElement; private treeElement: HTMLElement; private inputElement: HTMLElement; - private layoutDimensions: Dimension; + private layoutDimensions: DOM.Dimension; private model: IModel<any>; private inputChangingTimeoutHandle: number; private styles: IQuickOpenStyles; @@ -130,8 +130,8 @@ export class QuickOpenWidget implements IModelProvider { this.model = null; } - public getElement(): Builder { - return $(this.builder); + public getElement(): HTMLElement { + return $(this.builder).getHTMLElement(); } public getModel(): IModel<any> { @@ -143,10 +143,10 @@ export class QuickOpenWidget implements IModelProvider { } public create(): HTMLElement { - this.builder = $().div((div: Builder) => { + this.builder = $().div(div => { // Eventing - div.on(DOM.EventType.KEY_DOWN, (e) => { + div.on(DOM.EventType.KEY_DOWN, e => { const keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e as KeyboardEvent); if (keyboardEvent.keyCode === KeyCode.Escape) { DOM.EventHelper.stop(e, true); @@ -160,10 +160,10 @@ export class QuickOpenWidget implements IModelProvider { // Progress Bar this.progressBar = new ProgressBar(div.clone(), { progressBarBackground: this.styles.progressBarBackground }); - this.progressBar.getContainer().hide(); + this.progressBar.hide(); // Input Field - div.div({ 'class': 'quick-open-input' }, (inputContainer) => { + div.div({ 'class': 'quick-open-input' }, inputContainer => { this.inputContainer = inputContainer; this.inputBox = new InputBox(inputContainer.getHTMLElement(), null, { placeholder: this.options.inputPlaceHolder || '', @@ -226,7 +226,7 @@ export class QuickOpenWidget implements IModelProvider { // Tree this.treeContainer = div.div({ 'class': 'quick-open-tree' - }, (div: Builder) => { + }, div => { const createTree = this.options.treeCreator || ((container, config, opts) => new Tree(container, config, opts)); this.tree = createTree(div.getHTMLElement(), { @@ -240,6 +240,7 @@ export class QuickOpenWidget implements IModelProvider { indentPixels: 0, alwaysFocused: true, verticalScrollMode: ScrollbarVisibility.Visible, + horizontalScrollMode: ScrollbarVisibility.Hidden, ariaLabel: nls.localize('treeAriaLabel', "Quick Picker"), keyboardSupport: this.options.keyboardSupport, preventRootFocus: true @@ -248,11 +249,11 @@ export class QuickOpenWidget implements IModelProvider { this.treeElement = this.tree.getHTMLElement(); // Handle Focus and Selection event - this.toUnbind.push(this.tree.onDidChangeFocus((event: IFocusEvent) => { + this.toUnbind.push(this.tree.onDidChangeFocus(event => { this.elementFocused(event.focus, event); })); - this.toUnbind.push(this.tree.onDidChangeSelection((event: ISelectionEvent) => { + this.toUnbind.push(this.tree.onDidChangeSelection(event => { if (event.selection && event.selection.length > 0) { const mouseEvent: StandardMouseEvent = event.payload && event.payload.originalEvent instanceof StandardMouseEvent ? event.payload.originalEvent : void 0; const shouldOpenInBackground = mouseEvent ? this.shouldOpenInBackground(mouseEvent) : false; @@ -261,7 +262,7 @@ export class QuickOpenWidget implements IModelProvider { } })); }). - on(DOM.EventType.KEY_DOWN, (e) => { + on(DOM.EventType.KEY_DOWN, e => { const keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e as KeyboardEvent); // Only handle when in quick navigation mode @@ -276,7 +277,7 @@ export class QuickOpenWidget implements IModelProvider { this.navigateInTree(keyboardEvent.keyCode); } }). - on(DOM.EventType.KEY_UP, (e) => { + on(DOM.EventType.KEY_UP, e => { const keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e as KeyboardEvent); const keyCode = keyboardEvent.keyCode; @@ -287,7 +288,7 @@ export class QuickOpenWidget implements IModelProvider { // Select element when keys are pressed that signal it const quickNavKeys = this.quickNavigateConfiguration.keybindings; - const wasTriggerKeyPressed = keyCode === KeyCode.Enter || quickNavKeys.some((k) => { + const wasTriggerKeyPressed = keyCode === KeyCode.Enter || quickNavKeys.some(k => { const [firstPart, chordPart] = k.getParts(); if (chordPart) { return false; @@ -327,7 +328,7 @@ export class QuickOpenWidget implements IModelProvider { }) // Widget Attributes - .addClass('quick-open-widget') + .addClass('monaco-quick-open-widget') .build(this.container); // Support layout @@ -447,7 +448,7 @@ export class QuickOpenWidget implements IModelProvider { // Transition into quick navigate mode if not yet done if (!this.quickNavigateConfiguration && quickNavigate) { this.quickNavigateConfiguration = quickNavigate; - this.tree.DOMFocus(); + this.tree.domFocus(); } // Navigate @@ -558,7 +559,7 @@ export class QuickOpenWidget implements IModelProvider { if (this.quickNavigateConfiguration) { this.inputContainer.hide(); this.builder.show(); - this.tree.DOMFocus(); + this.tree.domFocus(); } // Otherwise use normal UI @@ -779,11 +780,11 @@ export class QuickOpenWidget implements IModelProvider { this.treeContainer.style({ height: (this.options.minItemsToShow ? this.options.minItemsToShow * 22 : 0) + 'px' }); // Clear any running Progress - this.progressBar.stop().getContainer().hide(); + this.progressBar.stop().hide(); // Clear Focus if (this.tree.isDOMFocused()) { - this.tree.DOMBlur(); + this.tree.domBlur(); } else if (this.inputBox.hasFocus()) { this.inputBox.blur(); } @@ -810,11 +811,13 @@ export class QuickOpenWidget implements IModelProvider { } } - public setValue(value: string, selection?: [number, number]): void { + public setValue(value: string, selectionOrStableHint?: [number, number] | null): void { if (this.inputBox) { this.inputBox.value = value; - if (Array.isArray(selection)) { - const [start, end] = selection; + if (selectionOrStableHint === null) { + // null means stable-selection + } else if (Array.isArray(selectionOrStableHint)) { + const [start, end] = selectionOrStableHint; this.inputBox.select({ start, end }); } else { this.inputBox.select(); @@ -918,7 +921,7 @@ export class QuickOpenWidget implements IModelProvider { return this.visible; } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this.layoutDimensions = dimension; // Apply to quick open width (height is dynamic by number of items to show) diff --git a/src/vs/base/parts/quickopen/browser/quickopen.css b/src/vs/base/parts/quickopen/browser/quickopen.css index 402e69d4f7..17db2704bb 100644 --- a/src/vs/base/parts/quickopen/browser/quickopen.css +++ b/src/vs/base/parts/quickopen/browser/quickopen.css @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.quick-open-widget { +.monaco-quick-open-widget { position: absolute; width: 600px; z-index: 2000; @@ -12,7 +12,7 @@ margin-left: -300px; } -.quick-open-widget .progress-container { +.monaco-quick-open-widget .monaco-progress-container { position: absolute; left: 0; top: 38px; @@ -20,34 +20,34 @@ height: 2px; } -.quick-open-widget .progress-container .progress-bit { +.monaco-quick-open-widget .monaco-progress-container .progress-bit { height: 2px; } -.quick-open-widget .quick-open-input { +.monaco-quick-open-widget .quick-open-input { width: 588px; border: none; margin: 6px; } -.quick-open-widget .quick-open-input .monaco-inputbox { +.monaco-quick-open-widget .quick-open-input .monaco-inputbox { width: 100%; height: 25px; } -.quick-open-widget .quick-open-tree { +.monaco-quick-open-widget .quick-open-tree { line-height: 22px; } -.quick-open-widget .quick-open-tree .monaco-tree-row > .content > .sub-content { +.monaco-quick-open-widget .quick-open-tree .monaco-tree-row > .content > .sub-content { overflow: hidden; } -.quick-open-widget.content-changing .quick-open-tree .monaco-scrollable-element .slider { +.monaco-quick-open-widget.content-changing .quick-open-tree .monaco-scrollable-element .slider { display: none; /* scrollbar slider causes some hectic updates when input changes quickly, so hide it while quick open changes */ } -.quick-open-widget .quick-open-tree .quick-open-entry { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry { overflow: hidden; text-overflow: ellipsis; display: flex; @@ -55,12 +55,12 @@ height: 100%; } -.quick-open-widget .quick-open-tree .quick-open-entry > .quick-open-row { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry > .quick-open-row { display: flex; align-items: center; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { overflow: hidden; width: 16px; height: 16px; @@ -70,39 +70,39 @@ flex-shrink: 0; } -.quick-open-widget .quick-open-tree .monaco-icon-label, -.quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-description-container { +.monaco-quick-open-widget .quick-open-tree .monaco-icon-label, +.monaco-quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-description-container { flex: 1; /* make sure the icon label grows within the row */ } -.quick-open-widget .quick-open-tree .quick-open-entry .monaco-highlighted-label span { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .monaco-highlighted-label span { opacity: 1; } -.quick-open-widget .quick-open-tree .quick-open-entry-meta { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry-meta { opacity: 0.7; line-height: normal; } -.quick-open-widget .quick-open-tree .content.has-group-label .quick-open-entry-keybinding { +.monaco-quick-open-widget .quick-open-tree .content.has-group-label .quick-open-entry-keybinding { margin-right: 8px; } -.quick-open-widget .quick-open-tree .quick-open-entry-keybinding .monaco-keybinding-key { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry-keybinding .monaco-keybinding-key { vertical-align: text-bottom; } -.quick-open-widget .quick-open-tree .results-group { +.monaco-quick-open-widget .quick-open-tree .results-group { margin-right: 18px; } -.quick-open-widget .quick-open-tree .monaco-tree-row.focused > .content.has-actions > .results-group, -.quick-open-widget .quick-open-tree .monaco-tree-row:hover:not(.highlighted) > .content.has-actions > .results-group, -.quick-open-widget .quick-open-tree .focused .monaco-tree-row.focused > .content.has-actions > .results-group { +.monaco-quick-open-widget .quick-open-tree .monaco-tree-row.focused > .content.has-actions > .results-group, +.monaco-quick-open-widget .quick-open-tree .monaco-tree-row:hover:not(.highlighted) > .content.has-actions > .results-group, +.monaco-quick-open-widget .quick-open-tree .focused .monaco-tree-row.focused > .content.has-actions > .results-group { margin-right: 0px; } -.quick-open-widget .quick-open-tree .results-group-separator { +.monaco-quick-open-widget .quick-open-tree .results-group-separator { border-top-width: 1px; border-top-style: solid; box-sizing: border-box; @@ -154,6 +154,6 @@ height: 16px; } -.quick-open-widget .quick-open-tree .monaco-highlighted-label .highlight { +.monaco-quick-open-widget .quick-open-tree .monaco-highlighted-label .highlight { font-weight: bold; } \ No newline at end of file diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts index 2d93d32387..87c0ff272f 100644 --- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts +++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts @@ -7,9 +7,9 @@ import { compareAnything } from 'vs/base/common/comparers'; import { matchesPrefix, IMatch, createMatches, matchesCamelCase, isUpper } from 'vs/base/common/filters'; -import { isEqual, nativeSep } from 'vs/base/common/paths'; -import { isWindows } from 'vs/base/common/platform'; -import { stripWildcards } from 'vs/base/common/strings'; +import { nativeSep } from 'vs/base/common/paths'; +import { isWindows, isLinux } from 'vs/base/common/platform'; +import { stripWildcards, equalsIgnoreCase } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; export type Score = [number /* score */, number[] /* match positions */]; @@ -313,7 +313,7 @@ export function prepareQuery(original: string): IPreparedQuery { if (original) { value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace if (isWindows) { - value = value.replace(/\//g, '\\'); // Help Windows users to search for paths when using slash + value = value.replace(/\//g, nativeSep); // Help Windows users to search for paths when using slash } lowercase = value.toLowerCase(); @@ -356,7 +356,7 @@ export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, acc function doScoreItem(label: string, description: string, path: string, query: IPreparedQuery, fuzzy: boolean): IItemScore { // 1.) treat identity matches on full path highest - if (path && isEqual(query.original, path, true)) { + if (path && isLinux ? query.original === path : equalsIgnoreCase(query.original, path)) { return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : void 0 }; } diff --git a/src/vs/base/parts/tree/browser/tree.ts b/src/vs/base/parts/tree/browser/tree.ts index 6b76693432..de1b8e7426 100644 --- a/src/vs/base/parts/tree/browser/tree.ts +++ b/src/vs/base/parts/tree/browser/tree.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import WinJS = require('vs/base/common/winjs.base'); -import Touch = require('vs/base/browser/touch'); -import Mouse = require('vs/base/browser/mouseEvent'); -import Keyboard = require('vs/base/browser/keyboardEvent'); +import * as WinJS from 'vs/base/common/winjs.base'; +import * as Touch from 'vs/base/browser/touch'; +import * as Mouse from 'vs/base/browser/mouseEvent'; +import * as Keyboard from 'vs/base/browser/keyboardEvent'; import { INavigator } from 'vs/base/common/iterator'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IAction, IActionItem } from 'vs/base/common/actions'; import { Color } from 'vs/base/common/color'; import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel'; @@ -60,7 +60,7 @@ export interface ITree { /** * Sets DOM focus on the tree. */ - DOMFocus(): void; + domFocus(): void; /** * Returns whether the tree has DOM focus. @@ -70,7 +70,7 @@ export interface ITree { /** * Removes DOM focus from the tree. */ - DOMBlur(): void; + domBlur(): void; /** * Refreshes an element. @@ -78,6 +78,11 @@ export interface ITree { */ refresh(element?: any, recursive?: boolean): WinJS.Promise; + /** + * Updates an element's width. + */ + updateWidth(element: any): void; + /** * Expands an element. * The returned promise returns a boolean for whether the element was expanded or not. @@ -674,6 +679,7 @@ export interface ITreeConfiguration { filter?: IFilter; sorter?: ISorter; accessibilityProvider?: IAccessibilityProvider; + styler?: ITreeStyler; } export interface ITreeOptions extends ITreeStyles { @@ -681,6 +687,7 @@ export interface ITreeOptions extends ITreeStyles { showTwistie?: boolean; indentPixels?: number; verticalScrollMode?: ScrollbarVisibility; + horizontalScrollMode?: ScrollbarVisibility; alwaysFocused?: boolean; autoExpandSingleChildren?: boolean; useShadows?: boolean; @@ -690,6 +697,10 @@ export interface ITreeOptions extends ITreeStyles { preventRootFocus?: boolean; } +export interface ITreeStyler { + style(styles: ITreeStyles): void; +} + export interface ITreeStyles { listFocusBackground?: Color; listFocusForeground?: Color; diff --git a/src/vs/base/parts/tree/browser/treeDefaults.ts b/src/vs/base/parts/tree/browser/treeDefaults.ts index 0aea482716..64f2793361 100644 --- a/src/vs/base/parts/tree/browser/treeDefaults.ts +++ b/src/vs/base/parts/tree/browser/treeDefaults.ts @@ -4,16 +4,16 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; -import platform = require('vs/base/common/platform'); -import touch = require('vs/base/browser/touch'); -import errors = require('vs/base/common/errors'); -import dom = require('vs/base/browser/dom'); -import mouse = require('vs/base/browser/mouseEvent'); +import * as platform from 'vs/base/common/platform'; +import * as touch from 'vs/base/browser/touch'; +import * as errors from 'vs/base/common/errors'; +import * as dom from 'vs/base/browser/dom'; +import * as mouse from 'vs/base/browser/mouseEvent'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import _ = require('vs/base/parts/tree/browser/tree'); +import * as _ from 'vs/base/parts/tree/browser/tree'; import { KeyCode, KeyMod, Keybinding, createKeybinding, SimpleKeybinding } from 'vs/base/common/keyCodes'; export interface IKeyBindingCallback { @@ -172,7 +172,7 @@ export class DefaultController implements _.IController { } eventish.stopPropagation(); - tree.DOMFocus(); + tree.domFocus(); tree.setSelection([element], payload); tree.setFocus(element, payload); @@ -447,6 +447,87 @@ export class DefaultAccessibilityProvider implements _.IAccessibilityProvider { } } +export class DefaultTreestyler implements _.ITreeStyler { + + constructor(private styleElement: HTMLStyleElement, private selectorSuffix?: string) { } + + style(styles: _.ITreeStyles): void { + const suffix = this.selectorSuffix ? `.${this.selectorSuffix}` : ''; + const content: string[] = []; + + if (styles.listFocusBackground) { + content.push(`.monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { background-color: ${styles.listFocusBackground}; }`); + } + + if (styles.listFocusForeground) { + content.push(`.monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { color: ${styles.listFocusForeground}; }`); + } + + if (styles.listActiveSelectionBackground) { + content.push(`.monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: ${styles.listActiveSelectionBackground}; }`); + } + + if (styles.listActiveSelectionForeground) { + content.push(`.monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: ${styles.listActiveSelectionForeground}; }`); + } + + if (styles.listFocusAndSelectionBackground) { + content.push(` + .monaco-tree-drag-image, + .monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { background-color: ${styles.listFocusAndSelectionBackground}; } + `); + } + + if (styles.listFocusAndSelectionForeground) { + content.push(` + .monaco-tree-drag-image, + .monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { color: ${styles.listFocusAndSelectionForeground}; } + `); + } + + if (styles.listInactiveSelectionBackground) { + content.push(`.monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: ${styles.listInactiveSelectionBackground}; }`); + } + + if (styles.listInactiveSelectionForeground) { + content.push(`.monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: ${styles.listInactiveSelectionForeground}; }`); + } + + if (styles.listHoverBackground) { + content.push(`.monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`); + } + + if (styles.listHoverForeground) { + content.push(`.monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { color: ${styles.listHoverForeground}; }`); + } + + if (styles.listDropBackground) { + content.push(` + .monaco-tree${suffix} .monaco-tree-wrapper.drop-target, + .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; } + `); + } + + if (styles.listFocusOutline) { + content.push(` + .monaco-tree-drag-image { border: 1px solid ${styles.listFocusOutline}; background: #000; } + .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row { border: 1px solid transparent; } + .monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { border: 1px dotted ${styles.listFocusOutline}; } + .monaco-tree${suffix}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { border: 1px solid ${styles.listFocusOutline}; } + .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { border: 1px solid ${styles.listFocusOutline}; } + .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { border: 1px dashed ${styles.listFocusOutline}; } + .monaco-tree${suffix} .monaco-tree-wrapper.drop-target, + .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.drop-target { border: 1px dashed ${styles.listFocusOutline}; } + `); + } + + const newStyles = content.join('\n'); + if (newStyles !== this.styleElement.innerHTML) { + this.styleElement.innerHTML = newStyles; + } + } +} + export class CollapseAllAction extends Action { constructor(private viewer: _.ITree, enabled: boolean) { @@ -461,7 +542,7 @@ export class CollapseAllAction extends Action { this.viewer.collapseAll(); this.viewer.clearSelection(); this.viewer.clearFocus(); - this.viewer.DOMFocus(); + this.viewer.domFocus(); this.viewer.focusFirst(); return TPromise.as(null); diff --git a/src/vs/base/parts/tree/browser/treeDnd.ts b/src/vs/base/parts/tree/browser/treeDnd.ts index 3f3ab9af33..0a9dcd29ad 100644 --- a/src/vs/base/parts/tree/browser/treeDnd.ts +++ b/src/vs/base/parts/tree/browser/treeDnd.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import _ = require('vs/base/parts/tree/browser/tree'); -import Mouse = require('vs/base/browser/mouseEvent'); +import * as _ from 'vs/base/parts/tree/browser/tree'; +import * as Mouse from 'vs/base/browser/mouseEvent'; export class ElementsDragAndDropData implements _.IDragAndDropData { diff --git a/src/vs/base/parts/tree/browser/treeImpl.ts b/src/vs/base/parts/tree/browser/treeImpl.ts index e909b51322..2170e0c6b9 100644 --- a/src/vs/base/parts/tree/browser/treeImpl.ts +++ b/src/vs/base/parts/tree/browser/treeImpl.ts @@ -5,17 +5,15 @@ 'use strict'; import 'vs/css!./tree'; -import WinJS = require('vs/base/common/winjs.base'); -import TreeDefaults = require('vs/base/parts/tree/browser/treeDefaults'); -import Model = require('vs/base/parts/tree/browser/treeModel'); -import View = require('./treeView'); -import _ = require('vs/base/parts/tree/browser/tree'); +import * as WinJS from 'vs/base/common/winjs.base'; +import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults'; +import * as Model from 'vs/base/parts/tree/browser/treeModel'; +import * as View from './treeView'; +import * as _ from 'vs/base/parts/tree/browser/tree'; import { INavigator, MappedNavigator } from 'vs/base/common/iterator'; -import Event, { Emitter, Relay } from 'vs/base/common/event'; +import { Event, Emitter, Relay } from 'vs/base/common/event'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; -import { ISelectionEvent, IFocusEvent, IHighlightEvent } from 'vs/base/parts/tree/browser/tree'; -import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel'; export class TreeContext implements _.ITreeContext { @@ -30,6 +28,7 @@ export class TreeContext implements _.ITreeContext { public filter: _.IFilter; public sorter: _.ISorter; public accessibilityProvider: _.IAccessibilityProvider; + public styler: _.ITreeStyler; constructor(tree: _.ITree, configuration: _.ITreeConfiguration, options: _.ITreeOptions = {}) { this.tree = tree; @@ -47,6 +46,7 @@ export class TreeContext implements _.ITreeContext { this.filter = configuration.filter || new TreeDefaults.DefaultFilter(); this.sorter = configuration.sorter || null; this.accessibilityProvider = configuration.accessibilityProvider || new TreeDefaults.DefaultAccessibilityProvider(); + this.styler = configuration.styler || null; } } @@ -69,16 +69,16 @@ export class Tree implements _.ITree { private model: Model.TreeModel; private view: View.TreeView; - private _onDidChangeFocus = new Relay<IFocusEvent>(); - readonly onDidChangeFocus: Event<IFocusEvent> = this._onDidChangeFocus.event; - private _onDidChangeSelection = new Relay<ISelectionEvent>(); - readonly onDidChangeSelection: Event<ISelectionEvent> = this._onDidChangeSelection.event; - private _onHighlightChange = new Relay<IHighlightEvent>(); - readonly onDidChangeHighlight: Event<IHighlightEvent> = this._onHighlightChange.event; - private _onDidExpandItem = new Relay<IItemExpandEvent>(); - readonly onDidExpandItem: Event<IItemExpandEvent> = this._onDidExpandItem.event; - private _onDidCollapseItem = new Relay<IItemCollapseEvent>(); - readonly onDidCollapseItem: Event<IItemCollapseEvent> = this._onDidCollapseItem.event; + private _onDidChangeFocus = new Relay<_.IFocusEvent>(); + readonly onDidChangeFocus: Event<_.IFocusEvent> = this._onDidChangeFocus.event; + private _onDidChangeSelection = new Relay<_.ISelectionEvent>(); + readonly onDidChangeSelection: Event<_.ISelectionEvent> = this._onDidChangeSelection.event; + private _onHighlightChange = new Relay<_.IHighlightEvent>(); + readonly onDidChangeHighlight: Event<_.IHighlightEvent> = this._onHighlightChange.event; + private _onDidExpandItem = new Relay<Model.IItemExpandEvent>(); + readonly onDidExpandItem: Event<Model.IItemExpandEvent> = this._onDidExpandItem.event; + private _onDidCollapseItem = new Relay<Model.IItemCollapseEvent>(); + readonly onDidCollapseItem: Event<Model.IItemCollapseEvent> = this._onDidCollapseItem.event; private _onDispose = new Emitter<void>(); readonly onDidDispose: Event<void> = this._onDispose.event; @@ -122,11 +122,11 @@ export class Tree implements _.ITree { return this.view.getHTMLElement(); } - public layout(height?: number): void { - this.view.layout(height); + public layout(height?: number, width?: number): void { + this.view.layout(height, width); } - public DOMFocus(): void { + public domFocus(): void { this.view.focus(); } @@ -134,7 +134,7 @@ export class Tree implements _.ITree { return this.view.isFocused(); } - public DOMBlur(): void { + public domBlur(): void { this.view.blur(); } @@ -158,6 +158,11 @@ export class Tree implements _.ITree { return this.model.refresh(element, recursive); } + public updateWidth(element: any): void { + let item = this.model.getItem(element); + return this.view.updateWidth(item); + } + public expand(element: any): WinJS.Promise { return this.model.expand(element); } @@ -212,7 +217,7 @@ export class Tree implements _.ITree { } getContentHeight(): number { - return this.view.getTotalHeight(); + return this.view.getContentHeight(); } public setHighlight(element?: any, eventPayload?: any): void { diff --git a/src/vs/base/parts/tree/browser/treeModel.ts b/src/vs/base/parts/tree/browser/treeModel.ts index 207d3de1ba..4802c70cff 100644 --- a/src/vs/base/parts/tree/browser/treeModel.ts +++ b/src/vs/base/parts/tree/browser/treeModel.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Assert = require('vs/base/common/assert'); +import * as Assert from 'vs/base/common/assert'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; -import arrays = require('vs/base/common/arrays'); +import * as arrays from 'vs/base/common/arrays'; import { INavigator } from 'vs/base/common/iterator'; -import WinJS = require('vs/base/common/winjs.base'); -import _ = require('./tree'); -import Event, { Emitter, once, EventMultiplexer, Relay } from 'vs/base/common/event'; +import * as WinJS from 'vs/base/common/winjs.base'; +import * as _ from './tree'; +import { Event, Emitter, once, EventMultiplexer, Relay } from 'vs/base/common/event'; interface IMap<T> { [id: string]: T; } interface IItemMap extends IMap<Item> { } diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index ed77b62d15..e47932f6bb 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -4,27 +4,28 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Platform = require('vs/base/common/platform'); -import Browser = require('vs/base/browser/browser'); -import WinJS = require('vs/base/common/winjs.base'); -import Lifecycle = require('vs/base/common/lifecycle'); -import DOM = require('vs/base/browser/dom'); -import Diff = require('vs/base/common/diff/diff'); -import Touch = require('vs/base/browser/touch'); -import strings = require('vs/base/common/strings'); -import Mouse = require('vs/base/browser/mouseEvent'); -import Keyboard = require('vs/base/browser/keyboardEvent'); -import Model = require('vs/base/parts/tree/browser/treeModel'); -import dnd = require('./treeDnd'); +import * as Platform from 'vs/base/common/platform'; +import * as Browser from 'vs/base/browser/browser'; +import * as WinJS from 'vs/base/common/winjs.base'; +import * as Lifecycle from 'vs/base/common/lifecycle'; +import * as DOM from 'vs/base/browser/dom'; +import * as Diff from 'vs/base/common/diff/diff'; +import * as Touch from 'vs/base/browser/touch'; +import * as strings from 'vs/base/common/strings'; +import * as Mouse from 'vs/base/browser/mouseEvent'; +import * as Keyboard from 'vs/base/browser/keyboardEvent'; +import * as Model from 'vs/base/parts/tree/browser/treeModel'; +import * as dnd from './treeDnd'; import { ArrayIterator, MappedIterator } from 'vs/base/common/iterator'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; -import _ = require('vs/base/parts/tree/browser/tree'); +import * as _ from 'vs/base/parts/tree/browser/tree'; import { KeyCode } from 'vs/base/common/keyCodes'; -import Event, { Emitter } from 'vs/base/common/event'; -import { IDomNodePagePosition } from 'vs/base/browser/dom'; +import { Event, Emitter } from 'vs/base/common/event'; import { DataTransfers } from 'vs/base/browser/dnd'; +import { DefaultTreestyler } from './treeDefaults'; +import { Delayer } from 'vs/base/common/async'; export interface IRow { element: HTMLElement; @@ -100,6 +101,7 @@ export class RowCache implements Lifecycle.IDisposable { export interface IViewContext extends _.ITreeContext { cache: RowCache; + horizontalScrolling: boolean; } export class ViewItem implements IViewItem { @@ -112,6 +114,7 @@ export class ViewItem implements IViewItem { public top: number; public height: number; + public width: number = 0; public onDragStart: (e: DragEvent) => void; public needsRender: boolean; @@ -249,11 +252,35 @@ export class ViewItem implements IViewItem { } } - if (!skipUserRender) { + if (!skipUserRender && this.element) { + const style = window.getComputedStyle(this.element); + const paddingLeft = parseFloat(style.paddingLeft); + + if (this.context.horizontalScrolling) { + this.element.style.width = 'fit-content'; + } + this.context.renderer.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row.templateData); + + if (this.context.horizontalScrolling) { + this.width = DOM.getContentWidth(this.element) + paddingLeft; + this.element.style.width = ''; + } } } + updateWidth(): any { + if (!this.context.horizontalScrolling || !this.element) { + return; + } + + const style = window.getComputedStyle(this.element); + const paddingLeft = parseFloat(style.paddingLeft); + this.element.style.width = 'fit-content'; + this.width = DOM.getContentWidth(this.element) + paddingLeft; + this.element.style.width = ''; + } + public insertInDOM(container: HTMLElement, afterElement: HTMLElement): void { if (!this.row) { this.row = this.context.cache.alloc(this.templateId); @@ -378,12 +405,16 @@ export class TreeView extends HeightMap { private domNode: HTMLElement; private wrapper: HTMLElement; private styleElement: HTMLStyleElement; + private treeStyler: _.ITreeStyler; private rowsContainer: HTMLElement; private scrollableElement: ScrollableElement; private msGesture: MSGesture; private lastPointerType: string; private lastClickTimeStamp: number = 0; + private horizontalScrolling: boolean; + private contentWidthUpdateDelayer = new Delayer<void>(50); + private lastRenderTop: number; private lastRenderHeight: number; @@ -408,10 +439,10 @@ export class TreeView extends HeightMap { private highlightedItemWasDraggable: boolean; private onHiddenScrollTop: number; - private _onDOMFocus: Emitter<void> = new Emitter<void>(); + private readonly _onDOMFocus: Emitter<void> = new Emitter<void>(); get onDOMFocus(): Event<void> { return this._onDOMFocus.event; } - private _onDOMBlur: Emitter<void> = new Emitter<void>(); + private readonly _onDOMBlur: Emitter<void> = new Emitter<void>(); get onDOMBlur(): Event<void> { return this._onDOMBlur.event; } constructor(context: _.ITreeContext, container: HTMLElement) { @@ -420,6 +451,9 @@ export class TreeView extends HeightMap { TreeView.counter++; this.instance = TreeView.counter; + const horizontalScrollMode = typeof context.options.horizontalScrollMode === 'undefined' ? ScrollbarVisibility.Hidden : context.options.horizontalScrollMode; + this.horizontalScrolling = horizontalScrollMode !== ScrollbarVisibility.Hidden; + this.context = { dataSource: context.dataSource, renderer: context.renderer, @@ -430,7 +464,8 @@ export class TreeView extends HeightMap { tree: context.tree, accessibilityProvider: context.accessibilityProvider, options: context.options, - cache: new RowCache(context) + cache: new RowCache(context), + horizontalScrolling: this.horizontalScrolling }; this.modelListeners = []; @@ -446,6 +481,11 @@ export class TreeView extends HeightMap { this.styleElement = DOM.createStyleSheet(this.domNode); + this.treeStyler = context.styler; + if (!this.treeStyler) { + this.treeStyler = new DefaultTreestyler(this.styleElement, `monaco-tree-instance-${this.instance}`); + } + // ARIA this.domNode.setAttribute('role', 'tree'); if (this.context.options.ariaLabel) { @@ -464,12 +504,12 @@ export class TreeView extends HeightMap { this.wrapper.className = 'monaco-tree-wrapper'; this.scrollableElement = new ScrollableElement(this.wrapper, { alwaysConsumeMouseWheel: true, - horizontal: ScrollbarVisibility.Hidden, + horizontal: horizontalScrollMode, vertical: (typeof context.options.verticalScrollMode !== 'undefined' ? context.options.verticalScrollMode : ScrollbarVisibility.Auto), useShadows: context.options.useShadows }); this.scrollableElement.onScroll((e) => { - this.render(e.scrollTop, e.height); + this.render(e.scrollTop, e.height, e.scrollLeft, e.width, e.scrollWidth); }); if (Browser.isIE) { @@ -552,75 +592,7 @@ export class TreeView extends HeightMap { } public applyStyles(styles: _.ITreeStyles): void { - const content: string[] = []; - - if (styles.listFocusBackground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { background-color: ${styles.listFocusBackground}; }`); - } - - if (styles.listFocusForeground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { color: ${styles.listFocusForeground}; }`); - } - - if (styles.listActiveSelectionBackground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: ${styles.listActiveSelectionBackground}; }`); - } - - if (styles.listActiveSelectionForeground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: ${styles.listActiveSelectionForeground}; }`); - } - - if (styles.listFocusAndSelectionBackground) { - content.push(` - .monaco-tree-drag-image, - .monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { background-color: ${styles.listFocusAndSelectionBackground}; } - `); - } - - if (styles.listFocusAndSelectionForeground) { - content.push(` - .monaco-tree-drag-image, - .monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { color: ${styles.listFocusAndSelectionForeground}; } - `); - } - - if (styles.listInactiveSelectionBackground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: ${styles.listInactiveSelectionBackground}; }`); - } - - if (styles.listInactiveSelectionForeground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: ${styles.listInactiveSelectionForeground}; }`); - } - - if (styles.listHoverBackground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`); - } - - if (styles.listHoverForeground) { - content.push(`.monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { color: ${styles.listHoverForeground}; }`); - } - - if (styles.listDropBackground) { - content.push(` - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-wrapper.drop-target, - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; } - `); - } - - if (styles.listFocusOutline) { - content.push(` - .monaco-tree-drag-image { border: 1px solid ${styles.listFocusOutline}; background: #000; } - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row { border: 1px solid transparent; } - .monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { border: 1px dotted ${styles.listFocusOutline}; } - .monaco-tree.monaco-tree-instance-${this.instance}.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { border: 1px solid ${styles.listFocusOutline}; } - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { border: 1px solid ${styles.listFocusOutline}; } - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { border: 1px dashed ${styles.listFocusOutline}; } - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-wrapper.drop-target, - .monaco-tree.monaco-tree-instance-${this.instance} .monaco-tree-rows > .monaco-tree-row.drop-target { border: 1px dashed ${styles.listFocusOutline}; } - `); - } - - this.styleElement.innerHTML = content.join('\n'); + this.treeStyler.style(styles); } protected createViewItem(item: Model.Item): IViewItem { @@ -664,15 +636,20 @@ export class TreeView extends HeightMap { return this.onHiddenScrollTop === null; } - public layout(height?: number): void { + public layout(height?: number, width?: number): void { if (!this.isTreeVisible()) { return; } this.viewHeight = height || DOM.getContentHeight(this.wrapper); // render + this.scrollHeight = this.getContentHeight(); + + if (this.horizontalScrolling) { + this.viewWidth = width || DOM.getContentWidth(this.wrapper); + } } - private render(scrollTop: number, viewHeight: number): void { + private render(scrollTop: number, viewHeight: number, scrollLeft: number, viewWidth: number, scrollWidth: number): void { var i: number; var stop: number; @@ -706,6 +683,11 @@ export class TreeView extends HeightMap { this.rowsContainer.style.top = (topItem.top - renderTop) + 'px'; } + if (this.horizontalScrolling) { + this.rowsContainer.style.left = -scrollLeft + 'px'; + this.rowsContainer.style.width = `${Math.max(scrollWidth, viewWidth)}px`; + } + this.lastRenderTop = renderTop; this.lastRenderHeight = renderBottom - renderTop; } @@ -746,6 +728,24 @@ export class TreeView extends HeightMap { } this.scrollTop = scrollTop; + this.updateScrollWidth(); + } + + private updateScrollWidth(): void { + if (!this.horizontalScrolling) { + return; + } + + this.contentWidthUpdateDelayer.trigger(() => { + const keys = Object.keys(this.items); + let scrollWidth = 0; + + for (const key of keys) { + scrollWidth = Math.max(scrollWidth, this.items[key].width); + } + + this.scrollWidth = scrollWidth + 10 /* scrollbar */; + }); } public focusNextPage(eventPayload?: any): void { @@ -803,11 +803,25 @@ export class TreeView extends HeightMap { return scrollDimensions.height; } - public set viewHeight(viewHeight: number) { - this.scrollableElement.setScrollDimensions({ - height: viewHeight, - scrollHeight: this.getTotalHeight() - }); + public set viewHeight(height: number) { + this.scrollableElement.setScrollDimensions({ height }); + } + + private set scrollHeight(scrollHeight: number) { + this.scrollableElement.setScrollDimensions({ scrollHeight }); + } + + public get viewWidth(): number { + const scrollDimensions = this.scrollableElement.getScrollDimensions(); + return scrollDimensions.width; + } + + public set viewWidth(viewWidth: number) { + this.scrollableElement.setScrollDimensions({ width: viewWidth }); + } + + private set scrollWidth(scrollWidth: number) { + this.scrollableElement.setScrollDimensions({ scrollWidth }); } public get scrollTop(): number { @@ -817,7 +831,7 @@ export class TreeView extends HeightMap { public set scrollTop(scrollTop: number) { this.scrollableElement.setScrollDimensions({ - scrollHeight: this.getTotalHeight() + scrollHeight: this.getContentHeight() }); this.scrollableElement.setScrollPosition({ scrollTop: scrollTop @@ -825,12 +839,12 @@ export class TreeView extends HeightMap { } public getScrollPosition(): number { - const height = this.getTotalHeight() - this.viewHeight; + const height = this.getContentHeight() - this.viewHeight; return height <= 0 ? 1 : this.scrollTop / height; } public setScrollPosition(pos: number): void { - const height = this.getTotalHeight() - this.viewHeight; + const height = this.getContentHeight() - this.viewHeight; this.scrollTop = height * pos; } @@ -999,6 +1013,21 @@ export class TreeView extends HeightMap { } } + public updateWidth(item: Model.Item): void { + if (!item || !item.isVisible()) { + return; + } + + const viewItem = this.items[item.id]; + + if (!viewItem) { + return; + } + + viewItem.updateWidth(); + this.updateScrollWidth(); + } + public getRelativeTop(item: Model.Item): number { if (item && item.isVisible()) { var viewItem = this.items[item.id]; @@ -1222,7 +1251,7 @@ export class TreeView extends HeightMap { var keyboardEvent = new Keyboard.StandardKeyboardEvent(<KeyboardEvent>event); element = this.model.getFocus(); - var position: IDomNodePagePosition; + var position: DOM.IDomNodePagePosition; if (!element) { element = this.model.getInput(); @@ -1652,6 +1681,11 @@ export class TreeView extends HeightMap { } this.domNode = null; + if (this.items) { + Object.keys(this.items).forEach(key => this.items[key].removeFromDOM()); + this.items = null; + } + if (this.context.cache) { this.context.cache.dispose(); this.context.cache = null; diff --git a/src/vs/base/parts/tree/browser/treeViewModel.ts b/src/vs/base/parts/tree/browser/treeViewModel.ts index 10587c2a6b..0617854f47 100644 --- a/src/vs/base/parts/tree/browser/treeViewModel.ts +++ b/src/vs/base/parts/tree/browser/treeViewModel.ts @@ -10,6 +10,7 @@ export interface IViewItem { model: Item; top: number; height: number; + width: number; } export class HeightMap { @@ -22,7 +23,7 @@ export class HeightMap { this.indexes = {}; } - public getTotalHeight(): number { + public getContentHeight(): number { var last = this.heightMap[this.heightMap.length - 1]; return !last ? 0 : last.top + last.height; } diff --git a/src/vs/base/parts/tree/test/browser/treeModel.test.ts b/src/vs/base/parts/tree/test/browser/treeModel.test.ts index 612ebff6c9..0fe88e0d52 100644 --- a/src/vs/base/parts/tree/test/browser/treeModel.test.ts +++ b/src/vs/base/parts/tree/test/browser/treeModel.test.ts @@ -5,13 +5,13 @@ 'use strict'; -import assert = require('assert'); -import lifecycle = require('vs/base/common/lifecycle'); -import _ = require('vs/base/parts/tree/browser/tree'); -import WinJS = require('vs/base/common/winjs.base'); -import model = require('vs/base/parts/tree/browser/treeModel'); -import TreeDefaults = require('vs/base/parts/tree/browser/treeDefaults'); -import Event, { Emitter } from 'vs/base/common/event'; +import * as assert from 'assert'; +import * as lifecycle from 'vs/base/common/lifecycle'; +import * as _ from 'vs/base/parts/tree/browser/tree'; +import * as WinJS from 'vs/base/common/winjs.base'; +import * as model from 'vs/base/parts/tree/browser/treeModel'; +import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults'; +import { Event, Emitter } from 'vs/base/common/event'; export class FakeRenderer { @@ -201,64 +201,60 @@ suite('TreeModel', () => { assert.equal(model.getInput(), SAMPLE.ONE); }); - test('refresh() refreshes all', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh() refreshes all', () => { + return model.setInput(SAMPLE.AB).then(() => { counter.listen(model.onRefresh); // 1 counter.listen(model.onDidRefresh); // 1 counter.listen(model.onDidRefreshItem); // 4 counter.listen(model.onRefreshItemChildren); // 1 counter.listen(model.onDidRefreshItemChildren); // 1 return model.refresh(null); - }).done(() => { + }).then(() => { assert.equal(counter.count, 8); - done(); }); }); - test('refresh(root) refreshes all', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh(root) refreshes all', () => { + return model.setInput(SAMPLE.AB).then(() => { counter.listen(model.onRefresh); // 1 counter.listen(model.onDidRefresh); // 1 counter.listen(model.onDidRefreshItem); // 4 counter.listen(model.onRefreshItemChildren); // 1 counter.listen(model.onDidRefreshItemChildren); // 1 return model.refresh(SAMPLE.AB); - }).done(() => { + }).then(() => { assert.equal(counter.count, 8); - done(); }); }); - test('refresh(root, false) refreshes the root', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh(root, false) refreshes the root', () => { + return model.setInput(SAMPLE.AB).then(() => { counter.listen(model.onRefresh); // 1 counter.listen(model.onDidRefresh); // 1 counter.listen(model.onDidRefreshItem); // 1 counter.listen(model.onRefreshItemChildren); // 1 counter.listen(model.onDidRefreshItemChildren); // 1 return model.refresh(SAMPLE.AB, false); - }).done(() => { + }).then(() => { assert.equal(counter.count, 5); - done(); }); }); - test('refresh(collapsed element) does not refresh descendants', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh(collapsed element) does not refresh descendants', () => { + return model.setInput(SAMPLE.AB).then(() => { counter.listen(model.onRefresh); // 1 counter.listen(model.onDidRefresh); // 1 counter.listen(model.onDidRefreshItem); // 1 counter.listen(model.onRefreshItemChildren); // 0 counter.listen(model.onDidRefreshItemChildren); // 0 return model.refresh(SAMPLE.AB.children[0]); - }).done(() => { + }).then(() => { assert.equal(counter.count, 3); - done(); }); }); - test('refresh(expanded element) refreshes the element and descendants', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh(expanded element) refreshes the element and descendants', () => { + return model.setInput(SAMPLE.AB).then(() => { model.expand(SAMPLE.AB.children[0]); counter.listen(model.onRefresh); // 1 @@ -267,14 +263,13 @@ suite('TreeModel', () => { counter.listen(model.onRefreshItemChildren); // 1 counter.listen(model.onDidRefreshItemChildren); // 1 return model.refresh(SAMPLE.AB.children[0]); - }).done(() => { + }).then(() => { assert.equal(counter.count, 7); - done(); }); }); - test('refresh(element, false) refreshes the element', (done) => { - model.setInput(SAMPLE.AB).then(() => { + test('refresh(element, false) refreshes the element', () => { + return model.setInput(SAMPLE.AB).then(() => { model.expand(SAMPLE.AB.children[0]); counter.listen(model.onRefresh); // 1 @@ -286,57 +281,53 @@ suite('TreeModel', () => { counter.listen(model.onRefreshItemChildren); // 1 counter.listen(model.onDidRefreshItemChildren); // 1 return model.refresh(SAMPLE.AB.children[0], false); - }).done(() => { + }).then(() => { assert.equal(counter.count, 6); - done(); }); }); - test('depths', (done) => { - model.setInput(SAMPLE.AB).then(() => { - model.expandAll(['a', 'c']); + test('depths', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expandAll(['a', 'c']).then(() => { + counter.listen(model.onDidRefreshItem, item => { + switch (item.id) { + case 'ROOT': assert.equal(item.getDepth(), 0); break; + case 'a': assert.equal(item.getDepth(), 1); break; + case 'aa': assert.equal(item.getDepth(), 2); break; + case 'ab': assert.equal(item.getDepth(), 2); break; + case 'b': assert.equal(item.getDepth(), 1); break; + case 'c': assert.equal(item.getDepth(), 1); break; + case 'ca': assert.equal(item.getDepth(), 2); break; + case 'cb': assert.equal(item.getDepth(), 2); break; + default: return; + } + counter.up(); + }); - counter.listen(model.onDidRefreshItem, item => { - switch (item.id) { - case 'ROOT': assert.equal(item.getDepth(), 0); break; - case 'a': assert.equal(item.getDepth(), 1); break; - case 'aa': assert.equal(item.getDepth(), 2); break; - case 'ab': assert.equal(item.getDepth(), 2); break; - case 'b': assert.equal(item.getDepth(), 1); break; - case 'c': assert.equal(item.getDepth(), 1); break; - case 'ca': assert.equal(item.getDepth(), 2); break; - case 'cb': assert.equal(item.getDepth(), 2); break; - default: return; - } - counter.up(); + return model.refresh(); }); - - return model.refresh(); - }).done(() => { + }).then(() => { assert.equal(counter.count, 16); - done(); }); }); - test('intersections', (done) => { - model.setInput(SAMPLE.AB).done(() => { - model.expandAll(['a', 'c']); + test('intersections', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expandAll(['a', 'c']).then(() => { + // going internals + var r = (<any>model).registry; - // going internals - var r = (<any>model).registry; - - assert(r.getItem('a').intersects(r.getItem('a'))); - assert(r.getItem('a').intersects(r.getItem('aa'))); - assert(r.getItem('a').intersects(r.getItem('ab'))); - assert(r.getItem('aa').intersects(r.getItem('a'))); - assert(r.getItem('ab').intersects(r.getItem('a'))); - assert(!r.getItem('aa').intersects(r.getItem('ab'))); - assert(!r.getItem('a').intersects(r.getItem('b'))); - assert(!r.getItem('a').intersects(r.getItem('c'))); - assert(!r.getItem('a').intersects(r.getItem('ca'))); - assert(!r.getItem('aa').intersects(r.getItem('ca'))); - - done(); + assert(r.getItem('a').intersects(r.getItem('a'))); + assert(r.getItem('a').intersects(r.getItem('aa'))); + assert(r.getItem('a').intersects(r.getItem('ab'))); + assert(r.getItem('aa').intersects(r.getItem('a'))); + assert(r.getItem('ab').intersects(r.getItem('a'))); + assert(!r.getItem('aa').intersects(r.getItem('ab'))); + assert(!r.getItem('a').intersects(r.getItem('b'))); + assert(!r.getItem('a').intersects(r.getItem('c'))); + assert(!r.getItem('a').intersects(r.getItem('ca'))); + assert(!r.getItem('aa').intersects(r.getItem('ca'))); + }); }); }); }); @@ -357,19 +348,18 @@ suite('TreeModel - TreeNavigator', () => { model.dispose(); }); - test('next()', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('next()', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'a'); assert.equal(nav.next().id, 'b'); assert.equal(nav.next().id, 'c'); assert.equal(nav.next() && false, null); - done(); }); }); - test('previous()', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('previous()', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(); nav.next(); @@ -379,13 +369,12 @@ suite('TreeModel - TreeNavigator', () => { assert.equal(nav.previous().id, 'b'); assert.equal(nav.previous().id, 'a'); assert.equal(nav.previous() && false, null); - done(); }); }); - test('parent()', (done) => { - model.setInput(SAMPLE.AB).done(() => { - model.expandAll([{ id: 'a' }, { id: 'c' }]).done(() => { + test('parent()', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'a'); @@ -404,67 +393,62 @@ suite('TreeModel - TreeNavigator', () => { assert.equal(nav.parent().id, 'c'); assert.equal(nav.parent() && false, null); - done(); }); }); }); - test('next() - scoped', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('next() - scoped', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0]); - model.expand({ id: 'a' }).done(() => { + return model.expand({ id: 'a' }).then(() => { assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.next() && false, null); - done(); }); }); }); - test('previous() - scoped', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('previous() - scoped', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0]); - model.expand({ id: 'a' }).done(() => { + return model.expand({ id: 'a' }).then(() => { assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.previous().id, 'aa'); assert.equal(nav.previous() && false, null); - done(); }); }); }); - test('parent() - scoped', (done) => { - model.setInput(SAMPLE.AB).done(() => { - model.expandAll([{ id: 'a' }, { id: 'c' }]).done(() => { + test('parent() - scoped', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0]); assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.parent() && false, null); - done(); }); }); }); - test('next() - non sub tree only', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('next() - non sub tree only', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0], false); - model.expand({ id: 'a' }).done(() => { + return model.expand({ id: 'a' }).then(() => { assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.next().id, 'b'); assert.equal(nav.next().id, 'c'); assert.equal(nav.next() && false, null); - done(); }); }); }); - test('previous() - non sub tree only', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('previous() - non sub tree only', () => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0], false); - model.expand({ id: 'a' }).done(() => { + return model.expand({ id: 'a' }).then(() => { assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.next().id, 'b'); @@ -474,49 +458,47 @@ suite('TreeModel - TreeNavigator', () => { assert.equal(nav.previous().id, 'aa'); assert.equal(nav.previous().id, 'a'); assert.equal(nav.previous() && false, null); - done(); }); }); }); - test('parent() - non sub tree only', (done) => { - model.setInput(SAMPLE.AB).done(() => { - model.expandAll([{ id: 'a' }, { id: 'c' }]).done(() => { + test('parent() - non sub tree only', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => { var nav = model.getNavigator(SAMPLE.AB.children[0], false); assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'ab'); assert.equal(nav.parent().id, 'a'); assert.equal(nav.parent() && false, null); - done(); }); }); }); - test('deep next() - scoped', (done) => { - model.setInput(SAMPLE.DEEP).done(() => { - model.expand(SAMPLE.DEEP.children[0]); - model.expand(SAMPLE.DEEP.children[0].children[0]); - - var nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]); - assert.equal(nav.next().id, 'xa'); - assert.equal(nav.next().id, 'xb'); - assert.equal(nav.next() && false, null); - done(); + test('deep next() - scoped', () => { + return model.setInput(SAMPLE.DEEP).then(() => { + return model.expand(SAMPLE.DEEP.children[0]).then(() => { + return model.expand(SAMPLE.DEEP.children[0].children[0]).then(() => { + var nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]); + assert.equal(nav.next().id, 'xa'); + assert.equal(nav.next().id, 'xb'); + assert.equal(nav.next() && false, null); + }); + }); }); }); - test('deep previous() - scoped', (done) => { - model.setInput(SAMPLE.DEEP).done(() => { - model.expand(SAMPLE.DEEP.children[0]); - model.expand(SAMPLE.DEEP.children[0].children[0]); - - var nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]); - assert.equal(nav.next().id, 'xa'); - assert.equal(nav.next().id, 'xb'); - assert.equal(nav.previous().id, 'xa'); - assert.equal(nav.previous() && false, null); - done(); + test('deep previous() - scoped', () => { + return model.setInput(SAMPLE.DEEP).then(() => { + return model.expand(SAMPLE.DEEP.children[0]).then(() => { + return model.expand(SAMPLE.DEEP.children[0].children[0]).then(() => { + var nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]); + assert.equal(nav.next().id, 'xa'); + assert.equal(nav.next().id, 'xb'); + assert.equal(nav.previous().id, 'xa'); + assert.equal(nav.previous() && false, null); + }); + }); }); }); @@ -546,8 +528,8 @@ suite('TreeModel - Expansion', () => { model.dispose(); }); - test('collapse, expand', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('collapse, expand', () => { + return model.setInput(SAMPLE.AB).then(() => { counter.listen(model.onExpandItem, (e) => { assert.equal(e.item.id, 'a'); var nav = model.getNavigator(e.item); @@ -572,7 +554,7 @@ suite('TreeModel - Expansion', () => { assert.equal(model.getExpandedElements().length, 0); - model.expand(SAMPLE.AB.children[0]).done(() => { + return model.expand(SAMPLE.AB.children[0]).then(() => { assert(model.isExpanded(SAMPLE.AB.children[0])); nav = model.getNavigator(); @@ -588,46 +570,42 @@ suite('TreeModel - Expansion', () => { assert.equal(expandedElements[0].id, 'a'); assert.equal(counter.count, 2); - done(); }); }); }); - test('toggleExpansion', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('toggleExpansion', () => { + return model.setInput(SAMPLE.AB).then(() => { assert(!model.isExpanded(SAMPLE.AB.children[0])); - model.toggleExpansion(SAMPLE.AB.children[0]).done(() => { + return model.toggleExpansion(SAMPLE.AB.children[0]).then(() => { assert(model.isExpanded(SAMPLE.AB.children[0])); assert(!model.isExpanded(SAMPLE.AB.children[0].children[0])); - model.toggleExpansion(SAMPLE.AB.children[0].children[0]).done(() => { + return model.toggleExpansion(SAMPLE.AB.children[0].children[0]).then(() => { assert(!model.isExpanded(SAMPLE.AB.children[0].children[0])); - model.toggleExpansion(SAMPLE.AB.children[0]).done(() => { + return model.toggleExpansion(SAMPLE.AB.children[0]).then(() => { assert(!model.isExpanded(SAMPLE.AB.children[0])); - - done(); }); }); }); }); }); - test('collapseAll', (done) => { - model.setInput(SAMPLE.DEEP2).done(() => { - model.expand(SAMPLE.DEEP2.children[0]).done(() => { - model.expand(SAMPLE.DEEP2.children[0].children[0]).done(() => { + test('collapseAll', () => { + return model.setInput(SAMPLE.DEEP2).then(() => { + return model.expand(SAMPLE.DEEP2.children[0]).then(() => { + return model.expand(SAMPLE.DEEP2.children[0].children[0]).then(() => { assert(model.isExpanded(SAMPLE.DEEP2.children[0])); assert(model.isExpanded(SAMPLE.DEEP2.children[0].children[0])); - model.collapseAll().done(() => { + return model.collapseAll().then(() => { assert(!model.isExpanded(SAMPLE.DEEP2.children[0])); - model.expand(SAMPLE.DEEP2.children[0]).done(() => { + return model.expand(SAMPLE.DEEP2.children[0]).then(() => { assert(!model.isExpanded(SAMPLE.DEEP2.children[0].children[0])); - done(); }); }); }); @@ -635,37 +613,35 @@ suite('TreeModel - Expansion', () => { }); }); - test('collapseDeepestExpandedLevel', (done) => { - model.setInput(SAMPLE.DEEP2).done(() => { - model.expand(SAMPLE.DEEP2.children[0]).done(() => { - model.expand(SAMPLE.DEEP2.children[0].children[0]).done(() => { + test('collapseDeepestExpandedLevel', () => { + return model.setInput(SAMPLE.DEEP2).then(() => { + return model.expand(SAMPLE.DEEP2.children[0]).then(() => { + return model.expand(SAMPLE.DEEP2.children[0].children[0]).then(() => { assert(model.isExpanded(SAMPLE.DEEP2.children[0])); assert(model.isExpanded(SAMPLE.DEEP2.children[0].children[0])); - model.collapseDeepestExpandedLevel().done(() => { + return model.collapseDeepestExpandedLevel().then(() => { assert(model.isExpanded(SAMPLE.DEEP2.children[0])); assert(!model.isExpanded(SAMPLE.DEEP2.children[0].children[0])); - done(); }); }); }); }); }); - test('auto expand single child folders', (done) => { - model.setInput(SAMPLE.DEEP).done(() => { - model.expand(SAMPLE.DEEP.children[0]).done(() => { + test('auto expand single child folders', () => { + return model.setInput(SAMPLE.DEEP).then(() => { + return model.expand(SAMPLE.DEEP.children[0]).then(() => { assert(model.isExpanded(SAMPLE.DEEP.children[0])); assert(model.isExpanded(SAMPLE.DEEP.children[0].children[0])); - done(); }); }); }); - test('expand can trigger refresh', (done) => { + test('expand can trigger refresh', () => { // MUnit.expect(16); - model.setInput(SAMPLE.AB).done(() => { + return model.setInput(SAMPLE.AB).then(() => { assert(!model.isExpanded(SAMPLE.AB.children[0])); @@ -685,7 +661,7 @@ suite('TreeModel - Expansion', () => { g(); }); - model.expand(SAMPLE.AB.children[0]).done(() => { + return model.expand(SAMPLE.AB.children[0]).then(() => { assert(model.isExpanded(SAMPLE.AB.children[0])); nav = model.getNavigator(); @@ -697,28 +673,25 @@ suite('TreeModel - Expansion', () => { assert.equal(nav.next() && false, null); assert.equal(counter.count, 2); - done(); }); }); }); - test('top level collapsed', (done) => { - model.setInput(SAMPLE.AB).done(() => { - - model.collapseAll([{ id: 'a' }, { id: 'b' }, { id: 'c' }]); - - var nav = model.getNavigator(); - assert.equal(nav.next().id, 'a'); - assert.equal(nav.next().id, 'b'); - assert.equal(nav.next().id, 'c'); - assert.equal(nav.previous().id, 'b'); - assert.equal(nav.previous().id, 'a'); - assert.equal(nav.previous() && false, null); - done(); + test('top level collapsed', () => { + return model.setInput(SAMPLE.AB).then(() => { + return model.collapseAll([{ id: 'a' }, { id: 'b' }, { id: 'c' }]).then(() => { + var nav = model.getNavigator(); + assert.equal(nav.next().id, 'a'); + assert.equal(nav.next().id, 'b'); + assert.equal(nav.next().id, 'c'); + assert.equal(nav.previous().id, 'b'); + assert.equal(nav.previous().id, 'a'); + assert.equal(nav.previous() && false, null); + }); }); }); - test('shouldAutoexpand', (done) => { + test('shouldAutoexpand', () => { // setup const model = new TreeModel({ dataSource: { @@ -734,13 +707,12 @@ suite('TreeModel - Expansion', () => { } }); - model.setInput('root').then(() => { + return model.setInput('root').then(() => { return model.refresh('root', true); }).then(() => { assert(!model.isExpanded('a')); assert(model.isExpanded('b')); assert(!model.isExpanded('c')); - done(); }); }); }); @@ -777,10 +749,10 @@ suite('TreeModel - Filter', () => { model.dispose(); }); - test('no filter', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('no filter', () => { + return model.setInput(SAMPLE.AB).then(() => { - model.expandAll([{ id: 'a' }, { id: 'c' }]).done(() => { + return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'a'); assert.equal(nav.next().id, 'aa'); @@ -797,30 +769,27 @@ suite('TreeModel - Filter', () => { assert.equal(nav.previous().id, 'aa'); assert.equal(nav.previous().id, 'a'); assert.equal(nav.previous() && false, null); - - done(); }); }); }); - test('filter all', (done) => { + test('filter all', () => { filter.fn = () => false; - model.setInput(SAMPLE.AB).done(() => { - model.refresh(); - var nav = model.getNavigator(); - assert.equal(nav.next() && false, null); - - done(); + return model.setInput(SAMPLE.AB).then(() => { + return model.refresh().then(() => { + var nav = model.getNavigator(); + assert.equal(nav.next() && false, null); + }); }); }); - test('simple filter', (done) => { + test('simple filter', () => { // hide elements that do not start with 'a' filter.fn = (e) => e.id[0] === 'a'; - model.setInput(SAMPLE.AB).done(() => { - model.expand({ id: 'a' }).done(() => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expand({ id: 'a' }).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'a'); @@ -829,35 +798,32 @@ suite('TreeModel - Filter', () => { assert.equal(nav.previous().id, 'aa'); assert.equal(nav.previous().id, 'a'); assert.equal(nav.previous() && false, null); - done(); }); }); }); - test('simple filter 2', (done) => { + test('simple filter 2', () => { // hide 'ab' filter.fn = (e) => e.id !== 'ab'; - model.setInput(SAMPLE.AB).done(() => { - model.expand({ id: 'a' }).done(() => { - + return model.setInput(SAMPLE.AB).then(() => { + return model.expand({ id: 'a' }).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'a'); assert.equal(nav.next().id, 'aa'); assert.equal(nav.next().id, 'b'); assert.equal(nav.next().id, 'c'); assert.equal(nav.next() && false, null); - done(); }); }); }); - test('simple filter, opposite', (done) => { + test('simple filter, opposite', () => { // hide elements that start with 'a' filter.fn = (e) => e.id[0] !== 'a'; - model.setInput(SAMPLE.AB).done(() => { - model.expand({ id: 'c' }).done(() => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expand({ id: 'c' }).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'b'); @@ -868,17 +834,16 @@ suite('TreeModel - Filter', () => { assert.equal(nav.previous().id, 'c'); assert.equal(nav.previous().id, 'b'); assert.equal(nav.previous() && false, null); - done(); }); }); }); - test('simple filter, mischieving', (done) => { + test('simple filter, mischieving', () => { // hide the element 'a' filter.fn = (e) => e.id !== 'a'; - model.setInput(SAMPLE.AB).done(() => { - model.expand({ id: 'c' }).done(() => { + return model.setInput(SAMPLE.AB).then(() => { + return model.expand({ id: 'c' }).then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'b'); @@ -889,20 +854,18 @@ suite('TreeModel - Filter', () => { assert.equal(nav.previous().id, 'c'); assert.equal(nav.previous().id, 'b'); assert.equal(nav.previous() && false, null); - done(); }); }); }); - test('simple filter & previous', (done) => { + test('simple filter & previous', () => { // hide 'b' filter.fn = (e) => e.id !== 'b'; - model.setInput(SAMPLE.AB).done(() => { + return model.setInput(SAMPLE.AB).then(() => { var nav = model.getNavigator({ id: 'c' }, false); assert.equal(nav.previous().id, 'a'); assert.equal(nav.previous() && false, null); - done(); }); }); }); @@ -923,8 +886,8 @@ suite('TreeModel - Traits', () => { model.dispose(); }); - test('Selection', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('Selection', () => { + return model.setInput(SAMPLE.AB).then(() => { assert.equal(model.getSelection().length, 0); model.select(SAMPLE.AB.children[1]); assert(model.isSelected(SAMPLE.AB.children[1])); @@ -1015,13 +978,11 @@ suite('TreeModel - Traits', () => { assert.equal(model.isSelected(SAMPLE.AB.children[0]), true); assert.equal(model.isSelected(SAMPLE.AB.children[2]), false); - - done(); }); }); - test('Focus', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('Focus', () => { + return model.setInput(SAMPLE.AB).then(() => { assert(!model.getFocus()); model.setFocus(SAMPLE.AB.children[1]); assert(model.isFocused(SAMPLE.AB.children[1])); @@ -1095,13 +1056,11 @@ suite('TreeModel - Traits', () => { assert(model.isFocused(SAMPLE.AB.children[0])); model.focusNth(1); assert(model.isFocused(SAMPLE.AB.children[1])); - - done(); }); }); - test('Highlight', (done) => { - model.setInput(SAMPLE.AB).done(() => { + test('Highlight', () => { + return model.setInput(SAMPLE.AB).then(() => { assert(!model.getHighlight()); model.setHighlight(SAMPLE.AB.children[1]); assert(model.isHighlighted(SAMPLE.AB.children[1])); @@ -1132,8 +1091,6 @@ suite('TreeModel - Traits', () => { assert(!model.isHighlighted(SAMPLE.AB.children[0])); assert(!model.isHighlighted(SAMPLE.AB.children[1])); assert(!model.isHighlighted(SAMPLE.AB.children[2])); - - done(); }); }); }); @@ -1218,15 +1175,15 @@ suite('TreeModel - Dynamic data model', () => { model.dispose(); }); - test('items get property disposed', (done) => { + test('items get property disposed', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); dataModel.addChild('father', 'daughter'); dataModel.addChild('son', 'baby'); - model.setInput('root').done(() => { - model.expandAll(['grandfather', 'father', 'son']).done(() => { + return model.setInput('root').then(() => { + return model.expandAll(['grandfather', 'father', 'son']).then(() => { dataModel.removeChild('grandfather', 'father'); var items = ['baby', 'son', 'daughter', 'father']; @@ -1235,21 +1192,20 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(items[times++], item.id); }); - model.refresh().done(() => { + return model.refresh().then(() => { assert.equal(times, items.length); assert.equal(counter.count, 4); - done(); }); }); }); }); - test('addChild, removeChild, collapse', (done) => { + test('addChild, removeChild, collapse', () => { dataModel.addChild('root', 'super'); dataModel.addChild('root', 'hyper'); dataModel.addChild('root', 'mega'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'super'); assert.equal(nav.next().id, 'hyper'); @@ -1257,7 +1213,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next() && false, null); dataModel.removeChild('root', 'hyper'); - model.refresh().done(() => { + return model.refresh().then(() => { nav = model.getNavigator(); assert.equal(nav.next().id, 'super'); assert.equal(nav.next().id, 'mega'); @@ -1267,8 +1223,8 @@ suite('TreeModel - Dynamic data model', () => { dataModel.addChild('mega', 'nano'); dataModel.addChild('mega', 'pico'); - model.refresh().done(() => { - model.expand('mega').done(() => { + return model.refresh().then(() => { + return model.expand('mega').then(() => { nav = model.getNavigator(); assert.equal(nav.next().id, 'super'); assert.equal(nav.next().id, 'mega'); @@ -1282,15 +1238,13 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next().id, 'super'); assert.equal(nav.next().id, 'mega'); assert.equal(nav.next() && false, null); - - done(); }); }); }); }); }); - test('move', (done) => { + test('move', () => { dataModel.addChild('root', 'super'); dataModel.addChild('super', 'apples'); dataModel.addChild('super', 'bananas'); @@ -1298,9 +1252,9 @@ suite('TreeModel - Dynamic data model', () => { dataModel.addChild('root', 'hyper'); dataModel.addChild('root', 'mega'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { - model.expand('super').done(() => { + return model.expand('super').then(() => { var nav = model.getNavigator(); assert.equal(nav.next().id, 'super'); @@ -1314,9 +1268,9 @@ suite('TreeModel - Dynamic data model', () => { dataModel.move('bananas', 'super', 'hyper'); dataModel.move('apples', 'super', 'mega'); - model.refresh().done(() => { + return model.refresh().then(() => { - model.expandAll(['hyper', 'mega']).done(() => { + return model.expandAll(['hyper', 'mega']).then(() => { nav = model.getNavigator(); assert.equal(nav.next().id, 'super'); assert.equal(nav.next().id, 'pears'); @@ -1325,20 +1279,18 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next().id, 'mega'); assert.equal(nav.next().id, 'apples'); assert.equal(nav.next() && false, null); - - done(); }); }); }); }); }); - test('refreshing grandfather recursively should not refresh collapsed father\'s children immediately', (done) => { + test('refreshing grandfather recursively should not refresh collapsed father\'s children immediately', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.collapse('father'); @@ -1348,7 +1300,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(element, 'grandfather'); }); - model.refresh('grandfather').done(() => { + return model.refresh('grandfather').then(() => { assert.equal(times, 1); listener.dispose(); @@ -1357,22 +1309,21 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(element, 'father'); }); - model.expand('father').done(() => { + return model.expand('father').then(() => { assert.equal(times, 2); listener.dispose(); - done(); }); }); }); }); - test('simultaneously refreshing two disjoint elements should parallelize the refreshes', (done) => { + test('simultaneously refreshing two disjoint elements should parallelize the refreshes', () => { dataModel.addChild('root', 'father'); dataModel.addChild('root', 'mother'); dataModel.addChild('father', 'son'); dataModel.addChild('mother', 'daughter'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('father'); model.expand('mother'); @@ -1403,7 +1354,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(getTimes, 2); assert.equal(gotTimes, 0); - WinJS.Promise.join([p1, p2]).done(() => { + return WinJS.Promise.join([p1, p2]).then(() => { assert.equal(getTimes, 2); assert.equal(gotTimes, 2); @@ -1416,17 +1367,16 @@ suite('TreeModel - Dynamic data model', () => { getListener.dispose(); gotListener.dispose(); - done(); }); }); }); - test('simultaneously recursively refreshing two intersecting elements should concatenate the refreshes - ancestor first', (done) => { + test('simultaneously recursively refreshing two intersecting elements should concatenate the refreshes - ancestor first', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); @@ -1487,7 +1437,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(getTimes, 3); assert.equal(gotTimes, 3); - p2.done(() => { + return p2.then(() => { nav = model.getNavigator(); assert.equal(nav.next().id, 'grandfather'); assert.equal(nav.next().id, 'father'); @@ -1496,17 +1446,16 @@ suite('TreeModel - Dynamic data model', () => { getListener.dispose(); gotListener.dispose(); - done(); }); }); }); - test('simultaneously recursively refreshing two intersecting elements should concatenate the refreshes - ancestor second', (done) => { + test('simultaneously recursively refreshing two intersecting elements should concatenate the refreshes - ancestor second', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); @@ -1552,7 +1501,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(getTimes, 3); assert.equal(gotTimes, 3); - p2.done(() => { + return p2.then(() => { nav = model.getNavigator(); assert.equal(nav.next().id, 'grandfather'); assert.equal(nav.next().id, 'father'); @@ -1561,16 +1510,15 @@ suite('TreeModel - Dynamic data model', () => { getListener.dispose(); gotListener.dispose(); - done(); }); }); }); - test('refreshing an empty element that adds children should still keep it collapsed', (done) => { + test('refreshing an empty element that adds children should still keep it collapsed', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); @@ -1578,19 +1526,18 @@ suite('TreeModel - Dynamic data model', () => { dataModel.addChild('father', 'son'); - model.refresh('father').done(() => { + return model.refresh('father').then(() => { assert(!model.isExpanded('father')); - done(); }); }); }); - test('refreshing a collapsed element that adds children should still keep it collapsed', (done) => { + test('refreshing a collapsed element that adds children should still keep it collapsed', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); model.collapse('father'); @@ -1599,39 +1546,37 @@ suite('TreeModel - Dynamic data model', () => { dataModel.addChild('father', 'daughter'); - model.refresh('father').done(() => { + return model.refresh('father').then(() => { assert(!model.isExpanded('father')); - done(); }); }); }); - test('recursively refreshing an ancestor of an expanded element, should keep that element expanded', (done) => { + test('recursively refreshing an ancestor of an expanded element, should keep that element expanded', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); assert(model.isExpanded('grandfather')); assert(model.isExpanded('father')); - model.refresh('grandfather').done(() => { + return model.refresh('grandfather').then(() => { assert(model.isExpanded('grandfather')); assert(model.isExpanded('father')); - done(); }); }); }); - test('recursively refreshing an ancestor of a collapsed element, should keep that element collapsed', (done) => { + test('recursively refreshing an ancestor of a collapsed element, should keep that element collapsed', () => { dataModel.addChild('root', 'grandfather'); dataModel.addChild('grandfather', 'father'); dataModel.addChild('father', 'son'); - model.setInput('root').done(() => { + return model.setInput('root').then(() => { model.expand('grandfather'); model.expand('father'); model.collapse('father'); @@ -1639,21 +1584,20 @@ suite('TreeModel - Dynamic data model', () => { assert(model.isExpanded('grandfather')); assert(!model.isExpanded('father')); - model.refresh('grandfather').done(() => { + return model.refresh('grandfather').then(() => { assert(model.isExpanded('grandfather')); assert(!model.isExpanded('father')); - done(); }); }); }); - test('Bug 10855:[explorer] quickly deleting things causes NPE in tree - intersectsLock should always be called when trying to unlock', (done) => { + test('Bug 10855:[explorer] quickly deleting things causes NPE in tree - intersectsLock should always be called when trying to unlock', () => { dataModel.addChild('root', 'father'); dataModel.addChild('father', 'son'); dataModel.addChild('root', 'mother'); dataModel.addChild('mother', 'daughter'); - model.setInput('root').then(() => { + return model.setInput('root').then(() => { // delay expansions and refreshes dataModel.promiseFactory = () => { return WinJS.TPromise.timeout(0); }; @@ -1673,7 +1617,7 @@ suite('TreeModel - Dynamic data model', () => { }, (errs) => { assert(false, 'should not fail'); }); - }).done(done); + }); }); }); @@ -1691,7 +1635,7 @@ suite('TreeModel - bugs', () => { /** * This bug occurs when an item is expanded right during its removal */ - test('Bug 10566:[tree] build viewlet is broken after some time', (done) => { + test('Bug 10566:[tree] build viewlet is broken after some time', () => { // setup let model = new TreeModel({ dataSource: { @@ -1718,7 +1662,7 @@ suite('TreeModel - bugs', () => { counter.listen(model.onExpandItem, () => { assert(false, 'should never receive item:expanding event'); }); counter.listen(model.onDidExpandItem, () => { assert(false, 'should never receive item:expanded event'); }); - model.setInput('root').then(() => { + return model.setInput('root').then(() => { // remove bart getRootChildren = getGetRootChildren(['homer', 'lisa', 'marge', 'maggie'], 10); @@ -1740,7 +1684,7 @@ suite('TreeModel - bugs', () => { // what now? return WinJS.Promise.join([p1, p2]); - }).done(() => { + }).then(() => { // teardown while (listeners.length > 0) { listeners.pop()(); } @@ -1749,7 +1693,6 @@ suite('TreeModel - bugs', () => { model = null; assert.equal(counter.count, 0); - done(); }); }); }); diff --git a/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts b/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts index 5d7b5d630d..268a437eb7 100644 --- a/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts +++ b/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts @@ -5,7 +5,7 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; import { ArrayIterator } from 'vs/base/common/iterator'; import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; @@ -45,7 +45,8 @@ class TestHeightMap extends HeightMap { return { model: item, top: 0, - height: item.getHeight() + height: item.getHeight(), + width: 0 }; } } diff --git a/src/vs/base/test/browser/builder.test.ts b/src/vs/base/test/browser/builder.test.ts index 13a168c569..2e3ce33a8b 100644 --- a/src/vs/base/test/browser/builder.test.ts +++ b/src/vs/base/test/browser/builder.test.ts @@ -5,11 +5,24 @@ 'use strict'; import * as assert from 'assert'; -import { Build, Builder, MultiBuilder, $, bindElement, withElement, setPropertyOnElement, getPropertyFromElement } from 'vs/base/browser/builder'; +import { Builder, MultiBuilder, $, bindElement, withElement, setPropertyOnElement, getPropertyFromElement } from 'vs/base/browser/builder'; import * as Types from 'vs/base/common/types'; import * as DomUtils from 'vs/base/browser/dom'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { timeout } from 'vs/base/common/async'; + +function withElementById(id: string, offdom?: boolean): Builder { + let element = document.getElementById(id); + if (element) { + return new Builder(element, offdom); + } + + return null; +} + +const Build = { + withElementById: withElementById +}; let withElementsBySelector = function (selector: string, offdom: boolean = false) { let elements = window.document.querySelectorAll(selector); diff --git a/src/vs/base/test/browser/progressBar.test.ts b/src/vs/base/test/browser/progressBar.test.ts index 25e737169a..61c7b2e435 100644 --- a/src/vs/base/test/browser/progressBar.test.ts +++ b/src/vs/base/test/browser/progressBar.test.ts @@ -6,7 +6,6 @@ import * as assert from 'assert'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; -import { Builder } from 'vs/base/browser/builder'; suite('ProgressBar', () => { let fixture: HTMLElement; @@ -21,10 +20,7 @@ suite('ProgressBar', () => { }); test('Progress Bar', function () { - const b = new Builder(fixture); - - const bar = new ProgressBar(b); - assert(bar.getContainer()); + const bar = new ProgressBar(fixture); assert(bar.infinite()); assert(bar.total(100)); assert(bar.worked(50)); diff --git a/src/vs/base/test/browser/ui/list/rangeMap.test.ts b/src/vs/base/test/browser/ui/list/rangeMap.test.ts index 33d22f60d2..74e5cc6dc2 100644 --- a/src/vs/base/test/browser/ui/list/rangeMap.test.ts +++ b/src/vs/base/test/browser/ui/list/rangeMap.test.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import assert = require('assert'); +import * as assert from 'assert'; import { RangeMap, intersect, groupIntersect, consolidate } from 'vs/base/browser/ui/list/rangeMap'; suite('RangeMap', () => { diff --git a/src/vs/base/test/common/arrays.test.ts b/src/vs/base/test/common/arrays.test.ts index 22867a0ea5..7f127f93bb 100644 --- a/src/vs/base/test/common/arrays.test.ts +++ b/src/vs/base/test/common/arrays.test.ts @@ -6,32 +6,31 @@ import * as assert from 'assert'; import { TPromise } from 'vs/base/common/winjs.base'; -import arrays = require('vs/base/common/arrays'); -import { coalesce } from 'vs/base/common/arrays'; +import * as arrays from 'vs/base/common/arrays'; suite('Arrays', () => { test('findFirst', function () { const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69]; - let idx = arrays.findFirst(array, e => e >= 0); + let idx = arrays.findFirstInSorted(array, e => e >= 0); assert.equal(array[idx], 1); - idx = arrays.findFirst(array, e => e > 1); + idx = arrays.findFirstInSorted(array, e => e > 1); assert.equal(array[idx], 4); - idx = arrays.findFirst(array, e => e >= 8); + idx = arrays.findFirstInSorted(array, e => e >= 8); assert.equal(array[idx], 55); - idx = arrays.findFirst(array, e => e >= 61); + idx = arrays.findFirstInSorted(array, e => e >= 61); assert.equal(array[idx], 61); - idx = arrays.findFirst(array, e => e >= 69); + idx = arrays.findFirstInSorted(array, e => e >= 69); assert.equal(array[idx], 69); - idx = arrays.findFirst(array, e => e >= 70); + idx = arrays.findFirstInSorted(array, e => e >= 70); assert.equal(idx, array.length); - idx = arrays.findFirst([], e => e >= 0); + idx = arrays.findFirstInSorted([], e => e >= 0); assert.equal(array[idx], 1); }); @@ -76,7 +75,7 @@ suite('Arrays', () => { for (let i = 1; i < array.length; i++) { let n = array[i]; if (last > n) { - assert.fail(array.slice(i - 10, i + 10)); + assert.fail(JSON.stringify(array.slice(i - 10, i + 10))); } } } @@ -218,18 +217,17 @@ suite('Arrays', () => { assert.deepEqual(arrays.top([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3), [1, 2, 3]); }); - test('topAsync', function (done) { + test('topAsync', function () { const cmp = (a: number, b: number) => { assert.strictEqual(typeof a, 'number', 'typeof a'); assert.strictEqual(typeof b, 'number', 'typeof b'); return a - b; }; - testTopAsync(cmp, 1) + return testTopAsync(cmp, 1) .then(() => { return testTopAsync(cmp, 2); - }) - .then(done, done); + }); }); function testTopAsync(cmp: any, m: number) { @@ -272,13 +270,13 @@ suite('Arrays', () => { } test('coalesce', function () { - let a = coalesce([null, 1, null, 2, 3]); + let a = arrays.coalesce([null, 1, null, 2, 3]); assert.equal(a.length, 3); assert.equal(a[0], 1); assert.equal(a[1], 2); assert.equal(a[2], 3); - coalesce([null, 1, null, void 0, undefined, 2, 3]); + arrays.coalesce([null, 1, null, void 0, undefined, 2, 3]); assert.equal(a.length, 3); assert.equal(a[0], 1); assert.equal(a[1], 2); @@ -288,7 +286,7 @@ suite('Arrays', () => { b[10] = 1; b[20] = 2; b[30] = 3; - b = coalesce(b); + b = arrays.coalesce(b); assert.equal(b.length, 3); assert.equal(b[0], 1); assert.equal(b[1], 2); @@ -303,7 +301,7 @@ suite('Arrays', () => { assert.equal(sparse.length, 1002); - sparse = coalesce(sparse); + sparse = arrays.coalesce(sparse); assert.equal(sparse.length, 5); }); }); diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index 75fdaf5668..95c52e7525 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -6,11 +6,11 @@ import * as assert from 'assert'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import Async = require('vs/base/common/async'); +import * as Async from 'vs/base/common/async'; import URI from 'vs/base/common/uri'; suite('Async', () => { - test('Throttler - non async', function (done) { + test('Throttler - non async', function () { let count = 0; let factory = () => { return TPromise.as(++count); @@ -18,16 +18,16 @@ suite('Async', () => { let throttler = new Async.Throttler(); - Promise.join([ + return Promise.join([ throttler.queue(factory).then((result) => { assert.equal(result, 1); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }), throttler.queue(factory).then((result) => { assert.equal(result, 3); }), throttler.queue(factory).then((result) => { assert.equal(result, 4); }), throttler.queue(factory).then((result) => { assert.equal(result, 5); }) - ]).done(() => done()); + ]); }); - test('Throttler', function (done) { + test('Throttler', function () { let count = 0; let factory = () => { return TPromise.timeout(0).then(() => { @@ -37,24 +37,24 @@ suite('Async', () => { let throttler = new Async.Throttler(); - Promise.join([ + return Promise.join([ throttler.queue(factory).then((result) => { assert.equal(result, 1); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }) - ]).done(() => { + ]).then(() => { Promise.join([ throttler.queue(factory).then((result) => { assert.equal(result, 3); }), throttler.queue(factory).then((result) => { assert.equal(result, 4); }), throttler.queue(factory).then((result) => { assert.equal(result, 4); }), throttler.queue(factory).then((result) => { assert.equal(result, 4); }), throttler.queue(factory).then((result) => { assert.equal(result, 4); }) - ]).done(() => done()); + ]); }); }); - test('Throttler - cancel should not cancel other promises', function (done) { + test('Throttler - cancel should not cancel other promises', function () { let count = 0; let factory = () => { return TPromise.timeout(0).then(() => { @@ -65,17 +65,19 @@ suite('Async', () => { let throttler = new Async.Throttler(); let p1: Promise; - Promise.join([ + const p = Promise.join([ p1 = throttler.queue(factory).then((result) => { assert(false, 'should not be here, 1'); }, () => { assert(true, 'yes, it was cancelled'); }), throttler.queue(factory).then((result) => { assert.equal(result, 1); }, () => { assert(false, 'should not be here, 2'); }), throttler.queue(factory).then((result) => { assert.equal(result, 1); }, () => { assert(false, 'should not be here, 3'); }), throttler.queue(factory).then((result) => { assert.equal(result, 1); }, () => { assert(false, 'should not be here, 4'); }) - ]).done(() => done()); + ]); p1.cancel(); + + return p; }); - test('Throttler - cancel the first queued promise should not cancel other promises', function (done) { + test('Throttler - cancel the first queued promise should not cancel other promises', function () { let count = 0; let factory = () => { return TPromise.timeout(0).then(() => { @@ -86,17 +88,19 @@ suite('Async', () => { let throttler = new Async.Throttler(); let p2: Promise; - Promise.join([ + const p = Promise.join([ throttler.queue(factory).then((result) => { assert.equal(result, 1); }, () => { assert(false, 'should not be here, 1'); }), p2 = throttler.queue(factory).then((result) => { assert(false, 'should not be here, 2'); }, () => { assert(true, 'yes, it was cancelled'); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }, () => { assert(false, 'should not be here, 3'); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }, () => { assert(false, 'should not be here, 4'); }) - ]).done(() => done()); + ]); p2.cancel(); + + return p; }); - test('Throttler - cancel in the middle should not cancel other promises', function (done) { + test('Throttler - cancel in the middle should not cancel other promises', function () { let count = 0; let factory = () => { return TPromise.timeout(0).then(() => { @@ -107,17 +111,19 @@ suite('Async', () => { let throttler = new Async.Throttler(); let p3: Promise; - Promise.join([ + const p = Promise.join([ throttler.queue(factory).then((result) => { assert.equal(result, 1); }, () => { assert(false, 'should not be here, 1'); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }, () => { assert(false, 'should not be here, 2'); }), p3 = throttler.queue(factory).then((result) => { assert(false, 'should not be here, 3'); }, () => { assert(true, 'yes, it was cancelled'); }), throttler.queue(factory).then((result) => { assert.equal(result, 2); }, () => { assert(false, 'should not be here, 4'); }) - ]).done(() => done()); + ]); p3.cancel(); + + return p; }); - test('Throttler - last factory should be the one getting called', function (done) { + test('Throttler - last factory should be the one getting called', function () { let factoryFactory = (n: number) => () => { return TPromise.timeout(0).then(() => n); }; @@ -130,10 +136,10 @@ suite('Async', () => { promises.push(throttler.queue(factoryFactory(2)).then((n) => { assert.equal(n, 3); })); promises.push(throttler.queue(factoryFactory(3)).then((n) => { assert.equal(n, 3); })); - Promise.join(promises).done(() => done()); + return Promise.join(promises); }); - test('Throttler - progress should work', function (done) { + test('Throttler - progress should work', function () { let order = 0; let factory = () => new TPromise((c, e, p) => { TPromise.timeout(0).done(() => { @@ -150,15 +156,14 @@ suite('Async', () => { promises.push(throttler.queue(factory).then(null, null, (p) => progresses[1].push(p))); promises.push(throttler.queue(factory).then(null, null, (p) => progresses[2].push(p))); - Promise.join(promises).done(() => { + return Promise.join(promises).then(() => { assert.deepEqual(progresses[0], [0]); assert.deepEqual(progresses[1], [0]); assert.deepEqual(progresses[2], [0]); - done(); }); }); - test('Delayer', function (done) { + test('Delayer', function () { let count = 0; let factory = () => { return TPromise.as(++count); @@ -178,13 +183,12 @@ suite('Async', () => { promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()); })); assert(delayer.isTriggered()); - Promise.join(promises).done(() => { + return Promise.join(promises).then(() => { assert(!delayer.isTriggered()); - done(); }); }); - test('Delayer - simple cancel', function (done) { + test('Delayer - simple cancel', function () { let count = 0; let factory = () => { return TPromise.as(++count); @@ -194,18 +198,20 @@ suite('Async', () => { assert(!delayer.isTriggered()); - delayer.trigger(factory).then(() => { + const p = delayer.trigger(factory).then(() => { assert(false); }, () => { assert(true, 'yes, it was cancelled'); - }).done(() => done()); + }); assert(delayer.isTriggered()); delayer.cancel(); assert(!delayer.isTriggered()); + + return p; }); - test('Delayer - cancel should cancel all calls to trigger', function (done) { + test('Delayer - cancel should cancel all calls to trigger', function () { let count = 0; let factory = () => { return TPromise.as(++count); @@ -227,13 +233,12 @@ suite('Async', () => { delayer.cancel(); - Promise.join(promises).done(() => { + return Promise.join(promises).then(() => { assert(!delayer.isTriggered()); - done(); }); }); - test('Delayer - trigger, cancel, then trigger again', function (done) { + test('Delayer - trigger, cancel, then trigger again', function () { let count = 0; let factory = () => { return TPromise.as(++count); @@ -244,7 +249,7 @@ suite('Async', () => { assert(!delayer.isTriggered()); - delayer.trigger(factory).then((result) => { + const p = delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()); @@ -256,8 +261,7 @@ suite('Async', () => { delayer.cancel(); - Promise.join(promises).then(() => { - + const p = Promise.join(promises).then(() => { promises = []; assert(!delayer.isTriggered()); @@ -268,22 +272,26 @@ suite('Async', () => { promises.push(delayer.trigger(factory).then(() => { assert.equal(result, 1); assert(!delayer.isTriggered()); })); assert(delayer.isTriggered()); - Promise.join(promises).then(() => { + const p = Promise.join(promises).then(() => { assert(!delayer.isTriggered()); - - done(); }); assert(delayer.isTriggered()); + + return p; }); assert(delayer.isTriggered()); + + return p; }); assert(delayer.isTriggered()); + + return p; }); - test('Delayer - last task should be the one getting called', function (done) { + test('Delayer - last task should be the one getting called', function () { let factoryFactory = (n: number) => () => { return TPromise.as(n); }; @@ -297,15 +305,16 @@ suite('Async', () => { promises.push(delayer.trigger(factoryFactory(2)).then((n) => { assert.equal(n, 3); })); promises.push(delayer.trigger(factoryFactory(3)).then((n) => { assert.equal(n, 3); })); - Promise.join(promises).then(() => { + const p = Promise.join(promises).then(() => { assert(!delayer.isTriggered()); - done(); }); assert(delayer.isTriggered()); + + return p; }); - test('Delayer - progress should work', function (done) { + test('Delayer - progress should work', function () { let order = 0; let factory = () => new TPromise((c, e, p) => { TPromise.timeout(0).done(() => { @@ -322,15 +331,14 @@ suite('Async', () => { promises.push(delayer.trigger(factory).then(null, null, (p) => progresses[1].push(p))); promises.push(delayer.trigger(factory).then(null, null, (p) => progresses[2].push(p))); - Promise.join(promises).done(() => { + return Promise.join(promises).then(() => { assert.deepEqual(progresses[0], [0]); assert.deepEqual(progresses[1], [0]); assert.deepEqual(progresses[2], [0]); - done(); }); }); - test('ThrottledDelayer - progress should work', function (done) { + test('ThrottledDelayer - progress should work', function () { let order = 0; let factory = () => new TPromise((c, e, p) => { TPromise.timeout(0).done(() => { @@ -347,20 +355,19 @@ suite('Async', () => { promises.push(delayer.trigger(factory).then(null, null, (p) => progresses[1].push(p))); promises.push(delayer.trigger(factory).then(null, null, (p) => progresses[2].push(p))); - Promise.join(promises).done(() => { + return Promise.join(promises).then(() => { assert.deepEqual(progresses[0], [0]); assert.deepEqual(progresses[1], [0]); assert.deepEqual(progresses[2], [0]); - done(); }); }); - test('Sequence', function (done) { + test('Sequence', function () { let factoryFactory = (n: number) => () => { return TPromise.as(n); }; - Async.sequence([ + return Async.sequence([ factoryFactory(1), factoryFactory(2), factoryFactory(3), @@ -373,11 +380,10 @@ suite('Async', () => { assert.equal(3, result[2]); assert.equal(4, result[3]); assert.equal(5, result[4]); - done(); }); }); - test('Limiter - sync', function (done) { + test('Limiter - sync', function () { let factoryFactory = (n: number) => () => { return TPromise.as(n); }; @@ -387,7 +393,7 @@ suite('Async', () => { let promises: Promise[] = []; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n)))); - Promise.join(promises).then((res) => { + return Promise.join(promises).then((res) => { assert.equal(10, res.length); limiter = new Async.Limiter(100); @@ -398,10 +404,10 @@ suite('Async', () => { return Promise.join(promises).then((res) => { assert.equal(10, res.length); }); - }).done(() => done()); + }); }); - test('Limiter - async', function (done) { + test('Limiter - async', function () { let factoryFactory = (n: number) => () => { return TPromise.timeout(0).then(() => n); }; @@ -410,7 +416,7 @@ suite('Async', () => { let promises: Promise[] = []; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n)))); - Promise.join(promises).then((res) => { + return Promise.join(promises).then((res) => { assert.equal(10, res.length); limiter = new Async.Limiter(100); @@ -418,13 +424,13 @@ suite('Async', () => { promises = []; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n)))); - Promise.join(promises).then((res) => { + return Promise.join(promises).then((res) => { assert.equal(10, res.length); }); - }).done(() => done()); + }); }); - test('Limiter - assert degree of paralellism', function (done) { + test('Limiter - assert degree of paralellism', function () { let activePromises = 0; let factoryFactory = (n: number) => () => { activePromises++; @@ -437,14 +443,13 @@ suite('Async', () => { let promises: Promise[] = []; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n)))); - Promise.join(promises).then((res) => { + return Promise.join(promises).then((res) => { assert.equal(10, res.length); assert.deepEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], res); - done(); }); }); - test('Queue - simple', function (done) { + test('Queue - simple', function () { let queue = new Async.Queue(); let syncPromise = false; @@ -464,12 +469,10 @@ suite('Async', () => { assert.equal(queue.size, 1); assert.ok(syncPromise); assert.ok(asyncPromise); - - done(); }); }); - test('Queue - order is kept', function (done) { + test('Queue - order is kept', function () { let queue = new Async.Queue(); let res: number[] = []; @@ -484,18 +487,16 @@ suite('Async', () => { queue.queue(f2); queue.queue(f3); queue.queue(f4); - queue.queue(f5).then(() => { + return queue.queue(f5).then(() => { assert.equal(res[0], 1); assert.equal(res[1], 2); assert.equal(res[2], 3); assert.equal(res[3], 4); assert.equal(res[4], 5); - - done(); }); }); - test('Queue - errors bubble individually but not cause stop', function (done) { + test('Queue - errors bubble individually but not cause stop', function () { let queue = new Async.Queue(); let res: number[] = []; @@ -511,18 +512,16 @@ suite('Async', () => { queue.queue(f2); queue.queue(f3).then(null, () => error = true); queue.queue(f4); - queue.queue(f5).then(() => { + return queue.queue(f5).then(() => { assert.equal(res[0], 1); assert.equal(res[1], 2); assert.ok(error); assert.equal(res[2], 4); assert.equal(res[3], 5); - - done(); }); }); - test('Queue - order is kept (chained)', function (done) { + test('Queue - order is kept (chained)', function () { let queue = new Async.Queue(); let res: number[] = []; @@ -533,18 +532,16 @@ suite('Async', () => { let f4 = () => TPromise.timeout(20).then(() => res.push(4)); let f5 = () => TPromise.timeout(0).then(() => res.push(5)); - queue.queue(f1).then(() => { - queue.queue(f2).then(() => { - queue.queue(f3).then(() => { - queue.queue(f4).then(() => { - queue.queue(f5).then(() => { + return queue.queue(f1).then(() => { + return queue.queue(f2).then(() => { + return queue.queue(f3).then(() => { + return queue.queue(f4).then(() => { + return queue.queue(f5).then(() => { assert.equal(res[0], 1); assert.equal(res[1], 2); assert.equal(res[2], 3); assert.equal(res[3], 4); assert.equal(res[4], 5); - - done(); }); }); }); diff --git a/src/vs/base/test/common/cache.test.ts b/src/vs/base/test/common/cache.test.ts index 9dcd5a1274..9a2f661da9 100644 --- a/src/vs/base/test/common/cache.test.ts +++ b/src/vs/base/test/common/cache.test.ts @@ -16,9 +16,9 @@ suite('Cache', () => { const cache = new Cache(() => TPromise.as(counter++)); return cache.get() - .then(c => assert.equal(c, 0), () => assert.fail()) + .then(c => assert.equal(c, 0), () => assert.fail('Unexpected assertion error')) .then(() => cache.get()) - .then(c => assert.equal(c, 0), () => assert.fail()); + .then(c => assert.equal(c, 0), () => assert.fail('Unexpected assertion error')); }); test('simple error', () => { @@ -26,9 +26,9 @@ suite('Cache', () => { const cache = new Cache(() => TPromise.wrapError(new Error(String(counter++)))); return cache.get() - .then(() => assert.fail(), err => assert.equal(err.message, 0)) + .then(() => assert.fail('Unexpected assertion error'), err => assert.equal(err.message, 0)) .then(() => cache.get()) - .then(() => assert.fail(), err => assert.equal(err.message, 0)); + .then(() => assert.fail('Unexpected assertion error'), err => assert.equal(err.message, 0)); }); test('should retry cancellations', () => { diff --git a/src/vs/base/test/common/cancellation.test.ts b/src/vs/base/test/common/cancellation.test.ts index 5ee05a1118..c4227f77e1 100644 --- a/src/vs/base/test/common/cancellation.test.ts +++ b/src/vs/base/test/common/cancellation.test.ts @@ -82,4 +82,18 @@ suite('CancellationToken', function () { token = source.token; assert.ok(token === source.token); // doesn't change on get }); + + test('dispose calls no listeners', function () { + + let count = 0; + + let source = new CancellationTokenSource(); + source.token.onCancellationRequested(function () { + count += 1; + }); + + source.dispose(); + source.cancel(); + assert.equal(count, 0); + }); }); diff --git a/src/vs/base/test/common/collections.test.ts b/src/vs/base/test/common/collections.test.ts index 9e0187c55f..6a9a2ed1f8 100644 --- a/src/vs/base/test/common/collections.test.ts +++ b/src/vs/base/test/common/collections.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import collections = require('vs/base/common/collections'); +import * as collections from 'vs/base/common/collections'; suite('Collections', () => { diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index b08a15471e..dc254fa448 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -5,9 +5,9 @@ 'use strict'; import * as assert from 'assert'; -import Event, { Emitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch, buffer, echo, EventMultiplexer } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch, buffer, echo, EventMultiplexer, latch } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Errors = require('vs/base/common/errors'); +import * as Errors from 'vs/base/common/errors'; import { TPromise } from 'vs/base/common/winjs.base'; namespace Samples { @@ -183,7 +183,7 @@ suite('Event', function () { doc.setText('3'); }); - test('Debounce Event - leading', function (done: () => void) { + test('Debounce Event - leading', function () { const emitter = new Emitter<void>(); let debounced = debounceEvent(emitter.event, (l, e) => e, 0, /*leading=*/true); @@ -194,13 +194,13 @@ suite('Event', function () { // If the source event is fired once, the debounced (on the leading edge) event should be fired only once emitter.fire(); - setTimeout(() => { + + return TPromise.timeout(1).then(() => { assert.equal(calls, 1); - done(); }); }); - test('Debounce Event - leading', function (done: () => void) { + test('Debounce Event - leading', function () { const emitter = new Emitter<void>(); let debounced = debounceEvent(emitter.event, (l, e) => e, 0, /*leading=*/true); @@ -213,9 +213,8 @@ suite('Event', function () { emitter.fire(); emitter.fire(); emitter.fire(); - setTimeout(() => { + return TPromise.timeout(1).then(() => { assert.equal(calls, 2); - done(); }); }); @@ -652,4 +651,40 @@ suite('Event utils', () => { assert.deepEqual(result, [1, 2, 3, 4, 5]); }); }); + + test('latch', function () { + const emitter = new Emitter<number>(); + const event = latch(emitter.event); + + const result: number[] = []; + const listener = event(num => result.push(num)); + + assert.deepEqual(result, []); + + emitter.fire(1); + assert.deepEqual(result, [1]); + + emitter.fire(2); + assert.deepEqual(result, [1, 2]); + + emitter.fire(2); + assert.deepEqual(result, [1, 2]); + + emitter.fire(1); + assert.deepEqual(result, [1, 2, 1]); + + emitter.fire(1); + assert.deepEqual(result, [1, 2, 1]); + + emitter.fire(3); + assert.deepEqual(result, [1, 2, 1, 3]); + + emitter.fire(3); + assert.deepEqual(result, [1, 2, 1, 3]); + + emitter.fire(3); + assert.deepEqual(result, [1, 2, 1, 3]); + + listener.dispose(); + }); }); diff --git a/src/vs/base/test/common/history.test.ts b/src/vs/base/test/common/history.test.ts index 1bf1f9f00f..a4c45aa2e8 100644 --- a/src/vs/base/test/common/history.test.ts +++ b/src/vs/base/test/common/history.test.ts @@ -9,36 +9,36 @@ import { HistoryNavigator } from 'vs/base/common/history'; suite('History Navigator', () => { - test('create reduces the input to limit', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); + test('create reduces the input to limit', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); assert.deepEqual(['3', '4'], toArray(testObject)); }); - test('create sets the position to last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('create sets the position to last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('4', testObject.current()); assert.equal(null, testObject.next()); assert.equal('3', testObject.previous()); }); - test('last returns last element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('last returns last element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); assert.equal('4', testObject.last()); }); - test('first returns first element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('first returns first element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('2', testObject.first()); }); - test('next returns next element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('next returns next element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); @@ -47,16 +47,16 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('previous returns previous element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('previous returns previous element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('3', testObject.previous()); assert.equal('2', testObject.previous()); assert.equal(null, testObject.previous()); }); - test('next on last element returs null and remains on last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('next on last element returs null and remains on last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); testObject.last(); @@ -65,8 +65,8 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('previous on first element returs null and remains on first', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('previous on first element returs null and remains on first', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); @@ -74,24 +74,24 @@ suite('History Navigator', () => { assert.equal(null, testObject.previous()); }); - test('add reduces the input to limit', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); + test('add reduces the input to limit', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); testObject.add('5'); assert.deepEqual(['4', '5'], toArray(testObject)); }); - test('adding existing element changes the position', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 5); + test('adding existing element changes the position', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 5); testObject.add('2'); assert.deepEqual(['1', '3', '4', '2'], toArray(testObject)); }); - test('add resets the navigator to last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('add resets the navigator to last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); testObject.add('5'); @@ -100,14 +100,21 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('adding an existing item changes the order', function () { - let testObject = new HistoryNavigator(['1', '2', '3']); + test('adding an existing item changes the order', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); testObject.add('1'); assert.deepEqual(['2', '3', '1'], toArray(testObject)); }); + test('clear', () => { + const testObject = new HistoryNavigator(['a', 'b', 'c']); + assert.equal('c', testObject.current()); + testObject.clear(); + assert.equal(undefined, testObject.current()); + }); + function toArray(historyNavigator: HistoryNavigator<string>): string[] { let result = []; historyNavigator.first(); diff --git a/src/vs/base/test/common/jsonEdit.test.ts b/src/vs/base/test/common/jsonEdit.test.ts index 61e29be676..9910b63601 100644 --- a/src/vs/base/test/common/jsonEdit.test.ts +++ b/src/vs/base/test/common/jsonEdit.test.ts @@ -6,7 +6,7 @@ import { FormattingOptions, Edit } from 'vs/base/common/jsonFormatter'; import { setProperty, removeProperty } from 'vs/base/common/jsonEdit'; -import assert = require('assert'); +import * as assert from 'assert'; suite('JSON - edits', () => { diff --git a/src/vs/base/test/common/jsonFormatter.test.ts b/src/vs/base/test/common/jsonFormatter.test.ts index 30b6c0ab32..f5ff646d29 100644 --- a/src/vs/base/test/common/jsonFormatter.test.ts +++ b/src/vs/base/test/common/jsonFormatter.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Formatter = require('vs/base/common/jsonFormatter'); -import assert = require('assert'); +import * as Formatter from 'vs/base/common/jsonFormatter'; +import * as assert from 'assert'; suite('JSON - formatter', () => { diff --git a/src/vs/base/test/common/labels.test.ts b/src/vs/base/test/common/labels.test.ts index 6ec001dcf0..8637115345 100644 --- a/src/vs/base/test/common/labels.test.ts +++ b/src/vs/base/test/common/labels.test.ts @@ -6,9 +6,8 @@ 'use strict'; import * as assert from 'assert'; -import labels = require('vs/base/common/labels'); -import platform = require('vs/base/common/platform'); -import { getBaseLabel } from 'vs/base/common/labels'; +import * as labels from 'vs/base/common/labels'; +import * as platform from 'vs/base/common/platform'; suite('Labels', () => { test('shorten - windows', () => { @@ -125,9 +124,9 @@ suite('Labels', () => { // conditional separator assert.strictEqual(labels.template('Foo${separator}Bar'), 'FooBar'); - assert.strictEqual(labels.template('Foo${separator}Bar', { separator: { label: ' - ' } }), 'FooBar'); - assert.strictEqual(labels.template('${separator}Foo${separator}Bar', { value: 'something', separator: { label: ' - ' } }), 'FooBar'); - assert.strictEqual(labels.template('${value} Foo${separator}Bar', { value: 'something', separator: { label: ' - ' } }), 'something FooBar'); + assert.strictEqual(labels.template('Foo${separator}Bar', { separator: { label: ' - ' } }), 'Foo - Bar'); + assert.strictEqual(labels.template('${separator}Foo${separator}Bar', { value: 'something', separator: { label: ' - ' } }), 'Foo - Bar'); + assert.strictEqual(labels.template('${value} Foo${separator}Bar', { value: 'something', separator: { label: ' - ' } }), 'something Foo - Bar'); // // real world example (macOS) let t = '${activeEditorShort}${separator}${rootName}'; @@ -151,9 +150,9 @@ suite('Labels', () => { return; } - assert.equal(getBaseLabel('/some/folder/file.txt'), 'file.txt'); - assert.equal(getBaseLabel('/some/folder'), 'folder'); - assert.equal(getBaseLabel('/'), '/'); + assert.equal(labels.getBaseLabel('/some/folder/file.txt'), 'file.txt'); + assert.equal(labels.getBaseLabel('/some/folder'), 'folder'); + assert.equal(labels.getBaseLabel('/'), '/'); }); test('getBaseLabel - windows', () => { @@ -162,9 +161,9 @@ suite('Labels', () => { return; } - assert.equal(getBaseLabel('c:'), 'C:'); - assert.equal(getBaseLabel('c:\\'), 'C:'); - assert.equal(getBaseLabel('c:\\some\\folder\\file.txt'), 'file.txt'); - assert.equal(getBaseLabel('c:\\some\\folder'), 'folder'); + assert.equal(labels.getBaseLabel('c:'), 'C:'); + assert.equal(labels.getBaseLabel('c:\\'), 'C:'); + assert.equal(labels.getBaseLabel('c:\\some\\folder\\file.txt'), 'file.txt'); + assert.equal(labels.getBaseLabel('c:\\some\\folder'), 'folder'); }); }); \ No newline at end of file diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts index f0b48eb474..4e6bec9e90 100644 --- a/src/vs/base/test/common/map.test.ts +++ b/src/vs/base/test/common/map.test.ts @@ -200,6 +200,33 @@ suite('Map', () => { assert.deepStrictEqual(cache.values(), values); }); + test('LinkedMap - toJSON / fromJSON', () => { + let map = new LinkedMap<string, string>(); + map.set('ak', 'av'); + map.set('bk', 'bv'); + map.set('ck', 'cv'); + + const json = map.toJSON(); + map = new LinkedMap<string, string>(); + map.fromJSON(json); + + let i = 0; + map.forEach((value, key) => { + if (i === 0) { + assert.equal(key, 'ak'); + assert.equal(value, 'av'); + } else if (i === 1) { + assert.equal(key, 'bk'); + assert.equal(value, 'bv'); + } else if (i === 2) { + assert.equal(key, 'ck'); + assert.equal(value, 'cv'); + } + + i++; + }); + }); + test('PathIterator', function () { const iter = new PathIterator(); iter.reset('file:///usr/bin/file.txt'); @@ -517,32 +544,32 @@ suite('Map', () => { assert.equal(map.get(uncFile), 'true'); }); - test('ResourceMap - files (ignorecase)', function () { - const map = new ResourceMap<any>(true); + // test('ResourceMap - files (ignorecase)', function () { + // const map = new ResourceMap<any>(true); - const fileA = URI.parse('file://some/filea'); - const fileB = URI.parse('some://some/other/fileb'); - const fileAUpper = URI.parse('file://SOME/FILEA'); + // const fileA = URI.parse('file://some/filea'); + // const fileB = URI.parse('some://some/other/fileb'); + // const fileAUpper = URI.parse('file://SOME/FILEA'); - map.set(fileA, 'true'); - assert.equal(map.get(fileA), 'true'); + // map.set(fileA, 'true'); + // assert.equal(map.get(fileA), 'true'); - assert.equal(map.get(fileAUpper), 'true'); + // assert.equal(map.get(fileAUpper), 'true'); - assert.ok(!map.get(fileB)); + // assert.ok(!map.get(fileB)); - map.set(fileAUpper, 'false'); - assert.equal(map.get(fileAUpper), 'false'); + // map.set(fileAUpper, 'false'); + // assert.equal(map.get(fileAUpper), 'false'); - assert.equal(map.get(fileA), 'false'); + // assert.equal(map.get(fileA), 'false'); - const windowsFile = URI.file('c:\\test with %25\\c#code'); - const uncFile = URI.file('\\\\shäres\\path\\c#\\plugin.json'); + // const windowsFile = URI.file('c:\\test with %25\\c#code'); + // const uncFile = URI.file('\\\\shäres\\path\\c#\\plugin.json'); - map.set(windowsFile, 'true'); - map.set(uncFile, 'true'); + // map.set(windowsFile, 'true'); + // map.set(uncFile, 'true'); - assert.equal(map.get(windowsFile), 'true'); - assert.equal(map.get(uncFile), 'true'); - }); + // assert.equal(map.get(windowsFile), 'true'); + // assert.equal(map.get(uncFile), 'true'); + // }); }); diff --git a/src/vs/base/test/common/objects.test.ts b/src/vs/base/test/common/objects.test.ts index 8aec1ac88d..743e6445d7 100644 --- a/src/vs/base/test/common/objects.test.ts +++ b/src/vs/base/test/common/objects.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import objects = require('vs/base/common/objects'); +import * as objects from 'vs/base/common/objects'; let check = (one: any, other: any, msg: string) => { assert(objects.equals(one, other), msg); diff --git a/src/vs/base/test/common/paths.test.ts b/src/vs/base/test/common/paths.test.ts index eac3146223..eb7f262500 100644 --- a/src/vs/base/test/common/paths.test.ts +++ b/src/vs/base/test/common/paths.test.ts @@ -5,8 +5,8 @@ 'use strict'; import * as assert from 'assert'; -import paths = require('vs/base/common/paths'); -import platform = require('vs/base/common/platform'); +import * as paths from 'vs/base/common/paths'; +import * as platform from 'vs/base/common/platform'; suite('Paths', () => { @@ -20,6 +20,7 @@ suite('Paths', () => { assert.equal(paths.dirname('/'), '/'); assert.equal(paths.dirname('\\'), '\\'); assert.equal(paths.dirname('foo'), '.'); + assert.equal(paths.dirname('/folder/'), '/'); if (platform.isWindows) { assert.equal(paths.dirname('c:\\some\\file.txt'), 'c:\\some'); assert.equal(paths.dirname('c:\\some'), 'c:\\'); @@ -226,4 +227,4 @@ suite('Paths', () => { assert.ok(!paths.isAbsolute_posix(nonAbsolutePath), nonAbsolutePath); }); }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/common/resources.test.ts b/src/vs/base/test/common/resources.test.ts index 6d40ac71d3..78965e920e 100644 --- a/src/vs/base/test/common/resources.test.ts +++ b/src/vs/base/test/common/resources.test.ts @@ -42,13 +42,12 @@ suite('Resources', () => { assert.equal(distinct[2].toString(), resources[4].toString()); }); - test('dirname', (done) => { + test('dirname', () => { const f = URI.file('/some/file/test.txt'); const d = dirname(f); assert.equal(d.fsPath, normalize('/some/file', true)); // does not explode (https://github.com/Microsoft/vscode/issues/41987) dirname(URI.from({ scheme: 'file', authority: '/users/someone/portal.h' })); - done(); }); }); \ No newline at end of file diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index 4821ac96fd..6b3d088862 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import strings = require('vs/base/common/strings'); +import * as strings from 'vs/base/common/strings'; suite('Strings', () => { test('equalsIgnoreCase', function () { @@ -21,29 +21,29 @@ suite('Strings', () => { }); test('beginsWithIgnoreCase', function () { - assert(strings.beginsWithIgnoreCase('', '')); - assert(!strings.beginsWithIgnoreCase('', '1')); - assert(strings.beginsWithIgnoreCase('1', '')); + assert(strings.startsWithIgnoreCase('', '')); + assert(!strings.startsWithIgnoreCase('', '1')); + assert(strings.startsWithIgnoreCase('1', '')); - assert(strings.beginsWithIgnoreCase('a', 'a')); - assert(strings.beginsWithIgnoreCase('abc', 'Abc')); - assert(strings.beginsWithIgnoreCase('abc', 'ABC')); - assert(strings.beginsWithIgnoreCase('Höhenmeter', 'HÖhenmeter')); - assert(strings.beginsWithIgnoreCase('ÖL', 'Öl')); + assert(strings.startsWithIgnoreCase('a', 'a')); + assert(strings.startsWithIgnoreCase('abc', 'Abc')); + assert(strings.startsWithIgnoreCase('abc', 'ABC')); + assert(strings.startsWithIgnoreCase('Höhenmeter', 'HÖhenmeter')); + assert(strings.startsWithIgnoreCase('ÖL', 'Öl')); - assert(strings.beginsWithIgnoreCase('alles klar', 'a')); - assert(strings.beginsWithIgnoreCase('alles klar', 'A')); - assert(strings.beginsWithIgnoreCase('alles klar', 'alles k')); - assert(strings.beginsWithIgnoreCase('alles klar', 'alles K')); - assert(strings.beginsWithIgnoreCase('alles klar', 'ALLES K')); - assert(strings.beginsWithIgnoreCase('alles klar', 'alles klar')); - assert(strings.beginsWithIgnoreCase('alles klar', 'ALLES KLAR')); + assert(strings.startsWithIgnoreCase('alles klar', 'a')); + assert(strings.startsWithIgnoreCase('alles klar', 'A')); + assert(strings.startsWithIgnoreCase('alles klar', 'alles k')); + assert(strings.startsWithIgnoreCase('alles klar', 'alles K')); + assert(strings.startsWithIgnoreCase('alles klar', 'ALLES K')); + assert(strings.startsWithIgnoreCase('alles klar', 'alles klar')); + assert(strings.startsWithIgnoreCase('alles klar', 'ALLES KLAR')); - assert(!strings.beginsWithIgnoreCase('alles klar', ' ALLES K')); - assert(!strings.beginsWithIgnoreCase('alles klar', 'ALLES K ')); - assert(!strings.beginsWithIgnoreCase('alles klar', 'öALLES K ')); - assert(!strings.beginsWithIgnoreCase('alles klar', ' ')); - assert(!strings.beginsWithIgnoreCase('alles klar', 'ö')); + assert(!strings.startsWithIgnoreCase('alles klar', ' ALLES K')); + assert(!strings.startsWithIgnoreCase('alles klar', 'ALLES K ')); + assert(!strings.startsWithIgnoreCase('alles klar', 'öALLES K ')); + assert(!strings.startsWithIgnoreCase('alles klar', ' ')); + assert(!strings.startsWithIgnoreCase('alles klar', 'ö')); }); test('compareIgnoreCase', function () { diff --git a/src/vs/base/test/common/types.test.ts b/src/vs/base/test/common/types.test.ts index d4d1a1dd30..3f99640c55 100644 --- a/src/vs/base/test/common/types.test.ts +++ b/src/vs/base/test/common/types.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; suite('Types', () => { test('isFunction', () => { diff --git a/src/vs/base/test/common/utils.ts b/src/vs/base/test/common/utils.ts index 4f5fa43f2c..fc1661ae9c 100644 --- a/src/vs/base/test/common/utils.ts +++ b/src/vs/base/test/common/utils.ts @@ -5,7 +5,6 @@ 'use strict'; -import * as assert from 'assert'; import { TPromise, PPromise, TValueCallback, TProgressCallback, ProgressCallback } from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import * as paths from 'vs/base/common/paths'; @@ -80,11 +79,6 @@ export class DeferredPPromise<C, P> extends PPromise<C, P> { } } -export function onError(error: Error, done: () => void): void { - assert.fail(error); - done(); -} - export function toResource(this: any, path: string) { return URI.file(paths.join('C:\\', Buffer.from(this.test.fullTitle()).toString('base64'), path)); } diff --git a/src/vs/base/test/common/uuid.test.ts b/src/vs/base/test/common/uuid.test.ts index 430aff3ff2..fe99c11c89 100644 --- a/src/vs/base/test/common/uuid.test.ts +++ b/src/vs/base/test/common/uuid.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import uuid = require('vs/base/common/uuid'); +import * as uuid from 'vs/base/common/uuid'; suite('UUID', () => { test('generation', () => { diff --git a/src/vs/base/test/node/config.test.ts b/src/vs/base/test/node/config.test.ts index f9f812fdc3..ab68c6ab27 100644 --- a/src/vs/base/test/node/config.test.ts +++ b/src/vs/base/test/node/config.test.ts @@ -5,30 +5,17 @@ 'use strict'; -import assert = require('assert'); -import os = require('os'); +import * as assert from 'assert'; +import * as os from 'os'; -import path = require('path'); -import fs = require('fs'); -import extfs = require('vs/base/node/extfs'); -import uuid = require('vs/base/common/uuid'); +import * as path from 'path'; +import * as fs from 'fs'; +import * as uuid from 'vs/base/common/uuid'; import { ConfigWatcher } from 'vs/base/node/config'; -import { onError } from 'vs/base/test/common/utils'; -import { mkdirp } from 'vs/base/node/pfs'; +import { testFile } from 'vs/base/test/node/utils'; suite('Config', () => { - function testFile(callback: (error: Error, path: string, cleanUp: (callback: () => void) => void) => void): void { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'config', id); - const testFile = path.join(newDir, 'config.json'); - - const onMkdirp = error => callback(error, testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback)); - - mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); - } - test('defaults', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); @@ -52,15 +39,11 @@ suite('Config', () => { watcher.dispose(); }); - test('getConfig / getValue', function (done: () => void) { - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } + test('getConfig / getValue', function () { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "bar" }'); - fs.writeFileSync(testFile, '// my comment\n{ "foo": "bar" }'); - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile); + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile); let config = watcher.getConfig(); assert.ok(config); @@ -72,19 +55,15 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); - test('getConfig / getValue - broken JSON', function (done: () => void) { - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } + test('getConfig / getValue - broken JSON', function () { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '// my comment\n "foo": "bar ... '); - fs.writeFileSync(testFile, '// my comment\n "foo": "bar ... '); - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile); + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile); let config = watcher.getConfig(); assert.ok(config); @@ -94,24 +73,20 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); - test('watching', function (done: () => void) { + test('watching', function (done) { this.timeout(10000); // watching is timing intense - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } + testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "bar" }'); - fs.writeFileSync(testFile, '// my comment\n{ "foo": "bar" }'); - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile); + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile); watcher.getConfig(); // ensure we are in sync - fs.writeFileSync(testFile, '// my comment\n{ "foo": "changed" }'); + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "changed" }'); watcher.onDidUpdateConfiguration(event => { assert.ok(event); @@ -120,24 +95,19 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + res.cleanUp().then(done, done); }); - - }); + }, done); }); - test('watching also works when file created later', function (done: () => void) { + test('watching also works when file created later', function (done) { this.timeout(10000); // watching is timing intense - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile); + testFile('config', 'config.json').then(res => { + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile); watcher.getConfig(); // ensure we are in sync - fs.writeFileSync(testFile, '// my comment\n{ "foo": "changed" }'); + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "changed" }'); watcher.onDidUpdateConfiguration(event => { assert.ok(event); @@ -146,23 +116,18 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + res.cleanUp().then(done, done); }); - - }); + }, done); }); - test('watching detects the config file getting deleted', function (done: () => void) { + test('watching detects the config file getting deleted', function (done) { this.timeout(10000); // watching is timing intense - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } + testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "bar" }'); - fs.writeFileSync(testFile, '// my comment\n{ "foo": "bar" }'); - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile); + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile); watcher.getConfig(); // ensure we are in sync watcher.onDidUpdateConfiguration(event => { @@ -170,25 +135,21 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + res.cleanUp().then(done, done); }); - fs.unlinkSync(testFile); - }); + fs.unlinkSync(res.testFile); + }, done); }); - test('reload', function (done: () => void) { - testFile((error, testFile, cleanUp) => { - if (error) { - return onError(error, done); - } + test('reload', function (done) { + testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "bar" }'); - fs.writeFileSync(testFile, '// my comment\n{ "foo": "bar" }'); - - let watcher = new ConfigWatcher<{ foo: string; }>(testFile, { changeBufferDelay: 100, onError: console.error }); + let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile, { changeBufferDelay: 100, onError: console.error }); watcher.getConfig(); // ensure we are in sync - fs.writeFileSync(testFile, '// my comment\n{ "foo": "changed" }'); + fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "changed" }'); // still old values because change is not bubbling yet assert.equal(watcher.getConfig().foo, 'bar'); @@ -202,8 +163,8 @@ suite('Config', () => { watcher.dispose(); - cleanUp(done); + res.cleanUp().then(done, done); }); - }); + }, done); }); }); \ No newline at end of file diff --git a/src/vs/base/test/node/decoder.test.ts b/src/vs/base/test/node/decoder.test.ts index 92364c7c47..11e52ab99f 100644 --- a/src/vs/base/test/node/decoder.test.ts +++ b/src/vs/base/test/node/decoder.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import decoder = require('vs/base/node/decoder'); +import * as decoder from 'vs/base/node/decoder'; suite('Decoder', () => { diff --git a/src/vs/base/test/node/encoding/encoding.test.ts b/src/vs/base/test/node/encoding/encoding.test.ts index 5c4cbe4352..7901154e0e 100644 --- a/src/vs/base/test/node/encoding/encoding.test.ts +++ b/src/vs/base/test/node/encoding/encoding.test.ts @@ -5,71 +5,261 @@ 'use strict'; -import assert = require('assert'); - -import encoding = require('vs/base/node/encoding'); -import { encodingExists } from 'vs/base/node/encoding'; +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as encoding from 'vs/base/node/encoding'; +import { readExactlyByFile } from 'vs/base/node/stream'; +import { Readable } from 'stream'; suite('Encoding', () => { - test('detectBOM UTF-8', (done: (err?: any) => void) => { + test('detectBOM UTF-8', () => { const file = require.toUrl('./fixtures/some_utf8.css'); - encoding.detectEncodingByBOM(file).then((encoding: string) => { + return encoding.detectEncodingByBOM(file).then((encoding: string) => { assert.equal(encoding, 'utf8'); - done(); - }, done); + }); }); - test('detectBOM UTF-16 LE', (done: (err?: any) => void) => { + test('detectBOM UTF-16 LE', () => { const file = require.toUrl('./fixtures/some_utf16le.css'); - encoding.detectEncodingByBOM(file).then((encoding: string) => { + return encoding.detectEncodingByBOM(file).then((encoding: string) => { assert.equal(encoding, 'utf16le'); - done(); - }, done); + }); }); - test('detectBOM UTF-16 BE', (done: (err?: any) => void) => { + test('detectBOM UTF-16 BE', () => { const file = require.toUrl('./fixtures/some_utf16be.css'); - encoding.detectEncodingByBOM(file).then((encoding: string) => { + return encoding.detectEncodingByBOM(file).then((encoding: string) => { assert.equal(encoding, 'utf16be'); - done(); - }, done); + }); }); - test('detectBOM ANSI', function (done: (err?: any) => void) { + test('detectBOM ANSI', function () { const file = require.toUrl('./fixtures/some_ansi.css'); - encoding.detectEncodingByBOM(file).then((encoding: string) => { + return encoding.detectEncodingByBOM(file).then((encoding: string) => { assert.equal(encoding, null); - done(); - }, done); + }); }); - test('detectBOM ANSI', function (done: (err?: any) => void) { + test('detectBOM ANSI', function () { const file = require.toUrl('./fixtures/empty.txt'); - encoding.detectEncodingByBOM(file).then((encoding: string) => { + return encoding.detectEncodingByBOM(file).then((encoding: string) => { assert.equal(encoding, null); - done(); - }, done); + }); }); - test('resolve terminal encoding (detect)', function (done: (err?: any) => void) { - encoding.resolveTerminalEncoding().then(encoding => { - assert.ok(encodingExists(encoding)); - done(); - }, done); + test('resolve terminal encoding (detect)', function () { + return encoding.resolveTerminalEncoding().then(enc => { + assert.ok(encoding.encodingExists(enc)); + }); }); - test('resolve terminal encoding (environment)', function (done: (err?: any) => void) { + test('resolve terminal encoding (environment)', function () { process.env['VSCODE_CLI_ENCODING'] = 'utf16le'; - encoding.resolveTerminalEncoding().then(encoding => { - assert.ok(encodingExists(encoding)); - assert.equal(encoding, 'utf16le'); - done(); - }, done); + return encoding.resolveTerminalEncoding().then(enc => { + assert.ok(encoding.encodingExists(enc)); + assert.equal(enc, 'utf16le'); + }); + }); + + test('detectEncodingFromBuffer (JSON saved as PNG)', function () { + const file = require.toUrl('./fixtures/some.json.png'); + + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, false); + }); + }); + + test('detectEncodingFromBuffer (PNG saved as TXT)', function () { + const file = require.toUrl('./fixtures/some.png.txt'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, true); + }); + }); + + test('detectEncodingFromBuffer (XML saved as PNG)', function () { + const file = require.toUrl('./fixtures/some.xml.png'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, false); + }); + }); + + test('detectEncodingFromBuffer (QWOFF saved as TXT)', function () { + const file = require.toUrl('./fixtures/some.qwoff.txt'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, true); + }); + }); + + test('detectEncodingFromBuffer (CSS saved as QWOFF)', function () { + const file = require.toUrl('./fixtures/some.css.qwoff'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, false); + }); + }); + + test('detectEncodingFromBuffer (PDF)', function () { + const file = require.toUrl('./fixtures/some.pdf'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.seemsBinary, true); + }); + }); + + test('detectEncodingFromBuffer (guess UTF-16 LE from content without BOM)', function () { + const file = require.toUrl('./fixtures/utf16_le_nobom.txt'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.encoding, encoding.UTF16le); + assert.equal(mimes.seemsBinary, false); + }); + }); + + test('detectEncodingFromBuffer (guess UTF-16 BE from content without BOM)', function () { + const file = require.toUrl('./fixtures/utf16_be_nobom.txt'); + return readExactlyByFile(file, 512).then(buffer => { + const mimes = encoding.detectEncodingFromBuffer(buffer); + assert.equal(mimes.encoding, encoding.UTF16be); + assert.equal(mimes.seemsBinary, false); + }); + }); + + test('autoGuessEncoding (ShiftJIS)', function () { + const file = require.toUrl('./fixtures/some.shiftjis.txt'); + return readExactlyByFile(file, 512 * 8).then(buffer => { + return encoding.detectEncodingFromBuffer(buffer, true).then(mimes => { + assert.equal(mimes.encoding, 'shiftjis'); + }); + }); + }); + + test('autoGuessEncoding (CP1252)', function () { + const file = require.toUrl('./fixtures/some.cp1252.txt'); + return readExactlyByFile(file, 512 * 8).then(buffer => { + return encoding.detectEncodingFromBuffer(buffer, true).then(mimes => { + assert.equal(mimes.encoding, 'windows1252'); + }); + }); + }); + + async function readAndDecodeFromDisk(path, _encoding) { + return new Promise<string>((resolve, reject) => { + fs.readFile(path, (err, data) => { + if (err) { + reject(err); + } else { + resolve(encoding.decode(data, _encoding)); + } + }); + }); + } + + async function readAllAsString(stream: NodeJS.ReadableStream) { + return new Promise<string>((resolve, reject) => { + let all = ''; + stream.on('data', chunk => { + all += chunk; + assert.equal(typeof chunk, 'string'); + }); + stream.on('end', () => { + resolve(all); + }); + stream.on('error', reject); + }); + } + + test('toDecodeStream - some stream', async function () { + + let source = new Readable({ + read(size) { + this.push(Buffer.from([65, 66, 67])); + this.push(Buffer.from([65, 66, 67])); + this.push(Buffer.from([65, 66, 67])); + this.push(null); + } + }); + + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 4 }); + + assert.ok(detected); + assert.ok(stream); + + const content = await readAllAsString(stream); + assert.equal(content, 'ABCABCABC'); + }); + + test('toDecodeStream - some stream, expect too much data', async function () { + + let source = new Readable({ + read(size) { + this.push(Buffer.from([65, 66, 67])); + this.push(Buffer.from([65, 66, 67])); + this.push(Buffer.from([65, 66, 67])); + this.push(null); + } + }); + + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64 }); + + assert.ok(detected); + assert.ok(stream); + + const content = await readAllAsString(stream); + assert.equal(content, 'ABCABCABC'); + }); + + test('toDecodeStream - some stream, no data', async function () { + + let source = new Readable({ + read(size) { + this.push(null); // empty + } + }); + + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 512 }); + + assert.ok(detected); + assert.ok(stream); + + const content = await readAllAsString(stream); + assert.equal(content, ''); + }); + + + test('toDecodeStream - encoding, utf16be', async function () { + + let path = require.toUrl('./fixtures/some_utf16be.css'); + let source = fs.createReadStream(path); + + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64 }); + + assert.equal(detected.encoding, 'utf16be'); + assert.equal(detected.seemsBinary, false); + + let expected = await readAndDecodeFromDisk(path, detected.encoding); + let actual = await readAllAsString(stream); + assert.equal(actual, expected); + }); + + + test('toDecodeStream - empty file', async function () { + + let path = require.toUrl('./fixtures/empty.txt'); + let source = fs.createReadStream(path); + let { detected, stream } = await encoding.toDecodeStream(source, {}); + + let expected = await readAndDecodeFromDisk(path, detected.encoding); + let actual = await readAllAsString(stream); + assert.equal(actual, expected); }); }); diff --git a/src/vs/base/test/node/mime/fixtures/some.cp1252.txt b/src/vs/base/test/node/encoding/fixtures/some.cp1252.txt similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.cp1252.txt rename to src/vs/base/test/node/encoding/fixtures/some.cp1252.txt diff --git a/src/vs/base/test/node/mime/fixtures/some.css.qwoff b/src/vs/base/test/node/encoding/fixtures/some.css.qwoff similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.css.qwoff rename to src/vs/base/test/node/encoding/fixtures/some.css.qwoff diff --git a/src/vs/base/test/node/mime/fixtures/some.json.png b/src/vs/base/test/node/encoding/fixtures/some.json.png similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.json.png rename to src/vs/base/test/node/encoding/fixtures/some.json.png diff --git a/src/vs/base/test/node/mime/fixtures/some.pdf b/src/vs/base/test/node/encoding/fixtures/some.pdf similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.pdf rename to src/vs/base/test/node/encoding/fixtures/some.pdf diff --git a/src/vs/base/test/node/mime/fixtures/some.png.txt b/src/vs/base/test/node/encoding/fixtures/some.png.txt similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.png.txt rename to src/vs/base/test/node/encoding/fixtures/some.png.txt diff --git a/src/vs/base/test/node/mime/fixtures/some.qwoff.txt b/src/vs/base/test/node/encoding/fixtures/some.qwoff.txt similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.qwoff.txt rename to src/vs/base/test/node/encoding/fixtures/some.qwoff.txt diff --git a/src/vs/base/test/node/mime/fixtures/some.shiftjis.txt b/src/vs/base/test/node/encoding/fixtures/some.shiftjis.txt similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.shiftjis.txt rename to src/vs/base/test/node/encoding/fixtures/some.shiftjis.txt diff --git a/src/vs/base/test/node/mime/fixtures/some.xml.png b/src/vs/base/test/node/encoding/fixtures/some.xml.png similarity index 100% rename from src/vs/base/test/node/mime/fixtures/some.xml.png rename to src/vs/base/test/node/encoding/fixtures/some.xml.png diff --git a/src/vs/base/test/node/encoding/fixtures/utf16_be_nobom.txt b/src/vs/base/test/node/encoding/fixtures/utf16_be_nobom.txt new file mode 100644 index 0000000000000000000000000000000000000000..63c29412093e3bd4d6b467adbf3ddc1b4608320f GIT binary patch literal 60 zcmZQ5VaQ;}WGH4(fRd#QB@Af{x(tR4W<aqdhEyO~4wM6_%Vz+|f<(VD<T7vp06L%w A!T<mO literal 0 HcmV?d00001 diff --git a/src/vs/base/test/node/encoding/fixtures/utf16_le_nobom.txt b/src/vs/base/test/node/encoding/fixtures/utf16_le_nobom.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b94ff215b0c096f2a32e4226a991988a6da111e GIT binary patch literal 60 zcmXS6$Y981C}vQAlBEnK3~3Cy42BG5K(QQ#R3KRnlq&(M%Vz+|DljB5d}GLE;9>v( DMvV&0 literal 0 HcmV?d00001 diff --git a/src/vs/base/test/node/extfs/extfs.test.ts b/src/vs/base/test/node/extfs/extfs.test.ts index ead8ff9cce..fb69500256 100644 --- a/src/vs/base/test/node/extfs/extfs.test.ts +++ b/src/vs/base/test/node/extfs/extfs.test.ts @@ -5,16 +5,15 @@ 'use strict'; -import assert = require('assert'); -import os = require('os'); +import * as assert from 'assert'; +import * as os from 'os'; -import path = require('path'); -import fs = require('fs'); +import * as path from 'path'; +import * as fs from 'fs'; -import uuid = require('vs/base/common/uuid'); -import strings = require('vs/base/common/strings'); -import extfs = require('vs/base/node/extfs'); -import { onError } from 'vs/base/test/common/utils'; +import * as uuid from 'vs/base/common/uuid'; +import * as strings from 'vs/base/common/strings'; +import * as extfs from 'vs/base/node/extfs'; import { Readable } from 'stream'; import { isLinux, isWindows } from 'vs/base/common/platform'; @@ -58,14 +57,14 @@ function toReadable(value: string, throwError?: boolean): Readable { suite('Extfs', () => { - test('mkdirp', function (done: () => void) { + test('mkdirp', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -74,7 +73,7 @@ suite('Extfs', () => { }); // 493 = 0755 }); - test('stat link', function (done: () => void) { + test('stat link', function (done) { if (isWindows) { // Symlinks are not the same on win, and we can not create them programitically without admin privileges return done(); @@ -89,21 +88,21 @@ suite('Extfs', () => { mkdirp(directory, 493, error => { if (error) { - return onError(error, done); + return done(error); } fs.symlinkSync(directory, symbolicLink); extfs.statLink(directory, (error, statAndIsLink) => { if (error) { - return onError(error, done); + return done(error); } assert.ok(!statAndIsLink.isSymbolicLink); extfs.statLink(symbolicLink, (error, statAndIsLink) => { if (error) { - return onError(error, done); + return done(error); } assert.ok(statAndIsLink.isSymbolicLink); @@ -124,14 +123,14 @@ suite('Extfs', () => { assert.ok(!fs.existsSync(newDir)); }); - test('delSync - simple', function (done: () => void) { + test('delSync - simple', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); @@ -144,14 +143,14 @@ suite('Extfs', () => { }); // 493 = 0755 }); - test('delSync - recursive folder structure', function (done: () => void) { + test('delSync - recursive folder structure', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); @@ -167,7 +166,7 @@ suite('Extfs', () => { }); // 493 = 0755 }); - test('copy, move and delete', function (done: () => void) { + test('copy, move and delete', function (done) { const id = uuid.generateUuid(); const id2 = uuid.generateUuid(); const sourceDir = require.toUrl('./fixtures'); @@ -177,7 +176,7 @@ suite('Extfs', () => { extfs.copy(sourceDir, targetDir, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(targetDir)); @@ -189,7 +188,7 @@ suite('Extfs', () => { extfs.mv(targetDir, targetDir2, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(!fs.existsSync(targetDir)); @@ -202,7 +201,7 @@ suite('Extfs', () => { extfs.mv(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'), error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html'))); @@ -210,11 +209,11 @@ suite('Extfs', () => { extfs.del(parentDir, os.tmpdir(), error => { if (error) { - return onError(error, done); + return done(error); } }, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(!fs.existsSync(parentDir)); done(); @@ -224,7 +223,7 @@ suite('Extfs', () => { }); }); - test('readdir', function (done: () => void) { + test('readdir', function (done) { if (strings.canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); @@ -232,7 +231,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -248,7 +247,7 @@ suite('Extfs', () => { } }); - test('writeFileAndFlush (string)', function (done: () => void) { + test('writeFileAndFlush (string)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -256,14 +255,14 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); extfs.writeFileAndFlush(testFile, 'Hello World', null, error => { if (error) { - return onError(error, done); + return done(error); } assert.equal(fs.readFileSync(testFile), 'Hello World'); @@ -272,7 +271,7 @@ suite('Extfs', () => { extfs.writeFileAndFlush(testFile, largeString, null, error => { if (error) { - return onError(error, done); + return done(error); } assert.equal(fs.readFileSync(testFile), largeString); @@ -283,7 +282,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (stream)', function (done: () => void) { + test('writeFileAndFlush (stream)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -291,14 +290,14 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => { if (error) { - return onError(error, done); + return done(error); } assert.equal(fs.readFileSync(testFile), 'Hello World'); @@ -307,7 +306,7 @@ suite('Extfs', () => { extfs.writeFileAndFlush(testFile, toReadable(largeString), null, error => { if (error) { - return onError(error, done); + return done(error); } assert.equal(fs.readFileSync(testFile), largeString); @@ -318,7 +317,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (file stream)', function (done: () => void) { + test('writeFileAndFlush (file stream)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const sourceFile = require.toUrl('./fixtures/index.html'); @@ -327,14 +326,14 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => { if (error) { - return onError(error, done); + return done(error); } assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString()); @@ -344,7 +343,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (string, error handling)', function (done: () => void) { + test('writeFileAndFlush (string, error handling)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -352,7 +351,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -361,7 +360,7 @@ suite('Extfs', () => { extfs.writeFileAndFlush(testFile, 'Hello World', null, error => { if (!error) { - return onError(new Error('Expected error for writing to readonly file'), done); + return done(new Error('Expected error for writing to readonly file')); } extfs.del(parentDir, os.tmpdir(), done, ignore); @@ -369,7 +368,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (stream, error handling EISDIR)', function (done: () => void) { + test('writeFileAndFlush (stream, error handling EISDIR)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -377,7 +376,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -387,7 +386,7 @@ suite('Extfs', () => { const readable = toReadable('Hello World'); extfs.writeFileAndFlush(testFile, readable, null, error => { if (!error || (<any>error).code !== 'EISDIR') { - return onError(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')), done); + return done(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (<any>error).code : 'no error'))); } // verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542) @@ -398,7 +397,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (stream, error handling READERROR)', function (done: () => void) { + test('writeFileAndFlush (stream, error handling READERROR)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -406,14 +405,14 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null, error => { if (!error || error.message !== readError) { - return onError(new Error('Expected error for writing to folder'), done); + return done(new Error('Expected error for writing to folder')); } extfs.del(parentDir, os.tmpdir(), done, ignore); @@ -421,7 +420,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (stream, error handling EACCES)', function (done: () => void) { + test('writeFileAndFlush (stream, error handling EACCES)', function (done) { if (isLinux) { return done(); // somehow this test fails on Linux in our TFS builds } @@ -433,7 +432,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -443,7 +442,7 @@ suite('Extfs', () => { extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => { if (!error || !((<any>error).code !== 'EACCES' || (<any>error).code !== 'EPERM')) { - return onError(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')), done); + return done(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (<any>error).code : 'no error'))); } extfs.del(parentDir, os.tmpdir(), done, ignore); @@ -451,7 +450,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlush (file stream, error handling)', function (done: () => void) { + test('writeFileAndFlush (file stream, error handling)', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const sourceFile = require.toUrl('./fixtures/index.html'); @@ -460,7 +459,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); @@ -469,7 +468,7 @@ suite('Extfs', () => { extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => { if (!error) { - return onError(new Error('Expected error for writing to folder'), done); + return done(new Error('Expected error for writing to folder')); } extfs.del(parentDir, os.tmpdir(), done, ignore); @@ -477,7 +476,7 @@ suite('Extfs', () => { }); }); - test('writeFileAndFlushSync', function (done: () => void) { + test('writeFileAndFlushSync', function (done) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -485,7 +484,7 @@ suite('Extfs', () => { mkdirp(newDir, 493, error => { if (error) { - return onError(error, done); + return done(error); } assert.ok(fs.existsSync(newDir)); diff --git a/src/vs/base/test/node/flow.test.ts b/src/vs/base/test/node/flow.test.ts index 3a680e16ed..cd0086d4b3 100644 --- a/src/vs/base/test/node/flow.test.ts +++ b/src/vs/base/test/node/flow.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import flow = require('vs/base/node/flow'); +import * as flow from 'vs/base/node/flow'; const loop = flow.loop; const sequence = flow.sequence; diff --git a/src/vs/base/test/node/glob.test.ts b/src/vs/base/test/node/glob.test.ts index 7a25f1f986..7384f6da76 100644 --- a/src/vs/base/test/node/glob.test.ts +++ b/src/vs/base/test/node/glob.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as path from 'path'; -import glob = require('vs/base/common/glob'); +import * as glob from 'vs/base/common/glob'; import { isWindows } from 'vs/base/common/platform'; suite('Glob', () => { diff --git a/src/vs/base/test/node/mime/mime.test.ts b/src/vs/base/test/node/mime/mime.test.ts deleted file mode 100644 index bd47f98b5b..0000000000 --- a/src/vs/base/test/node/mime/mime.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 assert = require('assert'); - -import mimeCommon = require('vs/base/common/mime'); -import mime = require('vs/base/node/mime'); -import { readExactlyByFile } from 'vs/base/node/stream'; - -suite('Mime', () => { - - test('detectMimesFromFile (JSON saved as PNG)', function (done: (err?: any) => void) { - const file = require.toUrl('./fixtures/some.json.png'); - - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['text/plain']); - done(); - }); - }); - - test('detectMimesFromFile (PNG saved as TXT)', function (done: (err?: any) => void) { - mimeCommon.registerTextMime({ id: 'text', mime: 'text/plain', extension: '.txt' }); - const file = require.toUrl('./fixtures/some.png.txt'); - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['application/octet-stream']); - done(); - }, done); - }); - - test('detectMimesFromFile (XML saved as PNG)', function (done: (err?: any) => void) { - const file = require.toUrl('./fixtures/some.xml.png'); - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['text/plain']); - done(); - }, done); - }); - - test('detectMimesFromFile (QWOFF saved as TXT)', function (done: (err?: any) => void) { - const file = require.toUrl('./fixtures/some.qwoff.txt'); - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['application/octet-stream']); - done(); - }, done); - }); - - test('detectMimesFromFile (CSS saved as QWOFF)', function (done: (err?: any) => void) { - const file = require.toUrl('./fixtures/some.css.qwoff'); - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['text/plain']); - done(); - }, done); - }); - - test('detectMimesFromFile (PDF)', function (done: () => void) { - const file = require.toUrl('./fixtures/some.pdf'); - readExactlyByFile(file, 512).then(buffer => { - const mimes = mime.detectMimeAndEncodingFromBuffer(buffer); - assert.deepEqual(mimes.mimes, ['application/octet-stream']); - done(); - }, done); - }); - - test('autoGuessEncoding (ShiftJIS)', function (done: () => void) { - const file = require.toUrl('./fixtures/some.shiftjis.txt'); - readExactlyByFile(file, 512 * 8).then(buffer => { - mime.detectMimeAndEncodingFromBuffer(buffer, true).then(mimes => { - assert.equal(mimes.encoding, 'shiftjis'); - done(); - }); - }, done); - }); - - test('autoGuessEncoding (CP1252)', function (done: () => void) { - const file = require.toUrl('./fixtures/some.cp1252.txt'); - readExactlyByFile(file, 512 * 8).then(buffer => { - mime.detectMimeAndEncodingFromBuffer(buffer, true).then(mimes => { - assert.equal(mimes.encoding, 'windows1252'); - done(); - }); - }, done); - }); -}); diff --git a/src/vs/base/test/node/pfs.test.ts b/src/vs/base/test/node/pfs.test.ts index 11f7eb13e9..e236738287 100644 --- a/src/vs/base/test/node/pfs.test.ts +++ b/src/vs/base/test/node/pfs.test.ts @@ -6,43 +6,36 @@ import { TPromise } from 'vs/base/common/winjs.base'; -import assert = require('assert'); -import os = require('os'); +import * as assert from 'assert'; +import * as os from 'os'; -import path = require('path'); -import fs = require('fs'); +import * as path from 'path'; +import * as fs from 'fs'; -import uuid = require('vs/base/common/uuid'); -import extfs = require('vs/base/node/extfs'); -import { onError } from 'vs/base/test/common/utils'; +import * as uuid from 'vs/base/common/uuid'; import * as pfs from 'vs/base/node/pfs'; +import { timeout } from 'vs/base/common/async'; suite('PFS', () => { - test('writeFile', function (done: () => void) { + test('writeFile', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'writefile.txt'); - const onMkdirp = error => { - if (error) { - return onError(error, done); - } - + return pfs.mkdirp(newDir, 493).then(() => { assert.ok(fs.existsSync(newDir)); - pfs.writeFile(testFile, 'Hello World', null).done(() => { + return pfs.writeFile(testFile, 'Hello World', null).then(() => { assert.equal(fs.readFileSync(testFile), 'Hello World'); - extfs.del(parentDir, os.tmpdir(), () => { }, done); - }, error => onError(error, done)); - }; - - pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); + return pfs.del(parentDir, os.tmpdir()); + }); + }); }); - test('writeFile - parallel write on different files works', function (done: () => void) { + test('writeFile - parallel write on different files works', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); @@ -52,106 +45,80 @@ suite('PFS', () => { const testFile4 = path.join(newDir, 'writefile4.txt'); const testFile5 = path.join(newDir, 'writefile5.txt'); - const onMkdirp = error => { - if (error) { - return onError(error, done); - } - + return pfs.mkdirp(newDir, 493).then(() => { assert.ok(fs.existsSync(newDir)); - TPromise.join([ + return TPromise.join([ pfs.writeFile(testFile1, 'Hello World 1', null), pfs.writeFile(testFile2, 'Hello World 2', null), pfs.writeFile(testFile3, 'Hello World 3', null), pfs.writeFile(testFile4, 'Hello World 4', null), pfs.writeFile(testFile5, 'Hello World 5', null) - ]).done(() => { + ]).then(() => { assert.equal(fs.readFileSync(testFile1), 'Hello World 1'); assert.equal(fs.readFileSync(testFile2), 'Hello World 2'); assert.equal(fs.readFileSync(testFile3), 'Hello World 3'); assert.equal(fs.readFileSync(testFile4), 'Hello World 4'); assert.equal(fs.readFileSync(testFile5), 'Hello World 5'); - extfs.del(parentDir, os.tmpdir(), () => { }, done); - }, error => onError(error, done)); - }; - - pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); + return pfs.del(parentDir, os.tmpdir()); + }); + }); }); - test('writeFile - parallel write on same files works and is sequentalized', function (done: () => void) { + test('writeFile - parallel write on same files works and is sequentalized', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'pfs', id); const testFile = path.join(newDir, 'writefile.txt'); - const onMkdirp = error => { - if (error) { - return onError(error, done); - } - + return pfs.mkdirp(newDir, 493).then(() => { assert.ok(fs.existsSync(newDir)); - TPromise.join([ + return TPromise.join([ pfs.writeFile(testFile, 'Hello World 1', null), pfs.writeFile(testFile, 'Hello World 2', null), - TPromise.timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', null)), + timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', null)), pfs.writeFile(testFile, 'Hello World 4', null), - TPromise.timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', null)) - ]).done(() => { + timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', null)) + ]).then(() => { assert.equal(fs.readFileSync(testFile), 'Hello World 5'); - extfs.del(parentDir, os.tmpdir(), () => { }, done); - }, error => onError(error, done)); - }; - - pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); + return pfs.del(parentDir, os.tmpdir()); + }); + }); }); - test('rimraf - simple', function (done: () => void) { + test('rimraf - simple', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); - const onMkdirp = error => { - if (error) { - return onError(error, done); - } - + return pfs.mkdirp(newDir, 493).then(() => { fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - pfs.rimraf(newDir).then(() => { + return pfs.rimraf(newDir).then(() => { assert.ok(!fs.existsSync(newDir)); - done(); - }, error => onError(error, done)); - }; - - pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); + }); + }); }); - test('rimraf - recursive folder structure', function (done: () => void) { + test('rimraf - recursive folder structure', function () { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); - const onMkdirp = error => { - if (error) { - return onError(error, done); - } - + return pfs.mkdirp(newDir, 493).then(() => { fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); fs.mkdirSync(path.join(newDir, 'somefolder')); fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - pfs.rimraf(newDir).then(() => { + return pfs.rimraf(newDir).then(() => { assert.ok(!fs.existsSync(newDir)); - done(); - }, error => onError(error, done)); - }; - - pfs.mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); + }); + }); }); }); \ No newline at end of file diff --git a/src/vs/base/test/node/port.test.ts b/src/vs/base/test/node/port.test.ts index 5fef96996f..f6312e6bf0 100644 --- a/src/vs/base/test/node/port.test.ts +++ b/src/vs/base/test/node/port.test.ts @@ -7,10 +7,10 @@ import * as assert from 'assert'; import * as net from 'net'; -import ports = require('vs/base/node/ports'); +import * as ports from 'vs/base/node/ports'; suite('Ports', () => { - test('Finds a free port (no timeout)', function (done: () => void) { + test('Finds a free port (no timeout)', function (done) { this.timeout(1000 * 10); // higher timeout for this test if (process.env['VSCODE_PID']) { @@ -31,8 +31,8 @@ suite('Ports', () => { server.close(); done(); - }); + }, err => done(err)); }); - }); + }, err => done(err)); }); }); diff --git a/src/vs/base/test/node/processes/fixtures/fork.ts b/src/vs/base/test/node/processes/fixtures/fork.ts index 63ad74fc1e..b3e51a0dc7 100644 --- a/src/vs/base/test/node/processes/fixtures/fork.ts +++ b/src/vs/base/test/node/processes/fixtures/fork.ts @@ -5,9 +5,9 @@ 'use strict'; -import processes = require('vs/base/node/processes'); +import * as processes from 'vs/base/node/processes'; -const sender = processes.createQueuedSender(process); +const sender = processes.createQueuedSender(<any>process); process.on('message', msg => { sender.send(msg); diff --git a/src/vs/base/test/node/processes/fixtures/fork_large.ts b/src/vs/base/test/node/processes/fixtures/fork_large.ts index 23692f0b90..0bc6ad4da5 100644 --- a/src/vs/base/test/node/processes/fixtures/fork_large.ts +++ b/src/vs/base/test/node/processes/fixtures/fork_large.ts @@ -5,9 +5,9 @@ 'use strict'; -import processes = require('vs/base/node/processes'); +import * as processes from 'vs/base/node/processes'; -const sender = processes.createQueuedSender(process); +const sender = processes.createQueuedSender(<any>process); process.on('message', msg => { sender.send(msg); diff --git a/src/vs/base/test/node/processes/processes.test.ts b/src/vs/base/test/node/processes/processes.test.ts index 62df184acb..a75d19a9a4 100644 --- a/src/vs/base/test/node/processes/processes.test.ts +++ b/src/vs/base/test/node/processes/processes.test.ts @@ -10,7 +10,7 @@ import * as cp from 'child_process'; import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; -import processes = require('vs/base/node/processes'); +import * as processes from 'vs/base/node/processes'; function fork(id: string): cp.ChildProcess { const opts: any = { diff --git a/src/vs/base/test/node/stream/stream.test.ts b/src/vs/base/test/node/stream/stream.test.ts index 690de8ebc8..d89d00d674 100644 --- a/src/vs/base/test/node/stream/stream.test.ts +++ b/src/vs/base/test/node/stream/stream.test.ts @@ -5,47 +5,42 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; -import stream = require('vs/base/node/stream'); +import * as stream from 'vs/base/node/stream'; suite('Stream', () => { - test('readExactlyByFile - ANSI', function (done: (err?) => void) { + test('readExactlyByFile - ANSI', function () { const file = require.toUrl('./fixtures/file.css'); - stream.readExactlyByFile(file, 10).then(({ buffer, bytesRead }) => { + return stream.readExactlyByFile(file, 10).then(({ buffer, bytesRead }) => { assert.equal(bytesRead, 10); assert.equal(buffer.toString(), '/*--------'); - done(); - }, done); + }); }); - test('readExactlyByFile - empty', function (done: (err?: any) => void) { + test('readExactlyByFile - empty', function () { const file = require.toUrl('./fixtures/empty.txt'); - stream.readExactlyByFile(file, 10).then(({ bytesRead }) => { + return stream.readExactlyByFile(file, 10).then(({ bytesRead }) => { assert.equal(bytesRead, 0); - done(); - }, done); + }); }); - test('readToMatchingString - ANSI', function (done: (err?: any) => void) { + test('readToMatchingString - ANSI', function () { const file = require.toUrl('./fixtures/file.css'); - stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { + return stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { // \r may be present on Windows assert.equal(result.replace('\r', ''), '/*---------------------------------------------------------------------------------------------'); - done(); - }, done); + }); }); - test('readToMatchingString - empty', function (done: (err?: any) => void) { + test('readToMatchingString - empty', function () { const file = require.toUrl('./fixtures/empty.txt'); - stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { + return stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { assert.equal(result, null); - - done(); - }, done); + }); }); }); \ No newline at end of file diff --git a/src/vs/base/test/node/utils.ts b/src/vs/base/test/node/utils.ts new file mode 100644 index 0000000000..525dcfe40b --- /dev/null +++ b/src/vs/base/test/node/utils.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { generateUuid } from 'vs/base/common/uuid'; +import { join } from 'path'; +import { tmpdir } from 'os'; +import { mkdirp, del } from 'vs/base/node/pfs'; + +export interface ITestFileResult { + testFile: string; + cleanUp: () => TPromise<void>; +} + +export function testFile(folder: string, file: string): TPromise<ITestFileResult> { + const id = generateUuid(); + const parentDir = join(tmpdir(), 'vsctests', id); + const newDir = join(parentDir, 'config', id); + const testFile = join(newDir, 'config.json'); + + return mkdirp(newDir, 493).then(() => { + return { + testFile, + cleanUp: () => del(parentDir, tmpdir()) + } as ITestFileResult; + }); +} \ No newline at end of file diff --git a/src/vs/base/test/node/zip/zip.test.ts b/src/vs/base/test/node/zip/zip.test.ts index f6e7df6220..b6c9b8acbe 100644 --- a/src/vs/base/test/node/zip/zip.test.ts +++ b/src/vs/base/test/node/zip/zip.test.ts @@ -12,6 +12,7 @@ import URI from 'vs/base/common/uri'; import { extract } from 'vs/base/node/zip'; import { generateUuid } from 'vs/base/common/uuid'; import { rimraf, exists } from 'vs/base/node/pfs'; +import { NullLogService } from '../../../../platform/log/common/log'; const fixtures = URI.parse(require.toUrl('./fixtures')).fsPath; @@ -21,7 +22,7 @@ suite('Zip', () => { const fixture = path.join(fixtures, 'extract.zip'); const target = path.join(os.tmpdir(), generateUuid()); - return extract(fixture, target) + return extract(fixture, target, {}, new NullLogService()) .then(() => exists(path.join(target, 'extension'))) .then(exists => assert(exists)) .then(() => rimraf(target)); diff --git a/src/vs/base/worker/defaultWorkerFactory.ts b/src/vs/base/worker/defaultWorkerFactory.ts index 56f6479922..ecd11383a4 100644 --- a/src/vs/base/worker/defaultWorkerFactory.ts +++ b/src/vs/base/worker/defaultWorkerFactory.ts @@ -7,22 +7,24 @@ import { globals } from 'vs/base/common/platform'; import { logOnceWebWorkerWarning, IWorker, IWorkerCallback, IWorkerFactory } from 'vs/base/common/worker/simpleWorker'; -// Option for hosts to overwrite the worker script url (used in the standalone editor) -const getCrossOriginWorkerScriptUrl: (workerId: string, label: string) => string = environment('getWorkerUrl', null); - -function environment(name: string, fallback: any = false): any { - if (globals.MonacoEnvironment && globals.MonacoEnvironment.hasOwnProperty(name)) { - return globals.MonacoEnvironment[name]; +function getWorker(workerId: string, label: string): Worker { + // Option for hosts to overwrite the worker script (used in the standalone editor) + if (globals.MonacoEnvironment) { + if (typeof globals.MonacoEnvironment.getWorker === 'function') { + return globals.MonacoEnvironment.getWorker(workerId, label); + } + if (typeof globals.MonacoEnvironment.getWorkerUrl === 'function') { + return new Worker(globals.MonacoEnvironment.getWorkerUrl(workerId, label)); + } } - - return fallback; + // ESM-comment-begin + if (typeof require === 'function') { + return new Worker(require.toUrl('./' + workerId) + '#' + label); + } + // ESM-comment-end + throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`); } -function defaultGetWorkerUrl(workerId: string, label: string): string { - return require.toUrl('./' + workerId) + '#' + label; -} -var getWorkerUrl = getCrossOriginWorkerScriptUrl || defaultGetWorkerUrl; - /** * A worker that uses HTML5 web workers so that is has * its own global scope and its own thread. @@ -34,7 +36,7 @@ class WebWorker implements IWorker { constructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) { this.id = id; - this.worker = new Worker(getWorkerUrl('workerMain.js', label)); + this.worker = getWorker('workerMain.js', label); this.postMessage(moduleId); this.worker.onmessage = function (ev: any) { onMessageCallback(ev.data); diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index 40bf37baa5..296e8e9f1a 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -5,23 +5,26 @@ 'use strict'; function createModuleDescription(name, exclude) { - var result= {}; + var result = {}; var excludes = ['vs/css', 'vs/nls']; - result.name= name; + result.name = name; if (Array.isArray(exclude) && exclude.length > 0) { excludes = excludes.concat(exclude); } - result.exclude= excludes; - + result.exclude = excludes; + return result; } -exports.collectModules= function() { +exports.collectModules = function () { return [ createModuleDescription('vs/code/electron-main/main', []), createModuleDescription('vs/code/node/cli', []), createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']), + createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []), createModuleDescription('vs/code/electron-browser/sharedProcess/sharedProcessMain', []), - createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []) + createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []), + createModuleDescription('vs/platform/driver/node/driver', []), + createModuleDescription('vs/code/electron-browser/processExplorer/processExplorerMain', []) ]; -}; \ No newline at end of file +}; diff --git a/src/vs/code/electron-browser/issue/issueReporter.js b/src/vs/code/electron-browser/issue/issueReporter.js index 812c656a45..d80ee545a2 100644 --- a/src/vs/code/electron-browser/issue/issueReporter.js +++ b/src/vs/code/electron-browser/issue/issueReporter.js @@ -9,6 +9,11 @@ const path = require('path'); const fs = require('fs'); const remote = require('electron').remote; +function assign(destination, source) { + return Object.keys(source) + .reduce(function (r, key) { r[key] = source[key]; return r; }, destination); +} + function parseURLQueryArgs() { const search = window.location.search || ''; @@ -19,15 +24,6 @@ function parseURLQueryArgs() { .reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {}); } -function createScript(src, onload) { - const script = document.createElement('script'); - script.src = src; - script.addEventListener('load', onload); - - const head = document.getElementsByTagName('head')[0]; - head.insertBefore(script, head.lastChild); -} - function uriFromPath(_path) { var pathName = path.resolve(_path).replace(/\\/g, '/'); if (pathName.length > 0 && pathName.charAt(0) !== '/') { @@ -53,6 +49,8 @@ function main() { const args = parseURLQueryArgs(); const configuration = JSON.parse(args['config'] || '{}') || {}; + assign(process.env, configuration.userEnv); + //#region Add support for using node_modules.asar (function () { const path = require('path'); @@ -65,10 +63,10 @@ function main() { const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); @@ -143,31 +141,34 @@ function main() { window.document.documentElement.setAttribute('lang', locale); - // In the bundled version the nls plugin is packaged with the loader so the NLS Plugins - // loads as soon as the loader loads. To be able to have pseudo translation - createScript(rootUrl + '/vs/loader.js', function () { - var define = global.define; - global.define = undefined; - define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code + // Load the loader + const loaderFilename = configuration.appRoot + '/out/vs/loader.js'; + const loaderSource = fs.readFileSync(loaderFilename); + require('vm').runInThisContext(loaderSource, { filename: loaderFilename }); + var define = global.define; + global.define = undefined; - window.MonacoEnvironment = {}; + window.nodeRequire = require.__$__nodeRequire; - require.config({ - baseUrl: rootUrl, - 'vs/nls': nlsConfig, - nodeCachedDataDir: configuration.nodeCachedDataDir, - nodeModules: [/*BUILD->INSERT_NODE_MODULES*/] + define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code + + window.MonacoEnvironment = {}; + + require.config({ + baseUrl: rootUrl, + 'vs/nls': nlsConfig, + nodeCachedDataDir: configuration.nodeCachedDataDir, + nodeModules: [/*BUILD->INSERT_NODE_MODULES*/] + }); + + if (nlsConfig.pseudo) { + require(['vs/nls'], function (nlsPlugin) { + nlsPlugin.setPseudoTranslation(nlsConfig.pseudo); }); + } - if (nlsConfig.pseudo) { - require(['vs/nls'], function (nlsPlugin) { - nlsPlugin.setPseudoTranslation(nlsConfig.pseudo); - }); - } - - require(['vs/code/electron-browser/issue/issueReporterMain'], (issueReporter) => { - issueReporter.startup(configuration); - }); + require(['vs/code/electron-browser/issue/issueReporterMain'], (issueReporter) => { + issueReporter.startup(configuration); }); } diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index d0d81f9895..d9507e471b 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -40,6 +40,7 @@ import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { ILogService, getLogLevel } from 'vs/platform/log/common/log'; import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; +import { normalizeGitHubIssuesUrl } from 'vs/code/electron-browser/issue/issueReporterUtil'; const MAX_URL_LENGTH = platform.isWindows ? 2081 : 5400; @@ -69,6 +70,7 @@ export class IssueReporter extends Disposable { private numberOfSearchResultsDisplayed = 0; private receivedSystemInfo = false; private receivedPerformanceInfo = false; + private shouldQueueSearch = false; constructor(configuration: IssueReporterConfiguration) { super(); @@ -105,7 +107,9 @@ export class IssueReporter extends Disposable { }); ipcRenderer.send('issueSystemInfoRequest'); - ipcRenderer.send('issuePerformanceInfoRequest'); + if (configuration.data.issueType === IssueType.PerformanceIssue) { + ipcRenderer.send('issuePerformanceInfoRequest'); + } this.logService.trace('issueReporter: Sent data requests'); if (window.document.documentElement.lang !== 'en') { @@ -160,7 +164,7 @@ export class IssueReporter extends Disposable { } if (styles.inputActiveBorder) { - content.push(`input[type='text']:focus, textarea:focus, select:focus, summary:focus, button:focus { border: 1px solid ${styles.inputActiveBorder}; outline-style: none; }`); + content.push(`input[type='text']:focus, textarea:focus, select:focus, summary:focus, button:focus, a:focus, .workbenchCommand:focus { border: 1px solid ${styles.inputActiveBorder}; outline-style: none; }`); } if (styles.textLinkColor) { @@ -208,14 +212,14 @@ export class IssueReporter extends Disposable { }); const numberOfThemeExtesions = themes && themes.length; - this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes }); + this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: extensions }); this.updateExtensionTable(nonThemes, numberOfThemeExtesions); if (this.environmentService.disableExtensions || extensions.length === 0) { (<HTMLButtonElement>document.getElementById('disableExtensions')).disabled = true; - (<HTMLInputElement>document.getElementById('reproducesWithoutExtensions')).checked = true; - this.issueReporterModel.update({ reprosWithoutExtensions: true }); } + + this.updateExtensionSelector(extensions); } private handleSettingsSearchData(data: ISettingsSearchIssueReporterData): void { @@ -292,7 +296,11 @@ export class IssueReporter extends Disposable { private setEventHandlers(): void { this.addEventListener('issue-type', 'change', (event: Event) => { - this.issueReporterModel.update({ issueType: parseInt((<HTMLInputElement>event.target).value) }); + const issueType = parseInt((<HTMLInputElement>event.target).value); + this.issueReporterModel.update({ issueType: issueType }); + if (issueType === IssueType.PerformanceIssue && !this.receivedPerformanceInfo) { + ipcRenderer.send('issuePerformanceInfoRequest'); + } this.updatePreviewButtonState(); this.render(); }); @@ -322,30 +330,33 @@ export class IssueReporter extends Disposable { }); } - this.addEventListener('reproducesWithoutExtensions', 'click', (e) => { - this.issueReporterModel.update({ reprosWithoutExtensions: true }); - }); + this.addEventListener('issue-source', 'change', (event: Event) => { + const fileOnExtension = JSON.parse((<HTMLInputElement>event.target).value); + this.issueReporterModel.update({ fileOnExtension: fileOnExtension, includeExtensions: !fileOnExtension }); + this.render(); - this.addEventListener('reproducesWithExtensions', 'click', (e) => { - this.issueReporterModel.update({ reprosWithoutExtensions: false }); + const title = (<HTMLInputElement>document.getElementById('issue-title')).value; + if (fileOnExtension) { + this.searchExtensionIssues(title); + } else { + const description = this.issueReporterModel.getData().issueDescription; + this.searchVSCodeIssues(title, description); + } }); this.addEventListener('description', 'input', (event: Event) => { const issueDescription = (<HTMLInputElement>event.target).value; this.issueReporterModel.update({ issueDescription }); - const title = (<HTMLInputElement>document.getElementById('issue-title')).value; - if (title || issueDescription) { - this.searchDuplicates(title, issueDescription); - } else { - this.clearSearchResults(); + // Only search for extension issues on title change + if (!this.issueReporterModel.fileOnExtension()) { + const title = (<HTMLInputElement>document.getElementById('issue-title')).value; + this.searchVSCodeIssues(title, issueDescription); } }); this.addEventListener('issue-title', 'input', (e) => { - const description = this.issueReporterModel.getData().issueDescription; const title = (<HTMLInputElement>event.target).value; - const lengthValidationMessage = document.getElementById('issue-title-length-validation-error'); if (title && this.getIssueUrlWithTitle(title).length > MAX_URL_LENGTH) { show(lengthValidationMessage); @@ -353,10 +364,11 @@ export class IssueReporter extends Disposable { hide(lengthValidationMessage); } - if (title || description) { - this.searchDuplicates(title, description); + if (this.issueReporterModel.fileOnExtension()) { + this.searchExtensionIssues(title); } else { - this.clearSearchResults(); + const description = this.issueReporterModel.getData().issueDescription; + this.searchVSCodeIssues(title, description); } }); @@ -367,43 +379,32 @@ export class IssueReporter extends Disposable { }); this.addEventListener('disableExtensions', 'keydown', (e: KeyboardEvent) => { + e.stopPropagation(); if (e.keyCode === 13 || e.keyCode === 32) { ipcRenderer.send('workbenchCommand', 'workbench.extensions.action.disableAll'); ipcRenderer.send('workbenchCommand', 'workbench.action.reloadWindow'); } }); - this.addEventListener('showRunning', 'click', () => { - ipcRenderer.send('workbenchCommand', 'workbench.action.showRuntimeExtensions'); - }); - - this.addEventListener('showRunning', 'keydown', (e: KeyboardEvent) => { - if (e.keyCode === 13 || e.keyCode === 32) { - ipcRenderer.send('workbenchCommand', 'workbench.action.showRuntimeExtensions'); + document.onkeydown = (e: KeyboardEvent) => { + const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; + // Cmd/Ctrl+Enter previews issue and closes window + if (cmdOrCtrlKey && e.keyCode === 13) { + if (this.createIssue()) { + remote.getCurrentWindow().close(); + } } - }); - // Cmd+Enter or Mac or Ctrl+Enter on other platforms previews issue and closes window - if (platform.isMacintosh) { - let prevKeyWasCommand = false; - document.onkeydown = (e: KeyboardEvent) => { - if (prevKeyWasCommand && e.keyCode === 13) { - if (this.createIssue()) { - remote.getCurrentWindow().close(); - } - } + // Cmd/Ctrl + zooms in + if (cmdOrCtrlKey && e.keyCode === 187) { + this.applyZoom(webFrame.getZoomLevel() + 1); + } - prevKeyWasCommand = e.keyCode === 91 || e.keyCode === 93; - }; - } else { - document.onkeydown = (e: KeyboardEvent) => { - if (e.ctrlKey && e.keyCode === 13) { - if (this.createIssue()) { - remote.getCurrentWindow().close(); - } - } - }; - } + // Cmd/Ctrl - zooms out + if (cmdOrCtrlKey && e.keyCode === 189) { + this.applyZoom(webFrame.getZoomLevel() - 1); + } + }; } private updatePreviewButtonState() { @@ -438,12 +439,77 @@ export class IssueReporter extends Disposable { return false; } + private getExtensionRepositoryUrl(): string { + const selectedExtension = this.issueReporterModel.getData().selectedExtension; + return selectedExtension && selectedExtension.manifest && selectedExtension.manifest.repository && selectedExtension.manifest.repository.url; + } + + private getExtensionBugsUrl(): string { + const selectedExtension = this.issueReporterModel.getData().selectedExtension; + return selectedExtension && selectedExtension.manifest && selectedExtension.manifest.bugs && selectedExtension.manifest.bugs.url; + } + + private searchVSCodeIssues(title: string, issueDescription: string): void { + if (title) { + this.searchDuplicates(title, issueDescription); + } else { + this.clearSearchResults(); + } + } + + private searchExtensionIssues(title: string): void { + const url = this.getExtensionRepositoryUrl(); + if (title) { + const matches = /^https?:\/\/github\.com\/(.*)(?:.git)/.exec(url); + if (matches && matches.length) { + const repo = matches[1]; + return this.searchGitHub(repo, title); + } + } + + this.clearSearchResults(); + } + private clearSearchResults(): void { const similarIssues = document.getElementById('similar-issues'); similarIssues.innerHTML = ''; this.numberOfSearchResultsDisplayed = 0; } + @debounce(300) + private searchGitHub(repo: string, title: string): void { + const query = `is:issue+repo:${repo}+${title}`; + const similarIssues = document.getElementById('similar-issues'); + + window.fetch(`https://api.github.com/search/issues?q=${query}`).then((response) => { + response.json().then(result => { + similarIssues.innerHTML = ''; + if (result && result.items) { + this.displaySearchResults(result.items); + } else { + // If the items property isn't present, the rate limit has been hit + const message = $('div.list-title'); + message.textContent = localize('rateLimited', "GitHub query limit exceeded. Please wait."); + similarIssues.appendChild(message); + + const resetTime = response.headers.get('X-RateLimit-Reset'); + const timeToWait = parseInt(resetTime) - Math.floor(Date.now() / 1000); + if (this.shouldQueueSearch) { + this.shouldQueueSearch = false; + setTimeout(() => { + this.searchGitHub(repo, title); + this.shouldQueueSearch = true; + }, timeToWait * 1000); + } + } + }).catch(e => { + this.logSearchError(e); + }); + }).catch(e => { + this.logSearchError(e); + }); + } + @debounce(300) private searchDuplicates(title: string, body: string): void { const url = 'https://vscode-probot.westus.cloudapp.azure.com:7890/duplicate_candidates'; @@ -516,7 +582,7 @@ export class IssueReporter extends Disposable { similarIssues.appendChild(issues); } else { const message = $('div.list-title'); - message.textContent = localize('noResults', "No results found"); + message.textContent = localize('noSimilarIssues', "No similar issues found"); similarIssues.appendChild(message); } } @@ -542,8 +608,8 @@ export class IssueReporter extends Disposable { } else { typeSelect.innerHTML = [ makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")), - makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")), - makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")) + makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")), + makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")) ].join('\n'); } @@ -552,7 +618,8 @@ export class IssueReporter extends Disposable { private renderBlocks(): void { // Depending on Issue Type, we render different blocks and text - const { issueType } = this.issueReporterModel.getData(); + const { issueType, fileOnExtension } = this.issueReporterModel.getData(); + const blockContainer = document.getElementById('block-container'); const systemBlock = document.querySelector('.block-system'); const processBlock = document.querySelector('.block-process'); const workspaceBlock = document.querySelector('.block-workspace'); @@ -560,39 +627,64 @@ export class IssueReporter extends Disposable { const searchedExtensionsBlock = document.querySelector('.block-searchedExtensions'); const settingsSearchResultsBlock = document.querySelector('.block-settingsSearchResults'); - const disabledExtensions = document.getElementById('disabledExtensions'); + const problemSource = document.getElementById('problem-source'); + const problemSourceHelpText = document.getElementById('problem-source-help-text'); const descriptionTitle = document.getElementById('issue-description-label'); const descriptionSubtitle = document.getElementById('issue-description-subtitle'); + const extensionSelector = document.getElementById('extension-selection'); // Hide all by default + hide(blockContainer); hide(systemBlock); hide(processBlock); hide(workspaceBlock); hide(extensionsBlock); hide(searchedExtensionsBlock); hide(settingsSearchResultsBlock); - hide(disabledExtensions); + hide(problemSource); + hide(problemSourceHelpText); + hide(extensionSelector); if (issueType === IssueType.Bug) { + show(blockContainer); show(systemBlock); - show(extensionsBlock); - show(disabledExtensions); + show(problemSource); + + if (fileOnExtension) { + show(extensionSelector); + } else { + show(extensionsBlock); + show(problemSourceHelpText); + } descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} <span class="required-input">*</span>`; descriptionSubtitle.innerHTML = localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."); } else if (issueType === IssueType.PerformanceIssue) { + show(blockContainer); show(systemBlock); show(processBlock); show(workspaceBlock); - show(extensionsBlock); - show(disabledExtensions); + show(problemSource); + + if (fileOnExtension) { + show(extensionSelector); + } else { + show(extensionsBlock); + show(problemSourceHelpText); + } descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} <span class="required-input">*</span>`; descriptionSubtitle.innerHTML = localize('performanceIssueDesciption', "When did this performance issue happen? Does it occur on startup or after a specific series of actions? We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."); } else if (issueType === IssueType.FeatureRequest) { descriptionTitle.innerHTML = `${localize('description', "Description")} <span class="required-input">*</span>`; descriptionSubtitle.innerHTML = localize('featureRequestDescription', "Please describe the feature you would like to see. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."); + show(problemSource); + + if (fileOnExtension) { + show(extensionSelector); + } } else if (issueType === IssueType.SettingsSearchIssue) { + show(blockContainer); show(searchedExtensionsBlock); show(settingsSearchResultsBlock); @@ -614,11 +706,14 @@ export class IssueReporter extends Disposable { private validateInputs(): boolean { let isValid = true; - ['issue-title', 'description'].forEach(elementId => { + ['issue-title', 'description', 'issue-source'].forEach(elementId => { isValid = this.validateInput(elementId) && isValid; - }); + if (this.issueReporterModel.fileOnExtension()) { + isValid = this.validateInput('extension-selector') && isValid; + } + return isValid; } @@ -626,7 +721,10 @@ export class IssueReporter extends Disposable { if (!this.validateInputs()) { // If inputs are invalid, set focus to the first one and add listeners on them // to detect further changes - (<HTMLInputElement>document.getElementsByClassName('invalid-input')[0]).focus(); + const invalidInput = document.getElementsByClassName('invalid-input'); + if (invalidInput.length) { + (<HTMLInputElement>invalidInput[0]).focus(); + } document.getElementById('issue-title').addEventListener('input', (event) => { this.validateInput('issue-title'); @@ -641,8 +739,8 @@ export class IssueReporter extends Disposable { /* __GDPR__ "issueReporterSubmit" : { - "issueType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "numSimilarIssuesDisplayed" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "issueType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "numSimilarIssuesDisplayed" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('issueReporterSubmit', { issueType: this.issueReporterModel.getData().issueType, numSimilarIssuesDisplayed: this.numberOfSearchResultsDisplayed }); @@ -660,24 +758,88 @@ export class IssueReporter extends Disposable { return true; } - private getIssueUrlWithTitle(issueTitle: string) { + private getIssueUrlWithTitle(issueTitle: string): string { + let repositoryUrl = product.reportIssueUrl; + if (this.issueReporterModel.fileOnExtension()) { + const bugsUrl = this.getExtensionBugsUrl(); + const extensionUrl = this.getExtensionRepositoryUrl(); + // If given, try to match the extension's bug url + if (bugsUrl && bugsUrl.match(/^https?:\/\/github\.com\/(.*)/)) { + repositoryUrl = normalizeGitHubIssuesUrl(bugsUrl); + } else if (extensionUrl && extensionUrl.match(/^https?:\/\/github\.com\/(.*)/)) { + repositoryUrl = normalizeGitHubIssuesUrl(extensionUrl); + } + } + const queryStringPrefix = product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&'; - return `${product.reportIssueUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`; + return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`; } private updateSystemInfo = (state) => { const target = document.querySelector('.block-system .block-info'); let tableHtml = ''; Object.keys(state.systemInfo).forEach(k => { + const data = typeof state.systemInfo[k] === 'object' + ? Object.keys(state.systemInfo[k]).map(key => `${key}: ${state.systemInfo[k][key]}`).join('<br>') + : state.systemInfo[k]; + tableHtml += ` <tr> <td>${k}</td> - <td>${state.systemInfo[k]}</td> + <td>${data}</td> </tr>`; }); target.innerHTML = `<table>${tableHtml}</table>`; } + private updateExtensionSelector(extensions: ILocalExtension[]): void { + interface IOption { + name: string; + id: string; + } + + const extensionOptions: IOption[] = extensions.map(extension => { + return { + name: extension.manifest.displayName || extension.manifest.name || '', + id: extension.identifier.id + }; + }); + + // Sort extensions by name + extensionOptions.sort((a, b) => { + const aName = a.name.toLowerCase(); + const bName = b.name.toLowerCase(); + if (aName > bName) { + return 1; + } + + if (aName < bName) { + return -1; + } + + return 0; + }); + + const makeOption = (extension: IOption) => `<option value="${extension.id}">${escape(extension.name)}</option>`; + const extensionsSelector = document.getElementById('extension-selector'); + extensionsSelector.innerHTML = '<option></option>' + extensionOptions.map(makeOption).join('\n'); + + this.addEventListener('extension-selector', 'change', (e: Event) => { + const selectedExtensionId = (<HTMLInputElement>e.target).value; + const extensions = this.issueReporterModel.getData().allExtensions; + const matches = extensions.filter(extension => extension.identifier.id === selectedExtensionId); + if (matches.length) { + this.issueReporterModel.update({ selectedExtension: matches[0] }); + + const title = (<HTMLInputElement>document.getElementById('issue-title')).value; + this.searchExtensionIssues(title); + } else { + this.issueReporterModel.update({ selectedExtension: null }); + this.clearSearchResults(); + } + }); + } + private updateProcessInfo = (state) => { const target = document.querySelector('.block-process .block-info'); target.innerHTML = `<code>${state.processInfo}</code>`; diff --git a/src/vs/code/electron-browser/issue/issueReporterModel.ts b/src/vs/code/electron-browser/issue/issueReporterModel.ts index 0ad65606ed..5a5130f809 100644 --- a/src/vs/code/electron-browser/issue/issueReporterModel.ts +++ b/src/vs/code/electron-browser/issue/issueReporterModel.ts @@ -26,9 +26,11 @@ export interface IssueReporterData { includeSettingsSearchDetails?: boolean; numberOfThemeExtesions?: number; + allExtensions?: ILocalExtension[]; enabledNonThemeExtesions?: ILocalExtension[]; extensionsDisabled?: boolean; - reprosWithoutExtensions?: boolean; + fileOnExtension?: boolean; + selectedExtension?: ILocalExtension; actualSearchResults?: ISettingSearchResult[]; query?: string; filterResultCount?: number; @@ -44,8 +46,7 @@ export class IssueReporterModel { includeProcessInfo: true, includeExtensions: true, includeSearchedExtensions: true, - includeSettingsSearchDetails: true, - reprosWithoutExtensions: false + includeSettingsSearchDetails: true }; this._data = initialData ? assign(defaultData, initialData) : defaultData; @@ -73,6 +74,22 @@ ${this.getInfos()} <!-- generated by issue reporter -->`; } + fileOnExtension(): boolean { + const fileOnExtensionSupported = this._data.issueType === IssueType.Bug + || this._data.issueType === IssueType.PerformanceIssue + || this._data.issueType === IssueType.FeatureRequest; + + return fileOnExtensionSupported && this._data.fileOnExtension; + } + + private getExtensionVersion(): string { + if (this.fileOnExtension()) { + return `\nExtension version: ${this._data.selectedExtension.manifest.version}`; + } else { + return ''; + } + } + private getIssueTypeTitle(): string { if (this._data.issueType === IssueType.Bug) { return 'Bug'; @@ -109,8 +126,6 @@ ${this.getInfos()} if (this._data.includeExtensions) { info += this.generateExtensionsMd(); } - - info += this._data.reprosWithoutExtensions ? '\nReproduces without extensions' : '\nReproduces only with extensions'; } if (this._data.issueType === IssueType.SettingsSearchIssue) { @@ -136,7 +151,11 @@ ${this.getInfos()} `; Object.keys(this._data.systemInfo).forEach(k => { - md += `|${k}|${this._data.systemInfo[k]}|\n`; + const data = typeof this._data.systemInfo[k] === 'object' + ? Object.keys(this._data.systemInfo[k]).map(key => `${key}: ${this._data.systemInfo[k][key]}`).join('<br>') + : this._data.systemInfo[k]; + + md += `|${k}|${data}|\n`; }); md += '\n</details>'; diff --git a/src/vs/code/electron-browser/issue/issueReporterPage.ts b/src/vs/code/electron-browser/issue/issueReporterPage.ts index 50016ae4d3..ee09c136b8 100644 --- a/src/vs/code/electron-browser/issue/issueReporterPage.ts +++ b/src/vs/code/electron-browser/issue/issueReporterPage.ts @@ -19,6 +19,25 @@ export default (): string => ` </select> </div> + <div class="input-group" id="problem-source"> + <label class="inline-label" for="issue-source">${escape(localize('issueSourceLabel', "File on"))}</label> + <select id="issue-source" class="inline-form-control"> + <!-- {{ SQL CARBON EDIT }} --> + <option value="false">${escape(localize('sqlops', "SQL Operations Studio"))}</option> + <option value="true">${escape(localize('extension', "An Extension"))}</option> + </select> + <div id="problem-source-help-text" class="instructions">${escape(localize('disableExtensionsLabelText', "Try to reproduce the problem after {0}. If the problem only reproduces when extensions are active, it is likely an issue with an extension.")) + .replace('{0}', `<span tabIndex=0 role="button" id="disableExtensions" class="workbenchCommand">${escape(localize('disableExtensions', "disabling all extensions and reloading the window"))}</span>`)} + </div> + + <div id="extension-selection"> + <label class="inline-label" for="extension-selector">${escape(localize('chooseExtension', "Extension"))} <span class="required-input">*</span></label> + <select id="extension-selector" class="inline-form-control"> + <!-- To be dynamically filled --> + </select> + </div> + </div> + <div class="input-group"> <label class="inline-label" for="issue-title">${escape(localize('issueTitleLabel', "Title"))} <span class="required-input">*</span></label> <input id="issue-title" type="text" class="inline-form-control" placeholder="${escape(localize('issueTitleRequired', "Please enter a title."))}" required> @@ -27,118 +46,93 @@ export default (): string => ` <!-- To be dynamically filled --> </small> </div> + </div> - <div class="system-info"> - <div id="block-container"> - <div class="block block-system"> - <details> - <summary>${escape(localize('systemInfo', "My System Info"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeSystemInfo" checked/> - <label class="caption" for="includeSystemInfo">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <div class="block-info"> - <!-- To be dynamically filled --> - </div> - </details> - </div> - <div class="block block-process"> - <details> - <summary>${escape(localize('processes', "Currently Running Processes"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeProcessInfo" checked/> - <label class="caption" for="includeProcessInfo">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <pre class="block-info"> - <!-- To be dynamically filled --> - </pre> - </details> - </div> - <div class="block block-workspace"> - <details> - <summary>${escape(localize('workspaceStats', "My Workspace Stats"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeWorkspaceInfo" checked/> - <label class="caption" for="includeWorkspaceInfo">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <pre class="block-info"> - <code> - <!-- To be dynamically filled --> - </code> - </pre> - </details> - </div> - <div class="block block-extensions"> - <details> - <summary>${escape(localize('extensions', "My Extensions"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeExtensions" checked/> - <label class="caption" for="includeExtensions">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <div class="block-info"> - <!-- To be dynamically filled --> - </div> - </details> - </div> - <div class="block block-searchedExtensions"> - <details> - <summary>${escape(localize('searchedExtensions', "Searched Extensions"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeSearchedExtensions" checked/> - <label class="caption" for="includeSearchedExtensions">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <div class="block-info"> - <!-- To be dynamically filled --> - </div> - </details> - </div> - <div class="block block-settingsSearchResults"> - <details> - <summary>${escape(localize('settingsSearchDetails', "Settings Search Details"))} - <div class="include-data"> - <input class="sendData" type="checkbox" id="includeSettingsSearchDetails" checked/> - <label class="caption" for="includeSettingsSearchDetails">${escape(localize('sendData', "Send my data"))}</label> - </div> - </summary> - <div class="block-info"> - <!-- To be dynamically filled --> - </div> - </details> - </div> - </div> - </div> - - <div class="section"> - <div id="disabledExtensions"> - <div class="extensions-form"> - <label>${escape(localize('tryDisablingExtensions', "Is the problem reproducible when extensions are disabled?"))}</label> - <div class="form-buttons"> - <div class="choice"> - <input type="radio" id="reproducesWithoutExtensions" value=true name="reprosWithoutExtensions" /> - <label for="reproducesWithoutExtensions">${escape(localize('yes', "Yes"))}</label> - </div> - <div class="choice"> - <input type="radio" id="reproducesWithExtensions" value=false name="reprosWithoutExtensions" checked/> - <label for="reproducesWithExtensions">${escape(localize('no', "No"))}</label> + <div class="system-info" id="block-container"> + <div class="block block-system"> + <details> + <summary>${escape(localize('systemInfo', "My System Info"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeSystemInfo" checked/> + <label class="caption" for="includeSystemInfo">${escape(localize('sendData', "Send my data"))}</label> </div> + </summary> + <div class="block-info"> + <!-- To be dynamically filled --> </div> - </div> - <div class="instructions">${escape(localize('disableExtensionsLabelText', "Try to reproduce the problem after {0}.")) - .replace('{0}', `<span tabIndex=0 role="button" id="disableExtensions" class="workbenchCommand">${escape(localize('disableExtensions', "disabling all extensions and reloading the window"))}</span>`)} - </div> - <div class="instructions">${escape(localize('showRunningExtensionsLabelText', "If you suspect it's an extension issue, {0} to report the issue on the extension.")) - .replace('{0}', `<span tabIndex=0 role="button"id="showRunning" class="workbenchCommand">${escape(localize('showRunningExtensions', "view all running extensions"))}</span>`)} - </div> + </details> + </div> + <div class="block block-process"> + <details> + <summary>${escape(localize('processes', "Currently Running Processes"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeProcessInfo" checked/> + <label class="caption" for="includeProcessInfo">${escape(localize('sendData', "Send my data"))}</label> + </div> + </summary> + <pre class="block-info"> + <!-- To be dynamically filled --> + </pre> + </details> + </div> + <div class="block block-workspace"> + <details> + <summary>${escape(localize('workspaceStats', "My Workspace Stats"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeWorkspaceInfo" checked/> + <label class="caption" for="includeWorkspaceInfo">${escape(localize('sendData', "Send my data"))}</label> + </div> + </summary> + <pre class="block-info"> + <code> + <!-- To be dynamically filled --> + </code> + </pre> + </details> + </div> + <div class="block block-extensions"> + <details> + <summary>${escape(localize('extensions', "My Extensions"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeExtensions" checked/> + <label class="caption" for="includeExtensions">${escape(localize('sendData', "Send my data"))}</label> + </div> + </summary> + <div class="block-info"> + <!-- To be dynamically filled --> + </div> + </details> + </div> + <div class="block block-searchedExtensions"> + <details> + <summary>${escape(localize('searchedExtensions', "Searched Extensions"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeSearchedExtensions" checked/> + <label class="caption" for="includeSearchedExtensions">${escape(localize('sendData', "Send my data"))}</label> + </div> + </summary> + <div class="block-info"> + <!-- To be dynamically filled --> + </div> + </details> + </div> + <div class="block block-settingsSearchResults"> + <details> + <summary>${escape(localize('settingsSearchDetails', "Settings Search Details"))} + <div class="include-data"> + <input class="sendData" type="checkbox" id="includeSettingsSearchDetails" checked/> + <label class="caption" for="includeSettingsSearchDetails">${escape(localize('sendData', "Send my data"))}</label> + </div> + </summary> + <div class="block-info"> + <!-- To be dynamically filled --> + </div> + </details> </div> </div> - <div class="input-group"> + <div class="input-group description-section"> <label for="description" id="issue-description-label"> <!-- To be dynamically filled --> </label> @@ -146,7 +140,7 @@ export default (): string => ` <!-- To be dynamically filled --> </div> <div class="block-info-text"> - <textarea name="description" id="description" cols="100" rows="12" placeholder="${escape(localize('details', "Please enter details."))}" required></textarea> + <textarea name="description" id="description" placeholder="${escape(localize('details', "Please enter details."))}" required></textarea> </div> </div> diff --git a/src/vs/code/electron-browser/issue/issueReporterUtil.ts b/src/vs/code/electron-browser/issue/issueReporterUtil.ts new file mode 100644 index 0000000000..165f2104a5 --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporterUtil.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { endsWith, rtrim } from 'vs/base/common/strings'; + +export function normalizeGitHubIssuesUrl(url: string): string { + // If the url has a .git suffix, remove it + if (endsWith(url, '.git')) { + url = url.substr(0, url.length - 4); + } + + // Remove trailing slash + url = rtrim(url, '/'); + + // If the url already ends with issues/new, it's beautiful, return it + if (endsWith(url, 'issues/new')) { + return url; + } + + // Add new segment if it does not exist + if (endsWith(url, 'issues')) { + return url + '/new'; + } + + return url + '/issues/new'; +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/issue/media/issueReporter.css b/src/vs/code/electron-browser/issue/media/issueReporter.css index ee9579d4eb..dafc9c6471 100644 --- a/src/vs/code/electron-browser/issue/media/issueReporter.css +++ b/src/vs/code/electron-browser/issue/media/issueReporter.css @@ -18,16 +18,11 @@ th { vertical-align: bottom; border-bottom: 2px solid #e9ecef; padding: .75rem; - border-top: 1px solid #e9ecef; text-align: inherit; } -tr:nth-of-type(even) { - background-color: rgba(0,0,0,.05); -} td { padding: .75rem; vertical-align: top; - border-top: 1px solid #e9ecef; } .block-settingsSearchResults-details { @@ -39,7 +34,7 @@ td { } .section { - margin-bottom: 1.5em; + margin-bottom: .5em; } /** @@ -103,21 +98,19 @@ textarea { html { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif; color: #CCCCCC; + height: 100%; } body { margin: 0; overflow: scroll; + height: 100%; } .hidden { display: none; } -#block-container { - margin-top: 1em; -} - .block .block-info { width: 100%; font-family: 'Menlo', 'Courier New', 'Courier', monospace; @@ -144,11 +137,32 @@ button:disabled { max-width: 85vw; margin-left: auto; margin-right: auto; - margin-top: 2em; + padding-top: 2em; + display: flex; + flex-direction: column; + height: 100%; +} + +.description-section { + flex-grow: 1; + display: flex; + flex-direction: column; + flex-shrink: 0; +} + +textarea { + flex-grow: 1; + min-height: 150px; +} + +.block-info-text { + display: flex; + flex-grow: 1; } #github-submit-btn { - float: right; + flex-shrink: 0; + margin-left: auto; margin-top: 10px; margin-bottom: 10px; } @@ -166,31 +180,8 @@ button:disabled { margin-bottom: 1em; } -.extensions-form { - display: flex; -} - -.extensions-form > .form-buttons { - display: flex; - margin-left: 20px; -} - -.extensions-form > .form-buttons > .choice { - margin-right: 35px; - position: relative; -} - -.extensions-form > .form-buttons > .choice > label, .extensions-form > .form-buttons > .choice > input { - cursor: pointer; - height: 100%; - margin-top: 1px; -} - -.extensions-form > .form-buttons > .choice > label { - position: absolute; - top: 50%; - margin-top: -50%; - left: 20px; +#extension-selection { + margin-top: 1em; } .system-info { @@ -206,6 +197,7 @@ summary { border: 1px solid transparent; padding: 0 10px; margin-bottom: 5px; + cursor: pointer; } .validation-error { @@ -250,8 +242,9 @@ input:disabled { margin-top: .5em; } -.workbenchCommand { +a, .workbenchCommand { cursor: pointer; + border: 1px solid transparent; } .workbenchCommand:disabled { @@ -309,17 +302,17 @@ button { } #similar-issues { - margin-left: 12%; + margin-left: 13%; display: block; } @media (max-width: 950px) { .section .inline-label { - width: 12%; + width: 13%; } .section .inline-form-control { - width: calc(88% - 5px); + width: calc(87% - 5px); } } @@ -328,7 +321,7 @@ button { display: none !important; } - .inline-form-control { + .section .inline-form-control { width: 100%; } @@ -352,26 +345,28 @@ button { .issues-container { margin-left: 1.5em; margin-top: .5em; - height: 92px; + max-height: 92px; overflow-y: auto; } .issues-container > .issue { padding: 4px 0; + display: flex; } .issues-container > .issue > .issue-link { - display: inline-block; width: calc(100% - 82px); - vertical-align: top; overflow: hidden; padding-top: 3px; white-space: nowrap; text-overflow: ellipsis; } +.issues-container > .issue > .issue-state .octicon { + width: 16px; +} + .issues-container > .issue > .issue-state { - display: inline-block; width: 77px; padding: 3px 6px; margin-right: 5px; @@ -380,14 +375,8 @@ button { border-radius: .25rem; } -.issues-container > .issue > .issue-state .octicon { - vertical-align: top; - width: 16px; -} - .issues-container > .issue .label { margin-left: 5px; - display: inline-block; width: 44px; text-overflow: ellipsis; overflow: hidden; diff --git a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts index 5fbd7007f6..dbb2bdee0c 100644 --- a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts +++ b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts @@ -7,6 +7,8 @@ import * as assert from 'assert'; import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel'; +import { normalizeGitHubIssuesUrl } from 'vs/code/electron-browser/issue/issueReporterUtil'; +import { IssueType } from 'vs/platform/issue/common/issue'; suite('IssueReporter', () => { @@ -18,8 +20,7 @@ suite('IssueReporter', () => { includeProcessInfo: true, includeExtensions: true, includeSearchedExtensions: true, - includeSettingsSearchDetails: true, - reprosWithoutExtensions: false + includeSettingsSearchDetails: true }); }); @@ -38,4 +39,75 @@ OS version: undefined <!-- generated by issue reporter -->`); }); + + test('serializes GPU information when data is provided', () => { + const issueReporterModel = new IssueReporterModel({ + issueType: 0, + systemInfo: { + 'GPU Status': { + '2d_canvas': 'enabled', + 'checker_imaging': 'disabled_off' + } + } + }); + assert.equal(issueReporterModel.serialize(), + // {{SQL CARBON EDIT}} + ` +Issue Type: <b>Bug</b> + +undefined + +SQL Operations Studio version: undefined +OS version: undefined + +<details> +<summary>System Info</summary> + +|Item|Value| +|---|---| +|GPU Status|2d_canvas: enabled<br>checker_imaging: disabled_off| + +</details>Extensions: none +<!-- generated by issue reporter -->`); + }); + + test('should normalize GitHub urls', () => { + [ + 'https://github.com/repo', + 'https://github.com/repo/', + 'https://github.com/repo.git', + 'https://github.com/repo/issues', + 'https://github.com/repo/issues/', + 'https://github.com/repo/issues/new', + 'https://github.com/repo/issues/new/' + ].forEach(url => { + assert.equal('https://github.com/repo/issues/new', normalizeGitHubIssuesUrl(url)); + }); + }); + + test('should have support for filing on extensions for bugs, performance issues, and feature requests', () => { + [ + IssueType.Bug, + IssueType.FeatureRequest, + IssueType.PerformanceIssue + ].forEach(type => { + const issueReporterModel = new IssueReporterModel({ + issueType: type, + fileOnExtension: true + }); + + assert.equal(issueReporterModel.fileOnExtension(), true); + }); + + [ + IssueType.SettingsSearchIssue + ].forEach(type => { + const issueReporterModel = new IssueReporterModel({ + issueType: type, + fileOnExtension: true + }); + + assert.equal(issueReporterModel.fileOnExtension(), false); + }); + }); }); diff --git a/src/vs/code/electron-browser/processExplorer/media/processExplorer.css b/src/vs/code/electron-browser/processExplorer/media/processExplorer.css new file mode 100644 index 0000000000..a888bd23b7 --- /dev/null +++ b/src/vs/code/electron-browser/processExplorer/media/processExplorer.css @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +html, +body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; + font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif; + font-size: 13px; + color: #cccccc; +} + +.cpu { + width: 45px; +} + +.pid { + width: 50px +} + +.memory { + width: 90px; +} + +.process-item { + line-height: 22px; +} + +table { + border-collapse: collapse; + width: 100%; + table-layout: fixed; +} +th { + vertical-align: bottom; + border-bottom: 1px solid #cccccc; + padding: .5rem; + border-top: 1px solid #cccccc; + cursor: default; +} +td { + padding: .25rem; + vertical-align: top; + cursor: default; +} + +.centered { + text-align: center; +} + +.nameLabel{ + text-align: left; +} + +.data { + white-space: pre; + padding-left: .5rem; +} + +tbody > tr:hover { + background-color: #2A2D2E; +} diff --git a/src/vs/code/electron-browser/processExplorer/processExplorer.html b/src/vs/code/electron-browser/processExplorer/processExplorer.html new file mode 100644 index 0000000000..4d6930d998 --- /dev/null +++ b/src/vs/code/electron-browser/processExplorer/processExplorer.html @@ -0,0 +1,17 @@ +<!-- Copyright (C) Microsoft Corporation. All rights reserved. --> +<!DOCTYPE html> +<html> + +<head> + <meta charset="utf-8" /> + <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;"> +</head> + +<body aria-label=""> + <div id="process-list"></div> +</body> + +<!-- Startup via processExplorer.js --> +<script src="processExplorer.js"></script> + +</html> \ No newline at end of file diff --git a/src/vs/code/electron-browser/processExplorer/processExplorer.js b/src/vs/code/electron-browser/processExplorer/processExplorer.js new file mode 100644 index 0000000000..94471fdd8f --- /dev/null +++ b/src/vs/code/electron-browser/processExplorer/processExplorer.js @@ -0,0 +1,175 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const path = require('path'); +const fs = require('fs'); +const remote = require('electron').remote; + +function assign(destination, source) { + return Object.keys(source) + .reduce(function (r, key) { r[key] = source[key]; return r; }, destination); +} + +function parseURLQueryArgs() { + const search = window.location.search || ''; + + return search.split(/[?&]/) + .filter(function (param) { return !!param; }) + .map(function (param) { return param.split('='); }) + .filter(function (param) { return param.length === 2; }) + .reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {}); +} + +function uriFromPath(_path) { + var pathName = path.resolve(_path).replace(/\\/g, '/'); + if (pathName.length > 0 && pathName.charAt(0) !== '/') { + pathName = '/' + pathName; + } + + return encodeURI('file://' + pathName); +} + +function readFile(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, 'utf8', function(err, data) { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + +function main() { + const args = parseURLQueryArgs(); + const configuration = JSON.parse(args['config'] || '{}') || {}; + + assign(process.env, configuration.userEnv); + + //#region Add support for using node_modules.asar + (function () { + const path = require('path'); + const Module = require('module'); + let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules'); + if (/[a-z]\:/.test(NODE_MODULES_PATH)) { + // Make drive letter uppercase + NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1); + } + const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; + + const originalResolveLookupPaths = Module._resolveLookupPaths; + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); + + const paths = newReturn ? result : result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === NODE_MODULES_PATH) { + paths.splice(i, 0, NODE_MODULES_ASAR_PATH); + break; + } + } + + return result; + }; + })(); + //#endregion + + // Get the nls configuration into the process.env as early as possible. + var nlsConfig = { availableLanguages: {} }; + const config = process.env['VSCODE_NLS_CONFIG']; + if (config) { + process.env['VSCODE_NLS_CONFIG'] = config; + try { + nlsConfig = JSON.parse(config); + } catch (e) { /*noop*/ } + } + + if (nlsConfig._resolvedLanguagePackCoreLocation) { + let bundles = Object.create(null); + nlsConfig.loadBundle = function(bundle, language, cb) { + let result = bundles[bundle]; + if (result) { + cb(undefined, result); + return; + } + let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json'); + readFile(bundleFile).then(function (content) { + let json = JSON.parse(content); + bundles[bundle] = json; + cb(undefined, json); + }) + .catch(cb); + }; + } + + var locale = nlsConfig.availableLanguages['*'] || 'en'; + if (locale === 'zh-tw') { + locale = 'zh-Hant'; + } else if (locale === 'zh-cn') { + locale = 'zh-Hans'; + } + + window.document.documentElement.setAttribute('lang', locale); + + const extractKey = function (e) { + return [ + e.ctrlKey ? 'ctrl-' : '', + e.metaKey ? 'meta-' : '', + e.altKey ? 'alt-' : '', + e.shiftKey ? 'shift-' : '', + e.keyCode + ].join(''); + }; + + const TOGGLE_DEV_TOOLS_KB = (process.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I + const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R + + window.addEventListener('keydown', function (e) { + const key = extractKey(e); + if (key === TOGGLE_DEV_TOOLS_KB) { + remote.getCurrentWebContents().toggleDevTools(); + } else if (key === RELOAD_KB) { + remote.getCurrentWindow().reload(); + } + }); + + // Load the loader + const loaderFilename = configuration.appRoot + '/out/vs/loader.js'; + const loaderSource = fs.readFileSync(loaderFilename); + require('vm').runInThisContext(loaderSource, { filename: loaderFilename }); + var define = global.define; + global.define = undefined; + + window.nodeRequire = require.__$__nodeRequire; + + define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code + + window.MonacoEnvironment = {}; + const rootUrl = uriFromPath(configuration.appRoot) + '/out'; + + require.config({ + baseUrl: rootUrl, + 'vs/nls': nlsConfig, + nodeCachedDataDir: configuration.nodeCachedDataDir, + nodeModules: [/*BUILD->INSERT_NODE_MODULES*/] + }); + + if (nlsConfig.pseudo) { + require(['vs/nls'], function (nlsPlugin) { + nlsPlugin.setPseudoTranslation(nlsConfig.pseudo); + }); + } + + require([ + 'vs/code/electron-browser/processExplorer/processExplorerMain' + ], function (processExplorer) { + processExplorer.startup(configuration.data); + }); +} + +main(); diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts new file mode 100644 index 0000000000..042ed1846a --- /dev/null +++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts @@ -0,0 +1,184 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'vs/css!./media/processExplorer'; +import { listProcesses, ProcessItem } from 'vs/base/node/ps'; +import { remote, webFrame } from 'electron'; +import { repeat } from 'vs/base/common/strings'; +import { totalmem } from 'os'; +import product from 'vs/platform/node/product'; +import { localize } from 'vs/nls'; +import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue'; +import * as browser from 'vs/base/browser/browser'; +import * as platform from 'vs/base/common/platform'; + +let processList: any[]; + +function getProcessList(rootProcess: ProcessItem) { + const processes: any[] = []; + + if (rootProcess) { + getProcessItem(processes, rootProcess, 0); + } + + return processes; +} + +function getProcessItem(processes: any[], item: ProcessItem, indent: number): void { + const isRoot = (indent === 0); + + const MB = 1024 * 1024; + + // Format name with indent + const name = isRoot ? `${product.applicationName} main` : item.name; + const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`; + const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100)); + processes.push({ + cpu: Number(item.load.toFixed(0)), + memory: Number((memory / MB).toFixed(0)), + pid: Number((item.pid).toFixed(0)), + name, + formattedName, + cmd: item.cmd + }); + + // Recurse into children if any + if (Array.isArray(item.children)) { + item.children.forEach(child => getProcessItem(processes, child, indent + 1)); + } +} + +function getProcessIdWithHighestProperty(processList, propertyName: string) { + let max = 0; + let maxProcessId; + processList.forEach(process => { + if (process[propertyName] > max) { + max = process[propertyName]; + maxProcessId = process.pid; + } + }); + + return maxProcessId; +} + +function updateProcessInfo(processList): void { + const target = document.getElementById('process-list'); + const highestCPUProcess = getProcessIdWithHighestProperty(processList, 'cpu'); + const highestMemoryProcess = getProcessIdWithHighestProperty(processList, 'memory'); + + let tableHtml = ` + <tr> + <th class="cpu">${localize('cpu', "CPU %")}</th> + <th class="memory">${localize('memory', "Memory (MB)")}</th> + <th class="pid">${localize('pid', "pid")}</th> + <th class="nameLabel">${localize('name', "Name")}</th> + </tr>`; + + processList.forEach(p => { + const cpuClass = p.pid === highestCPUProcess ? 'highest' : ''; + const memoryClass = p.pid === highestMemoryProcess ? 'highest' : ''; + + tableHtml += ` + <tr id=${p.pid}> + <td class="centered ${cpuClass}">${p.cpu}</td> + <td class="centered ${memoryClass}">${p.memory}</td> + <td class="centered">${p.pid}</td> + <td title="${p.name}" class="data">${p.formattedName}</td> + </tr>`; + }); + + target.innerHTML = `<table>${tableHtml}</table>`; +} + +function applyStyles(styles: ProcessExplorerStyles): void { + const styleTag = document.createElement('style'); + const content: string[] = []; + + if (styles.hoverBackground) { + content.push(`tbody > tr:hover { background-color: ${styles.hoverBackground}; }`); + } + + if (styles.hoverForeground) { + content.push(`tbody > tr:hover{ color: ${styles.hoverForeground}; }`); + } + + if (styles.highlightForeground) { + content.push(`.highest { color: ${styles.highlightForeground}; }`); + } + + styleTag.innerHTML = content.join('\n'); + document.head.appendChild(styleTag); + document.body.style.color = styles.color; +} + +function applyZoom(zoomLevel: number): void { + webFrame.setZoomLevel(zoomLevel); + browser.setZoomFactor(webFrame.getZoomFactor()); + // See https://github.com/Microsoft/vscode/issues/26151 + // Cannot be trusted because the webFrame might take some time + // until it really applies the new zoom level + browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false); +} + +function showContextMenu(e) { + e.preventDefault(); + + const pid = parseInt(e.currentTarget.id); + if (pid && typeof pid === 'number') { + const menu = new remote.Menu(); + menu.append(new remote.MenuItem({ + label: localize('killProcess', "Kill Process"), + click() { + process.kill(pid, 'SIGTERM'); + } + }) + ); + + menu.append(new remote.MenuItem({ + label: localize('forceKillProcess', "Force Kill Process"), + click() { + process.kill(pid, 'SIGKILL'); + } + }) + ); + + menu.popup(remote.getCurrentWindow()); + } +} + +export function startup(data: ProcessExplorerData): void { + applyStyles(data.styles); + applyZoom(data.zoomLevel); + + setInterval(() => listProcesses(remote.process.pid).then(processes => { + processList = getProcessList(processes); + updateProcessInfo(processList); + + const tableRows = document.getElementsByTagName('tr'); + for (let i = 0; i < tableRows.length; i++) { + const tableRow = tableRows[i]; + tableRow.addEventListener('contextmenu', (e) => { + showContextMenu(e); + }); + } + }), 1200); + + + document.onkeydown = (e: KeyboardEvent) => { + const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; + + // Cmd/Ctrl + zooms in + if (cmdOrCtrlKey && e.keyCode === 187) { + applyZoom(webFrame.getZoomLevel() + 1); + } + + // Cmd/Ctrl - zooms out + if (cmdOrCtrlKey && e.keyCode === 189) { + applyZoom(webFrame.getZoomLevel() - 1); + } + }; +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js index 0d9928a8c1..fceb99296a 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js @@ -69,10 +69,10 @@ function main() { const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 6f0c682e8d..d2df85cb04 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -30,10 +30,9 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProper import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; -import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IWindowsService, ActiveWindowManager } from 'vs/platform/windows/common/windows'; import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc'; import { ipcRenderer } from 'electron'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createSharedProcessContributions } from 'vs/code/electron-browser/sharedProcess/contrib/contributions'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; @@ -41,8 +40,8 @@ import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { LocalizationsChannel } from 'vs/platform/localizations/common/localizationsIpc'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { ChoiceChannelClient } from 'vs/platform/dialogs/common/choiceIpc'; +import { DialogChannelClient } from 'vs/platform/dialogs/common/dialogIpc'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -58,28 +57,6 @@ interface ISharedProcessInitData { logLevel: LogLevel; } -class ActiveWindowManager implements IDisposable { - private disposables: IDisposable[] = []; - private _activeWindowId: number; - - constructor( @IWindowsService windowsService: IWindowsService) { - windowsService.onWindowOpen(this.setActiveWindow, this, this.disposables); - windowsService.onWindowFocus(this.setActiveWindow, this, this.disposables); - } - - private setActiveWindow(windowId: number) { - this._activeWindowId = windowId; - } - - public get activeClientId(): string { - return `window:${this._activeWindowId}`; - } - - public dispose() { - this.disposables = dispose(this.disposables); - } -} - const eventPrefix = 'monacoworkbench'; function main(server: Server, initData: ISharedProcessInitData, configuration: ISharedProcessConfiguration): void { @@ -102,13 +79,13 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I services.set(IWindowsService, windowsService); const activeWindowManager = new ActiveWindowManager(windowsService); - const choiceChannel = server.getChannel('choice', { + const dialogChannel = server.getChannel('dialog', { route: () => { - logService.info('Routing choice request to the client', activeWindowManager.activeClientId); + logService.info('Routing dialog request to the client', activeWindowManager.activeClientId); return activeWindowManager.activeClientId; } }); - services.set(IChoiceService, new ChoiceChannelClient(choiceChannel)); + services.set(IDialogService, new DialogChannelClient(dialogChannel)); const instantiationService = new InstantiationService(services); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 5b47f1591d..8a71f00292 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -5,10 +5,10 @@ 'use strict'; -import { app, ipcMain as ipc, BrowserWindow } from 'electron'; +import { app, ipcMain as ipc } from 'electron'; import * as platform from 'vs/base/common/platform'; import { WindowsManager } from 'vs/code/electron-main/windows'; -import { IWindowsService, OpenContext } from 'vs/platform/windows/common/windows'; +import { IWindowsService, OpenContext, ActiveWindowManager } from 'vs/platform/windows/common/windows'; import { WindowsChannel } from 'vs/platform/windows/common/windowsIpc'; import { WindowsService } from 'vs/platform/windows/electron-main/windowsService'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; @@ -29,7 +29,7 @@ import { IStateService } from 'vs/platform/state/common/state'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IURLService } from 'vs/platform/url/common/url'; -import { URLChannel } from 'vs/platform/url/common/urlIpc'; +import { URLHandlerChannelClient, URLServiceChannel } from 'vs/platform/url/common/urlIpc'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc'; @@ -59,6 +59,8 @@ import { IssueChannel } from 'vs/platform/issue/common/issueIpc'; import { IssueService } from 'vs/platform/issue/electron-main/issueService'; import { LogLevelSetterChannel } from 'vs/platform/log/common/logIpc'; import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; +import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener'; +import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver'; export class CodeApplication { @@ -126,7 +128,7 @@ export class CodeApplication { return srcUri.startsWith(URI.file(this.environmentService.appRoot.toLowerCase()).toString()); }; - app.on('web-contents-created', (_event: any, contents) => { + app.on('web-contents-created', (event: any, contents) => { contents.on('will-attach-webview', (event: Electron.Event, webPreferences, params) => { delete webPreferences.preload; webPreferences.nodeIntegration = false; @@ -181,15 +183,15 @@ export class CodeApplication { this.windowsMainService.openNewWindow(OpenContext.DESKTOP); //macOS native tab "+" button }); - ipc.on('vscode:exit', (_event: any, code: number) => { + ipc.on('vscode:exit', (event: any, code: number) => { this.logService.trace('IPC#vscode:exit', code); this.dispose(); this.lifecycleService.kill(code); }); - ipc.on('vscode:fetchShellEnv', (_event: any, windowId: number) => { - const { webContents } = BrowserWindow.fromId(windowId); + ipc.on('vscode:fetchShellEnv', event => { + const webContents = event.sender.webContents; getShellEnvironment().then(shellEnv => { if (!webContents.isDestroyed()) { webContents.send('vscode:acceptShellEnv', shellEnv); @@ -203,7 +205,7 @@ export class CodeApplication { }); }); - ipc.on('vscode:broadcast', (_event: any, windowId: number, broadcast: { channel: string; payload: any; }) => { + ipc.on('vscode:broadcast', (event: any, windowId: number, broadcast: { channel: string; payload: any; }) => { if (this.windowsMainService && broadcast.channel && !isUndefinedOrNull(broadcast.payload)) { this.logService.trace('IPC#vscode:broadcast', broadcast.channel, broadcast.payload); @@ -277,22 +279,34 @@ export class CodeApplication { this.logService.trace(`Resolved machine identifier: ${machineId}`); // Spawn shared process - this.sharedProcess = new SharedProcess(this.environmentService, machineId, this.userEnv, this.logService); - this.toDispose.push(this.sharedProcess); + this.sharedProcess = new SharedProcess(this.environmentService, this.lifecycleService, this.logService, machineId, this.userEnv); this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main')); // Services const appInstantiationService = this.initServices(machineId); - // Setup Auth Handler - const authHandler = appInstantiationService.createInstance(ProxyAuthHandler); - this.toDispose.push(authHandler); + let promise: TPromise<any> = TPromise.as(null); - // Open Windows - appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor)); + // Create driver + if (this.environmentService.driverHandle) { + serveDriver(this.electronIpcServer, this.environmentService.driverHandle, appInstantiationService).then(server => { + this.logService.info('Driver started at:', this.environmentService.driverHandle); + this.toDispose.push(server); + }); + } - // Post Open Windows Tasks - appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor)); + return promise.then(() => { + + // Setup Auth Handler + const authHandler = appInstantiationService.createInstance(ProxyAuthHandler); + this.toDispose.push(authHandler); + + // Open Windows + appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor)); + + // Post Open Windows Tasks + appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor)); + }); }); } @@ -325,7 +339,7 @@ export class CodeApplication { services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, machineId)); services.set(IWindowsService, new SyncDescriptor(WindowsService, this.sharedProcess)); services.set(ILaunchService, new SyncDescriptor(LaunchService)); - services.set(IIssueService, new SyncDescriptor(IssueService, machineId)); + services.set(IIssueService, new SyncDescriptor(IssueService, machineId, this.userEnv)); // Telemtry if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) { @@ -346,16 +360,6 @@ export class CodeApplication { private openFirstWindow(accessor: ServicesAccessor): void { const appInstantiationService = accessor.get(IInstantiationService); - // TODO@Joao: unfold this - this.windowsMainService = accessor.get(IWindowsMainService); - - // TODO@Joao: so ugly... - this.windowsMainService.onWindowsCountChanged(e => { - if (!platform.isMacintosh && e.newCount === 0) { - this.sharedProcess.dispose(); - } - }); - // Register more Main IPC services const launchService = accessor.get(ILaunchService); const launchChannel = new LaunchChannel(launchService); @@ -366,10 +370,6 @@ export class CodeApplication { const updateChannel = new UpdateChannel(updateService); this.electronIpcServer.registerChannel('update', updateChannel); - const urlService = accessor.get(IURLService); - const urlChannel = appInstantiationService.createInstance(URLChannel, urlService); - this.electronIpcServer.registerChannel('url', urlChannel); - const issueService = accessor.get(IIssueService); const issueChannel = new IssueChannel(issueService); this.electronIpcServer.registerChannel('issue', issueChannel); @@ -383,6 +383,10 @@ export class CodeApplication { this.electronIpcServer.registerChannel('windows', windowsChannel); this.sharedProcessClient.done(client => client.registerChannel('windows', windowsChannel)); + const urlService = accessor.get(IURLService); + const urlChannel = new URLServiceChannel(urlService); + this.electronIpcServer.registerChannel('url', urlChannel); + // Log level management const logLevelChannel = new LogLevelSetterChannel(accessor.get(ILogService)); this.electronIpcServer.registerChannel('loglevel', logLevelChannel); @@ -392,15 +396,51 @@ export class CodeApplication { this.lifecycleService.ready(); // Propagate to clients + const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); // TODO@Joao: unfold this + + const args = this.environmentService.args; + + // Create a URL handler which forwards to the last active window + const activeWindowManager = new ActiveWindowManager(windowsService); + const urlHandlerChannel = this.electronIpcServer.getChannel('urlHandler', { route: () => activeWindowManager.activeClientId }); + const multiplexURLHandler = new URLHandlerChannelClient(urlHandlerChannel); + + // On Mac, Code can be running without any open windows, so we must create a window to handle urls, + // if there is none + if (platform.isMacintosh) { + const environmentService = accessor.get(IEnvironmentService); + + urlService.registerHandler({ + async handleURL(uri: URI): TPromise<boolean> { + if (windowsMainService.getWindowCount() === 0) { + const cli = { ...environmentService.args, goto: true }; + const [window] = windowsMainService.open({ context: OpenContext.API, cli, forceEmpty: true }); + + return window.ready().then(() => urlService.open(uri)); + } + + return false; + } + }); + } + + // Register the multiple URL handker + urlService.registerHandler(multiplexURLHandler); + + // Watch Electron URLs and forward them to the UrlService + const urls = args['open-url'] ? args._urls : []; + const urlListener = new ElectronURLListener(urls, urlService, this.windowsMainService); + this.toDispose.push(urlListener); + this.windowsMainService.ready(this.userEnv); // Open our first window - const args = this.environmentService.args; + const macOpenFiles = (<any>global).macOpenFiles as string[]; const context = !!process.env['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; if (args['new-window'] && args._.length === 0) { this.windowsMainService.open({ context, cli: args, forceNewWindow: true, forceEmpty: true, initialStartup: true }); // new window if "-n" was used without paths - } else if (global.macOpenFiles && global.macOpenFiles.length && (!args._ || !args._.length)) { - this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, pathsToOpen: global.macOpenFiles, initialStartup: true }); // mac: open-file event received on startup + } else if (macOpenFiles && macOpenFiles.length && (!args._ || !args._.length)) { + this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, pathsToOpen: macOpenFiles, initialStartup: true }); // mac: open-file event received on startup } else { this.windowsMainService.open({ context, cli: args, forceNewWindow: args['new-window'] || (!args._.length && args['unity-launch']), diffMode: args.diff, initialStartup: true }); // default: read paths from cli } diff --git a/src/vs/code/electron-main/diagnostics.ts b/src/vs/code/electron-main/diagnostics.ts index 0f8186c56d..dd1336376b 100644 --- a/src/vs/code/electron-main/diagnostics.ts +++ b/src/vs/code/electron-main/diagnostics.ts @@ -29,6 +29,7 @@ export interface SystemInfo { VM: string; 'Screen Reader': string; 'Process Argv': string; + 'GPU Status': Electron.GPUFeatureStatus; } export interface ProcessInfo { @@ -92,7 +93,8 @@ export function getSystemInfo(info: IMainProcessInfo): SystemInfo { 'Memory (System)': `${(os.totalmem() / GB).toFixed(2)}GB (${(os.freemem() / GB).toFixed(2)}GB free)`, VM: `${Math.round((virtualMachineHint.value() * 100))}%`, 'Screen Reader': `${app.isAccessibilitySupportEnabled() ? 'yes' : 'no'}`, - 'Process Argv': `${info.mainArguments.join(' ')}` + 'Process Argv': `${info.mainArguments.join(' ')}`, + 'GPU Status': app.getGPUFeatureStatus() }; const cpus = os.cpus(); @@ -208,7 +210,14 @@ function formatLaunchConfigs(configs: WorkspaceStatItem[]): string { return output.join('\n'); } -function formatEnvironment(info: IMainProcessInfo): string { +function expandGPUFeatures(): string { + const gpuFeatures = app.getGPUFeatureStatus(); + const longestFeatureName = Math.max(...Object.keys(gpuFeatures).map(feature => feature.length)); + // Make columns aligned by adding spaces after feature name + return Object.keys(gpuFeatures).map(feature => `${feature}: ${repeat(' ', longestFeatureName - feature.length)} ${gpuFeatures[feature]}`).join('\n '); +} + +export function formatEnvironment(info: IMainProcessInfo): string { const MB = 1024 * 1024; const GB = 1024 * MB; @@ -226,6 +235,7 @@ function formatEnvironment(info: IMainProcessInfo): string { output.push(`VM: ${Math.round((virtualMachineHint.value() * 100))}%`); output.push(`Screen Reader: ${app.isAccessibilitySupportEnabled() ? 'yes' : 'no'}`); output.push(`Process Argv: ${info.mainArguments.join(' ')}`); + output.push(`GPU Status: ${expandGPUFeatures()}`); return output.join('\n'); } diff --git a/src/vs/code/electron-main/keyboard.ts b/src/vs/code/electron-main/keyboard.ts index d1ca8f26c4..b9c2c0c1c4 100644 --- a/src/vs/code/electron-main/keyboard.ts +++ b/src/vs/code/electron-main/keyboard.ts @@ -8,7 +8,7 @@ import * as nativeKeymap from 'native-keymap'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IStateService } from 'vs/platform/state/common/state'; -import Event, { Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { ConfigWatcher } from 'vs/base/node/config'; import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -20,7 +20,7 @@ export class KeyboardLayoutMonitor { public static readonly INSTANCE = new KeyboardLayoutMonitor(); - private _emitter: Emitter<void>; + private readonly _emitter: Emitter<void>; private _registered: boolean; private constructor() { diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index 631b96e977..446bb6bbcd 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -9,14 +9,16 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; import { ILogService } from 'vs/platform/log/common/log'; import { IURLService } from 'vs/platform/url/common/url'; -import { IProcessEnvironment } from 'vs/base/common/platform'; +import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { OpenContext } from 'vs/platform/windows/common/windows'; +import { OpenContext, IWindowSettings } from 'vs/platform/windows/common/windows'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { whenDeleted } from 'vs/base/node/pfs'; import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { Schemas } from 'vs/base/common/network'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import URI from 'vs/base/common/uri'; export const ID = 'launchService'; export const ILaunchService = createDecorator<ILaunchService>(ID); @@ -38,6 +40,24 @@ export interface IMainProcessInfo { windows: IWindowInfo[]; } +function parseOpenUrl(args: ParsedArgs): URI[] { + if (args['open-url'] && args._urls && args._urls.length > 0) { + // --open-url must contain -- followed by the url(s) + // process.argv is used over args._ as args._ are resolved to file paths at this point + return args._urls + .map(url => { + try { + return URI.parse(url); + } catch (err) { + return null; + } + }) + .filter(uri => !!uri); + } + + return []; +} + export interface ILaunchService { _serviceBrand: any; start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void>; @@ -110,14 +130,32 @@ export class LaunchService implements ILaunchService { @IWindowsMainService private windowsMainService: IWindowsMainService, @IURLService private urlService: IURLService, @IWorkspacesMainService private workspacesMainService: IWorkspacesMainService, - @IEnvironmentService private readonly environmentService: IEnvironmentService + @IEnvironmentService private readonly environmentService: IEnvironmentService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { } public start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> { this.logService.trace('Received data from other instance: ', args, userEnv); + const urlsToOpen = parseOpenUrl(args); + // Check early for open-url which is handled in URL service - if (this.shouldOpenUrl(args)) { + if (urlsToOpen.length) { + let whenWindowReady = TPromise.as<any>(null); + + // Create a window if there is none + if (this.windowsMainService.getWindowCount() === 0) { + const window = this.windowsMainService.openNewWindow(OpenContext.DESKTOP)[0]; + whenWindowReady = window.ready(); + } + + // Make sure a window is open, ready to receive the url event + whenWindowReady.then(() => { + for (const url of urlsToOpen) { + this.urlService.open(url); + } + }); + return TPromise.as(null); } @@ -125,28 +163,54 @@ export class LaunchService implements ILaunchService { return this.startOpenWindow(args, userEnv); } - private shouldOpenUrl(args: ParsedArgs): boolean { - if (args['open-url'] && args._urls && args._urls.length > 0) { - // --open-url must contain -- followed by the url(s) - // process.argv is used over args._ as args._ are resolved to file paths at this point - args._urls.forEach(url => this.urlService.open(url)); - - return true; - } - - return false; - } - private startOpenWindow(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> { const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; let usedWindows: ICodeWindow[]; + + // Special case extension development if (!!args.extensionDevelopmentPath) { this.windowsMainService.openExtensionDevelopmentHostWindow({ context, cli: args, userEnv }); - } else if (args._.length === 0 && (args['new-window'] || args['unity-launch'])) { - usedWindows = this.windowsMainService.open({ context, cli: args, userEnv, forceNewWindow: true, forceEmpty: true }); - } else if (args._.length === 0) { - usedWindows = [this.windowsMainService.focusLastActive(args, context)]; - } else { + } + + // Start without file/folder arguments + else if (args._.length === 0) { + let openNewWindow = false; + + // Force new window + if (args['new-window'] || args['unity-launch']) { + openNewWindow = true; + } + + // Force reuse window + else if (args['reuse-window']) { + openNewWindow = false; + } + + // Otherwise check for settings + else { + const windowConfig = this.configurationService.getValue<IWindowSettings>('window'); + const openWithoutArgumentsInNewWindowConfig = (windowConfig && windowConfig.openWithoutArgumentsInNewWindow) || 'default' /* default */; + switch (openWithoutArgumentsInNewWindowConfig) { + case 'on': + openNewWindow = true; + break; + case 'off': + openNewWindow = false; + break; + default: + openNewWindow = !isMacintosh; // prefer to restore running instance on macOS + } + } + + if (openNewWindow) { + usedWindows = this.windowsMainService.open({ context, cli: args, userEnv, forceNewWindow: true, forceEmpty: true }); + } else { + usedWindows = [this.windowsMainService.focusLastActive(args, context)]; + } + } + + // Start with file/folder arguments + else { usedWindows = this.windowsMainService.open({ context, cli: args, diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 7b031fe5ba..026d6297f4 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -34,7 +34,7 @@ import { ConfigurationService } from 'vs/platform/configuration/node/configurati import { IRequestService } from 'vs/platform/request/node/request'; import { RequestService } from 'vs/platform/request/electron-main/requestService'; import { IURLService } from 'vs/platform/url/common/url'; -import { URLService } from 'vs/platform/url/electron-main/urlService'; +import { URLService } from 'vs/platform/url/common/urlService'; import * as fs from 'original-fs'; import { CodeApplication } from 'vs/code/electron-main/app'; import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService'; @@ -48,8 +48,8 @@ import { printDiagnostics } from 'vs/code/electron-main/diagnostics'; import { BufferLogService } from 'vs/platform/log/common/bufferLog'; import { uploadLogs } from 'vs/code/electron-main/logUploader'; import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { ChoiceCliService } from 'vs/platform/dialogs/node/choiceCli'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { CommandLineDialogService } from 'vs/platform/dialogs/node/dialogService'; function createServices(args: ParsedArgs, bufferLogService: BufferLogService): IInstantiationService { const services = new ServiceCollection(); @@ -71,9 +71,9 @@ function createServices(args: ParsedArgs, bufferLogService: BufferLogService): I services.set(IStateService, new SyncDescriptor(StateService)); services.set(IConfigurationService, new SyncDescriptor(ConfigurationService)); services.set(IRequestService, new SyncDescriptor(RequestService)); - services.set(IURLService, new SyncDescriptor(URLService, args['open-url'] ? args._urls : [])); + services.set(IURLService, new SyncDescriptor(URLService)); services.set(IBackupMainService, new SyncDescriptor(BackupMainService)); - services.set(IChoiceService, new SyncDescriptor(ChoiceCliService)); + services.set(IDialogService, new SyncDescriptor(CommandLineDialogService)); return new InstantiationService(services, true); } diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index c22a9bd6f2..d1983a9b27 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -100,7 +100,7 @@ export class CodeMenu { this.windowsMainService.onWindowClose(() => this.updateWorkspaceMenuItems()); // Listen to extension viewlets - ipc.on('vscode:extensionViewlets', (_event: any, rawExtensionViewlets: string) => { + ipc.on('vscode:extensionViewlets', (event: any, rawExtensionViewlets: string) => { let extensionViewlets: IExtensionViewlet[] = []; try { extensionViewlets = JSON.parse(rawExtensionViewlets); @@ -465,7 +465,7 @@ export class CodeMenu { } private getPreferencesMenu(): Electron.MenuItem { - const settings = this.createMenuItem(nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&Settings"), 'workbench.action.openGlobalSettings'); + const settings = this.createMenuItem(nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&Settings"), 'workbench.action.openSettings'); const kebindingSettings = this.createMenuItem(nls.localize({ key: 'miOpenKeymap', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts"), 'workbench.action.openGlobalKeybindings'); // {{SQL CARBON EDIT}} // const keymapExtensions = this.createMenuItem(nls.localize({ key: 'miOpenKeymapExtensions', comment: ['&& denotes a mnemonic'] }, "&&Keymap Extensions"), 'workbench.extensions.action.showRecommendedKeymapExtensions'); @@ -892,6 +892,7 @@ export class CodeMenu { breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miConditionalBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Conditional Breakpoint..."), 'editor.debug.action.conditionalBreakpoint')); breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miColumnBreakpoint', comment: ['&& denotes a mnemonic'] }, "C&&olumn Breakpoint"), 'editor.debug.action.toggleColumnBreakpoint')); breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miFunctionBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Function Breakpoint..."), 'workbench.debug.viewlet.action.addFunctionBreakpointAction')); + breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Logpoint..."), 'editor.debug.action.toggleLogPoint')); const newBreakpoints = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miNewBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&New Breakpoint")), submenu: breakpointsMenu }); const enableAllBreakpoints = this.createMenuItem(nls.localize({ key: 'miEnableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Enable All Breakpoints"), 'workbench.debug.viewlet.action.enableAllBreakpoints'); const disableAllBreakpoints = this.createMenuItem(nls.localize({ key: 'miDisableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Disable A&&ll Breakpoints"), 'workbench.debug.viewlet.action.disableAllBreakpoints'); @@ -980,6 +981,8 @@ export class CodeMenu { } }, false)); + const openProcessExplorer = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")), click: () => this.runActionInRenderer('workbench.action.openProcessExplorer') }); + let reportIssuesItem: Electron.MenuItem = null; if (product.reportIssueUrl) { const label = nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue"); @@ -1042,7 +1045,8 @@ export class CodeMenu { }) : null, (product.licenseUrl || product.privacyStatementUrl) ? __separator__() : null, toggleDevToolsItem, - isWindows && product.quality !== 'stable' ? showAccessibilityOptions : null + openProcessExplorer, + isWindows && product.quality !== 'stable' ? showAccessibilityOptions : null, ]).forEach(item => helpMenu.append(item)); if (!isMacintosh) { @@ -1085,7 +1089,7 @@ export class CodeMenu { } private openAccessibilityOptions(): void { - let win = new BrowserWindow({ + const win = new BrowserWindow({ alwaysOnTop: true, skipTaskbar: true, resizable: false, diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index a1844c077b..9838b08078 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -5,7 +5,6 @@ import { assign } from 'vs/base/common/objects'; import { memoize } from 'vs/base/common/decorators'; -import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { TPromise } from 'vs/base/common/winjs.base'; import { IProcessEnvironment } from 'vs/base/common/platform'; @@ -13,20 +12,22 @@ import { BrowserWindow, ipcMain } from 'electron'; import { ISharedProcess } from 'vs/platform/windows/electron-main/windows'; import { Barrier } from 'vs/base/common/async'; import { ILogService } from 'vs/platform/log/common/log'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; export class SharedProcess implements ISharedProcess { private barrier = new Barrier(); private window: Electron.BrowserWindow; - private disposables: IDisposable[] = []; constructor( - private environmentService: IEnvironmentService, + private readonly environmentService: IEnvironmentService, + private readonly lifecycleService: ILifecycleService, + private readonly logService: ILogService, private readonly machineId: string, private readonly userEnv: IProcessEnvironment, - private readonly logService: ILogService - ) { } + ) { + } @memoize private get _whenReady(): TPromise<void> { @@ -50,16 +51,27 @@ export class SharedProcess implements ISharedProcess { // Prevent the window from dying const onClose = (e: Event) => { + this.logService.trace('SharedProcess#close prevented'); + + // We never allow to close the shared process unless we get explicitly disposed() + e.preventDefault(); + + // Still hide the window though if visible if (this.window.isVisible()) { - e.preventDefault(); this.window.hide(); } }; this.window.on('close', onClose); - this.disposables.push(toDisposable(() => this.window.removeListener('close', onClose))); - this.disposables.push(toDisposable(() => { + this.lifecycleService.onShutdown(() => { + // Shut the shared process down when we are quitting + // + // Note: because we veto the window close, we must first remove our veto. + // Otherwise the application would never quit because the shared process + // window is refusing to close! + // + this.window.removeListener('close', onClose); // Electron seems to crash on Windows without this setTimeout :| setTimeout(() => { @@ -71,7 +83,7 @@ export class SharedProcess implements ISharedProcess { this.window = null; }, 0); - })); + }); return new TPromise<void>((c, e) => { ipcMain.once('handshake:hello', ({ sender }: { sender: any }) => { @@ -111,8 +123,4 @@ export class SharedProcess implements ISharedProcess { this.window.webContents.closeDevTools(); this.window.hide(); } - - dispose(): void { - this.disposables = dispose(this.disposables); - } } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 51144974cf..b7f6972672 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import * as objects from 'vs/base/common/objects'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; import { IStateService } from 'vs/platform/state/common/state'; import { shell, screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage } from 'electron'; @@ -20,35 +20,19 @@ import product from 'vs/platform/node/product'; import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, IRunActionInWindowRequest } from 'vs/platform/windows/common/windows'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; -import { ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { ICommandAction } from 'vs/platform/actions/common/actions'; import { mark, exportEntries } from 'vs/base/common/performance'; import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService'; -export interface IWindowState { - width?: number; - height?: number; - x?: number; - y?: number; - mode?: WindowMode; - display?: number; -} - export interface IWindowCreationOptions { state: IWindowState; extensionDevelopmentPath?: string; isExtensionTestHost?: boolean; } -export enum WindowMode { - Maximized, - Normal, - Minimized, // not used anymore, but also cannot remove due to existing stored UI state (needs migration) - Fullscreen -} - export const defaultWindowState = function (mode = WindowMode.Normal): IWindowState { return { width: 1024, @@ -92,7 +76,7 @@ export class CodeWindow implements ICodeWindow { private toDispose: IDisposable[]; private representedFilename: string; - private whenReadyCallbacks: TValueCallback<CodeWindow>[]; + private whenReadyCallbacks: TValueCallback<ICodeWindow>[]; private currentConfig: IWindowConfiguration; private pendingLoadConfig: IWindowConfiguration; @@ -167,8 +151,16 @@ export class CodeWindow implements ICodeWindow { const windowConfig = this.configurationService.getValue<IWindowSettings>('window'); + if (isMacintosh) { + options.acceptFirstMouse = true; // enabled by default + + if (windowConfig && windowConfig.clickThroughInactive === false) { + options.acceptFirstMouse = false; + } + } + let useNativeTabs = false; - if (windowConfig && windowConfig.nativeTabs) { + if (isMacintosh && windowConfig && windowConfig.nativeTabs === true) { options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs useNativeTabs = true; } @@ -219,15 +211,6 @@ export class CodeWindow implements ICodeWindow { this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any } - // Set relaunch command - if (isWindows && product.win32AppUserModelId && typeof this._win.setAppDetails === 'function') { - this._win.setAppDetails({ - appId: product.win32AppUserModelId, - relaunchCommand: `"${process.execPath}" -n`, - relaunchDisplayName: product.nameLong - }); - } - if (isFullscreenOrMaximized) { this._win.maximize(); @@ -324,8 +307,8 @@ export class CodeWindow implements ICodeWindow { } } - public ready(): TPromise<CodeWindow> { - return new TPromise<CodeWindow>((c) => { + public ready(): TPromise<ICodeWindow> { + return new TPromise<ICodeWindow>((c) => { if (this._readyState === ReadyState.READY) { return c(this); } @@ -443,6 +426,34 @@ export class CodeWindow implements ICodeWindow { // Handle Workspace events this.toDispose.push(this.workspacesMainService.onUntitledWorkspaceDeleted(e => this.onUntitledWorkspaceDeleted(e))); + + // TODO@Ben workaround for https://github.com/Microsoft/vscode/issues/13612 + // It looks like smooth scrolling disappears as soon as the window is minimized + // and maximized again. Touching some window properties "fixes" it, like toggling + // the visibility of the menu. + if (isWindows) { + const windowConfig = this.configurationService.getValue<IWindowSettings>('window'); + if (windowConfig && windowConfig.smoothScrollingWorkaround === true) { + let minimized = false; + + const restoreSmoothScrolling = () => { + if (minimized) { + const visibility = this.getMenuBarVisibility(); + const temporaryVisibility: MenuBarVisibility = (visibility === 'hidden' || visibility === 'toggle') ? 'default' : 'hidden'; + setTimeout(() => { + this.doSetMenuBarVisibility(temporaryVisibility); + this.doSetMenuBarVisibility(visibility); + }, 0); + } + + minimized = false; + }; + + this._win.on('minimize', () => minimized = true); + this._win.on('restore', () => restoreSmoothScrolling()); + this._win.on('maximize', () => restoreSmoothScrolling()); + } + } } private onUntitledWorkspaceDeleted(workspace: IWorkspaceIdentifier): void { @@ -599,7 +610,7 @@ export class CodeWindow implements ICodeWindow { // Perf Counters windowConfiguration.perfEntries = exportEntries(); - windowConfiguration.perfStartTime = global.perfStartTime; + windowConfiguration.perfStartTime = (<any>global).perfStartTime; windowConfiguration.perfWindowLoadTime = Date.now(); // Config (combination of process.argv and window configuration) @@ -826,11 +837,32 @@ export class CodeWindow implements ICodeWindow { return menuBarVisibility; } - public setMenuBarVisibility(visibility: MenuBarVisibility, notify: boolean = true): void { + private setMenuBarVisibility(visibility: MenuBarVisibility, notify: boolean = true): void { if (isMacintosh) { return; // ignore for macOS platform } + if (visibility === 'toggle') { + if (notify) { + this.send('vscode:showInfoMessage', nls.localize('hiddenMenuBar', "You can still access the menu bar by pressing the Alt-key.")); + } + } + + if (visibility === 'hidden') { + // for some weird reason that I have no explanation for, the menu bar is not hiding when calling + // this without timeout (see https://github.com/Microsoft/vscode/issues/19777). there seems to be + // a timing issue with us opening the first window and the menu bar getting created. somehow the + // fact that we want to hide the menu without being able to bring it back via Alt key makes Electron + // still show the menu. Unable to reproduce from a simple Hello World application though... + setTimeout(() => { + this.doSetMenuBarVisibility(visibility); + }); + } else { + this.doSetMenuBarVisibility(visibility); + } + } + + private doSetMenuBarVisibility(visibility: MenuBarVisibility): void { const isFullscreen = this._win.isFullScreen(); switch (visibility) { @@ -847,22 +879,11 @@ export class CodeWindow implements ICodeWindow { case ('toggle'): this._win.setMenuBarVisibility(false); this._win.setAutoHideMenuBar(true); - - if (notify) { - this.send('vscode:showInfoMessage', nls.localize('hiddenMenuBar', "You can still access the menu bar by pressing the Alt-key.")); - } break; case ('hidden'): - // for some weird reason that I have no explanation for, the menu bar is not hiding when calling - // this without timeout (see https://github.com/Microsoft/vscode/issues/19777). there seems to be - // a timing issue with us opening the first window and the menu bar getting created. somehow the - // fact that we want to hide the menu without being able to bring it back via Alt key makes Electron - // still show the menu. Unable to reproduce from a simple Hello World application though... - setTimeout(() => { - this._win.setMenuBarVisibility(false); - this._win.setAutoHideMenuBar(false); - }); + this._win.setMenuBarVisibility(false); + this._win.setAutoHideMenuBar(false); break; } } @@ -907,7 +928,9 @@ export class CodeWindow implements ICodeWindow { } public send(channel: string, ...args: any[]): void { - this._win.webContents.send(channel, ...args); + if (this._win) { + this._win.webContents.send(channel, ...args); + } } public updateTouchBar(groups: ICommandAction[][]): void { diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 02473936fa..f97c2d05a8 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -13,7 +13,7 @@ import { assign, mixin, equals } from 'vs/base/common/objects'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { IStateService } from 'vs/platform/state/common/state'; -import { CodeWindow, IWindowState as ISingleWindowState, defaultWindowState, WindowMode } from 'vs/code/electron-main/window'; +import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences, app } from 'electron'; import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths'; import { ILifecycleService, UnloadReason, IWindowUnloadEvent } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; @@ -21,11 +21,11 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, ReadyState, IPathsToWaitFor, IEnterWorkspaceResult, IMessageBoxResult } from 'vs/platform/windows/common/windows'; import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderPath } from 'vs/code/node/windowsFinder'; -import CommonEvent, { Emitter } from 'vs/base/common/event'; +import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import product from 'vs/platform/node/product'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { isEqual } from 'vs/base/common/paths'; -import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IHistoryMainService } from 'vs/platform/history/common/history'; import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -36,6 +36,7 @@ import { Schemas } from 'vs/base/common/network'; import { normalizeNFC } from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; import { Queue } from 'vs/base/common/async'; +import { exists } from 'vs/base/node/pfs'; enum WindowError { UNRESPONSIVE, @@ -76,7 +77,7 @@ interface IOpenBrowserWindowOptions { filesToWait?: IPathsToWaitFor; forceNewWindow?: boolean; - windowToUse?: CodeWindow; + windowToUse?: ICodeWindow; emptyWindowBackupFolder?: string; } @@ -102,7 +103,7 @@ export class WindowsManager implements IWindowsMainService { private static readonly windowsStateStorageKey = 'windowsState'; - private static WINDOWS: CodeWindow[] = []; + private static WINDOWS: ICodeWindow[] = []; private initialUserEnv: IProcessEnvironment; @@ -112,8 +113,8 @@ export class WindowsManager implements IWindowsMainService { private dialogs: Dialogs; private workspacesManager: WorkspacesManager; - private _onWindowReady = new Emitter<CodeWindow>(); - onWindowReady: CommonEvent<CodeWindow> = this._onWindowReady.event; + private _onWindowReady = new Emitter<ICodeWindow>(); + onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event; private _onWindowClose = new Emitter<number>(); onWindowClose: CommonEvent<number> = this._onWindowClose.event; @@ -121,8 +122,8 @@ export class WindowsManager implements IWindowsMainService { private _onWindowLoad = new Emitter<number>(); onWindowLoad: CommonEvent<number> = this._onWindowLoad.event; - private _onActiveWindowChanged = new Emitter<CodeWindow>(); - onActiveWindowChanged: CommonEvent<CodeWindow> = this._onActiveWindowChanged.event; + private _onActiveWindowChanged = new Emitter<ICodeWindow>(); + onActiveWindowChanged: CommonEvent<ICodeWindow> = this._onActiveWindowChanged.event; private _onWindowReload = new Emitter<number>(); onWindowReload: CommonEvent<number> = this._onWindowReload.event; @@ -168,7 +169,7 @@ export class WindowsManager implements IWindowsMainService { }); // React to workbench loaded events from windows - ipc.on('vscode:workbenchLoaded', (_event: any, windowId: number) => { + ipc.on('vscode:workbenchLoaded', (event: any, windowId: number) => { this.logService.trace('IPC#vscode-workbenchLoaded'); const win = this.getWindowById(windowId); @@ -193,8 +194,8 @@ export class WindowsManager implements IWindowsMainService { // Handle various lifecycle events around windows this.lifecycleService.onBeforeWindowUnload(e => this.onBeforeWindowUnload(e)); - this.lifecycleService.onBeforeWindowClose(win => this.onBeforeWindowClose(win as CodeWindow)); - this.lifecycleService.onBeforeQuit(() => this.onBeforeQuit()); + this.lifecycleService.onBeforeWindowClose(win => this.onBeforeWindowClose(win as ICodeWindow)); + this.lifecycleService.onBeforeShutdown(() => this.onBeforeShutdown()); this.onWindowsCountChanged(e => { if (e.newCount - e.oldCount > 0) { // clear last closed window state when a new window opens. this helps on macOS where @@ -205,12 +206,12 @@ export class WindowsManager implements IWindowsMainService { }); } - // Note that onBeforeQuit() and onBeforeWindowClose() are fired in different order depending on the OS: + // Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS: // - macOS: since the app will not quit when closing the last window, you will always first get - // the onBeforeQuit() event followed by N onbeforeWindowClose() events for each window + // the onBeforeShutdown() event followed by N onbeforeWindowClose() events for each window // - other: on other OS, closing the last window will quit the app so the order depends on the // user interaction: closing the last window will first trigger onBeforeWindowClose() - // and then onBeforeQuit(). Using the quit action however will first issue onBeforeQuit() + // and then onBeforeShutdown(). Using the quit action however will first issue onBeforeShutdown() // and then onBeforeWindowClose(). // // Here is the behaviour on different OS dependig on action taken (Electron 1.7.x): @@ -219,30 +220,30 @@ export class WindowsManager implements IWindowsMainService { // - quit(N): quit application with N windows opened // - close(1): close one window via the window close button // - closeAll: close all windows via the taskbar command - // - onBeforeQuit(N): number of windows reported in this event handler + // - onBeforeShutdown(N): number of windows reported in this event handler // - onBeforeWindowClose(N, M): number of windows reported and quitRequested boolean in this event handler // // macOS - // - quit(1): onBeforeQuit(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeQuit(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) - // - quit(0): onBeforeQuit(0) + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - quit(0): onBeforeShutdown(0) // - close(1): onBeforeWindowClose(1, false) // // Windows - // - quit(1): onBeforeQuit(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeQuit(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) // - close(1): onBeforeWindowClose(2, false)[not last window] - // - close(1): onBeforeWindowClose(1, false), onBeforequit(0)[last window] - // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeQuit(0) + // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] + // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) // // Linux - // - quit(1): onBeforeQuit(1), onBeforeWindowClose(1, true) - // - quit(2): onBeforeQuit(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) + // - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true) + // - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true) // - close(1): onBeforeWindowClose(2, false)[not last window] - // - close(1): onBeforeWindowClose(1, false), onBeforequit(0)[last window] - // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeQuit(0) + // - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window] + // - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0) // - private onBeforeQuit(): void { + private onBeforeShutdown(): void { const currentWindowsState: IWindowsState = { openedWindows: [], lastPluginDevelopmentHostWindow: this.windowsState.lastPluginDevelopmentHostWindow, @@ -280,9 +281,9 @@ export class WindowsManager implements IWindowsMainService { this.stateService.setItem(WindowsManager.windowsStateStorageKey, currentWindowsState); } - // See note on #onBeforeQuit() for details how these events are flowing - private onBeforeWindowClose(win: CodeWindow): void { - if (this.lifecycleService.isQuitRequested()) { + // See note on #onBeforeShutdown() for details how these events are flowing + private onBeforeWindowClose(win: ICodeWindow): void { + if (this.lifecycleService.isQuitRequested) { return; // during quit, many windows close in parallel so let it be handled in the before-quit handler } @@ -313,7 +314,7 @@ export class WindowsManager implements IWindowsMainService { } } - private toWindowState(win: CodeWindow): IWindowState { + private toWindowState(win: ICodeWindow): IWindowState { return { workspace: win.openedWorkspace, folderPath: win.openedFolderPath, @@ -322,7 +323,7 @@ export class WindowsManager implements IWindowsMainService { }; } - public open(openConfig: IOpenConfiguration): CodeWindow[] { + public open(openConfig: IOpenConfiguration): ICodeWindow[] { openConfig = this.validateOpenConfig(openConfig); let pathsToOpen = this.getPathsToOpen(openConfig); @@ -481,7 +482,7 @@ export class WindowsManager implements IWindowsMainService { filesToWait: IPathsToWaitFor, foldersToAdd: IPath[] ) { - const usedWindows: CodeWindow[] = []; + const usedWindows: ICodeWindow[] = []; // Settings can decide if files/folders open in new window or not let { openFolderInNewWindow, openFilesInNewWindow } = this.shouldOpenNewWindow(openConfig); @@ -536,7 +537,7 @@ export class WindowsManager implements IWindowsMainService { else { // Do open files - usedWindows.push(this.doOpenFilesInExistingWindow(bestWindowOrFolder, filesToOpen, filesToCreate, filesToDiff, filesToWait)); + usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, bestWindowOrFolder, filesToOpen, filesToCreate, filesToDiff, filesToWait)); // Reset these because we handled them filesToOpen = []; @@ -582,7 +583,7 @@ export class WindowsManager implements IWindowsMainService { const windowOnWorkspace = windowsOnWorkspace[0]; // Do open files - usedWindows.push(this.doOpenFilesInExistingWindow(windowOnWorkspace, filesToOpen, filesToCreate, filesToDiff, filesToWait)); + usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnWorkspace, filesToOpen, filesToCreate, filesToDiff, filesToWait)); // Reset these because we handled them filesToOpen = []; @@ -622,7 +623,7 @@ export class WindowsManager implements IWindowsMainService { const windowOnFolderPath = windowsOnFolderPath[0]; // Do open files - usedWindows.push(this.doOpenFilesInExistingWindow(windowOnFolderPath, filesToOpen, filesToCreate, filesToDiff, filesToWait)); + usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnFolderPath, filesToOpen, filesToCreate, filesToDiff, filesToWait)); // Reset these because we handled them filesToOpen = []; @@ -694,17 +695,18 @@ export class WindowsManager implements IWindowsMainService { return arrays.distinct(usedWindows); } - private doOpenFilesInExistingWindow(window: CodeWindow, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[], filesToWait: IPathsToWaitFor): CodeWindow { + private doOpenFilesInExistingWindow(configuration: IOpenConfiguration, window: ICodeWindow, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[], filesToWait: IPathsToWaitFor): ICodeWindow { window.focus(); // make sure window has focus window.ready().then(readyWindow => { - readyWindow.send('vscode:openFiles', { filesToOpen, filesToCreate, filesToDiff, filesToWait }); + const termProgram = configuration.userEnv ? configuration.userEnv['TERM_PROGRAM'] : void 0; + readyWindow.send('vscode:openFiles', { filesToOpen, filesToCreate, filesToDiff, filesToWait, termProgram }); }); return window; } - private doAddFoldersToExistingWidow(window: CodeWindow, foldersToAdd: IPath[]): CodeWindow { + private doAddFoldersToExistingWidow(window: ICodeWindow, foldersToAdd: IPath[]): ICodeWindow { window.focus(); // make sure window has focus window.ready().then(readyWindow => { @@ -714,7 +716,7 @@ export class WindowsManager implements IWindowsMainService { return window; } - private doOpenFolderOrWorkspace(openConfig: IOpenConfiguration, folderOrWorkspace: IPathToOpen, openInNewWindow: boolean, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[], filesToWait: IPathsToWaitFor, windowToUse?: CodeWindow): CodeWindow { + private doOpenFolderOrWorkspace(openConfig: IOpenConfiguration, folderOrWorkspace: IPathToOpen, openInNewWindow: boolean, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[], filesToWait: IPathsToWaitFor, windowToUse?: ICodeWindow): ICodeWindow { const browserWindow = this.openInBrowserWindow({ userEnv: openConfig.userEnv, cli: openConfig.cli, @@ -981,10 +983,22 @@ export class WindowsManager implements IWindowsMainService { if (openConfig.forceNewWindow || openConfig.forceReuseWindow) { openFilesInNewWindow = openConfig.forceNewWindow && !openConfig.forceReuseWindow; } else { - if (openConfig.context === OpenContext.DOCK) { - openFilesInNewWindow = true; // only on macOS do we allow to open files in a new window if this is triggered via DOCK context + + // macOS: by default we open files in a new window if this is triggered via DOCK context + if (isMacintosh) { + if (openConfig.context === OpenContext.DOCK) { + openFilesInNewWindow = true; + } } + // Linux/Windows: by default we open files in the new window unless triggered via DIALOG or MENU context + else { + if (openConfig.context !== OpenContext.DIALOG && openConfig.context !== OpenContext.MENU) { + openFilesInNewWindow = true; + } + } + + // finally check for overrides of default if (!openConfig.cli.extensionDevelopmentPath && (openFilesInNewWindowConfig === 'on' || openFilesInNewWindowConfig === 'off')) { openFilesInNewWindow = (openFilesInNewWindowConfig === 'on'); } @@ -1024,7 +1038,7 @@ export class WindowsManager implements IWindowsMainService { this.open({ context: openConfig.context, cli: openConfig.cli, forceNewWindow: true, forceEmpty: openConfig.cli._.length === 0, userEnv: openConfig.userEnv }); } - private openInBrowserWindow(options: IOpenBrowserWindowOptions): CodeWindow { + private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow { // Build IWindowConfiguration from config and options const configuration: IWindowConfiguration = mixin({}, options.cli); // inherit all properties from CLI @@ -1049,7 +1063,7 @@ export class WindowsManager implements IWindowsMainService { configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupFolder); } - let window: CodeWindow; + let window: ICodeWindow; if (!options.forceNewWindow) { window = options.windowToUse || this.getLastActiveWindow(); if (window) { @@ -1217,9 +1231,12 @@ export class WindowsManager implements IWindowsMainService { } } + // Compute x/y based on display bounds + // Note: important to use Math.round() because Electron does not seem to be too happy about + // display coordinates that are not absolute numbers. let state = defaultWindowState() as INewWindowState; - state.x = displayToUse.bounds.x + (displayToUse.bounds.width / 2) - (state.width / 2); - state.y = displayToUse.bounds.y + (displayToUse.bounds.height / 2) - (state.height / 2); + state.x = Math.round(displayToUse.bounds.x + (displayToUse.bounds.width / 2) - (state.width / 2)); + state.y = Math.round(displayToUse.bounds.y + (displayToUse.bounds.height / 2) - (state.height / 2)); // Check for newWindowDimensions setting and adjust accordingly const windowConfig = this.configurationService.getValue<IWindowSettings>('window'); @@ -1266,7 +1283,7 @@ export class WindowsManager implements IWindowsMainService { return state; } - public reload(win: CodeWindow, cli?: ParsedArgs): void { + public reload(win: ICodeWindow, cli?: ParsedArgs): void { // Only reload when the window has not vetoed this this.lifecycleService.unload(win, UnloadReason.RELOAD).done(veto => { @@ -1279,22 +1296,22 @@ export class WindowsManager implements IWindowsMainService { }); } - public closeWorkspace(win: CodeWindow): void { + public closeWorkspace(win: ICodeWindow): void { this.openInBrowserWindow({ cli: this.environmentService.args, windowToUse: win }); } - public saveAndEnterWorkspace(win: CodeWindow, path: string): TPromise<IEnterWorkspaceResult> { + public saveAndEnterWorkspace(win: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> { return this.workspacesManager.saveAndEnterWorkspace(win, path).then(result => this.doEnterWorkspace(win, result)); } - public createAndEnterWorkspace(win: CodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> { + public createAndEnterWorkspace(win: ICodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> { return this.workspacesManager.createAndEnterWorkspace(win, folders, path).then(result => this.doEnterWorkspace(win, result)); } - private doEnterWorkspace(win: CodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult { + private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult { // Mark as recently opened this.historyMainService.addRecentlyOpened([result.workspace], []); @@ -1346,7 +1363,7 @@ export class WindowsManager implements IWindowsMainService { })); } - public focusLastActive(cli: ParsedArgs, context: OpenContext): CodeWindow { + public focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { const lastActive = this.getLastActiveWindow(); if (lastActive) { lastActive.focus(); @@ -1358,12 +1375,12 @@ export class WindowsManager implements IWindowsMainService { return this.open({ context, cli, forceEmpty: true })[0]; } - public getLastActiveWindow(): CodeWindow { + public getLastActiveWindow(): ICodeWindow { return getLastActiveWindow(WindowsManager.WINDOWS); } - public openNewWindow(context: OpenContext): void { - this.open({ context, cli: this.environmentService.args, forceNewWindow: true, forceEmpty: true }); + public openNewWindow(context: OpenContext): ICodeWindow[] { + return this.open({ context, cli: this.environmentService.args, forceNewWindow: true, forceEmpty: true }); } public waitForWindowCloseOrLoad(windowId: number): TPromise<void> { @@ -1400,7 +1417,7 @@ export class WindowsManager implements IWindowsMainService { }); } - public getFocusedWindow(): CodeWindow { + public getFocusedWindow(): ICodeWindow { const win = BrowserWindow.getFocusedWindow(); if (win) { return this.getWindowById(win.id); @@ -1409,7 +1426,7 @@ export class WindowsManager implements IWindowsMainService { return null; } - public getWindowById(windowId: number): CodeWindow { + public getWindowById(windowId: number): ICodeWindow { const res = WindowsManager.WINDOWS.filter(w => w.id === windowId); if (res && res.length === 1) { return res[0]; @@ -1418,7 +1435,7 @@ export class WindowsManager implements IWindowsMainService { return null; } - public getWindows(): CodeWindow[] { + public getWindows(): ICodeWindow[] { return WindowsManager.WINDOWS; } @@ -1426,7 +1443,7 @@ export class WindowsManager implements IWindowsMainService { return WindowsManager.WINDOWS.length; } - private onWindowError(window: CodeWindow, error: WindowError): void { + private onWindowError(window: ICodeWindow, error: WindowError): void { this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive'); // Unresponsive @@ -1476,7 +1493,7 @@ export class WindowsManager implements IWindowsMainService { } } - private onWindowClosed(win: CodeWindow): void { + private onWindowClosed(win: ICodeWindow): void { // Tell window win.dispose(); @@ -1524,6 +1541,7 @@ export class WindowsManager implements IWindowsMainService { if (!internalOptions.telemetryEventName) { if (pickFolders && pickFiles) { + // __GDPR__TODO__ classify event internalOptions.telemetryEventName = 'openFileFolder'; } else if (pickFolders) { internalOptions.telemetryEventName = 'openFolder'; @@ -1535,15 +1553,15 @@ export class WindowsManager implements IWindowsMainService { this.dialogs.pickAndOpen(internalOptions); } - public showMessageBox(options: Electron.MessageBoxOptions, win?: CodeWindow): TPromise<IMessageBoxResult> { + public showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): TPromise<IMessageBoxResult> { return this.dialogs.showMessageBox(options, win); } - public showSaveDialog(options: Electron.SaveDialogOptions, win?: CodeWindow): TPromise<string> { + public showSaveDialog(options: Electron.SaveDialogOptions, win?: ICodeWindow): TPromise<string> { return this.dialogs.showSaveDialog(options, win); } - public showOpenDialog(options: Electron.OpenDialogOptions, win?: CodeWindow): TPromise<string[]> { + public showOpenDialog(options: Electron.OpenDialogOptions, win?: ICodeWindow): TPromise<string[]> { return this.dialogs.showOpenDialog(options, win); } @@ -1684,6 +1702,7 @@ class Dialogs { } public showSaveDialog(options: Electron.SaveDialogOptions, window?: ICodeWindow): TPromise<string> { + function normalizePath(path: string): string { if (path && isMacintosh) { path = normalizeNFC(path); // normalize paths returned from the OS @@ -1702,6 +1721,7 @@ class Dialogs { } public showOpenDialog(options: Electron.OpenDialogOptions, window?: ICodeWindow): TPromise<string[]> { + function normalizePaths(paths: string[]): string[] { if (paths && paths.length > 0 && isMacintosh) { paths = paths.map(path => normalizeNFC(path)); // normalize paths returned from the OS @@ -1712,8 +1732,22 @@ class Dialogs { return this.getDialogQueue(window).queue(() => { return new TPromise((c, e) => { - dialog.showOpenDialog(window ? window.win : void 0, options, paths => { - c(normalizePaths(paths)); + + // Ensure the path exists (if provided) + let validatePathPromise: TPromise<void> = TPromise.as(void 0); + if (options.defaultPath) { + validatePathPromise = exists(options.defaultPath).then(exists => { + if (!exists) { + options.defaultPath = void 0; + } + }); + } + + // Show dialog and wrap as promise + validatePathPromise.then(() => { + dialog.showOpenDialog(window ? window.win : void 0, options, paths => { + c(normalizePaths(paths)); + }); }); }); }); @@ -1730,7 +1764,7 @@ class WorkspacesManager { ) { } - public saveAndEnterWorkspace(window: CodeWindow, path: string): TPromise<IEnterWorkspaceResult> { + public saveAndEnterWorkspace(window: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> { if (!window || !window.win || window.readyState !== ReadyState.READY || !window.openedWorkspace || !path || !this.isValidTargetWorkspacePath(window, path)) { return TPromise.as(null); // return early if the window is not ready or disposed or does not have a workspace } @@ -1738,7 +1772,7 @@ class WorkspacesManager { return this.doSaveAndOpenWorkspace(window, window.openedWorkspace, path); } - public createAndEnterWorkspace(window: CodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> { + public createAndEnterWorkspace(window: ICodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> { if (!window || !window.win || window.readyState !== ReadyState.READY) { return TPromise.as(null); // return early if the window is not ready or disposed } @@ -1755,7 +1789,7 @@ class WorkspacesManager { } - private isValidTargetWorkspacePath(window: CodeWindow, path?: string): TPromise<boolean> { + private isValidTargetWorkspacePath(window: ICodeWindow, path?: string): TPromise<boolean> { if (!path) { return TPromise.wrap(true); } @@ -1781,7 +1815,7 @@ class WorkspacesManager { return TPromise.wrap(true); // OK } - private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise<IEnterWorkspaceResult> { + private doSaveAndOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise<IEnterWorkspaceResult> { let savePromise: TPromise<IWorkspaceIdentifier>; if (path) { savePromise = this.workspacesMainService.saveWorkspace(workspace, path); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 1bb42e5222..e56a122d65 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -36,8 +36,8 @@ import { StateService } from 'vs/platform/state/node/stateService'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { ILogService, getLogLevel } from 'vs/platform/log/common/log'; import { isPromiseCanceledError } from 'vs/base/common/errors'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { ChoiceCliService } from 'vs/platform/dialogs/node/choiceCli'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { CommandLineDialogService } from 'vs/platform/dialogs/node/dialogService'; const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id); const notInstalled = (id: string) => localize('notInstalled', "Extension '{0}' is not installed.", id); @@ -144,15 +144,15 @@ class Main { return this.extensionManagementService.installFromGallery(extension) .then( - () => console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)), - error => { - if (isPromiseCanceledError(error)) { - console.log(localize('cancelVsixInstall', "Cancelled installing Extension '{0}'.", id)); - return null; - } else { - return TPromise.wrapError(error); - } - }); + () => console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)), + error => { + if (isPromiseCanceledError(error)) { + console.log(localize('cancelVsixInstall', "Cancelled installing Extension '{0}'.", id)); + return null; + } else { + return TPromise.wrapError(error); + } + }); }); }); }); @@ -219,7 +219,7 @@ export function main(argv: ParsedArgs): TPromise<void> { services.set(IRequestService, new SyncDescriptor(RequestService)); services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); - services.set(IChoiceService, new SyncDescriptor(ChoiceCliService)); + services.set(IDialogService, new SyncDescriptor(CommandLineDialogService)); if (isBuilt && !extensionDevelopmentPath && !envService.args['disable-telemetry'] && product.enableTelemetry) { const appenders: AppInsightsAppender[] = []; diff --git a/src/vs/code/node/windowsFinder.ts b/src/vs/code/node/windowsFinder.ts index 90376b586c..6f54221d00 100644 --- a/src/vs/code/node/windowsFinder.ts +++ b/src/vs/code/node/windowsFinder.ts @@ -5,8 +5,6 @@ 'use strict'; -import * as path from 'path'; -import * as fs from 'fs'; import * as platform from 'vs/base/common/platform'; import * as paths from 'vs/base/common/paths'; import { OpenContext } from 'vs/platform/windows/common/windows'; @@ -35,22 +33,9 @@ export interface IBestWindowOrFolderOptions<W extends ISimpleWindow> { export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, codeSettingsFolder, workspaceResolver }: IBestWindowOrFolderOptions<W>): W | string { if (!newWindow && filePath && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) { const windowOnFilePath = findWindowOnFilePath(windows, filePath, workspaceResolver); - - // 1) window wins if it has a workspace opened - if (windowOnFilePath && !!windowOnFilePath.openedWorkspace) { + if (windowOnFilePath) { return windowOnFilePath; } - - // 2) window wins if it has a folder opened that is more specific than settings folder - const folderWithCodeSettings = !reuseWindow && findFolderWithCodeSettings(filePath, userHome, codeSettingsFolder); - if (windowOnFilePath && !(folderWithCodeSettings && folderWithCodeSettings.length > windowOnFilePath.openedFolderPath.length)) { - return windowOnFilePath; - } - - // 3) finally return path to folder with settings - if (folderWithCodeSettings) { - return folderWithCodeSettings; - } } return !newWindow ? getLastActiveWindow(windows) : null; @@ -77,41 +62,6 @@ function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], filePath: s return null; } -function findFolderWithCodeSettings(filePath: string, userHome?: string, codeSettingsFolder?: string): string { - let folder = path.dirname(paths.normalize(filePath, true)); - let homeFolder = userHome && paths.normalize(userHome, true); - if (!platform.isLinux) { - homeFolder = homeFolder && homeFolder.toLowerCase(); - } - - let previous = null; - while (folder !== previous) { - if (hasCodeSettings(folder, homeFolder, codeSettingsFolder)) { - return folder; - } - - previous = folder; - folder = path.dirname(folder); - } - - return null; -} - -// {{SQL CARBON EDIT}} -function hasCodeSettings(folder: string, normalizedUserHome?: string, codeSettingsFolder = '.sqlops') { - try { - if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) { - return fs.statSync(path.join(folder, codeSettingsFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions - } - - return fs.statSync(path.join(folder, codeSettingsFolder)).isDirectory(); - } catch (err) { - // assume impossible to access - } - - return false; -} - export function getLastActiveWindow<W extends ISimpleWindow>(windows: W[]): W { const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime)); diff --git a/src/vs/code/test/node/argv.test.ts b/src/vs/code/test/node/argv.test.ts index ab0c4acc7f..94c92eeddd 100644 --- a/src/vs/code/test/node/argv.test.ts +++ b/src/vs/code/test/node/argv.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; import { formatOptions } from 'vs/platform/environment/node/argv'; suite('formatOptions', () => { diff --git a/src/vs/code/test/node/fixtures/vscode_folder/_vscode/keepfolder.txt b/src/vs/code/test/node/fixtures/vscode_folder/_vscode/settings.json similarity index 100% rename from src/vs/code/test/node/fixtures/vscode_folder/_vscode/keepfolder.txt rename to src/vs/code/test/node/fixtures/vscode_folder/_vscode/settings.json diff --git a/src/vs/code/test/node/fixtures/vscode_folder/nested_vscode_folder/_vscode/keepfolder.txt b/src/vs/code/test/node/fixtures/vscode_folder/nested_vscode_folder/_vscode/settings.json similarity index 100% rename from src/vs/code/test/node/fixtures/vscode_folder/nested_vscode_folder/_vscode/keepfolder.txt rename to src/vs/code/test/node/fixtures/vscode_folder/nested_vscode_folder/_vscode/settings.json diff --git a/src/vs/code/test/node/windowsFinder.test.ts b/src/vs/code/test/node/windowsFinder.test.ts index dee19f37d7..bbb7e7d2f9 100644 --- a/src/vs/code/test/node/windowsFinder.test.ts +++ b/src/vs/code/test/node/windowsFinder.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import assert = require('assert'); -import path = require('path'); +import * as assert from 'assert'; +import * as path from 'path'; import { findBestWindowOrFolderForFile, ISimpleWindow, IBestWindowOrFolderOptions } from 'vs/code/node/windowsFinder'; import { OpenContext } from 'vs/platform/windows/common/windows'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; @@ -48,25 +48,22 @@ suite('WindowsFinder', () => { })), null); assert.equal(findBestWindowOrFolderForFile(options({ filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'), - newWindow: true // We assume this implies 'editor' work mode, might need separate CLI option later. + newWindow: true })), null); assert.equal(findBestWindowOrFolderForFile(options({ filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'), - reuseWindow: true // We assume this implies 'editor' work mode, might need separate CLI option later. + reuseWindow: true })), null); assert.equal(findBestWindowOrFolderForFile(options({ filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'), context: OpenContext.API })), null); - }); - - test('New window with folder when no windows exist', () => { assert.equal(findBestWindowOrFolderForFile(options({ filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt') - })), path.join(fixturesFolder, 'vscode_folder')); + })), null); assert.equal(findBestWindowOrFolderForFile(options({ filePath: path.join(fixturesFolder, 'vscode_folder', 'new_folder', 'new_file.txt') - })), path.join(fixturesFolder, 'vscode_folder')); + })), null); }); test('New window without folder when windows exist', () => { @@ -106,19 +103,11 @@ suite('WindowsFinder', () => { windows, filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt') })), vscodeFolderWindow); - }); - - test('Existing window wins over vscode folder if more specific', () => { const window = { lastFocusTime: 1, openedFolderPath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder') }; assert.equal(findBestWindowOrFolderForFile(options({ windows: [window], filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt') })), window); - // check - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window], - filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder2', 'subfolder', 'file.txt') - })), path.join(fixturesFolder, 'vscode_folder')); }); test('More specific existing window wins', () => { @@ -130,37 +119,6 @@ suite('WindowsFinder', () => { })), nestedFolderWindow); }); - test('VSCode folder wins over existing window if more specific', () => { - const window = { lastFocusTime: 1, openedFolderPath: path.join(fixturesFolder, 'vscode_folder') }; - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window], - filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder', 'subfolder', 'file.txt') - })), path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder')); - // check - assert.equal(findBestWindowOrFolderForFile(options({ - windows: [window], - filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt') - })), window); - }); - - test('More specific VSCode folder wins', () => { - assert.equal(findBestWindowOrFolderForFile(options({ - filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder', 'subfolder', 'file.txt') - })), path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder')); - }); - - test('VSCode folder in home folder needs settings.json', () => { - // Because ~/.vscode/extensions is used for extensions, ~/.vscode is not enough as a hint. - assert.equal(findBestWindowOrFolderForFile(options({ - filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'), - userHome: path.join(fixturesFolder, 'vscode_folder') - })), null); - assert.equal(findBestWindowOrFolderForFile(options({ - filePath: path.join(fixturesFolder, 'vscode_home_folder', 'file.txt'), - userHome: path.join(fixturesFolder, 'vscode_home_folder') - })), path.join(fixturesFolder, 'vscode_home_folder')); - }); - test('Workspace folder wins', () => { const window = { lastFocusTime: 1, openedWorkspace: testWorkspace }; assert.equal(findBestWindowOrFolderForFile(options({ diff --git a/src/vs/editor/browser/codeEditor.ts b/src/vs/editor/browser/codeEditor.ts index 0dea4cd91e..58d616bffd 100644 --- a/src/vs/editor/browser/codeEditor.ts +++ b/src/vs/editor/browser/codeEditor.ts @@ -12,6 +12,7 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { EditorAction, EditorExtensionsRegistry, IEditorContributionCtor } from 'vs/editor/browser/editorExtensions'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; export class CodeEditor extends CodeEditorWidget { @@ -22,9 +23,10 @@ export class CodeEditor extends CodeEditorWidget { @ICodeEditorService codeEditorService: ICodeEditorService, @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService ) { - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService); + super(domElement, options, false, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService); } protected _getContributions(): IEditorContributionCtor[] { diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index c69810775b..c2757ab891 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import * as browser from 'vs/base/browser/browser'; @@ -102,7 +102,7 @@ class CSSBasedConfiguration extends Disposable { private _evictUntrustedReadingsTimeout: number; private _onDidChange = this._register(new Emitter<void>()); - public onDidChange: Event<void> = this._onDidChange.event; + public readonly onDidChange: Event<void> = this._onDidChange.event; constructor() { super(); @@ -276,8 +276,21 @@ class CSSBasedConfiguration extends Disposable { export class Configuration extends CommonEditorConfiguration { + private static _massageFontFamily(fontFamily: string): string { + if (/[,"']/.test(fontFamily)) { + // Looks like the font family might be already escaped + return fontFamily; + } + if (/[+ ]/.test(fontFamily)) { + // Wrap a font family using + or <space> with quotes + return `"${fontFamily}"`; + } + + return fontFamily; + } + public static applyFontInfoSlow(domNode: HTMLElement, fontInfo: BareFontInfo): void { - domNode.style.fontFamily = fontInfo.fontFamily; + domNode.style.fontFamily = Configuration._massageFontFamily(fontInfo.fontFamily); domNode.style.fontWeight = fontInfo.fontWeight; domNode.style.fontSize = fontInfo.fontSize + 'px'; domNode.style.lineHeight = fontInfo.lineHeight + 'px'; @@ -285,7 +298,7 @@ export class Configuration extends CommonEditorConfiguration { } public static applyFontInfo(domNode: FastDomNode<HTMLElement>, fontInfo: BareFontInfo): void { - domNode.setFontFamily(fontInfo.fontFamily); + domNode.setFontFamily(Configuration._massageFontFamily(fontInfo.fontFamily)); domNode.setFontWeight(fontInfo.fontWeight); domNode.setFontSize(fontInfo.fontSize); domNode.setLineHeight(fontInfo.lineHeight); @@ -349,7 +362,7 @@ export class Configuration extends CommonEditorConfiguration { extraEditorClassName: this._getExtraEditorClassName(), outerWidth: this._elementSizeObserver.getWidth(), outerHeight: this._elementSizeObserver.getHeight(), - emptySelectionClipboard: browser.isWebKit, + emptySelectionClipboard: browser.isWebKit || browser.isFirefox, pixelRatio: browser.getPixelRatio(), zoomLevel: browser.getZoomLevel(), accessibilitySupport: browser.getAccessibilitySupport() diff --git a/src/vs/editor/browser/controller/coreCommands.ts b/src/vs/editor/browser/controller/coreCommands.ts index 48fecb8a27..8e8ce234e3 100644 --- a/src/vs/editor/browser/controller/coreCommands.ts +++ b/src/vs/editor/browser/controller/coreCommands.ts @@ -325,7 +325,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.LeftArrow, linux: { primary: 0 } } @@ -344,7 +344,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.RightArrow, linux: { primary: 0 } } @@ -376,7 +376,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.UpArrow, linux: { primary: 0 } } @@ -388,7 +388,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.PageUp, linux: { primary: 0 } } @@ -414,7 +414,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.DownArrow, linux: { primary: 0 } } @@ -426,7 +426,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.PageDown, linux: { primary: 0 } } @@ -502,7 +502,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.LeftArrow, mac: { primary: KeyCode.LeftArrow, secondary: [KeyMod.WinCtrl | KeyCode.KEY_B] } } @@ -519,7 +519,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.LeftArrow } })); @@ -535,7 +535,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.RightArrow, mac: { primary: KeyCode.RightArrow, secondary: [KeyMod.WinCtrl | KeyCode.KEY_F] } } @@ -552,7 +552,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.RightArrow } })); @@ -568,7 +568,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.UpArrow, mac: { primary: KeyCode.UpArrow, secondary: [KeyMod.WinCtrl | KeyCode.KEY_P] } } @@ -585,7 +585,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.UpArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow], mac: { primary: KeyMod.Shift | KeyCode.UpArrow }, @@ -604,7 +604,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.PageUp } })); @@ -620,7 +620,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.PageUp } })); @@ -636,7 +636,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.DownArrow, mac: { primary: KeyCode.DownArrow, secondary: [KeyMod.WinCtrl | KeyCode.KEY_N] } } @@ -653,7 +653,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.DownArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow], mac: { primary: KeyMod.Shift | KeyCode.DownArrow }, @@ -672,7 +672,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.PageDown } })); @@ -688,7 +688,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.PageDown } })); @@ -813,7 +813,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Home, mac: { primary: KeyCode.Home, secondary: [KeyMod.CtrlCmd | KeyCode.LeftArrow] } } @@ -825,7 +825,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.Home, mac: { primary: KeyMod.Shift | KeyCode.Home, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow] } } @@ -838,7 +838,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_A } } @@ -892,7 +892,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.End, mac: { primary: KeyCode.End, secondary: [KeyMod.CtrlCmd | KeyCode.RightArrow] } } @@ -904,7 +904,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.End, mac: { primary: KeyMod.Shift | KeyCode.End, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow] } } @@ -917,7 +917,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_E } } @@ -972,7 +972,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Home, mac: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow } } @@ -984,7 +984,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Home, mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow } } @@ -1016,7 +1016,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.End, mac: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow } } @@ -1028,7 +1028,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.End, mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } } @@ -1112,7 +1112,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.UpArrow, mac: { primary: KeyMod.WinCtrl | KeyCode.PageUp } } @@ -1137,7 +1137,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.PageUp, win: { primary: KeyMod.Alt | KeyCode.PageUp }, linux: { primary: KeyMod.Alt | KeyCode.PageUp } @@ -1163,7 +1163,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.DownArrow, mac: { primary: KeyMod.WinCtrl | KeyCode.PageDown } } @@ -1188,7 +1188,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.PageDown, win: { primary: KeyMod.Alt | KeyCode.PageDown }, linux: { primary: KeyMod.Alt | KeyCode.PageDown } @@ -1351,7 +1351,7 @@ export namespace CoreNavigationCommands { precondition: null, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_I } }); @@ -1376,7 +1376,7 @@ export namespace CoreNavigationCommands { precondition: EditorContextKeys.hasNonEmptySelection, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] } @@ -1403,7 +1403,7 @@ export namespace CoreNavigationCommands { precondition: EditorContextKeys.hasMultipleSelections, kbOpts: { weight: CORE_WEIGHT + 1, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] } @@ -1521,7 +1521,7 @@ export namespace CoreEditingCommands { precondition: EditorContextKeys.writable, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: null, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_O } } @@ -1542,7 +1542,7 @@ export namespace CoreEditingCommands { kbOpts: { weight: CORE_WEIGHT, kbExpr: ContextKeyExpr.and( - EditorContextKeys.textFocus, + EditorContextKeys.editorTextFocus, EditorContextKeys.tabDoesNotMoveFocus ), primary: KeyMod.Shift | KeyCode.Tab @@ -1565,7 +1565,7 @@ export namespace CoreEditingCommands { kbOpts: { weight: CORE_WEIGHT, kbExpr: ContextKeyExpr.and( - EditorContextKeys.textFocus, + EditorContextKeys.editorTextFocus, EditorContextKeys.tabDoesNotMoveFocus ), primary: KeyCode.Tab @@ -1587,7 +1587,7 @@ export namespace CoreEditingCommands { precondition: EditorContextKeys.writable, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Backspace, secondary: [KeyMod.Shift | KeyCode.Backspace], mac: { primary: KeyCode.Backspace, secondary: [KeyMod.Shift | KeyCode.Backspace, KeyMod.WinCtrl | KeyCode.KEY_H, KeyMod.WinCtrl | KeyCode.Backspace] } @@ -1613,7 +1613,7 @@ export namespace CoreEditingCommands { precondition: EditorContextKeys.writable, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Delete, mac: { primary: KeyCode.Delete, secondary: [KeyMod.WinCtrl | KeyCode.KEY_D, KeyMod.WinCtrl | KeyCode.Delete] } } @@ -1743,7 +1743,7 @@ registerCommand(new EditorOrNativeTextInputCommand({ precondition: EditorContextKeys.writable, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_Z } })); @@ -1756,7 +1756,7 @@ registerCommand(new EditorOrNativeTextInputCommand({ precondition: EditorContextKeys.writable, kbOpts: { weight: CORE_WEIGHT, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_Y, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z], mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z } diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index e7bd06b4a5..b283e2a9a0 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -11,7 +11,7 @@ import * as dom from 'vs/base/browser/dom'; import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; -import { MouseTarget, MouseTargetFactory, IViewZoneData } from 'vs/editor/browser/controller/mouseTarget'; +import { MouseTarget, MouseTargetFactory, IViewZoneData, HitTestContext } from 'vs/editor/browser/controller/mouseTarget'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import { TimeoutTimer, RunOnceScheduler } from 'vs/base/common/async'; import { ViewContext } from 'vs/editor/common/view/viewContext'; @@ -220,8 +220,8 @@ export class MouseHandler extends ViewEventHandler { let targetIsViewZone = (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE); let targetIsWidget = (t.type === editorBrowser.MouseTargetType.CONTENT_WIDGET); - let shouldHandle = e.leftButton; - if (platform.isMacintosh && e.ctrlKey) { + let shouldHandle = e.leftButton || e.middleButton; + if (platform.isMacintosh && e.leftButton && e.ctrlKey) { shouldHandle = false; } @@ -334,6 +334,7 @@ class MouseDownOperation extends Disposable { this._lastMouseEvent = e; this._mouseState.setStartedOnLineNumbers(targetType === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS); + this._mouseState.setStartButtons(e); this._mouseState.setModifiers(e); let position = this._findMousePosition(e, true); if (!position) { @@ -423,12 +424,30 @@ class MouseDownOperation extends Disposable { const mouseColumn = this._getMouseColumn(e); if (e.posy < editorContent.y) { - let aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(Math.max(viewLayout.getCurrentScrollTop() - (editorContent.y - e.posy), 0)); + const verticalOffset = Math.max(viewLayout.getCurrentScrollTop() - (editorContent.y - e.posy), 0); + const viewZoneData = HitTestContext.getZoneAtCoord(this._context, verticalOffset); + if (viewZoneData) { + const newPosition = this._helpPositionJumpOverViewZone(viewZoneData); + if (newPosition) { + return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition); + } + } + + let aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(aboveLineNumber, 1)); } if (e.posy > editorContent.y + editorContent.height) { - let belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y)); + const verticalOffset = viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y); + const viewZoneData = HitTestContext.getZoneAtCoord(this._context, verticalOffset); + if (viewZoneData) { + const newPosition = this._helpPositionJumpOverViewZone(viewZoneData); + if (newPosition) { + return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition); + } + } + + let belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset); return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber))); } @@ -458,24 +477,31 @@ class MouseDownOperation extends Disposable { } if (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE) { - // Force position on view zones to go above or below depending on where selection started from - let selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn); - let viewZoneData = <IViewZoneData>t.detail; - let positionBefore = viewZoneData.positionBefore; - let positionAfter = viewZoneData.positionAfter; - - if (positionBefore && positionAfter) { - if (positionBefore.isBefore(selectionStart)) { - return new MouseTarget(t.element, t.type, t.mouseColumn, positionBefore, null, t.detail); - } else { - return new MouseTarget(t.element, t.type, t.mouseColumn, positionAfter, null, t.detail); - } + const newPosition = this._helpPositionJumpOverViewZone(<IViewZoneData>t.detail); + if (newPosition) { + return new MouseTarget(t.element, t.type, t.mouseColumn, newPosition, null, t.detail); } } return t; } + private _helpPositionJumpOverViewZone(viewZoneData: IViewZoneData): Position { + // Force position on view zones to go above or below depending on where selection started from + let selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn); + let positionBefore = viewZoneData.positionBefore; + let positionAfter = viewZoneData.positionAfter; + + if (positionBefore && positionAfter) { + if (positionBefore.isBefore(selectionStart)) { + return positionBefore; + } else { + return positionAfter; + } + } + return null; + } + private _dispatchMouse(position: MouseTarget, inSelectionMode: boolean): void { this._viewController.dispatchMouse({ position: position.position, @@ -488,6 +514,9 @@ class MouseDownOperation extends Disposable { ctrlKey: this._mouseState.ctrlKey, metaKey: this._mouseState.metaKey, shiftKey: this._mouseState.shiftKey, + + leftButton: this._mouseState.leftButton, + middleButton: this._mouseState.middleButton, }); } } @@ -508,6 +537,12 @@ class MouseDownState { private _shiftKey: boolean; public get shiftKey(): boolean { return this._shiftKey; } + private _leftButton: boolean; + public get leftButton(): boolean { return this._leftButton; } + + private _middleButton: boolean; + public get middleButton(): boolean { return this._middleButton; } + private _startedOnLineNumbers: boolean; public get startedOnLineNumbers(): boolean { return this._startedOnLineNumbers; } @@ -522,6 +557,8 @@ class MouseDownState { this._ctrlKey = false; this._metaKey = false; this._shiftKey = false; + this._leftButton = false; + this._middleButton = false; this._startedOnLineNumbers = false; this._lastMouseDownPosition = null; this._lastMouseDownPositionEqualCount = 0; @@ -541,6 +578,11 @@ class MouseDownState { this._shiftKey = source.shiftKey; } + public setStartButtons(source: EditorMouseEvent) { + this._leftButton = source.leftButton; + this._middleButton = source.middleButton; + } + public setStartedOnLineNumbers(startedOnLineNumbers: boolean): void { this._startedOnLineNumbers = startedOnLineNumbers; } diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 4ebcd6bb05..0e2edf6862 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -16,6 +16,7 @@ import { PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPa import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions'; import { ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine'; +import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; export interface IViewZoneData { viewZoneId: number; @@ -34,6 +35,7 @@ export interface IMarginData { export interface IEmptyContentData { isAfterLines: boolean; + horizontalDistanceToText?: number; } interface IETextRange { @@ -174,6 +176,14 @@ class ElementPath { ); } + public static isStrictChildOfViewLines(path: Uint8Array): boolean { + return ( + path.length > 4 + && path[0] === PartFingerprint.OverflowGuard + && path[3] === PartFingerprint.ViewLines + ); + } + public static isChildOfScrollableElement(path: Uint8Array): boolean { return ( path.length >= 2 @@ -214,7 +224,7 @@ class ElementPath { } } -class HitTestContext { +export class HitTestContext { public readonly model: IViewModel; public readonly layoutInfo: EditorLayoutInfo; @@ -238,12 +248,16 @@ class HitTestContext { } public getZoneAtCoord(mouseVerticalOffset: number): IViewZoneData { + return HitTestContext.getZoneAtCoord(this._context, mouseVerticalOffset); + } + + public static getZoneAtCoord(context: ViewContext, mouseVerticalOffset: number): IViewZoneData { // The target is either a view zone or the empty space after the last view-line - let viewZoneWhitespace = this._context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset); + let viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset); if (viewZoneWhitespace) { let viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2, - lineCount = this._context.model.getLineCount(), + lineCount = context.model.getLineCount(), positionBefore: Position = null, position: Position, positionAfter: Position = null; @@ -254,7 +268,7 @@ class HitTestContext { } if (viewZoneWhitespace.afterLineNumber > 0) { // There are more lines above this view zone - positionBefore = new Position(viewZoneWhitespace.afterLineNumber, this._context.model.getLineMaxColumn(viewZoneWhitespace.afterLineNumber)); + positionBefore = new Position(viewZoneWhitespace.afterLineNumber, context.model.getLineMaxColumn(viewZoneWhitespace.afterLineNumber)); } if (positionAfter === null) { @@ -330,7 +344,7 @@ class HitTestContext { return this._viewHelper.getLineWidth(lineNumber); } - public visibleRangeForPosition2(lineNumber: number, column: number) { + public visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange { return this._viewHelper.visibleRangeForPosition2(lineNumber, column); } @@ -402,7 +416,13 @@ class HitTestRequest extends BareHitTestRequest { } const EMPTY_CONTENT_AFTER_LINES: IEmptyContentData = { isAfterLines: true }; -const EMPTY_CONTENT_IN_LINES: IEmptyContentData = { isAfterLines: false }; + +function createEmptyContentDataInLines(horizontalDistanceToText: number): IEmptyContentData { + return { + isAfterLines: false, + horizontalDistanceToText: horizontalDistanceToText + }; +} export class MouseTargetFactory { @@ -621,6 +641,17 @@ export class MouseTargetFactory { } if (domHitTestExecuted) { + // Check if we are hitting a view-line (can happen in the case of inline decorations on empty lines) + // See https://github.com/Microsoft/vscode/issues/46942 + if (ElementPath.isStrictChildOfViewLines(request.targetPath)) { + const lineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset); + if (ctx.model.getLineLength(lineNumber) === 0) { + const lineWidth = ctx.getLineWidth(lineNumber); + const detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth); + return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineNumber, 1), void 0, detail); + } + } + // We have already executed hit test... return request.fulfill(MouseTargetType.UNKNOWN); } @@ -691,9 +722,11 @@ export class MouseTargetFactory { if (request.mouseContentHorizontalOffset > lineWidth) { if (browser.isEdge && pos.column === 1) { // See https://github.com/Microsoft/vscode/issues/10875 - return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineNumber, ctx.model.getLineMaxColumn(lineNumber)), void 0, EMPTY_CONTENT_IN_LINES); + const detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth); + return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineNumber, ctx.model.getLineMaxColumn(lineNumber)), void 0, detail); } - return request.fulfill(MouseTargetType.CONTENT_EMPTY, pos, void 0, EMPTY_CONTENT_IN_LINES); + const detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth); + return request.fulfill(MouseTargetType.CONTENT_EMPTY, pos, void 0, detail); } const visibleRange = ctx.visibleRangeForPosition2(lineNumber, column); diff --git a/src/vs/editor/browser/controller/pointerHandler.ts b/src/vs/editor/browser/controller/pointerHandler.ts index 7344b71dac..fc35446ae1 100644 --- a/src/vs/editor/browser/controller/pointerHandler.ts +++ b/src/vs/editor/browser/controller/pointerHandler.ts @@ -228,7 +228,7 @@ export class PointerHandler implements IDisposable { this.handler = new MsPointerHandler(context, viewController, viewHelper); } else if ((<any>window).TouchEvent) { this.handler = new TouchHandler(context, viewController, viewHelper); - } else if (window.navigator.pointerEnabled) { + } else if (window.navigator.pointerEnabled || (<any>window).PointerEvent) { this.handler = new StandardPointerHandler(context, viewController, viewHelper); } else { this.handler = new MouseHandler(context, viewController, viewHelper); diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 1bfc65f2da..3138ba98b2 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -27,6 +27,7 @@ import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/line import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions'; import { EndOfLinePreference } from 'vs/editor/common/model'; +import { getMapForWordSeparators, WordCharacterClass } from 'vs/editor/common/controller/wordCharacterClassifier'; export interface ITextAreaHandlerHelper { visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalRange; @@ -163,7 +164,7 @@ export class TextAreaHandler extends ViewPart { const textAreaInputHost: ITextAreaInputHost = { getPlainTextToCopy: (): string => { - const rawWhatToCopy = this._context.model.getPlainTextToCopy(this._selections, this._emptySelectionClipboard); + const rawWhatToCopy = this._context.model.getPlainTextToCopy(this._selections, this._emptySelectionClipboard, platform.isWindows); const newLineCharacter = this._context.model.getEOL(); const isFromEmptySelection = (this._emptySelectionClipboard && this._selections.length === 1 && this._selections[0].isEmpty()); @@ -203,16 +204,19 @@ export class TextAreaHandler extends ViewPart { if (this._accessibilitySupport === platform.AccessibilitySupport.Disabled) { // We know for a fact that a screen reader is not attached // On OSX, we write the character before the cursor to allow for "long-press" composition + // Also on OSX, we write the word before the cursor to allow for the Accessibility Keyboard to give good hints if (platform.isMacintosh) { const selection = this._selections[0]; if (selection.isEmpty()) { const position = selection.getStartPosition(); - if (position.column > 1) { - const lineContent = this._context.model.getLineContent(position.lineNumber); - const charBefore = lineContent.charAt(position.column - 2); - if (!strings.isHighSurrogate(charBefore.charCodeAt(0))) { - return new TextAreaState(charBefore, 1, 1, position, position); - } + + let textBefore = this._getWordBeforePosition(position); + if (textBefore.length === 0) { + textBefore = this._getCharacterBeforePosition(position); + } + + if (textBefore.length > 0) { + return new TextAreaState(textBefore, textBefore.length, textBefore.length, position, position); } } } @@ -328,6 +332,35 @@ export class TextAreaHandler extends ViewPart { super.dispose(); } + private _getWordBeforePosition(position: Position): string { + const lineContent = this._context.model.getLineContent(position.lineNumber); + const wordSeparators = getMapForWordSeparators(this._context.configuration.editor.wordSeparators); + + let column = position.column; + let distance = 0; + while (column > 1) { + const charCode = lineContent.charCodeAt(column - 2); + const charClass = wordSeparators.get(charCode); + if (charClass !== WordCharacterClass.Regular || distance > 50) { + return lineContent.substring(column - 1, position.column - 1); + } + distance++; + column--; + } + return lineContent.substring(0, position.column - 1); + } + + private _getCharacterBeforePosition(position: Position): string { + if (position.column > 1) { + const lineContent = this._context.model.getLineContent(position.lineNumber); + const charBefore = lineContent.charAt(position.column - 2); + if (!strings.isHighSurrogate(charBefore.charCodeAt(0))) { + return charBefore; + } + } + return ''; + } + // --- begin event handlers public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { @@ -509,7 +542,7 @@ export class TextAreaHandler extends ViewPart { tac.setHeight(1); if (this._context.configuration.editor.viewInfo.glyphMargin) { - tac.setClassName('monaco-editor-background textAreaCover ' + Margin.CLASS_NAME); + tac.setClassName('monaco-editor-background textAreaCover ' + Margin.OUTER_CLASS_NAME); } else { if (this._context.configuration.editor.viewInfo.renderLineNumbers !== RenderLineNumbersType.Off) { tac.setClassName('monaco-editor-background textAreaCover ' + LineNumbersOverlay.CLASS_NAME); diff --git a/src/vs/editor/browser/controller/textAreaInput.ts b/src/vs/editor/browser/controller/textAreaInput.ts index 23003d854a..caf5729c0b 100644 --- a/src/vs/editor/browser/controller/textAreaInput.ts +++ b/src/vs/editor/browser/controller/textAreaInput.ts @@ -8,7 +8,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import * as strings from 'vs/base/common/strings'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable } from 'vs/base/common/lifecycle'; import { ITypeData, TextAreaState, ITextAreaWrapper } from 'vs/editor/browser/controller/textAreaState'; @@ -42,6 +42,19 @@ export interface ITextAreaInputHost { deduceModelPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position; } +const enum TextAreaInputEventType { + none, + compositionstart, + compositionupdate, + compositionend, + input, + cut, + copy, + paste, + focus, + blur +} + /** * Writes screen reader content to the textarea and is able to analyze its input events to generate: * - onCut @@ -53,42 +66,43 @@ export interface ITextAreaInputHost { export class TextAreaInput extends Disposable { private _onFocus = this._register(new Emitter<void>()); - public onFocus: Event<void> = this._onFocus.event; + public readonly onFocus: Event<void> = this._onFocus.event; private _onBlur = this._register(new Emitter<void>()); - public onBlur: Event<void> = this._onBlur.event; + public readonly onBlur: Event<void> = this._onBlur.event; private _onKeyDown = this._register(new Emitter<IKeyboardEvent>()); - public onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event; + public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event; private _onKeyUp = this._register(new Emitter<IKeyboardEvent>()); - public onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event; + public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event; private _onCut = this._register(new Emitter<void>()); - public onCut: Event<void> = this._onCut.event; + public readonly onCut: Event<void> = this._onCut.event; private _onPaste = this._register(new Emitter<IPasteData>()); - public onPaste: Event<IPasteData> = this._onPaste.event; + public readonly onPaste: Event<IPasteData> = this._onPaste.event; private _onType = this._register(new Emitter<ITypeData>()); - public onType: Event<ITypeData> = this._onType.event; + public readonly onType: Event<ITypeData> = this._onType.event; private _onCompositionStart = this._register(new Emitter<void>()); - public onCompositionStart: Event<void> = this._onCompositionStart.event; + public readonly onCompositionStart: Event<void> = this._onCompositionStart.event; private _onCompositionUpdate = this._register(new Emitter<ICompositionData>()); - public onCompositionUpdate: Event<ICompositionData> = this._onCompositionUpdate.event; + public readonly onCompositionUpdate: Event<ICompositionData> = this._onCompositionUpdate.event; private _onCompositionEnd = this._register(new Emitter<void>()); - public onCompositionEnd: Event<void> = this._onCompositionEnd.event; + public readonly onCompositionEnd: Event<void> = this._onCompositionEnd.event; private _onSelectionChangeRequest = this._register(new Emitter<Selection>()); - public onSelectionChangeRequest: Event<Selection> = this._onSelectionChangeRequest.event; + public readonly onSelectionChangeRequest: Event<Selection> = this._onSelectionChangeRequest.event; // --- private readonly _host: ITextAreaInputHost; private readonly _textArea: TextAreaWrapper; + private _lastTextAreaEvent: TextAreaInputEventType; private readonly _asyncTriggerCut: RunOnceScheduler; private _textAreaState: TextAreaState; @@ -101,6 +115,7 @@ export class TextAreaInput extends Disposable { super(); this._host = host; this._textArea = this._register(new TextAreaWrapper(textArea)); + this._lastTextAreaEvent = TextAreaInputEventType.none; this._asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0)); this._textAreaState = TextAreaState.EMPTY; @@ -129,6 +144,8 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'compositionstart', (e: CompositionEvent) => { + this._lastTextAreaEvent = TextAreaInputEventType.compositionstart; + if (this._isDoingComposition) { return; } @@ -145,10 +162,10 @@ export class TextAreaInput extends Disposable { /** * Deduce the typed input from a text area's value and the last observed state. */ - const deduceInputFromTextAreaValue = (couldBeEmojiInput: boolean): [TextAreaState, ITypeData] => { + const deduceInputFromTextAreaValue = (couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean): [TextAreaState, ITypeData] => { const oldState = this._textAreaState; - const newState = this._textAreaState.readFromTextArea(this._textArea); - return [newState, TextAreaState.deduceInput(oldState, newState, couldBeEmojiInput)]; + const newState = TextAreaState.readFromTextArea(this._textArea); + return [newState, TextAreaState.deduceInput(oldState, newState, couldBeEmojiInput, couldBeTypingAtOffset0)]; }; /** @@ -164,7 +181,29 @@ export class TextAreaInput extends Disposable { return [newState, typeInput]; }; + const compositionDataInValid = (locale: string): boolean => { + // https://github.com/Microsoft/monaco-editor/issues/339 + // Multi-part Japanese compositions reset cursor in Edge/IE, Chinese and Korean IME don't have this issue. + // The reason that we can't use this path for all CJK IME is IE and Edge behave differently when handling Korean IME, + // which breaks this path of code. + if (browser.isEdgeOrIE && locale === 'ja') { + return true; + } + + // https://github.com/Microsoft/monaco-editor/issues/545 + // On IE11, we can't trust composition data when typing Chinese as IE11 doesn't emit correct + // events when users type numbers in IME. + // Chinese: zh-Hans-CN, zh-Hans-SG, zh-Hant-TW, zh-Hant-HK + if (browser.isIE && locale.indexOf('zh-Han') === 0) { + return true; + } + + return false; + }; + this._register(dom.addDisposableListener(textArea.domNode, 'compositionupdate', (e: CompositionEvent) => { + this._lastTextAreaEvent = TextAreaInputEventType.compositionupdate; + if (browser.isChromev56) { // See https://github.com/Microsoft/monaco-editor/issues/320 // where compositionupdate .data is broken in Chrome v55 and v56 @@ -174,12 +213,8 @@ export class TextAreaInput extends Disposable { return; } - if (browser.isEdgeOrIE && e.locale === 'ja') { - // https://github.com/Microsoft/monaco-editor/issues/339 - // Multi-part Japanese compositions reset cursor in Edge/IE, Chinese and Korean IME don't have this issue. - // The reason that we can't use this path for all CJK IME is IE and Edge behave differently when handling Korean IME, - // which breaks this path of code. - const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false); + if (compositionDataInValid(e.locale)) { + const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false); this._textAreaState = newState; this._onType.fire(typeInput); this._onCompositionUpdate.fire(e); @@ -193,13 +228,14 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'compositionend', (e: CompositionEvent) => { - if (browser.isEdgeOrIE && e.locale === 'ja') { + this._lastTextAreaEvent = TextAreaInputEventType.compositionend; + + if (compositionDataInValid(e.locale)) { // https://github.com/Microsoft/monaco-editor/issues/339 - const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false); + const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false); this._textAreaState = newState; this._onType.fire(typeInput); - } - else { + } else { const [newState, typeInput] = deduceComposition(e.data); this._textAreaState = newState; this._onType.fire(typeInput); @@ -208,7 +244,7 @@ export class TextAreaInput extends Disposable { // Due to isEdgeOrIE (where the textarea was not cleared initially) and isChrome (the textarea is not updated correctly when composition ends) // we cannot assume the text at the end consists only of the composited text if (browser.isEdgeOrIE || browser.isChrome) { - this._textAreaState = this._textAreaState.readFromTextArea(this._textArea); + this._textAreaState = TextAreaState.readFromTextArea(this._textArea); } if (!this._isDoingComposition) { @@ -220,6 +256,10 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'input', () => { + // We want to find out if this is the first `input` after a `focus`. + const previousEventWasFocus = (this._lastTextAreaEvent === TextAreaInputEventType.focus); + this._lastTextAreaEvent = TextAreaInputEventType.input; + // Pretend here we touched the text area, as the `input` event will most likely // result in a `selectionchange` event which we want to ignore this._textArea.setIgnoreSelectionChangeTime('received input event'); @@ -239,7 +279,7 @@ export class TextAreaInput extends Disposable { return; } - const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/platform.isMacintosh); + const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/platform.isMacintosh, /*couldBeTypingAtOffset0*/previousEventWasFocus && platform.isMacintosh); if (typeInput.replaceCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) { // Ignore invalid input but keep it around for next time return; @@ -264,6 +304,8 @@ export class TextAreaInput extends Disposable { // --- Clipboard operations this._register(dom.addDisposableListener(textArea.domNode, 'cut', (e: ClipboardEvent) => { + this._lastTextAreaEvent = TextAreaInputEventType.cut; + // Pretend here we touched the text area, as the `cut` event will most likely // result in a `selectionchange` event which we want to ignore this._textArea.setIgnoreSelectionChangeTime('received cut event'); @@ -273,10 +315,14 @@ export class TextAreaInput extends Disposable { })); this._register(dom.addDisposableListener(textArea.domNode, 'copy', (e: ClipboardEvent) => { + this._lastTextAreaEvent = TextAreaInputEventType.copy; + this._ensureClipboardGetsEditorSelection(e); })); this._register(dom.addDisposableListener(textArea.domNode, 'paste', (e: ClipboardEvent) => { + this._lastTextAreaEvent = TextAreaInputEventType.paste; + // Pretend here we touched the text area, as the `paste` event will most likely // result in a `selectionchange` event which we want to ignore this._textArea.setIgnoreSelectionChangeTime('received paste event'); @@ -297,8 +343,14 @@ export class TextAreaInput extends Disposable { } })); - this._register(dom.addDisposableListener(textArea.domNode, 'focus', () => this._setHasFocus(true))); - this._register(dom.addDisposableListener(textArea.domNode, 'blur', () => this._setHasFocus(false))); + this._register(dom.addDisposableListener(textArea.domNode, 'focus', () => { + this._lastTextAreaEvent = TextAreaInputEventType.focus; + this._setHasFocus(true); + })); + this._register(dom.addDisposableListener(textArea.domNode, 'blur', () => { + this._lastTextAreaEvent = TextAreaInputEventType.blur; + this._setHasFocus(false); + })); // See https://github.com/Microsoft/vscode/issues/27216 diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts index 54dc049ab9..b0fa4ae129 100644 --- a/src/vs/editor/browser/controller/textAreaState.ts +++ b/src/vs/editor/browser/controller/textAreaState.ts @@ -51,7 +51,7 @@ export class TextAreaState { return '[ <' + this.value + '>, selectionStart: ' + this.selectionStart + ', selectionEnd: ' + this.selectionEnd + ']'; } - public readFromTextArea(textArea: ITextAreaWrapper): TextAreaState { + public static readFromTextArea(textArea: ITextAreaWrapper): TextAreaState { return new TextAreaState(textArea.getValue(), textArea.getSelectionStart(), textArea.getSelectionEnd(), null, null); } @@ -60,7 +60,7 @@ export class TextAreaState { } public writeToTextArea(reason: string, textArea: ITextAreaWrapper, select: boolean): void { - // console.log(Date.now() + ': applyToTextArea ' + reason + ': ' + this.toString()); + // console.log(Date.now() + ': writeToTextArea ' + reason + ': ' + this.toString()); textArea.setValue(reason, this.value); if (select) { textArea.setSelectionRange(reason, this.selectionStart, this.selectionEnd); @@ -97,7 +97,7 @@ export class TextAreaState { return new TextAreaState(text, 0, text.length, null, null); } - public static deduceInput(previousState: TextAreaState, currentState: TextAreaState, couldBeEmojiInput: boolean): ITypeData { + public static deduceInput(previousState: TextAreaState, currentState: TextAreaState, couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean): ITypeData { if (!previousState) { // This is the EMPTY state return { @@ -117,6 +117,18 @@ export class TextAreaState { let currentSelectionStart = currentState.selectionStart; let currentSelectionEnd = currentState.selectionEnd; + if (couldBeTypingAtOffset0 && previousValue.length > 0 && previousSelectionStart === previousSelectionEnd && currentSelectionStart === currentSelectionEnd) { + // See https://github.com/Microsoft/vscode/issues/42251 + // where typing always happens at offset 0 in the textarea + // when using a custom title area in OSX and moving the window + if (strings.endsWith(currentValue, previousValue)) { + // Looks like something was typed at offset 0 + // ==> pretend we placed the cursor at offset 0 to begin with... + previousSelectionStart = 0; + previousSelectionEnd = 0; + } + } + // Strip the previous suffix from the value (without interfering with the current selection) const previousSuffix = previousValue.substring(previousSelectionEnd); const currentSuffix = currentValue.substring(currentSelectionEnd); diff --git a/src/vs/editor/browser/core/editorState.ts b/src/vs/editor/browser/core/editorState.ts index 6797183e9b..c57eb21de1 100644 --- a/src/vs/editor/browser/core/editorState.ts +++ b/src/vs/editor/browser/core/editorState.ts @@ -71,3 +71,33 @@ export class EditorState { return this._equals(new EditorState(editor, this.flags)); } } + +export class StableEditorScrollState { + + public static capture(editor: ICodeEditor): StableEditorScrollState { + let visiblePosition: Position = null; + let visiblePositionScrollDelta = 0; + if (editor.getScrollTop() !== 0) { + const visibleRanges = editor.getVisibleRanges(); + if (visibleRanges.length > 0) { + visiblePosition = visibleRanges[0].getStartPosition(); + const visiblePositionScrollTop = editor.getTopForPosition(visiblePosition.lineNumber, visiblePosition.column); + visiblePositionScrollDelta = editor.getScrollTop() - visiblePositionScrollTop; + } + } + return new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta); + } + + constructor( + private readonly _visiblePosition: Position, + private readonly _visiblePositionScrollDelta: number + ) { + } + + public restore(editor: ICodeEditor): void { + if (this._visiblePosition) { + const visiblePositionScrollTop = editor.getTopForPosition(this._visiblePosition.lineNumber, this._visiblePosition.column); + editor.setScrollTop(visiblePositionScrollTop + this._visiblePositionScrollDelta); + } + } +} diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index c7da14979a..444470398c 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -309,6 +309,11 @@ export interface IOverviewRuler { * A rich code editor. */ export interface ICodeEditor extends editorCommon.IEditor { + /** + * This editor is used as an alternative to an <input> box, i.e. as a simple widget. + * @internal + */ + readonly isSimpleWidget: boolean; /** * An event emitted when the content of the current model has changed. * @event @@ -386,6 +391,12 @@ export interface ICodeEditor extends editorCommon.IEditor { * @internal */ onDidType(listener: (text: string) => void): IDisposable; + /** + * An event emitted when editing failed because the editor is read-only. + * @event + * @internal + */ + onDidAttemptReadOnlyEdit(listener: () => void): IDisposable; /** * An event emitted when users paste text in the editor. * @event @@ -614,11 +625,6 @@ export interface ICodeEditor extends editorCommon.IEditor { */ getLayoutInfo(): editorOptions.EditorLayoutInfo; - /** - * Returns the range that is currently centered in the view port. - */ - getCenteredRangeInViewport(): Range; - /** * Returns the ranges that are currently visible. * Does not account for horizontal scrolling. diff --git a/src/vs/editor/browser/services/abstractCodeEditorService.ts b/src/vs/editor/browser/services/abstractCodeEditorService.ts index fb619d5eff..1aca0d8ab9 100644 --- a/src/vs/editor/browser/services/abstractCodeEditorService.ts +++ b/src/vs/editor/browser/services/abstractCodeEditorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon'; import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; @@ -14,12 +14,12 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService { _serviceBrand: any; - private _onCodeEditorAdd: Emitter<ICodeEditor>; - private _onCodeEditorRemove: Emitter<ICodeEditor>; + private readonly _onCodeEditorAdd: Emitter<ICodeEditor>; + private readonly _onCodeEditorRemove: Emitter<ICodeEditor>; private _codeEditors: { [editorId: string]: ICodeEditor; }; - private _onDiffEditorAdd: Emitter<IDiffEditor>; - private _onDiffEditorRemove: Emitter<IDiffEditor>; + private readonly _onDiffEditorAdd: Emitter<IDiffEditor>; + private readonly _onDiffEditorRemove: Emitter<IDiffEditor>; private _diffEditors: { [editorId: string]: IDiffEditor; }; constructor() { diff --git a/src/vs/editor/browser/services/codeEditorService.ts b/src/vs/editor/browser/services/codeEditorService.ts index 3ae32e3c39..a67155a780 100644 --- a/src/vs/editor/browser/services/codeEditorService.ts +++ b/src/vs/editor/browser/services/codeEditorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon'; import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model'; diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index 9cb167cb26..eaf391fcca 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -19,7 +19,7 @@ export class CodeEditorServiceImpl extends AbstractCodeEditorService { private _decorationOptionProviders: { [key: string]: IModelDecorationOptionsProvider }; private _themeService: IThemeService; - constructor( @IThemeService themeService: IThemeService, styleSheet = dom.createStyleSheet()) { + constructor(@IThemeService themeService: IThemeService, styleSheet = dom.createStyleSheet()) { super(); this._styleSheet = styleSheet; this._decorationOptionProviders = Object.create(null); @@ -126,6 +126,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { public className: string; public inlineClassName: string; + public inlineClassNameAffectsLetterSpacing: boolean; public beforeContentClassName: string; public afterContentClassName: string; public glyphMarginClassName: string; @@ -145,9 +146,21 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { } return void 0; }; + let createInlineCSSRules = (type: ModelDecorationCSSRuleType) => { + let rules = new DecorationCSSRules(type, providerArgs, themeService); + if (rules.hasContent) { + this._disposables.push(rules); + return { className: rules.className, hasLetterSpacing: rules.hasLetterSpacing }; + } + return null; + }; this.className = createCSSRules(ModelDecorationCSSRuleType.ClassName); - this.inlineClassName = createCSSRules(ModelDecorationCSSRuleType.InlineClassName); + const inlineData = createInlineCSSRules(ModelDecorationCSSRuleType.InlineClassName); + if (inlineData) { + this.inlineClassName = inlineData.className; + this.inlineClassNameAffectsLetterSpacing = inlineData.hasLetterSpacing; + } this.beforeContentClassName = createCSSRules(ModelDecorationCSSRuleType.BeforeContentClassName); this.afterContentClassName = createCSSRules(ModelDecorationCSSRuleType.AfterContentClassName); this.glyphMarginClassName = createCSSRules(ModelDecorationCSSRuleType.GlyphMarginClassName); @@ -194,6 +207,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { const _CSS_MAP = { color: 'color:{0} !important;', + opacity: 'opacity:{0};', backgroundColor: 'background-color:{0};', outline: 'outline:{0};', @@ -231,6 +245,7 @@ class DecorationCSSRules { private _className: string; private _unThemedSelector: string; private _hasContent: boolean; + private _hasLetterSpacing: boolean; private _ruleType: ModelDecorationCSSRuleType; private _themeListener: IDisposable; private _providerArgs: ProviderArguments; @@ -242,6 +257,7 @@ class DecorationCSSRules { this._providerArgs = providerArgs; this._usesThemeColors = false; this._hasContent = false; + this._hasLetterSpacing = false; let className = CSSNameHelper.getClassName(this._providerArgs.key, ruleType); if (this._providerArgs.parentTypeKey) { @@ -277,6 +293,10 @@ class DecorationCSSRules { return this._hasContent; } + public get hasLetterSpacing(): boolean { + return this._hasLetterSpacing; + } + public get className(): string { return this._className; } @@ -357,7 +377,10 @@ class DecorationCSSRules { return ''; } let cssTextArr: string[] = []; - this.collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'cursor', 'color', 'letterSpacing'], cssTextArr); + this.collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'cursor', 'color', 'opacity', 'letterSpacing'], cssTextArr); + if (opts.letterSpacing) { + this._hasLetterSpacing = true; + } return cssTextArr.join(''); } @@ -385,7 +408,7 @@ class DecorationCSSRules { cssTextArr.push(strings.format(_CSS_MAP.contentText, escaped)); } - this.collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'color', 'backgroundColor', 'margin'], cssTextArr); + this.collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'color', 'opacity', 'backgroundColor', 'margin'], cssTextArr); if (this.collectCSSText(opts, ['width', 'height'], cssTextArr)) { cssTextArr.push('display:inline-block;'); } diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 0648627c17..fef2d42543 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -7,9 +7,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; -import * as editorCommon from 'vs/editor/common/editorCommon'; import { IEditorMouseEvent } from 'vs/editor/browser/editorBrowser'; -import { ICommandService } from 'vs/platform/commands/common/commands'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents'; import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands'; @@ -33,6 +31,18 @@ export interface IMouseDispatchData { ctrlKey: boolean; metaKey: boolean; shiftKey: boolean; + + leftButton: boolean; + middleButton: boolean; +} + +export interface ICommandDelegate { + paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]): void; + type(source: string, text: string): void; + replacePreviousChar(source: string, text: string, replaceCharCnt: number): void; + compositionStart(source: string): void; + compositionEnd(source: string): void; + cut(source: string): void; } export class ViewController { @@ -41,20 +51,20 @@ export class ViewController { private readonly viewModel: IViewModel; private readonly _execCoreEditorCommandFunc: ExecCoreEditorCommandFunc; private readonly outgoingEvents: ViewOutgoingEvents; - private readonly commandService: ICommandService; + private readonly commandDelegate: ICommandDelegate; constructor( configuration: Configuration, viewModel: IViewModel, execCommandFunc: ExecCoreEditorCommandFunc, outgoingEvents: ViewOutgoingEvents, - commandService: ICommandService + commandDelegate: ICommandDelegate ) { this.configuration = configuration; this.viewModel = viewModel; this._execCoreEditorCommandFunc = execCommandFunc; this.outgoingEvents = outgoingEvents; - this.commandService = commandService; + this.commandDelegate = commandDelegate; } private _execMouseCommand(editorCommand: CoreEditorCommand, args: any): void { @@ -63,36 +73,27 @@ export class ViewController { } public paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]): void { - this.commandService.executeCommand(editorCommon.Handler.Paste, { - text: text, - pasteOnNewLine: pasteOnNewLine, - multicursorText: multicursorText - }); + this.commandDelegate.paste(source, text, pasteOnNewLine, multicursorText); } public type(source: string, text: string): void { - this.commandService.executeCommand(editorCommon.Handler.Type, { - text: text - }); + this.commandDelegate.type(source, text); } public replacePreviousChar(source: string, text: string, replaceCharCnt: number): void { - this.commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, { - text: text, - replaceCharCnt: replaceCharCnt - }); + this.commandDelegate.replacePreviousChar(source, text, replaceCharCnt); } public compositionStart(source: string): void { - this.commandService.executeCommand(editorCommon.Handler.CompositionStart, {}); + this.commandDelegate.compositionStart(source); } public compositionEnd(source: string): void { - this.commandService.executeCommand(editorCommon.Handler.CompositionEnd, {}); + this.commandDelegate.compositionEnd(source); } public cut(source: string): void { - this.commandService.executeCommand(editorCommon.Handler.Cut, {}); + this.commandDelegate.cut(source); } public setSelection(source: string, modelSelection: Selection): void { @@ -135,7 +136,13 @@ export class ViewController { } public dispatchMouse(data: IMouseDispatchData): void { - if (data.startedOnLineNumbers) { + if (data.middleButton) { + if (data.inSelectionMode) { + this.columnSelect(data.position, data.mouseColumn); + } else { + this.moveTo(data.position); + } + } else if (data.startedOnLineNumbers) { // If the dragging started on the gutter, then have operations work on the entire line if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 68287e0c5b..2ae1986c75 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -8,14 +8,13 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable } from 'vs/base/common/lifecycle'; import * as dom from 'vs/base/browser/dom'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; -import { ICommandService } from 'vs/platform/commands/common/commands'; import { Range } from 'vs/editor/common/core/range'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; import { Configuration } from 'vs/editor/browser/config/configuration'; import { TextAreaHandler, ITextAreaHandlerHelper } from 'vs/editor/browser/controller/textAreaHandler'; import { PointerHandler } from 'vs/editor/browser/controller/pointerHandler'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; -import { ViewController, ExecCoreEditorCommandFunc } from 'vs/editor/browser/view/viewController'; +import { ViewController, ExecCoreEditorCommandFunc, ICommandDelegate } from 'vs/editor/browser/view/viewController'; import { ViewEventDispatcher } from 'vs/editor/common/view/viewEventDispatcher'; import { ContentViewOverlays, MarginViewOverlays } from 'vs/editor/browser/view/viewOverlays'; import { ViewContentWidgets } from 'vs/editor/browser/viewParts/contentWidgets/contentWidgets'; @@ -93,7 +92,7 @@ export class View extends ViewEventHandler { private _renderAnimationFrame: IDisposable; constructor( - commandService: ICommandService, + commandDelegate: ICommandDelegate, configuration: Configuration, themeService: IThemeService, model: IViewModel, @@ -105,7 +104,7 @@ export class View extends ViewEventHandler { this._renderAnimationFrame = null; this.outgoingEvents = new ViewOutgoingEvents(model); - let viewController = new ViewController(configuration, model, execCoreEditorCommandFunc, this.outgoingEvents, commandService); + let viewController = new ViewController(configuration, model, execCoreEditorCommandFunc, this.outgoingEvents, commandDelegate); // The event dispatcher will always go through _renderOnce before dispatching any events this.eventDispatcher = new ViewEventDispatcher((callback: () => void) => this._renderOnce(callback)); @@ -178,8 +177,8 @@ export class View extends ViewEventHandler { this.viewParts.push(contentViewOverlays); contentViewOverlays.addDynamicOverlay(new CurrentLineHighlightOverlay(this._context)); contentViewOverlays.addDynamicOverlay(new SelectionsOverlay(this._context)); - contentViewOverlays.addDynamicOverlay(new DecorationsOverlay(this._context)); contentViewOverlays.addDynamicOverlay(new IndentGuidesOverlay(this._context)); + contentViewOverlays.addDynamicOverlay(new DecorationsOverlay(this._context)); let marginViewOverlays = new MarginViewOverlays(this._context); this.viewParts.push(marginViewOverlays); @@ -322,6 +321,7 @@ export class View extends ViewEventHandler { } public onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean { this.domNode.setClassName(this.getEditorClassName()); + this._context.model.setHasFocus(e.isFocused); if (e.isFocused) { this.outgoingEvents.emitViewFocusGained(); } else { diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 00d482a17c..09fd98de2f 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -308,7 +308,8 @@ class Widget { private _layoutBoxInPage(topLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult { let left0 = topLeft.left - ctx.scrollLeft; - if (left0 + width < 0 || left0 > this._contentWidth) { + if (left0 < 0 || left0 > this._contentWidth) { + // Don't render if position is scrolled outside viewport return null; } diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index 6639cd5d0c..e66c6f9cf3 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -85,8 +85,14 @@ export class DecorationsOverlay extends DynamicViewOverlay { // Sort decorations for consistent render output decorations = decorations.sort((a, b) => { - let aClassName = a.options.className; - let bClassName = b.options.className; + if (a.options.zIndex < b.options.zIndex) { + return -1; + } + if (a.options.zIndex > b.options.zIndex) { + return 1; + } + const aClassName = a.options.className; + const bClassName = b.options.className; if (aClassName < bClassName) { return -1; @@ -142,8 +148,12 @@ export class DecorationsOverlay extends DynamicViewOverlay { } private _renderNormalDecorations(ctx: RenderingContext, decorations: ViewModelDecoration[], output: string[]): void { - let lineHeight = String(this._lineHeight); - let visibleStartLineNumber = ctx.visibleRange.startLineNumber; + const lineHeight = String(this._lineHeight); + const visibleStartLineNumber = ctx.visibleRange.startLineNumber; + + let prevClassName: string = null; + let prevShowIfCollapsed: boolean = false; + let prevRange: Range = null; for (let i = 0, lenI = decorations.length; i < lenI; i++) { const d = decorations[i]; @@ -160,39 +170,60 @@ export class DecorationsOverlay extends DynamicViewOverlay { range = new Range(range.startLineNumber, range.startColumn, range.endLineNumber - 1, this._context.model.getLineMaxColumn(range.endLineNumber - 1)); } - let linesVisibleRanges = ctx.linesVisibleRangesForRange(range, /*TODO@Alex*/className === 'findMatch'); - if (!linesVisibleRanges) { + if (prevClassName === className && prevShowIfCollapsed === showIfCollapsed && Range.areIntersectingOrTouching(prevRange, range)) { + // merge into previous decoration + prevRange = Range.plusRange(prevRange, range); continue; } - for (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) { - let lineVisibleRanges = linesVisibleRanges[j]; - const lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber; + // flush previous decoration + if (prevClassName !== null) { + this._renderNormalDecoration(ctx, prevRange, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output); + } - if (showIfCollapsed && lineVisibleRanges.ranges.length === 1) { - const singleVisibleRange = lineVisibleRanges.ranges[0]; - if (singleVisibleRange.width === 0) { - // collapsed range case => make the decoration visible by faking its width - lineVisibleRanges.ranges[0] = new HorizontalRange(singleVisibleRange.left, this._typicalHalfwidthCharacterWidth); - } - } + prevClassName = className; + prevShowIfCollapsed = showIfCollapsed; + prevRange = range; + } - for (let k = 0, lenK = lineVisibleRanges.ranges.length; k < lenK; k++) { - const visibleRange = lineVisibleRanges.ranges[k]; - const decorationOutput = ( - '<div class="cdr ' - + className - + '" style="left:' - + String(visibleRange.left) - + 'px;width:' - + String(visibleRange.width) - + 'px;height:' - + lineHeight - + 'px;"></div>' - ); - output[lineIndex] += decorationOutput; + if (prevClassName !== null) { + this._renderNormalDecoration(ctx, prevRange, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output); + } + } + + private _renderNormalDecoration(ctx: RenderingContext, range: Range, className: string, showIfCollapsed: boolean, lineHeight: string, visibleStartLineNumber: number, output: string[]): void { + let linesVisibleRanges = ctx.linesVisibleRangesForRange(range, /*TODO@Alex*/className === 'findMatch'); + if (!linesVisibleRanges) { + return; + } + + for (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) { + let lineVisibleRanges = linesVisibleRanges[j]; + const lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber; + + if (showIfCollapsed && lineVisibleRanges.ranges.length === 1) { + const singleVisibleRange = lineVisibleRanges.ranges[0]; + if (singleVisibleRange.width === 0) { + // collapsed range case => make the decoration visible by faking its width + lineVisibleRanges.ranges[0] = new HorizontalRange(singleVisibleRange.left, this._typicalHalfwidthCharacterWidth); } } + + for (let k = 0, lenK = lineVisibleRanges.ranges.length; k < lenK; k++) { + const visibleRange = lineVisibleRanges.ranges[k]; + const decorationOutput = ( + '<div class="cdr ' + + className + + '" style="left:' + + String(visibleRange.left) + + 'px;width:' + + String(visibleRange.width) + + 'px;height:' + + lineHeight + + 'px;"></div>' + ); + output[lineIndex] += decorationOutput; + } } } diff --git a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.css b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.css index 06552b33b3..87699c609e 100644 --- a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.css +++ b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.css @@ -10,3 +10,6 @@ .monaco-editor .lines-content .cigr { position: absolute; } +.monaco-editor .lines-content .cigra { + position: absolute; +} diff --git a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts index a542e2d3c2..e15a36d4f5 100644 --- a/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts +++ b/src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts @@ -11,13 +11,13 @@ import { ViewContext } from 'vs/editor/common/view/viewContext'; import { RenderingContext } from 'vs/editor/common/view/renderingContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { editorIndentGuides } from 'vs/editor/common/view/editorColorRegistry'; -import * as dom from 'vs/base/browser/dom'; +import { editorIndentGuides, editorActiveIndentGuides } from 'vs/editor/common/view/editorColorRegistry'; import { Position } from 'vs/editor/common/core/position'; export class IndentGuidesOverlay extends DynamicViewOverlay { private _context: ViewContext; + private _primaryLineNumber: number; private _lineHeight: number; private _spaceWidth: number; private _renderResult: string[]; @@ -26,6 +26,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { constructor(context: ViewContext) { super(); this._context = context; + this._primaryLineNumber = 0; this._lineHeight = this._context.configuration.editor.lineHeight; this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth; this._enabled = this._context.configuration.editor.viewInfo.renderIndentGuides; @@ -55,6 +56,17 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { } return true; } + public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { + const selection = e.selections[0]; + const newPrimaryLineNumber = selection.isEmpty() ? selection.positionLineNumber : 0; + + if (this._primaryLineNumber !== newPrimaryLineNumber) { + this._primaryLineNumber = newPrimaryLineNumber; + return true; + } + + return false; + } public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { // true for inline decorations return true; @@ -94,20 +106,32 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { const tabSize = this._context.model.getTabSize(); const tabWidth = tabSize * this._spaceWidth; const lineHeight = this._lineHeight; - const indentGuideWidth = dom.computeScreenAwareSize(1); + const indentGuideWidth = tabWidth; const indents = this._context.model.getLinesIndentGuides(visibleStartLineNumber, visibleEndLineNumber); + let activeIndentStartLineNumber = 0; + let activeIndentEndLineNumber = 0; + let activeIndentLevel = 0; + if (this._primaryLineNumber) { + const activeIndentInfo = this._context.model.getActiveIndentGuide(this._primaryLineNumber, visibleStartLineNumber, visibleEndLineNumber); + activeIndentStartLineNumber = activeIndentInfo.startLineNumber; + activeIndentEndLineNumber = activeIndentInfo.endLineNumber; + activeIndentLevel = activeIndentInfo.indent; + } + let output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { + const containsActiveIndentGuide = (activeIndentStartLineNumber <= lineNumber && lineNumber <= activeIndentEndLineNumber); const lineIndex = lineNumber - visibleStartLineNumber; const indent = indents[lineIndex]; let result = ''; let leftMostVisiblePosition = ctx.visibleRangeForPosition(new Position(lineNumber, 1)); let left = leftMostVisiblePosition ? leftMostVisiblePosition.left : 0; - for (let i = 0; i < indent; i++) { - result += `<div class="cigr" style="left:${left}px;height:${lineHeight}px;width:${indentGuideWidth}px"></div>`; + for (let i = 1; i <= indent; i++) { + let className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr'); + result += `<div class="${className}" style="left:${left}px;height:${lineHeight}px;width:${indentGuideWidth}px"></div>`; left += tabWidth; } @@ -129,8 +153,12 @@ export class IndentGuidesOverlay extends DynamicViewOverlay { } registerThemingParticipant((theme, collector) => { - let editorGuideColor = theme.getColor(editorIndentGuides); - if (editorGuideColor) { - collector.addRule(`.monaco-editor .lines-content .cigr { background-color: ${editorGuideColor}; }`); + let editorIndentGuidesColor = theme.getColor(editorIndentGuides); + if (editorIndentGuidesColor) { + collector.addRule(`.monaco-editor .lines-content .cigr { box-shadow: 1px 0 0 0 ${editorIndentGuidesColor} inset; }`); + } + let editorActiveIndentGuidesColor = theme.getColor(editorActiveIndentGuides) || editorIndentGuidesColor; + if (editorActiveIndentGuidesColor) { + collector.addRule(`.monaco-editor .lines-content .cigra { box-shadow: 1px 0 0 0 ${editorActiveIndentGuidesColor} inset; }`); } }); diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 514e052475..e4763e084b 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -6,11 +6,10 @@ import * as browser from 'vs/base/browser/browser'; import * as platform from 'vs/base/common/platform'; -import * as strings from 'vs/base/common/strings'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; import { IConfiguration } from 'vs/editor/common/editorCommon'; import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations'; -import { renderViewLine, RenderLineInput, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; +import { renderViewLine, RenderLineInput, CharacterMapping, ForeignElementType } from 'vs/editor/common/viewLayout/viewLineRenderer'; import { IVisibleLine } from 'vs/editor/browser/view/viewLayer'; import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil'; import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; @@ -192,7 +191,8 @@ export class ViewLine implements IVisibleLine { let renderLineInput = new RenderLineInput( options.useMonospaceOptimizations, lineData.content, - lineData.mightContainRTL, + lineData.isBasicASCII, + lineData.containsRTL, lineData.minColumn - 1, lineData.tokens, actualInlineDecorations, @@ -222,18 +222,16 @@ export class ViewLine implements IVisibleLine { sb.appendASCIIString('</div>'); let renderedViewLine: IRenderedViewLine = null; - if (canUseFastRenderedViewLine && options.useMonospaceOptimizations && !output.containsForeignElements) { - let isRegularASCII = true; - if (lineData.mightContainNonBasicASCII) { - isRegularASCII = strings.isBasicASCII(lineData.content); - } - - if (isRegularASCII && lineData.content.length < 1000 && renderLineInput.lineTokens.getCount() < 100) { + if (canUseFastRenderedViewLine && lineData.isBasicASCII && options.useMonospaceOptimizations && output.containsForeignElements === ForeignElementType.None) { + if (lineData.content.length < 300 && renderLineInput.lineTokens.getCount() < 100) { // Browser rounding errors have been observed in Chrome and IE, so using the fast // view line only for short lines. Please test before removing the length check... // --- // Another rounding error has been observed on Linux in VSCode, where <span> width // rounding errors add up to an observable large number... + // --- + // Also see another example of rounding errors on Windows in + // https://github.com/Microsoft/vscode/issues/33178 renderedViewLine = new FastRenderedViewLine( this._renderedViewLine ? this._renderedViewLine.domNode : null, renderLineInput, @@ -385,7 +383,7 @@ class RenderedViewLine implements IRenderedViewLine { protected readonly _characterMapping: CharacterMapping; private readonly _isWhitespaceOnly: boolean; - private readonly _containsForeignElements: boolean; + private readonly _containsForeignElements: ForeignElementType; private _cachedWidth: number; /** @@ -393,7 +391,7 @@ class RenderedViewLine implements IRenderedViewLine { */ private _pixelOffsetCache: Int32Array; - constructor(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: boolean) { + constructor(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) { this.domNode = domNode; this.input = renderLineInput; this._characterMapping = characterMapping; @@ -471,10 +469,18 @@ class RenderedViewLine implements IRenderedViewLine { protected _readPixelOffset(column: number, context: DomReadingContext): number { if (this._characterMapping.length === 0) { // This line has no content - if (!this._containsForeignElements) { + if (this._containsForeignElements === ForeignElementType.None) { // We can assume the line is really empty return 0; } + if (this._containsForeignElements === ForeignElementType.After) { + // We have foreign elements after the (empty) line + return 0; + } + if (this._containsForeignElements === ForeignElementType.Before) { + // We have foreign element before the (empty) line + return this.getWidth(); + } } if (this._pixelOffsetCache !== null) { @@ -503,7 +509,7 @@ class RenderedViewLine implements IRenderedViewLine { return r[0].left; } - if (column === this._characterMapping.length && this._isWhitespaceOnly && !this._containsForeignElements) { + if (column === this._characterMapping.length && this._isWhitespaceOnly && this._containsForeignElements === ForeignElementType.None) { // This branch helps in the case of whitespace only lines which have a width set return this.getWidth(); } @@ -586,17 +592,17 @@ class WebKitRenderedViewLine extends RenderedViewLine { } } -const createRenderedLine: (domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: boolean) => RenderedViewLine = (function () { +const createRenderedLine: (domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) => RenderedViewLine = (function () { if (browser.isWebKit) { return createWebKitRenderedLine; } return createNormalRenderedLine; })(); -function createWebKitRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: boolean): RenderedViewLine { +function createWebKitRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine { return new WebKitRenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements); } -function createNormalRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: boolean): RenderedViewLine { +function createNormalRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine { return new RenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements); } diff --git a/src/vs/editor/browser/viewParts/margin/margin.ts b/src/vs/editor/browser/viewParts/margin/margin.ts index 7847611dcf..36fd5c6e72 100644 --- a/src/vs/editor/browser/viewParts/margin/margin.ts +++ b/src/vs/editor/browser/viewParts/margin/margin.ts @@ -14,6 +14,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; export class Margin extends ViewPart { public static readonly CLASS_NAME = 'glyph-margin'; + public static readonly OUTER_CLASS_NAME = 'margin'; private _domNode: FastDomNode<HTMLElement>; private _canUseLayerHinting: boolean; @@ -42,7 +43,7 @@ export class Margin extends ViewPart { private _createDomNode(): FastDomNode<HTMLElement> { let domNode = createFastDomNode(document.createElement('div')); - domNode.setClassName('margin'); + domNode.setClassName(Margin.OUTER_CLASS_NAME); domNode.setPosition('absolute'); domNode.setAttribute('role', 'presentation'); domNode.setAttribute('aria-hidden', 'true'); diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 04cc11ffd4..51dc863fee 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -7,6 +7,7 @@ import 'vs/css!./minimap'; import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart'; +import * as strings from 'vs/base/common/strings'; import { ViewContext } from 'vs/editor/common/view/viewContext'; import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; import { getOrCreateMinimapCharRenderer } from 'vs/editor/common/view/runtimeMinimapCharRenderer'; @@ -897,17 +898,22 @@ export class Minimap extends ViewPart { // No need to render anything since space is invisible dx += charWidth; } else { - if (renderMinimap === RenderMinimap.Large) { - minimapCharRenderer.x2RenderChar(target, dx, dy, charCode, tokenColor, backgroundColor, useLighterFont); - } else if (renderMinimap === RenderMinimap.Small) { - minimapCharRenderer.x1RenderChar(target, dx, dy, charCode, tokenColor, backgroundColor, useLighterFont); - } else if (renderMinimap === RenderMinimap.LargeBlocks) { - minimapCharRenderer.x2BlockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont); - } else { - // RenderMinimap.SmallBlocks - minimapCharRenderer.x1BlockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont); + // Render twice for a full width character + let count = strings.isFullWidthCharacter(charCode) ? 2 : 1; + + for (let i = 0; i < count; i++) { + if (renderMinimap === RenderMinimap.Large) { + minimapCharRenderer.x2RenderChar(target, dx, dy, charCode, tokenColor, backgroundColor, useLighterFont); + } else if (renderMinimap === RenderMinimap.Small) { + minimapCharRenderer.x1RenderChar(target, dx, dy, charCode, tokenColor, backgroundColor, useLighterFont); + } else if (renderMinimap === RenderMinimap.LargeBlocks) { + minimapCharRenderer.x2BlockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont); + } else { + // RenderMinimap.SmallBlocks + minimapCharRenderer.x1BlockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont); + } + dx += charWidth; } - dx += charWidth; } } } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 769945ca12..7462f07eaf 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -58,8 +58,13 @@ class Settings { this.themeType = theme.type; const minimapEnabled = config.editor.viewInfo.minimap.enabled; + const minimapSide = config.editor.viewInfo.minimap.side; const backgroundColor = (minimapEnabled ? TokenizationRegistry.getDefaultBackground() : null); - this.backgroundColor = (backgroundColor ? Color.Format.CSS.formatHex(backgroundColor) : null); + if (backgroundColor === null || minimapSide === 'left') { + this.backgroundColor = null; + } else { + this.backgroundColor = Color.Format.CSS.formatHex(backgroundColor); + } const position = config.editor.layoutInfo.overviewRuler; this.top = position.top; diff --git a/src/vs/editor/browser/viewParts/rulers/rulers.ts b/src/vs/editor/browser/viewParts/rulers/rulers.ts index cf0c3818d6..e3c98cc9b0 100644 --- a/src/vs/editor/browser/viewParts/rulers/rulers.ts +++ b/src/vs/editor/browser/viewParts/rulers/rulers.ts @@ -13,7 +13,6 @@ import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/v import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorRuler } from 'vs/editor/common/view/editorColorRegistry'; -import * as dom from 'vs/base/browser/dom'; export class Rulers extends ViewPart { @@ -67,7 +66,7 @@ export class Rulers extends ViewPart { } if (currentCount < desiredCount) { - const rulerWidth = dom.computeScreenAwareSize(1); + const rulerWidth = this._context.model.getTabSize(); let addCount = desiredCount - currentCount; while (addCount > 0) { let node = createFastDomNode(document.createElement('div')); @@ -104,6 +103,6 @@ export class Rulers extends ViewPart { registerThemingParticipant((theme, collector) => { let rulerColor = theme.getColor(editorRuler); if (rulerColor) { - collector.addRule(`.monaco-editor .view-ruler { background-color: ${rulerColor}; }`); + collector.addRule(`.monaco-editor .view-ruler { box-shadow: 1px 0 0 0 ${rulerColor} inset; }`); } }); diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index 8fe08aaeec..364602a801 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -54,7 +54,12 @@ export class ScrollDecorationViewPart extends ViewPart { private _updateWidth(): boolean { const layoutInfo = this._context.configuration.editor.layoutInfo; - let newWidth = layoutInfo.width - layoutInfo.minimapWidth; + let newWidth = 0; + if (layoutInfo.renderMinimap === 0 || (layoutInfo.minimapWidth > 0 && layoutInfo.minimapLeft === 0)) { + newWidth = layoutInfo.width; + } else { + newWidth = layoutInfo.width - layoutInfo.minimapWidth - layoutInfo.verticalScrollbarWidth; + } if (this._width !== newWidth) { this._width = newWidth; return true; diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index ed614173ed..8342090e99 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -78,6 +78,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { private _context: ViewContext; private _lineHeight: number; private _roundedSelection: boolean; + private _typicalHalfwidthCharacterWidth: number; private _selections: Range[]; private _renderResult: string[]; @@ -86,6 +87,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { this._context = context; this._lineHeight = this._context.configuration.editor.lineHeight; this._roundedSelection = this._context.configuration.editor.viewInfo.roundedSelection; + this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth; this._selections = []; this._renderResult = null; this._context.addEventHandler(this); @@ -108,6 +110,9 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (e.viewInfo) { this._roundedSelection = this._context.configuration.editor.viewInfo.roundedSelection; } + if (e.fontInfo) { + this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth; + } return true; } public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { @@ -153,23 +158,28 @@ export class SelectionsOverlay extends DynamicViewOverlay { return false; } - private _enrichVisibleRangesWithStyle(linesVisibleRanges: LineVisibleRangesWithStyle[], previousFrame: LineVisibleRangesWithStyle[]): void { + private _enrichVisibleRangesWithStyle(viewport: Range, linesVisibleRanges: LineVisibleRangesWithStyle[], previousFrame: LineVisibleRangesWithStyle[]): void { + const epsilon = this._typicalHalfwidthCharacterWidth / 4; let previousFrameTop: HorizontalRangeWithStyle = null; let previousFrameBottom: HorizontalRangeWithStyle = null; if (previousFrame && previousFrame.length > 0 && linesVisibleRanges.length > 0) { let topLineNumber = linesVisibleRanges[0].lineNumber; - for (let i = 0; !previousFrameTop && i < previousFrame.length; i++) { - if (previousFrame[i].lineNumber === topLineNumber) { - previousFrameTop = previousFrame[i].ranges[0]; + if (topLineNumber === viewport.startLineNumber) { + for (let i = 0; !previousFrameTop && i < previousFrame.length; i++) { + if (previousFrame[i].lineNumber === topLineNumber) { + previousFrameTop = previousFrame[i].ranges[0]; + } } } let bottomLineNumber = linesVisibleRanges[linesVisibleRanges.length - 1].lineNumber; - for (let i = previousFrame.length - 1; !previousFrameBottom && i >= 0; i--) { - if (previousFrame[i].lineNumber === bottomLineNumber) { - previousFrameBottom = previousFrame[i].ranges[0]; + if (bottomLineNumber === viewport.endLineNumber) { + for (let i = previousFrame.length - 1; !previousFrameBottom && i >= 0; i--) { + if (previousFrame[i].lineNumber === bottomLineNumber) { + previousFrameBottom = previousFrame[i].ranges[0]; + } } } @@ -202,13 +212,13 @@ export class SelectionsOverlay extends DynamicViewOverlay { let prevLeft = linesVisibleRanges[i - 1].ranges[0].left; let prevRight = linesVisibleRanges[i - 1].ranges[0].left + linesVisibleRanges[i - 1].ranges[0].width; - if (curLeft === prevLeft) { + if (abs(curLeft - prevLeft) < epsilon) { startStyle.top = CornerStyle.FLAT; } else if (curLeft > prevLeft) { startStyle.top = CornerStyle.INTERN; } - if (curRight === prevRight) { + if (abs(curRight - prevRight) < epsilon) { endStyle.top = CornerStyle.FLAT; } else if (prevLeft < curRight && curRight < prevRight) { endStyle.top = CornerStyle.INTERN; @@ -224,13 +234,13 @@ export class SelectionsOverlay extends DynamicViewOverlay { let nextLeft = linesVisibleRanges[i + 1].ranges[0].left; let nextRight = linesVisibleRanges[i + 1].ranges[0].left + linesVisibleRanges[i + 1].ranges[0].width; - if (curLeft === nextLeft) { + if (abs(curLeft - nextLeft) < epsilon) { startStyle.bottom = CornerStyle.FLAT; } else if (nextLeft < curLeft && curLeft < nextRight) { startStyle.bottom = CornerStyle.INTERN; } - if (curRight === nextRight) { + if (abs(curRight - nextRight) < epsilon) { endStyle.bottom = CornerStyle.FLAT; } else if (curRight < nextRight) { endStyle.bottom = CornerStyle.INTERN; @@ -252,7 +262,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { let visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges); if (!isIEWithZoomingIssuesNearRoundedBorders && !visibleRangesHaveGaps && this._roundedSelection) { - this._enrichVisibleRangesWithStyle(linesVisibleRanges, previousFrame); + this._enrichVisibleRangesWithStyle(ctx.visibleRange, linesVisibleRanges, previousFrame); } // The visible ranges are sorted TOP-BOTTOM and LEFT-RIGHT @@ -407,3 +417,7 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.monaco-editor .view-line span.inline-selected-text { color: ${editorSelectionForegroundColor}; }`); } }); + +function abs(n: number): number { + return n < 0 ? -n : n; +} \ No newline at end of file diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts index 201634a6d5..f42b57d431 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts @@ -13,6 +13,7 @@ import { ViewContext } from 'vs/editor/common/view/viewContext'; import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import * as dom from 'vs/base/browser/dom'; +import * as strings from 'vs/base/common/strings'; export interface IViewCursorRenderData { domNode: HTMLElement; @@ -28,7 +29,8 @@ class ViewCursorRenderData { public readonly left: number, public readonly width: number, public readonly height: number, - public readonly textContent: string + public readonly textContent: string, + public readonly textContentClassName: string ) { } } @@ -118,6 +120,7 @@ export class ViewCursor { private _prepareRender(ctx: RenderingContext): ViewCursorRenderData { let textContent = ''; + let textContentClassName = ''; if (this._cursorStyle === TextEditorCursorStyle.Line || this._cursorStyle === TextEditorCursorStyle.LineThin) { const visibleRange = ctx.visibleRangeForPosition(this._position); @@ -136,7 +139,7 @@ export class ViewCursor { width = dom.computeScreenAwareSize(1); } const top = ctx.getVerticalOffsetForLineNumber(this._position.lineNumber) - ctx.bigNumbersDelta; - return new ViewCursorRenderData(top, visibleRange.left, width, this._lineHeight, textContent); + return new ViewCursorRenderData(top, visibleRange.left, width, this._lineHeight, textContent, textContentClassName); } const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(this._position.lineNumber, this._position.column, this._position.lineNumber, this._position.column + 1), false); @@ -150,8 +153,13 @@ export class ViewCursor { const width = range.width < 1 ? this._typicalHalfwidthCharacterWidth : range.width; if (this._cursorStyle === TextEditorCursorStyle.Block) { - const lineContent = this._context.model.getLineContent(this._position.lineNumber); - textContent = lineContent.charAt(this._position.column - 1); + const lineData = this._context.model.getViewLineData(this._position.lineNumber); + textContent = lineData.content.charAt(this._position.column - 1); + if (strings.isHighSurrogate(lineData.content.charCodeAt(this._position.column - 1))) { + textContent += lineData.content.charAt(this._position.column); + } + const tokenIndex = lineData.tokens.findTokenIndexAtOffset(this._position.column - 1); + textContentClassName = lineData.tokens.getClassName(tokenIndex); } let top = ctx.getVerticalOffsetForLineNumber(this._position.lineNumber) - ctx.bigNumbersDelta; @@ -163,7 +171,7 @@ export class ViewCursor { height = 2; } - return new ViewCursorRenderData(top, range.left, width, height, textContent); + return new ViewCursorRenderData(top, range.left, width, height, textContent, textContentClassName); } public prepareRender(ctx: RenderingContext): void { @@ -181,6 +189,8 @@ export class ViewCursor { this._domNode.domNode.textContent = this._lastRenderedContent; } + this._domNode.setClassName('cursor ' + this._renderData.textContentClassName); + this._domNode.setDisplay('block'); this._domNode.setTop(this._renderData.top); this._domNode.setLeft(this._renderData.left); diff --git a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts index 9715ba8add..3e3db20172 100644 --- a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts +++ b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts @@ -99,7 +99,11 @@ export class ViewZones extends ViewPart { } public onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): boolean { - return this._recomputeWhitespacesProps(); + const hadAChange = this._recomputeWhitespacesProps(); + if (hadAChange) { + this._context.viewLayout.onHeightMaybeChanged(); + } + return hadAChange; } public onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean { diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 39a4f66ee1..d2fd6c9cda 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -21,18 +21,20 @@ import { Configuration } from 'vs/editor/browser/config/configuration'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import { View, IOverlayWidgetData, IContentWidgetData } from 'vs/editor/browser/view/viewImpl'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { InternalEditorAction } from 'vs/editor/common/editorAction'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; -import { IPosition } from 'vs/editor/common/core/position'; +import { IPosition, Position } from 'vs/editor/common/core/position'; import { CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoBorder, editorInfoForeground } from 'vs/editor/common/view/editorColorRegistry'; +import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoBorder, editorInfoForeground, editorHintForeground, editorHintBorder } from 'vs/editor/common/view/editorColorRegistry'; import { Color } from 'vs/base/common/color'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { ClassName } from 'vs/editor/common/model/intervalTree'; import { ITextModel, IModelDecorationOptions } from 'vs/editor/common/model'; +import { ICommandDelegate } from 'vs/editor/browser/view/viewController'; +import { INotificationService } from 'vs/platform/notification/common/notification'; export abstract class CodeEditorWidget extends CommonCodeEditor implements editorBrowser.ICodeEditor { @@ -86,26 +88,22 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito constructor( domElement: HTMLElement, options: IEditorOptions, + isSimpleWidget: boolean, @IInstantiationService instantiationService: IInstantiationService, @ICodeEditorService codeEditorService: ICodeEditorService, @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService ) { - super(domElement, options, instantiationService, contextKeyService); + super(domElement, options, isSimpleWidget, instantiationService, contextKeyService, notificationService); this._codeEditorService = codeEditorService; this._commandService = commandService; this._themeService = themeService; this._focusTracker = new CodeEditorWidgetFocusTracker(domElement); this._focusTracker.onChange(() => { - let hasFocus = this._focusTracker.hasFocus(); - - if (hasFocus) { - this._onDidFocusEditor.fire(); - } else { - this._onDidBlurEditor.fire(); - } + this._editorFocus.setValue(this._focusTracker.hasFocus()); }); this.contentWidgets = {}; @@ -358,8 +356,62 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito } protected _createView(): void { + let commandDelegate: ICommandDelegate; + if (this.isSimpleWidget) { + commandDelegate = { + paste: (source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]) => { + this.cursor.trigger(source, editorCommon.Handler.Paste, { text, pasteOnNewLine, multicursorText }); + }, + type: (source: string, text: string) => { + this.cursor.trigger(source, editorCommon.Handler.Type, { text }); + }, + replacePreviousChar: (source: string, text: string, replaceCharCnt: number) => { + this.cursor.trigger(source, editorCommon.Handler.ReplacePreviousChar, { text, replaceCharCnt }); + }, + compositionStart: (source: string) => { + this.cursor.trigger(source, editorCommon.Handler.CompositionStart, undefined); + }, + compositionEnd: (source: string) => { + this.cursor.trigger(source, editorCommon.Handler.CompositionEnd, undefined); + }, + cut: (source: string) => { + this.cursor.trigger(source, editorCommon.Handler.Cut, undefined); + } + }; + } else { + commandDelegate = { + paste: (source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]) => { + this._commandService.executeCommand(editorCommon.Handler.Paste, { + text: text, + pasteOnNewLine: pasteOnNewLine, + multicursorText: multicursorText + }); + }, + type: (source: string, text: string) => { + this._commandService.executeCommand(editorCommon.Handler.Type, { + text: text + }); + }, + replacePreviousChar: (source: string, text: string, replaceCharCnt: number) => { + this._commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, { + text: text, + replaceCharCnt: replaceCharCnt + }); + }, + compositionStart: (source: string) => { + this._commandService.executeCommand(editorCommon.Handler.CompositionStart, {}); + }, + compositionEnd: (source: string) => { + this._commandService.executeCommand(editorCommon.Handler.CompositionEnd, {}); + }, + cut: (source: string) => { + this._commandService.executeCommand(editorCommon.Handler.Cut, {}); + } + }; + } + this._view = new View( - this._commandService, + commandDelegate, this._configuration, this._themeService, this.viewModel, @@ -375,13 +427,13 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito const viewEventBus = this._view.getInternalEventBus(); viewEventBus.onDidGainFocus = () => { - this._onDidFocusEditorText.fire(); + this._editorTextFocus.setValue(true); // In IE, the focus is not synchronous, so we give it a little help - this._onDidFocusEditor.fire(); + this._editorFocus.setValue(true); }; viewEventBus.onDidScroll = (e) => this._onDidScrollChange.fire(e); - viewEventBus.onDidLoseFocus = () => this._onDidBlurEditorText.fire(); + viewEventBus.onDidLoseFocus = () => this._editorTextFocus.setValue(false); viewEventBus.onContextMenu = (e) => this._onContextMenu.fire(e); viewEventBus.onMouseDown = (e) => this._onMouseDown.fire(e); viewEventBus.onMouseUp = (e) => this._onMouseUp.fire(e); @@ -399,7 +451,12 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito return; } if (s && s.cursorState && s.viewState) { - this._view.restoreState(this.viewModel.viewLayout.reduceRestoreState(s.viewState)); + const reducedState = this.viewModel.reduceRestoreState(s.viewState); + const linesViewportData = this.viewModel.viewLayout.getLinesViewportDataAtScrollTop(reducedState.scrollTop); + const startPosition = this.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(linesViewportData.startLineNumber, 1)); + const endPosition = this.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(linesViewportData.endLineNumber, 1)); + this.model.tokenizeViewport(startPosition.lineNumber, endPosition.lineNumber); + this._view.restoreState(reducedState); } } @@ -455,8 +512,8 @@ class CodeEditorWidgetFocusTracker extends Disposable { private _hasFocus: boolean; private _domFocusTracker: dom.IFocusTracker; - private _onChange: Emitter<void> = this._register(new Emitter<void>()); - public onChange: Event<void> = this._onChange.event; + private readonly _onChange: Emitter<void> = this._register(new Emitter<void>()); + public readonly onChange: Event<void> = this._onChange.event; constructor(domElement: HTMLElement) { super(); @@ -486,6 +543,13 @@ function getSquigglySVGData(color: Color) { return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd; } +const dotdotdotStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" height="3" width="12"><g fill="`); +const dotdotdotEnd = encodeURIComponent(`"><circle cx="1" cy="1" r="1"/><circle cx="5" cy="1" r="1"/><circle cx="9" cy="1" r="1"/></g></svg>`); + +function getDotDotDotSVGData(color: Color) { + return dotdotdotStart + encodeURIComponent(color.toString()) + dotdotdotEnd; +} + registerThemingParticipant((theme, collector) => { let errorBorderColor = theme.getColor(editorErrorBorder); if (errorBorderColor) { @@ -513,4 +577,13 @@ registerThemingParticipant((theme, collector) => { if (infoForeground) { collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`); } + + let hintBorderColor = theme.getColor(editorHintBorder); + if (hintBorderColor) { + collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { border-bottom: 2px dotted ${hintBorderColor}; }`); + } + let hintForeground = theme.getColor(editorHintForeground); + if (hintForeground) { + collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml;utf8,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`); + } }); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 546390a34f..8a938fa1b4 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -27,10 +27,10 @@ import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { Configuration } from 'vs/editor/browser/config/configuration'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Selection, ISelection } from 'vs/editor/common/core/selection'; -import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; +import { InlineDecoration, InlineDecorationType, ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ColorId, MetadataConsts, FontStyle } from 'vs/editor/common/modes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; import { registerThemingParticipant, IThemeService, ITheme, getThemeTypeSelector } from 'vs/platform/theme/common/themeService'; import { scrollbarShadow, diffInserted, diffRemoved, defaultInsertColor, defaultRemoveColor, diffInsertedOutline, diffRemovedOutline } from 'vs/platform/theme/common/colorRegistry'; @@ -43,6 +43,7 @@ import URI from 'vs/base/common/uri'; import { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder'; import { IModelDeltaDecoration, IModelDecorationsChangeAccessor, ITextModel } from 'vs/editor/common/model'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { StableEditorScrollState } from 'vs/editor/browser/core/editorState'; interface IEditorDiffDecorations { decorations: IModelDeltaDecoration[]; @@ -99,15 +100,13 @@ class VisualEditorState { this._zonesMap = {}; // (2) Model decorations - if (this._decorations.length > 0) { - editor.changeDecorations((changeAccessor: IModelDecorationsChangeAccessor) => { - changeAccessor.deltaDecorations(this._decorations, []); - }); - } - this._decorations = []; + this._decorations = editor.deltaDecorations(this._decorations, []); } - public apply(editor: CodeEditor, overviewRuler: editorBrowser.IOverviewRuler, newDecorations: IEditorDiffDecorationsWithZones): void { + public apply(editor: CodeEditor, overviewRuler: editorBrowser.IOverviewRuler, newDecorations: IEditorDiffDecorationsWithZones, restoreScrollState: boolean): void { + + const scrollState = restoreScrollState ? StableEditorScrollState.capture(editor) : null; + // view zones editor.changeViewZones((viewChangeAccessor: editorBrowser.IViewZoneChangeAccessor) => { for (let i = 0, length = this._zones.length; i < length; i++) { @@ -123,6 +122,10 @@ class VisualEditorState { } }); + if (scrollState) { + scrollState.restore(editor); + } + // decorations this._decorations = editor.deltaDecorations(this._decorations, newDecorations.decorations); @@ -284,13 +287,22 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._lineChanges = null; - const services = new ServiceCollection(); - services.set(IContextKeyService, this._contextKeyService); + const leftContextKeyService = this._contextKeyService.createScoped(); + leftContextKeyService.createKey('isInDiffLeftEditor', true); - const scopedInstantiationService = instantiationService.createChild(services); + const leftServices = new ServiceCollection(); + leftServices.set(IContextKeyService, leftContextKeyService); + const leftScopedInstantiationService = instantiationService.createChild(leftServices); - this._createLeftHandSideEditor(options, scopedInstantiationService); - this._createRightHandSideEditor(options, scopedInstantiationService); + const rightContextKeyService = this._contextKeyService.createScoped(); + rightContextKeyService.createKey('isInDiffRightEditor', true); + + const rightServices = new ServiceCollection(); + rightServices.set(IContextKeyService, rightContextKeyService); + const rightScopedInstantiationService = instantiationService.createChild(rightServices); + + this._createLeftHandSideEditor(options, leftScopedInstantiationService); + this._createRightHandSideEditor(options, rightScopedInstantiationService); this._reviewPane = new DiffReview(this); this._containerDomElement.appendChild(this._reviewPane.domNode.domNode); @@ -912,8 +924,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE try { this._currentlyChangingViewZones = true; - this._originalEditorState.apply(this.originalEditor, this._originalOverviewRuler, diffDecorations.original); - this._modifiedEditorState.apply(this.modifiedEditor, this._modifiedOverviewRuler, diffDecorations.modified); + this._originalEditorState.apply(this.originalEditor, this._originalOverviewRuler, diffDecorations.original, false); + this._modifiedEditorState.apply(this.modifiedEditor, this._modifiedOverviewRuler, diffDecorations.modified, true); } finally { this._currentlyChangingViewZones = false; } @@ -1989,10 +2001,13 @@ class InlineViewZonesComputer extends ViewZonesComputer { sb.appendASCIIString(String(count * config.lineHeight)); sb.appendASCIIString('px;width:1000000px;">'); + const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, originalModel.mightContainNonBasicASCII()); + const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, originalModel.mightContainRTL()); renderViewLine(new RenderLineInput( (config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations), lineContent, - originalModel.mightContainRTL(), + isBasicASCII, + containsRTL, 0, lineTokens, actualDecorations, @@ -2023,27 +2038,31 @@ function createFakeLinesDiv(): HTMLElement { } registerThemingParticipant((theme, collector) => { - let added = theme.getColor(diffInserted); + const added = theme.getColor(diffInserted); if (added) { collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { background-color: ${added}; }`); collector.addRule(`.monaco-diff-editor .line-insert, .monaco-diff-editor .char-insert { background-color: ${added}; }`); collector.addRule(`.monaco-editor .inline-added-margin-view-zone { background-color: ${added}; }`); } - let removed = theme.getColor(diffRemoved); + + const removed = theme.getColor(diffRemoved); if (removed) { collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { background-color: ${removed}; }`); collector.addRule(`.monaco-diff-editor .line-delete, .monaco-diff-editor .char-delete { background-color: ${removed}; }`); collector.addRule(`.monaco-editor .inline-deleted-margin-view-zone { background-color: ${removed}; }`); } - let addedOutline = theme.getColor(diffInsertedOutline); + + const addedOutline = theme.getColor(diffInsertedOutline); if (addedOutline) { - collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px dashed ${addedOutline}; }`); + collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${addedOutline}; }`); } - let removedOutline = theme.getColor(diffRemovedOutline); + + const removedOutline = theme.getColor(diffRemovedOutline); if (removedOutline) { - collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px dashed ${removedOutline}; }`); + collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${removedOutline}; }`); } - let shadow = theme.getColor(scrollbarShadow); + + const shadow = theme.getColor(scrollbarShadow); if (shadow) { collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`); } diff --git a/src/vs/editor/browser/widget/diffNavigator.ts b/src/vs/editor/browser/widget/diffNavigator.ts index 4ffb941e17..a857c20e94 100644 --- a/src/vs/editor/browser/widget/diffNavigator.ts +++ b/src/vs/editor/browser/widget/diffNavigator.ts @@ -11,7 +11,7 @@ import { ILineChange, ScrollType } from 'vs/editor/common/editorCommon'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; interface IDiffRange { diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index a4e4dc8dfd..63e142393c 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -29,6 +29,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model'; +import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel'; const DIFF_LINES_PADDING = 3; @@ -583,9 +584,34 @@ export class DiffReview extends Disposable { let cell = document.createElement('div'); cell.className = 'diff-review-cell diff-review-summary'; - cell.appendChild(document.createTextNode(`${diffIndex + 1}/${this._diffs.length}: @@ -${minOriginalLine},${maxOriginalLine - minOriginalLine + 1} +${minModifiedLine},${maxModifiedLine - minModifiedLine + 1} @@`)); + const originalChangedLinesCnt = maxOriginalLine - minOriginalLine + 1; + const modifiedChangedLinesCnt = maxModifiedLine - minModifiedLine + 1; + cell.appendChild(document.createTextNode(`${diffIndex + 1}/${this._diffs.length}: @@ -${minOriginalLine},${originalChangedLinesCnt} +${minModifiedLine},${modifiedChangedLinesCnt} @@`)); header.setAttribute('data-line', String(minModifiedLine)); - header.setAttribute('aria-label', nls.localize('header', "Difference {0} of {1}: original {2}, {3} lines, modified {4}, {5} lines", (diffIndex + 1), this._diffs.length, minOriginalLine, maxOriginalLine - minOriginalLine + 1, minModifiedLine, maxModifiedLine - minModifiedLine + 1)); + + const getAriaLines = (lines: number) => { + if (lines === 0) { + return nls.localize('no_lines', "no lines"); + } else if (lines === 1) { + return nls.localize('one_line', "1 line"); + } else { + return nls.localize('more_lines', "{0} lines", lines); + } + }; + + const originalChangedLinesCntAria = getAriaLines(originalChangedLinesCnt); + const modifiedChangedLinesCntAria = getAriaLines(modifiedChangedLinesCnt); + header.setAttribute('aria-label', nls.localize({ + key: 'header', + comment: [ + 'This is the ARIA label for a git diff header.', + 'A git diff header looks like this: @@ -154,12 +159,39 @@.', + 'That encodes that at original line 154 (which is now line 159), 12 lines were removed/changed with 39 lines.', + 'Variables 0 and 1 refer to the diff index out of total number of diffs.', + 'Variables 2 and 4 will be numbers (a line number).', + 'Variables 3 and 5 will be "no lines", "1 line" or "X lines", localized separately.' + ] + }, "Difference {0} of {1}: original {2}, {3}, modified {4}, {5}", (diffIndex + 1), this._diffs.length, minOriginalLine, originalChangedLinesCntAria, minModifiedLine, modifiedChangedLinesCntAria)); header.appendChild(cell); // @@ -504,7 +517,7 @@ @@ -738,10 +764,13 @@ export class DiffReview extends Disposable { const lineTokens = new LineTokens(tokens, lineContent); + const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, model.mightContainNonBasicASCII()); + const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, model.mightContainRTL()); const r = renderViewLine(new RenderLineInput( (config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations), lineContent, - model.mightContainRTL(), + isBasicASCII, + containsRTL, 0, lineTokens, [], diff --git a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts index 40324e4bfc..04664ca084 100644 --- a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts +++ b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts @@ -30,9 +30,10 @@ export class EmbeddedCodeEditorWidget extends CodeEditor { @ICodeEditorService codeEditorService: ICodeEditorService, @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService ) { - super(domElement, parentEditor.getRawConfiguration(), instantiationService, codeEditorService, commandService, contextKeyService, themeService); + super(domElement, parentEditor.getRawConfiguration(), instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService); this._parentEditor = parentEditor; this._overwriteOptions = options; diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 03c00810f5..29dfdc4b6e 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -30,6 +31,7 @@ import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceCompute import * as modes from 'vs/editor/common/modes'; import { Schemas } from 'vs/base/common/network'; import { ITextModel, EndOfLinePreference, IIdentifiedSingleEditOperation, IModelDecorationsChangeAccessor, IModelDecoration, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/model'; +import { INotificationService } from 'vs/platform/notification/common/notification'; let EDITOR_ID = 0; @@ -65,20 +67,19 @@ export abstract class CommonCodeEditor extends Disposable { private readonly _onDidChangeCursorSelection: Emitter<ICursorSelectionChangedEvent> = this._register(new Emitter<ICursorSelectionChangedEvent>()); public readonly onDidChangeCursorSelection: Event<ICursorSelectionChangedEvent> = this._onDidChangeCursorSelection.event; + private readonly _onDidAttemptReadOnlyEdit: Emitter<void> = this._register(new Emitter<void>()); + public readonly onDidAttemptReadOnlyEdit: Event<void> = this._onDidAttemptReadOnlyEdit.event; + private readonly _onDidLayoutChange: Emitter<editorOptions.EditorLayoutInfo> = this._register(new Emitter<editorOptions.EditorLayoutInfo>()); public readonly onDidLayoutChange: Event<editorOptions.EditorLayoutInfo> = this._onDidLayoutChange.event; - protected readonly _onDidFocusEditorText: Emitter<void> = this._register(new Emitter<void>()); - public readonly onDidFocusEditorText: Event<void> = this._onDidFocusEditorText.event; + protected _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); + public readonly onDidFocusEditorText: Event<void> = this._editorTextFocus.onDidChangeToTrue; + public readonly onDidBlurEditorText: Event<void> = this._editorTextFocus.onDidChangeToFalse; - protected readonly _onDidBlurEditorText: Emitter<void> = this._register(new Emitter<void>()); - public readonly onDidBlurEditorText: Event<void> = this._onDidBlurEditorText.event; - - protected readonly _onDidFocusEditor: Emitter<void> = this._register(new Emitter<void>()); - public readonly onDidFocusEditor: Event<void> = this._onDidFocusEditor.event; - - protected readonly _onDidBlurEditor: Emitter<void> = this._register(new Emitter<void>()); - public readonly onDidBlurEditor: Event<void> = this._onDidBlurEditor.event; + protected _editorFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter()); + public readonly onDidFocusEditor: Event<void> = this._editorFocus.onDidChangeToTrue; + public readonly onDidBlurEditor: Event<void> = this._editorFocus.onDidChangeToFalse; private readonly _onWillType: Emitter<string> = this._register(new Emitter<string>()); public readonly onWillType = this._onWillType.event; @@ -89,6 +90,7 @@ export abstract class CommonCodeEditor extends Disposable { private readonly _onDidPaste: Emitter<Range> = this._register(new Emitter<Range>()); public readonly onDidPaste = this._onDidPaste.event; + public readonly isSimpleWidget: boolean; protected readonly domElement: IContextKeyServiceTarget; protected readonly id: number; @@ -107,6 +109,7 @@ export abstract class CommonCodeEditor extends Disposable { protected readonly _instantiationService: IInstantiationService; protected readonly _contextKeyService: IContextKeyService; + protected readonly _notificationService: INotificationService; /** * map from "parent" decoration type to live decoration ids. @@ -118,14 +121,17 @@ export abstract class CommonCodeEditor extends Disposable { constructor( domElement: IContextKeyServiceTarget, options: editorOptions.IEditorOptions, + isSimpleWidget: boolean, instantiationService: IInstantiationService, - contextKeyService: IContextKeyService + contextKeyService: IContextKeyService, + notificationService: INotificationService, ) { super(); this.domElement = domElement; this.id = (++EDITOR_ID); this._decorationTypeKeysToIds = {}; this._decorationTypeSubtypes = {}; + this.isSimpleWidget = isSimpleWidget; options = options || {}; this._configuration = this._register(this._createConfiguration(options)); @@ -138,6 +144,7 @@ export abstract class CommonCodeEditor extends Disposable { })); this._contextKeyService = this._register(contextKeyService.createScoped(this.domElement)); + this._notificationService = notificationService; this._register(new EditorContextKeysManager(this, this._contextKeyService)); this._register(new EditorModeContext(this, this._contextKeyService)); @@ -249,13 +256,6 @@ export abstract class CommonCodeEditor extends Disposable { } } - public getCenteredRangeInViewport(): Range { - if (!this.hasView) { - return null; - } - return this.viewModel.getCenteredRangeInViewport(); - } - public getVisibleRanges(): Range[] { if (!this.hasView) { return []; @@ -626,19 +626,19 @@ export abstract class CommonCodeEditor extends Disposable { if (!this.cursor || !this.hasView) { return null; } - let contributionsState: { [key: string]: any } = {}; + const contributionsState: { [key: string]: any } = {}; - let keys = Object.keys(this._contributions); + const keys = Object.keys(this._contributions); for (let i = 0, len = keys.length; i < len; i++) { - let id = keys[i]; - let contribution = this._contributions[id]; + const id = keys[i]; + const contribution = this._contributions[id]; if (typeof contribution.saveViewState === 'function') { contributionsState[id] = contribution.saveViewState(); } } - let cursorState = this.cursor.saveState(); - let viewState = this.viewModel.viewLayout.saveState(); + const cursorState = this.cursor.saveState(); + const viewState = this.viewModel.saveState(); return { cursorState: cursorState, viewState: viewState, @@ -798,7 +798,7 @@ export abstract class CommonCodeEditor extends Disposable { } this.model.pushEditOperations(this.cursor.getSelections(), edits, () => { - return endCursorState ? endCursorState : this.cursor.getSelections(); + return endCursorState ? endCursorState : null; }); if (endCursorState) { @@ -967,6 +967,14 @@ export abstract class CommonCodeEditor extends Disposable { this._createView(); + this.listenersToRemove.push(this.cursor.onDidReachMaxCursorCount(() => { + this._notificationService.warn(nls.localize('cursors.maximum', "The number of cursors has been limited to {0}.", Cursor.MAX_CURSOR_COUNT)); + })); + + this.listenersToRemove.push(this.cursor.onDidAttemptReadOnlyEdit(() => { + this._onDidAttemptReadOnlyEdit.fire(void 0); + })); + this.listenersToRemove.push(this.cursor.onDidChange((e: CursorStateChangedEvent) => { let positions: Position[] = []; @@ -1044,10 +1052,45 @@ export abstract class CommonCodeEditor extends Disposable { } } +const enum BooleanEventValue { + NotSet, + False, + True +} + +export class BooleanEventEmitter extends Disposable { + private readonly _onDidChangeToTrue: Emitter<void> = this._register(new Emitter<void>()); + public readonly onDidChangeToTrue: Event<void> = this._onDidChangeToTrue.event; + + private readonly _onDidChangeToFalse: Emitter<void> = this._register(new Emitter<void>()); + public readonly onDidChangeToFalse: Event<void> = this._onDidChangeToFalse.event; + + private _value: BooleanEventValue; + + constructor() { + super(); + this._value = BooleanEventValue.NotSet; + } + + public setValue(_value: boolean) { + let value = (_value ? BooleanEventValue.True : BooleanEventValue.False); + if (this._value === value) { + return; + } + this._value = value; + if (this._value === BooleanEventValue.True) { + this._onDidChangeToTrue.fire(); + } else if (this._value === BooleanEventValue.False) { + this._onDidChangeToFalse.fire(); + } + } +} + class EditorContextKeysManager extends Disposable { private _editor: CommonCodeEditor; private _editorFocus: IContextKey<boolean>; + private _textInputFocus: IContextKey<boolean>; private _editorTextFocus: IContextKey<boolean>; private _editorTabMovesFocus: IContextKey<boolean>; private _editorReadonly: IContextKey<boolean>; @@ -1064,7 +1107,8 @@ class EditorContextKeysManager extends Disposable { contextKeyService.createKey('editorId', editor.getId()); this._editorFocus = EditorContextKeys.focus.bindTo(contextKeyService); - this._editorTextFocus = EditorContextKeys.textFocus.bindTo(contextKeyService); + this._textInputFocus = EditorContextKeys.textInputFocus.bindTo(contextKeyService); + this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService); this._editorTabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService); this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService); this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService); @@ -1101,8 +1145,9 @@ class EditorContextKeysManager extends Disposable { } private _updateFromFocus(): void { - this._editorFocus.set(this._editor.hasWidgetFocus()); - this._editorTextFocus.set(this._editor.isFocused()); + this._editorFocus.set(this._editor.hasWidgetFocus() && !this._editor.isSimpleWidget); + this._editorTextFocus.set(this._editor.isFocused() && !this._editor.isSimpleWidget); + this._textInputFocus.set(this._editor.isFocused()); } } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index a2ad9b25c8..748bb62cb8 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -5,7 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; @@ -34,8 +34,8 @@ export interface ITabFocus { export const TabFocus: ITabFocus = new class implements ITabFocus { private _tabFocus: boolean = false; - private _onDidChangeTabFocus: Emitter<boolean> = new Emitter<boolean>(); - public onDidChangeTabFocus: Event<boolean> = this._onDidChangeTabFocus.event; + private readonly _onDidChangeTabFocus: Emitter<boolean> = new Emitter<boolean>(); + public readonly onDidChangeTabFocus: Event<boolean> = this._onDidChangeTabFocus.event; public getTabFocusMode(): boolean { return this._tabFocus; @@ -70,7 +70,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed private _lineNumbersDigitCount: number; private _onDidChange = this._register(new Emitter<editorOptions.IConfigurationChangedEvent>()); - public onDidChange: Event<editorOptions.IConfigurationChangedEvent> = this._onDidChange.event; + public readonly onDidChange: Event<editorOptions.IConfigurationChangedEvent> = this._onDidChange.event; constructor(options: editorOptions.IEditorOptions) { super(); @@ -166,7 +166,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed } -const configurationRegistry = <IConfigurationRegistry>Registry.as(Extensions.Configuration); +const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration); const editorConfiguration: IConfigurationNode = { 'id': 'editor', 'order': 5, @@ -211,7 +211,7 @@ const editorConfiguration: IConfigurationNode = { nls.localize('lineNumbers.interval', "Line numbers are rendered every 10 lines.") ], 'default': 'on', - 'description': nls.localize('lineNumbers', "Controls the display of line numbers. Possible values are 'on', 'off', 'relative' and 'interval'.") + 'description': nls.localize('lineNumbers', "Controls the display of line numbers.") }, 'editor.rulers': { 'type': 'array', @@ -268,13 +268,13 @@ const editorConfiguration: IConfigurationNode = { 'type': 'string', 'enum': ['left', 'right'], 'default': EDITOR_DEFAULTS.viewInfo.minimap.side, - 'description': nls.localize('minimap.side', "Controls the side where to render the minimap. Possible values are \'right\' and \'left\'") + 'description': nls.localize('minimap.side', "Controls the side where to render the minimap.") }, 'editor.minimap.showSlider': { 'type': 'string', 'enum': ['always', 'mouseover'], 'default': EDITOR_DEFAULTS.viewInfo.minimap.showSlider, - 'description': nls.localize('minimap.showSlider', "Controls whether the minimap slider is automatically hidden. Possible values are \'always\' and \'mouseover\'") + 'description': nls.localize('minimap.showSlider', "Controls whether the minimap slider is automatically hidden.") }, 'editor.minimap.renderCharacters': { 'type': 'boolean', @@ -370,6 +370,11 @@ const editorConfiguration: IConfigurationNode = { ] }, "The modifier to be used to add multiple cursors with the mouse. `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on macOS. The Go To Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier.") }, + 'editor.multiCursorMergeOverlapping': { + 'type': 'boolean', + 'default': EDITOR_DEFAULTS.multiCursorMergeOverlapping, + 'description': nls.localize('multiCursorMergeOverlapping', "Merge multiple cursors when they are overlapping.") + }, 'editor.quickSuggestions': { 'anyOf': [ { @@ -515,7 +520,7 @@ const editorConfiguration: IConfigurationNode = { 'type': 'string', 'enum': ['blink', 'smooth', 'phase', 'expand', 'solid'], 'default': editorOptions.blinkingStyleToString(EDITOR_DEFAULTS.viewInfo.cursorBlinking), - 'description': nls.localize('cursorBlinking', "Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'") + 'description': nls.localize('cursorBlinking', "Control the cursor animation style.") }, 'editor.mouseWheelZoom': { 'type': 'boolean', @@ -568,13 +573,23 @@ const editorConfiguration: IConfigurationNode = { 'editor.codeLens': { 'type': 'boolean', 'default': EDITOR_DEFAULTS.contribInfo.codeLens, - 'description': nls.localize('codeLens', "Controls if the editor shows code lenses") + 'description': nls.localize('codeLens', "Controls if the editor shows CodeLens") }, 'editor.folding': { 'type': 'boolean', 'default': EDITOR_DEFAULTS.contribInfo.folding, 'description': nls.localize('folding', "Controls whether the editor has code folding enabled") }, + 'editor.foldingStrategy': { + 'type': 'string', + 'enum': ['auto', 'indentation'], + 'enumDescriptions': [ + nls.localize('foldingStrategyAuto', 'If available, use a language specific folding strategy, otherwise falls back to the indentation based strategy.'), + nls.localize('foldingStrategyIndentation', 'Always use the indentation based folding strategy') + ], + 'default': EDITOR_DEFAULTS.contribInfo.foldingStrategy, + 'description': nls.localize('foldingStrategy', "Controls the way folding ranges are computed. 'auto' picks uses a language specific folding strategy, if available. 'indentation' forces that the indentation based folding strategy is used.") + }, 'editor.showFoldingControls': { 'type': 'string', 'enum': ['always', 'mouseover'], @@ -637,6 +652,25 @@ const editorConfiguration: IConfigurationNode = { 'default': EDITOR_DEFAULTS.contribInfo.lightbulbEnabled, 'description': nls.localize('codeActions', "Enables the code action lightbulb") }, + 'editor.codeActionsOnSave': { + 'type': 'object', + 'properties': { + 'source.organizeImports': { + 'type': 'boolean', + 'description': nls.localize('codeActionsOnSave.organizeImports', "Run organize imports on save?") + } + }, + 'additionalProperties': { + 'type': 'boolean' + }, + 'default': EDITOR_DEFAULTS.contribInfo.codeActionsOnSave, + 'description': nls.localize('codeActionsOnSave', "Code action kinds to be run on save.") + }, + 'editor.codeActionsOnSaveTimeout': { + 'type': 'number', + 'default': EDITOR_DEFAULTS.contribInfo.codeActionsOnSaveTimeout, + 'description': nls.localize('codeActionsOnSaveTimeout', "Timeout for code actions run on save.") + }, 'editor.selectionClipboard': { 'type': 'boolean', 'default': EDITOR_DEFAULTS.contribInfo.selectionClipboard, @@ -653,6 +687,11 @@ const editorConfiguration: IConfigurationNode = { 'default': true, 'description': nls.localize('ignoreTrimWhitespace', "Controls if the diff editor shows changes in leading or trailing whitespace as diffs") }, + 'editor.largeFileOptimizations': { + 'type': 'boolean', + 'default': EDITOR_MODEL_DEFAULTS.largeFileOptimizations, + 'description': nls.localize('largeFileOptimizations', "Special handling for large files to disable certain memory intensive features.") + }, 'diffEditor.renderIndicators': { 'type': 'boolean', 'default': true, diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 3d7eb61c5b..294af26cd4 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -10,6 +10,8 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; import { Constants } from 'vs/editor/common/core/uint'; import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper'; +import * as arrays from 'vs/base/common/arrays'; +import * as objects from 'vs/base/common/objects'; /** * Configuration options for editor scrollbars @@ -135,6 +137,13 @@ export interface IEditorLightbulbOptions { enabled?: boolean; } +/** + * Configuration map for codeActionsOnSave + */ +export interface ICodeActionsOnSaveOptions { + [kind: string]: boolean; +} + /** * Configuration options for the editor. */ @@ -381,6 +390,11 @@ export interface IEditorOptions { * Defaults to 'alt' */ multiCursorModifier?: 'ctrlCmd' | 'alt'; + /** + * Merge overlapping selections. + * Defaults to true + */ + multiCursorMergeOverlapping?: boolean; /** * Configure the editor's accessibility support. * Defaults to 'auto'. It is best to leave this to 'auto'. @@ -460,7 +474,7 @@ export interface IEditorOptions { /** * The history mode for suggestions. */ - suggestSelection?: string; + suggestSelection?: 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix'; /** * The font size for the suggest widget. * Defaults to the editor font size. @@ -486,20 +500,28 @@ export interface IEditorOptions { * Defaults to true. */ codeLens?: boolean; - /** - * @deprecated - use codeLens instead - * @internal - */ - referenceInfos?: boolean; /** * Control the behavior and rendering of the code action lightbulb. */ lightbulb?: IEditorLightbulbOptions; + /** + * Code action kinds to be run on save. + */ + codeActionsOnSave?: ICodeActionsOnSaveOptions; + /** + * Timeout for running code actions on save. + */ + codeActionsOnSaveTimeout?: number; /** * Enable code folding - * Defaults to true in vscode and to false in monaco-editor. + * Defaults to true. */ folding?: boolean; + /** + * Selects the folding strategy. 'auto' uses the strategies contributed for the current document, 'indentation' uses the indentation based folding strategy. + * Defaults to 'auto'. + */ + foldingStrategy?: 'auto' | 'indentation'; /** * Controls whether the fold actions in the gutter stay always visible or hide unless the mouse is over the gutter. * Defaults to 'mouseover'. @@ -838,11 +860,14 @@ export interface EditorContribOptions { readonly occurrencesHighlight: boolean; readonly codeLens: boolean; readonly folding: boolean; + readonly foldingStrategy: 'auto' | 'indentation'; readonly showFoldingControls: 'always' | 'mouseover'; readonly matchBrackets: boolean; readonly find: InternalEditorFindOptions; readonly colorDecorators: boolean; readonly lightbulbEnabled: boolean; + readonly codeActionsOnSave: ICodeActionsOnSaveOptions; + readonly codeActionsOnSaveTimeout: number; } /** @@ -872,6 +897,7 @@ export interface IValidatedEditorOptions { readonly emptySelectionClipboard: boolean; readonly useTabStops: boolean; readonly multiCursorModifier: 'altKey' | 'ctrlKey' | 'metaKey'; + readonly multiCursorMergeOverlapping: boolean; readonly accessibilitySupport: 'auto' | 'off' | 'on'; readonly viewInfo: InternalEditorViewOptions; @@ -894,6 +920,7 @@ export class InternalEditorOptions { */ readonly accessibilitySupport: platform.AccessibilitySupport; readonly multiCursorModifier: 'altKey' | 'ctrlKey' | 'metaKey'; + readonly multiCursorMergeOverlapping: boolean; // ---- cursor options readonly wordSeparators: string; @@ -922,6 +949,7 @@ export class InternalEditorOptions { readOnly: boolean; accessibilitySupport: platform.AccessibilitySupport; multiCursorModifier: 'altKey' | 'ctrlKey' | 'metaKey'; + multiCursorMergeOverlapping: boolean; wordSeparators: string; autoClosingBrackets: boolean; autoIndent: boolean; @@ -942,6 +970,7 @@ export class InternalEditorOptions { this.readOnly = source.readOnly; this.accessibilitySupport = source.accessibilitySupport; this.multiCursorModifier = source.multiCursorModifier; + this.multiCursorMergeOverlapping = source.multiCursorMergeOverlapping; this.wordSeparators = source.wordSeparators; this.autoClosingBrackets = source.autoClosingBrackets; this.autoIndent = source.autoIndent; @@ -968,6 +997,7 @@ export class InternalEditorOptions { && this.readOnly === other.readOnly && this.accessibilitySupport === other.accessibilitySupport && this.multiCursorModifier === other.multiCursorModifier + && this.multiCursorMergeOverlapping === other.multiCursorMergeOverlapping && this.wordSeparators === other.wordSeparators && this.autoClosingBrackets === other.autoClosingBrackets && this.autoIndent === other.autoIndent @@ -995,6 +1025,7 @@ export class InternalEditorOptions { readOnly: (this.readOnly !== newOpts.readOnly), accessibilitySupport: (this.accessibilitySupport !== newOpts.accessibilitySupport), multiCursorModifier: (this.multiCursorModifier !== newOpts.multiCursorModifier), + multiCursorMergeOverlapping: (this.multiCursorMergeOverlapping !== newOpts.multiCursorMergeOverlapping), wordSeparators: (this.wordSeparators !== newOpts.wordSeparators), autoClosingBrackets: (this.autoClosingBrackets !== newOpts.autoClosingBrackets), autoIndent: (this.autoIndent !== newOpts.autoIndent), @@ -1058,7 +1089,7 @@ export class InternalEditorOptions { return ( a.extraEditorClassName === b.extraEditorClassName && a.disableMonospaceOptimizations === b.disableMonospaceOptimizations - && this._equalsNumberArrays(a.rulers, b.rulers) + && arrays.equals(a.rulers, b.rulers) && a.ariaLabel === b.ariaLabel && a.renderLineNumbers === b.renderLineNumbers && a.renderCustomLineNumbers === b.renderCustomLineNumbers @@ -1120,18 +1151,6 @@ export class InternalEditorOptions { ); } - private static _equalsNumberArrays(a: number[], b: number[]): boolean { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (a[i] !== b[i]) { - return false; - } - } - return true; - } - /** * @internal */ @@ -1188,10 +1207,13 @@ export class InternalEditorOptions { && a.occurrencesHighlight === b.occurrencesHighlight && a.codeLens === b.codeLens && a.folding === b.folding + && a.foldingStrategy === b.foldingStrategy && a.showFoldingControls === b.showFoldingControls && a.matchBrackets === b.matchBrackets && this._equalFindOptions(a.find, b.find) && a.colorDecorators === b.colorDecorators + && objects.equals(a.codeActionsOnSave, b.codeActionsOnSave) + && a.codeActionsOnSaveTimeout === b.codeActionsOnSaveTimeout && a.lightbulbEnabled === b.lightbulbEnabled ); } @@ -1347,6 +1369,7 @@ export interface IConfigurationChangedEvent { readonly readOnly: boolean; readonly accessibilitySupport: boolean; readonly multiCursorModifier: boolean; + readonly multiCursorMergeOverlapping: boolean; readonly wordSeparators: boolean; readonly autoClosingBrackets: boolean; readonly autoIndent: boolean; @@ -1388,6 +1411,21 @@ function _boolean<T>(value: any, defaultValue: T): boolean | T { return Boolean(value); } +function _booleanMap(value: { [key: string]: boolean }, defaultValue: { [key: string]: boolean }): { [key: string]: boolean } { + if (!value) { + return defaultValue; + } + + const out = Object.create(null); + for (const k of Object.keys(value)) { + const v = value[k]; + if (typeof v === 'boolean') { + out[k] = v; + } + } + return out; +} + function _string(value: any, defaultValue: string): string { if (typeof value !== 'string') { return defaultValue; @@ -1395,14 +1433,14 @@ function _string(value: any, defaultValue: string): string { return value; } -function _stringSet<T>(value: any, defaultValue: T, allowedValues: string[]): T { +function _stringSet<T>(value: T, defaultValue: T, allowedValues: T[]): T { if (typeof value !== 'string') { return defaultValue; } if (allowedValues.indexOf(value) === -1) { return defaultValue; } - return <T><any>value; + return value; } function _clampedInt(value: any, defaultValue: number, minimum: number, maximum: number): number { @@ -1532,6 +1570,7 @@ export class EditorOptionsValidator { emptySelectionClipboard: _boolean(opts.emptySelectionClipboard, defaults.emptySelectionClipboard), useTabStops: _boolean(opts.useTabStops, defaults.useTabStops), multiCursorModifier: multiCursorModifier, + multiCursorMergeOverlapping: _boolean(opts.multiCursorMergeOverlapping, defaults.multiCursorMergeOverlapping), accessibilitySupport: _stringSet<'auto' | 'on' | 'off'>(opts.accessibilitySupport, defaults.accessibilitySupport, ['auto', 'on', 'off']), viewInfo: viewInfo, contribInfo: contribInfo, @@ -1652,7 +1691,11 @@ export class EditorOptionsValidator { renderLineHighlight = _stringSet<'none' | 'gutter' | 'line' | 'all'>(opts.renderLineHighlight, defaults.renderLineHighlight, ['none', 'gutter', 'line', 'all']); } - const mouseWheelScrollSensitivity = _float(opts.mouseWheelScrollSensitivity, defaults.scrollbar.mouseWheelScrollSensitivity); + let mouseWheelScrollSensitivity = _float(opts.mouseWheelScrollSensitivity, defaults.scrollbar.mouseWheelScrollSensitivity); + if (mouseWheelScrollSensitivity === 0) { + // Disallow 0, as it would prevent/block scrolling + mouseWheelScrollSensitivity = 1; + } const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity); const minimap = this._sanitizeMinimapOpts(opts.minimap, defaults.minimap); @@ -1695,6 +1738,10 @@ export class EditorOptionsValidator { } else { quickSuggestions = _boolean(opts.quickSuggestions, defaults.quickSuggestions); } + // Compatibility support for acceptSuggestionOnEnter + if (typeof opts.acceptSuggestionOnEnter === 'boolean') { + opts.acceptSuggestionOnEnter = opts.acceptSuggestionOnEnter ? 'on' : 'off'; + } const find = this._santizeFindOpts(opts.find, defaults.find); return { selectionClipboard: _boolean(opts.selectionClipboard, defaults.selectionClipboard), @@ -1708,7 +1755,7 @@ export class EditorOptionsValidator { formatOnType: _boolean(opts.formatOnType, defaults.formatOnType), formatOnPaste: _boolean(opts.formatOnPaste, defaults.formatOnPaste), suggestOnTriggerCharacters: _boolean(opts.suggestOnTriggerCharacters, defaults.suggestOnTriggerCharacters), - acceptSuggestionOnEnter: typeof opts.acceptSuggestionOnEnter === 'string' ? _stringSet<'on' | 'smart' | 'off'>(opts.acceptSuggestionOnEnter, defaults.acceptSuggestionOnEnter, ['on', 'smart', 'off']) : opts.acceptSuggestionOnEnter ? 'on' : 'off', + acceptSuggestionOnEnter: _stringSet<'on' | 'smart' | 'off'>(opts.acceptSuggestionOnEnter, defaults.acceptSuggestionOnEnter, ['on', 'smart', 'off']), acceptSuggestionOnCommitCharacter: _boolean(opts.acceptSuggestionOnCommitCharacter, defaults.acceptSuggestionOnCommitCharacter), snippetSuggestions: _stringSet<'top' | 'bottom' | 'inline' | 'none'>(opts.snippetSuggestions, defaults.snippetSuggestions, ['top', 'bottom', 'inline', 'none']), wordBasedSuggestions: _boolean(opts.wordBasedSuggestions, defaults.wordBasedSuggestions), @@ -1717,13 +1764,16 @@ export class EditorOptionsValidator { suggestLineHeight: _clampedInt(opts.suggestLineHeight, defaults.suggestLineHeight, 0, 1000), selectionHighlight: _boolean(opts.selectionHighlight, defaults.selectionHighlight), occurrencesHighlight: _boolean(opts.occurrencesHighlight, defaults.occurrencesHighlight), - codeLens: _boolean(opts.codeLens, defaults.codeLens) && _boolean(opts.referenceInfos, true), + codeLens: _boolean(opts.codeLens, defaults.codeLens), folding: _boolean(opts.folding, defaults.folding), + foldingStrategy: _stringSet<'auto' | 'indentation'>(opts.foldingStrategy, defaults.foldingStrategy, ['auto', 'indentation']), showFoldingControls: _stringSet<'always' | 'mouseover'>(opts.showFoldingControls, defaults.showFoldingControls, ['always', 'mouseover']), matchBrackets: _boolean(opts.matchBrackets, defaults.matchBrackets), find: find, colorDecorators: _boolean(opts.colorDecorators, defaults.colorDecorators), - lightbulbEnabled: _boolean(opts.lightbulb ? opts.lightbulb.enabled : false, defaults.lightbulbEnabled) + lightbulbEnabled: _boolean(opts.lightbulb ? opts.lightbulb.enabled : false, defaults.lightbulbEnabled), + codeActionsOnSave: _booleanMap(opts.codeActionsOnSave, {}), + codeActionsOnSaveTimeout: _clampedInt(opts.codeActionsOnSaveTimeout, defaults.codeActionsOnSaveTimeout, 1, 10000) }; } } @@ -1758,6 +1808,7 @@ export class InternalEditorOptionsFactory { emptySelectionClipboard: opts.emptySelectionClipboard, useTabStops: opts.useTabStops, multiCursorModifier: opts.multiCursorModifier, + multiCursorMergeOverlapping: opts.multiCursorMergeOverlapping, accessibilitySupport: opts.accessibilitySupport, viewInfo: { @@ -1820,11 +1871,14 @@ export class InternalEditorOptionsFactory { occurrencesHighlight: (accessibilityIsOn ? false : opts.contribInfo.occurrencesHighlight), // DISABLED WHEN SCREEN READER IS ATTACHED codeLens: (accessibilityIsOn ? false : opts.contribInfo.codeLens), // DISABLED WHEN SCREEN READER IS ATTACHED folding: (accessibilityIsOn ? false : opts.contribInfo.folding), // DISABLED WHEN SCREEN READER IS ATTACHED + foldingStrategy: opts.contribInfo.foldingStrategy, showFoldingControls: opts.contribInfo.showFoldingControls, matchBrackets: (accessibilityIsOn ? false : opts.contribInfo.matchBrackets), // DISABLED WHEN SCREEN READER IS ATTACHED find: opts.contribInfo.find, colorDecorators: opts.contribInfo.colorDecorators, - lightbulbEnabled: opts.contribInfo.lightbulbEnabled + lightbulbEnabled: opts.contribInfo.lightbulbEnabled, + codeActionsOnSave: opts.contribInfo.codeActionsOnSave, + codeActionsOnSaveTimeout: opts.contribInfo.codeActionsOnSaveTimeout } }; } @@ -1964,6 +2018,7 @@ export class InternalEditorOptionsFactory { readOnly: opts.readOnly, accessibilitySupport: accessibilitySupport, multiCursorModifier: opts.multiCursorModifier, + multiCursorMergeOverlapping: opts.multiCursorMergeOverlapping, wordSeparators: opts.wordSeparators, autoClosingBrackets: opts.autoClosingBrackets, autoIndent: opts.autoIndent, @@ -1984,31 +2039,31 @@ export class InternalEditorOptionsFactory { * @internal */ export interface IEditorLayoutProviderOpts { - outerWidth: number; - outerHeight: number; + readonly outerWidth: number; + readonly outerHeight: number; - showGlyphMargin: boolean; - lineHeight: number; + readonly showGlyphMargin: boolean; + readonly lineHeight: number; - showLineNumbers: boolean; - lineNumbersMinChars: number; - lineNumbersDigitCount: number; + readonly showLineNumbers: boolean; + readonly lineNumbersMinChars: number; + readonly lineNumbersDigitCount: number; - lineDecorationsWidth: number; + readonly lineDecorationsWidth: number; - typicalHalfwidthCharacterWidth: number; - maxDigitWidth: number; + readonly typicalHalfwidthCharacterWidth: number; + readonly maxDigitWidth: number; - verticalScrollbarWidth: number; - verticalScrollbarHasArrows: boolean; - scrollbarArrowSize: number; - horizontalScrollbarHeight: number; + readonly verticalScrollbarWidth: number; + readonly verticalScrollbarHasArrows: boolean; + readonly scrollbarArrowSize: number; + readonly horizontalScrollbarHeight: number; - minimap: boolean; - minimapSide: string; - minimapRenderCharacters: boolean; - minimapMaxColumn: number; - pixelRatio: number; + readonly minimap: boolean; + readonly minimapSide: string; + readonly minimapRenderCharacters: boolean; + readonly minimapMaxColumn: number; + readonly pixelRatio: number; } /** @@ -2074,18 +2129,19 @@ export class EditorLayoutProvider { } // Given: - // viewportColumn = (contentWidth - verticalScrollbarWidth) / typicalHalfwidthCharacterWidth + // (leaving 2px for the cursor to have space after the last character) + // viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth // minimapWidth = viewportColumn * minimapCharWidth // contentWidth = remainingWidth - minimapWidth // What are good values for contentWidth and minimapWidth ? - // minimapWidth = ((contentWidth - verticalScrollbarWidth) / typicalHalfwidthCharacterWidth) * minimapCharWidth - // typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth) * minimapCharWidth - // typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth) * minimapCharWidth - // (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth) * minimapCharWidth - // minimapWidth = ((remainingWidth - verticalScrollbarWidth) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth) + // minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth + // typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth + // typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth + // (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth + // minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth) - minimapWidth = Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))); + minimapWidth = Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))); let minimapColumns = minimapWidth / minimapCharWidth; if (minimapColumns > minimapMaxColumn) { minimapWidth = Math.floor(minimapMaxColumn * minimapCharWidth); @@ -2103,7 +2159,8 @@ export class EditorLayoutProvider { } } - const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth) / typicalHalfwidthCharacterWidth)); + // (leaving 2px for the cursor to have space after the last character) + const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth)); const verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0); @@ -2172,7 +2229,8 @@ export const EDITOR_MODEL_DEFAULTS = { tabSize: 4, insertSpaces: true, detectIndentation: true, - trimAutoWhitespace: true + trimAutoWhitespace: true, + largeFileOptimizations: true }; /** @@ -2200,6 +2258,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { emptySelectionClipboard: true, useTabStops: true, multiCursorModifier: 'altKey', + multiCursorMergeOverlapping: true, accessibilitySupport: 'auto', viewInfo: { @@ -2276,6 +2335,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { occurrencesHighlight: true, codeLens: true, folding: true, + foldingStrategy: 'auto', showFoldingControls: 'mouseover', matchBrackets: true, find: { @@ -2284,6 +2344,8 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { globalFindClipboard: false }, colorDecorators: true, - lightbulbEnabled: true + lightbulbEnabled: true, + codeActionsOnSave: {}, + codeActionsOnSaveTimeout: 750 }, }; diff --git a/src/vs/editor/common/config/editorZoom.ts b/src/vs/editor/common/config/editorZoom.ts index a74c5b435c..1e23049be2 100644 --- a/src/vs/editor/common/config/editorZoom.ts +++ b/src/vs/editor/common/config/editorZoom.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface IEditorZoom { onDidChangeZoomLevel: Event<number>; @@ -16,8 +16,8 @@ export const EditorZoom: IEditorZoom = new class implements IEditorZoom { private _zoomLevel: number = 0; - private _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>(); - public onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event; + private readonly _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>(); + public readonly onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event; public getZoomLevel(): number { return this._zoomLevel; diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index fbc3a32966..985cd86c96 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -19,7 +19,7 @@ import { RawContentChangedType } from 'vs/editor/common/model/textModelEvents'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITextModel, IIdentifiedSingleEditOperation, TrackedRangeStickiness } from 'vs/editor/common/model'; function containsLineMappingChanged(events: viewEvents.ViewEvent[]): boolean { @@ -87,6 +87,14 @@ export class CursorModelState { export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { + public static MAX_CURSOR_COUNT = 10000; + + private readonly _onDidReachMaxCursorCount: Emitter<void> = this._register(new Emitter<void>()); + public readonly onDidReachMaxCursorCount: Event<void> = this._onDidReachMaxCursorCount.event; + + private readonly _onDidAttemptReadOnlyEdit: Emitter<void> = this._register(new Emitter<void>()); + public readonly onDidAttemptReadOnlyEdit: Event<void> = this._onDidAttemptReadOnlyEdit.event; + private readonly _onDidChange: Emitter<CursorStateChangedEvent> = this._register(new Emitter<CursorStateChangedEvent>()); public readonly onDidChange: Event<CursorStateChangedEvent> = this._onDidChange.event; @@ -185,6 +193,11 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { } public setStates(source: string, reason: CursorChangeReason, states: CursorState[]): void { + if (states.length > Cursor.MAX_CURSOR_COUNT) { + states = states.slice(0, Cursor.MAX_CURSOR_COUNT); + this._onDidReachMaxCursorCount.fire(void 0); + } + const oldState = new CursorModelState(this._model, this); this._cursors.setStates(states); @@ -361,7 +374,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { private _interpretCommandResult(cursorState: Selection[]): void { if (!cursorState || cursorState.length === 0) { - return; + cursorState = this._cursors.readSelectionFromMarkers(); } this._columnSelectData = null; @@ -456,12 +469,19 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { if (this._configuration.editor.readOnly) { // All the remaining handlers will try to edit the model, // but we cannot edit when read only... + this._onDidAttemptReadOnlyEdit.fire(void 0); return; } const oldState = new CursorModelState(this._model, this); let cursorChangeReason = CursorChangeReason.NotSet; + if (handlerId !== H.Undo && handlerId !== H.Redo) { + // TODO@Alex: if the undo/redo stack contains non-null selections + // it would also be OK to stop tracking selections here + this._cursors.stopTrackingSelections(); + } + // ensure valid state on all cursors this._cursors.ensureValidState(); @@ -510,6 +530,10 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { this._isHandling = false; + if (handlerId !== H.Undo && handlerId !== H.Redo) { + this._cursors.startTrackingSelections(); + } + if (this._emitStateChangedIfNecessary(source, cursorChangeReason, oldState)) { this._revealRange(RevealTarget.Primary, viewEvents.VerticalRevealType.Simple, true, editorCommon.ScrollType.Smooth); } diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index 26d6ef4038..7b32659a69 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -31,6 +31,20 @@ export class CursorCollection { this.killSecondaryCursors(); } + public startTrackingSelections(): void { + this.primaryCursor.startTrackingSelection(this.context); + for (let i = 0, len = this.secondaryCursors.length; i < len; i++) { + this.secondaryCursors[i].startTrackingSelection(this.context); + } + } + + public stopTrackingSelections(): void { + this.primaryCursor.stopTrackingSelection(this.context); + for (let i = 0, len = this.secondaryCursors.length; i < len; i++) { + this.secondaryCursors[i].stopTrackingSelection(this.context); + } + } + public updateContext(context: CursorContext): void { this.context = context; } @@ -193,6 +207,10 @@ export class CursorCollection { const currentViewSelection = current.viewSelection; const nextViewSelection = next.viewSelection; + if (!this.context.config.multiCursorMergeOverlapping) { + continue; + } + let shouldMergeCursors: boolean; if (nextViewSelection.isEmpty() || currentViewSelection.isEmpty()) { // Merge touching cursors if one of them is collapsed diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 3ff06891c8..d9021118c2 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -78,6 +78,7 @@ export class CursorConfiguration { public readonly useTabStops: boolean; public readonly wordSeparators: string; public readonly emptySelectionClipboard: boolean; + public readonly multiCursorMergeOverlapping: boolean; public readonly autoClosingBrackets: boolean; public readonly autoIndent: boolean; public readonly autoClosingPairsOpen: CharacterMap; @@ -92,6 +93,7 @@ export class CursorConfiguration { e.layoutInfo || e.wordSeparators || e.emptySelectionClipboard + || e.multiCursorMergeOverlapping || e.autoClosingBrackets || e.useTabStops || e.lineHeight @@ -118,6 +120,7 @@ export class CursorConfiguration { this.useTabStops = c.useTabStops; this.wordSeparators = c.wordSeparators; this.emptySelectionClipboard = c.emptySelectionClipboard; + this.multiCursorMergeOverlapping = c.multiCursorMergeOverlapping; this.autoClosingBrackets = c.autoClosingBrackets; this.autoIndent = c.autoIndent; diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 1009720fec..37f2e2709b 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -18,6 +18,7 @@ import { IndentAction, EnterAction } from 'vs/editor/common/modes/languageConfig import { SurroundSelectionCommand } from 'vs/editor/common/commands/surroundSelectionCommand'; import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter'; import { getMapForWordSeparators, WordCharacterClass } from 'vs/editor/common/controller/wordCharacterClassifier'; +import { CharCode } from 'vs/base/common/charCode'; export class TypeOperations { @@ -123,6 +124,15 @@ export class TypeOperations { return multicursorText; } + // Remove trailing \n if present + if (text.charCodeAt(text.length - 1) === CharCode.LineFeed) { + text = text.substr(0, text.length - 1); + } + let lines = text.split(/\r\n|\r|\n/); + if (lines.length === selections.length) { + return lines; + } + return null; } diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index e363728c02..6d29895d59 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -24,6 +24,10 @@ interface IFindWordResult { * The word type. */ wordType: WordType; + /** + * The reason the word ended. + */ + nextCharClass: WordCharacterClass; } const enum WordType { @@ -39,9 +43,9 @@ export const enum WordNavigationType { export class WordOperations { - private static _createWord(lineContent: string, wordType: WordType, start: number, end: number): IFindWordResult { + private static _createWord(lineContent: string, wordType: WordType, nextCharClass: WordCharacterClass, start: number, end: number): IFindWordResult { // console.log('WORD ==> ' + start + ' => ' + end + ':::: <<<' + lineContent.substring(start, end) + '>>>'); - return { start: start, end: end, wordType: wordType }; + return { start: start, end: end, wordType: wordType, nextCharClass: nextCharClass }; } private static _findPreviousWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult { @@ -57,23 +61,23 @@ export class WordOperations { if (chClass === WordCharacterClass.Regular) { if (wordType === WordType.Separator) { - return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); + return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); } wordType = WordType.Regular; } else if (chClass === WordCharacterClass.WordSeparator) { if (wordType === WordType.Regular) { - return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); + return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); } wordType = WordType.Separator; } else if (chClass === WordCharacterClass.Whitespace) { if (wordType !== WordType.None) { - return this._createWord(lineContent, wordType, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); + return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1)); } } } if (wordType !== WordType.None) { - return this._createWord(lineContent, wordType, 0, this._findEndOfWord(lineContent, wordSeparators, wordType, 0)); + return this._createWord(lineContent, wordType, WordCharacterClass.Whitespace, 0, this._findEndOfWord(lineContent, wordSeparators, wordType, 0)); } return null; @@ -113,23 +117,23 @@ export class WordOperations { if (chClass === WordCharacterClass.Regular) { if (wordType === WordType.Separator) { - return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); + return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); } wordType = WordType.Regular; } else if (chClass === WordCharacterClass.WordSeparator) { if (wordType === WordType.Regular) { - return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); + return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); } wordType = WordType.Separator; } else if (chClass === WordCharacterClass.Whitespace) { if (wordType !== WordType.None) { - return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); + return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex); } } } if (wordType !== WordType.None) { - return this._createWord(lineContent, wordType, this._findStartOfWord(lineContent, wordSeparators, wordType, len - 1), len); + return this._createWord(lineContent, wordType, WordCharacterClass.Whitespace, this._findStartOfWord(lineContent, wordSeparators, wordType, len - 1), len); } return null; @@ -167,6 +171,12 @@ export class WordOperations { let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, column)); if (wordNavigationType === WordNavigationType.WordStart) { + if (prevWordOnLine && prevWordOnLine.wordType === WordType.Separator) { + if (prevWordOnLine.end - prevWordOnLine.start === 1 && prevWordOnLine.nextCharClass === WordCharacterClass.Regular) { + // Skip over a word made up of one single separator and followed by a regular character + prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1)); + } + } if (prevWordOnLine) { column = prevWordOnLine.start + 1; } else { @@ -200,6 +210,12 @@ export class WordOperations { let nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, column)); if (wordNavigationType === WordNavigationType.WordEnd) { + if (nextWordOnLine && nextWordOnLine.wordType === WordType.Separator) { + if (nextWordOnLine.end - nextWordOnLine.start === 1 && nextWordOnLine.nextCharClass === WordCharacterClass.Regular) { + // Skip over a word made up of one single separator and followed by a regular character + nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1)); + } + } if (nextWordOnLine) { column = nextWordOnLine.end + 1; } else { @@ -374,20 +390,20 @@ export class WordOperations { public static word(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, position: Position): SingleCursorState { const wordSeparators = getMapForWordSeparators(config.wordSeparators); let prevWord = WordOperations._findPreviousWordOnLine(wordSeparators, model, position); - let isInPrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start < position.column - 1 && position.column - 1 <= prevWord.end); let nextWord = WordOperations._findNextWordOnLine(wordSeparators, model, position); - let isInNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start < position.column - 1 && position.column - 1 <= nextWord.end); if (!inSelectionMode) { // Entering word selection for the first time + const isTouchingPrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start <= position.column - 1 && position.column - 1 <= prevWord.end); + const isTouchingNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start <= position.column - 1 && position.column - 1 <= nextWord.end); let startColumn: number; let endColumn: number; - if (isInPrevWord) { + if (isTouchingPrevWord) { startColumn = prevWord.start + 1; endColumn = prevWord.end + 1; - } else if (isInNextWord) { + } else if (isTouchingNextWord) { startColumn = nextWord.start + 1; endColumn = nextWord.end + 1; } else { @@ -409,13 +425,16 @@ export class WordOperations { ); } + const isInsidePrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start < position.column - 1 && position.column - 1 < prevWord.end); + const isInsideNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start < position.column - 1 && position.column - 1 < nextWord.end); + let startColumn: number; let endColumn: number; - if (isInPrevWord) { + if (isInsidePrevWord) { startColumn = prevWord.start + 1; endColumn = prevWord.end + 1; - } else if (isInNextWord) { + } else if (isInsideNextWord) { startColumn = nextWord.start + 1; endColumn = nextWord.end + 1; } else { diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 8ac44d4145..e983c7c888 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -16,12 +16,14 @@ export class OneCursor { public viewState: SingleCursorState; private _selTrackedRange: string; + private _trackSelection: boolean; constructor(context: CursorContext) { this.modelState = null; this.viewState = null; this._selTrackedRange = null; + this._trackSelection = true; this._setState( context, @@ -31,6 +33,28 @@ export class OneCursor { } public dispose(context: CursorContext): void { + this._removeTrackedRange(context); + } + + public startTrackingSelection(context: CursorContext): void { + this._trackSelection = true; + this._updateTrackedRange(context); + } + + public stopTrackingSelection(context: CursorContext): void { + this._trackSelection = false; + this._removeTrackedRange(context); + } + + private _updateTrackedRange(context: CursorContext): void { + if (!this._trackSelection) { + // don't track the selection + return; + } + this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + } + + private _removeTrackedRange(context: CursorContext): void { this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, null, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); } @@ -93,14 +117,9 @@ export class OneCursor { viewState = new SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns); } - if (this.modelState && this.viewState && this.modelState.equals(modelState) && this.viewState.equals(viewState)) { - // No-op, early return - return; - } - this.modelState = modelState; this.viewState = viewState; - this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, this.modelState.selection, TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges); + this._updateTrackedRange(context); } } diff --git a/src/vs/editor/common/core/lineTokens.ts b/src/vs/editor/common/core/lineTokens.ts index 18dfd8cfbd..09b3f2de83 100644 --- a/src/vs/editor/common/core/lineTokens.ts +++ b/src/vs/editor/common/core/lineTokens.ts @@ -13,6 +13,7 @@ export interface IViewLineTokens { getEndOffset(tokenIndex: number): number; getClassName(tokenIndex: number): string; getInlineStyle(tokenIndex: number, colorMap: string[]): string; + findTokenIndexAtOffset(offset: number): number; } export class LineTokens implements IViewLineTokens { @@ -207,4 +208,8 @@ export class SlicedLineTokens implements IViewLineTokens { public getInlineStyle(tokenIndex: number, colorMap: string[]): string { return this._source.getInlineStyle(this._firstTokenIndex + tokenIndex, colorMap); } + + public findTokenIndexAtOffset(offset: number): number { + return this._source.findTokenIndexAtOffset(offset + this._startOffset - this._deltaOffset) - this._firstTokenIndex; + } } diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index cebfbec38a..44748d8e5e 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -284,7 +284,7 @@ class LineChange implements ILineChange { const originalCharSequence = originalLineSequence.getCharSequence(diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1); const modifiedCharSequence = modifiedLineSequence.getCharSequence(diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1); - let rawChanges = computeDiff(originalCharSequence, modifiedCharSequence, continueProcessingPredicate, false); + let rawChanges = computeDiff(originalCharSequence, modifiedCharSequence, continueProcessingPredicate, true); if (shouldPostProcessCharChanges) { rawChanges = postProcessCharChanges(rawChanges); diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 285e3f8134..df7ba10822 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -199,9 +199,13 @@ export interface ICursorState { * A (serializable) state of the view. */ export interface IViewState { - scrollTop: number; - scrollTopWithoutViewZones: number; + /** written by previous versions */ + scrollTop?: number; + /** written by previous versions */ + scrollTopWithoutViewZones?: number; scrollLeft: number; + firstPosition: IPosition; + firstPositionDeltaTop: number; } /** * A (serializable) state of the code editor. @@ -505,6 +509,7 @@ export interface IThemeDecorationRenderOptions { textDecoration?: string; cursor?: string; color?: string | ThemeColor; + opacity?: number; letterSpacing?: string; gutterIconPath?: string | UriComponents; diff --git a/src/vs/editor/common/editorContextKeys.ts b/src/vs/editor/common/editorContextKeys.ts index d0e033307f..4781eafcbd 100644 --- a/src/vs/editor/common/editorContextKeys.ts +++ b/src/vs/editor/common/editorContextKeys.ts @@ -10,12 +10,17 @@ export namespace EditorContextKeys { /** * A context key that is set when the editor's text has focus (cursor is blinking). */ - export const textFocus = new RawContextKey<boolean>('editorTextFocus', false); + export const editorTextFocus = new RawContextKey<boolean>('editorTextFocus', false); /** * A context key that is set when the editor's text or an editor's widget has focus. */ export const focus = new RawContextKey<boolean>('editorFocus', false); + /** + * A context key that is set when any editor input has focus (regular editor, repl input...). + */ + export const textInputFocus = new RawContextKey<boolean>('textInputFocus', false); + export const readOnly = new RawContextKey<boolean>('editorReadonly', false); export const writable: ContextKeyExpr = readOnly.toNegated(); export const hasNonEmptySelection = new RawContextKey<boolean>('editorHasSelection', false); diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index ab391b6720..6777d49ea2 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -15,6 +15,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { ModelRawContentChangedEvent, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelOptionsChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelContentChange } from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { ITextSnapshot } from 'vs/platform/files/common/files'; +import { SearchData } from 'vs/editor/common/model/textModelSearch'; /** * Vertical Lane in the overview ruler of the editor. @@ -80,7 +81,12 @@ export interface IModelDecorationOptions { * Always render the decoration (even when the range it encompasses is collapsed). * @internal */ - readonly showIfCollapsed?: boolean; + showIfCollapsed?: boolean; + /** + * Specifies the stack order of a decoration. + * A decoration with greater stack order is always in front of a decoration with a lower stack order. + */ + zIndex?: number; /** * If set, render this decoration in the overview ruler. */ @@ -103,6 +109,10 @@ export interface IModelDecorationOptions { * to have a background color decoration. */ inlineClassName?: string; + /** + * If there is an `inlineClassName` which affects letter spacing. + */ + inlineClassNameAffectsLetterSpacing?: boolean; /** * If set, the decoration will be rendered before the text with this CSS class name. */ @@ -389,6 +399,8 @@ export interface ITextModelCreationOptions { detectIndentation: boolean; trimAutoWhitespace: boolean; defaultEOL: DefaultEndOfLine; + isForSimpleWidget: boolean; + largeFileOptimizations: boolean; } export interface ITextModelUpdateOptions { @@ -433,6 +445,15 @@ export enum TrackedRangeStickiness { GrowsOnlyWhenTypingAfter = 3, } +/** + * @internal + */ +export interface IActiveIndentGuideInfo { + startLineNumber: number; + endLineNumber: number; + indent: number; +} + /** * A model. */ @@ -448,6 +469,12 @@ export interface ITextModel { */ readonly id: string; + /** + * This model is constructed for a simple widget code editor. + * @internal + */ + readonly isForSimpleWidget: boolean; + /** * If true, the text model might contain RTL. * If false, the text model **contains only** contain LTR. @@ -553,6 +580,10 @@ export interface ITextModel { */ getLineContent(lineNumber: number): string; + /** + * Get the text length for a certain line. + */ + getLineLength(lineNumber: number): number; /** * Get the text for all lines. @@ -643,11 +674,16 @@ export interface ITextModel { isDisposed(): boolean; /** - * Only basic mode supports allowed on this model because it is simply too large. - * (tokenization is allowed and other basic supports) * @internal */ - isTooLargeForHavingARichMode(): boolean; + tokenizeViewport(startLineNumber: number, endLineNumber: number): void; + + /** + * This model is so large that it would not be a good idea to sync it over + * to web workers or other places. + * @internal + */ + isTooLargeForSyncing(): boolean; /** * The file is so large, that even tokenization is disabled. @@ -829,6 +865,11 @@ export interface ITextModel { */ matchBracket(position: IPosition): [Range, Range]; + /** + * @internal + */ + getActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo; + /** * @internal */ @@ -989,6 +1030,13 @@ export interface ITextModel { */ redo(): Selection[]; + /** + * @deprecated Please use `onDidChangeContent` instead. + * An event emitted when the contents of the model have changed. + * @internal + * @event + */ + onDidChangeRawContentFast(listener: (e: ModelRawContentChangedEvent) => void): IDisposable; /** * @deprecated Please use `onDidChangeContent` instead. * An event emitted when the contents of the model have changed. @@ -1054,6 +1102,12 @@ export interface ITextModel { * @internal */ isAttachedToEditor(): boolean; + + /** + * Returns the count of editors this model is attached to. + * @internal + */ + getAttachedEditorCount(): number; } /** @@ -1100,6 +1154,7 @@ export interface ITextBuffer { setEOL(newEOL: '\r\n' | '\n'): void; applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult; + findMatchesLineByLine?(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[]; } /** @@ -1120,6 +1175,5 @@ export class ApplyEditsResult { */ export interface IInternalModelContentChange extends IModelContentChange { range: Range; - rangeOffset: number; forceMoveMarkers: boolean; } diff --git a/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts b/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts deleted file mode 100644 index 71be2cfbe3..0000000000 --- a/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts +++ /dev/null @@ -1,323 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { CharCode } from 'vs/base/common/charCode'; - -export class LeafOffsetLenEdit { - constructor( - public readonly start: number, - public readonly length: number, - public readonly text: string - ) { } -} - -export class BufferPiece { - private readonly _str: string; - public get text(): string { return this._str; } - - private readonly _lineStarts: Uint32Array; - - constructor(str: string, lineStarts: Uint32Array = null) { - this._str = str; - if (lineStarts === null) { - this._lineStarts = createLineStartsFast(str); - } else { - this._lineStarts = lineStarts; - } - } - - public length(): number { - return this._str.length; - } - - public newLineCount(): number { - return this._lineStarts.length; - } - - public lineStartFor(relativeLineIndex: number): number { - return this._lineStarts[relativeLineIndex]; - } - - public charCodeAt(index: number): number { - return this._str.charCodeAt(index); - } - - public substr(from: number, length: number): string { - return this._str.substr(from, length); - } - - public findLineStartBeforeOffset(offset: number): number { - if (this._lineStarts.length === 0 || offset < this._lineStarts[0]) { - return -1; - } - - let low = 0, high = this._lineStarts.length - 1; - - while (low < high) { - let mid = low + Math.ceil((high - low) / 2); - let lineStart = this._lineStarts[mid]; - - if (offset === lineStart) { - return mid; - } else if (offset < lineStart) { - high = mid - 1; - } else { - low = mid; - } - } - - return low; - } - - public findLineFirstNonWhitespaceIndex(searchStartOffset: number): number { - for (let i = searchStartOffset, len = this._str.length; i < len; i++) { - const chCode = this._str.charCodeAt(i); - if (chCode === CharCode.CarriageReturn || chCode === CharCode.LineFeed) { - // Reached EOL - return -2; - } - if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { - return i; - } - } - return -1; - } - - public findLineLastNonWhitespaceIndex(searchStartOffset: number): number { - for (let i = searchStartOffset - 1; i >= 0; i--) { - const chCode = this._str.charCodeAt(i); - if (chCode === CharCode.CarriageReturn || chCode === CharCode.LineFeed) { - // Reached EOL - return -2; - } - if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { - return i; - } - } - return -1; - } - - public static normalizeEOL(target: BufferPiece, eol: '\r\n' | '\n'): BufferPiece { - return new BufferPiece(target._str.replace(/\r\n|\r|\n/g, eol)); - } - - public static deleteLastChar(target: BufferPiece): BufferPiece { - const targetCharsLength = target.length(); - const targetLineStartsLength = target.newLineCount(); - const targetLineStarts = target._lineStarts; - - let newLineStartsLength; - if (targetLineStartsLength > 0 && targetLineStarts[targetLineStartsLength - 1] === targetCharsLength) { - newLineStartsLength = targetLineStartsLength - 1; - } else { - newLineStartsLength = targetLineStartsLength; - } - - let newLineStarts = new Uint32Array(newLineStartsLength); - newLineStarts.set(targetLineStarts); - - return new BufferPiece( - target._str.substr(0, targetCharsLength - 1), - newLineStarts - ); - } - - public static insertFirstChar(target: BufferPiece, character: number): BufferPiece { - const targetLineStartsLength = target.newLineCount(); - const targetLineStarts = target._lineStarts; - const insertLineStart = ((character === CharCode.CarriageReturn && (targetLineStartsLength === 0 || targetLineStarts[0] !== 1 || target.charCodeAt(0) !== CharCode.LineFeed)) || (character === CharCode.LineFeed)); - - const newLineStartsLength = (insertLineStart ? targetLineStartsLength + 1 : targetLineStartsLength); - let newLineStarts = new Uint32Array(newLineStartsLength); - - if (insertLineStart) { - newLineStarts[0] = 1; - for (let i = 0; i < targetLineStartsLength; i++) { - newLineStarts[i + 1] = targetLineStarts[i] + 1; - } - } else { - for (let i = 0; i < targetLineStartsLength; i++) { - newLineStarts[i] = targetLineStarts[i] + 1; - } - } - - return new BufferPiece( - String.fromCharCode(character) + target._str, - newLineStarts - ); - } - - public static join(first: BufferPiece, second: BufferPiece): BufferPiece { - const firstCharsLength = first._str.length; - - const firstLineStartsLength = first._lineStarts.length; - const secondLineStartsLength = second._lineStarts.length; - - const firstLineStarts = first._lineStarts; - const secondLineStarts = second._lineStarts; - - const newLineStartsLength = firstLineStartsLength + secondLineStartsLength; - let newLineStarts = new Uint32Array(newLineStartsLength); - newLineStarts.set(firstLineStarts, 0); - for (let i = 0; i < secondLineStartsLength; i++) { - newLineStarts[i + firstLineStartsLength] = secondLineStarts[i] + firstCharsLength; - } - - return new BufferPiece(first._str + second._str, newLineStarts); - } - - public static replaceOffsetLen(target: BufferPiece, edits: LeafOffsetLenEdit[], idealLeafLength: number, maxLeafLength: number, result: BufferPiece[]): void { - const editsSize = edits.length; - const originalCharsLength = target.length(); - if (editsSize === 1 && edits[0].text.length === 0 && edits[0].start === 0 && edits[0].length === originalCharsLength) { - // special case => deleting everything - return; - } - - let pieces: string[] = new Array<string>(2 * editsSize + 1); - let originalFromIndex = 0; - let piecesTextLength = 0; - for (let i = 0; i < editsSize; i++) { - const edit = edits[i]; - - const originalText = target._str.substr(originalFromIndex, edit.start - originalFromIndex); - pieces[2 * i] = originalText; - piecesTextLength += originalText.length; - - originalFromIndex = edit.start + edit.length; - pieces[2 * i + 1] = edit.text; - piecesTextLength += edit.text.length; - } - - // maintain the chars that survive to the right of the last edit - let text = target._str.substr(originalFromIndex, originalCharsLength - originalFromIndex); - pieces[2 * editsSize] = text; - piecesTextLength += text.length; - - let targetDataLength = piecesTextLength > maxLeafLength ? idealLeafLength : piecesTextLength; - let targetDataOffset = 0; - - let data: string = ''; - - for (let pieceIndex = 0, pieceCount = pieces.length; pieceIndex < pieceCount; pieceIndex++) { - const pieceText = pieces[pieceIndex]; - const pieceLength = pieceText.length; - if (pieceLength === 0) { - continue; - } - - let pieceOffset = 0; - while (pieceOffset < pieceLength) { - if (targetDataOffset >= targetDataLength) { - result.push(new BufferPiece(data)); - targetDataLength = piecesTextLength > maxLeafLength ? idealLeafLength : piecesTextLength; - targetDataOffset = 0; - data = ''; - } - - let writingCnt = min(pieceLength - pieceOffset, targetDataLength - targetDataOffset); - data += pieceText.substr(pieceOffset, writingCnt); - pieceOffset += writingCnt; - targetDataOffset += writingCnt; - piecesTextLength -= writingCnt; - - // check that the buffer piece does not end in a \r or high surrogate - if (targetDataOffset === targetDataLength && piecesTextLength > 0) { - const lastChar = data.charCodeAt(targetDataLength - 1); - if (lastChar === CharCode.CarriageReturn || (0xD800 <= lastChar && lastChar <= 0xDBFF)) { - // move lastChar over to next buffer piece - targetDataLength -= 1; - pieceOffset -= 1; - targetDataOffset -= 1; - piecesTextLength += 1; - data = data.substr(0, data.length - 1); - } - } - } - } - - result.push(new BufferPiece(data)); - } -} - -function min(a: number, b: number): number { - return (a < b ? a : b); -} - -export function createUint32Array(arr: number[]): Uint32Array { - let r = new Uint32Array(arr.length); - r.set(arr, 0); - return r; -} - -export class LineStarts { - constructor( - public readonly lineStarts: Uint32Array, - public readonly cr: number, - public readonly lf: number, - public readonly crlf: number, - public readonly isBasicASCII: boolean - ) { } -} - -export function createLineStartsFast(str: string): Uint32Array { - let r: number[] = [], rLength = 0; - for (let i = 0, len = str.length; i < len; i++) { - const chr = str.charCodeAt(i); - - if (chr === CharCode.CarriageReturn) { - if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { - // \r\n... case - r[rLength++] = i + 2; - i++; // skip \n - } else { - // \r... case - r[rLength++] = i + 1; - } - } else if (chr === CharCode.LineFeed) { - r[rLength++] = i + 1; - } - } - return createUint32Array(r); -} - -export function createLineStarts(r: number[], str: string): LineStarts { - r.length = 0; - - let rLength = 0; - let cr = 0, lf = 0, crlf = 0; - let isBasicASCII = true; - for (let i = 0, len = str.length; i < len; i++) { - const chr = str.charCodeAt(i); - - if (chr === CharCode.CarriageReturn) { - if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { - // \r\n... case - crlf++; - r[rLength++] = i + 2; - i++; // skip \n - } else { - cr++; - // \r... case - r[rLength++] = i + 1; - } - } else if (chr === CharCode.LineFeed) { - lf++; - r[rLength++] = i + 1; - } else { - if (isBasicASCII) { - if (chr !== CharCode.Tab && (chr < 32 || chr > 126)) { - isBasicASCII = false; - } - } - } - } - - const result = new LineStarts(createUint32Array(r), cr, lf, crlf, isBasicASCII); - r.length = 0; - - return result; -} diff --git a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts deleted file mode 100644 index 1c65e85c18..0000000000 --- a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts +++ /dev/null @@ -1,1526 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { CharCode } from 'vs/base/common/charCode'; -import { ITextBuffer, EndOfLinePreference, IIdentifiedSingleEditOperation, ApplyEditsResult, ISingleEditOperationIdentifier, IInternalModelContentChange } from 'vs/editor/common/model'; -import { BufferPiece, LeafOffsetLenEdit } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; -import { Position } from 'vs/editor/common/core/position'; -import { Range } from 'vs/editor/common/core/range'; -import * as strings from 'vs/base/common/strings'; -import { ITextSnapshot } from 'vs/platform/files/common/files'; - -export interface IValidatedEditOperation { - sortIndex: number; - identifier: ISingleEditOperationIdentifier; - range: Range; - rangeOffset: number; - rangeLength: number; - lines: string[]; - forceMoveMarkers: boolean; - isAutoWhitespaceEdit: boolean; -} - -export class ChunksTextBuffer implements ITextBuffer { - - private _BOM: string; - private _actual: Buffer; - private _mightContainRTL: boolean; - private _mightContainNonBasicASCII: boolean; - - constructor(pieces: BufferPiece[], _averageChunkSize: number, BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, isBasicASCII: boolean) { - this._BOM = BOM; - const averageChunkSize = Math.floor(Math.min(65536.0, Math.max(128.0, _averageChunkSize))); - const delta = Math.floor(averageChunkSize / 3); - const min = averageChunkSize - delta; - const max = 2 * min; - this._actual = new Buffer(pieces, min, max, eol); - this._mightContainRTL = containsRTL; - this._mightContainNonBasicASCII = !isBasicASCII; - } - - equals(other: ITextBuffer): boolean { - if (!(other instanceof ChunksTextBuffer)) { - return false; - } - return this._actual.equals(other._actual); - } - mightContainRTL(): boolean { - return this._mightContainRTL; - } - mightContainNonBasicASCII(): boolean { - return this._mightContainNonBasicASCII; - } - getBOM(): string { - return this._BOM; - } - getEOL(): string { - return this._actual.getEOL(); - } - getOffsetAt(lineNumber: number, column: number): number { - return this._actual.convertPositionToOffset(lineNumber, column); - } - getPositionAt(offset: number): Position { - return this._actual.convertOffsetToPosition(offset); - } - getRangeAt(offset: number, length: number): Range { - return this._actual.convertOffsetLenToRange(offset, length); - } - getValueInRange(range: Range, eol: EndOfLinePreference): string { - if (range.isEmpty()) { - return ''; - } - - const text = this._actual.getValueInRange(range); - switch (eol) { - case EndOfLinePreference.TextDefined: - return text; - case EndOfLinePreference.LF: - if (this.getEOL() === '\n') { - return text; - } else { - return text.replace(/\r\n/g, '\n'); - } - case EndOfLinePreference.CRLF: - if (this.getEOL() === '\r\n') { - return text; - } else { - return text.replace(/\n/g, '\r\n'); - } - } - return null; - } - - public createSnapshot(preserveBOM: boolean): ITextSnapshot { - return this._actual.createSnapshot(preserveBOM ? this._BOM : ''); - } - - getValueLengthInRange(range: Range, eol: EndOfLinePreference): number { - if (range.isEmpty()) { - return 0; - } - const eolCount = range.endLineNumber - range.startLineNumber; - const result = this._actual.getValueLengthInRange(range); - switch (eol) { - case EndOfLinePreference.TextDefined: - return result; - case EndOfLinePreference.LF: - if (this.getEOL() === '\n') { - return result; - } else { - return result - eolCount; // \r\n => \n - } - case EndOfLinePreference.CRLF: - if (this.getEOL() === '\r\n') { - return result; - } else { - return result + eolCount; // \n => \r\n - } - } - return 0; - } - - public getLength(): number { - return this._actual.getLength(); - } - - getLineCount(): number { - return this._actual.getLineCount(); - } - - getLinesContent(): string[] { - return this._actual.getLinesContent(); - } - - getLineContent(lineNumber: number): string { - return this._actual.getLineContent(lineNumber); - } - - getLineCharCode(lineNumber: number, index: number): number { - return this._actual.getLineCharCode(lineNumber, index); - } - - getLineLength(lineNumber: number): number { - return this._actual.getLineLength(lineNumber); - } - - getLineFirstNonWhitespaceColumn(lineNumber: number): number { - const result = this._actual.getLineFirstNonWhitespaceIndex(lineNumber); - if (result === -1) { - return 0; - } - return result + 1; - } - getLineLastNonWhitespaceColumn(lineNumber: number): number { - const result = this._actual.getLineLastNonWhitespaceIndex(lineNumber); - if (result === -1) { - return 0; - } - return result + 1; - } - setEOL(newEOL: '\r\n' | '\n'): void { - if (this.getEOL() === newEOL) { - // nothing to do... - return; - } - this._actual.setEOL(newEOL); - } - - private static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { - let r = Range.compareRangesUsingEnds(a.range, b.range); - if (r === 0) { - return a.sortIndex - b.sortIndex; - } - return r; - } - - private static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { - let r = Range.compareRangesUsingEnds(a.range, b.range); - if (r === 0) { - return b.sortIndex - a.sortIndex; - } - return -r; - } - - applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { - if (rawOperations.length === 0) { - return new ApplyEditsResult([], [], []); - } - - let mightContainRTL = this._mightContainRTL; - let mightContainNonBasicASCII = this._mightContainNonBasicASCII; - let canReduceOperations = true; - - let operations: IValidatedEditOperation[] = []; - for (let i = 0; i < rawOperations.length; i++) { - let op = rawOperations[i]; - if (canReduceOperations && op._isTracked) { - canReduceOperations = false; - } - let validatedRange = op.range; - if (!mightContainRTL && op.text) { - // check if the new inserted text contains RTL - mightContainRTL = strings.containsRTL(op.text); - } - if (!mightContainNonBasicASCII && op.text) { - mightContainNonBasicASCII = !strings.isBasicASCII(op.text); - } - operations[i] = { - sortIndex: i, - identifier: op.identifier || null, - range: validatedRange, - rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), - rangeLength: this.getValueLengthInRange(validatedRange, EndOfLinePreference.TextDefined), - lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, - forceMoveMarkers: op.forceMoveMarkers || false, - isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false - }; - } - - // Sort operations ascending - operations.sort(ChunksTextBuffer._sortOpsAscending); - - for (let i = 0, count = operations.length - 1; i < count; i++) { - let rangeEnd = operations[i].range.getEndPosition(); - let nextRangeStart = operations[i + 1].range.getStartPosition(); - - if (nextRangeStart.isBefore(rangeEnd)) { - // overlapping ranges - throw new Error('Overlapping ranges are not allowed!'); - } - } - - if (canReduceOperations) { - operations = this._reduceOperations(operations); - } - - // Delta encode operations - let reverseRanges = ChunksTextBuffer._getInverseEditRanges(operations); - let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = []; - - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; - - if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) { - // Record already the future line numbers that might be auto whitespace removal candidates on next edit - for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { - let currentLineContent = ''; - if (lineNumber === reverseRange.startLineNumber) { - currentLineContent = this.getLineContent(op.range.startLineNumber); - if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { - continue; - } - } - newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); - } - } - } - - let reverseOperations: IIdentifiedSingleEditOperation[] = []; - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; - - reverseOperations[i] = { - identifier: op.identifier, - range: reverseRange, - text: this.getValueInRange(op.range, EndOfLinePreference.TextDefined), - forceMoveMarkers: op.forceMoveMarkers - }; - } - - this._mightContainRTL = mightContainRTL; - this._mightContainNonBasicASCII = mightContainNonBasicASCII; - - const contentChanges = this._doApplyEdits(operations); - - let trimAutoWhitespaceLineNumbers: number[] = null; - if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { - // sort line numbers auto whitespace removal candidates for next edit descending - newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber); - - trimAutoWhitespaceLineNumbers = []; - for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) { - let lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber; - if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) { - // Do not have the same line number twice - continue; - } - - let prevContent = newTrimAutoWhitespaceCandidates[i].oldContent; - let lineContent = this.getLineContent(lineNumber); - - if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) { - continue; - } - - trimAutoWhitespaceLineNumbers.push(lineNumber); - } - } - - return new ApplyEditsResult( - reverseOperations, - contentChanges, - trimAutoWhitespaceLineNumbers - ); - } - - /** - * Transform operations such that they represent the same logic edit, - * but that they also do not cause OOM crashes. - */ - private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] { - if (operations.length < 1000) { - // We know from empirical testing that a thousand edits work fine regardless of their shape. - return operations; - } - - // At one point, due to how events are emitted and how each operation is handled, - // some operations can trigger a high ammount of temporary string allocations, - // that will immediately get edited again. - // e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line - // Therefore, the strategy is to collapse all the operations into a huge single edit operation - return [this._toSingleEditOperation(operations)]; - } - - _toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation { - let forceMoveMarkers = false, - firstEditRange = operations[0].range, - lastEditRange = operations[operations.length - 1].range, - entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn), - lastEndLineNumber = firstEditRange.startLineNumber, - lastEndColumn = firstEditRange.startColumn, - result: string[] = []; - - for (let i = 0, len = operations.length; i < len; i++) { - let operation = operations[i], - range = operation.range; - - forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers; - - // (1) -- Push old text - for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) { - if (lineNumber === lastEndLineNumber) { - result.push(this.getLineContent(lineNumber).substring(lastEndColumn - 1)); - } else { - result.push('\n'); - result.push(this.getLineContent(lineNumber)); - } - } - - if (range.startLineNumber === lastEndLineNumber) { - result.push(this.getLineContent(range.startLineNumber).substring(lastEndColumn - 1, range.startColumn - 1)); - } else { - result.push('\n'); - result.push(this.getLineContent(range.startLineNumber).substring(0, range.startColumn - 1)); - } - - // (2) -- Push new text - if (operation.lines) { - for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) { - if (j !== 0) { - result.push('\n'); - } - result.push(operation.lines[j]); - } - } - - lastEndLineNumber = operation.range.endLineNumber; - lastEndColumn = operation.range.endColumn; - } - - return { - sortIndex: 0, - identifier: operations[0].identifier, - range: entireEditRange, - rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), - rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined), - lines: result.join('').split('\n'), - forceMoveMarkers: forceMoveMarkers, - isAutoWhitespaceEdit: false - }; - } - - private _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] { - - // Sort operations descending - operations.sort(ChunksTextBuffer._sortOpsDescending); - - let contentChanges: IInternalModelContentChange[] = []; - let edits: OffsetLenEdit[] = []; - - for (let i = 0, len = operations.length; i < len; i++) { - const op = operations[i]; - - const text = (op.lines ? op.lines.join(this.getEOL()) : ''); - edits[i] = new OffsetLenEdit(op.sortIndex, op.rangeOffset, op.rangeLength, text); - - const startLineNumber = op.range.startLineNumber; - const startColumn = op.range.startColumn; - const endLineNumber = op.range.endLineNumber; - const endColumn = op.range.endColumn; - - if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) { - // no-op - continue; - } - - contentChanges.push({ - range: op.range, - rangeLength: op.rangeLength, - text: text, - rangeOffset: op.rangeOffset, - forceMoveMarkers: op.forceMoveMarkers - }); - } - - this._actual.replaceOffsetLen(edits); - - return contentChanges; - } - - /** - * Assumes `operations` are validated and sorted ascending - */ - public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] { - let result: Range[] = []; - - let prevOpEndLineNumber: number; - let prevOpEndColumn: number; - let prevOp: IValidatedEditOperation = null; - for (let i = 0, len = operations.length; i < len; i++) { - let op = operations[i]; - - let startLineNumber: number; - let startColumn: number; - - if (prevOp) { - if (prevOp.range.endLineNumber === op.range.startLineNumber) { - startLineNumber = prevOpEndLineNumber; - startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn); - } else { - startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber); - startColumn = op.range.startColumn; - } - } else { - startLineNumber = op.range.startLineNumber; - startColumn = op.range.startColumn; - } - - let resultRange: Range; - - if (op.lines && op.lines.length > 0) { - // the operation inserts something - let lineCount = op.lines.length; - let firstLine = op.lines[0]; - let lastLine = op.lines[lineCount - 1]; - - if (lineCount === 1) { - // single line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length); - } else { - // multi line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1); - } - } else { - // There is nothing to insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn); - } - - prevOpEndLineNumber = resultRange.endLineNumber; - prevOpEndColumn = resultRange.endColumn; - - result.push(resultRange); - prevOp = op; - } - - return result; - } -} - - -class BufferNodes { - - public length: Uint32Array; - public newLineCount: Uint32Array; - - constructor(count: number) { - this.length = new Uint32Array(count); - this.newLineCount = new Uint32Array(count); - } - -} - -class BufferCursor { - constructor( - public offset: number, - public leafIndex: number, - public leafStartOffset: number, - public leafStartNewLineCount: number - ) { } - - public set(offset: number, leafIndex: number, leafStartOffset: number, leafStartNewLineCount: number) { - this.offset = offset; - this.leafIndex = leafIndex; - this.leafStartOffset = leafStartOffset; - this.leafStartNewLineCount = leafStartNewLineCount; - } -} - -class OffsetLenEdit { - constructor( - public readonly initialIndex: number, - public readonly offset: number, - public length: number, - public text: string - ) { } -} - -class InternalOffsetLenEdit { - constructor( - public readonly startLeafIndex: number, - public readonly startInnerOffset: number, - public readonly endLeafIndex: number, - public readonly endInnerOffset: number, - public text: string - ) { } -} - -class LeafReplacement { - constructor( - public readonly startLeafIndex: number, - public readonly endLeafIndex: number, - public readonly replacements: BufferPiece[] - ) { } -} - -const BUFFER_CURSOR_POOL_SIZE = 10; -const BufferCursorPool = new class { - private _pool: BufferCursor[]; - private _len: number; - - constructor() { - this._pool = []; - for (let i = 0; i < BUFFER_CURSOR_POOL_SIZE; i++) { - this._pool[i] = new BufferCursor(0, 0, 0, 0); - } - this._len = this._pool.length; - } - - public put(cursor: BufferCursor): void { - if (this._len > this._pool.length) { - // oh, well - return; - } - this._pool[this._len++] = cursor; - } - - public take(): BufferCursor { - if (this._len === 0) { - // oh, well - console.log(`insufficient BufferCursor pool`); - return new BufferCursor(0, 0, 0, 0); - } - const result = this._pool[this._len - 1]; - this._pool[this._len--] = null; - return result; - } -}; - -class BufferSnapshot implements ITextSnapshot { - - private readonly _pieces: BufferPiece[]; - private readonly _piecesLength: number; - private readonly _BOM: string; - private _piecesIndex: number; - - constructor(pieces: BufferPiece[], BOM: string) { - this._pieces = pieces; - this._piecesLength = this._pieces.length; - this._BOM = BOM; - this._piecesIndex = 0; - } - - public read(): string { - if (this._piecesIndex >= this._piecesLength) { - return null; - } - - let result: string = null; - if (this._piecesIndex === 0) { - result = this._BOM + this._pieces[this._piecesIndex].text; - } else { - result = this._pieces[this._piecesIndex].text; - } - - this._piecesIndex++; - return result; - } -} - -class Buffer { - - private _minLeafLength: number; - private _maxLeafLength: number; - private _idealLeafLength: number; - - private _eol: '\r\n' | '\n'; - private _eolLength: number; - - private _leafs: BufferPiece[]; - private _nodes: BufferNodes; - private _nodesCount: number; - private _leafsStart: number; - private _leafsEnd: number; - - constructor(pieces: BufferPiece[], minLeafLength: number, maxLeafLength: number, eol: '\r\n' | '\n') { - if (!(2 * minLeafLength >= maxLeafLength)) { - throw new Error(`assertion violation`); - } - - this._minLeafLength = minLeafLength; - this._maxLeafLength = maxLeafLength; - this._idealLeafLength = (minLeafLength + maxLeafLength) >>> 1; - - this._eol = eol; - this._eolLength = this._eol.length; - - this._leafs = pieces; - this._nodes = null; - this._nodesCount = 0; - this._leafsStart = 0; - this._leafsEnd = 0; - - this._rebuildNodes(); - } - - equals(other: Buffer): boolean { - return Buffer.equals(this, other); - } - - private static equals(a: Buffer, b: Buffer): boolean { - const aLength = a.getLength(); - const bLength = b.getLength(); - if (aLength !== bLength) { - return false; - } - if (a.getLineCount() !== b.getLineCount()) { - return false; - } - - let remaining = aLength; - let aLeafIndex = -1, aLeaf = null, aLeafLength = 0, aLeafRemaining = 0; - let bLeafIndex = -1, bLeaf = null, bLeafLength = 0, bLeafRemaining = 0; - - while (remaining > 0) { - if (aLeafRemaining === 0) { - aLeafIndex++; - aLeaf = a._leafs[aLeafIndex]; - aLeafLength = aLeaf.length(); - aLeafRemaining = aLeafLength; - } - - if (bLeafRemaining === 0) { - bLeafIndex++; - bLeaf = b._leafs[bLeafIndex]; - bLeafLength = bLeaf.length(); - bLeafRemaining = bLeafLength; - } - - let consuming = Math.min(aLeafRemaining, bLeafRemaining); - - let aStr = aLeaf.substr(aLeafLength - aLeafRemaining, consuming); - let bStr = bLeaf.substr(bLeafLength - bLeafRemaining, consuming); - - if (aStr !== bStr) { - return false; - } - - remaining -= consuming; - aLeafRemaining -= consuming; - bLeafRemaining -= consuming; - } - - return true; - } - - public getEOL(): string { - return this._eol; - } - - private _rebuildNodes() { - const leafsCount = this._leafs.length; - - this._nodesCount = (1 << log2(leafsCount)); - this._leafsStart = this._nodesCount; - this._leafsEnd = this._leafsStart + leafsCount; - - this._nodes = new BufferNodes(this._nodesCount); - for (let i = this._nodesCount - 1; i >= 1; i--) { - this._updateSingleNode(i); - } - } - - private _updateSingleNode(nodeIndex: number): void { - const left = LEFT_CHILD(nodeIndex); - const right = RIGHT_CHILD(nodeIndex); - - let length = 0; - let newLineCount = 0; - - if (this.IS_NODE(left)) { - length += this._nodes.length[left]; - newLineCount += this._nodes.newLineCount[left]; - } else if (this.IS_LEAF(left)) { - const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; - length += leaf.length(); - newLineCount += leaf.newLineCount(); - } - - if (this.IS_NODE(right)) { - length += this._nodes.length[right]; - newLineCount += this._nodes.newLineCount[right]; - } else if (this.IS_LEAF(right)) { - const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(right)]; - length += leaf.length(); - newLineCount += leaf.newLineCount(); - } - - this._nodes.length[nodeIndex] = length; - this._nodes.newLineCount[nodeIndex] = newLineCount; - } - - private _findOffset(offset: number, result: BufferCursor): boolean { - if (offset > this._nodes.length[1]) { - return false; - } - - let it = 1; - let searchOffset = offset; - let leafStartOffset = 0; - let leafStartNewLineCount = 0; - while (!this.IS_LEAF(it)) { - const left = LEFT_CHILD(it); - const right = RIGHT_CHILD(it); - - let leftNewLineCount = 0; - let leftLength = 0; - if (this.IS_NODE(left)) { - leftNewLineCount = this._nodes.newLineCount[left]; - leftLength = this._nodes.length[left]; - } else if (this.IS_LEAF(left)) { - const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; - leftNewLineCount = leaf.newLineCount(); - leftLength = leaf.length(); - } - - let rightLength = 0; - if (this.IS_NODE(right)) { - rightLength += this._nodes.length[right]; - } else if (this.IS_LEAF(right)) { - rightLength += this._leafs[this.NODE_TO_LEAF_INDEX(right)].length(); - } - - if (searchOffset < leftLength || rightLength === 0) { - // go left - it = left; - } else { - // go right - searchOffset -= leftLength; - leafStartOffset += leftLength; - leafStartNewLineCount += leftNewLineCount; - it = right; - } - } - it = this.NODE_TO_LEAF_INDEX(it); - - result.set(offset, it, leafStartOffset, leafStartNewLineCount); - return true; - } - - private _findOffsetCloseAfter(offset: number, start: BufferCursor, result: BufferCursor): boolean { - if (offset > this._nodes.length[1]) { - return false; - } - - let innerOffset = offset - start.leafStartOffset; - const leafsCount = this._leafs.length; - - let leafIndex = start.leafIndex; - let leafStartOffset = start.leafStartOffset; - let leafStartNewLineCount = start.leafStartNewLineCount; - - while (true) { - const leaf = this._leafs[leafIndex]; - - if (innerOffset < leaf.length() || (innerOffset === leaf.length() && leafIndex + 1 === leafsCount)) { - result.set(offset, leafIndex, leafStartOffset, leafStartNewLineCount); - return true; - } - - leafIndex++; - - if (leafIndex >= leafsCount) { - result.set(offset, leafIndex, leafStartOffset, leafStartNewLineCount); - return true; - } - - leafStartOffset += leaf.length(); - leafStartNewLineCount += leaf.newLineCount(); - innerOffset -= leaf.length(); - } - } - - private _findLineStart(lineNumber: number, result: BufferCursor): boolean { - let lineIndex = lineNumber - 1; - if (lineIndex < 0 || lineIndex > this._nodes.newLineCount[1]) { - result.set(0, 0, 0, 0); - return false; - } - - let it = 1; - let leafStartOffset = 0; - let leafStartNewLineCount = 0; - while (!this.IS_LEAF(it)) { - const left = LEFT_CHILD(it); - const right = RIGHT_CHILD(it); - - let leftNewLineCount = 0; - let leftLength = 0; - if (this.IS_NODE(left)) { - leftNewLineCount = this._nodes.newLineCount[left]; - leftLength = this._nodes.length[left]; - } else if (this.IS_LEAF(left)) { - const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; - leftNewLineCount = leaf.newLineCount(); - leftLength = leaf.length(); - } - - if (lineIndex <= leftNewLineCount) { - // go left - it = left; - continue; - } - - // go right - lineIndex -= leftNewLineCount; - leafStartOffset += leftLength; - leafStartNewLineCount += leftNewLineCount; - it = right; - } - it = this.NODE_TO_LEAF_INDEX(it); - - const innerLineStartOffset = (lineIndex === 0 ? 0 : this._leafs[it].lineStartFor(lineIndex - 1)); - - result.set(leafStartOffset + innerLineStartOffset, it, leafStartOffset, leafStartNewLineCount); - return true; - } - - private _findLineEnd(start: BufferCursor, lineNumber: number, result: BufferCursor): void { - let innerLineIndex = lineNumber - 1 - start.leafStartNewLineCount; - const leafsCount = this._leafs.length; - - let leafIndex = start.leafIndex; - let leafStartOffset = start.leafStartOffset; - let leafStartNewLineCount = start.leafStartNewLineCount; - while (true) { - const leaf = this._leafs[leafIndex]; - - if (innerLineIndex < leaf.newLineCount()) { - const lineEndOffset = this._leafs[leafIndex].lineStartFor(innerLineIndex); - result.set(leafStartOffset + lineEndOffset, leafIndex, leafStartOffset, leafStartNewLineCount); - return; - } - - leafIndex++; - - if (leafIndex >= leafsCount) { - result.set(leafStartOffset + leaf.length(), leafIndex - 1, leafStartOffset, leafStartNewLineCount); - return; - } - - leafStartOffset += leaf.length(); - leafStartNewLineCount += leaf.newLineCount(); - innerLineIndex = 0; - } - } - - private _findLine(lineNumber: number, start: BufferCursor, end: BufferCursor): boolean { - if (!this._findLineStart(lineNumber, start)) { - return false; - } - - this._findLineEnd(start, lineNumber, end); - return true; - } - - public getLength(): number { - return this._nodes.length[1]; - } - - public getLineCount(): number { - return this._nodes.newLineCount[1] + 1; - } - - public getLineContent(lineNumber: number): string { - const start = BufferCursorPool.take(); - const end = BufferCursorPool.take(); - - if (!this._findLine(lineNumber, start, end)) { - BufferCursorPool.put(start); - BufferCursorPool.put(end); - throw new Error(`Line not found`); - } - - let result: string; - if (lineNumber === this.getLineCount()) { - // last line is not trailed by an eol - result = this.extractString(start, end.offset - start.offset); - } else { - result = this.extractString(start, end.offset - start.offset - this._eolLength); - } - - BufferCursorPool.put(start); - BufferCursorPool.put(end); - return result; - } - - public getLineCharCode(lineNumber: number, index: number): number { - const start = BufferCursorPool.take(); - - if (!this._findLineStart(lineNumber, start)) { - BufferCursorPool.put(start); - throw new Error(`Line not found`); - } - - const tmp = BufferCursorPool.take(); - this._findOffsetCloseAfter(start.offset + index, start, tmp); - const result = this._leafs[tmp.leafIndex].charCodeAt(tmp.offset - tmp.leafStartNewLineCount); - BufferCursorPool.put(tmp); - - BufferCursorPool.put(start); - return result; - } - - public getLineLength(lineNumber: number): number { - const start = BufferCursorPool.take(); - const end = BufferCursorPool.take(); - - if (!this._findLine(lineNumber, start, end)) { - BufferCursorPool.put(start); - BufferCursorPool.put(end); - throw new Error(`Line not found`); - } - - let result: number; - if (lineNumber === this.getLineCount()) { - // last line is not trailed by an eol - result = end.offset - start.offset; - } else { - result = end.offset - start.offset - this._eolLength; - } - - BufferCursorPool.put(start); - BufferCursorPool.put(end); - return result; - } - - public getLineFirstNonWhitespaceIndex(lineNumber: number): number { - const start = BufferCursorPool.take(); - - if (!this._findLineStart(lineNumber, start)) { - BufferCursorPool.put(start); - throw new Error(`Line not found`); - } - - let leafIndex = start.leafIndex; - let searchStartOffset = start.offset - start.leafStartOffset; - BufferCursorPool.put(start); - - const leafsCount = this._leafs.length; - let totalDelta = 0; - while (true) { - const leaf = this._leafs[leafIndex]; - - const leafResult = leaf.findLineFirstNonWhitespaceIndex(searchStartOffset); - if (leafResult === -2) { - // reached EOL - return -1; - } - if (leafResult !== -1) { - return (leafResult - searchStartOffset) + totalDelta; - } - - leafIndex++; - - if (leafIndex >= leafsCount) { - return -1; - } - - totalDelta += (leaf.length() - searchStartOffset); - searchStartOffset = 0; - } - } - - public getLineLastNonWhitespaceIndex(lineNumber: number): number { - const start = BufferCursorPool.take(); - const end = BufferCursorPool.take(); - - if (!this._findLineStart(lineNumber, start)) { - BufferCursorPool.put(start); - BufferCursorPool.put(end); - throw new Error(`Line not found`); - } - - this._findLineEnd(start, lineNumber, end); - - const startOffset = start.offset; - const endOffset = end.offset; - let leafIndex = end.leafIndex; - let searchStartOffset = end.offset - end.leafStartOffset - this._eolLength; - - BufferCursorPool.put(start); - BufferCursorPool.put(end); - - let totalDelta = 0; - while (true) { - const leaf = this._leafs[leafIndex]; - - const leafResult = leaf.findLineLastNonWhitespaceIndex(searchStartOffset); - if (leafResult === -2) { - // reached EOL - return -1; - } - if (leafResult !== -1) { - const delta = (searchStartOffset - 1 - leafResult); - const absoluteOffset = (endOffset - this._eolLength) - delta - totalDelta; - return absoluteOffset - startOffset; - } - - leafIndex--; - - if (leafIndex < 0) { - return -1; - } - - totalDelta += searchStartOffset; - searchStartOffset = leaf.length(); - } - } - - public getLinesContent(): string[] { - let result: string[] = new Array<string>(this.getLineCount()); - let resultIndex = 0; - - let currentLine = ''; - for (let leafIndex = 0, leafsCount = this._leafs.length; leafIndex < leafsCount; leafIndex++) { - const leaf = this._leafs[leafIndex]; - const leafNewLineCount = leaf.newLineCount(); - - if (leafNewLineCount === 0) { - // special case => push entire leaf text - currentLine += leaf.text; - continue; - } - - let leafSubstrOffset = 0; - for (let newLineIndex = 0; newLineIndex < leafNewLineCount; newLineIndex++) { - const newLineStart = leaf.lineStartFor(newLineIndex); - currentLine += leaf.substr(leafSubstrOffset, newLineStart - leafSubstrOffset - this._eolLength); - result[resultIndex++] = currentLine; - - currentLine = ''; - leafSubstrOffset = newLineStart; - } - currentLine += leaf.substr(leafSubstrOffset, leaf.length()); - } - result[resultIndex++] = currentLine; - - return result; - } - - public extractString(start: BufferCursor, len: number): string { - if (!(start.offset + len <= this._nodes.length[1])) { - throw new Error(`assertion violation`); - } - - let innerLeafOffset = start.offset - start.leafStartOffset; - let leafIndex = start.leafIndex; - let res = ''; - while (len > 0) { - const leaf = this._leafs[leafIndex]; - const cnt = Math.min(len, leaf.length() - innerLeafOffset); - res += leaf.substr(innerLeafOffset, cnt); - - len -= cnt; - innerLeafOffset = 0; - - if (len === 0) { - break; - } - - leafIndex++; - } - return res; - } - - private _getOffsetAt(lineNumber: number, column: number, result: BufferCursor): boolean { - const lineStart = BufferCursorPool.take(); - - if (!this._findLineStart(lineNumber, lineStart)) { - BufferCursorPool.put(lineStart); - return false; - } - - const startOffset = lineStart.offset + column - 1; - if (!this._findOffsetCloseAfter(startOffset, lineStart, result)) { - BufferCursorPool.put(lineStart); - return false; - } - - BufferCursorPool.put(lineStart); - return true; - } - - public convertPositionToOffset(lineNumber: number, column: number): number { - const r = BufferCursorPool.take(); - - if (!this._findLineStart(lineNumber, r)) { - BufferCursorPool.put(r); - throw new Error(`Position not found`); - } - - const result = r.offset + column - 1; - - BufferCursorPool.put(r); - return result; - } - - /** - * returns `lineNumber` - */ - private _findLineStartBeforeOffsetInLeaf(offset: number, leafIndex: number, leafStartOffset: number, leafStartNewLineCount: number, result: BufferCursor): number { - const leaf = this._leafs[leafIndex]; - const lineStartIndex = leaf.findLineStartBeforeOffset(offset - leafStartOffset); - const lineStartOffset = leafStartOffset + leaf.lineStartFor(lineStartIndex); - - result.set(lineStartOffset, leafIndex, leafStartOffset, leafStartNewLineCount); - return leafStartNewLineCount + lineStartIndex + 2; - } - - /** - * returns `lineNumber`. - */ - private _findLineStartBeforeOffset(offset: number, location: BufferCursor, result: BufferCursor): number { - - let leafIndex = location.leafIndex; - let leafStartOffset = location.leafStartOffset; - let leafStartNewLineCount = location.leafStartNewLineCount; - while (true) { - const leaf = this._leafs[leafIndex]; - - if (leaf.newLineCount() >= 1 && leaf.lineStartFor(0) + leafStartOffset <= offset) { - // must be in this leaf - return this._findLineStartBeforeOffsetInLeaf(offset, leafIndex, leafStartOffset, leafStartNewLineCount, result); - } - - // continue looking in previous leaf - leafIndex--; - - if (leafIndex < 0) { - result.set(0, 0, 0, 0); - return 1; - } - - leafStartOffset -= this._leafs[leafIndex].length(); - leafStartNewLineCount -= this._leafs[leafIndex].newLineCount(); - } - } - - public convertOffsetToPosition(offset: number): Position { - const r = BufferCursorPool.take(); - const lineStart = BufferCursorPool.take(); - - if (!this._findOffset(offset, r)) { - BufferCursorPool.put(r); - BufferCursorPool.put(lineStart); - throw new Error(`Offset not found`); - } - - const lineNumber = this._findLineStartBeforeOffset(offset, r, lineStart); - const column = offset - lineStart.offset + 1; - - BufferCursorPool.put(r); - BufferCursorPool.put(lineStart); - - return new Position(lineNumber, column); - } - - public convertOffsetLenToRange(offset: number, len: number): Range { - const r = BufferCursorPool.take(); - const lineStart = BufferCursorPool.take(); - - if (!this._findOffset(offset, r)) { - BufferCursorPool.put(r); - BufferCursorPool.put(lineStart); - throw new Error(`Offset not found`); - } - const startLineNumber = this._findLineStartBeforeOffset(offset, r, lineStart); - const startColumn = offset - lineStart.offset + 1; - - if (!this._findOffset(offset + len, r)) { - BufferCursorPool.put(r); - BufferCursorPool.put(lineStart); - throw new Error(`Offset not found`); - } - const endLineNumber = this._findLineStartBeforeOffset(offset + len, r, lineStart); - const endColumn = offset + len - lineStart.offset + 1; - - BufferCursorPool.put(r); - BufferCursorPool.put(lineStart); - - return new Range(startLineNumber, startColumn, endLineNumber, endColumn); - } - - public getValueInRange(range: Range): string { - const start = BufferCursorPool.take(); - - if (!this._getOffsetAt(range.startLineNumber, range.startColumn, start)) { - BufferCursorPool.put(start); - throw new Error(`Line not found`); - } - - const endOffset = this.convertPositionToOffset(range.endLineNumber, range.endColumn); - const result = this.extractString(start, endOffset - start.offset); - - BufferCursorPool.put(start); - return result; - } - - public createSnapshot(BOM: string): ITextSnapshot { - return new BufferSnapshot(this._leafs, BOM); - } - - public getValueLengthInRange(range: Range): number { - const startOffset = this.convertPositionToOffset(range.startLineNumber, range.startColumn); - const endOffset = this.convertPositionToOffset(range.endLineNumber, range.endColumn); - return endOffset - startOffset; - } - - //#region Editing - - private _mergeAdjacentEdits(edits: OffsetLenEdit[]): OffsetLenEdit[] { - // Check if we must merge adjacent edits - let merged: OffsetLenEdit[] = [], mergedLength = 0; - let prev = edits[0]; - for (let i = 1, len = edits.length; i < len; i++) { - const curr = edits[i]; - if (prev.offset + prev.length === curr.offset) { - // merge into `prev` - prev.length = prev.length + curr.length; - prev.text = prev.text + curr.text; - } else { - merged[mergedLength++] = prev; - prev = curr; - } - } - merged[mergedLength++] = prev; - - return merged; - } - - private _resolveEdits(edits: OffsetLenEdit[]): InternalOffsetLenEdit[] { - edits = this._mergeAdjacentEdits(edits); - - let result: InternalOffsetLenEdit[] = []; - let tmp = new BufferCursor(0, 0, 0, 0); - let tmp2 = new BufferCursor(0, 0, 0, 0); - for (let i = 0, len = edits.length; i < len; i++) { - const edit = edits[i]; - - let text = edit.text; - - this._findOffset(edit.offset, tmp); - let startLeafIndex = tmp.leafIndex; - let startInnerOffset = tmp.offset - tmp.leafStartOffset; - if (startInnerOffset > 0) { - const startLeaf = this._leafs[startLeafIndex]; - const charBefore = startLeaf.charCodeAt(startInnerOffset - 1); - if (charBefore === CharCode.CarriageReturn) { - // include the replacement of \r in the edit - text = '\r' + text; - - this._findOffsetCloseAfter(edit.offset - 1, tmp, tmp2); - startLeafIndex = tmp2.leafIndex; - startInnerOffset = tmp2.offset - tmp2.leafStartOffset; - // this._findOffset(edit.offset - 1, tmp); - // startLeafIndex = tmp.leafIndex; - // startInnerOffset = tmp.offset - tmp.leafStartOffset; - } - } - - this._findOffset(edit.offset + edit.length, tmp); - let endLeafIndex = tmp.leafIndex; - let endInnerOffset = tmp.offset - tmp.leafStartOffset; - const endLeaf = this._leafs[endLeafIndex]; - if (endInnerOffset < endLeaf.length()) { - const charAfter = endLeaf.charCodeAt(endInnerOffset); - if (charAfter === CharCode.LineFeed) { - // include the replacement of \n in the edit - text = text + '\n'; - - this._findOffsetCloseAfter(edit.offset + edit.length + 1, tmp, tmp2); - endLeafIndex = tmp2.leafIndex; - endInnerOffset = tmp2.offset - tmp2.leafStartOffset; - // this._findOffset(edit.offset + edit.length + 1, tmp); - // endLeafIndex = tmp.leafIndex; - // endInnerOffset = tmp.offset - tmp.leafStartOffset; - } - } - - result[i] = new InternalOffsetLenEdit( - startLeafIndex, startInnerOffset, - endLeafIndex, endInnerOffset, - text - ); - } - - return result; - } - - private _pushLeafReplacement(startLeafIndex: number, endLeafIndex: number, replacements: LeafReplacement[]): LeafReplacement { - const res = new LeafReplacement(startLeafIndex, endLeafIndex, []); - replacements.push(res); - return res; - } - - private _flushLeafEdits(accumulatedLeafIndex: number, accumulatedLeafEdits: LeafOffsetLenEdit[], replacements: LeafReplacement[]): void { - if (accumulatedLeafEdits.length > 0) { - const rep = this._pushLeafReplacement(accumulatedLeafIndex, accumulatedLeafIndex, replacements); - BufferPiece.replaceOffsetLen(this._leafs[accumulatedLeafIndex], accumulatedLeafEdits, this._idealLeafLength, this._maxLeafLength, rep.replacements); - } - accumulatedLeafEdits.length = 0; - } - - private _pushLeafEdits(start: number, length: number, text: string, accumulatedLeafEdits: LeafOffsetLenEdit[]): void { - if (length !== 0 || text.length !== 0) { - accumulatedLeafEdits.push(new LeafOffsetLenEdit(start, length, text)); - } - } - - private _appendLeaf(leaf: BufferPiece, leafs: BufferPiece[], prevLeaf: BufferPiece): BufferPiece { - if (prevLeaf === null) { - leafs.push(leaf); - prevLeaf = leaf; - return prevLeaf; - } - - let prevLeafLength = prevLeaf.length(); - let currLeafLength = leaf.length(); - - if ((prevLeafLength < this._minLeafLength || currLeafLength < this._minLeafLength) && prevLeafLength + currLeafLength <= this._maxLeafLength) { - const joinedLeaf = BufferPiece.join(prevLeaf, leaf); - leafs[leafs.length - 1] = joinedLeaf; - prevLeaf = joinedLeaf; - return prevLeaf; - } - - const lastChar = prevLeaf.charCodeAt(prevLeafLength - 1); - const firstChar = leaf.charCodeAt(0); - - if ( - (lastChar >= 0xd800 && lastChar <= 0xdbff) || (lastChar === CharCode.CarriageReturn && firstChar === CharCode.LineFeed) - ) { - const modifiedPrevLeaf = BufferPiece.deleteLastChar(prevLeaf); - leafs[leafs.length - 1] = modifiedPrevLeaf; - - const modifiedLeaf = BufferPiece.insertFirstChar(leaf, lastChar); - leaf = modifiedLeaf; - } - - leafs.push(leaf); - prevLeaf = leaf; - return prevLeaf; - } - - private static _compareEdits(a: OffsetLenEdit, b: OffsetLenEdit): number { - if (a.offset === b.offset) { - if (a.length === b.length) { - return (a.initialIndex - b.initialIndex); - } - return (a.length - b.length); - } - return a.offset - b.offset; - } - - public replaceOffsetLen(_edits: OffsetLenEdit[]): void { - _edits.sort(Buffer._compareEdits); - - const initialLeafLength = this._leafs.length; - const edits = this._resolveEdits(_edits); - - let accumulatedLeafIndex = 0; - let accumulatedLeafEdits: LeafOffsetLenEdit[] = []; - let replacements: LeafReplacement[] = []; - - for (let i = 0, len = edits.length; i < len; i++) { - const edit = edits[i]; - - const startLeafIndex = edit.startLeafIndex; - const endLeafIndex = edit.endLeafIndex; - - if (startLeafIndex !== accumulatedLeafIndex) { - this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); - accumulatedLeafIndex = startLeafIndex; - } - - const leafEditStart = edit.startInnerOffset; - const leafEditEnd = (startLeafIndex === endLeafIndex ? edit.endInnerOffset : this._leafs[startLeafIndex].length()); - this._pushLeafEdits(leafEditStart, leafEditEnd - leafEditStart, edit.text, accumulatedLeafEdits); - - if (startLeafIndex < endLeafIndex) { - this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); - accumulatedLeafIndex = endLeafIndex; - - // delete leafs in the middle - if (startLeafIndex + 1 < endLeafIndex) { - this._pushLeafReplacement(startLeafIndex + 1, endLeafIndex - 1, replacements); - } - - // delete on last leaf - const leafEditStart = 0; - const leafEditEnd = edit.endInnerOffset; - this._pushLeafEdits(leafEditStart, leafEditEnd - leafEditStart, '', accumulatedLeafEdits); - } - } - this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); - - let leafs: BufferPiece[] = []; - let leafIndex = 0; - let prevLeaf: BufferPiece = null; - - for (let i = 0, len = replacements.length; i < len; i++) { - const replaceStartLeafIndex = replacements[i].startLeafIndex; - const replaceEndLeafIndex = replacements[i].endLeafIndex; - const innerLeafs = replacements[i].replacements; - - // add leafs to the left of this replace op. - while (leafIndex < replaceStartLeafIndex) { - prevLeaf = this._appendLeaf(this._leafs[leafIndex], leafs, prevLeaf); - leafIndex++; - } - - // delete leafs that get replaced. - while (leafIndex <= replaceEndLeafIndex) { - leafIndex++; - } - - // add new leafs. - for (let j = 0, lenJ = innerLeafs.length; j < lenJ; j++) { - prevLeaf = this._appendLeaf(innerLeafs[j], leafs, prevLeaf); - } - } - - // add remaining leafs to the right of the last replacement. - while (leafIndex < initialLeafLength) { - prevLeaf = this._appendLeaf(this._leafs[leafIndex], leafs, prevLeaf); - leafIndex++; - } - - if (leafs.length === 0) { - // don't leave behind an empty leafs array - leafs.push(new BufferPiece('')); - } - - this._leafs = leafs; - this._rebuildNodes(); - } - - public setEOL(newEOL: '\r\n' | '\n'): void { - let leafs: BufferPiece[] = []; - for (let i = 0, len = this._leafs.length; i < len; i++) { - leafs[i] = BufferPiece.normalizeEOL(this._leafs[i], newEOL); - } - this._leafs = leafs; - this._rebuildNodes(); - this._eol = newEOL; - this._eolLength = this._eol.length; - } - - //#endregion - - private IS_NODE(i: number): boolean { - return (i < this._nodesCount); - } - private IS_LEAF(i: number): boolean { - return (i >= this._leafsStart && i < this._leafsEnd); - } - private NODE_TO_LEAF_INDEX(i: number): number { - return (i - this._leafsStart); - } - // private LEAF_TO_NODE_INDEX(i: number): number { - // return (i + this._leafsStart); - // } -} - -function log2(n: number): number { - let v = 1; - for (let pow = 1; ; pow++) { - v = v << 1; - if (v >= n) { - return pow; - } - } - // return -1; -} - -function LEFT_CHILD(i: number): number { - return (i << 1); -} - -function RIGHT_CHILD(i: number): number { - return (i << 1) + 1; -} diff --git a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts deleted file mode 100644 index 3bc15fbb6f..0000000000 --- a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts +++ /dev/null @@ -1,186 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 strings from 'vs/base/common/strings'; -import { ITextBufferBuilder, ITextBufferFactory, ITextBuffer, DefaultEndOfLine } from 'vs/editor/common/model'; -import { BufferPiece, createLineStarts } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; -import { ChunksTextBuffer } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBuffer'; -import { CharCode } from 'vs/base/common/charCode'; - -export class TextBufferFactory implements ITextBufferFactory { - - constructor( - private readonly _pieces: BufferPiece[], - private readonly _averageChunkSize: number, - private readonly _BOM: string, - private readonly _cr: number, - private readonly _lf: number, - private readonly _crlf: number, - private readonly _containsRTL: boolean, - private readonly _isBasicASCII: boolean, - ) { - } - - /** - * if text source is empty or with precisely one line, returns null. No end of line is detected. - * if text source contains more lines ending with '\r\n', returns '\r\n'. - * Otherwise returns '\n'. More lines end with '\n'. - */ - private _getEOL(defaultEOL: DefaultEndOfLine): '\r\n' | '\n' { - const totalEOLCount = this._cr + this._lf + this._crlf; - const totalCRCount = this._cr + this._crlf; - if (totalEOLCount === 0) { - // This is an empty file or a file with precisely one line - return (defaultEOL === DefaultEndOfLine.LF ? '\n' : '\r\n'); - } - if (totalCRCount > totalEOLCount / 2) { - // More than half of the file contains \r\n ending lines - return '\r\n'; - } - // At least one line more ends in \n - return '\n'; - } - - public create(defaultEOL: DefaultEndOfLine): ITextBuffer { - const eol = this._getEOL(defaultEOL); - let pieces = this._pieces; - - if ( - (eol === '\r\n' && (this._cr > 0 || this._lf > 0)) - || (eol === '\n' && (this._cr > 0 || this._crlf > 0)) - ) { - // Normalize pieces - for (let i = 0, len = pieces.length; i < len; i++) { - pieces[i] = BufferPiece.normalizeEOL(pieces[i], eol); - } - } - return new ChunksTextBuffer(pieces, this._averageChunkSize, this._BOM, eol, this._containsRTL, this._isBasicASCII); - } - - public getFirstLineText(lengthLimit: number): string { - const firstPiece = this._pieces[0]; - if (firstPiece.newLineCount() === 0) { - return firstPiece.substr(0, lengthLimit); - } - - const firstEOLOffset = firstPiece.lineStartFor(0); - return firstPiece.substr(0, Math.min(lengthLimit, firstEOLOffset)); - } -} - -export class ChunksTextBufferBuilder implements ITextBufferBuilder { - - private _rawPieces: BufferPiece[]; - private _hasPreviousChar: boolean; - private _previousChar: number; - private _averageChunkSize: number; - private _tmpLineStarts: number[]; - - private BOM: string; - private cr: number; - private lf: number; - private crlf: number; - private containsRTL: boolean; - private isBasicASCII: boolean; - - constructor() { - this._rawPieces = []; - this._hasPreviousChar = false; - this._previousChar = 0; - this._averageChunkSize = 0; - this._tmpLineStarts = []; - - this.BOM = ''; - this.cr = 0; - this.lf = 0; - this.crlf = 0; - this.containsRTL = false; - this.isBasicASCII = true; - } - - public acceptChunk(chunk: string): void { - if (chunk.length === 0) { - return; - } - - if (this._rawPieces.length === 0) { - if (strings.startsWithUTF8BOM(chunk)) { - this.BOM = strings.UTF8_BOM_CHARACTER; - chunk = chunk.substr(1); - } - } - - this._averageChunkSize = (this._averageChunkSize * this._rawPieces.length + chunk.length) / (this._rawPieces.length + 1); - - const lastChar = chunk.charCodeAt(chunk.length - 1); - if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) { - // last character is \r or a high surrogate => keep it back - this._acceptChunk1(chunk.substr(0, chunk.length - 1), false); - this._hasPreviousChar = true; - this._previousChar = lastChar; - } else { - this._acceptChunk1(chunk, false); - this._hasPreviousChar = false; - this._previousChar = lastChar; - } - } - - private _acceptChunk1(chunk: string, allowEmptyStrings: boolean): void { - if (!allowEmptyStrings && chunk.length === 0) { - // Nothing to do - return; - } - - if (this._hasPreviousChar) { - this._acceptChunk2(chunk + String.fromCharCode(this._previousChar)); - } else { - this._acceptChunk2(chunk); - } - } - - private _acceptChunk2(chunk: string): void { - const lineStarts = createLineStarts(this._tmpLineStarts, chunk); - - this._rawPieces.push(new BufferPiece(chunk, lineStarts.lineStarts)); - this.cr += lineStarts.cr; - this.lf += lineStarts.lf; - this.crlf += lineStarts.crlf; - - if (this.isBasicASCII) { - this.isBasicASCII = lineStarts.isBasicASCII; - } - if (!this.isBasicASCII && !this.containsRTL) { - // No need to check if is basic ASCII - this.containsRTL = strings.containsRTL(chunk); - } - } - - public finish(): TextBufferFactory { - this._finish(); - return new TextBufferFactory(this._rawPieces, this._averageChunkSize, this.BOM, this.cr, this.lf, this.crlf, this.containsRTL, this.isBasicASCII); - } - - private _finish(): void { - if (this._rawPieces.length === 0) { - // no chunks => forcefully go through accept chunk - this._acceptChunk1('', true); - return; - } - - if (this._hasPreviousChar) { - this._hasPreviousChar = false; - - // recreate last chunk - const lastPiece = this._rawPieces[this._rawPieces.length - 1]; - const tmp = new BufferPiece(String.fromCharCode(this._previousChar)); - const newLastPiece = BufferPiece.join(lastPiece, tmp); - this._rawPieces[this._rawPieces.length - 1] = newLastPiece; - if (this._previousChar === CharCode.CarriageReturn) { - this.cr++; - } - } - } -} diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index f2b10a970e..2085724b59 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -12,13 +12,11 @@ import { IModelDecoration } from 'vs/editor/common/model'; // The red-black tree is based on the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. // -/** - * The class name sort order must match the severity order. Highest severity last. - */ export const ClassName = { - EditorInfoDecoration: 'squiggly-a-info', - EditorWarningDecoration: 'squiggly-b-warning', - EditorErrorDecoration: 'squiggly-c-error' + EditorHintDecoration: 'squiggly-hint', + EditorInfoDecoration: 'squiggly-info', + EditorWarningDecoration: 'squiggly-warning', + EditorErrorDecoration: 'squiggly-error' }; /** diff --git a/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts b/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts deleted file mode 100644 index 0140732fc1..0000000000 --- a/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts +++ /dev/null @@ -1,660 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { Range } from 'vs/editor/common/core/range'; -import { Position } from 'vs/editor/common/core/position'; -import * as strings from 'vs/base/common/strings'; -import * as arrays from 'vs/base/common/arrays'; -import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { ISingleEditOperationIdentifier, IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange } from 'vs/editor/common/model'; -import { ITextSnapshot } from 'vs/platform/files/common/files'; - -export interface IValidatedEditOperation { - sortIndex: number; - identifier: ISingleEditOperationIdentifier; - range: Range; - rangeOffset: number; - rangeLength: number; - lines: string[]; - forceMoveMarkers: boolean; - isAutoWhitespaceEdit: boolean; -} - -/** - * A processed string with its EOL resolved ready to be turned into an editor model. - */ -export interface ITextSource { - /** - * The text split into lines. - */ - readonly lines: string[]; - /** - * The BOM (leading character sequence of the file). - */ - readonly BOM: string; - /** - * The end of line sequence. - */ - readonly EOL: string; - /** - * The text contains Unicode characters classified as "R" or "AL". - */ - readonly containsRTL: boolean; - /** - * The text contains only characters inside the ASCII range 32-126 or \t \r \n - */ - readonly isBasicASCII: boolean; -} - -class LinesTextBufferSnapshot implements ITextSnapshot { - - private readonly _lines: string[]; - private readonly _linesLength: number; - private readonly _eol: string; - private readonly _bom: string; - private _lineIndex: number; - - constructor(lines: string[], eol: string, bom: string) { - this._lines = lines; - this._linesLength = this._lines.length; - this._eol = eol; - this._bom = bom; - this._lineIndex = 0; - } - - public read(): string { - if (this._lineIndex >= this._linesLength) { - return null; - } - - let result: string = null; - - if (this._lineIndex === 0) { - result = this._bom + this._lines[this._lineIndex]; - } else { - result = this._lines[this._lineIndex]; - } - - this._lineIndex++; - - if (this._lineIndex < this._linesLength) { - result += this._eol; - } - - return result; - } -} - -export class LinesTextBuffer implements ITextBuffer { - - private _lines: string[]; - private _BOM: string; - private _EOL: string; - private _mightContainRTL: boolean; - private _mightContainNonBasicASCII: boolean; - private _lineStarts: PrefixSumComputer; - - constructor(textSource: ITextSource) { - this._lines = textSource.lines.slice(0); - this._BOM = textSource.BOM; - this._EOL = textSource.EOL; - this._mightContainRTL = textSource.containsRTL; - this._mightContainNonBasicASCII = !textSource.isBasicASCII; - this._constructLineStarts(); - } - - private _constructLineStarts(): void { - const eolLength = this._EOL.length; - const linesLength = this._lines.length; - const lineStartValues = new Uint32Array(linesLength); - for (let i = 0; i < linesLength; i++) { - lineStartValues[i] = this._lines[i].length + eolLength; - } - this._lineStarts = new PrefixSumComputer(lineStartValues); - } - - public equals(other: ITextBuffer): boolean { - if (!(other instanceof LinesTextBuffer)) { - return false; - } - if (this._BOM !== other._BOM) { - return false; - } - if (this._EOL !== other._EOL) { - return false; - } - if (this._lines.length !== other._lines.length) { - return false; - } - for (let i = 0, len = this._lines.length; i < len; i++) { - if (this._lines[i] !== other._lines[i]) { - return false; - } - } - return true; - } - - public mightContainRTL(): boolean { - return this._mightContainRTL; - } - - public mightContainNonBasicASCII(): boolean { - return this._mightContainNonBasicASCII; - } - - public getBOM(): string { - return this._BOM; - } - - public getEOL(): string { - return this._EOL; - } - - public getOffsetAt(lineNumber: number, column: number): number { - return this._lineStarts.getAccumulatedValue(lineNumber - 2) + column - 1; - } - - public getPositionAt(offset: number): Position { - offset = Math.floor(offset); - offset = Math.max(0, offset); - - let out = this._lineStarts.getIndexOf(offset); - - let lineLength = this._lines[out.index].length; - - // Ensure we return a valid position - return new Position(out.index + 1, Math.min(out.remainder + 1, lineLength + 1)); - } - - public getRangeAt(offset: number, length: number): Range { - const startResult = this._lineStarts.getIndexOf(offset); - const startLineLength = this._lines[startResult.index].length; - const startColumn = Math.min(startResult.remainder + 1, startLineLength + 1); - - const endResult = this._lineStarts.getIndexOf(offset + length); - const endLineLength = this._lines[endResult.index].length; - const endColumn = Math.min(endResult.remainder + 1, endLineLength + 1); - - return new Range(startResult.index + 1, startColumn, endResult.index + 1, endColumn); - } - - private _getEndOfLine(eol: EndOfLinePreference): string { - switch (eol) { - case EndOfLinePreference.LF: - return '\n'; - case EndOfLinePreference.CRLF: - return '\r\n'; - case EndOfLinePreference.TextDefined: - return this.getEOL(); - } - throw new Error('Unknown EOL preference'); - } - - public getValueInRange(range: Range, eol: EndOfLinePreference): string { - if (range.isEmpty()) { - return ''; - } - - if (range.startLineNumber === range.endLineNumber) { - return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1); - } - - const lineEnding = this._getEndOfLine(eol); - const startLineIndex = range.startLineNumber - 1; - const endLineIndex = range.endLineNumber - 1; - let resultLines: string[] = []; - - resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1)); - for (let i = startLineIndex + 1; i < endLineIndex; i++) { - resultLines.push(this._lines[i]); - } - resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1)); - - return resultLines.join(lineEnding); - } - - public createSnapshot(preserveBOM: boolean): ITextSnapshot { - return new LinesTextBufferSnapshot(this._lines.slice(0), this._EOL, preserveBOM ? this._BOM : ''); - } - - public getValueLengthInRange(range: Range, eol: EndOfLinePreference): number { - if (range.isEmpty()) { - return 0; - } - - if (range.startLineNumber === range.endLineNumber) { - return (range.endColumn - range.startColumn); - } - - let startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn); - let endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn); - return endOffset - startOffset; - } - - public getLineCount(): number { - return this._lines.length; - } - - public getLinesContent(): string[] { - return this._lines.slice(0); - } - - public getLength(): number { - return this._lineStarts.getTotalValue(); - } - - public getLineContent(lineNumber: number): string { - return this._lines[lineNumber - 1]; - } - - public getLineCharCode(lineNumber: number, index: number): number { - return this._lines[lineNumber - 1].charCodeAt(index); - } - - public getLineLength(lineNumber: number): number { - return this._lines[lineNumber - 1].length; - } - - public getLineFirstNonWhitespaceColumn(lineNumber: number): number { - const result = strings.firstNonWhitespaceIndex(this._lines[lineNumber - 1]); - if (result === -1) { - return 0; - } - return result + 1; - } - - public getLineLastNonWhitespaceColumn(lineNumber: number): number { - const result = strings.lastNonWhitespaceIndex(this._lines[lineNumber - 1]); - if (result === -1) { - return 0; - } - return result + 2; - } - - //#region Editing - - public setEOL(newEOL: '\r\n' | '\n'): void { - this._EOL = newEOL; - this._constructLineStarts(); - } - - private static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { - let r = Range.compareRangesUsingEnds(a.range, b.range); - if (r === 0) { - return a.sortIndex - b.sortIndex; - } - return r; - } - - private static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { - let r = Range.compareRangesUsingEnds(a.range, b.range); - if (r === 0) { - return b.sortIndex - a.sortIndex; - } - return -r; - } - - public applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { - if (rawOperations.length === 0) { - return new ApplyEditsResult([], [], []); - } - - let mightContainRTL = this._mightContainRTL; - let mightContainNonBasicASCII = this._mightContainNonBasicASCII; - let canReduceOperations = true; - - let operations: IValidatedEditOperation[] = []; - for (let i = 0; i < rawOperations.length; i++) { - let op = rawOperations[i]; - if (canReduceOperations && op._isTracked) { - canReduceOperations = false; - } - let validatedRange = op.range; - if (!mightContainRTL && op.text) { - // check if the new inserted text contains RTL - mightContainRTL = strings.containsRTL(op.text); - } - if (!mightContainNonBasicASCII && op.text) { - mightContainNonBasicASCII = !strings.isBasicASCII(op.text); - } - operations[i] = { - sortIndex: i, - identifier: op.identifier || null, - range: validatedRange, - rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), - rangeLength: this.getValueLengthInRange(validatedRange, EndOfLinePreference.TextDefined), - lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, - forceMoveMarkers: op.forceMoveMarkers || false, - isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false - }; - } - - // Sort operations ascending - operations.sort(LinesTextBuffer._sortOpsAscending); - - for (let i = 0, count = operations.length - 1; i < count; i++) { - let rangeEnd = operations[i].range.getEndPosition(); - let nextRangeStart = operations[i + 1].range.getStartPosition(); - - if (nextRangeStart.isBefore(rangeEnd)) { - // overlapping ranges - throw new Error('Overlapping ranges are not allowed!'); - } - } - - if (canReduceOperations) { - operations = this._reduceOperations(operations); - } - - // Delta encode operations - let reverseRanges = LinesTextBuffer._getInverseEditRanges(operations); - let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = []; - - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; - - if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) { - // Record already the future line numbers that might be auto whitespace removal candidates on next edit - for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { - let currentLineContent = ''; - if (lineNumber === reverseRange.startLineNumber) { - currentLineContent = this.getLineContent(op.range.startLineNumber); - if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { - continue; - } - } - newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); - } - } - } - - let reverseOperations: IIdentifiedSingleEditOperation[] = []; - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; - - reverseOperations[i] = { - identifier: op.identifier, - range: reverseRange, - text: this.getValueInRange(op.range, EndOfLinePreference.TextDefined), - forceMoveMarkers: op.forceMoveMarkers - }; - } - - this._mightContainRTL = mightContainRTL; - this._mightContainNonBasicASCII = mightContainNonBasicASCII; - - const contentChanges = this._doApplyEdits(operations); - - let trimAutoWhitespaceLineNumbers: number[] = null; - if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { - // sort line numbers auto whitespace removal candidates for next edit descending - newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber); - - trimAutoWhitespaceLineNumbers = []; - for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) { - let lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber; - if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) { - // Do not have the same line number twice - continue; - } - - let prevContent = newTrimAutoWhitespaceCandidates[i].oldContent; - let lineContent = this.getLineContent(lineNumber); - - if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) { - continue; - } - - trimAutoWhitespaceLineNumbers.push(lineNumber); - } - } - - return new ApplyEditsResult( - reverseOperations, - contentChanges, - trimAutoWhitespaceLineNumbers - ); - } - - /** - * Transform operations such that they represent the same logic edit, - * but that they also do not cause OOM crashes. - */ - private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] { - if (operations.length < 1000) { - // We know from empirical testing that a thousand edits work fine regardless of their shape. - return operations; - } - - // At one point, due to how events are emitted and how each operation is handled, - // some operations can trigger a high ammount of temporary string allocations, - // that will immediately get edited again. - // e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line - // Therefore, the strategy is to collapse all the operations into a huge single edit operation - return [this._toSingleEditOperation(operations)]; - } - - _toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation { - let forceMoveMarkers = false, - firstEditRange = operations[0].range, - lastEditRange = operations[operations.length - 1].range, - entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn), - lastEndLineNumber = firstEditRange.startLineNumber, - lastEndColumn = firstEditRange.startColumn, - result: string[] = []; - - for (let i = 0, len = operations.length; i < len; i++) { - let operation = operations[i], - range = operation.range; - - forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers; - - // (1) -- Push old text - for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) { - if (lineNumber === lastEndLineNumber) { - result.push(this._lines[lineNumber - 1].substring(lastEndColumn - 1)); - } else { - result.push('\n'); - result.push(this._lines[lineNumber - 1]); - } - } - - if (range.startLineNumber === lastEndLineNumber) { - result.push(this._lines[range.startLineNumber - 1].substring(lastEndColumn - 1, range.startColumn - 1)); - } else { - result.push('\n'); - result.push(this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)); - } - - // (2) -- Push new text - if (operation.lines) { - for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) { - if (j !== 0) { - result.push('\n'); - } - result.push(operation.lines[j]); - } - } - - lastEndLineNumber = operation.range.endLineNumber; - lastEndColumn = operation.range.endColumn; - } - - return { - sortIndex: 0, - identifier: operations[0].identifier, - range: entireEditRange, - rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), - rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined), - lines: result.join('').split('\n'), - forceMoveMarkers: forceMoveMarkers, - isAutoWhitespaceEdit: false - }; - } - - private _setLineContent(lineNumber: number, content: string): void { - this._lines[lineNumber - 1] = content; - this._lineStarts.changeValue(lineNumber - 1, content.length + this._EOL.length); - } - - private _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] { - - // Sort operations descending - operations.sort(LinesTextBuffer._sortOpsDescending); - - let contentChanges: IInternalModelContentChange[] = []; - - for (let i = 0, len = operations.length; i < len; i++) { - const op = operations[i]; - - const startLineNumber = op.range.startLineNumber; - const startColumn = op.range.startColumn; - const endLineNumber = op.range.endLineNumber; - const endColumn = op.range.endColumn; - - if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) { - // no-op - continue; - } - - const deletingLinesCnt = endLineNumber - startLineNumber; - const insertingLinesCnt = (op.lines ? op.lines.length - 1 : 0); - const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); - - for (let j = editingLinesCnt; j >= 0; j--) { - const editLineNumber = startLineNumber + j; - let editText = (op.lines ? op.lines[j] : ''); - - if (editLineNumber === startLineNumber || editLineNumber === endLineNumber) { - const editStartColumn = (editLineNumber === startLineNumber ? startColumn : 1); - const editEndColumn = (editLineNumber === endLineNumber ? endColumn : this.getLineLength(editLineNumber) + 1); - - editText = ( - this._lines[editLineNumber - 1].substring(0, editStartColumn - 1) - + editText - + this._lines[editLineNumber - 1].substring(editEndColumn - 1) - ); - } - - this._setLineContent(editLineNumber, editText); - } - - if (editingLinesCnt < deletingLinesCnt) { - // Must delete some lines - - const spliceStartLineNumber = startLineNumber + editingLinesCnt; - const endLineRemains = this._lines[endLineNumber - 1].substring(endColumn - 1); - - // Reconstruct first line - this._setLineContent(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1] + endLineRemains); - - this._lines.splice(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); - this._lineStarts.removeValues(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); - } - - if (editingLinesCnt < insertingLinesCnt) { - // Must insert some lines - - const spliceLineNumber = startLineNumber + editingLinesCnt; - let spliceColumn = (spliceLineNumber === startLineNumber ? startColumn : 1); - if (op.lines) { - spliceColumn += op.lines[editingLinesCnt].length; - } - - // Split last line - const leftoverLine = this._lines[spliceLineNumber - 1].substring(spliceColumn - 1); - - this._setLineContent(spliceLineNumber, this._lines[spliceLineNumber - 1].substring(0, spliceColumn - 1)); - - // Lines in the middle - let newLines: string[] = new Array<string>(insertingLinesCnt - editingLinesCnt); - let newLinesLengths = new Uint32Array(insertingLinesCnt - editingLinesCnt); - for (let j = editingLinesCnt + 1; j <= insertingLinesCnt; j++) { - newLines[j - editingLinesCnt - 1] = op.lines[j]; - newLinesLengths[j - editingLinesCnt - 1] = op.lines[j].length + this._EOL.length; - } - newLines[newLines.length - 1] += leftoverLine; - newLinesLengths[newLines.length - 1] += leftoverLine.length; - this._lines = arrays.arrayInsert(this._lines, startLineNumber + editingLinesCnt, newLines); - this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths); - } - - const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn); - const text = (op.lines ? op.lines.join(this.getEOL()) : ''); - contentChanges.push({ - range: contentChangeRange, - rangeLength: op.rangeLength, - text: text, - rangeOffset: op.rangeOffset, - forceMoveMarkers: op.forceMoveMarkers - }); - } - - return contentChanges; - } - - /** - * Assumes `operations` are validated and sorted ascending - */ - public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] { - let result: Range[] = []; - - let prevOpEndLineNumber: number; - let prevOpEndColumn: number; - let prevOp: IValidatedEditOperation = null; - for (let i = 0, len = operations.length; i < len; i++) { - let op = operations[i]; - - let startLineNumber: number; - let startColumn: number; - - if (prevOp) { - if (prevOp.range.endLineNumber === op.range.startLineNumber) { - startLineNumber = prevOpEndLineNumber; - startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn); - } else { - startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber); - startColumn = op.range.startColumn; - } - } else { - startLineNumber = op.range.startLineNumber; - startColumn = op.range.startColumn; - } - - let resultRange: Range; - - if (op.lines && op.lines.length > 0) { - // the operation inserts something - let lineCount = op.lines.length; - let firstLine = op.lines[0]; - let lastLine = op.lines[lineCount - 1]; - - if (lineCount === 1) { - // single line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length); - } else { - // multi line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1); - } - } else { - // There is nothing to insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn); - } - - prevOpEndLineNumber = resultRange.endLineNumber; - prevOpEndColumn = resultRange.endColumn; - - result.push(resultRange); - prevOp = op; - } - - return result; - } - - //#endregion -} diff --git a/src/vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder.ts b/src/vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder.ts deleted file mode 100644 index 4bf35c915a..0000000000 --- a/src/vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder.ts +++ /dev/null @@ -1,139 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 strings from 'vs/base/common/strings'; -import { CharCode } from 'vs/base/common/charCode'; -import { ITextBufferBuilder, ITextBufferFactory, ITextBuffer, DefaultEndOfLine } from 'vs/editor/common/model'; -import { IRawTextSource, TextSource } from 'vs/editor/common/model/linesTextBuffer/textSource'; -import { LinesTextBuffer } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer'; - -export class TextBufferFactory implements ITextBufferFactory { - - constructor(public readonly rawTextSource: IRawTextSource) { - } - - public create(defaultEOL: DefaultEndOfLine): ITextBuffer { - const textSource = TextSource.fromRawTextSource(this.rawTextSource, defaultEOL); - return new LinesTextBuffer(textSource); - } - - public getFirstLineText(lengthLimit: number): string { - return this.rawTextSource.lines[0].substr(0, lengthLimit); - } -} - -class ModelLineBasedBuilder { - - private BOM: string; - private lines: string[]; - private currLineIndex: number; - - constructor() { - this.BOM = ''; - this.lines = []; - this.currLineIndex = 0; - } - - public acceptLines(lines: string[]): void { - if (this.currLineIndex === 0) { - // Remove the BOM (if present) - if (strings.startsWithUTF8BOM(lines[0])) { - this.BOM = strings.UTF8_BOM_CHARACTER; - lines[0] = lines[0].substr(1); - } - } - - for (let i = 0, len = lines.length; i < len; i++) { - this.lines[this.currLineIndex++] = lines[i]; - } - } - - public finish(carriageReturnCnt: number, containsRTL: boolean, isBasicASCII: boolean): TextBufferFactory { - return new TextBufferFactory({ - BOM: this.BOM, - lines: this.lines, - containsRTL: containsRTL, - totalCRCount: carriageReturnCnt, - isBasicASCII, - }); - } -} - -export class LinesTextBufferBuilder implements ITextBufferBuilder { - - private leftoverPrevChunk: string; - private leftoverEndsInCR: boolean; - private totalCRCount: number; - private lineBasedBuilder: ModelLineBasedBuilder; - private containsRTL: boolean; - private isBasicASCII: boolean; - - constructor() { - this.leftoverPrevChunk = ''; - this.leftoverEndsInCR = false; - this.totalCRCount = 0; - this.lineBasedBuilder = new ModelLineBasedBuilder(); - this.containsRTL = false; - this.isBasicASCII = true; - } - - private _updateCRCount(chunk: string): void { - // Count how many \r are present in chunk to determine the majority EOL sequence - let chunkCarriageReturnCnt = 0; - let lastCarriageReturnIndex = -1; - while ((lastCarriageReturnIndex = chunk.indexOf('\r', lastCarriageReturnIndex + 1)) !== -1) { - chunkCarriageReturnCnt++; - } - this.totalCRCount += chunkCarriageReturnCnt; - } - - public acceptChunk(chunk: string): void { - if (chunk.length === 0) { - return; - } - - this._updateCRCount(chunk); - - if (!this.containsRTL) { - this.containsRTL = strings.containsRTL(chunk); - } - if (this.isBasicASCII) { - this.isBasicASCII = strings.isBasicASCII(chunk); - } - - // Avoid dealing with a chunk that ends in \r (push the \r to the next chunk) - if (this.leftoverEndsInCR) { - chunk = '\r' + chunk; - } - if (chunk.charCodeAt(chunk.length - 1) === CharCode.CarriageReturn) { - this.leftoverEndsInCR = true; - chunk = chunk.substr(0, chunk.length - 1); - } else { - this.leftoverEndsInCR = false; - } - - let lines = chunk.split(/\r\n|\r|\n/); - - if (lines.length === 1) { - // no \r or \n encountered - this.leftoverPrevChunk += lines[0]; - return; - } - - lines[0] = this.leftoverPrevChunk + lines[0]; - this.lineBasedBuilder.acceptLines(lines.slice(0, lines.length - 1)); - this.leftoverPrevChunk = lines[lines.length - 1]; - } - - public finish(): TextBufferFactory { - let finalLines = [this.leftoverPrevChunk]; - if (this.leftoverEndsInCR) { - finalLines.push(''); - } - this.lineBasedBuilder.acceptLines(finalLines); - return this.lineBasedBuilder.finish(this.totalCRCount, this.containsRTL, this.isBasicASCII); - } -} diff --git a/src/vs/editor/common/model/linesTextBuffer/textSource.ts b/src/vs/editor/common/model/linesTextBuffer/textSource.ts deleted file mode 100644 index 3d10337567..0000000000 --- a/src/vs/editor/common/model/linesTextBuffer/textSource.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { DefaultEndOfLine } from 'vs/editor/common/model'; -import { ITextSource } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer'; - -/** - * A processed string ready to be turned into an editor model. - */ -export interface IRawTextSource { - /** - * The text split into lines. - */ - readonly lines: string[]; - /** - * The BOM (leading character sequence of the file). - */ - readonly BOM: string; - /** - * The number of lines ending with '\r\n' - */ - readonly totalCRCount: number; - /** - * The text contains Unicode characters classified as "R" or "AL". - */ - readonly containsRTL: boolean; - /** - * The text contains only characters inside the ASCII range 32-126 or \t \r \n - */ - readonly isBasicASCII: boolean; -} - -export class TextSource { - - /** - * if text source is empty or with precisely one line, returns null. No end of line is detected. - * if text source contains more lines ending with '\r\n', returns '\r\n'. - * Otherwise returns '\n'. More lines end with '\n'. - */ - private static _getEOL(rawTextSource: IRawTextSource, defaultEOL: DefaultEndOfLine): '\r\n' | '\n' { - const lineFeedCnt = rawTextSource.lines.length - 1; - if (lineFeedCnt === 0) { - // This is an empty file or a file with precisely one line - return (defaultEOL === DefaultEndOfLine.LF ? '\n' : '\r\n'); - } - if (rawTextSource.totalCRCount > lineFeedCnt / 2) { - // More than half of the file contains \r\n ending lines - return '\r\n'; - } - // At least one line more ends in \n - return '\n'; - } - - public static fromRawTextSource(rawTextSource: IRawTextSource, defaultEOL: DefaultEndOfLine): ITextSource { - return { - lines: rawTextSource.lines, - BOM: rawTextSource.BOM, - EOL: TextSource._getEOL(rawTextSource, defaultEOL), - containsRTL: rawTextSource.containsRTL, - isBasicASCII: rawTextSource.isBasicASCII, - }; - } -} diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts index 7758cbb759..e228cbfc3a 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -9,8 +9,11 @@ import { CharCode } from 'vs/base/common/charCode'; import { Range } from 'vs/editor/common/core/range'; import { ITextSnapshot } from 'vs/platform/files/common/files'; import { leftest, righttest, updateTreeMetadata, rbDelete, fixInsert, NodeColor, SENTINEL, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase'; +import { SearchData, isValidMatch, Searcher, createFindMatch } from 'vs/editor/common/model/textModelSearch'; +import { FindMatch } from 'vs/editor/common/model'; // const lfRegex = new RegExp(/\r\n|\r|\n/g); +export const AverageBufferSize = 65535; export function createUintArray(arr: number[]): Uint32Array | Uint16Array { let r; @@ -33,7 +36,7 @@ export class LineStarts { ) { } } -export function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | number[] { +export function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] { let r: number[] = [0], rLength = 1; for (let i = 0, len = str.length; i < len; i++) { @@ -309,7 +312,7 @@ export class PieceTreeBase { } normalizeEOL(eol: '\r\n' | '\n') { - let averageBufferSize = 65536; + let averageBufferSize = AverageBufferSize; let min = averageBufferSize - Math.floor(averageBufferSize / 3); let max = min * 2; @@ -446,7 +449,7 @@ export class PieceTreeBase { return new Position(1, 1); } - public getValueInRange(range: Range): string { + public getValueInRange(range: Range, eol?: string): string { if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) { return ''; } @@ -454,7 +457,21 @@ export class PieceTreeBase { let startPosition = this.nodeAt2(range.startLineNumber, range.startColumn); let endPosition = this.nodeAt2(range.endLineNumber, range.endColumn); - return this.getValueInRange2(startPosition, endPosition); + let value = this.getValueInRange2(startPosition, endPosition); + if (eol) { + if (eol !== this._EOL || !this._EOLNormalized) { + return value.replace(/\r\n|\r|\n/g, eol); + } + + if (eol === this.getEOL() && this._EOLNormalized) { + if (eol === '\r\n') { + + } + return value; + } + return value.replace(/\r\n|\r|\n/g, eol); + } + return value; } public getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string { @@ -520,11 +537,23 @@ export class PieceTreeBase { public getLineCharCode(lineNumber: number, index: number): number { let nodePos = this.nodeAt2(lineNumber, index + 1); - let buffer = this._buffers[nodePos.node.piece.bufferIndex]; - let startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start); - let targetOffset = startOffset + index; + if (nodePos.remainder === nodePos.node.piece.length) { + // the char we want to fetch is at the head of next node. + let matchingNode = nodePos.node.next(); + if (!matchingNode) { + return 0; + } - return buffer.buffer.charCodeAt(targetOffset); + let buffer = this._buffers[matchingNode.piece.bufferIndex]; + let startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start); + return buffer.buffer.charCodeAt(startOffset); + } else { + let buffer = this._buffers[nodePos.node.piece.bufferIndex]; + let startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start); + let targetOffset = startOffset + nodePos.remainder; + + return buffer.buffer.charCodeAt(targetOffset); + } } public getLineLength(lineNumber: number): number { @@ -535,6 +564,151 @@ export class PieceTreeBase { return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength; } + public findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) { + let buffer = this._buffers[node.piece.bufferIndex]; + let startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start); + let start = this.offsetInBuffer(node.piece.bufferIndex, startCursor); + let end = this.offsetInBuffer(node.piece.bufferIndex, endCursor); + + let m: RegExpExecArray; + // Reset regex to search from the beginning + searcher.reset(start); + let ret: BufferCursor = { line: 0, column: 0 }; + + do { + m = searcher.next(buffer.buffer); + + if (m) { + if (m.index >= end) { + return resultLen; + } + this.positionInBuffer(node, m.index - startOffsetInBuffer, ret); + let lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret); + let retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1; + let retEndColumn = retStartColumn + m[0].length; + result[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches); + + if (m.index + m[0].length >= end) { + return resultLen; + } + if (resultLen >= limitResultCount) { + return resultLen; + } + } + + } while (m); + + return resultLen; + } + + public findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] { + const result: FindMatch[] = []; + let resultLen = 0; + const searcher = new Searcher(searchData.wordSeparators, searchData.regex); + + let startPostion = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn); + if (startPostion === null) { + return []; + } + let endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn); + if (endPosition === null) { + return []; + } + let start = this.positionInBuffer(startPostion.node, startPostion.remainder); + let end = this.positionInBuffer(endPosition.node, endPosition.remainder); + + if (startPostion.node === endPosition.node) { + this.findMatchesInNode(startPostion.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result); + return result; + } + + let startLineNumber = searchRange.startLineNumber; + + let currentNode = startPostion.node; + while (currentNode !== endPosition.node) { + let lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end); + + if (lineBreakCnt >= 1) { + // last line break position + let lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts; + let startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start); + let nextLineStartOffset = lineStarts[start.line + lineBreakCnt]; + let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1; + resultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result); + + if (resultLen >= limitResultCount) { + return result; + } + + startLineNumber += lineBreakCnt; + } + + let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0; + // search for the remaining content + if (startLineNumber === searchRange.endLineNumber) { + const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1); + resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount); + return result; + } + + resultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount); + + if (resultLen >= limitResultCount) { + return result; + } + + startLineNumber++; + startPostion = this.nodeAt2(startLineNumber, 1); + currentNode = startPostion.node; + start = this.positionInBuffer(startPostion.node, startPostion.remainder); + } + + if (startLineNumber === searchRange.endLineNumber) { + let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0; + const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1); + resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount); + return result; + } + + let startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1; + resultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result); + return result; + } + + private _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number { + const wordSeparators = searchData.wordSeparators; + if (!captureMatches && searchData.simpleSearch) { + const searchString = searchData.simpleSearch; + const searchStringLen = searchString.length; + const textLength = text.length; + + let lastMatchIndex = -searchStringLen; + while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) { + if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) { + result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null); + if (resultLen >= limitResultCount) { + return resultLen; + } + } + } + return resultLen; + } + + let m: RegExpExecArray; + // Reset regex to search from the beginning + searcher.reset(0); + do { + m = searcher.next(text); + if (m) { + result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches); + if (resultLen >= limitResultCount) { + return resultLen; + } + } + } while (m); + return resultLen; + } + // #endregion // #region Piece Table @@ -551,7 +725,8 @@ export class PieceTreeBase { if (node.piece.bufferIndex === 0 && piece.end.line === this._lastChangeBufferPos.line && piece.end.column === this._lastChangeBufferPos.column && - (nodeStartOffset + piece.length === offset) + (nodeStartOffset + piece.length === offset) && + value.length < AverageBufferSize ) { // changed buffer this.appendToNode(node, value); @@ -608,19 +783,27 @@ export class PieceTreeBase { this.deleteNodeTail(node, insertPosInBuffer); } - let newPiece = this.createNewPiece(value); + let newPieces = this.createNewPieces(value); if (newRightPiece.length > 0) { this.rbInsertRight(node, newRightPiece); } - this.rbInsertRight(node, newPiece); + + let tmpNode = node; + for (let k = 0; k < newPieces.length; k++) { + tmpNode = this.rbInsertRight(tmpNode, newPieces[k]); + } this.deleteNodes(nodesToDel); } else { this.insertContentToNodeRight(value, node); } } else { // insert new node - let piece = this.createNewPiece(value); - this.rbInsertLeft(null, piece); + let pieces = this.createNewPieces(value); + let node = this.rbInsertLeft(null, pieces[0]); + + for (let k = 1; k < pieces.length; k++) { + node = this.rbInsertRight(node, pieces[k]); + } } // todo, this is too brutal. Total line feed count should be updated the same way as lf_left. @@ -726,8 +909,11 @@ export class PieceTreeBase { } } - let newPiece = this.createNewPiece(value); - let newNode = this.rbInsertLeft(node, newPiece); + let newPieces = this.createNewPieces(value); + let newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]); + for (let k = newPieces.length - 2; k >= 0; k--) { + newNode = this.rbInsertLeft(newNode, newPieces[k]); + } this.validateCRLFWithPrevNode(newNode); this.deleteNodes(nodesToDel); } @@ -739,12 +925,18 @@ export class PieceTreeBase { value += '\n'; } - let newPiece = this.createNewPiece(value); - let newNode = this.rbInsertRight(node, newPiece); + let newPieces = this.createNewPieces(value); + let newNode = this.rbInsertRight(node, newPieces[0]); + let tmpNode = newNode; + + for (let k = 1; k < newPieces.length; k++) { + tmpNode = this.rbInsertRight(tmpNode, newPieces[k]); + } + this.validateCRLFWithPrevNode(newNode); } - positionInBuffer(node: TreeNode, remainder: number): BufferCursor { + positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor { let piece = node.piece; let bufferIndex = node.piece.bufferIndex; let lineStarts = this._buffers[bufferIndex].lineStarts; @@ -780,6 +972,12 @@ export class PieceTreeBase { } } + if (ret) { + ret.line = mid; + ret.column = offset - midStart; + return null; + } + return { line: mid, column: offset - midStart @@ -827,7 +1025,47 @@ export class PieceTreeBase { } } - createNewPiece(text: string): Piece { + createNewPieces(text: string): Piece[] { + if (text.length > AverageBufferSize) { + // the content is large, operations like substring, charCode becomes slow + // so here we split it into smaller chunks, just like what we did for CR/LF normalization + let newPieces = []; + while (text.length > AverageBufferSize) { + const lastChar = text.charCodeAt(AverageBufferSize - 1); + let splitText; + if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) { + // last character is \r or a high surrogate => keep it back + splitText = text.substring(0, AverageBufferSize - 1); + text = text.substring(AverageBufferSize - 1); + } else { + splitText = text.substring(0, AverageBufferSize); + text = text.substring(AverageBufferSize); + } + + let lineStarts = createLineStartsFast(splitText); + newPieces.push(new Piece( + this._buffers.length, /* buffer index */ + { line: 0, column: 0 }, + { line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] }, + lineStarts.length - 1, + splitText.length + )); + this._buffers.push(new StringBuffer(splitText, lineStarts)); + } + + let lineStarts = createLineStartsFast(text); + newPieces.push(new Piece( + this._buffers.length, /* buffer index */ + { line: 0, column: 0 }, + { line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] }, + lineStarts.length - 1, + text.length + )); + this._buffers.push(new StringBuffer(text, lineStarts)); + + return newPieces; + } + let startOffset = this._buffers[0].buffer.length; const lineStarts = createLineStartsFast(text, false); @@ -862,14 +1100,14 @@ export class PieceTreeBase { let endColumn = endOffset - this._buffers[0].lineStarts[endIndex]; let endPos = { line: endIndex, column: endColumn }; let newPiece = new Piece( - 0, + 0, /** todo */ start, endPos, this.getLineFeedCnt(0, start, endPos), endOffset - startOffset ); this._lastChangeBufferPos = endPos; - return newPiece; + return [newPiece]; } getLinesRawContent(): string { @@ -1352,8 +1590,8 @@ export class PieceTreeBase { } // create new piece which contains \r\n - let piece = this.createNewPiece('\r\n'); - this.rbInsertRight(prev, piece); + let pieces = this.createNewPieces('\r\n'); + this.rbInsertRight(prev, pieces[0]); // delete empty nodes for (let i = 0; i < nodesToDel.length; i++) { diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index f78561a82d..56eb282234 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -7,10 +7,25 @@ import { Range } from 'vs/editor/common/core/range'; import { Position } from 'vs/editor/common/core/position'; import * as strings from 'vs/base/common/strings'; -import { IValidatedEditOperation } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer'; import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; -import { IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange } from 'vs/editor/common/model'; +import { IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange, FindMatch, ISingleEditOperationIdentifier } from 'vs/editor/common/model'; import { ITextSnapshot } from 'vs/platform/files/common/files'; +import { SearchData } from 'vs/editor/common/model/textModelSearch'; + +export interface IValidatedEditOperation { + sortIndex: number; + identifier: ISingleEditOperationIdentifier; + range: Range; + rangeOffset: number; + rangeLength: number; + lines: string[]; + forceMoveMarkers: boolean; + isAutoWhitespaceEdit: boolean; +} + +export interface IReverseSingleEditOperation extends IIdentifiedSingleEditOperation { + sortIndex: number; +} export class PieceTreeTextBuffer implements ITextBuffer { private _pieceTree: PieceTreeBase; @@ -76,8 +91,7 @@ export class PieceTreeTextBuffer implements ITextBuffer { } const lineEnding = this._getEndOfLine(eol); - const text = this._pieceTree.getValueInRange(range); - return text.replace(/\r\n|\r|\n/g, lineEnding); + return this._pieceTree.getValueInRange(range, lineEnding); } public getValueLengthInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): number { @@ -192,13 +206,17 @@ export class PieceTreeTextBuffer implements ITextBuffer { // Sort operations ascending operations.sort(PieceTreeTextBuffer._sortOpsAscending); + let hasTouchingRanges = false; for (let i = 0, count = operations.length - 1; i < count; i++) { let rangeEnd = operations[i].range.getEndPosition(); let nextRangeStart = operations[i + 1].range.getStartPosition(); - if (nextRangeStart.isBefore(rangeEnd)) { - // overlapping ranges - throw new Error('Overlapping ranges are not allowed!'); + if (nextRangeStart.isBeforeOrEqual(rangeEnd)) { + if (nextRangeStart.isBefore(rangeEnd)) { + // overlapping ranges + throw new Error('Overlapping ranges are not allowed!'); + } + hasTouchingRanges = true; } } @@ -229,12 +247,13 @@ export class PieceTreeTextBuffer implements ITextBuffer { } } - let reverseOperations: IIdentifiedSingleEditOperation[] = []; + let reverseOperations: IReverseSingleEditOperation[] = []; for (let i = 0; i < operations.length; i++) { let op = operations[i]; let reverseRange = reverseRanges[i]; reverseOperations[i] = { + sortIndex: op.sortIndex, identifier: op.identifier, range: reverseRange, text: this.getValueInRange(op.range), @@ -242,6 +261,11 @@ export class PieceTreeTextBuffer implements ITextBuffer { }; } + // Can only sort reverse operations when the order is not significant + if (!hasTouchingRanges) { + reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex); + } + this._mightContainRTL = mightContainRTL; this._mightContainNonBasicASCII = mightContainNonBasicASCII; @@ -279,9 +303,9 @@ export class PieceTreeTextBuffer implements ITextBuffer { } /** - * Transform operations such that they represent the same logic edit, - * but that they also do not cause OOM crashes. - */ + * Transform operations such that they represent the same logic edit, + * but that they also do not cause OOM crashes. + */ private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] { if (operations.length < 1000) { // We know from empirical testing that a thousand edits work fine regardless of their shape. @@ -410,6 +434,10 @@ export class PieceTreeTextBuffer implements ITextBuffer { return contentChanges; } + findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] { + return this._pieceTree.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount); + } + // #endregion // #region helper diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index ce000e7187..2306dddba1 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -5,7 +5,7 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as model from 'vs/editor/common/model'; import { LanguageIdentifier, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; import { EditStack } from 'vs/editor/common/model/editStack'; @@ -30,31 +30,13 @@ import { getWordAtText } from 'vs/editor/common/model/wordHelper'; import { ModelLinesTokens, ModelTokensChangedEventBuilder } from 'vs/editor/common/model/textModelTokens'; import { guessIndentation } from 'vs/editor/common/model/indentationGuesser'; import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { TextModelSearch, SearchParams } from 'vs/editor/common/model/textModelSearch'; +import { TextModelSearch, SearchParams, SearchData } from 'vs/editor/common/model/textModelSearch'; import { TPromise } from 'vs/base/common/winjs.base'; import { IStringStream, ITextSnapshot } from 'vs/platform/files/common/files'; -import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; -import { ChunksTextBufferBuilder } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder'; - -export enum TextBufferType { - LinesArray, - PieceTree, - Chunks -} -// Here is the master switch for the text buffer implementation: -export const OPTIONS = { - TEXT_BUFFER_IMPLEMENTATION: TextBufferType.PieceTree -}; function createTextBufferBuilder() { - if (OPTIONS.TEXT_BUFFER_IMPLEMENTATION === TextBufferType.PieceTree) { - return new PieceTreeTextBufferBuilder(); - } - if (OPTIONS.TEXT_BUFFER_IMPLEMENTATION === TextBufferType.Chunks) { - return new ChunksTextBufferBuilder(); - } - return new LinesTextBufferBuilder(); + return new PieceTreeTextBufferBuilder(); } export function createTextBufferFactory(text: string): model.ITextBufferFactory { @@ -173,15 +155,17 @@ class TextModelSnapshot implements ITextSnapshot { export class TextModel extends Disposable implements model.ITextModel { private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB - private static readonly MODEL_TOKENIZATION_LIMIT = 20 * 1024 * 1024; // 20 MB - private static readonly MANY_MANY_LINES = 300 * 1000; // 300K lines + private static readonly LARGE_FILE_SIZE_THRESHOLD = 20 * 1024 * 1024; // 20 MB; + private static readonly LARGE_FILE_LINE_COUNT_THRESHOLD = 300 * 1000; // 300K lines public static DEFAULT_CREATION_OPTIONS: model.ITextModelCreationOptions = { + isForSimpleWidget: false, tabSize: EDITOR_MODEL_DEFAULTS.tabSize, insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces, detectIndentation: false, defaultEOL: model.DefaultEndOfLine.LF, trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace, + largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations, }; public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): TextModel { @@ -228,15 +212,19 @@ export class TextModel extends Disposable implements model.ITextModel { public readonly onDidChangeOptions: Event<IModelOptionsChangedEvent> = this._onDidChangeOptions.event; private readonly _eventEmitter: DidChangeContentEmitter = this._register(new DidChangeContentEmitter()); + public onDidChangeRawContentFast(listener: (e: ModelRawContentChangedEvent) => void): IDisposable { + return this._eventEmitter.fastEvent((e: InternalModelContentChangeEvent) => listener(e.rawContentChangedEvent)); + } public onDidChangeRawContent(listener: (e: ModelRawContentChangedEvent) => void): IDisposable { - return this._eventEmitter.event((e: InternalModelContentChangeEvent) => listener(e.rawContentChangedEvent)); + return this._eventEmitter.slowEvent((e: InternalModelContentChangeEvent) => listener(e.rawContentChangedEvent)); } public onDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable { - return this._eventEmitter.event((e: InternalModelContentChangeEvent) => listener(e.contentChangedEvent)); + return this._eventEmitter.slowEvent((e: InternalModelContentChangeEvent) => listener(e.contentChangedEvent)); } //#endregion public readonly id: string; + public readonly isForSimpleWidget: boolean; private readonly _associatedResource: URI; private _attachedEditorCount: number; private _buffer: model.ITextBuffer; @@ -249,7 +237,7 @@ export class TextModel extends Disposable implements model.ITextModel { * Unlike, versionId, this can go down (via undo) or go to previous values (via redo) */ private _alternativeVersionId: number; - private readonly _shouldSimplifyMode: boolean; + private readonly _isTooLargeForSyncing: boolean; private readonly _isTooLargeForTokenization: boolean; //#region Editing @@ -284,6 +272,7 @@ export class TextModel extends Disposable implements model.ITextModel { // Generate a new unique model id MODEL_ID++; this.id = '$model' + MODEL_ID; + this.isForSimpleWidget = creationOptions.isForSimpleWidget; if (typeof associatedResource === 'undefined' || associatedResource === null) { this._associatedResource = URI.parse('inmemory://model/' + MODEL_ID); } else { @@ -297,18 +286,20 @@ export class TextModel extends Disposable implements model.ITextModel { const bufferLineCount = this._buffer.getLineCount(); const bufferTextLength = this._buffer.getValueLengthInRange(new Range(1, 1, bufferLineCount, this._buffer.getLineLength(bufferLineCount) + 1), model.EndOfLinePreference.TextDefined); + // !!! Make a decision in the ctor and permanently respect this decision !!! // If a model is too large at construction time, it will never get tokenized, // under no circumstances. - this._isTooLargeForTokenization = ( - (bufferTextLength > TextModel.MODEL_TOKENIZATION_LIMIT) - || (bufferLineCount > TextModel.MANY_MANY_LINES) - ); + if (creationOptions.largeFileOptimizations) { + this._isTooLargeForTokenization = ( + (bufferTextLength > TextModel.LARGE_FILE_SIZE_THRESHOLD) + || (bufferLineCount > TextModel.LARGE_FILE_LINE_COUNT_THRESHOLD) + ); + } else { + this._isTooLargeForTokenization = false; + } - this._shouldSimplifyMode = ( - this._isTooLargeForTokenization - || (bufferTextLength > TextModel.MODEL_SYNC_LIMIT) - ); + this._isTooLargeForSyncing = (bufferTextLength > TextModel.MODEL_SYNC_LIMIT); this._setVersionId(1); this._isDisposed = false; @@ -398,10 +389,11 @@ export class TextModel extends Disposable implements model.ITextModel { this.setValueFromTextBuffer(textBuffer); } - private _createContentChanged2(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeLength: number, text: string, isUndoing: boolean, isRedoing: boolean, isFlush: boolean): IModelContentChangedEvent { + private _createContentChanged2(range: Range, rangeOffset: number, rangeLength: number, text: string, isUndoing: boolean, isRedoing: boolean, isFlush: boolean): IModelContentChangedEvent { return { changes: [{ - range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), + range: range, + rangeOffset: rangeOffset, rangeLength: rangeLength, text: text, }], @@ -447,7 +439,7 @@ export class TextModel extends Disposable implements model.ITextModel { false, false ), - this._createContentChanged2(1, 1, endLineNumber, endColumn, oldModelValueLength, this.getValue(), false, false, true) + this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, true) ); } @@ -478,7 +470,7 @@ export class TextModel extends Disposable implements model.ITextModel { false, false ), - this._createContentChanged2(1, 1, endLineNumber, endColumn, oldModelValueLength, this.getValue(), false, false, false) + this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, false) ); } @@ -548,8 +540,12 @@ export class TextModel extends Disposable implements model.ITextModel { return this._attachedEditorCount > 0; } - public isTooLargeForHavingARichMode(): boolean { - return this._shouldSimplifyMode; + public getAttachedEditorCount(): number { + return this._attachedEditorCount; + } + + public isTooLargeForSyncing(): boolean { + return this._isTooLargeForSyncing; } public isTooLargeForTokenization(): boolean { @@ -779,6 +775,15 @@ export class TextModel extends Disposable implements model.ITextModel { return this._buffer.getLineContent(lineNumber); } + public getLineLength(lineNumber: number): number { + this._assertNotDisposed(); + if (lineNumber < 1 || lineNumber > this.getLineCount()) { + throw new Error('Illegal value for lineNumber'); + } + + return this._buffer.getLineLength(lineNumber); + } + public getLinesContent(): string[] { this._assertNotDisposed(); return this._buffer.getLinesContent(); @@ -889,6 +894,41 @@ export class TextModel extends Disposable implements model.ITextModel { return new Range(startLineNumber, startColumn, endLineNumber, endColumn); } + /** + * @param strict Do NOT allow a position inside a high-low surrogate pair + */ + private _isValidPosition(lineNumber: number, column: number, strict: boolean): boolean { + + if (lineNumber < 1) { + return false; + } + + const lineCount = this._buffer.getLineCount(); + if (lineNumber > lineCount) { + return false; + } + + if (column < 1) { + return false; + } + + const maxColumn = this.getLineMaxColumn(lineNumber); + if (column > maxColumn) { + return false; + } + + if (strict) { + if (column > 1) { + const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2); + if (strings.isHighSurrogate(charCodeBefore)) { + return false; + } + } + } + + return true; + } + /** * @param strict Do NOT allow a position inside a high-low surrogate pair */ @@ -929,11 +969,60 @@ export class TextModel extends Disposable implements model.ITextModel { public validatePosition(position: IPosition): Position { this._assertNotDisposed(); + + // Avoid object allocation and cover most likely case + if (position instanceof Position) { + if (this._isValidPosition(position.lineNumber, position.column, true)) { + return position; + } + } + return this._validatePosition(position.lineNumber, position.column, true); } + /** + * @param strict Do NOT allow a range to have its boundaries inside a high-low surrogate pair + */ + private _isValidRange(range: Range, strict: boolean): boolean { + const startLineNumber = range.startLineNumber; + const startColumn = range.startColumn; + const endLineNumber = range.endLineNumber; + const endColumn = range.endColumn; + + if (!this._isValidPosition(startLineNumber, startColumn, false)) { + return false; + } + if (!this._isValidPosition(endLineNumber, endColumn, false)) { + return false; + } + + if (strict) { + const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0); + const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0); + + const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart); + const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd); + + if (!startInsideSurrogatePair && !endInsideSurrogatePair) { + return true; + } + + return false; + } + + return true; + } + public validateRange(_range: IRange): Range { this._assertNotDisposed(); + + // Avoid object allocation and cover most likely case + if ((_range instanceof Range) && !(_range instanceof Selection)) { + if (this._isValidRange(_range, true)) { + return _range; + } + } + const start = this._validatePosition(_range.startLineNumber, _range.startColumn, false); const end = this._validatePosition(_range.endLineNumber, _range.endColumn, false); @@ -983,6 +1072,10 @@ export class TextModel extends Disposable implements model.ITextModel { return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount)); } + private findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): model.FindMatch[] { + return this._buffer.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount); + } + public findMatches(searchString: string, rawSearchScope: any, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean, limitResultCount: number = LIMIT_FIND_COUNT): model.FindMatch[] { this._assertNotDisposed(); @@ -993,12 +1086,46 @@ export class TextModel extends Disposable implements model.ITextModel { searchRange = this.getFullModelRange(); } + if (!isRegex && searchString.indexOf('\n') < 0) { + // not regex, not multi line + const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators); + const searchData = searchParams.parseSearchRequest(); + + if (!searchData) { + return []; + } + + return this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount); + } + return TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount); } public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch { this._assertNotDisposed(); const searchStart = this.validatePosition(rawSearchStart); + + if (!isRegex && searchString.indexOf('\n') < 0) { + const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators); + const searchData = searchParams.parseSearchRequest(); + const lineCount = this.getLineCount(); + let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount)); + let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1); + TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches); + if (ret.length > 0) { + return ret[0]; + } + + searchRange = new Range(1, 1, searchStart.lineNumber, this.getLineMaxColumn(searchStart.lineNumber)); + ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1); + + if (ret.length > 0) { + return ret[0]; + } + + return null; + } + return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches); } @@ -1584,6 +1711,88 @@ export class TextModel extends Disposable implements model.ITextModel { //#region Tokenization + public tokenizeViewport(startLineNumber: number, endLineNumber: number): void { + if (!this._tokens.tokenizationSupport) { + return; + } + + // we tokenize `this._tokens.inValidLineStartIndex` lines in around 20ms so it's a good baseline. + const contextBefore = Math.floor(this._tokens.inValidLineStartIndex * 0.3); + startLineNumber = Math.max(1, startLineNumber - contextBefore); + + if (startLineNumber <= this._tokens.inValidLineStartIndex) { + this.forceTokenization(endLineNumber); + return; + } + + const eventBuilder = new ModelTokensChangedEventBuilder(); + let nonWhitespaceColumn = this.getLineFirstNonWhitespaceColumn(startLineNumber); + let fakeLines = []; + let i = startLineNumber - 1; + let initialState = null; + if (nonWhitespaceColumn > 0) { + while (nonWhitespaceColumn > 0 && i >= 1) { + let newNonWhitespaceIndex = this.getLineFirstNonWhitespaceColumn(i); + + if (newNonWhitespaceIndex === 0) { + i--; + continue; + } + + if (newNonWhitespaceIndex < nonWhitespaceColumn) { + initialState = this._tokens._getState(i - 1); + if (initialState) { + break; + } + fakeLines.push(this.getLineContent(i)); + nonWhitespaceColumn = newNonWhitespaceIndex; + } + + i--; + } + } + + if (!initialState) { + initialState = this._tokens.tokenizationSupport.getInitialState(); + } + + let state = initialState.clone(); + for (let i = fakeLines.length - 1; i >= 0; i--) { + let r = this._tokens._tokenizeText(this._buffer, fakeLines[i], state); + if (r) { + state = r.endState.clone(); + } else { + state = initialState.clone(); + } + } + + const contextAfter = Math.floor(this._tokens.inValidLineStartIndex * 0.4); + endLineNumber = Math.min(this.getLineCount(), endLineNumber + contextAfter); + for (let i = startLineNumber; i <= endLineNumber; i++) { + let text = this.getLineContent(i); + let r = this._tokens._tokenizeText(this._buffer, text, state); + if (r) { + this._tokens._setTokens(this._tokens.languageIdentifier.id, i - 1, text.length, r.tokens); + /* + * we think it's valid and give it a state but we don't update `_invalidLineStartIndex` then the top-to-bottom tokenization + * goes through the viewport, it can skip them if they already have correct tokens and state, and the lines after the viewport + * can still be tokenized. + */ + this._tokens._setIsInvalid(i - 1, false); + this._tokens._setState(i - 1, state); + state = r.endState.clone(); + eventBuilder.registerChangedTokens(i); + } else { + state = initialState.clone(); + } + } + + const e = eventBuilder.build(); + if (e) { + this._onDidChangeTokens.fire(e); + } + } + public forceTokenization(lineNumber: number): void { if (lineNumber < 1 || lineNumber > this.getLineCount()) { throw new Error('Illegal value for lineNumber'); @@ -1726,8 +1935,39 @@ export class TextModel extends Disposable implements model.ITextModel { const position = this.validatePosition(_position); const lineContent = this.getLineContent(position.lineNumber); const lineTokens = this._getLineTokens(position.lineNumber); - const offset = position.column - 1; - const tokenIndex = lineTokens.findTokenIndexAtOffset(offset); + const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1); + + // (1). First try checking right biased word + const [rbStartOffset, rbEndOffset] = TextModel._findLanguageBoundaries(lineTokens, tokenIndex); + const rightBiasedWord = getWordAtText( + position.column, + LanguageConfigurationRegistry.getWordDefinition(lineTokens.getLanguageId(tokenIndex)), + lineContent.substring(rbStartOffset, rbEndOffset), + rbStartOffset + ); + if (rightBiasedWord) { + return rightBiasedWord; + } + + // (2). Else, if we were at a language boundary, check the left biased word + if (tokenIndex > 0 && rbStartOffset === position.column - 1) { + // edge case, where `position` sits between two tokens belonging to two different languages + const [lbStartOffset, lbEndOffset] = TextModel._findLanguageBoundaries(lineTokens, tokenIndex - 1); + const leftBiasedWord = getWordAtText( + position.column, + LanguageConfigurationRegistry.getWordDefinition(lineTokens.getLanguageId(tokenIndex - 1)), + lineContent.substring(lbStartOffset, lbEndOffset), + lbStartOffset + ); + if (leftBiasedWord) { + return leftBiasedWord; + } + } + + return null; + } + + private static _findLanguageBoundaries(lineTokens: LineTokens, tokenIndex: number): [number, number] { const languageId = lineTokens.getLanguageId(tokenIndex); // go left until a different language is hit @@ -1742,12 +1982,7 @@ export class TextModel extends Disposable implements model.ITextModel { endOffset = lineTokens.getEndOffset(i); } - return getWordAtText( - position.column, - LanguageConfigurationRegistry.getWordDefinition(languageId), - lineContent.substring(startOffset, endOffset), - startOffset - ); + return [startOffset, endOffset]; } public getWordUntilPosition(position: IPosition): model.IWordAtPosition { @@ -1809,25 +2044,13 @@ export class TextModel extends Disposable implements model.ITextModel { // limit search to not go after `maxBracketLength` const searchEndOffset = Math.min(lineTokens.getEndOffset(tokenIndex), position.column - 1 + currentModeBrackets.maxBracketLength); - // first, check if there is a bracket to the right of `position` - let foundBracket = BracketsUtils.findNextBracketInToken(currentModeBrackets.forwardRegex, lineNumber, lineText, position.column - 1, searchEndOffset); - if (foundBracket && foundBracket.startColumn === position.column) { - let foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1); - foundBracketText = foundBracketText.toLowerCase(); - - let r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText]); - - // check that we can actually match this bracket - if (r) { - return r; - } - } - - // it might still be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets + // it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets + // `bestResult` will contain the most right-side result + let bestResult: [Range, Range] = null; while (true) { let foundBracket = BracketsUtils.findNextBracketInToken(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset); if (!foundBracket) { - // there are no brackets in this text + // there are no more brackets in this text break; } @@ -1840,12 +2063,16 @@ export class TextModel extends Disposable implements model.ITextModel { // check that we can actually match this bracket if (r) { - return r; + bestResult = r; } } searchStartOffset = foundBracket.endColumn - 1; } + + if (bestResult) { + return bestResult; + } } // If position is in between two tokens, try also looking in the previous token @@ -1879,6 +2106,10 @@ export class TextModel extends Disposable implements model.ITextModel { } private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] { + if (!data) { + return null; + } + if (isOpen) { let matched = this._findMatchingBracketDown(data, foundBracket.getEndPosition()); if (matched) { @@ -2158,6 +2389,173 @@ export class TextModel extends Disposable implements model.ITextModel { return TextModel.computeIndentLevel(this._buffer.getLineContent(lineIndex + 1), this._options.tabSize); } + public getActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): model.IActiveIndentGuideInfo { + this._assertNotDisposed(); + const lineCount = this.getLineCount(); + + if (lineNumber < 1 || lineNumber > lineCount) { + throw new Error('Illegal value for lineNumber'); + } + + const foldingRules = LanguageConfigurationRegistry.getFoldingRules(this._languageIdentifier.id); + const offSide = foldingRules && foldingRules.offSide; + + let up_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */ + let up_aboveContentLineIndent = -1; + let up_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */ + let up_belowContentLineIndent = -1; + const up_resolveIndents = (lineNumber: number) => { + if (up_aboveContentLineIndex !== -1 && (up_aboveContentLineIndex === -2 || up_aboveContentLineIndex > lineNumber - 1)) { + up_aboveContentLineIndex = -1; + up_aboveContentLineIndent = -1; + + // must find previous line with content + for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) { + let indent = this._computeIndentLevel(lineIndex); + if (indent >= 0) { + up_aboveContentLineIndex = lineIndex; + up_aboveContentLineIndent = indent; + break; + } + } + } + + if (up_belowContentLineIndex === -2) { + up_belowContentLineIndex = -1; + up_belowContentLineIndent = -1; + + // must find next line with content + for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) { + let indent = this._computeIndentLevel(lineIndex); + if (indent >= 0) { + up_belowContentLineIndex = lineIndex; + up_belowContentLineIndent = indent; + break; + } + } + } + }; + + let down_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */ + let down_aboveContentLineIndent = -1; + let down_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */ + let down_belowContentLineIndent = -1; + const down_resolveIndents = (lineNumber: number) => { + if (down_aboveContentLineIndex === -2) { + down_aboveContentLineIndex = -1; + down_aboveContentLineIndent = -1; + + // must find previous line with content + for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) { + let indent = this._computeIndentLevel(lineIndex); + if (indent >= 0) { + down_aboveContentLineIndex = lineIndex; + down_aboveContentLineIndent = indent; + break; + } + } + } + + if (down_belowContentLineIndex !== -1 && (down_belowContentLineIndex === -2 || down_belowContentLineIndex < lineNumber - 1)) { + down_belowContentLineIndex = -1; + down_belowContentLineIndent = -1; + + // must find next line with content + for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) { + let indent = this._computeIndentLevel(lineIndex); + if (indent >= 0) { + down_belowContentLineIndex = lineIndex; + down_belowContentLineIndent = indent; + break; + } + } + } + }; + + let startLineNumber = 0; + let goUp = true; + let endLineNumber = 0; + let goDown = true; + let indent = 0; + + for (let distance = 0; goUp || goDown; distance++) { + const upLineNumber = lineNumber - distance; + const downLineNumber = lineNumber + distance; + + if (upLineNumber < 1 || upLineNumber < minLineNumber) { + goUp = false; + } + if (downLineNumber > lineCount || downLineNumber > maxLineNumber) { + goDown = false; + } + if (distance > 50000) { + // stop processing + goUp = false; + goDown = false; + } + + if (goUp) { + // compute indent level going up + let upLineIndentLevel: number; + + const currentIndent = this._computeIndentLevel(upLineNumber - 1); + if (currentIndent >= 0) { + // This line has content (besides whitespace) + // Use the line's indent + up_belowContentLineIndex = upLineNumber - 1; + up_belowContentLineIndent = currentIndent; + upLineIndentLevel = Math.ceil(currentIndent / this._options.tabSize); + } else { + up_resolveIndents(upLineNumber); + upLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, up_aboveContentLineIndent, up_belowContentLineIndent); + } + + if (distance === 0) { + // This is the initial line number + startLineNumber = upLineNumber; + endLineNumber = downLineNumber; + indent = upLineIndentLevel; + if (indent === 0) { + // No need to continue + return { startLineNumber, endLineNumber, indent }; + } + continue; + } + + if (upLineIndentLevel >= indent) { + startLineNumber = upLineNumber; + } else { + goUp = false; + } + } + + if (goDown) { + // compute indent level going down + let downLineIndentLevel: number; + + const currentIndent = this._computeIndentLevel(downLineNumber - 1); + if (currentIndent >= 0) { + // This line has content (besides whitespace) + // Use the line's indent + down_aboveContentLineIndex = downLineNumber - 1; + down_aboveContentLineIndent = currentIndent; + downLineIndentLevel = Math.ceil(currentIndent / this._options.tabSize); + } else { + down_resolveIndents(downLineNumber); + downLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, down_aboveContentLineIndent, down_belowContentLineIndent); + } + + if (downLineIndentLevel >= indent) { + endLineNumber = downLineNumber; + } else { + goDown = false; + } + } + } + + return { startLineNumber, endLineNumber, indent }; + } + public getLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[] { this._assertNotDisposed(); const lineCount = this.getLineCount(); @@ -2223,32 +2621,38 @@ export class TextModel extends Disposable implements model.ITextModel { } } - if (aboveContentLineIndent === -1 || belowContentLineIndent === -1) { - // At the top or bottom of the file - result[resultIndex] = 0; + result[resultIndex] = this._getIndentLevelForWhitespaceLine(offSide, aboveContentLineIndent, belowContentLineIndent); - } else if (aboveContentLineIndent < belowContentLineIndent) { - // we are inside the region above - result[resultIndex] = (1 + Math.floor(aboveContentLineIndent / this._options.tabSize)); - - } else if (aboveContentLineIndent === belowContentLineIndent) { - // we are in between two regions - result[resultIndex] = Math.ceil(belowContentLineIndent / this._options.tabSize); - - } else { - - if (offSide) { - // same level as region below - result[resultIndex] = Math.ceil(belowContentLineIndent / this._options.tabSize); - } else { - // we are inside the region that ends below - result[resultIndex] = (1 + Math.floor(belowContentLineIndent / this._options.tabSize)); - } - - } } return result; } + + private _getIndentLevelForWhitespaceLine(offSide: boolean, aboveContentLineIndent: number, belowContentLineIndent: number): number { + if (aboveContentLineIndent === -1 || belowContentLineIndent === -1) { + // At the top or bottom of the file + return 0; + + } else if (aboveContentLineIndent < belowContentLineIndent) { + // we are inside the region above + return (1 + Math.floor(aboveContentLineIndent / this._options.tabSize)); + + } else if (aboveContentLineIndent === belowContentLineIndent) { + // we are in between two regions + return Math.ceil(belowContentLineIndent / this._options.tabSize); + + } else { + + if (offSide) { + // same level as region below + return Math.ceil(belowContentLineIndent / this._options.tabSize); + } else { + // we are inside the region that ends below + return (1 + Math.floor(belowContentLineIndent / this._options.tabSize)); + } + + } + } + //#endregion } @@ -2363,22 +2767,20 @@ export class ModelDecorationOverviewRulerOptions implements model.IModelDecorati } } -let lastStaticId = 0; - export class ModelDecorationOptions implements model.IModelDecorationOptions { public static EMPTY: ModelDecorationOptions; public static register(options: model.IModelDecorationOptions): ModelDecorationOptions { - return new ModelDecorationOptions(++lastStaticId, options); + return new ModelDecorationOptions(options); } public static createDynamic(options: model.IModelDecorationOptions): ModelDecorationOptions { - return new ModelDecorationOptions(0, options); + return new ModelDecorationOptions(options); } - readonly staticId: number; readonly stickiness: model.TrackedRangeStickiness; + readonly zIndex: number; readonly className: string; readonly hoverMessage: IMarkdownString | IMarkdownString[]; readonly glyphMarginHoverMessage: IMarkdownString | IMarkdownString[]; @@ -2389,12 +2791,13 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions { readonly linesDecorationsClassName: string; readonly marginClassName: string; readonly inlineClassName: string; + readonly inlineClassNameAffectsLetterSpacing: boolean; readonly beforeContentClassName: string; readonly afterContentClassName: string; - private constructor(staticId: number, options: model.IModelDecorationOptions) { - this.staticId = staticId; + private constructor(options: model.IModelDecorationOptions) { this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges; + this.zIndex = options.zIndex || 0; this.className = options.className ? cleanClassName(options.className) : strings.empty; this.hoverMessage = options.hoverMessage || []; this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || []; @@ -2405,6 +2808,7 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions { this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : strings.empty; this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : strings.empty; this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : strings.empty; + this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false; this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : strings.empty; this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : strings.empty; } @@ -2465,8 +2869,13 @@ export class DidChangeDecorationsEmitter extends Disposable { export class DidChangeContentEmitter extends Disposable { - private readonly _actual: Emitter<InternalModelContentChangeEvent> = this._register(new Emitter<InternalModelContentChangeEvent>()); - public readonly event: Event<InternalModelContentChangeEvent> = this._actual.event; + /** + * Both `fastEvent` and `slowEvent` work the same way and contain the same events, but first we invoke `fastEvent` and then `slowEvent`. + */ + private readonly _fastEmitter: Emitter<InternalModelContentChangeEvent> = this._register(new Emitter<InternalModelContentChangeEvent>()); + public readonly fastEvent: Event<InternalModelContentChangeEvent> = this._fastEmitter.event; + private readonly _slowEmitter: Emitter<InternalModelContentChangeEvent> = this._register(new Emitter<InternalModelContentChangeEvent>()); + public readonly slowEvent: Event<InternalModelContentChangeEvent> = this._slowEmitter.event; private _deferredCnt: number; private _deferredEvent: InternalModelContentChangeEvent; @@ -2487,7 +2896,8 @@ export class DidChangeContentEmitter extends Disposable { if (this._deferredEvent !== null) { const e = this._deferredEvent; this._deferredEvent = null; - this._actual.fire(e); + this._fastEmitter.fire(e); + this._slowEmitter.fire(e); } } } @@ -2501,6 +2911,7 @@ export class DidChangeContentEmitter extends Disposable { } return; } - this._actual.fire(e); + this._fastEmitter.fire(e); + this._slowEmitter.fire(e); } } diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index 42ef490a09..af86a55339 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -32,6 +32,10 @@ export interface IModelContentChange { * The range that got replaced. */ readonly range: IRange; + /** + * The offset of the range that got replaced. + */ + readonly rangeOffset: number; /** * The length of the range that got replaced. */ diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index 9ef4651b92..91ce9da661 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -116,7 +116,7 @@ export class SearchData { } } -function createFindMatch(range: Range, rawMatches: RegExpExecArray, captureMatches: boolean): FindMatch { +export function createFindMatch(range: Range, rawMatches: RegExpExecArray, captureMatches: boolean): FindMatch { if (!captureMatches) { return new FindMatch(range, null); } @@ -434,6 +434,11 @@ function leftIsWordBounday(wordSeparators: WordCharacterClassifier, text: string return true; } + if (charBefore === CharCode.CarriageReturn || charBefore === CharCode.LineFeed) { + // The character before the match is line break or carriage return. + return true; + } + if (matchLength > 0) { const firstCharInMatch = text.charCodeAt(matchStartIndex); if (wordSeparators.get(firstCharInMatch) !== WordCharacterClass.Regular) { @@ -457,6 +462,11 @@ function rightIsWordBounday(wordSeparators: WordCharacterClassifier, text: strin return true; } + if (charAfter === CharCode.CarriageReturn || charAfter === CharCode.LineFeed) { + // The character after the match is line break or carriage return. + return true; + } + if (matchLength > 0) { const lastCharInMatch = text.charCodeAt(matchStartIndex + matchLength - 1); if (wordSeparators.get(lastCharInMatch) !== WordCharacterClass.Regular) { @@ -468,14 +478,14 @@ function rightIsWordBounday(wordSeparators: WordCharacterClassifier, text: strin return false; } -function isValidMatch(wordSeparators: WordCharacterClassifier, text: string, textLength: number, matchStartIndex: number, matchLength: number): boolean { +export function isValidMatch(wordSeparators: WordCharacterClassifier, text: string, textLength: number, matchStartIndex: number, matchLength: number): boolean { return ( leftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) && rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) ); } -class Searcher { +export class Searcher { private _wordSeparators: WordCharacterClassifier; private _searchRegex: RegExp; private _prevMatchStartIndex: number; diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index b98953c5db..093fd1b24a 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -25,7 +25,7 @@ function getDefaultMetadata(topLevelLanguageId: LanguageId): number { ) >>> 0; } -const EMPTY_LINE_TOKENS = new Uint32Array(0); +const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer; class ModelLineTokens { _state: IState; @@ -196,9 +196,13 @@ export class ModelLinesTokens { this._lastState = null; } + public get inValidLineStartIndex() { + return this._invalidLineStartIndex; + } + public getTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineText: string): LineTokens { let rawLineTokens: ArrayBuffer = null; - if (lineIndex < this._tokens.length) { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { rawLineTokens = this._tokens[lineIndex]._lineTokens; } @@ -229,21 +233,21 @@ export class ModelLinesTokens { } } - private _setIsInvalid(lineIndex: number, invalid: boolean): void { - if (lineIndex < this._tokens.length) { + _setIsInvalid(lineIndex: number, invalid: boolean): void { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { this._tokens[lineIndex]._invalid = invalid; } } _isInvalid(lineIndex: number): boolean { - if (lineIndex < this._tokens.length) { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { return this._tokens[lineIndex]._invalid; } return true; } _getState(lineIndex: number): IState { - if (lineIndex < this._tokens.length) { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { return this._tokens[lineIndex]._state; } return null; @@ -251,7 +255,7 @@ export class ModelLinesTokens { _setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, tokens: Uint32Array): void { let target: ModelLineTokens; - if (lineIndex < this._tokens.length) { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { target = this._tokens[lineIndex]; } else { target = new ModelLineTokens(null); @@ -274,8 +278,8 @@ export class ModelLinesTokens { target._lineTokens = tokens.buffer; } - private _setState(lineIndex: number, state: IState): void { - if (lineIndex < this._tokens.length) { + _setState(lineIndex: number, state: IState): void { + if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { this._tokens[lineIndex]._state = state; } else { const tmp = new ModelLineTokens(state); @@ -376,6 +380,21 @@ export class ModelLinesTokens { return lineNumber; } + public _tokenizeText(buffer: ITextBuffer, text: string, state: IState): TokenizationResult2 { + let r: TokenizationResult2 = null; + + try { + r = this.tokenizationSupport.tokenize2(text, state, 0); + } catch (e) { + onUnexpectedError(e); + } + + if (!r) { + r = nullTokenize2(this.languageIdentifier.id, text, state, 0); + } + return r; + } + public _updateTokensUntilLine(buffer: ITextBuffer, eventBuilder: ModelTokensChangedEventBuilder, lineNumber: number): void { if (!this.tokenizationSupport) { this._invalidLineStartIndex = buffer.getLineCount(); diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 6e93d5472c..2d665175e6 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -12,7 +12,7 @@ import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegis import { CancellationToken } from 'vs/base/common/cancellation'; import { Position } from 'vs/editor/common/core/position'; import { Range, IRange } from 'vs/editor/common/core/range'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { TokenizationRegistryImpl } from 'vs/editor/common/modes/tokenizationRegistry'; import { Color } from 'vs/base/common/color'; import { IMarkerData } from 'vs/platform/markers/common/markers'; @@ -230,7 +230,7 @@ export interface Hover { * editor will use the range at the current position or the * current position itself. */ - range: IRange; + range?: IRange; } /** @@ -364,6 +364,11 @@ export interface CodeActionProvider { * Provide commands for the given document and range. */ provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): CodeAction[] | Thenable<CodeAction[]>; + + /** + * Optional list of of CodeActionKinds that this provider returns. + */ + providedCodeActionKinds?: string[]; } /** @@ -825,66 +830,60 @@ export interface DocumentColorProvider { */ provideColorPresentations(model: model.ITextModel, colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable<IColorPresentation[]>; } - +export interface FoldingContext { +} /** * A provider of colors for editor models. */ -/** - * @internal - */ -export interface FoldingProvider { +export interface FoldingRangeProvider { /** * Provides the color ranges for a specific model. */ - provideFoldingRanges(model: model.ITextModel, token: CancellationToken): IFoldingRangeList | Thenable<IFoldingRangeList>; + provideFoldingRanges(model: model.ITextModel, context: FoldingContext, token: CancellationToken): FoldingRange[] | Thenable<FoldingRange[]>; } -/** - * @internal - */ -export interface IFoldingRangeList { - ranges: IFoldingRange[]; +export interface FoldingRange { + + /** + * The zero-based start line of the range to fold. The folded area starts after the line's last character. + */ + start: number; + + /** + * The zero-based end line of the range to fold. The folded area ends with the line's last character. + */ + end: number; + + /** + * Describes the [Kind](#FoldingRangeKind) of the folding range such as [Comment](#FoldingRangeKind.Comment) or + * [Region](#FoldingRangeKind.Region). The kind is used to categorize folding ranges and used by commands + * like 'Fold all comments'. See + * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. + */ + kind?: FoldingRangeKind; } -/** - * @internal - */ -export interface IFoldingRange { +export class FoldingRangeKind { + /** + * Kind for folding range representing a comment. The value of the kind is 'comment'. + */ + static readonly Comment = new FoldingRangeKind('comment'); + /** + * Kind for folding range representing a import. The value of the kind is 'imports'. + */ + static readonly Imports = new FoldingRangeKind('imports'); + /** + * Kind for folding range representing regions (for example marked by `#region`, `#endregion`). + * The value of the kind is 'region'. + */ + static readonly Region = new FoldingRangeKind('region'); /** - * The start line number + * Creates a new [FoldingRangeKind](#FoldingRangeKind). + * + * @param value of the kind. */ - startLineNumber: number; - - /** - * The end line number - */ - endLineNumber: number; - - /** - * The optional type of the folding range - */ - type?: FoldingRangeType | string; - - // auto-collapse - // header span - -} -/** - * @internal - */ -export enum FoldingRangeType { - /** - * Folding range for a comment - */ - Comment = 'comment', - /** - * Folding range for a imports or includes - */ - Imports = 'imports', - /** - * Folding range for a region (e.g. `#region`) - */ - Region = 'region' + public constructor(public value: string) { + } } /** @@ -917,14 +916,14 @@ export interface WorkspaceEdit { rejectReason?: string; // TODO@joh, move to rename } -export interface RenameInitialValue { +export interface RenameLocation { range: IRange; - text?: string; + text: string; } export interface RenameProvider { provideRenameEdits(model: model.ITextModel, position: Position, newName: string, token: CancellationToken): WorkspaceEdit | Thenable<WorkspaceEdit>; - resolveInitialRenameValue?(model: model.ITextModel, position: Position, token: CancellationToken): RenameInitialValue | Thenable<RenameInitialValue>; + resolveRenameLocation?(model: model.ITextModel, position: Position, token: CancellationToken): RenameLocation | Thenable<RenameLocation>; } @@ -1035,7 +1034,7 @@ export const ColorProviderRegistry = new LanguageFeatureRegistry<DocumentColorPr /** * @internal */ -export const FoldingProviderRegistry = new LanguageFeatureRegistry<FoldingProvider>(); +export const FoldingRangeProviderRegistry = new LanguageFeatureRegistry<FoldingRangeProvider>(); /** * @internal diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index bc8063d6e8..55b19bb6a4 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -9,7 +9,7 @@ import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/comm import { IOnEnterSupportOptions, OnEnterSupport } from 'vs/editor/common/modes/supports/onEnter'; import { IndentRulesSupport, IndentConsts } from 'vs/editor/common/modes/supports/indentRules'; import { RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITextModel } from 'vs/editor/common/model'; import { onUnexpectedError } from 'vs/base/common/errors'; import * as strings from 'vs/base/common/strings'; @@ -177,8 +177,8 @@ export class LanguageConfigurationRegistryImpl { private _entries: RichEditSupport[]; - private _onDidChange: Emitter<LanguageConfigurationChangeEvent> = new Emitter<LanguageConfigurationChangeEvent>(); - public onDidChange: Event<LanguageConfigurationChangeEvent> = this._onDidChange.event; + private readonly _onDidChange: Emitter<LanguageConfigurationChangeEvent> = new Emitter<LanguageConfigurationChangeEvent>(); + public readonly onDidChange: Event<LanguageConfigurationChangeEvent> = this._onDidChange.event; constructor() { this._entries = []; diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index a3dfe5ec63..926db4cadd 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -5,10 +5,11 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ITextModel } from 'vs/editor/common/model'; import { LanguageSelector, score } from 'vs/editor/common/modes/languageSelector'; +import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; interface Entry<T> { selector: LanguageSelector; @@ -17,11 +18,21 @@ interface Entry<T> { _time: number; } +function isExclusive(selector: LanguageSelector): boolean { + if (typeof selector === 'string') { + return false; + } else if (Array.isArray(selector)) { + return selector.every(isExclusive); + } else { + return selector.exclusive; + } +} + export default class LanguageFeatureRegistry<T> { private _clock: number = 0; private _entries: Entry<T>[] = []; - private _onDidChange: Emitter<number> = new Emitter<number>(); + private readonly _onDidChange: Emitter<number> = new Emitter<number>(); constructor() { } @@ -63,7 +74,7 @@ export default class LanguageFeatureRegistry<T> { } all(model: ITextModel): T[] { - if (!model || model.isTooLargeForHavingARichMode()) { + if (!model) { return []; } @@ -106,7 +117,7 @@ export default class LanguageFeatureRegistry<T> { private _orderedForEach(model: ITextModel, callback: (provider: Entry<T>) => any): void { - if (!model || model.isTooLargeForHavingARichMode()) { + if (!model) { return; } @@ -140,7 +151,17 @@ export default class LanguageFeatureRegistry<T> { this._lastCandidate = candidate; for (let entry of this._entries) { - entry._score = score(entry.selector, model.uri, model.getLanguageIdentifier().language); + entry._score = score(entry.selector, model.uri, model.getLanguageIdentifier().language, shouldSynchronizeModel(model)); + + if (isExclusive(entry.selector) && entry._score > 0) { + // support for one exclusive selector that overwrites + // any other selector + for (let entry of this._entries) { + entry._score = 0; + } + entry._score = 1000; + break; + } } // needs sorting diff --git a/src/vs/editor/common/modes/languageSelector.ts b/src/vs/editor/common/modes/languageSelector.ts index 8362959660..22938c90ac 100644 --- a/src/vs/editor/common/modes/languageSelector.ts +++ b/src/vs/editor/common/modes/languageSelector.ts @@ -12,17 +12,22 @@ export interface LanguageFilter { language?: string; scheme?: string; pattern?: string | IRelativePattern; + /** + * This provider is implemented in the UI thread. + */ + hasAccessToAllModels?: boolean; + exclusive?: boolean; } export type LanguageSelector = string | LanguageFilter | (string | LanguageFilter)[]; -export function score(selector: LanguageSelector, candidateUri: URI, candidateLanguage: string): number { +export function score(selector: LanguageSelector, candidateUri: URI, candidateLanguage: string, candidateIsSynchronized: boolean): number { if (Array.isArray(selector)) { // array -> take max individual value let ret = 0; for (const filter of selector) { - const value = score(filter, candidateUri, candidateLanguage); + const value = score(filter, candidateUri, candidateLanguage, candidateIsSynchronized); if (value === 10) { return value; // already at the highest } @@ -33,9 +38,14 @@ export function score(selector: LanguageSelector, candidateUri: URI, candidateLa return ret; } else if (typeof selector === 'string') { + + if (!candidateIsSynchronized) { + return 0; + } + // short-hand notion, desugars to - // 'fooLang' -> [{ language: 'fooLang', scheme: 'file' }, { language: 'fooLang', scheme: 'untitled' }] - // '*' -> { language: '*', scheme: '*' } + // 'fooLang' -> { language: 'fooLang'} + // '*' -> { language: '*' } if (selector === '*') { return 5; } else if (selector === candidateLanguage) { @@ -46,7 +56,11 @@ export function score(selector: LanguageSelector, candidateUri: URI, candidateLa } else if (selector) { // filter -> select accordingly, use defaults for scheme - const { language, pattern, scheme } = selector; + const { language, pattern, scheme, hasAccessToAllModels } = selector; + + if (!candidateIsSynchronized && !hasAccessToAllModels) { + return 0; + } let ret = 0; diff --git a/src/vs/editor/common/modes/modesRegistry.ts b/src/vs/editor/common/modes/modesRegistry.ts index 6ecd2ae14b..6f94b69709 100644 --- a/src/vs/editor/common/modes/modesRegistry.ts +++ b/src/vs/editor/common/modes/modesRegistry.ts @@ -5,7 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { ILanguageExtensionPoint } from 'vs/editor/common/services/modeService'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; @@ -20,8 +20,8 @@ export class EditorModesRegistry { private _languages: ILanguageExtensionPoint[]; - private _onDidAddLanguages: Emitter<ILanguageExtensionPoint[]> = new Emitter<ILanguageExtensionPoint[]>(); - public onDidAddLanguages: Event<ILanguageExtensionPoint[]> = this._onDidAddLanguages.event; + private readonly _onDidAddLanguages: Emitter<ILanguageExtensionPoint[]> = new Emitter<ILanguageExtensionPoint[]>(); + public readonly onDidAddLanguages: Event<ILanguageExtensionPoint[]> = this._onDidAddLanguages.event; constructor() { this._languages = []; diff --git a/src/vs/editor/common/modes/supports/richEditBrackets.ts b/src/vs/editor/common/modes/supports/richEditBrackets.ts index 911060c92a..6635ff67a1 100644 --- a/src/vs/editor/common/modes/supports/richEditBrackets.ts +++ b/src/vs/editor/common/modes/supports/richEditBrackets.ts @@ -85,14 +85,14 @@ function once<T, R>(keyFn: (input: T) => string, computeFn: (input: T) => R): (i const getRegexForBracketPair = once<ISimpleInternalBracket, RegExp>( (input) => `${input.open};${input.close}`, (input) => { - return createOrRegex([input.open, input.close]); + return createBracketOrRegExp([input.open, input.close]); } ); const getReversedRegexForBracketPair = once<ISimpleInternalBracket, RegExp>( (input) => `${input.open};${input.close}`, (input) => { - return createOrRegex([toReversedString(input.open), toReversedString(input.close)]); + return createBracketOrRegExp([toReversedString(input.open), toReversedString(input.close)]); } ); @@ -104,7 +104,7 @@ const getRegexForBrackets = once<ISimpleInternalBracket[], RegExp>( pieces.push(b.open); pieces.push(b.close); }); - return createOrRegex(pieces); + return createBracketOrRegExp(pieces); } ); @@ -116,12 +116,19 @@ const getReversedRegexForBrackets = once<ISimpleInternalBracket[], RegExp>( pieces.push(toReversedString(b.open)); pieces.push(toReversedString(b.close)); }); - return createOrRegex(pieces); + return createBracketOrRegExp(pieces); } ); -function createOrRegex(pieces: string[]): RegExp { - let regexStr = `(${pieces.map(strings.escapeRegExpCharacters).join(')|(')})`; +function prepareBracketForRegExp(str: string): string { + // This bracket pair uses letters like e.g. "begin" - "end" + const insertWordBoundaries = (/^[\w]+$/.test(str)); + str = strings.escapeRegExpCharacters(str); + return (insertWordBoundaries ? `\\b${str}\\b` : str); +} + +function createBracketOrRegExp(pieces: string[]): RegExp { + let regexStr = `(${pieces.map(prepareBracketForRegExp).join(')|(')})`; return strings.createRegExp(regexStr, true); } diff --git a/src/vs/editor/common/modes/tokenizationRegistry.ts b/src/vs/editor/common/modes/tokenizationRegistry.ts index 1349abc9aa..add6bdef73 100644 --- a/src/vs/editor/common/modes/tokenizationRegistry.ts +++ b/src/vs/editor/common/modes/tokenizationRegistry.ts @@ -5,7 +5,7 @@ 'use strict'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes'; import { Color } from 'vs/base/common/color'; @@ -13,8 +13,8 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { private _map: { [language: string]: ITokenizationSupport }; - private _onDidChange: Emitter<ITokenizationSupportChangedEvent> = new Emitter<ITokenizationSupportChangedEvent>(); - public onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event; + private readonly _onDidChange: Emitter<ITokenizationSupportChangedEvent> = new Emitter<ITokenizationSupportChangedEvent>(); + public readonly onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event; private _colorMap: Color[]; diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 9205ffb700..779a6234d8 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -22,6 +22,7 @@ import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model import { createMonacoBaseAPI } from 'vs/editor/common/standalone/standaloneBase'; import { IWordAtPosition, EndOfLineSequence } from 'vs/editor/common/model'; import { globals } from 'vs/base/common/platform'; +import { IIterator } from 'vs/base/common/iterator'; export interface IMirrorModel { readonly uri: URI; @@ -58,8 +59,8 @@ export interface ICommonModel { getLinesContent(): string[]; getLineCount(): number; getLineContent(lineNumber: number): string; + createWordIterator(wordDefinition: RegExp): IIterator<string>; getWordUntilPosition(position: IPosition, wordDefinition: RegExp): IWordAtPosition; - getAllUniqueWords(wordDefinition: RegExp, skipWordOnce?: string): string[]; getValueInRange(range: IRange): string; getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range; offsetAt(position: IPosition): number; @@ -146,30 +147,37 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { }; } - private _getAllWords(wordDefinition: RegExp): string[] { - let result: string[] = []; - this._lines.forEach((line) => { - this._wordenize(line, wordDefinition).forEach((info) => { - result.push(line.substring(info.start, info.end)); - }); - }); - return result; - } + public createWordIterator(wordDefinition: RegExp): IIterator<string> { + let obj = { + done: false, + value: '' + }; + let lineNumber = 0; + let lineText: string; + let wordRangesIdx = 0; + let wordRanges: IWordRange[] = []; + let next = () => { + + if (wordRangesIdx < wordRanges.length) { + obj.done = false; + obj.value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end); + wordRangesIdx += 1; + + } else if (lineNumber >= this._lines.length) { + obj.done = true; + obj.value = undefined; - public getAllUniqueWords(wordDefinition: RegExp, skipWordOnce?: string): string[] { - let foundSkipWord = false; - let uniqueWords = Object.create(null); - return this._getAllWords(wordDefinition).filter((word) => { - if (skipWordOnce && !foundSkipWord && skipWordOnce === word) { - foundSkipWord = true; - return false; - } else if (uniqueWords[word]) { - return false; } else { - uniqueWords[word] = true; - return true; + lineText = this._lines[lineNumber]; + wordRanges = this._wordenize(lineText, wordDefinition); + wordRangesIdx = 0; + lineNumber += 1; + return next(); } - }); + + return obj; + }; + return { next }; } private _wordenize(content: string, wordDefinition: RegExp): IWordRange[] { @@ -288,13 +296,24 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { } } +/** + * @internal + */ +export interface IForeignModuleFactory { + (ctx: IWorkerContext, createData: any): any; +} + +declare var require; + /** * @internal */ export abstract class BaseEditorSimpleWorker { + private _foreignModuleFactory: IForeignModuleFactory; private _foreignModule: any; - constructor() { + constructor(foreignModuleFactory: IForeignModuleFactory) { + this._foreignModuleFactory = foreignModuleFactory; this._foreignModule = null; } @@ -416,6 +435,8 @@ export abstract class BaseEditorSimpleWorker { // ---- BEGIN suggest -------------------------------------------------------------------------- + private static readonly _suggestionsLimit = 10000; + public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): TPromise<ISuggestResult> { const model = this._getModel(modelUrl); if (model) { @@ -423,17 +444,32 @@ export abstract class BaseEditorSimpleWorker { const wordDefRegExp = new RegExp(wordDef, wordDefFlags); const currentWord = model.getWordUntilPosition(position, wordDefRegExp).word; - for (const word of model.getAllUniqueWords(wordDefRegExp)) { - if (word !== currentWord && isNaN(Number(word))) { - suggestions.push({ - type: 'text', - label: word, - insertText: word, - noAutoAccept: true, - overwriteBefore: currentWord.length - }); + const seen: Record<string, boolean> = Object.create(null); + seen[currentWord] = true; + + for ( + let iter = model.createWordIterator(wordDefRegExp), e = iter.next(); + !e.done && suggestions.length <= BaseEditorSimpleWorker._suggestionsLimit; + e = iter.next() + ) { + const word = e.value; + if (seen[word]) { + continue; } + seen[word] = true; + if (!isNaN(Number(word))) { + continue; + } + + suggestions.push({ + type: 'text', + label: word, + insertText: word, + noAutoAccept: true, + overwriteBefore: currentWord.length + }); } + return TPromise.as({ suggestions }); } return undefined; @@ -474,14 +510,25 @@ export abstract class BaseEditorSimpleWorker { // ---- BEGIN foreign module support -------------------------------------------------------------------------- public loadForeignModule(moduleId: string, createData: any): TPromise<string[]> { + let ctx: IWorkerContext = { + getMirrorModels: (): IMirrorModel[] => { + return this._getModels(); + } + }; + + if (this._foreignModuleFactory) { + this._foreignModule = this._foreignModuleFactory(ctx, createData); + // static foreing module + let methods: string[] = []; + for (let prop in this._foreignModule) { + if (typeof this._foreignModule[prop] === 'function') { + methods.push(prop); + } + } + return TPromise.as(methods); + } return new TPromise<any>((c, e) => { - // Use the global require to be sure to get the global config - (<any>self).require([moduleId], (foreignModule: { create: (ctx: IWorkerContext, createData: any) => any; }) => { - let ctx: IWorkerContext = { - getMirrorModels: (): IMirrorModel[] => { - return this._getModels(); - } - }; + require([moduleId], (foreignModule: { create: IForeignModuleFactory }) => { this._foreignModule = foreignModule.create(ctx, createData); let methods: string[] = []; @@ -521,8 +568,8 @@ export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IR private _models: { [uri: string]: MirrorModel; }; - constructor() { - super(); + constructor(foreignModuleFactory: IForeignModuleFactory) { + super(foreignModuleFactory); this._models = Object.create(null); } @@ -565,9 +612,12 @@ export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IR * @internal */ export function create(): IRequestHandler { - return new EditorSimpleWorkerImpl(); + return new EditorSimpleWorkerImpl(null); } +// This is only available in a Web Worker +declare function importScripts(...urls: string[]): void; + if (typeof importScripts === 'function') { // Running in a web worker globals.monaco = createMonacoBaseAPI(); diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index aa293a5cd7..708e06f928 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -351,7 +351,7 @@ export class EditorWorkerClient extends Disposable { )); } catch (err) { logOnceWebWorkerWarning(err); - this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl()); + this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null)); } } return this._worker; @@ -360,7 +360,7 @@ export class EditorWorkerClient extends Disposable { protected _getProxy(): TPromise<EditorSimpleWorkerImpl> { return new ShallowCancelThenPromise(this._getOrCreateWorker().getProxyObject().then(null, (err) => { logOnceWebWorkerWarning(err); - this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl()); + this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null)); return this._getOrCreateWorker().getProxyObject(); })); } diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index 30e1aea558..5127e972aa 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -111,13 +111,9 @@ export class LanguagesRegistry { let primaryMime: string = null; - if (typeof lang.mimetypes !== 'undefined' && Array.isArray(lang.mimetypes)) { - for (let i = 0; i < lang.mimetypes.length; i++) { - if (!primaryMime) { - primaryMime = lang.mimetypes[i]; - } - resolvedLanguage.mimetypes.push(lang.mimetypes[i]); - } + if (Array.isArray(lang.mimetypes) && lang.mimetypes.length > 0) { + resolvedLanguage.mimetypes.push(...lang.mimetypes); + primaryMime = lang.mimetypes[0]; } if (!primaryMime) { diff --git a/src/vs/editor/common/services/modeService.ts b/src/vs/editor/common/services/modeService.ts index 0f65ae9199..46cff37947 100644 --- a/src/vs/editor/common/services/modeService.ts +++ b/src/vs/editor/common/services/modeService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index 264d5c99d2..ae4e1af48c 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -5,7 +5,7 @@ 'use strict'; import { onUnexpectedError } from 'vs/base/common/errors'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; import { FrankensteinMode } from 'vs/editor/common/modes/abstractMode'; diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index 9fb249fd75..f363b62c0e 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -16,7 +16,7 @@ export const IModelService = createDecorator<IModelService>('modelService'); export interface IModelService { _serviceBrand: any; - createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI): ITextModel; + createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI, isForSimpleWidget?: boolean): ITextModel; updateModel(model: ITextModel, value: string | ITextBufferFactory): void; @@ -26,7 +26,7 @@ export interface IModelService { getModels(): ITextModel[]; - getCreationOptions(language: string, resource: URI): ITextModelCreationOptions; + getCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions; getModel(resource: URI): ITextModel; @@ -36,3 +36,9 @@ export interface IModelService { onModelModeChanged: Event<{ model: ITextModel; oldModeId: string; }>; } + +export function shouldSynchronizeModel(model: ITextModel): boolean { + return ( + !model.isTooLargeForSyncing() && !model.isForSimpleWidget + ); +} diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 370bec5d22..76d7be70de 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -5,16 +5,14 @@ 'use strict'; import * as nls from 'vs/nls'; -import network = require('vs/base/common/network'); -import Event, { Emitter } from 'vs/base/common/event'; +import * as network from 'vs/base/common/network'; +import { Event, Emitter } from 'vs/base/common/event'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IMarker, IMarkerService } from 'vs/platform/markers/common/markers'; +import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { Range } from 'vs/editor/common/core/range'; -import { Selection } from 'vs/editor/common/core/selection'; import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; import { IMode, LanguageIdentifier } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -28,6 +26,8 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService'; import { overviewRulerWarning, overviewRulerError, overviewRulerInfo } from 'vs/editor/common/view/editorColorRegistry'; import { ITextModel, IModelDeltaDecoration, IModelDecorationOptions, TrackedRangeStickiness, OverviewRulerLane, DefaultEndOfLine, ITextModelCreationOptions, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBufferFactory, ITextBuffer, EndOfLinePreference } from 'vs/editor/common/model'; +import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { basename } from 'vs/base/common/paths'; function MODEL_ID(resource: URI): string { return resource.toString(); @@ -82,15 +82,23 @@ class ModelMarkerHandler { } private static _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range { - let marker = model.validateRange(new Range(rawMarker.startLineNumber, rawMarker.startColumn, rawMarker.endLineNumber, rawMarker.endColumn)); - let ret: Range = new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn); + + let ret = Range.lift(rawMarker); + + if (rawMarker.severity === MarkerSeverity.Hint && Range.spansMultipleLines(ret)) { + // never render hints on multiple lines + ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn); + } + + ret = model.validateRange(ret); + if (ret.isEmpty()) { let word = model.getWordAtPosition(ret.getStartPosition()); if (word) { ret = new Range(ret.startLineNumber, word.startColumn, ret.endLineNumber, word.endColumn); } else { - let maxColumn = model.getLineLastNonWhitespaceColumn(marker.startLineNumber) || - model.getLineMaxColumn(marker.startLineNumber); + let maxColumn = model.getLineLastNonWhitespaceColumn(ret.startLineNumber) || + model.getLineMaxColumn(ret.startLineNumber); if (maxColumn === 1) { // empty line @@ -118,31 +126,36 @@ class ModelMarkerHandler { let className: string; let color: ThemeColor; let darkColor: ThemeColor; + let zIndex: number; switch (marker.severity) { - case Severity.Ignore: - // do something + case MarkerSeverity.Hint: + className = ClassName.EditorHintDecoration; + zIndex = 0; break; - case Severity.Warning: + case MarkerSeverity.Warning: className = ClassName.EditorWarningDecoration; color = themeColorFromId(overviewRulerWarning); darkColor = themeColorFromId(overviewRulerWarning); + zIndex = 20; break; - case Severity.Info: + case MarkerSeverity.Info: className = ClassName.EditorInfoDecoration; color = themeColorFromId(overviewRulerInfo); darkColor = themeColorFromId(overviewRulerInfo); + zIndex = 10; break; - case Severity.Error: + case MarkerSeverity.Error: default: className = ClassName.EditorErrorDecoration; color = themeColorFromId(overviewRulerError); darkColor = themeColorFromId(overviewRulerError); + zIndex = 30; break; } let hoverMessage: MarkdownString = null; - let { message, source } = marker; + let { message, source, relatedInformation } = marker; if (typeof message === 'string') { message = message.trim(); @@ -156,6 +169,16 @@ class ModelMarkerHandler { } hoverMessage = new MarkdownString().appendCodeblock('_', message); + + if (!isFalsyOrEmpty(relatedInformation)) { + hoverMessage.appendMarkdown('\n'); + for (const { message, resource, startLineNumber, startColumn } of relatedInformation) { + hoverMessage.appendMarkdown( + `* [${basename(resource.path)}(${startLineNumber}, ${startColumn})](${resource.toString(false)}#${startLineNumber},${startColumn}): \`${message}\` \n` + ); + } + hoverMessage.appendMarkdown('\n'); + } } return { @@ -167,7 +190,8 @@ class ModelMarkerHandler { color, darkColor, position: OverviewRulerLane.Right - } + }, + zIndex }; } } @@ -181,6 +205,8 @@ interface IRawConfig { insertSpaces?: any; detectIndentation?: any; trimAutoWhitespace?: any; + creationOptions?: any; + largeFileOptimizations?: any; }; } @@ -194,9 +220,9 @@ export class ModelServiceImpl implements IModelService { private _configurationService: IConfigurationService; private _configurationServiceSubscription: IDisposable; - private _onModelAdded: Emitter<ITextModel>; - private _onModelRemoved: Emitter<ITextModel>; - private _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }>; + private readonly _onModelAdded: Emitter<ITextModel>; + private readonly _onModelRemoved: Emitter<ITextModel>; + private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }>; private _modelCreationOptionsByLanguageAndResource: { [languageAndResource: string]: ITextModelCreationOptions; @@ -227,7 +253,7 @@ export class ModelServiceImpl implements IModelService { this._updateModelOptions(); } - private static _readModelOptions(config: IRawConfig): ITextModelCreationOptions { + private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions { let tabSize = EDITOR_MODEL_DEFAULTS.tabSize; if (config.editor && typeof config.editor.tabSize !== 'undefined') { let parsedTabSize = parseInt(config.editor.tabSize, 10); @@ -259,19 +285,26 @@ export class ModelServiceImpl implements IModelService { detectIndentation = (config.editor.detectIndentation === 'false' ? false : Boolean(config.editor.detectIndentation)); } + let largeFileOptimizations = EDITOR_MODEL_DEFAULTS.largeFileOptimizations; + if (config.editor && typeof config.editor.largeFileOptimizations !== 'undefined') { + largeFileOptimizations = (config.editor.largeFileOptimizations === 'false' ? false : Boolean(config.editor.largeFileOptimizations)); + } + return { + isForSimpleWidget: isForSimpleWidget, tabSize: tabSize, insertSpaces: insertSpaces, detectIndentation: detectIndentation, defaultEOL: newDefaultEOL, - trimAutoWhitespace: trimAutoWhitespace + trimAutoWhitespace: trimAutoWhitespace, + largeFileOptimizations: largeFileOptimizations }; } - public getCreationOptions(language: string, resource: URI): ITextModelCreationOptions { + public getCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions { let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource]; if (!creationOptions) { - creationOptions = ModelServiceImpl._readModelOptions(this._configurationService.getValue({ overrideIdentifier: language, resource })); + creationOptions = ModelServiceImpl._readModelOptions(this._configurationService.getValue({ overrideIdentifier: language, resource }), isForSimpleWidget); this._modelCreationOptionsByLanguageAndResource[language + resource] = creationOptions; } return creationOptions; @@ -289,7 +322,7 @@ export class ModelServiceImpl implements IModelService { const language = modelData.model.getLanguageIdentifier().language; const uri = modelData.model.uri; const oldOptions = oldOptionsByLanguageAndResource[language + uri]; - const newOptions = this.getCreationOptions(language, uri); + const newOptions = this.getCreationOptions(language, uri, modelData.model.isForSimpleWidget); ModelServiceImpl._setModelOptionsForModel(modelData.model, newOptions, oldOptions); } } @@ -353,9 +386,9 @@ export class ModelServiceImpl implements IModelService { // --- begin IModelService - private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI): ModelData { + private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI, isForSimpleWidget: boolean): ModelData { // create & save the model - const options = this.getCreationOptions(languageIdentifier.language, resource); + const options = this.getCreationOptions(languageIdentifier.language, resource, isForSimpleWidget); const model: TextModel = new TextModel(value, options, languageIdentifier, resource); const modelId = MODEL_ID(model.uri); @@ -375,7 +408,7 @@ export class ModelServiceImpl implements IModelService { } public updateModel(model: ITextModel, value: string | ITextBufferFactory): void { - const options = this.getCreationOptions(model.getLanguageIdentifier().language, model.uri); + const options = this.getCreationOptions(model.getLanguageIdentifier().language, model.uri, model.isForSimpleWidget); const textBuffer = createTextBuffer(value, options.defaultEOL); // Return early if the text is already set in that form @@ -384,12 +417,14 @@ export class ModelServiceImpl implements IModelService { } // Otherwise find a diff between the values and update model + model.pushStackElement(); model.setEOL(textBuffer.getEOL() === '\r\n' ? EndOfLineSequence.CRLF : EndOfLineSequence.LF); model.pushEditOperations( - [new Selection(1, 1, 1, 1)], + [], ModelServiceImpl._computeEdits(model, textBuffer), - (inverseEditOperations: IIdentifiedSingleEditOperation[]) => [new Selection(1, 1, 1, 1)] + (inverseEditOperations: IIdentifiedSingleEditOperation[]) => [] ); + model.pushStackElement(); } private static _commonPrefix(a: ILineSequence, aLen: number, aDelta: number, b: ILineSequence, bLen: number, bDelta: number): number { @@ -439,17 +474,17 @@ export class ModelServiceImpl implements IModelService { newRange = new Range(1, 1, textBufferLineCount, 1 + textBuffer.getLineLength(textBufferLineCount)); } - return [EditOperation.replace(oldRange, textBuffer.getValueInRange(newRange, EndOfLinePreference.TextDefined))]; + return [EditOperation.replaceMove(oldRange, textBuffer.getValueInRange(newRange, EndOfLinePreference.TextDefined))]; } - public createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI): ITextModel { + public createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI, isForSimpleWidget: boolean = false): ITextModel { let modelData: ModelData; if (!modeOrPromise || TPromise.is(modeOrPromise)) { - modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource); + modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource, isForSimpleWidget); this.setMode(modelData.model, modeOrPromise); } else { - modelData = this._createModelData(value, modeOrPromise.getLanguageIdentifier(), resource); + modelData = this._createModelData(value, modeOrPromise.getLanguageIdentifier(), resource, isForSimpleWidget); } // handle markers (marker service => model) @@ -535,8 +570,8 @@ export class ModelServiceImpl implements IModelService { private _onDidChangeLanguage(model: ITextModel, e: IModelLanguageChangedEvent): void { const oldModeId = e.oldLanguage; const newModeId = model.getLanguageIdentifier().language; - const oldOptions = this.getCreationOptions(oldModeId, model.uri); - const newOptions = this.getCreationOptions(newModeId, model.uri); + const oldOptions = this.getCreationOptions(oldModeId, model.uri, model.isForSimpleWidget); + const newOptions = this.getCreationOptions(newModeId, model.uri, model.isForSimpleWidget); ModelServiceImpl._setModelOptionsForModel(model, newOptions, oldOptions); this._onModelModeChanged.fire({ model, oldModeId }); } diff --git a/src/vs/editor/common/services/resourceConfiguration.ts b/src/vs/editor/common/services/resourceConfiguration.ts index a03c63238d..47365ab840 100644 --- a/src/vs/editor/common/services/resourceConfiguration.ts +++ b/src/vs/editor/common/services/resourceConfiguration.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IPosition } from 'vs/editor/common/core/position'; diff --git a/src/vs/editor/common/services/resourceConfigurationImpl.ts b/src/vs/editor/common/services/resourceConfigurationImpl.ts index 5cb28572ac..964d8520db 100644 --- a/src/vs/editor/common/services/resourceConfigurationImpl.ts +++ b/src/vs/editor/common/services/resourceConfigurationImpl.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; @@ -11,6 +11,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res import { IPosition, Position } from 'vs/editor/common/core/position'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { basename } from 'vs/base/common/paths'; export class TextResourceConfigurationService extends Disposable implements ITextResourceConfigurationService { @@ -42,6 +43,6 @@ export class TextResourceConfigurationService extends Disposable implements ITex if (model) { return position ? this.modeService.getLanguageIdentifier(model.getLanguageIdAtPosition(position.lineNumber, position.column)).language : model.getLanguageIdentifier().language; } - return this.modeService.getModeIdByFilenameOrFirstLine(resource.fsPath); + return this.modeService.getModeIdByFilenameOrFirstLine(basename(resource.path)); } } \ No newline at end of file diff --git a/src/vs/editor/common/standalone/standaloneBase.ts b/src/vs/editor/common/standalone/standaloneBase.ts index 3cf595724f..1b0fa7360a 100644 --- a/src/vs/editor/common/standalone/standaloneBase.ts +++ b/src/vs/editor/common/standalone/standaloneBase.ts @@ -25,6 +25,13 @@ export enum Severity { Error = 3, } +export enum MarkerSeverity { + Hint = 1, + Info = 2, + Warning = 4, + Error = 8, +} + // -------------------------------------------- // This is repeated here so it can be exported // because TS inlines const enums @@ -238,6 +245,7 @@ export function createMonacoBaseAPI(): typeof monaco { Selection: Selection, SelectionDirection: SelectionDirection, Severity: Severity, + MarkerSeverity: MarkerSeverity, Promise: TPromise, Uri: <any>URI, Token: Token diff --git a/src/vs/editor/common/view/editorColorRegistry.ts b/src/vs/editor/common/view/editorColorRegistry.ts index ce4bf2149b..c30df3066b 100644 --- a/src/vs/editor/common/view/editorColorRegistry.ts +++ b/src/vs/editor/common/view/editorColorRegistry.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { registerColor, editorBackground, activeContrastBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { Color, RGBA } from 'vs/base/common/color'; @@ -20,8 +20,12 @@ export const editorCursorForeground = registerColor('editorCursor.foreground', { export const editorCursorBackground = registerColor('editorCursor.background', null, nls.localize('editorCursorBackground', 'The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.')); export const editorWhitespaces = registerColor('editorWhitespace.foreground', { dark: '#e3e4e229', light: '#33333333', hc: '#e3e4e229' }, nls.localize('editorWhitespaces', 'Color of whitespace characters in the editor.')); export const editorIndentGuides = registerColor('editorIndentGuide.background', { dark: editorWhitespaces, light: editorWhitespaces, hc: editorWhitespaces }, nls.localize('editorIndentGuides', 'Color of the editor indentation guides.')); +export const editorActiveIndentGuides = registerColor('editorIndentGuide.activeBackground', { dark: editorWhitespaces, light: editorWhitespaces, hc: editorWhitespaces }, nls.localize('editorActiveIndentGuide', 'Color of the active editor indentation guides.')); export const editorLineNumbers = registerColor('editorLineNumber.foreground', { dark: '#5A5A5A', light: '#2B91AF', hc: Color.white }, nls.localize('editorLineNumbers', 'Color of editor line numbers.')); -export const editorActiveLineNumber = registerColor('editorActiveLineNumber.foreground', { dark: null, light: null, hc: null }, nls.localize('editorActiveLineNumber', 'Color of editor active line number')); + +const deprecatedEditorActiveLineNumber = registerColor('editorActiveLineNumber.foreground', { dark: null, light: null, hc: null }, nls.localize('editorActiveLineNumber', 'Color of editor active line number'), false, nls.localize('deprecatedEditorActiveLineNumber', 'Id is deprecated. Use \'editorLineNumber.activeForeground\' instead.')); +export const editorActiveLineNumber = registerColor('editorLineNumber.activeForeground', { dark: deprecatedEditorActiveLineNumber, light: deprecatedEditorActiveLineNumber, hc: deprecatedEditorActiveLineNumber }, nls.localize('editorActiveLineNumber', 'Color of editor active line number')); + export const editorRuler = registerColor('editorRuler.foreground', { dark: '#5A5A5A', light: Color.lightgrey, hc: Color.white }, nls.localize('editorRuler', 'Color of the editor rulers.')); export const editorCodeLensForeground = registerColor('editorCodeLens.foreground', { dark: '#999999', light: '#999999', hc: '#999999' }, nls.localize('editorCodeLensForeground', 'Foreground color of editor code lenses')); @@ -42,36 +46,44 @@ export const editorWarningBorder = registerColor('editorWarning.border', { dark: export const editorInfoForeground = registerColor('editorInfo.foreground', { dark: '#008000', light: '#008000', hc: null }, nls.localize('infoForeground', 'Foreground color of info squigglies in the editor.')); export const editorInfoBorder = registerColor('editorInfo.border', { dark: null, light: null, hc: Color.fromHex('#71B771').transparent(0.8) }, nls.localize('infoBorder', 'Border color of info squigglies in the editor.')); +export const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('hintForeground', 'Foreground color of hint squigglies in the editor.')); +export const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint squigglies in the editor.')); + const rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6)); -export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights.')); +export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque to not hide underlying decorations.'), true); export const overviewRulerError = registerColor('editorOverviewRuler.errorForeground', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hc: new Color(new RGBA(255, 50, 50, 1)) }, nls.localize('overviewRuleError', 'Overview ruler marker color for errors.')); export const overviewRulerWarning = registerColor('editorOverviewRuler.warningForeground', { dark: new Color(new RGBA(18, 136, 18, 0.7)), light: new Color(new RGBA(18, 136, 18, 0.7)), hc: new Color(new RGBA(50, 255, 50, 1)) }, nls.localize('overviewRuleWarning', 'Overview ruler marker color for warnings.')); export const overviewRulerInfo = registerColor('editorOverviewRuler.infoForeground', { dark: new Color(new RGBA(18, 18, 136, 0.7)), light: new Color(new RGBA(18, 18, 136, 0.7)), hc: new Color(new RGBA(50, 50, 255, 1)) }, nls.localize('overviewRuleInfo', 'Overview ruler marker color for infos.')); // contains all color rules that used to defined in editor/browser/widget/editor.css registerThemingParticipant((theme, collector) => { - let background = theme.getColor(editorBackground); + const background = theme.getColor(editorBackground); if (background) { collector.addRule(`.monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { background-color: ${background}; }`); } - let foreground = theme.getColor(editorForeground); + + const foreground = theme.getColor(editorForeground); if (foreground) { collector.addRule(`.monaco-editor, .monaco-editor .inputarea.ime-input { color: ${foreground}; }`); } - let gutter = theme.getColor(editorGutter); + + const gutter = theme.getColor(editorGutter); if (gutter) { collector.addRule(`.monaco-editor .margin { background-color: ${gutter}; }`); } - let rangeHighlight = theme.getColor(editorRangeHighlight); + + const rangeHighlight = theme.getColor(editorRangeHighlight); if (rangeHighlight) { collector.addRule(`.monaco-editor .rangeHighlight { background-color: ${rangeHighlight}; }`); } - let rangeHighlightBorder = theme.getColor(editorRangeHighlightBorder); + + const rangeHighlightBorder = theme.getColor(editorRangeHighlightBorder); if (rangeHighlightBorder) { - collector.addRule(`.monaco-editor .rangeHighlight { border: 1px dotted ${rangeHighlightBorder}; }`); + collector.addRule(`.monaco-editor .rangeHighlight { border: 1px ${theme.type === 'hc' ? 'dotted' : 'solid'} ${rangeHighlightBorder}; }`); } - let invisibles = theme.getColor(editorWhitespaces); + + const invisibles = theme.getColor(editorWhitespaces); if (invisibles) { collector.addRule(`.vs-whitespace { color: ${invisibles} !important; }`); } -}); \ No newline at end of file +}); diff --git a/src/vs/editor/common/view/minimapCharRenderer.ts b/src/vs/editor/common/view/minimapCharRenderer.ts index 0b27e50bff..9c5eae32b0 100644 --- a/src/vs/editor/common/view/minimapCharRenderer.ts +++ b/src/vs/editor/common/view/minimapCharRenderer.ts @@ -5,7 +5,7 @@ 'use strict'; import { ColorId, TokenizationRegistry } from 'vs/editor/common/modes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { RGBA8 } from 'vs/editor/common/core/rgba'; export class MinimapTokensColorTracker { @@ -21,7 +21,7 @@ export class MinimapTokensColorTracker { private _backgroundIsLight: boolean; private _onDidChange = new Emitter<void>(); - public onDidChange: Event<void> = this._onDidChange.event; + public readonly onDidChange: Event<void> = this._onDidChange.event; private constructor() { this._updateColorMap(); diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index 9268189fe3..99ea1cd416 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -58,7 +58,7 @@ export class LineDecoration { continue; } - if (range.isEmpty() && d.type === InlineDecorationType.Regular) { + if (range.isEmpty() && (d.type === InlineDecorationType.Regular || d.type === InlineDecorationType.RegularAffectingLetterSpacing)) { // Ignore empty range decorations continue; } diff --git a/src/vs/editor/common/viewLayout/viewLayout.ts b/src/vs/editor/common/viewLayout/viewLayout.ts index cbd7a2f75f..e0a2389eb1 100644 --- a/src/vs/editor/common/viewLayout/viewLayout.ts +++ b/src/vs/editor/common/viewLayout/viewLayout.ts @@ -11,7 +11,7 @@ import { LinesLayout } from 'vs/editor/common/viewLayout/linesLayout'; import { IViewLayout, IViewWhitespaceViewportData, Viewport } from 'vs/editor/common/viewModel/viewModel'; import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions'; const SMOOTH_SCROLLING_TIME = 125; @@ -75,15 +75,12 @@ export class ViewLayout extends Disposable implements IViewLayout { } public onFlushed(lineCount: number): void { this._linesLayout.onFlushed(lineCount); - this._updateHeight(); } public onLinesDeleted(fromLineNumber: number, toLineNumber: number): void { this._linesLayout.onLinesDeleted(fromLineNumber, toLineNumber); - this._updateHeight(); } public onLinesInserted(fromLineNumber: number, toLineNumber: number): void { this._linesLayout.onLinesInserted(fromLineNumber, toLineNumber); - this._updateHeight(); } // ---- end view event handlers @@ -163,7 +160,7 @@ export class ViewLayout extends Disposable implements IViewLayout { // ---- view state - public saveState(): editorCommon.IViewState { + public saveState(): { scrollTop: number; scrollTopWithoutViewZones: number; scrollLeft: number; } { const currentScrollPosition = this.scrollable.getFutureScrollPosition(); let scrollTop = currentScrollPosition.scrollTop; let firstLineNumberInViewport = this._linesLayout.getLineNumberAtOrAfterVerticalOffset(scrollTop); @@ -175,17 +172,6 @@ export class ViewLayout extends Disposable implements IViewLayout { }; } - public reduceRestoreState(state: editorCommon.IViewState): { scrollLeft: number; scrollTop: number; } { - let restoreScrollTop = state.scrollTop; - if (typeof state.scrollTopWithoutViewZones === 'number' && !this._linesLayout.hasWhitespace()) { - restoreScrollTop = state.scrollTopWithoutViewZones; - } - return { - scrollLeft: state.scrollLeft, - scrollTop: restoreScrollTop - }; - } - // ---- IVerticalLayoutProvider public addWhitespace(afterLineNumber: number, ordinal: number, height: number): number { diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index 1cc218f966..f86265c2e8 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -36,7 +36,8 @@ export class RenderLineInput { public readonly useMonospaceOptimizations: boolean; public readonly lineContent: string; - public readonly mightContainRTL: boolean; + public readonly isBasicASCII: boolean; + public readonly containsRTL: boolean; public readonly fauxIndentLength: number; public readonly lineTokens: IViewLineTokens; public readonly lineDecorations: LineDecoration[]; @@ -50,7 +51,8 @@ export class RenderLineInput { constructor( useMonospaceOptimizations: boolean, lineContent: string, - mightContainRTL: boolean, + isBasicASCII: boolean, + containsRTL: boolean, fauxIndentLength: number, lineTokens: IViewLineTokens, lineDecorations: LineDecoration[], @@ -63,7 +65,8 @@ export class RenderLineInput { ) { this.useMonospaceOptimizations = useMonospaceOptimizations; this.lineContent = lineContent; - this.mightContainRTL = mightContainRTL; + this.isBasicASCII = isBasicASCII; + this.containsRTL = containsRTL; this.fauxIndentLength = fauxIndentLength; this.lineTokens = lineTokens; this.lineDecorations = lineDecorations; @@ -85,7 +88,8 @@ export class RenderLineInput { return ( this.useMonospaceOptimizations === other.useMonospaceOptimizations && this.lineContent === other.lineContent - && this.mightContainRTL === other.mightContainRTL + && this.isBasicASCII === other.isBasicASCII + && this.containsRTL === other.containsRTL && this.fauxIndentLength === other.fauxIndentLength && this.tabSize === other.tabSize && this.spaceWidth === other.spaceWidth @@ -217,14 +221,20 @@ export class CharacterMapping { } } +export const enum ForeignElementType { + None = 0, + Before = 1, + After = 2 +} + export class RenderLineOutput { _renderLineOutputBrand: void; readonly characterMapping: CharacterMapping; readonly containsRTL: boolean; - readonly containsForeignElements: boolean; + readonly containsForeignElements: ForeignElementType; - constructor(characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: boolean) { + constructor(characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) { this.characterMapping = characterMapping; this.containsRTL = containsRTL; this.containsForeignElements = containsForeignElements; @@ -234,7 +244,7 @@ export class RenderLineOutput { export function renderViewLine(input: RenderLineInput, sb: IStringBuilder): RenderLineOutput { if (input.lineContent.length === 0) { - let containsForeignElements = false; + let containsForeignElements = ForeignElementType.None; // This is basically for IE's hit test to work let content: string = '<span><span>\u00a0</span></span>'; @@ -244,13 +254,17 @@ export function renderViewLine(input: RenderLineInput, sb: IStringBuilder): Rend let classNames: string[] = []; for (let i = 0, len = input.lineDecorations.length; i < len; i++) { const lineDecoration = input.lineDecorations[i]; - if (lineDecoration.type !== InlineDecorationType.Regular) { + if (lineDecoration.type === InlineDecorationType.Before) { classNames.push(input.lineDecorations[i].className); - containsForeignElements = true; + containsForeignElements |= ForeignElementType.Before; + } + if (lineDecoration.type === InlineDecorationType.After) { + classNames.push(input.lineDecorations[i].className); + containsForeignElements |= ForeignElementType.After; } } - if (containsForeignElements) { + if (containsForeignElements !== ForeignElementType.None) { content = `<span><span class="${classNames.join(' ')}"></span></span>`; } } @@ -271,7 +285,7 @@ export class RenderLineOutput2 { public readonly characterMapping: CharacterMapping, public readonly html: string, public readonly containsRTL: boolean, - public readonly containsForeignElements: boolean + public readonly containsForeignElements: ForeignElementType ) { } } @@ -289,7 +303,7 @@ class ResolvedRenderLineInput { public readonly len: number, public readonly isOverflowing: boolean, public readonly parts: LinePart[], - public readonly containsForeignElements: boolean, + public readonly containsForeignElements: ForeignElementType, public readonly tabSize: number, public readonly containsRTL: boolean, public readonly spaceWidth: number, @@ -319,22 +333,22 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput if (input.renderWhitespace === RenderWhitespace.All || input.renderWhitespace === RenderWhitespace.Boundary) { tokens = _applyRenderWhitespace(lineContent, len, tokens, input.fauxIndentLength, input.tabSize, useMonospaceOptimizations, input.renderWhitespace === RenderWhitespace.Boundary); } - let containsForeignElements = false; + let containsForeignElements = ForeignElementType.None; if (input.lineDecorations.length > 0) { for (let i = 0, len = input.lineDecorations.length; i < len; i++) { const lineDecoration = input.lineDecorations[i]; - if (lineDecoration.type !== InlineDecorationType.Regular) { - containsForeignElements = true; - break; + if (lineDecoration.type === InlineDecorationType.RegularAffectingLetterSpacing) { + // Pretend there are foreign elements... although not 100% accurate. + containsForeignElements |= ForeignElementType.Before; + } else if (lineDecoration.type === InlineDecorationType.Before) { + containsForeignElements |= ForeignElementType.Before; + } else if (lineDecoration.type === InlineDecorationType.After) { + containsForeignElements |= ForeignElementType.After; } } tokens = _applyInlineDecorations(lineContent, len, tokens, input.lineDecorations); } - let containsRTL = false; - if (input.mightContainRTL) { - containsRTL = strings.containsRTL(lineContent); - } - if (!containsRTL && !input.fontLigatures) { + if (input.isBasicASCII && !input.fontLigatures) { tokens = splitLargeTokens(lineContent, tokens); } @@ -346,7 +360,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput tokens, containsForeignElements, input.tabSize, - containsRTL, + input.containsRTL, input.spaceWidth, input.renderWhitespace, input.renderControlCharacters @@ -406,11 +420,6 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[]): LinePart[] { const piecesCount = Math.ceil(diff / Constants.LongToken); for (let j = 1; j < piecesCount; j++) { let pieceEndIndex = lastTokenEndIndex + (j * Constants.LongToken); - let lastCharInPiece = lineContent.charCodeAt(pieceEndIndex - 1); - if (strings.isHighSurrogate(lastCharInPiece)) { - // Don't cut in the middle of a surrogate pair - pieceEndIndex--; - } result[resultLen++] = new LinePart(pieceEndIndex, tokenType); } result[resultLen++] = new LinePart(tokenEndIndex, tokenType); diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 97ca06ff8d..ef9de252d2 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -14,7 +14,7 @@ import { WrappingIndent } from 'vs/editor/common/config/editorOptions'; import { ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModel'; import { ThemeColor, ITheme } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; -import { IModelDecoration, ITextModel, IModelDeltaDecoration, EndOfLinePreference } from 'vs/editor/common/model'; +import { IModelDecoration, ITextModel, IModelDeltaDecoration, EndOfLinePreference, IActiveIndentGuideInfo } from 'vs/editor/common/model'; export class OutputPosition { _outputPositionBrand: void; @@ -41,6 +41,7 @@ export interface ILineMapperFactory { export interface ISimpleModel { getLineTokens(lineNumber: number): LineTokens; getLineContent(lineNumber: number): string; + getLineLength(lineNumber: number): number; getLineMinColumn(lineNumber: number): number; getLineMaxColumn(lineNumber: number): number; getValueInRange(range: IRange, eol?: EndOfLinePreference): string; @@ -52,6 +53,7 @@ export interface ISplitLine { getViewLineCount(): number; getViewLineContent(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): string; + getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number; getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number; getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number; getViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData; @@ -80,8 +82,10 @@ export interface IViewModelLinesCollection { getViewLineCount(): number; warmUpLookupCache(viewStartLineNumber: number, viewEndLineNumber: number): void; + getActiveIndentGuide(viewLineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo; getViewLinesIndentGuides(viewStartLineNumber: number, viewEndLineNumber: number): number[]; getViewLineContent(viewLineNumber: number): string; + getViewLineLength(viewLineNumber: number): number; getViewLineMinColumn(viewLineNumber: number): number; getViewLineMaxColumn(viewLineNumber: number): number; getViewLineData(viewLineNumber: number): ViewLineData; @@ -501,6 +505,26 @@ export class SplitLinesCollection implements IViewModelLinesCollection { this.prefixSumComputer.warmUpCache(viewStartLineNumber - 1, viewEndLineNumber - 1); } + public getActiveIndentGuide(viewLineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo { + this._ensureValidState(); + viewLineNumber = this._toValidViewLineNumber(viewLineNumber); + minLineNumber = this._toValidViewLineNumber(minLineNumber); + maxLineNumber = this._toValidViewLineNumber(maxLineNumber); + + const modelPosition = this.convertViewPositionToModelPosition(viewLineNumber, this.getViewLineMinColumn(viewLineNumber)); + const modelMinPosition = this.convertViewPositionToModelPosition(minLineNumber, this.getViewLineMinColumn(minLineNumber)); + const modelMaxPosition = this.convertViewPositionToModelPosition(maxLineNumber, this.getViewLineMinColumn(maxLineNumber)); + const result = this.model.getActiveIndentGuide(modelPosition.lineNumber, modelMinPosition.lineNumber, modelMaxPosition.lineNumber); + + const viewStartPosition = this.convertModelPositionToViewPosition(result.startLineNumber, 1); + const viewEndPosition = this.convertModelPositionToViewPosition(result.endLineNumber, 1); + return { + startLineNumber: viewStartPosition.lineNumber, + endLineNumber: viewEndPosition.lineNumber, + indent: result.indent + }; + } + public getViewLinesIndentGuides(viewStartLineNumber: number, viewEndLineNumber: number): number[] { this._ensureValidState(); viewStartLineNumber = this._toValidViewLineNumber(viewStartLineNumber); @@ -570,6 +594,16 @@ export class SplitLinesCollection implements IViewModelLinesCollection { return this.lines[lineIndex].getViewLineContent(this.model, lineIndex + 1, remainder); } + public getViewLineLength(viewLineNumber: number): number { + this._ensureValidState(); + viewLineNumber = this._toValidViewLineNumber(viewLineNumber); + let r = this.prefixSumComputer.getIndexOf(viewLineNumber - 1); + let lineIndex = r.index; + let remainder = r.remainder; + + return this.lines[lineIndex].getViewLineLength(this.model, lineIndex + 1, remainder); + } + public getViewLineMinColumn(viewLineNumber: number): number { this._ensureValidState(); viewLineNumber = this._toValidViewLineNumber(viewLineNumber); @@ -815,6 +849,10 @@ class VisibleIdentitySplitLine implements ISplitLine { return model.getLineContent(modelLineNumber); } + public getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number { + return model.getLineLength(modelLineNumber); + } + public getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number { return model.getLineMinColumn(modelLineNumber); } @@ -880,6 +918,10 @@ class InvisibleIdentitySplitLine implements ISplitLine { throw new Error('Not supported'); } + public getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number { + throw new Error('Not supported'); + } + public getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number { throw new Error('Not supported'); } @@ -973,6 +1015,21 @@ export class SplitLine implements ISplitLine { return r; } + public getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number { + if (!this._isVisible) { + throw new Error('Not supported'); + } + let startOffset = this.getInputStartOffsetOfOutputLineIndex(outputLineIndex); + let endOffset = this.getInputEndOffsetOfOutputLineIndex(model, modelLineNumber, outputLineIndex); + let r = endOffset - startOffset; + + if (outputLineIndex > 0) { + r = this.wrappedIndent.length + r; + } + + return r; + } + public getViewLineMinColumn(model: ITextModel, modelLineNumber: number, outputLineIndex: number): number { if (!this._isVisible) { throw new Error('Not supported'); @@ -1205,6 +1262,14 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { public warmUpLookupCache(viewStartLineNumber: number, viewEndLineNumber: number): void { } + public getActiveIndentGuide(viewLineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo { + return { + startLineNumber: viewLineNumber, + endLineNumber: viewLineNumber, + indent: 0 + }; + } + public getViewLinesIndentGuides(viewStartLineNumber: number, viewEndLineNumber: number): number[] { const viewLineCount = viewEndLineNumber - viewStartLineNumber + 1; let result = new Array<number>(viewLineCount); @@ -1218,6 +1283,10 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { return this.model.getLineContent(viewLineNumber); } + public getViewLineLength(viewLineNumber: number): number { + return this.model.getLineLength(viewLineNumber); + } + public getViewLineMinColumn(viewLineNumber: number): number { return this.model.getLineMinColumn(viewLineNumber); } diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index 9a8f163fa9..c6eae8ad64 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { INewScrollPosition, IViewState } from 'vs/editor/common/editorCommon'; -import { EndOfLinePreference, IModelDecorationOptions } from 'vs/editor/common/model'; +import { INewScrollPosition } from 'vs/editor/common/editorCommon'; +import { EndOfLinePreference, IModelDecorationOptions, IActiveIndentGuideInfo } from 'vs/editor/common/model'; import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; @@ -15,6 +15,7 @@ import { Scrollable, IScrollPosition } from 'vs/base/common/scrollable'; import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; import { ITheme } from 'vs/platform/theme/common/themeService'; +import * as strings from 'vs/base/common/strings'; export interface IViewWhitespaceViewportData { readonly id: number; @@ -63,9 +64,6 @@ export interface IViewLayout { getLinesViewportDataAtScrollTop(scrollTop: number): IPartialViewLinesViewportData; getWhitespaces(): IEditorWhitespace[]; - saveState(): IViewState; - reduceRestoreState(state: IViewState): { scrollLeft: number; scrollTop: number; }; - isAfterLines(verticalOffset: number): boolean; getLineNumberAtVerticalOffset(verticalOffset: number): number; getVerticalOffsetForLineNumber(lineNumber: number): number; @@ -122,9 +120,11 @@ export interface IViewModel { * Gives a hint that a lot of requests are about to come in for these line numbers. */ setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void; + setHasFocus(hasFocus: boolean): void; getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[]; getViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData; + getViewLineData(lineNumber: number): ViewLineData; getMinimapLinesRenderingData(startLineNumber: number, endLineNumber: number, needed: boolean[]): MinimapLinesRenderingData; getCompletelyVisibleViewRange(): Range; getCompletelyVisibleViewRangeAtScrollTop(scrollTop: number): Range; @@ -132,6 +132,8 @@ export interface IViewModel { getTabSize(): number; getLineCount(): number; getLineContent(lineNumber: number): string; + getLineLength(lineNumber: number): number; + getActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo; getLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[]; getLineMinColumn(lineNumber: number): number; getLineMaxColumn(lineNumber: number): number; @@ -146,7 +148,7 @@ export interface IViewModel { deduceModelPositionRelativeToViewPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position; getEOL(): string; - getPlainTextToCopy(ranges: Range[], emptySelectionClipboard: boolean): string | string[]; + getPlainTextToCopy(ranges: Range[], emptySelectionClipboard: boolean, forceCRLF: boolean): string | string[]; getHTMLToCopy(ranges: Range[], emptySelectionClipboard: boolean): string; } @@ -210,13 +212,13 @@ export class ViewLineRenderingData { */ public readonly content: string; /** - * If set to false, it is guaranteed that `content` contains only LTR chars. + * Describes if `content` contains RTL characters. */ - public readonly mightContainRTL: boolean; + public readonly containsRTL: boolean; /** - * If set to false, it is guaranteed that `content` contains only basic ASCII chars. + * Describes if `content` contains non basic ASCII chars. */ - public readonly mightContainNonBasicASCII: boolean; + public readonly isBasicASCII: boolean; /** * The tokens at this view line. */ @@ -243,18 +245,35 @@ export class ViewLineRenderingData { this.minColumn = minColumn; this.maxColumn = maxColumn; this.content = content; - this.mightContainRTL = mightContainRTL; - this.mightContainNonBasicASCII = mightContainNonBasicASCII; + + this.isBasicASCII = ViewLineRenderingData.isBasicASCII(content, mightContainNonBasicASCII); + this.containsRTL = ViewLineRenderingData.containsRTL(content, this.isBasicASCII, mightContainRTL); + this.tokens = tokens; this.inlineDecorations = inlineDecorations; this.tabSize = tabSize; } + + public static isBasicASCII(lineContent: string, mightContainNonBasicASCII: boolean): boolean { + if (mightContainNonBasicASCII) { + return strings.isBasicASCII(lineContent); + } + return true; + } + + public static containsRTL(lineContent: string, isBasicASCII: boolean, mightContainRTL: boolean): boolean { + if (!isBasicASCII && mightContainRTL) { + return strings.containsRTL(lineContent); + } + return false; + } } export const enum InlineDecorationType { Regular = 0, Before = 1, - After = 2 + After = 2, + RegularAffectingLetterSpacing = 3 } export class InlineDecoration { diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index 0cf899c972..95b957696e 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -124,7 +124,7 @@ export class ViewModelDecorations implements IDisposable { decorationsInViewport[decorationsInViewportLen++] = viewModelDecoration; if (decorationOptions.inlineClassName) { - let inlineDecoration = new InlineDecoration(viewRange, decorationOptions.inlineClassName, InlineDecorationType.Regular); + let inlineDecoration = new InlineDecoration(viewRange, decorationOptions.inlineClassName, decorationOptions.inlineClassNameAffectsLetterSpacing ? InlineDecorationType.RegularAffectingLetterSpacing : InlineDecorationType.Regular); let intersectedStartLineNumber = Math.max(startLineNumber, viewRange.startLineNumber); let intersectedEndLineNumber = Math.min(endLineNumber, viewRange.endLineNumber); for (let j = intersectedStartLineNumber; j <= intersectedEndLineNumber; j++) { diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index a20046c0dc..81226bdfba 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -11,7 +11,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { TokenizationRegistry, ColorId, LanguageId } from 'vs/editor/common/modes'; import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations'; -import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, IOverviewRulerDecorations } from 'vs/editor/common/viewModel/viewModel'; +import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, IOverviewRulerDecorations, ViewLineData } from 'vs/editor/common/viewModel/viewModel'; import { SplitLinesCollection, IViewModelLinesCollection, IdentityLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer'; @@ -23,7 +23,7 @@ import { Color } from 'vs/base/common/color'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ITheme } from 'vs/platform/theme/common/themeService'; import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModel'; -import { ITextModel, EndOfLinePreference } from 'vs/editor/common/model'; +import { ITextModel, EndOfLinePreference, TrackedRangeStickiness, IActiveIndentGuideInfo } from 'vs/editor/common/model'; const USE_IDENTITY_LINES_COLLECTION = true; @@ -32,20 +32,26 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel private readonly editorId: number; private readonly configuration: editorCommon.IConfiguration; private readonly model: ITextModel; + private hasFocus: boolean; + private viewportStartLine: number; + private viewportStartLineTrackedRange: string; + private viewportStartLineTop: number; private readonly lines: IViewModelLinesCollection; public readonly coordinatesConverter: ICoordinatesConverter; public readonly viewLayout: ViewLayout; private readonly decorations: ViewModelDecorations; - private _centeredViewLine: number; - constructor(editorId: number, configuration: editorCommon.IConfiguration, model: ITextModel, scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable) { super(); this.editorId = editorId; this.configuration = configuration; this.model = model; + this.hasFocus = false; + this.viewportStartLine = -1; + this.viewportStartLineTrackedRange = null; + this.viewportStartLineTop = 0; if (USE_IDENTITY_LINES_COLLECTION && this.model.isTooLargeForTokenization()) { @@ -83,8 +89,6 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel } })); - this._centeredViewLine = -1; - this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, this.lines, this.coordinatesConverter); this._registerModelEvents(); @@ -114,13 +118,22 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel super.dispose(); this.decorations.dispose(); this.lines.dispose(); + this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); + } + + public setHasFocus(hasFocus: boolean): void { + this.hasFocus = hasFocus; } private _onConfigurationChanged(eventsCollector: viewEvents.ViewEventsCollector, e: IConfigurationChangedEvent): void { // We might need to restore the current centered view range, so save it (if available) - const previousCenteredModelRange = this.getCenteredRangeInViewport(); - let revealPreviousCenteredModelRange = false; + let previousViewportStartModelPosition: Position = null; + if (this.viewportStartLine !== -1) { + let previousViewportStartViewPosition = new Position(this.viewportStartLine, this.getLineMinColumn(this.viewportStartLine)); + previousViewportStartModelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(previousViewportStartViewPosition); + } + let restorePreviousViewportStart = false; const conf = this.configuration.editor; @@ -133,7 +146,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel if (this.viewLayout.getCurrentScrollTop() !== 0) { // Never change the scroll position from 0 to something else... - revealPreviousCenteredModelRange = true; + restorePreviousViewportStart = true; } } @@ -146,23 +159,16 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel eventsCollector.emit(new viewEvents.ViewConfigurationChangedEvent(e)); this.viewLayout.onConfigurationChanged(e); - if (revealPreviousCenteredModelRange && previousCenteredModelRange) { - // modelLine -> viewLine - const newCenteredViewRange = this.coordinatesConverter.convertModelRangeToViewRange(previousCenteredModelRange); - - // Send a reveal event to restore the centered content - eventsCollector.emit(new viewEvents.ViewRevealRangeRequestEvent( - newCenteredViewRange, - viewEvents.VerticalRevealType.Center, - false, - editorCommon.ScrollType.Immediate - )); + if (restorePreviousViewportStart && previousViewportStartModelPosition) { + const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(previousViewportStartModelPosition); + const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); + this.viewLayout.deltaScrollNow(0, viewPositionTop - this.viewportStartLineTop); } } private _registerModelEvents(): void { - this._register(this.model.onDidChangeRawContent((e) => { + this._register(this.model.onDidChangeRawContentFast((e) => { try { const eventsCollector = this._beginEmit(); @@ -225,6 +231,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel } } this.lines.acceptVersionId(versionId); + this.viewLayout.onHeightMaybeChanged(); if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) { eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent()); @@ -236,8 +243,18 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel } // Update the configuration and reset the centered view line - this._centeredViewLine = -1; + this.viewportStartLine = -1; this.configuration.setMaxLineNumber(this.model.getLineCount()); + + // Recover viewport + if (!this.hasFocus && this.model.getAttachedEditorCount() >= 2 && this.viewportStartLineTrackedRange) { + const modelRange = this.model._getTrackedRange(this.viewportStartLineTrackedRange); + if (modelRange) { + const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(modelRange.getStartPosition()); + const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); + this.viewLayout.deltaScrollNow(0, viewPositionTop - this.viewportStartLineTop); + } + } })); this._register(this.model.onDidChangeTokens((e) => { @@ -311,16 +328,6 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel } } - public getCenteredRangeInViewport(): Range { - if (this._centeredViewLine === -1) { - // Never got rendered or not rendered since last content change event - return null; - } - let viewLineNumber = this._centeredViewLine; - let currentCenteredViewRange = new Range(viewLineNumber, this.getLineMinColumn(viewLineNumber), viewLineNumber, this.getLineMaxColumn(viewLineNumber)); - return this.coordinatesConverter.convertViewRangeToModelRange(currentCenteredViewRange); - } - public getVisibleRanges(): Range[] { const visibleViewRange = this.getCompletelyVisibleViewRange(); const visibleRange = this.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange); @@ -388,6 +395,43 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ); } + public saveState(): editorCommon.IViewState { + const compatViewState = this.viewLayout.saveState(); + + const scrollTop = compatViewState.scrollTop; + const firstViewLineNumber = this.viewLayout.getLineNumberAtVerticalOffset(scrollTop); + const firstPosition = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(firstViewLineNumber, this.getLineMinColumn(firstViewLineNumber))); + const firstPositionDeltaTop = this.viewLayout.getVerticalOffsetForLineNumber(firstViewLineNumber) - scrollTop; + + return { + scrollLeft: compatViewState.scrollLeft, + firstPosition: firstPosition, + firstPositionDeltaTop: firstPositionDeltaTop + }; + } + + public reduceRestoreState(state: editorCommon.IViewState): { scrollLeft: number; scrollTop: number; } { + if (typeof state.firstPosition === 'undefined') { + // This is a view state serialized by an older version + return this._reduceRestoreStateCompatibility(state); + } + + const modelPosition = this.model.validatePosition(state.firstPosition); + const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(modelPosition); + const scrollTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber) - state.firstPositionDeltaTop; + return { + scrollLeft: state.scrollLeft, + scrollTop: scrollTop + }; + } + + private _reduceRestoreStateCompatibility(state: editorCommon.IViewState): { scrollLeft: number; scrollTop: number; } { + return { + scrollLeft: state.scrollLeft, + scrollTop: state.scrollTopWithoutViewZones + }; + } + public getTabSize(): number { return this.model.getOptions().tabSize; } @@ -400,8 +444,16 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel * Gives a hint that a lot of requests are about to come in for these line numbers. */ public setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void { - this._centeredViewLine = centeredLineNumber; this.lines.warmUpLookupCache(startLineNumber, endLineNumber); + + this.viewportStartLine = startLineNumber; + let position = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(startLineNumber, this.getLineMinColumn(startLineNumber))); + this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, new Range(position.lineNumber, position.column, position.lineNumber, position.column), TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); + this.viewportStartLineTop = this.viewLayout.getVerticalOffsetForLineNumber(startLineNumber); + } + + public getActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo { + return this.lines.getActiveIndentGuide(lineNumber, minLineNumber, maxLineNumber); } public getLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[] { @@ -412,6 +464,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel return this.lines.getViewLineContent(lineNumber); } + public getLineLength(lineNumber: number): number { + return this.lines.getViewLineLength(lineNumber); + } + public getLineMinColumn(lineNumber: number): number { return this.lines.getViewLineMinColumn(lineNumber); } @@ -460,6 +516,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ); } + public getViewLineData(lineNumber: number): ViewLineData { + return this.lines.getViewLineData(lineNumber); + } + public getMinimapLinesRenderingData(startLineNumber: number, endLineNumber: number, needed: boolean[]): MinimapLinesRenderingData { let result = this.lines.getViewLinesData(startLineNumber, endLineNumber, needed); return new MinimapLinesRenderingData( @@ -514,8 +574,8 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel return this.model.getEOL(); } - public getPlainTextToCopy(ranges: Range[], emptySelectionClipboard: boolean): string | string[] { - const newLineCharacter = this.model.getEOL(); + public getPlainTextToCopy(ranges: Range[], emptySelectionClipboard: boolean, forceCRLF: boolean): string | string[] { + const newLineCharacter = forceCRLF ? '\r\n' : this.model.getEOL(); ranges = ranges.slice(0); ranges.sort(Range.compareRangesUsingStarts); @@ -543,7 +603,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel let result: string[] = []; for (let i = 0; i < nonEmptyRanges.length; i++) { - result.push(this.getValueInRange(nonEmptyRanges[i], EndOfLinePreference.TextDefined)); + result.push(this.getValueInRange(nonEmptyRanges[i], forceCRLF ? EndOfLinePreference.CRLF : EndOfLinePreference.TextDefined)); } return result.length === 1 ? result[0] : result; } diff --git a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts index 3f93e212cf..541eff64b3 100644 --- a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts +++ b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts @@ -33,7 +33,7 @@ class JumpToBracketAction extends EditorAction { alias: 'Go to Bracket', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKSLASH } }); @@ -176,41 +176,47 @@ export class BracketMatchingController extends Disposable implements editorCommo if (!model) { return; } - const selection = this._editor.getSelection(); - if (!selection.isEmpty()) { - return; - } - const position = selection.getStartPosition(); + let newSelections: Selection[] = []; - let brackets = model.matchBracket(position); + this._editor.getSelections().forEach(selection => { + const position = selection.getStartPosition(); - let openBracket: Position = null; - let closeBracket: Position = null; + let brackets = model.matchBracket(position); - if (!brackets) { - const nextBracket = model.findNextBracket(position); - if (nextBracket && nextBracket.range) { - brackets = model.matchBracket(nextBracket.range.getStartPosition()); + let openBracket: Position = null; + let closeBracket: Position = null; + + if (!brackets) { + const nextBracket = model.findNextBracket(position); + if (nextBracket && nextBracket.range) { + brackets = model.matchBracket(nextBracket.range.getStartPosition()); + } } - } - if (brackets) { - if (brackets[0].startLineNumber === brackets[1].startLineNumber) { - openBracket = brackets[1].startColumn < brackets[0].startColumn ? - brackets[1].getStartPosition() : brackets[0].getStartPosition(); - closeBracket = brackets[1].startColumn < brackets[0].startColumn ? - brackets[0].getEndPosition() : brackets[1].getEndPosition(); - } else { - openBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? - brackets[1].getStartPosition() : brackets[0].getStartPosition(); - closeBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? - brackets[0].getEndPosition() : brackets[1].getEndPosition(); + if (brackets) { + if (brackets[0].startLineNumber === brackets[1].startLineNumber) { + openBracket = brackets[1].startColumn < brackets[0].startColumn ? + brackets[1].getStartPosition() : brackets[0].getStartPosition(); + closeBracket = brackets[1].startColumn < brackets[0].startColumn ? + brackets[0].getEndPosition() : brackets[1].getEndPosition(); + } else { + openBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? + brackets[1].getStartPosition() : brackets[0].getStartPosition(); + closeBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? + brackets[0].getEndPosition() : brackets[1].getEndPosition(); + } } - } - if (openBracket && closeBracket) { - this._editor.setSelection(new Range(openBracket.lineNumber, openBracket.column, closeBracket.lineNumber, closeBracket.column)); + if (openBracket && closeBracket) { + newSelections.push(new Selection(openBracket.lineNumber, openBracket.column, closeBracket.lineNumber, closeBracket.column)); + } + }); + + + if (newSelections.length > 0) { + this._editor.setSelections(newSelections); + this._editor.revealRange(newSelections[0]); } } diff --git a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts index b8b6bb7807..9cb7cebc06 100644 --- a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts +++ b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts @@ -144,4 +144,57 @@ suite('bracket matching', () => { model.dispose(); mode.dispose(); }); + + test('issue #45369: Select to Bracket with multicursor', () => { + let mode = new BracketMode(); + let model = TextModel.createFromString('{ } { } { }', undefined, mode.getLanguageIdentifier()); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + let bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController); + + // cursors inside brackets become selections of the entire bracket contents + editor.setSelections([ + new Selection(1, 3, 1, 3), + new Selection(1, 10, 1, 10), + new Selection(1, 17, 1, 17) + ]); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(1, 8, 1, 13), + new Selection(1, 16, 1, 19) + ]); + + // cursors to the left of bracket pairs become selections of the entire pair + editor.setSelections([ + new Selection(1, 1, 1, 1), + new Selection(1, 6, 1, 6), + new Selection(1, 14, 1, 14) + ]); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(1, 8, 1, 13), + new Selection(1, 16, 1, 19) + ]); + + // cursors just right of a bracket pair become selections of the entire pair + editor.setSelections([ + new Selection(1, 5, 1, 5), + new Selection(1, 13, 1, 13), + new Selection(1, 19, 1, 19) + ]); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getSelections(), [ + new Selection(1, 1, 1, 5), + new Selection(1, 8, 1, 13), + new Selection(1, 16, 1, 19) + ]); + + bracketMatchingController.dispose(); + }); + + model.dispose(); + mode.dispose(); + }); }); diff --git a/src/vs/editor/contrib/caretOperations/transpose.ts b/src/vs/editor/contrib/caretOperations/transpose.ts index d3f8f32b31..a3335dfcb3 100644 --- a/src/vs/editor/contrib/caretOperations/transpose.ts +++ b/src/vs/editor/contrib/caretOperations/transpose.ts @@ -6,15 +6,56 @@ import * as nls from 'vs/nls'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { isLowSurrogate, isHighSurrogate } from 'vs/base/common/strings'; import { Range } from 'vs/editor/common/core/range'; +import { Position, IPosition } from 'vs/editor/common/core/position'; import { ICommand } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { registerEditorAction, EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ITextModel } from 'vs/editor/common/model'; class TransposeLettersAction extends EditorAction { + private positionLeftOf(start: IPosition, model: ITextModel): Position { + let column = start.column; + let lineNumber = start.lineNumber; + + if (column > model.getLineMinColumn(lineNumber)) { + if (isLowSurrogate(model.getLineContent(lineNumber).charCodeAt(column - 2))) { + // character before column is a low surrogate + column = column - 2; + } else { + column = column - 1; + } + } else if (lineNumber > 1) { + lineNumber = lineNumber - 1; + column = model.getLineMaxColumn(lineNumber); + } + + return new Position(lineNumber, column); + } + + private positionRightOf(start: IPosition, model: ITextModel): Position { + let column = start.column; + let lineNumber = start.lineNumber; + + if (column < model.getLineMaxColumn(lineNumber)) { + if (isHighSurrogate(model.getLineContent(lineNumber).charCodeAt(column - 1))) { + // character after column is a high surrogate + column = column + 2; + } else { + column = column + 1; + } + } else if (lineNumber < model.getLineCount()) { + lineNumber = lineNumber + 1; + column = 0; + } + + return new Position(lineNumber, column); + } + constructor() { super({ id: 'editor.action.transposeLetters', @@ -22,7 +63,7 @@ class TransposeLettersAction extends EditorAction { alias: 'Transpose Letters', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_T @@ -36,30 +77,35 @@ class TransposeLettersAction extends EditorAction { let commands: ICommand[] = []; let selections = editor.getSelections(); - for (let i = 0; i < selections.length; i++) { - let selection = selections[i]; + for (let selection of selections) { if (!selection.isEmpty()) { continue; } + let lineNumber = selection.startLineNumber; let column = selection.startColumn; - if (column === 1) { - // at the beginning of line - continue; - } - let maxColumn = model.getLineMaxColumn(lineNumber); - if (column === maxColumn) { - // at the end of line + + let lastColumn = model.getLineMaxColumn(lineNumber); + + if (lineNumber === 1 && (column === 1 || (column === 2 && lastColumn === 2))) { + // at beginning of file, nothing to do continue; } - let lineContent = model.getLineContent(lineNumber); - let charToTheLeft = lineContent.charAt(column - 2); - let charToTheRight = lineContent.charAt(column - 1); + // handle special case: when at end of line, transpose left two chars + // otherwise, transpose left and right chars + let endPosition = (column === lastColumn) ? + selection.getPosition() : + this.positionRightOf(selection.getPosition(), model); - let replaceRange = new Range(lineNumber, column - 1, lineNumber, column + 1); + let middlePosition = this.positionLeftOf(endPosition, model); + let beginPosition = this.positionLeftOf(middlePosition, model); - commands.push(new ReplaceCommand(replaceRange, charToTheRight + charToTheLeft)); + let leftChar = model.getValueInRange(Range.fromPositions(beginPosition, middlePosition)); + let rightChar = model.getValueInRange(Range.fromPositions(middlePosition, endPosition)); + + let replaceRange = Range.fromPositions(beginPosition, endPosition); + commands.push(new ReplaceCommand(replaceRange, rightChar + leftChar)); } if (commands.length > 0) { diff --git a/src/vs/editor/contrib/clipboard/clipboard.ts b/src/vs/editor/contrib/clipboard/clipboard.ts index 5c4b88a602..ab0c365f82 100644 --- a/src/vs/editor/contrib/clipboard/clipboard.ts +++ b/src/vs/editor/contrib/clipboard/clipboard.ts @@ -60,7 +60,7 @@ class ExecCommandCutAction extends ExecCommandAction { constructor() { let kbOpts: ICommandKeybindingsOptions = { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_X, win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_X, secondary: [KeyMod.Shift | KeyCode.Delete] } }; @@ -97,7 +97,7 @@ class ExecCommandCopyAction extends ExecCommandAction { constructor() { let kbOpts: ICommandKeybindingsOptions = { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_C, win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_C, secondary: [KeyMod.CtrlCmd | KeyCode.Insert] } }; @@ -135,7 +135,7 @@ class ExecCommandPasteAction extends ExecCommandAction { constructor() { let kbOpts: ICommandKeybindingsOptions = { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_V, win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] } }; @@ -168,7 +168,7 @@ class ExecCommandCopyWithSyntaxHighlightingAction extends ExecCommandAction { alias: 'Copy With Syntax Highlighting', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: null } }); diff --git a/src/vs/editor/contrib/quickFix/quickFix.ts b/src/vs/editor/contrib/codeAction/codeAction.ts similarity index 59% rename from src/vs/editor/contrib/quickFix/quickFix.ts rename to src/vs/editor/contrib/codeAction/codeAction.ts index d5ef00ef92..7089c3d3b4 100644 --- a/src/vs/editor/contrib/quickFix/quickFix.ts +++ b/src/vs/editor/contrib/codeAction/codeAction.ts @@ -2,46 +2,58 @@ * 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 URI from 'vs/base/common/uri'; -import { ITextModel } from 'vs/editor/common/model'; -import { Range } from 'vs/editor/common/core/range'; -import { CodeActionProviderRegistry, CodeAction } from 'vs/editor/common/modes'; +import { isFalsyOrEmpty, mergeSort, flatten } from 'vs/base/common/arrays'; import { asWinJsPromise } from 'vs/base/common/async'; +import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors'; +import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { onUnexpectedExternalError, illegalArgument } from 'vs/base/common/errors'; -import { IModelService } from 'vs/editor/common/services/modelService'; import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions'; -import { isFalsyOrEmpty, mergeSort } from 'vs/base/common/arrays'; -import { CodeActionKind } from './codeActionTrigger'; +import { Range } from 'vs/editor/common/core/range'; +import { ITextModel } from 'vs/editor/common/model'; +import { CodeAction, CodeActionProviderRegistry } from 'vs/editor/common/modes'; +import { IModelService } from 'vs/editor/common/services/modelService'; +import { CodeActionFilter, CodeActionKind } from './codeActionTrigger'; -export function getCodeActions(model: ITextModel, range: Range, scope?: CodeActionKind): TPromise<CodeAction[]> { +export function getCodeActions(model: ITextModel, range: Range, filter?: CodeActionFilter): TPromise<CodeAction[]> { + const codeActionContext = { only: filter && filter.kind ? filter.kind.value : undefined }; - const allResults: CodeAction[] = []; const promises = CodeActionProviderRegistry.all(model).map(support => { - return asWinJsPromise(token => support.provideCodeActions(model, range, { only: scope ? scope.value : undefined }, token)).then(result => { - if (Array.isArray(result)) { - for (const quickFix of result) { - if (quickFix) { - if (!scope || (quickFix.kind && scope.contains(quickFix.kind))) { - allResults.push(quickFix); - } - } - } + return asWinJsPromise(token => support.provideCodeActions(model, range, codeActionContext, token)).then(providedCodeActions => { + if (!Array.isArray(providedCodeActions)) { + return []; } - }, err => { + return providedCodeActions.filter(action => isValidAction(filter, action)); + }, (err): CodeAction[] => { onUnexpectedExternalError(err); + return []; }); }); - return TPromise.join(promises).then( - () => mergeSort(allResults, codeActionsComparator) - ); + return TPromise.join(promises) + .then(flatten) + .then(allCodeActions => mergeSort(allCodeActions, codeActionsComparator)); +} + +function isValidAction(filter: CodeActionFilter | undefined, action: CodeAction): boolean { + if (!action) { + return false; + } + + // Filter out actions by kind + if (filter && filter.kind && (!action.kind || !filter.kind.contains(action.kind))) { + return false; + } + + // Don't return source actions unless they are explicitly requested + if (action.kind && CodeActionKind.Source.contains(action.kind) && (!filter || !filter.includeSourceActions)) { + return false; + } + + return true; } function codeActionsComparator(a: CodeAction, b: CodeAction): number { - const aHasDiags = !isFalsyOrEmpty(a.diagnostics); const bHasDiags = !isFalsyOrEmpty(b.diagnostics); if (aHasDiags) { @@ -58,7 +70,6 @@ function codeActionsComparator(a: CodeAction, b: CodeAction): number { } registerLanguageCommand('_executeCodeActionProvider', function (accessor, args) { - const { resource, range } = args; if (!(resource instanceof URI) || !Range.isIRange(range)) { throw illegalArgument(); diff --git a/src/vs/editor/contrib/quickFix/quickFixCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts similarity index 51% rename from src/vs/editor/contrib/quickFix/quickFixCommands.ts rename to src/vs/editor/contrib/codeAction/codeActionCommands.ts index 2962fb3d1a..efe79675a8 100644 --- a/src/vs/editor/contrib/quickFix/quickFixCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -2,30 +2,37 @@ * 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 nls from 'vs/nls'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { optional } from 'vs/platform/instantiation/common/instantiation'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EditorAction, EditorCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { QuickFixContextMenu } from './quickFixWidget'; -import { LightBulbWidget } from './lightBulbWidget'; -import { QuickFixModel, QuickFixComputeEvent } from './quickFixModel'; -import { CodeActionKind, CodeActionAutoApply } from './codeActionTrigger'; -import { TPromise } from 'vs/base/common/winjs.base'; import { CodeAction } from 'vs/editor/common/modes'; -import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; -import { IFileService } from 'vs/platform/files/common/files'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { MessageController } from 'vs/editor/contrib/message/messageController'; +import * as nls from 'vs/nls'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IFileService } from 'vs/platform/files/common/files'; +import { optional } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { CodeActionModel, CodeActionsComputeEvent, SUPPORTED_CODE_ACTIONS } from './codeActionModel'; +import { CodeActionAutoApply, CodeActionFilter, CodeActionKind } from './codeActionTrigger'; +import { CodeActionContextMenu } from './codeActionWidget'; +import { LightBulbWidget } from './lightBulbWidget'; +import { escapeRegExpCharacters } from 'vs/base/common/strings'; + +function contextKeyForSupportedActions(kind: CodeActionKind) { + return ContextKeyExpr.regex( + SUPPORTED_CODE_ACTIONS.keys()[0], + new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b')); +} export class QuickFixController implements IEditorContribution { @@ -36,8 +43,8 @@ export class QuickFixController implements IEditorContribution { } private _editor: ICodeEditor; - private _model: QuickFixModel; - private _quickFixContextMenu: QuickFixContextMenu; + private _model: CodeActionModel; + private _codeActionContextMenu: CodeActionContextMenu; private _lightBulbWidget: LightBulbWidget; private _disposables: IDisposable[] = []; @@ -51,16 +58,16 @@ export class QuickFixController implements IEditorContribution { @optional(IFileService) private _fileService: IFileService ) { this._editor = editor; - this._model = new QuickFixModel(this._editor, markerService); - this._quickFixContextMenu = new QuickFixContextMenu(editor, contextMenuService, action => this._onApplyCodeAction(action)); + this._model = new CodeActionModel(this._editor, markerService, contextKeyService); + this._codeActionContextMenu = new CodeActionContextMenu(editor, contextMenuService, action => this._onApplyCodeAction(action)); this._lightBulbWidget = new LightBulbWidget(editor); this._updateLightBulbTitle(); this._disposables.push( - this._quickFixContextMenu.onDidExecuteCodeAction(_ => this._model.trigger({ type: 'auto' })), + this._codeActionContextMenu.onDidExecuteCodeAction(_ => this._model.trigger({ type: 'auto', filter: {} })), this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), - this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)), + this._model.onDidChangeFixes(e => this._onCodeActionsEvent(e)), this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) ); } @@ -70,28 +77,28 @@ export class QuickFixController implements IEditorContribution { dispose(this._disposables); } - private _onQuickFixEvent(e: QuickFixComputeEvent): void { - if (e && e.trigger.kind) { + private _onCodeActionsEvent(e: CodeActionsComputeEvent): void { + if (e && e.trigger.filter && e.trigger.filter.kind) { // Triggered for specific scope // Apply if we only have one action or requested autoApply, otherwise show menu - e.fixes.then(fixes => { + e.actions.then(fixes => { if (e.trigger.autoApply === CodeActionAutoApply.First || (e.trigger.autoApply === CodeActionAutoApply.IfSingle && fixes.length === 1)) { this._onApplyCodeAction(fixes[0]); } else { - this._quickFixContextMenu.show(e.fixes, e.position); + this._codeActionContextMenu.show(e.actions, e.position); } }); return; } if (e && e.trigger.type === 'manual') { - this._quickFixContextMenu.show(e.fixes, e.position); - } else if (e && e.fixes) { + this._codeActionContextMenu.show(e.actions, e.position); + } else if (e && e.actions) { // auto magically triggered // * update an existing list of code actions // * manage light bulb - if (this._quickFixContextMenu.isVisible) { - this._quickFixContextMenu.show(e.fixes, e.position); + if (this._codeActionContextMenu.isVisible) { + this._codeActionContextMenu.show(e.actions, e.position); } else { this._lightBulbWidget.model = e; } @@ -105,15 +112,11 @@ export class QuickFixController implements IEditorContribution { } private _handleLightBulbSelect(coords: { x: number, y: number }): void { - this._quickFixContextMenu.show(this._lightBulbWidget.model.fixes, coords); + this._codeActionContextMenu.show(this._lightBulbWidget.model.actions, coords); } - public triggerFromEditorSelection(): void { - this._model.trigger({ type: 'manual' }); - } - - public triggerCodeActionFromEditorSelection(kind?: CodeActionKind, autoApply?: CodeActionAutoApply): void { - this._model.trigger({ type: 'manual', kind, autoApply }); + public triggerFromEditorSelection(filter?: CodeActionFilter, autoApply?: CodeActionAutoApply): TPromise<CodeAction[] | undefined> { + return this._model.trigger({ type: 'manual', filter, autoApply }); } private _updateLightBulbTitle(): void { @@ -128,16 +131,44 @@ export class QuickFixController implements IEditorContribution { } private async _onApplyCodeAction(action: CodeAction): TPromise<void> { - if (action.edit) { - await BulkEdit.perform(action.edit.edits, this._textModelService, this._fileService, this._editor); - } - - if (action.command) { - await this._commandService.executeCommand(action.command.id, ...action.command.arguments); - } + await applyCodeAction(action, this._textModelService, this._fileService, this._commandService, this._editor); } } +export async function applyCodeAction( + action: CodeAction, + textModelService: ITextModelService, + fileService: IFileService, + commandService: ICommandService, + editor: ICodeEditor, +) { + if (action.edit) { + await BulkEdit.perform(action.edit.edits, textModelService, fileService, editor); + } + if (action.command) { + await commandService.executeCommand(action.command.id, ...action.command.arguments); + } +} + +function showCodeActionsForEditorSelection( + editor: ICodeEditor, + notAvailableMessage: string, + filter?: CodeActionFilter, + autoApply?: CodeActionAutoApply +) { + const controller = QuickFixController.get(editor); + if (!controller) { + return; + } + + const pos = editor.getPosition(); + controller.triggerFromEditorSelection(filter, autoApply).then(codeActions => { + if (!codeActions || !codeActions.length) { + MessageController.get(editor).showMessage(notAvailableMessage, pos); + } + }); +} + export class QuickFixAction extends EditorAction { static readonly Id = 'editor.action.quickFix'; @@ -145,21 +176,18 @@ export class QuickFixAction extends EditorAction { constructor() { super({ id: QuickFixAction.Id, - label: nls.localize('quickfix.trigger.label', "Quick Fix"), + label: nls.localize('quickfix.trigger.label', "Quick Fix..."), alias: 'Quick Fix', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.US_DOT } }); } public run(accessor: ServicesAccessor, editor: ICodeEditor): void { - let controller = QuickFixController.get(editor); - if (controller) { - controller.triggerFromEditorSelection(); - } + return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available")); } } @@ -212,11 +240,8 @@ export class CodeActionCommand extends EditorCommand { } public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, userArg: any) { - const controller = QuickFixController.get(editor); - if (controller) { - const args = CodeActionCommandArgs.fromUser(userArg); - controller.triggerCodeActionFromEditorSelection(args.kind, args.apply); - } + const args = CodeActionCommandArgs.fromUser(userArg); + return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), { kind: args.kind, includeSourceActions: true }, args.apply); } } @@ -228,26 +253,86 @@ export class RefactorAction extends EditorAction { constructor() { super({ id: RefactorAction.Id, - label: nls.localize('refactor.label', "Refactor"), + label: nls.localize('refactor.label', "Refactor..."), alias: 'Refactor', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider), kbOpts: { - kbExpr: EditorContextKeys.textFocus, - primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_R + kbExpr: EditorContextKeys.editorTextFocus, + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_R, + mac: { + primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_R + } + }, + menuOpts: { + group: '1_modification', + order: 2, + when: ContextKeyExpr.and( + EditorContextKeys.writable, + contextKeyForSupportedActions(CodeActionKind.Refactor)), } }); } public run(accessor: ServicesAccessor, editor: ICodeEditor): void { - const controller = QuickFixController.get(editor); - if (controller) { - controller.triggerCodeActionFromEditorSelection(CodeActionKind.Refactor, CodeActionAutoApply.Never); - } + return showCodeActionsForEditorSelection(editor, + nls.localize('editor.action.refactor.noneMessage', "No refactorings available"), + { kind: CodeActionKind.Refactor }, + CodeActionAutoApply.Never); } } -registerEditorContribution(QuickFixController); -registerEditorAction(QuickFixAction); -registerEditorAction(RefactorAction); -registerEditorCommand(new CodeActionCommand()); +export class SourceAction extends EditorAction { + + static readonly Id = 'editor.action.sourceAction'; + + constructor() { + super({ + id: SourceAction.Id, + label: nls.localize('source.label', "Source Action..."), + alias: 'Source Action', + precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider), + menuOpts: { + group: '1_modification', + order: 2.1, + when: ContextKeyExpr.and( + EditorContextKeys.writable, + contextKeyForSupportedActions(CodeActionKind.Source)), + } + }); + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + return showCodeActionsForEditorSelection(editor, + nls.localize('editor.action.source.noneMessage', "No source actions available"), + { kind: CodeActionKind.Source, includeSourceActions: true }, + CodeActionAutoApply.Never); + } +} + +export class OrganizeImportsAction extends EditorAction { + + static readonly Id = 'editor.action.organizeImports'; + + constructor() { + super({ + id: OrganizeImportsAction.Id, + label: nls.localize('organizeImports.label', "Organize Imports"), + alias: 'Organize Imports', + precondition: ContextKeyExpr.and( + EditorContextKeys.writable, + contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)), + kbOpts: { + kbExpr: EditorContextKeys.editorTextFocus, + primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_O + } + }); + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + return showCodeActionsForEditorSelection(editor, + nls.localize('editor.action.organize.noneMessage', "No organize imports action available"), + { kind: CodeActionKind.SourceOrganizeImports, includeSourceActions: true }, + CodeActionAutoApply.IfSingle); + } +} \ No newline at end of file diff --git a/src/vs/editor/contrib/codeAction/codeActionContributions.ts b/src/vs/editor/contrib/codeAction/codeActionContributions.ts new file mode 100644 index 0000000000..4f532eb77c --- /dev/null +++ b/src/vs/editor/contrib/codeAction/codeActionContributions.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerEditorAction, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { SourceAction, QuickFixController, QuickFixAction, CodeActionCommand, RefactorAction, OrganizeImportsAction } from 'vs/editor/contrib/codeAction/codeActionCommands'; + + +registerEditorContribution(QuickFixController); +registerEditorAction(QuickFixAction); +registerEditorAction(RefactorAction); +registerEditorAction(SourceAction); +registerEditorAction(OrganizeImportsAction); +registerEditorCommand(new CodeActionCommand()); diff --git a/src/vs/editor/contrib/quickFix/quickFixModel.ts b/src/vs/editor/contrib/codeAction/codeActionModel.ts similarity index 66% rename from src/vs/editor/contrib/quickFix/quickFixModel.ts rename to src/vs/editor/contrib/codeAction/codeActionModel.ts index db317a5fb4..e848b4ceda 100644 --- a/src/vs/editor/contrib/quickFix/quickFixModel.ts +++ b/src/vs/editor/contrib/codeAction/codeActionModel.ts @@ -2,29 +2,31 @@ * 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 Event, { Emitter, debounceEvent } from 'vs/base/common/event'; +import { Emitter, Event, debounceEvent } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { CodeActionProviderRegistry, CodeAction } from 'vs/editor/common/modes'; -import { getCodeActions } from './quickFix'; +import { CodeAction, CodeActionProviderRegistry } from 'vs/editor/common/modes'; +import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { getCodeActions } from './codeAction'; import { CodeActionTrigger } from './codeActionTrigger'; -import { Position } from 'vs/editor/common/core/position'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -export class QuickFixOracle { +export const SUPPORTED_CODE_ACTIONS = new RawContextKey<string>('supportedCodeAction', ''); + +export class CodeActionOracle { private _disposables: IDisposable[] = []; constructor( private _editor: ICodeEditor, private _markerService: IMarkerService, - private _signalChange: (e: QuickFixComputeEvent) => any, + private _signalChange: (e: CodeActionsComputeEvent) => any, delay: number = 250 ) { this._disposables.push( @@ -37,12 +39,12 @@ export class QuickFixOracle { this._disposables = dispose(this._disposables); } - trigger(trigger: CodeActionTrigger): void { + trigger(trigger: CodeActionTrigger) { let rangeOrSelection = this._getRangeOfMarker() || this._getRangeOfSelectionUnlessWhitespaceEnclosed(); if (!rangeOrSelection && trigger.type === 'manual') { rangeOrSelection = this._editor.getSelection(); } - this._createEventAndSignalChange(trigger, rangeOrSelection); + return this._createEventAndSignalChange(trigger, rangeOrSelection); } private _onMarkerChanges(resources: URI[]): void { @@ -99,51 +101,56 @@ export class QuickFixOracle { return selection; } - private _createEventAndSignalChange(trigger: CodeActionTrigger, rangeOrSelection: Range | Selection): void { + private _createEventAndSignalChange(trigger: CodeActionTrigger, rangeOrSelection: Range | Selection): TPromise<CodeAction[] | undefined> { if (!rangeOrSelection) { // cancel this._signalChange({ trigger, range: undefined, position: undefined, - fixes: undefined, + actions: undefined, }); + return TPromise.as(undefined); } else { // actual const model = this._editor.getModel(); const range = model.validateRange(rangeOrSelection); const position = rangeOrSelection instanceof Selection ? rangeOrSelection.getPosition() : rangeOrSelection.getStartPosition(); - const fixes = getCodeActions(model, range, trigger && trigger.kind); + const actions = getCodeActions(model, range, trigger && trigger.filter); this._signalChange({ trigger, range, position, - fixes + actions }); + return actions; } } } -export interface QuickFixComputeEvent { +export interface CodeActionsComputeEvent { trigger: CodeActionTrigger; range: Range; position: Position; - fixes: TPromise<CodeAction[]>; + actions: TPromise<CodeAction[]>; } -export class QuickFixModel { +export class CodeActionModel { private _editor: ICodeEditor; private _markerService: IMarkerService; - private _quickFixOracle: QuickFixOracle; - private _onDidChangeFixes = new Emitter<QuickFixComputeEvent>(); + private _codeActionOracle: CodeActionOracle; + private _onDidChangeFixes = new Emitter<CodeActionsComputeEvent>(); private _disposables: IDisposable[] = []; + private readonly _supportedCodeActions: IContextKey<string>; - constructor(editor: ICodeEditor, markerService: IMarkerService) { + constructor(editor: ICodeEditor, markerService: IMarkerService, contextKeyService: IContextKeyService) { this._editor = editor; this._markerService = markerService; + this._supportedCodeActions = SUPPORTED_CODE_ACTIONS.bindTo(contextKeyService); + this._disposables.push(this._editor.onDidChangeModel(() => this._update())); this._disposables.push(this._editor.onDidChangeModelLanguage(() => this._update())); this._disposables.push(CodeActionProviderRegistry.onDidChange(this._update, this)); @@ -153,18 +160,18 @@ export class QuickFixModel { dispose(): void { this._disposables = dispose(this._disposables); - dispose(this._quickFixOracle); + dispose(this._codeActionOracle); } - get onDidChangeFixes(): Event<QuickFixComputeEvent> { + get onDidChangeFixes(): Event<CodeActionsComputeEvent> { return this._onDidChangeFixes.event; } private _update(): void { - if (this._quickFixOracle) { - this._quickFixOracle.dispose(); - this._quickFixOracle = undefined; + if (this._codeActionOracle) { + this._codeActionOracle.dispose(); + this._codeActionOracle = undefined; this._onDidChangeFixes.fire(undefined); } @@ -172,14 +179,26 @@ export class QuickFixModel { && CodeActionProviderRegistry.has(this._editor.getModel()) && !this._editor.getConfiguration().readOnly) { - this._quickFixOracle = new QuickFixOracle(this._editor, this._markerService, p => this._onDidChangeFixes.fire(p)); - this._quickFixOracle.trigger({ type: 'auto' }); + const supportedActions: string[] = []; + for (const provider of CodeActionProviderRegistry.all(this._editor.getModel())) { + if (Array.isArray(provider.providedCodeActionKinds)) { + supportedActions.push(...provider.providedCodeActionKinds); + } + } + + this._supportedCodeActions.set(supportedActions.join(' ')); + + this._codeActionOracle = new CodeActionOracle(this._editor, this._markerService, p => this._onDidChangeFixes.fire(p)); + this._codeActionOracle.trigger({ type: 'auto' }); + } else { + this._supportedCodeActions.reset(); } } - trigger(trigger: CodeActionTrigger): void { - if (this._quickFixOracle) { - this._quickFixOracle.trigger(trigger); + trigger(trigger: CodeActionTrigger): TPromise<CodeAction[] | undefined> { + if (this._codeActionOracle) { + return this._codeActionOracle.trigger(trigger); } + return TPromise.as(undefined); } } diff --git a/src/vs/editor/contrib/quickFix/codeActionTrigger.ts b/src/vs/editor/contrib/codeAction/codeActionTrigger.ts similarity index 69% rename from src/vs/editor/contrib/quickFix/codeActionTrigger.ts rename to src/vs/editor/contrib/codeAction/codeActionTrigger.ts index 17096cb30a..b923b9fca5 100644 --- a/src/vs/editor/contrib/quickFix/codeActionTrigger.ts +++ b/src/vs/editor/contrib/codeAction/codeActionTrigger.ts @@ -10,6 +10,8 @@ export class CodeActionKind { public static readonly Empty = new CodeActionKind(''); public static readonly Refactor = new CodeActionKind('refactor'); + public static readonly Source = new CodeActionKind('source'); + public static readonly SourceOrganizeImports = new CodeActionKind('source.organizeImports'); constructor( public readonly value: string @@ -26,8 +28,13 @@ export enum CodeActionAutoApply { Never = 3 } +export interface CodeActionFilter { + readonly kind?: CodeActionKind; + readonly includeSourceActions?: boolean; +} + export interface CodeActionTrigger { - type: 'auto' | 'manual'; - kind?: CodeActionKind; - autoApply?: CodeActionAutoApply; + readonly type: 'auto' | 'manual'; + readonly filter?: CodeActionFilter; + readonly autoApply?: CodeActionAutoApply; } \ No newline at end of file diff --git a/src/vs/editor/contrib/quickFix/quickFixWidget.ts b/src/vs/editor/contrib/codeAction/codeActionWidget.ts similarity index 88% rename from src/vs/editor/contrib/quickFix/quickFixWidget.ts rename to src/vs/editor/contrib/codeAction/codeActionWidget.ts index 18826f6edb..3a337dd4c8 100644 --- a/src/vs/editor/contrib/quickFix/quickFixWidget.ts +++ b/src/vs/editor/contrib/codeAction/codeActionWidget.ts @@ -3,20 +3,19 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { TPromise } from 'vs/base/common/winjs.base'; -import { always } from 'vs/base/common/async'; import { getDomNodePagePosition } from 'vs/base/browser/dom'; -import { Position } from 'vs/editor/common/core/position'; +import { Action } from 'vs/base/common/actions'; +import { always } from 'vs/base/common/async'; +import { canceled } from 'vs/base/common/errors'; +import { Emitter, Event } from 'vs/base/common/event'; +import { TPromise } from 'vs/base/common/winjs.base'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { Position } from 'vs/editor/common/core/position'; +import { ScrollType } from 'vs/editor/common/editorCommon'; import { CodeAction } from 'vs/editor/common/modes'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { Action } from 'vs/base/common/actions'; -import Event, { Emitter } from 'vs/base/common/event'; -import { ScrollType } from 'vs/editor/common/editorCommon'; -export class QuickFixContextMenu { +export class CodeActionContextMenu { private _visible: boolean; private _onDidExecuteCodeAction = new Emitter<void>(); @@ -39,6 +38,12 @@ export class QuickFixContextMenu { () => this._onDidExecuteCodeAction.fire(undefined)); }); }); + }).then(actions => { + if (!this._editor.getDomNode()) { + // cancel when editor went off-dom + return TPromise.wrapError<any>(canceled()); + } + return actions; }); this._contextMenuService.showContextMenu({ diff --git a/src/vs/editor/contrib/quickFix/lightBulbWidget.css b/src/vs/editor/contrib/codeAction/lightBulbWidget.css similarity index 100% rename from src/vs/editor/contrib/quickFix/lightBulbWidget.css rename to src/vs/editor/contrib/codeAction/lightBulbWidget.css diff --git a/src/vs/editor/contrib/quickFix/lightBulbWidget.ts b/src/vs/editor/contrib/codeAction/lightBulbWidget.ts similarity index 89% rename from src/vs/editor/contrib/quickFix/lightBulbWidget.ts rename to src/vs/editor/contrib/codeAction/lightBulbWidget.ts index 3bb15bb3c2..a22ce9e3bc 100644 --- a/src/vs/editor/contrib/quickFix/lightBulbWidget.ts +++ b/src/vs/editor/contrib/codeAction/lightBulbWidget.ts @@ -2,17 +2,16 @@ * 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 'vs/css!./lightBulbWidget'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; -import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor'; import * as dom from 'vs/base/browser/dom'; -import { ICodeEditor, IContentWidget, IContentWidgetPosition, ContentWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; -import { QuickFixComputeEvent } from './quickFixModel'; +import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import 'vs/css!./lightBulbWidget'; +import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; import { TextModel } from 'vs/editor/common/model/textModel'; +import { CodeActionsComputeEvent } from './codeActionModel'; export class LightBulbWidget implements IDisposable, IContentWidget { @@ -26,7 +25,7 @@ export class LightBulbWidget implements IDisposable, IContentWidget { readonly onClick: Event<{ x: number, y: number }> = this._onClick.event; private _position: IContentWidgetPosition; - private _model: QuickFixComputeEvent; + private _model: CodeActionsComputeEvent; private _futureFixes = new CancellationTokenSource(); constructor(editor: ICodeEditor) { @@ -45,6 +44,8 @@ export class LightBulbWidget implements IDisposable, IContentWidget { } })); this._disposables.push(dom.addStandardDisposableListener(this._domNode, 'click', e => { + // Make sure that focus / cursor location is not lost when clicking widget icon + this._editor.focus(); // a bit of extra work to make sure the menu // doesn't cover the line-text const { top, height } = dom.getDomNodePagePosition(this._domNode); @@ -98,7 +99,7 @@ export class LightBulbWidget implements IDisposable, IContentWidget { return this._position; } - set model(value: QuickFixComputeEvent) { + set model(value: CodeActionsComputeEvent) { if (this._position && (!value.position || this._position.position.lineNumber !== value.position.lineNumber)) { // hide when getting a 'hide'-request or when currently @@ -113,7 +114,7 @@ export class LightBulbWidget implements IDisposable, IContentWidget { const { token } = this._futureFixes; this._model = value; - this._model.fixes.done(fixes => { + this._model.actions.done(fixes => { if (!token.isCancellationRequested && fixes && fixes.length > 0) { this._show(); } else { @@ -124,7 +125,7 @@ export class LightBulbWidget implements IDisposable, IContentWidget { }); } - get model(): QuickFixComputeEvent { + get model(): CodeActionsComputeEvent { return this._model; } diff --git a/src/vs/editor/contrib/quickFix/lightbulb-dark.svg b/src/vs/editor/contrib/codeAction/lightbulb-dark.svg similarity index 100% rename from src/vs/editor/contrib/quickFix/lightbulb-dark.svg rename to src/vs/editor/contrib/codeAction/lightbulb-dark.svg diff --git a/src/vs/editor/contrib/quickFix/lightbulb.svg b/src/vs/editor/contrib/codeAction/lightbulb.svg similarity index 100% rename from src/vs/editor/contrib/quickFix/lightbulb.svg rename to src/vs/editor/contrib/codeAction/lightbulb.svg diff --git a/src/vs/editor/contrib/quickFix/test/quickFix.test.ts b/src/vs/editor/contrib/codeAction/test/codeAction.test.ts similarity index 77% rename from src/vs/editor/contrib/quickFix/test/quickFix.test.ts rename to src/vs/editor/contrib/codeAction/test/codeAction.test.ts index a9f34c9f38..94decdad83 100644 --- a/src/vs/editor/contrib/quickFix/test/quickFix.test.ts +++ b/src/vs/editor/contrib/codeAction/test/codeAction.test.ts @@ -6,15 +6,15 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; import { TextModel } from 'vs/editor/common/model/textModel'; import { CodeActionProviderRegistry, LanguageIdentifier, CodeActionProvider, Command, WorkspaceEdit, ResourceTextEdit, CodeAction, CodeActionContext } from 'vs/editor/common/modes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; -import { getCodeActions } from 'vs/editor/contrib/quickFix/quickFix'; -import { CodeActionKind } from 'vs/editor/contrib/quickFix/codeActionTrigger'; +import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction'; +import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger'; +import { MarkerSeverity } from 'vs/platform/markers/common/markers'; -suite('QuickFix', () => { +suite('CodeAction', () => { let langId = new LanguageIdentifier('fooLang', 17); let uri = URI.parse('untitled:path'); @@ -29,7 +29,7 @@ suite('QuickFix', () => { startColumn: 1, endLineNumber: 2, endColumn: 1, - severity: Severity.Error, + severity: MarkerSeverity.Error, message: 'abc' }] }, @@ -40,7 +40,7 @@ suite('QuickFix', () => { startColumn: 1, endLineNumber: 2, endColumn: 1, - severity: Severity.Error, + severity: MarkerSeverity.Error, message: 'bcd' }] } @@ -136,20 +136,20 @@ suite('QuickFix', () => { disposables.push(CodeActionProviderRegistry.register('fooLang', provider)); { - const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a')); + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), { kind: new CodeActionKind('a') }); assert.equal(actions.length, 2); assert.strictEqual(actions[0].title, 'a'); assert.strictEqual(actions[1].title, 'a.b'); } { - const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a.b')); + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), { kind: new CodeActionKind('a.b') }); assert.equal(actions.length, 1); assert.strictEqual(actions[0].title, 'a.b'); } { - const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a.b.c')); + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), { kind: new CodeActionKind('a.b.c') }); assert.equal(actions.length, 0); } }); @@ -165,8 +165,33 @@ suite('QuickFix', () => { disposables.push(CodeActionProviderRegistry.register('fooLang', provider)); - const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a')); + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), { kind: new CodeActionKind('a') }); assert.equal(actions.length, 1); assert.strictEqual(actions[0].title, 'a'); }); + + test('getCodeActions should not return source code action by default', async function () { + const provider = new class implements CodeActionProvider { + provideCodeActions(): CodeAction[] { + return [ + { title: 'a', kind: CodeActionKind.Source.value }, + { title: 'b', kind: 'b' } + ]; + } + }; + + disposables.push(CodeActionProviderRegistry.register('fooLang', provider)); + + { + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), {}); + assert.equal(actions.length, 1); + assert.strictEqual(actions[0].title, 'b'); + } + + { + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), { kind: CodeActionKind.Source, includeSourceActions: true }); + assert.equal(actions.length, 1); + assert.strictEqual(actions[0].title, 'a'); + } + }); }); diff --git a/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts b/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts similarity index 91% rename from src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts rename to src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts index 72adacba29..03c596129a 100644 --- a/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts +++ b/src/vs/editor/contrib/codeAction/test/codeActionModel.test.ts @@ -10,13 +10,13 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { TextModel } from 'vs/editor/common/model/textModel'; import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { MarkerService } from 'vs/platform/markers/common/markerService'; -import { QuickFixOracle } from 'vs/editor/contrib/quickFix/quickFixModel'; +import { CodeActionOracle } from 'vs/editor/contrib/codeAction/codeActionModel'; import { CodeActionProviderRegistry, LanguageIdentifier } from 'vs/editor/common/modes'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -suite('QuickFix', () => { +suite('CodeAction', () => { const languageIdentifier = new LanguageIdentifier('foo-lang', 3); let uri = URI.parse('untitled:path'); @@ -46,11 +46,11 @@ suite('QuickFix', () => { test('Orcale -> marker added', done => { - const oracle = new QuickFixOracle(editor, markerService, e => { + const oracle = new CodeActionOracle(editor, markerService, e => { assert.equal(e.trigger.type, 'auto'); - assert.ok(e.fixes); + assert.ok(e.actions); - e.fixes.then(fixes => { + e.actions.then(fixes => { oracle.dispose(); assert.equal(fixes.length, 1); done(); @@ -82,10 +82,10 @@ suite('QuickFix', () => { return new Promise((resolve, reject) => { - const oracle = new QuickFixOracle(editor, markerService, e => { + const oracle = new CodeActionOracle(editor, markerService, e => { assert.equal(e.trigger.type, 'auto'); - assert.ok(e.fixes); - e.fixes.then(fixes => { + assert.ok(e.actions); + e.actions.then(fixes => { oracle.dispose(); assert.equal(fixes.length, 1); resolve(undefined); @@ -115,8 +115,8 @@ suite('QuickFix', () => { }]); let fixes: TPromise<any>[] = []; - let oracle = new QuickFixOracle(editor, markerService, e => { - fixes.push(e.fixes); + let oracle = new CodeActionOracle(editor, markerService, e => { + fixes.push(e.actions); }, 10); editor.setSelection({ startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 13 }); @@ -159,7 +159,7 @@ suite('QuickFix', () => { // case 1 - drag selection over multiple lines -> range of enclosed marker, position or marker await new Promise(resolve => { - let oracle = new QuickFixOracle(editor, markerService, e => { + let oracle = new CodeActionOracle(editor, markerService, e => { assert.equal(e.trigger.type, 'auto'); assert.deepEqual(e.range, { startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 4 }); assert.deepEqual(e.position, { lineNumber: 3, column: 1 }); diff --git a/src/vs/editor/contrib/codelens/codelens.ts b/src/vs/editor/contrib/codelens/codelens.ts index 6df61603b3..443569bcaa 100644 --- a/src/vs/editor/contrib/codelens/codelens.ts +++ b/src/vs/editor/contrib/codelens/codelens.ts @@ -14,6 +14,7 @@ import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions'; import { CodeLensProviderRegistry, CodeLensProvider, ICodeLensSymbol } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; import { asWinJsPromise } from 'vs/base/common/async'; +import { CancellationToken } from 'vs/base/common/cancellation'; export interface ICodeLensData { symbol: ICodeLensSymbol; @@ -58,7 +59,7 @@ export function getCodeLensData(model: ITextModel): TPromise<ICodeLensData[]> { registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) { - const { resource } = args; + let { resource, itemResolveCount } = args; if (!(resource instanceof URI)) { throw illegalArgument(); } @@ -68,5 +69,22 @@ registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) { throw illegalArgument(); } - return getCodeLensData(model).then(value => value.map(item => item.symbol)); + const result: ICodeLensSymbol[] = []; + return getCodeLensData(model).then(value => { + + let resolve: Thenable<any>[] = []; + + for (const item of value) { + if (typeof itemResolveCount === 'undefined' || Boolean(item.symbol.command)) { + result.push(item.symbol); + } else if (itemResolveCount-- > 0) { + resolve.push(Promise.resolve(item.provider.resolveCodeLens(model, item.symbol, CancellationToken.None)).then(symbol => result.push(symbol))); + } + } + + return Promise.all(resolve); + + }).then(() => { + return result; + }); }); diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index a56bfccfa4..52041b8566 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -19,6 +19,7 @@ import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOption import { CodeLens, CodeLensHelper } from 'vs/editor/contrib/codelens/codelensWidget'; import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { StableEditorScrollState } from 'vs/editor/browser/core/editorState'; export class CodeLensContribution implements editorCommon.IEditorContribution { @@ -170,11 +171,13 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { this._localToDispose.push({ dispose: () => { if (this._editor.getModel()) { + const scrollState = StableEditorScrollState.capture(this._editor); this._editor.changeDecorations((changeAccessor) => { this._editor.changeViewZones((accessor) => { this._disposeAllLenses(changeAccessor, accessor); }); }); + scrollState.restore(this._editor); } else { // No accessors available this._disposeAllLenses(null, null); @@ -218,8 +221,8 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { } } - const centeredRange = this._editor.getCenteredRangeInViewport(); - const shouldRestoreCenteredRange = centeredRange && (groups.length !== this._lenses.length && this._editor.getScrollTop() !== 0); + const scrollState = StableEditorScrollState.capture(this._editor); + this._editor.changeDecorations((changeAccessor) => { this._editor.changeViewZones((accessor) => { @@ -259,9 +262,8 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { helper.commit(changeAccessor); }); }); - if (shouldRestoreCenteredRange) { - this._editor.revealRangeInCenter(centeredRange, editorCommon.ScrollType.Immediate); - } + + scrollState.restore(this._editor); } private _onViewportChanged(): void { diff --git a/src/vs/editor/contrib/colorPicker/color.ts b/src/vs/editor/contrib/colorPicker/color.ts index f7f8ccc8b3..cfb7f59597 100644 --- a/src/vs/editor/contrib/colorPicker/color.ts +++ b/src/vs/editor/contrib/colorPicker/color.ts @@ -3,10 +3,17 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import URI from 'vs/base/common/uri'; + import { TPromise } from 'vs/base/common/winjs.base'; import { ColorProviderRegistry, DocumentColorProvider, IColorInformation, IColorPresentation } from 'vs/editor/common/modes'; import { asWinJsPromise } from 'vs/base/common/async'; import { ITextModel } from 'vs/editor/common/model'; +import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions'; +import { Range, IRange } from 'vs/editor/common/core/range'; +import { illegalArgument } from 'vs/base/common/errors'; +import { IModelService } from 'vs/editor/common/services/modelService'; + export interface IColorData { colorInfo: IColorInformation; @@ -30,3 +37,57 @@ export function getColors(model: ITextModel): TPromise<IColorData[]> { export function getColorPresentations(model: ITextModel, colorInfo: IColorInformation, provider: DocumentColorProvider): TPromise<IColorPresentation[]> { return asWinJsPromise(token => provider.provideColorPresentations(model, colorInfo, token)); } + +registerLanguageCommand('_executeDocumentColorProvider', function (accessor, args) { + + const { resource } = args; + if (!(resource instanceof URI)) { + throw illegalArgument(); + } + + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(); + } + + const rawCIs: { range: IRange, color: [number, number, number, number] }[] = []; + const providers = ColorProviderRegistry.ordered(model).reverse(); + const promises = providers.map(provider => asWinJsPromise(token => provider.provideDocumentColors(model, token)).then(result => { + if (Array.isArray(result)) { + for (let ci of result) { + rawCIs.push({ range: ci.range, color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] }); + } + } + })); + + return TPromise.join(promises).then(() => rawCIs); +}); + + +registerLanguageCommand('_executeColorPresentationProvider', function (accessor, args) { + + const { resource, color, range } = args; + if (!(resource instanceof URI) || !Array.isArray(color) || color.length !== 4 || !Range.isIRange(range)) { + throw illegalArgument(); + } + const [red, green, blue, alpha] = color; + + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(); + } + + const colorInfo = { + range, + color: { red, green, blue, alpha } + }; + + const presentations: IColorPresentation[] = []; + const providers = ColorProviderRegistry.ordered(model).reverse(); + const promises = providers.map(provider => asWinJsPromise(token => provider.provideColorPresentations(model, colorInfo, token)).then(result => { + if (Array.isArray(result)) { + presentations.push(...result); + } + })); + return TPromise.join(promises).then(() => presentations); +}); diff --git a/src/vs/editor/contrib/colorPicker/colorDetector.ts b/src/vs/editor/contrib/colorPicker/colorDetector.ts index 300e0e2b3b..9605fc55d1 100644 --- a/src/vs/editor/contrib/colorPicker/colorDetector.ts +++ b/src/vs/editor/contrib/colorPicker/colorDetector.ts @@ -16,6 +16,7 @@ import { ColorProviderRegistry } from 'vs/editor/common/modes'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { getColors, IColorData } from 'vs/editor/contrib/colorPicker/color'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; const MAX_DECORATORS = 500; @@ -153,7 +154,7 @@ export class ColorDetector implements IEditorContribution { endLineNumber: c.colorInfo.range.endLineNumber, endColumn: c.colorInfo.range.endColumn }, - options: {} + options: ModelDecorationOptions.EMPTY })); this._decorationsIds = this._editor.deltaDecorations(this._decorationsIds, decorations); diff --git a/src/vs/editor/contrib/colorPicker/colorPicker.css b/src/vs/editor/contrib/colorPicker/colorPicker.css index c81982d807..85653b5481 100644 --- a/src/vs/editor/contrib/colorPicker/colorPicker.css +++ b/src/vs/editor/contrib/colorPicker/colorPicker.css @@ -8,7 +8,7 @@ user-select: none; } -.monaco-shell .colorpicker-hover[tabindex="0"]:focus { +.monaco-editor .colorpicker-hover:focus { outline: none; } diff --git a/src/vs/editor/contrib/colorPicker/colorPickerModel.ts b/src/vs/editor/contrib/colorPicker/colorPickerModel.ts index 1224915e8b..f6598dfd5b 100644 --- a/src/vs/editor/contrib/colorPicker/colorPickerModel.ts +++ b/src/vs/editor/contrib/colorPicker/colorPickerModel.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Color } from 'vs/base/common/color'; import { IColorPresentation } from 'vs/editor/common/modes'; diff --git a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts index b271b1f745..626f65034e 100644 --- a/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts +++ b/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./colorPicker'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Widget } from 'vs/base/browser/ui/widget'; import * as dom from 'vs/base/browser/dom'; import { onDidChangeZoomLevel } from 'vs/base/browser/browser'; @@ -13,7 +13,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor'; import { Color, RGBA, HSVA } from 'vs/base/common/color'; import { editorHoverBackground } from 'vs/platform/theme/common/colorRegistry'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; const $ = dom.$; @@ -23,7 +23,7 @@ export class ColorPickerHeader extends Disposable { private pickedColorNode: HTMLElement; private backgroundColor: Color; - constructor(container: HTMLElement, private model: ColorPickerModel) { + constructor(container: HTMLElement, private model: ColorPickerModel, themeService: IThemeService) { super(); this.domNode = $('.colorpicker-header'); @@ -34,6 +34,7 @@ export class ColorPickerHeader extends Disposable { const colorBox = dom.append(this.domNode, $('.original-color')); colorBox.style.backgroundColor = Color.Format.CSS.format(this.model.originalColor); + this.backgroundColor = themeService.getTheme().getColor(editorHoverBackground) || Color.white; this._register(registerThemingParticipant((theme, collector) => { this.backgroundColor = theme.getColor(editorHoverBackground) || Color.white; })); @@ -332,7 +333,7 @@ export class ColorPickerWidget extends Widget { body: ColorPickerBody; - constructor(container: Node, private model: ColorPickerModel, private pixelRatio: number) { + constructor(container: Node, private model: ColorPickerModel, private pixelRatio: number, themeService: IThemeService) { super(); this._register(onDidChangeZoomLevel(() => this.layout())); @@ -340,7 +341,7 @@ export class ColorPickerWidget extends Widget { const element = $('.colorpicker-widget'); container.appendChild(element); - const header = new ColorPickerHeader(element, this.model); + const header = new ColorPickerHeader(element, this.model, themeService); this.body = new ColorPickerBody(element, this.model, this.pixelRatio); this._register(header); diff --git a/src/vs/editor/contrib/comment/blockCommentCommand.ts b/src/vs/editor/contrib/comment/blockCommentCommand.ts index b6564bb2d0..2c5719c834 100644 --- a/src/vs/editor/contrib/comment/blockCommentCommand.ts +++ b/src/vs/editor/contrib/comment/blockCommentCommand.ts @@ -32,10 +32,24 @@ export class BlockCommentCommand implements editorCommon.ICommand { if (offset + needleLength > haystackLength) { return false; } + for (let i = 0; i < needleLength; i++) { - if (haystack.charCodeAt(offset + i) !== needle.charCodeAt(i)) { - return false; + const codeA = haystack.charCodeAt(offset + i); + const codeB = needle.charCodeAt(i); + + if (codeA === codeB) { + continue; } + if (codeA >= CharCode.A && codeA <= CharCode.Z && codeA + 32 === codeB) { + // codeA is upper-case variant of codeB + continue; + } + if (codeB >= CharCode.A && codeB <= CharCode.Z && codeB + 32 === codeA) { + // codeB is upper-case variant of codeA + continue; + } + + return false; } return true; } diff --git a/src/vs/editor/contrib/comment/comment.ts b/src/vs/editor/contrib/comment/comment.ts index a5be622d6f..38b9fac02b 100644 --- a/src/vs/editor/contrib/comment/comment.ts +++ b/src/vs/editor/contrib/comment/comment.ts @@ -51,7 +51,7 @@ class ToggleCommentLineAction extends CommentLineAction { alias: 'Toggle Line Comment', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.US_SLASH } }); @@ -66,7 +66,7 @@ class AddLineCommentAction extends CommentLineAction { alias: 'Add Line Comment', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C) } }); @@ -81,7 +81,7 @@ class RemoveLineCommentAction extends CommentLineAction { alias: 'Remove Line Comment', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U) } }); @@ -97,7 +97,7 @@ class BlockCommentAction extends EditorAction { alias: 'Toggle Block Comment', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_A } } diff --git a/src/vs/editor/contrib/comment/lineCommentCommand.ts b/src/vs/editor/contrib/comment/lineCommentCommand.ts index fd13833ddf..def4439a07 100644 --- a/src/vs/editor/contrib/comment/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/lineCommentCommand.ts @@ -336,10 +336,10 @@ export class LineCommentCommand implements editorCommon.ICommand { } return new Selection( - result.startLineNumber, - result.startColumn + this._deltaColumn, - result.endLineNumber, - result.endColumn + this._deltaColumn + result.selectionStartLineNumber, + result.selectionStartColumn + this._deltaColumn, + result.positionLineNumber, + result.positionColumn + this._deltaColumn ); } diff --git a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts index 031b2cebf1..593e57ef5c 100644 --- a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts +++ b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts @@ -45,6 +45,25 @@ suite('Editor Contrib - Line Comment Command', () => { ); }); + test('case insensitive', function () { + function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void { + let mode = new CommentMode({ lineComment: 'rem' }); + testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle), expectedLines, expectedSelection); + mode.dispose(); + } + + testLineCommentCommand( + [ + 'REM some text' + ], + new Selection(1, 1, 1, 1), + [ + 'some text' + ], + new Selection(1, 1, 1, 1) + ); + }); + function createSimpleModel(lines: string[]): ISimpleModel { return { getLineContent: (lineNumber: number) => { @@ -237,7 +256,7 @@ suite('Editor Contrib - Line Comment Command', () => { '\t!@# some text', '\t!@# some more text' ], - new Selection(1, 1, 2, 2) + new Selection(2, 2, 1, 1) ); }); @@ -252,7 +271,7 @@ suite('Editor Contrib - Line Comment Command', () => { '\t!@# some text', ' !@# some more text' ], - new Selection(1, 1, 2, 2) + new Selection(2, 2, 1, 1) ); }); @@ -271,7 +290,7 @@ suite('Editor Contrib - Line Comment Command', () => { '', '\t!@# some more text' ], - new Selection(1, 1, 4, 2) + new Selection(4, 2, 1, 1) ); }); @@ -288,7 +307,7 @@ suite('Editor Contrib - Line Comment Command', () => { '\t ', '\t\tsome more text' ], - new Selection(1, 1, 3, 2) + new Selection(3, 2, 1, 1) ); }); @@ -305,7 +324,7 @@ suite('Editor Contrib - Line Comment Command', () => { '\t!@# ', '\t\tsome more text' ], - new Selection(1, 1, 3, 1) + new Selection(3, 1, 1, 1) ); }); @@ -350,7 +369,7 @@ suite('Editor Contrib - Line Comment Command', () => { 'first!@#', '\t!@# second line' ], - new Selection(2, 1, 2, 7) + new Selection(2, 7, 2, 1) ); }); @@ -371,7 +390,7 @@ suite('Editor Contrib - Line Comment Command', () => { 'fourth line', 'fifth' ], - new Selection(1, 5, 2, 1) + new Selection(2, 1, 1, 5) ); }); @@ -392,7 +411,7 @@ suite('Editor Contrib - Line Comment Command', () => { 'fourth line', 'fifth' ], - new Selection(1, 5, 2, 8) + new Selection(2, 8, 1, 5) ); }); @@ -413,7 +432,7 @@ suite('Editor Contrib - Line Comment Command', () => { '!@# fourth line', 'fifth' ], - new Selection(3, 5, 4, 8) + new Selection(4, 8, 3, 5) ); }); @@ -474,7 +493,7 @@ suite('Editor Contrib - Line Comment Command', () => { 'fourth line', 'fifth' ], - new Selection(1, 5, 2, 8) + new Selection(2, 8, 1, 5) ); testLineCommentCommand( @@ -493,7 +512,7 @@ suite('Editor Contrib - Line Comment Command', () => { 'fourth line', 'fifth' ], - new Selection(1, 1, 2, 3) + new Selection(2, 3, 1, 1) ); }); @@ -588,6 +607,21 @@ suite('Editor Contrib - Line Comment Command', () => { new Selection(1, 1, 8, 60) ); }); + + test('issue #47004: Toggle comments shouldn\'t move cursor', () => { + testAddLineCommentCommand( + [ + ' A line', + ' Another line' + ], + new Selection(2, 7, 1, 1), + [ + ' !@# A line', + ' !@# Another line' + ], + new Selection(2, 11, 1, 1) + ); + }); }); suite('Editor Contrib - Line Comment As Block Comment', () => { @@ -636,7 +670,7 @@ suite('Editor Contrib - Line Comment As Block Comment', () => { 'fourth line', 'fifth' ], - new Selection(1, 1, 1, 6) + new Selection(1, 6, 1, 1) ); }); @@ -678,7 +712,7 @@ suite('Editor Contrib - Line Comment As Block Comment', () => { 'fourth line', 'fifth' ], - new Selection(1, 5, 3, 2) + new Selection(3, 2, 1, 5) ); testLineCommentCommand( @@ -697,7 +731,7 @@ suite('Editor Contrib - Line Comment As Block Comment', () => { 'fourth line', 'fifth' ], - new Selection(1, 1, 3, 11) + new Selection(3, 11, 1, 1) ); }); }); @@ -823,7 +857,7 @@ suite('Editor Contrib - Line Comment As Block Comment 2', () => { 'fourth line', '\t\tfifth\t\t' ], - new Selection(5, 3, 5, 8) + new Selection(5, 8, 5, 3) ); testLineCommentCommand( @@ -842,7 +876,7 @@ suite('Editor Contrib - Line Comment As Block Comment 2', () => { 'fourth line', '\t\tfifth\t\t' ], - new Selection(5, 3, 5, 8) + new Selection(5, 8, 5, 3) ); testLineCommentCommand( diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts index dafaab93ff..4da1a4cc19 100644 --- a/src/vs/editor/contrib/contextmenu/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts @@ -224,7 +224,7 @@ class ShowContextMenu extends EditorAction { alias: 'Show Editor Context Menu', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.Shift | KeyCode.F10 } }); diff --git a/src/vs/editor/contrib/cursorUndo/cursorUndo.ts b/src/vs/editor/contrib/cursorUndo/cursorUndo.ts index 7730f68430..522e0d2f96 100644 --- a/src/vs/editor/contrib/cursorUndo/cursorUndo.ts +++ b/src/vs/editor/contrib/cursorUndo/cursorUndo.ts @@ -114,7 +114,7 @@ export class CursorUndo extends EditorCommand { id: 'cursorUndo', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.KEY_U } }); diff --git a/src/vs/editor/contrib/dnd/dnd.ts b/src/vs/editor/contrib/dnd/dnd.ts index 472ec97855..fe74a92e17 100644 --- a/src/vs/editor/contrib/dnd/dnd.ts +++ b/src/vs/editor/contrib/dnd/dnd.ts @@ -173,22 +173,17 @@ export class DragAndDropController implements editorCommon.IEditorContribution { }); public showAt(position: Position): void { - this._editor.changeDecorations(changeAccessor => { - let newDecorations: IModelDeltaDecoration[] = []; - newDecorations.push({ - range: new Range(position.lineNumber, position.column, position.lineNumber, position.column), - options: DragAndDropController._DECORATION_OPTIONS - }); + let newDecorations: IModelDeltaDecoration[] = [{ + range: new Range(position.lineNumber, position.column, position.lineNumber, position.column), + options: DragAndDropController._DECORATION_OPTIONS + }]; - this._dndDecorationIds = changeAccessor.deltaDecorations(this._dndDecorationIds, newDecorations); - }); + this._dndDecorationIds = this._editor.deltaDecorations(this._dndDecorationIds, newDecorations); this._editor.revealPosition(position, editorCommon.ScrollType.Immediate); } private _removeDecoration(): void { - this._editor.changeDecorations(changeAccessor => { - changeAccessor.deltaDecorations(this._dndDecorationIds, []); - }); + this._dndDecorationIds = this._editor.deltaDecorations(this._dndDecorationIds, []); } private _hitContent(target: IMouseTarget): boolean { diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index e5511e5bc3..da04493027 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -345,14 +345,20 @@ export class CommonFindController extends Disposable implements editorCommon.IEd } public getGlobalBufferTerm(): string { - if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard && this._clipboardService) { + if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard + && this._clipboardService + && !this._editor.getModel().isTooLargeForSyncing() + ) { return this._clipboardService.readFindText(); } return ''; } public setGlobalBufferTerm(text: string) { - if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard && this._clipboardService) { + if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard + && this._clipboardService + && !this._editor.getModel().isTooLargeForSyncing() + ) { this._clipboardService.writeFindText(text); } } @@ -440,8 +446,8 @@ export class StartFindWithSelectionAction extends EditorAction { constructor() { super({ id: FIND_IDS.StartFindWithSelection, - label: nls.localize('startFindAction', "Find"), - alias: 'Find', + label: nls.localize('startFindWithSelectionAction', "Find With Selection"), + alias: 'Find With Selection', precondition: null, kbOpts: { kbExpr: null, diff --git a/src/vs/editor/contrib/find/findDecorations.ts b/src/vs/editor/contrib/find/findDecorations.ts index bfafab81e5..bacd8e62bc 100644 --- a/src/vs/editor/contrib/find/findDecorations.ts +++ b/src/vs/editor/contrib/find/findDecorations.ts @@ -208,6 +208,50 @@ export class FindDecorations implements IDisposable { }); } + public matchBeforePosition(position: Position): Range { + if (this._decorations.length === 0) { + return null; + } + for (let i = this._decorations.length - 1; i >= 0; i--) { + let decorationId = this._decorations[i]; + let r = this._editor.getModel().getDecorationRange(decorationId); + if (!r || r.endLineNumber > position.lineNumber) { + continue; + } + if (r.endLineNumber < position.lineNumber) { + return r; + } + if (r.endColumn > position.column) { + continue; + } + return r; + } + + return this._editor.getModel().getDecorationRange(this._decorations[this._decorations.length - 1]); + } + + public matchAfterPosition(position: Position): Range { + if (this._decorations.length === 0) { + return null; + } + for (let i = 0, len = this._decorations.length; i < len; i++) { + let decorationId = this._decorations[i]; + let r = this._editor.getModel().getDecorationRange(decorationId); + if (!r || r.startLineNumber < position.lineNumber) { + continue; + } + if (r.startLineNumber > position.lineNumber) { + return r; + } + if (r.startColumn < position.column) { + continue; + } + return r; + } + + return this._editor.getModel().getDecorationRange(this._decorations[0]); + } + private _allDecorations(): string[] { let result: string[] = []; result = result.concat(this._decorations); @@ -223,6 +267,7 @@ export class FindDecorations implements IDisposable { private static readonly _CURRENT_FIND_MATCH_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + zIndex: 13, className: 'currentFindMatch', showIfCollapsed: true, overviewRuler: { diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index 32d3888df3..b2e5f0d5a9 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { RunOnceScheduler } from 'vs/base/common/async'; +import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ReplacePattern, parseReplaceString } from 'vs/editor/contrib/find/replacePattern'; import { ReplaceCommand, ReplaceCommandThatPreservesSelection } from 'vs/editor/common/commands/replaceCommand'; @@ -28,6 +28,7 @@ export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('findWidge export const CONTEXT_FIND_WIDGET_NOT_VISIBLE: ContextKeyExpr = CONTEXT_FIND_WIDGET_VISIBLE.toNegated(); // Keep ContextKey use of 'Focussed' to not break when clauses export const CONTEXT_FIND_INPUT_FOCUSED = new RawContextKey<boolean>('findInputFocussed', false); +export const CONTEXT_REPLACE_INPUT_FOCUSED = new RawContextKey<boolean>('replaceInputFocussed', false); export const ToggleCaseSensitiveKeybinding: IKeybindings = { primary: KeyMod.Alt | KeyCode.KEY_C, @@ -73,6 +74,7 @@ export const FIND_IDS = { }; export const MATCHES_LIMIT = 19999; +const RESEARCH_DELAY = 240; export class FindModelBoundToEditorModel { @@ -81,6 +83,7 @@ export class FindModelBoundToEditorModel { private _toDispose: IDisposable[]; private _decorations: FindDecorations; private _ignoreModelContentChanged: boolean; + private _startSearchingTimer: TimeoutTimer; private _updateDecorationsScheduler: RunOnceScheduler; private _isDisposed: boolean; @@ -90,6 +93,7 @@ export class FindModelBoundToEditorModel { this._state = state; this._toDispose = []; this._isDisposed = false; + this._startSearchingTimer = new TimeoutTimer(); this._decorations = new FindDecorations(editor); this._toDispose.push(this._decorations); @@ -127,6 +131,7 @@ export class FindModelBoundToEditorModel { public dispose(): void { this._isDisposed = true; + dispose(this._startSearchingTimer); this._toDispose = dispose(this._toDispose); } @@ -140,10 +145,24 @@ export class FindModelBoundToEditorModel { return; } if (e.searchString || e.isReplaceRevealed || e.isRegex || e.wholeWord || e.matchCase || e.searchScope) { - if (e.searchScope) { - this.research(e.moveCursor, this._state.searchScope); + let model = this._editor.getModel(); + + if (model.isTooLargeForSyncing()) { + this._startSearchingTimer.cancel(); + + this._startSearchingTimer.setIfNotSet(() => { + if (e.searchScope) { + this.research(e.moveCursor, this._state.searchScope); + } else { + this.research(e.moveCursor); + } + }, RESEARCH_DELAY); } else { - this.research(e.moveCursor); + if (e.searchScope) { + this.research(e.moveCursor, this._state.searchScope); + } else { + this.research(e.moveCursor); + } } } } @@ -215,7 +234,44 @@ export class FindModelBoundToEditorModel { this._editor.revealRangeInCenterIfOutsideViewport(match, editorCommon.ScrollType.Smooth); } + private _prevSearchPosition(before: Position) { + let isUsingLineStops = this._state.isRegex && ( + this._state.searchString.indexOf('^') >= 0 + || this._state.searchString.indexOf('$') >= 0 + ); + let { lineNumber, column } = before; + let model = this._editor.getModel(); + + if (isUsingLineStops || column === 1) { + if (lineNumber === 1) { + lineNumber = model.getLineCount(); + } else { + lineNumber--; + } + column = model.getLineMaxColumn(lineNumber); + } else { + column--; + } + + return new Position(lineNumber, column); + } + private _moveToPrevMatch(before: Position, isRecursed: boolean = false): void { + if (this._decorations.getCount() < MATCHES_LIMIT) { + let prevMatchRange = this._decorations.matchBeforePosition(before); + + if (prevMatchRange && prevMatchRange.isEmpty() && prevMatchRange.getStartPosition().equals(before)) { + before = this._prevSearchPosition(before); + prevMatchRange = this._decorations.matchBeforePosition(before); + } + + if (prevMatchRange) { + this._setCurrentFindMatch(prevMatchRange); + } + + return; + } + if (this._cannotFind()) { return; } @@ -242,24 +298,7 @@ export class FindModelBoundToEditorModel { if (prevMatch && prevMatch.range.isEmpty() && prevMatch.range.getStartPosition().equals(position)) { // Looks like we're stuck at this position, unacceptable! - - let isUsingLineStops = this._state.isRegex && ( - this._state.searchString.indexOf('^') >= 0 - || this._state.searchString.indexOf('$') >= 0 - ); - - if (isUsingLineStops || column === 1) { - if (lineNumber === 1) { - lineNumber = model.getLineCount(); - } else { - lineNumber--; - } - column = model.getLineMaxColumn(lineNumber); - } else { - column--; - } - - position = new Position(lineNumber, column); + position = this._prevSearchPosition(position); prevMatch = model.findPreviousMatch(this._state.searchString, position, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false); } @@ -279,7 +318,45 @@ export class FindModelBoundToEditorModel { this._moveToPrevMatch(this._editor.getSelection().getStartPosition()); } + private _nextSearchPosition(after: Position) { + let isUsingLineStops = this._state.isRegex && ( + this._state.searchString.indexOf('^') >= 0 + || this._state.searchString.indexOf('$') >= 0 + ); + + let { lineNumber, column } = after; + let model = this._editor.getModel(); + + if (isUsingLineStops || column === model.getLineMaxColumn(lineNumber)) { + if (lineNumber === model.getLineCount()) { + lineNumber = 1; + } else { + lineNumber++; + } + column = 1; + } else { + column++; + } + + return new Position(lineNumber, column); + } + private _moveToNextMatch(after: Position): void { + if (this._decorations.getCount() < MATCHES_LIMIT) { + let nextMatchRange = this._decorations.matchAfterPosition(after); + + if (nextMatchRange && nextMatchRange.isEmpty() && nextMatchRange.getStartPosition().equals(after)) { + // Looks like we're stuck at this position, unacceptable! + after = this._nextSearchPosition(after); + nextMatchRange = this._decorations.matchAfterPosition(after); + } + if (nextMatchRange) { + this._setCurrentFindMatch(nextMatchRange); + } + + return; + } + let nextMatch = this._getNextMatch(after, false, true); if (nextMatch) { this._setCurrentFindMatch(nextMatch.range); @@ -313,24 +390,7 @@ export class FindModelBoundToEditorModel { if (forceMove && nextMatch && nextMatch.range.isEmpty() && nextMatch.range.getStartPosition().equals(position)) { // Looks like we're stuck at this position, unacceptable! - - let isUsingLineStops = this._state.isRegex && ( - this._state.searchString.indexOf('^') >= 0 - || this._state.searchString.indexOf('$') >= 0 - ); - - if (isUsingLineStops || column === model.getLineMaxColumn(lineNumber)) { - if (lineNumber === model.getLineCount()) { - lineNumber = 1; - } else { - lineNumber++; - } - column = 1; - } else { - column++; - } - - position = new Position(lineNumber, column); + position = this._nextSearchPosition(position); nextMatch = model.findNextMatch(this._state.searchString, position, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getConfiguration().wordSeparators : null, captureMatches); } diff --git a/src/vs/editor/contrib/find/findState.ts b/src/vs/editor/contrib/find/findState.ts index 14f71fc58a..708dadfd7b 100644 --- a/src/vs/editor/contrib/find/findState.ts +++ b/src/vs/editor/contrib/find/findState.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; @@ -70,7 +70,7 @@ export class FindReplaceState implements IDisposable { private _matchesPosition: number; private _matchesCount: number; private _currentMatch: Range; - private _onFindReplaceStateChange: Emitter<FindReplaceStateChangedEvent>; + private readonly _onFindReplaceStateChange: Emitter<FindReplaceStateChangedEvent>; public get searchString(): string { return this._searchString; } public get replaceString(): string { return this._replaceString; } diff --git a/src/vs/editor/contrib/find/findWidget.css b/src/vs/editor/contrib/find/findWidget.css index 0e0271f89a..a964a9a420 100644 --- a/src/vs/editor/contrib/find/findWidget.css +++ b/src/vs/editor/contrib/find/findWidget.css @@ -71,14 +71,6 @@ font-size: 13px; } -.monaco-editor .find-widget.visible.noanimation { - -webkit-transition: none; - -o-transition: none; - -moz-transition: none; - -ms-transition: none; - transition: none; -} - .monaco-editor .find-widget > .find-part, .monaco-editor .find-widget > .replace-part { margin: 4px 0 0 17px; diff --git a/src/vs/editor/contrib/find/findWidget.ts b/src/vs/editor/contrib/find/findWidget.ts index 131c19743d..8d6656c06d 100644 --- a/src/vs/editor/contrib/find/findWidget.ts +++ b/src/vs/editor/contrib/find/findWidget.ts @@ -21,7 +21,7 @@ import { Widget } from 'vs/base/browser/ui/widget'; import { Sash, IHorizontalSashLayoutProvider, ISashEvent, Orientation } from 'vs/base/browser/ui/sash/sash'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; -import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; +import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED, CONTEXT_REPLACE_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState'; import { Range } from 'vs/editor/common/core/range'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -65,10 +65,10 @@ const FIND_REPLACE_AREA_HEIGHT = 64; // The height of Find Widget when Replace I export class FindWidgetViewZone implements IViewZone { - public afterLineNumber: number; + public readonly afterLineNumber: number; public heightInPx: number; - public suppressMouseDown: boolean; - public domNode: HTMLElement; + public readonly suppressMouseDown: boolean; + public readonly domNode: HTMLElement; constructor(afterLineNumber: number) { this.afterLineNumber = afterLineNumber; @@ -82,11 +82,11 @@ export class FindWidgetViewZone implements IViewZone { export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSashLayoutProvider { private static readonly ID = 'editor.contrib.findWidget'; - private _codeEditor: ICodeEditor; + private readonly _codeEditor: ICodeEditor; private _state: FindReplaceState; private _controller: IFindController; - private _contextViewProvider: IContextViewProvider; - private _keybindingService: IKeybindingService; + private readonly _contextViewProvider: IContextViewProvider; + private readonly _keybindingService: IKeybindingService; private _domNode: HTMLElement; private _findInput: FindInput; @@ -104,8 +104,10 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas private _isVisible: boolean; private _isReplaceVisible: boolean; - private _focusTracker: dom.IFocusTracker; + private _findFocusTracker: dom.IFocusTracker; private _findInputFocused: IContextKey<boolean>; + private _replaceFocusTracker: dom.IFocusTracker; + private _replaceInputFocused: IContextKey<boolean>; private _viewZone: FindWidgetViewZone; private _viewZoneId: number; @@ -163,28 +165,25 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas } })); this._findInputFocused = CONTEXT_FIND_INPUT_FOCUSED.bindTo(contextKeyService); - this._focusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement)); - this._register(this._focusTracker.onDidFocus(() => { + this._findFocusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement)); + this._register(this._findFocusTracker.onDidFocus(() => { this._findInputFocused.set(true); - - if (this._toggleSelectionFind.checked) { - let selection = this._codeEditor.getSelection(); - if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) { - selection = selection.setEndPosition(selection.endLineNumber - 1, 1); - } - let currentMatch = this._state.currentMatch; - if (selection.startLineNumber !== selection.endLineNumber) { - if (!Range.equalsRange(selection, currentMatch)) { - // Reseed find scope - this._state.change({ searchScope: selection }, true); - } - } - } + this._updateSearchScope(); })); - this._register(this._focusTracker.onDidBlur(() => { + this._register(this._findFocusTracker.onDidBlur(() => { this._findInputFocused.set(false); })); + this._replaceInputFocused = CONTEXT_REPLACE_INPUT_FOCUSED.bindTo(contextKeyService); + this._replaceFocusTracker = this._register(dom.trackFocus(this._replaceInputBox.inputElement)); + this._register(this._replaceFocusTracker.onDidFocus(() => { + this._replaceInputFocused.set(true); + this._updateSearchScope(); + })); + this._register(this._replaceFocusTracker.onDidBlur(() => { + this._replaceInputFocused.set(false); + })); + this._codeEditor.addOverlayWidget(this); this._viewZone = new FindWidgetViewZone(0); // Put it before the first line then users can scroll beyond the first line. @@ -382,12 +381,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas setTimeout(() => { dom.addClass(this._domNode, 'visible'); this._domNode.setAttribute('aria-hidden', 'false'); - if (!animate) { - dom.addClass(this._domNode, 'noanimation'); - setTimeout(() => { - dom.removeClass(this._domNode, 'noanimation'); - }, 200); - } }, 0); this._codeEditor.layoutOverlayWidget(this); @@ -572,6 +565,22 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas this._findInput.highlightFindOptions(); } + private _updateSearchScope(): void { + if (this._toggleSelectionFind.checked) { + let selection = this._codeEditor.getSelection(); + if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) { + selection = selection.setEndPosition(selection.endLineNumber - 1, 1); + } + let currentMatch = this._state.currentMatch; + if (selection.startLineNumber !== selection.endLineNumber) { + if (!Range.equalsRange(selection, currentMatch)) { + // Reseed find scope + this._state.change({ searchScope: selection }, true); + } + } + } + } + private _onFindInputMouseDown(e: IMouseEvent): void { // on linux, middle key does pasting. if (e.middleButton) { @@ -726,8 +735,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas className: 'previous', onTrigger: () => { this._codeEditor.getAction(FIND_IDS.PreviousMatchFindAction).run().done(null, onUnexpectedError); - }, - onKeyDown: (e) => { } + } })); // Next button @@ -736,8 +744,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas className: 'next', onTrigger: () => { this._codeEditor.getAction(FIND_IDS.NextMatchFindAction).run().done(null, onUnexpectedError); - }, - onKeyDown: (e) => { } + } })); let findPart = document.createElement('div'); @@ -828,8 +835,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas className: 'replace-all', onTrigger: () => { this._controller.replaceAll(); - }, - onKeyDown: (e) => { } + } })); let replacePart = document.createElement('div'); @@ -858,8 +864,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas this._replaceInputBox.width = this._findInput.inputBox.width; } this._showViewZone(); - }, - onKeyDown: (e) => { } + } })); this._toggleReplaceBtn.toggleClass('expand', this._isReplaceVisible); this._toggleReplaceBtn.toggleClass('collapse', !this._isReplaceVisible); @@ -911,19 +916,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas } interface ISimpleCheckboxOpts { - parent: HTMLElement; - title: string; - onChange: () => void; + readonly parent: HTMLElement; + readonly title: string; + readonly onChange: () => void; } class SimpleCheckbox extends Widget { private static _COUNTER = 0; - private _opts: ISimpleCheckboxOpts; - private _domNode: HTMLElement; - private _checkbox: HTMLInputElement; - private _label: HTMLLabelElement; + private readonly _opts: ISimpleCheckboxOpts; + private readonly _domNode: HTMLElement; + private readonly _checkbox: HTMLInputElement; + private readonly _label: HTMLLabelElement; constructor(opts: ISimpleCheckboxOpts) { super(); @@ -992,16 +997,16 @@ class SimpleCheckbox extends Widget { } export interface ISimpleButtonOpts { - label: string; - className: string; - onTrigger: () => void; - onKeyDown: (e: IKeyboardEvent) => void; + readonly label: string; + readonly className: string; + readonly onTrigger: () => void; + readonly onKeyDown?: (e: IKeyboardEvent) => void; } export class SimpleButton extends Widget { - private _opts: ISimpleButtonOpts; - private _domNode: HTMLElement; + private readonly _opts: ISimpleButtonOpts; + private readonly _domNode: HTMLElement; constructor(opts: ISimpleButtonOpts) { super(); @@ -1018,13 +1023,16 @@ export class SimpleButton extends Widget { this._opts.onTrigger(); e.preventDefault(); }); + this.onkeydown(this._domNode, (e) => { if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) { this._opts.onTrigger(); e.preventDefault(); return; } - this._opts.onKeyDown(e); + if (this._opts.onKeyDown) { + this._opts.onKeyDown(e); + } }); } @@ -1058,48 +1066,50 @@ export class SimpleButton extends Widget { // theming registerThemingParticipant((theme, collector) => { - function addBackgroundColorRule(selector: string, color: Color): void { + const addBackgroundColorRule = (selector: string, color: Color): void => { if (color) { collector.addRule(`.monaco-editor ${selector} { background-color: ${color}; }`); } - } + }; addBackgroundColorRule('.findMatch', theme.getColor(editorFindMatchHighlight)); addBackgroundColorRule('.currentFindMatch', theme.getColor(editorFindMatch)); addBackgroundColorRule('.findScope', theme.getColor(editorFindRangeHighlight)); - let widgetBackground = theme.getColor(editorWidgetBackground); + const widgetBackground = theme.getColor(editorWidgetBackground); addBackgroundColorRule('.find-widget', widgetBackground); - let widgetShadowColor = theme.getColor(widgetShadow); + const widgetShadowColor = theme.getColor(widgetShadow); if (widgetShadowColor) { collector.addRule(`.monaco-editor .find-widget { box-shadow: 0 2px 8px ${widgetShadowColor}; }`); } - let findMatchHighlightBorder = theme.getColor(editorFindMatchHighlightBorder); + const findMatchHighlightBorder = theme.getColor(editorFindMatchHighlightBorder); if (findMatchHighlightBorder) { - collector.addRule(`.monaco-editor .findMatch { border: 1px dotted ${findMatchHighlightBorder}; -moz-box-sizing: border-box; box-sizing: border-box; }`); - } - let findMatchBorder = theme.getColor(editorFindMatchBorder); - if (findMatchBorder) { - collector.addRule(`.monaco-editor .currentFindMatch { border: 2px solid ${findMatchBorder}; padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; }`); - } - let findRangeHighlightBorder = theme.getColor(editorFindRangeHighlightBorder); - if (findRangeHighlightBorder) { - collector.addRule(`.monaco-editor .findScope { border: 1px dashed ${findRangeHighlightBorder}; }`); + collector.addRule(`.monaco-editor .findMatch { border: 1px ${theme.type === 'hc' ? 'dotted' : 'solid'} ${findMatchHighlightBorder}; box-sizing: border-box; }`); } - let hcBorder = theme.getColor(contrastBorder); + const findMatchBorder = theme.getColor(editorFindMatchBorder); + if (findMatchBorder) { + collector.addRule(`.monaco-editor .currentFindMatch { border: 2px solid ${findMatchBorder}; padding: 1px; box-sizing: border-box; }`); + } + + const findRangeHighlightBorder = theme.getColor(editorFindRangeHighlightBorder); + if (findRangeHighlightBorder) { + collector.addRule(`.monaco-editor .findScope { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${findRangeHighlightBorder}; }`); + } + + const hcBorder = theme.getColor(contrastBorder); if (hcBorder) { collector.addRule(`.monaco-editor .find-widget { border: 2px solid ${hcBorder}; }`); } - let error = theme.getColor(errorForeground); + const error = theme.getColor(errorForeground); if (error) { collector.addRule(`.monaco-editor .find-widget.no-results .matchesCount { color: ${error}; }`); } - let border = theme.getColor(editorWidgetBorder); + const border = theme.getColor(editorWidgetBorder); if (border) { collector.addRule(`.monaco-editor .find-widget .monaco-sash { background-color: ${border}; width: 3px !important; margin-left: -4px;}`); } diff --git a/src/vs/editor/contrib/find/simpleFindWidget.ts b/src/vs/editor/contrib/find/simpleFindWidget.ts index 252b4b3c68..8de7f2eb03 100644 --- a/src/vs/editor/contrib/find/simpleFindWidget.ts +++ b/src/vs/editor/contrib/find/simpleFindWidget.ts @@ -23,20 +23,20 @@ const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next mat const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); export abstract class SimpleFindWidget extends Widget { - protected _findInput: FindInput; - protected _domNode: HTMLElement; - protected _innerDomNode: HTMLElement; - protected _isVisible: boolean; - protected _focusTracker: dom.IFocusTracker; - protected _findInputFocusTracker: dom.IFocusTracker; - protected _findHistory: HistoryNavigator<string>; - protected _updateHistoryDelayer: Delayer<void>; + private _findInput: FindInput; + private _domNode: HTMLElement; + private _innerDomNode: HTMLElement; + private _isVisible: boolean; + private _focusTracker: dom.IFocusTracker; + private _findInputFocusTracker: dom.IFocusTracker; + private _findHistory: HistoryNavigator<string>; + private _updateHistoryDelayer: Delayer<void>; constructor( - @IContextViewService private readonly _contextViewService: IContextViewService, - private animate: boolean = true + @IContextViewService private readonly _contextViewService: IContextViewService ) { super(); + this._findInput = this._register(new FindInput(null, this._contextViewService, { label: NLS_FIND_INPUT_LABEL, placeholder: NLS_FIND_INPUT_PLACEHOLDER, @@ -65,31 +65,28 @@ export abstract class SimpleFindWidget extends Widget { } })); - let prevBtn = new SimpleButton({ + const prevBtn = new SimpleButton({ label: NLS_PREVIOUS_MATCH_BTN_LABEL, className: 'previous', onTrigger: () => { this.find(true); - }, - onKeyDown: (e) => { } + } }); - let nextBtn = new SimpleButton({ + const nextBtn = new SimpleButton({ label: NLS_NEXT_MATCH_BTN_LABEL, className: 'next', onTrigger: () => { this.find(false); - }, - onKeyDown: (e) => { } + } }); - let closeBtn = new SimpleButton({ + const closeBtn = new SimpleButton({ label: NLS_CLOSE_BTN_LABEL, className: 'close-fw', onTrigger: () => { this.hide(); - }, - onKeyDown: (e) => { } + } }); this._innerDomNode = document.createElement('div'); @@ -136,8 +133,8 @@ export abstract class SimpleFindWidget extends Widget { return this._findInput.getValue(); } - public updateTheme(theme?: ITheme): void { - let inputStyles = { + public updateTheme(theme: ITheme): void { + const inputStyles = { inputActiveOptionBorder: theme.getColor(inputActiveOptionBorder), inputBackground: theme.getColor(inputBackground), inputForeground: theme.getColor(inputForeground), @@ -152,6 +149,14 @@ export abstract class SimpleFindWidget extends Widget { this._findInput.style(inputStyles); } + dipose() { + super.dispose(); + + if (this._domNode && this._domNode.parentElement) { + this._domNode.parentElement.removeChild(this._domNode); + } + } + public getDomNode(): HTMLElement { return this._domNode; } @@ -171,11 +176,7 @@ export abstract class SimpleFindWidget extends Widget { setTimeout(() => { dom.addClass(this._innerDomNode, 'visible'); this._innerDomNode.setAttribute('aria-hidden', 'false'); - if (!this.animate) { - dom.addClass(this._innerDomNode, 'noanimation'); - } setTimeout(() => { - dom.removeClass(this._innerDomNode, 'noanimation'); this._findInput.select(); }, 200); }, 0); @@ -201,14 +202,14 @@ export abstract class SimpleFindWidget extends Widget { } public showNextFindTerm() { - let next = this._findHistory.next(); + const next = this._findHistory.next(); if (next) { this._findInput.setValue(next); } } public showPreviousFindTerm() { - let previous = this._findHistory.previous(); + const previous = this._findHistory.previous(); if (previous) { this._findInput.setValue(previous); } @@ -222,7 +223,7 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.monaco-workbench .simple-find-part { background-color: ${findWidgetBGColor} !important; }`); } - let widgetShadowColor = theme.getColor(widgetShadow); + const widgetShadowColor = theme.getColor(widgetShadow); if (widgetShadowColor) { collector.addRule(`.monaco-workbench .simple-find-part { box-shadow: 0 2px 8px ${widgetShadowColor}; }`); } diff --git a/src/vs/editor/contrib/find/test/findController.test.ts b/src/vs/editor/contrib/find/test/findController.test.ts index 9e01edbc52..fbbf3ac3fb 100644 --- a/src/vs/editor/contrib/find/test/findController.test.ts +++ b/src/vs/editor/contrib/find/test/findController.test.ts @@ -28,7 +28,7 @@ export class TestFindController extends CommonFindController { public delayUpdateHistory: boolean = false; public delayedUpdateHistoryPromise: TPromise<void>; - private _delayedUpdateHistoryEvent: Emitter<void> = new Emitter<void>(); + private readonly _delayedUpdateHistoryEvent: Emitter<void> = new Emitter<void>(); constructor( editor: ICodeEditor, @@ -335,7 +335,7 @@ suite('FindController', () => { findController.delayedUpdateHistoryPromise.then(() => { assert.deepEqual(['3'], toArray(findController.getHistory())); done(); - }); + }, error => done(error)); }); }); diff --git a/src/vs/editor/contrib/find/test/findModel.test.ts b/src/vs/editor/contrib/find/test/findModel.test.ts index d5e3ba5b49..4f3da57f96 100644 --- a/src/vs/editor/contrib/find/test/findModel.test.ts +++ b/src/vs/editor/contrib/find/test/findModel.test.ts @@ -14,12 +14,14 @@ import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { TextModel } from 'vs/editor/common/model/textModel'; +import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; suite('FindModel', () => { function findTest(testName: string, callback: (editor: ICodeEditor, cursor: Cursor) => void): void { test(testName, () => { - withTestCodeEditor([ + const textArr = [ '// my cool header', '#include "cool.h"', '#include <iostream>', @@ -32,7 +34,19 @@ suite('FindModel', () => { '}', '// blablablaciao', '' - ], {}, callback); + ]; + withTestCodeEditor(textArr, {}, callback); + + const text = textArr.join('\n'); + const ptBuilder = new PieceTreeTextBufferBuilder(); + ptBuilder.acceptChunk(text.substr(0, 94)); + ptBuilder.acceptChunk(text.substr(94, 101)); + ptBuilder.acceptChunk(text.substr(195, 59)); + const factory = ptBuilder.finish(); + withTestCodeEditor([], + { + model: new TextModel(factory, TextModel.DEFAULT_CREATION_OPTIONS, null, null) + }, callback); }); } diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 6ac40383d4..4a01b66753 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/// <amd-dependency path="vs/css!./folding" /> 'use strict'; +import 'vs/css!./folding'; import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; -import { RunOnceScheduler, Delayer } from 'vs/base/common/async'; +import { RunOnceScheduler, Delayer, asWinJsPromise } from 'vs/base/common/async'; import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -28,13 +28,14 @@ import { IRange } from 'vs/editor/common/core/range'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { IndentRangeProvider } from 'vs/editor/contrib/folding/indentRangeProvider'; import { IPosition } from 'vs/editor/common/core/position'; -import { FoldingProviderRegistry, FoldingRangeType } from 'vs/editor/common/modes'; +import { FoldingRangeProviderRegistry, FoldingRangeKind } from 'vs/editor/common/modes'; import { SyntaxRangeProvider } from './syntaxRangeProvider'; +import { CancellationToken } from 'vs/base/common/cancellation'; export const ID = 'editor.contrib.folding'; export interface RangeProvider { - compute(editorModel: ITextModel): TPromise<FoldingRegions>; + compute(editorModel: ITextModel, cancelationToken: CancellationToken): Thenable<FoldingRegions>; } export class FoldingController implements IEditorContribution { @@ -49,6 +50,7 @@ export class FoldingController implements IEditorContribution { private editor: ICodeEditor; private _isEnabled: boolean; private _autoHideFoldingControls: boolean; + private _useFoldingProviders: boolean; private foldingDecorationProvider: FoldingDecorationProvider; @@ -56,6 +58,7 @@ export class FoldingController implements IEditorContribution { private hiddenRangeModel: HiddenRangeModel; private rangeProvider: RangeProvider; + private foldingRegionPromise: TPromise<FoldingRegions>; private foldingModelPromise: TPromise<FoldingModel>; private updateScheduler: Delayer<FoldingModel>; @@ -70,6 +73,7 @@ export class FoldingController implements IEditorContribution { this.editor = editor; this._isEnabled = this.editor.getConfiguration().contribInfo.folding; this._autoHideFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls === 'mouseover'; + this._useFoldingProviders = this.editor.getConfiguration().contribInfo.foldingStrategy !== 'indentation'; this.globalToDispose = []; this.localToDispose = []; @@ -78,7 +82,7 @@ export class FoldingController implements IEditorContribution { this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls; this.globalToDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged())); - this.globalToDispose.push(FoldingProviderRegistry.onDidChange(() => this.onModelChanged())); + this.globalToDispose.push(FoldingRangeProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged())); this.globalToDispose.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { if (e.contribInfo) { @@ -93,6 +97,11 @@ export class FoldingController implements IEditorContribution { this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls; this.onModelContentChanged(); } + let oldUseFoldingProviders = this._useFoldingProviders; + this._useFoldingProviders = this.editor.getConfiguration().contribInfo.foldingStrategy !== 'indentation'; + if (oldUseFoldingProviders !== this._useFoldingProviders) { + this.onFoldingStrategyChanged(); + } } })); this.globalToDispose.push({ dispose: () => dispose(this.localToDispose) }); @@ -171,6 +180,10 @@ export class FoldingController implements IEditorContribution { this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e))); this.localToDispose.push({ dispose: () => { + if (this.foldingRegionPromise) { + this.foldingRegionPromise.cancel(); + this.foldingRegionPromise = null; + } this.updateScheduler.cancel(); this.updateScheduler = null; this.foldingModel = null; @@ -178,16 +191,22 @@ export class FoldingController implements IEditorContribution { this.hiddenRangeModel = null; this.cursorChangedScheduler = null; this.rangeProvider = null; + } }); this.onModelContentChanged(); } + private onFoldingStrategyChanged() { + this.rangeProvider = null; + this.onModelContentChanged(); + } + private getRangeProvider(): RangeProvider { if (!this.rangeProvider) { - let foldingProviders = FoldingProviderRegistry.ordered(this.foldingModel.textModel); - if (foldingProviders.length) { - this.rangeProvider = new SyntaxRangeProvider(foldingProviders); + if (this._useFoldingProviders) { + let foldingProviders = FoldingRangeProviderRegistry.ordered(this.foldingModel.textModel); + this.rangeProvider = foldingProviders.length ? new SyntaxRangeProvider(foldingProviders) : new IndentRangeProvider(); } else { this.rangeProvider = new IndentRangeProvider(); } @@ -201,19 +220,24 @@ export class FoldingController implements IEditorContribution { private onModelContentChanged() { if (this.updateScheduler) { + if (this.foldingRegionPromise) { + this.foldingRegionPromise.cancel(); + this.foldingRegionPromise = null; + } this.foldingModelPromise = this.updateScheduler.trigger(() => { - if (this.foldingModel) { // null if editor has been disposed, or folding turned off - // some cursors might have moved into hidden regions, make sure they are in expanded regions - let selections = this.editor.getSelections(); - let selectionLineNumbers = selections ? selections.map(s => s.startLineNumber) : []; - return this.getRangeProvider().compute(this.foldingModel.textModel).then(foldingRanges => { - if (this.foldingModel) { // null if editor has been disposed, or folding turned off - this.foldingModel.update(foldingRanges, selectionLineNumbers); - } - return this.foldingModel; - }); + if (!this.foldingModel) { // null if editor has been disposed, or folding turned off + return null; } - return null; + let foldingRegionPromise = this.foldingRegionPromise = asWinJsPromise<FoldingRegions>(token => this.getRangeProvider().compute(this.foldingModel.textModel, token)); + return foldingRegionPromise.then(foldingRanges => { + if (foldingRanges && foldingRegionPromise === this.foldingRegionPromise) { // new request or cancelled in the meantime? + // some cursors might have moved into hidden regions, make sure they are in expanded regions + let selections = this.editor.getSelections(); + let selectionLineNumbers = selections ? selections.map(s => s.startLineNumber) : []; + this.foldingModel.update(foldingRanges, selectionLineNumbers); + } + return this.foldingModel; + }); }); } } @@ -425,7 +449,7 @@ class UnfoldAction extends FoldingAction<FoldingArguments> { alias: 'Unfold', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_CLOSE_SQUARE_BRACKET @@ -468,7 +492,7 @@ class UnFoldRecursivelyAction extends FoldingAction<void> { alias: 'Unfold Recursively', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET) } }); @@ -488,7 +512,7 @@ class FoldAction extends FoldingAction<FoldingArguments> { alias: 'Fold', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_OPEN_SQUARE_BRACKET @@ -531,7 +555,7 @@ class FoldRecursivelyAction extends FoldingAction<void> { alias: 'Fold Recursively', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET) } }); @@ -552,7 +576,7 @@ class FoldAllBlockCommentsAction extends FoldingAction<void> { alias: 'Fold All Block Comments', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_SLASH) } }); @@ -560,7 +584,7 @@ class FoldAllBlockCommentsAction extends FoldingAction<void> { invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { if (foldingModel.regions.hasTypes()) { - setCollapseStateForType(foldingModel, FoldingRangeType.Comment, true); + setCollapseStateForType(foldingModel, FoldingRangeKind.Comment.value, true); } else { let comments = LanguageConfigurationRegistry.getComments(editor.getModel().getLanguageIdentifier().id); if (comments && comments.blockCommentStartToken) { @@ -580,7 +604,7 @@ class FoldAllRegionsAction extends FoldingAction<void> { alias: 'Fold All Regions', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_8) } }); @@ -588,7 +612,7 @@ class FoldAllRegionsAction extends FoldingAction<void> { invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { if (foldingModel.regions.hasTypes()) { - setCollapseStateForType(foldingModel, FoldingRangeType.Region, true); + setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, true); } else { let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); if (foldingRules && foldingRules.markers && foldingRules.markers.start) { @@ -608,7 +632,7 @@ class UnfoldAllRegionsAction extends FoldingAction<void> { alias: 'Unfold All Regions', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_9) } }); @@ -616,7 +640,7 @@ class UnfoldAllRegionsAction extends FoldingAction<void> { invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { if (foldingModel.regions.hasTypes()) { - setCollapseStateForType(foldingModel, FoldingRangeType.Region, false); + setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, false); } else { let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); if (foldingRules && foldingRules.markers && foldingRules.markers.start) { @@ -636,7 +660,7 @@ class FoldAllAction extends FoldingAction<void> { alias: 'Fold All', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_0) } }); @@ -656,7 +680,7 @@ class UnfoldAllAction extends FoldingAction<void> { alias: 'Unfold All', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_J) } }); @@ -699,7 +723,7 @@ for (let i = 1; i <= 7; i++) { alias: `Fold Level ${i}`, precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | (KeyCode.KEY_0 + i)) } }) diff --git a/src/vs/editor/contrib/folding/foldingDecorations.ts b/src/vs/editor/contrib/folding/foldingDecorations.ts index e5897230b8..448b641111 100644 --- a/src/vs/editor/contrib/folding/foldingDecorations.ts +++ b/src/vs/editor/contrib/folding/foldingDecorations.ts @@ -10,18 +10,18 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; export class FoldingDecorationProvider implements IDecorationProvider { - private COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, afterContentClassName: 'inline-folded', linesDecorationsClassName: 'folding collapsed' }); - private EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, linesDecorationsClassName: 'folding' }); - private EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ + private static EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, linesDecorationsClassName: 'folding alwaysShowFoldIcons' }); @@ -33,11 +33,11 @@ export class FoldingDecorationProvider implements IDecorationProvider { getDecorationOption(isCollapsed: boolean): ModelDecorationOptions { if (isCollapsed) { - return this.COLLAPSED_VISUAL_DECORATION; + return FoldingDecorationProvider.COLLAPSED_VISUAL_DECORATION; } else if (this.autoHideFoldingControls) { - return this.EXPANDED_AUTO_HIDE_VISUAL_DECORATION; + return FoldingDecorationProvider.EXPANDED_AUTO_HIDE_VISUAL_DECORATION; } else { - return this.EXPANDED_VISUAL_DECORATION; + return FoldingDecorationProvider.EXPANDED_VISUAL_DECORATION; } } diff --git a/src/vs/editor/contrib/folding/foldingModel.ts b/src/vs/editor/contrib/folding/foldingModel.ts index a640da4cd7..5b3d900b70 100644 --- a/src/vs/editor/contrib/folding/foldingModel.ts +++ b/src/vs/editor/contrib/folding/foldingModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ITextModel, IModelDecorationOptions, IModelDeltaDecoration, IModelDecorationsChangeAccessor } from 'vs/editor/common/model'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { FoldingRegions, ILineRange, FoldingRegion } from './foldingRanges'; export interface IDecorationProvider { diff --git a/src/vs/editor/contrib/folding/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/hiddenRangeModel.ts index efe396235a..b673352ed7 100644 --- a/src/vs/editor/contrib/folding/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/hiddenRangeModel.ts @@ -3,12 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Range, IRange } from 'vs/editor/common/core/range'; import { FoldingModel, CollapseMemento } from 'vs/editor/contrib/folding/foldingModel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Selection } from 'vs/editor/common/core/selection'; -import { findFirst } from 'vs/base/common/arrays'; +import { findFirstInSorted } from 'vs/base/common/arrays'; export class HiddenRangeModel { private _foldingModel: FoldingModel; @@ -149,7 +149,7 @@ function isInside(line: number, range: IRange) { return line >= range.startLineNumber && line <= range.endLineNumber; } function findRange(ranges: IRange[], line: number): IRange { - let i = findFirst(ranges, r => line < r.startLineNumber) - 1; + let i = findFirstInSorted(ranges, r => line < r.startLineNumber) - 1; if (i >= 0 && ranges[i].endLineNumber >= line) { return ranges[i]; } diff --git a/src/vs/editor/contrib/folding/indentRangeProvider.ts b/src/vs/editor/contrib/folding/indentRangeProvider.ts index 4b98c91f31..dfa85097da 100644 --- a/src/vs/editor/contrib/folding/indentRangeProvider.ts +++ b/src/vs/editor/contrib/folding/indentRangeProvider.ts @@ -12,11 +12,12 @@ import { TextModel } from 'vs/editor/common/model/textModel'; import { RangeProvider } from './folding'; import { TPromise } from 'vs/base/common/winjs.base'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { CancellationToken } from 'vs/base/common/cancellation'; const MAX_FOLDING_REGIONS_FOR_INDENT_LIMIT = 5000; export class IndentRangeProvider implements RangeProvider { - compute(editorModel: ITextModel): TPromise<FoldingRegions> { + compute(editorModel: ITextModel, cancelationToken: CancellationToken): Thenable<FoldingRegions> { let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editorModel.getLanguageIdentifier().id); let offSide = foldingRules && foldingRules.offSide; let markers = foldingRules && foldingRules.markers; diff --git a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts index ad8c008fb6..73a3e3c672 100644 --- a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts +++ b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts @@ -5,51 +5,66 @@ 'use strict'; -import { FoldingProvider, IFoldingRange } from 'vs/editor/common/modes'; +import { FoldingRangeProvider, FoldingRange, FoldingContext } from 'vs/editor/common/modes'; import { onUnexpectedExternalError } from 'vs/base/common/errors'; -import { asWinJsPromise } from 'vs/base/common/async'; +import { toThenable } from 'vs/base/common/async'; import { ITextModel } from 'vs/editor/common/model'; import { RangeProvider } from './folding'; import { TPromise } from 'vs/base/common/winjs.base'; import { MAX_LINE_NUMBER, FoldingRegions } from './foldingRanges'; +import { CancellationToken } from 'vs/base/common/cancellation'; const MAX_FOLDING_REGIONS_FOR_INDENT_LIMIT = 5000; -export interface IFoldingRangeData extends IFoldingRange { +export interface IFoldingRangeData extends FoldingRange { rank: number; } +const foldingContext: FoldingContext = { + maxRanges: MAX_FOLDING_REGIONS_FOR_INDENT_LIMIT +}; + export class SyntaxRangeProvider implements RangeProvider { - constructor(private providers: FoldingProvider[]) { + constructor(private providers: FoldingRangeProvider[]) { } - compute(model: ITextModel): TPromise<FoldingRegions> { - return collectSyntaxRanges(this.providers, model).then(ranges => { - let res = sanitizeRanges(ranges); - //console.log(res.toString()); - return res; + compute(model: ITextModel, cancellationToken: CancellationToken): Thenable<FoldingRegions> { + return collectSyntaxRanges(this.providers, model, cancellationToken).then(ranges => { + if (ranges) { + let res = sanitizeRanges(ranges); + return res; + } + return null; }); } } -function collectSyntaxRanges(providers: FoldingProvider[], model: ITextModel): TPromise<IFoldingRangeData[]> { - const rangeData: IFoldingRangeData[] = []; - let promises = providers.map((provider, rank) => asWinJsPromise(token => provider.provideFoldingRanges(model, token)).then(list => { - if (list && Array.isArray(list.ranges)) { - let nLines = model.getLineCount(); - for (let r of list.ranges) { - if (r.startLineNumber > 0 && r.endLineNumber > r.startLineNumber && r.endLineNumber <= nLines) { - rangeData.push({ startLineNumber: r.startLineNumber, endLineNumber: r.endLineNumber, rank, type: r.type }); +function collectSyntaxRanges(providers: FoldingRangeProvider[], model: ITextModel, cancellationToken: CancellationToken): Thenable<IFoldingRangeData[] | null> { + let promises = providers.map(provider => toThenable(provider.provideFoldingRanges(model, foldingContext, cancellationToken))); + return TPromise.join(promises).then(results => { + let rangeData: IFoldingRangeData[] = null; + if (cancellationToken.isCancellationRequested) { + return null; + } + for (let i = 0; i < results.length; i++) { + let ranges = results[i]; + if (Array.isArray(ranges)) { + if (!Array.isArray(rangeData)) { + rangeData = []; + } + let nLines = model.getLineCount(); + for (let r of ranges) { + if (r.start > 0 && r.end > r.start && r.end <= nLines) { + rangeData.push({ start: r.start, end: r.end, rank: i, kind: r.kind }); + } } } } - }, onUnexpectedExternalError)); - - return TPromise.join(promises).then(() => { return rangeData; - }); + + }, onUnexpectedExternalError); } export class RangesCollector { @@ -130,7 +145,7 @@ export class RangesCollector { export function sanitizeRanges(rangeData: IFoldingRangeData[]): FoldingRegions { let sorted = rangeData.sort((d1, d2) => { - let diff = d1.startLineNumber - d2.startLineNumber; + let diff = d1.start - d2.start; if (diff === 0) { diff = d1.rank - d2.rank; } @@ -143,20 +158,20 @@ export function sanitizeRanges(rangeData: IFoldingRangeData[]): FoldingRegions { for (let entry of sorted) { if (!top) { top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); + collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length); } else { - if (entry.startLineNumber > top.startLineNumber) { - if (entry.endLineNumber <= top.endLineNumber) { + if (entry.start > top.start) { + if (entry.end <= top.end) { previous.push(top); top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); - } else if (entry.startLineNumber > top.endLineNumber) { + collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length); + } else if (entry.start > top.end) { do { top = previous.pop(); - } while (top && entry.startLineNumber > top.endLineNumber); + } while (top && entry.start > top.end); previous.push(top); top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); + collector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length); } } } diff --git a/src/vs/editor/contrib/format/format.ts b/src/vs/editor/contrib/format/format.ts index 790f815d43..aed350f33e 100644 --- a/src/vs/editor/contrib/format/format.ts +++ b/src/vs/editor/contrib/format/format.ts @@ -38,14 +38,14 @@ export function getDocumentRangeFormattingEdits(model: ITextModel, range: Range, let result: TextEdit[]; return sequence(providers.map(provider => { - if (isFalsyOrEmpty(result)) { - return () => { - return asWinJsPromise(token => provider.provideDocumentRangeFormattingEdits(model, range, options, token)).then(value => { - result = value; - }, onUnexpectedExternalError); - }; - } - return undefined; + return () => { + if (!isFalsyOrEmpty(result)) { + return undefined; + } + return asWinJsPromise(token => provider.provideDocumentRangeFormattingEdits(model, range, options, token)).then(value => { + result = value; + }, onUnexpectedExternalError); + }; })).then(() => result); } @@ -59,14 +59,14 @@ export function getDocumentFormattingEdits(model: ITextModel, options: Formattin let result: TextEdit[]; return sequence(providers.map(provider => { - if (isFalsyOrEmpty(result)) { - return () => { - return asWinJsPromise(token => provider.provideDocumentFormattingEdits(model, options, token)).then(value => { - result = value; - }, onUnexpectedExternalError); - }; - } - return undefined; + return () => { + if (!isFalsyOrEmpty(result)) { + return undefined; + } + return asWinJsPromise(token => provider.provideDocumentFormattingEdits(model, options, token)).then(value => { + result = value; + }, onUnexpectedExternalError); + }; })).then(() => result); } diff --git a/src/vs/editor/contrib/format/formatActions.ts b/src/vs/editor/contrib/format/formatActions.ts index 5f65270a4d..2c8606c51b 100644 --- a/src/vs/editor/contrib/format/formatActions.ts +++ b/src/vs/editor/contrib/format/formatActions.ts @@ -161,7 +161,7 @@ class FormatOnType implements editorCommon.IEditorContribution { return; } - EditOperationsCommand.execute(this.editor, edits, true); + EditOperationsCommand.executeAsCommand(this.editor, edits); alertFormattingEdits(edits); }, (err) => { @@ -244,7 +244,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution { if (!state.validate(this.editor) || isFalsyOrEmpty(edits)) { return; } - EditOperationsCommand.execute(this.editor, edits, false); + EditOperationsCommand.execute(this.editor, edits); alertFormattingEdits(edits); }); } @@ -280,12 +280,12 @@ export abstract class AbstractFormatAction extends EditorAction { return; } - EditOperationsCommand.execute(editor, edits, false); + EditOperationsCommand.execute(editor, edits); alertFormattingEdits(edits); editor.focus(); }, err => { if (err instanceof Error && err.name === NoProviderError.Name) { - notificationService.info(nls.localize('no.provider', "There is no formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language)); + this._notifyNoProviderError(notificationService, editor.getModel().getLanguageIdentifier().language); } else { throw err; } @@ -293,6 +293,9 @@ export abstract class AbstractFormatAction extends EditorAction { } protected abstract _getFormattingEdits(editor: ICodeEditor): TPromise<ISingleEditOperation[]>; + protected _notifyNoProviderError(notificationService: INotificationService, language: string): void { + notificationService.info(nls.localize('no.provider', "There is no formatter for '{0}'-files installed.", language)); + } } export class FormatDocumentAction extends AbstractFormatAction { @@ -304,7 +307,7 @@ export class FormatDocumentAction extends AbstractFormatAction { alias: 'Format Document', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F, // secondary: [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)], linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I } @@ -322,6 +325,10 @@ export class FormatDocumentAction extends AbstractFormatAction { const { tabSize, insertSpaces } = model.getOptions(); return getDocumentFormattingEdits(model, { tabSize, insertSpaces }); } + + protected _notifyNoProviderError(notificationService: INotificationService, language: string): void { + notificationService.info(nls.localize('no.documentprovider', "There is no document formatter for '{0}'-files installed.", language)); + } } export class FormatSelectionAction extends AbstractFormatAction { @@ -333,7 +340,7 @@ export class FormatSelectionAction extends AbstractFormatAction { alias: 'Format Code', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasNonEmptySelection), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_F) }, menuOpts: { @@ -349,6 +356,10 @@ export class FormatSelectionAction extends AbstractFormatAction { const { tabSize, insertSpaces } = model.getOptions(); return getDocumentRangeFormattingEdits(model, editor.getSelection(), { tabSize, insertSpaces }); } + + protected _notifyNoProviderError(notificationService: INotificationService, language: string): void { + notificationService.info(nls.localize('no.selectionprovider', "There is no selection formatter for '{0}'-files installed.", language)); + } } registerEditorContribution(FormatOnType); diff --git a/src/vs/editor/contrib/format/formatCommand.ts b/src/vs/editor/contrib/format/formatCommand.ts index 2d3fa507ef..1994f1ff34 100644 --- a/src/vs/editor/contrib/format/formatCommand.ts +++ b/src/vs/editor/contrib/format/formatCommand.ts @@ -15,39 +15,60 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; export class EditOperationsCommand implements editorCommon.ICommand { - static execute(editor: ICodeEditor, edits: TextEdit[], asCommand: boolean) { - const cmd = new EditOperationsCommand(edits, editor.getSelection()); - if (typeof cmd._newEol === 'number') { - editor.getModel().setEOL(cmd._newEol); + static _handleEolEdits(editor: ICodeEditor, edits: TextEdit[]): ISingleEditOperation[] { + let newEol: EndOfLineSequence = undefined; + let singleEdits: ISingleEditOperation[] = []; + + for (let edit of edits) { + if (typeof edit.eol === 'number') { + newEol = edit.eol; + } + if (edit.range && typeof edit.text === 'string') { + singleEdits.push(edit); + } } + + if (typeof newEol === 'number') { + editor.getModel().setEOL(newEol); + } + + return singleEdits; + } + + static executeAsCommand(editor: ICodeEditor, _edits: TextEdit[]) { + let edits = this._handleEolEdits(editor, _edits); + const cmd = new EditOperationsCommand(edits, editor.getSelection()); editor.pushUndoStop(); - if (!asCommand) { - editor.executeEdits('formatEditsCommand', cmd._edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text))); + editor.executeCommand('formatEditsCommand', cmd); + editor.pushUndoStop(); + } + + static isFullModelReplaceEdit(editor: ICodeEditor, edit: ISingleEditOperation): boolean { + const model = editor.getModel(); + const editRange = model.validateRange(edit.range); + const fullModelRange = model.getFullModelRange(); + return fullModelRange.equalsRange(editRange); + } + + static execute(editor: ICodeEditor, _edits: TextEdit[]) { + let edits = this._handleEolEdits(editor, _edits); + editor.pushUndoStop(); + if (edits.length === 1 && EditOperationsCommand.isFullModelReplaceEdit(editor, edits[0])) { + // We use replace semantics and hope that markers stay put... + editor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text))); } else { - editor.executeCommand('formatEditsCommand', cmd); + editor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replaceMove(Range.lift(edit.range), edit.text))); } editor.pushUndoStop(); } - private _edits: TextEdit[]; - private _newEol: EndOfLineSequence; - + private _edits: ISingleEditOperation[]; private _initialSelection: Selection; private _selectionId: string; - constructor(edits: TextEdit[], initialSelection: Selection) { + constructor(edits: ISingleEditOperation[], initialSelection: Selection) { this._initialSelection = initialSelection; - this._edits = []; - this._newEol = undefined; - - for (let edit of edits) { - if (typeof edit.eol === 'number') { - this._newEol = edit.eol; - } - if (edit.range && typeof edit.text === 'string') { - this._edits.push(edit); - } - } + this._edits = edits; } public getEditOperations(model: ITextModel, builder: editorCommon.IEditOperationBuilder): void { diff --git a/src/vs/editor/contrib/format/test/formatCommand.test.ts b/src/vs/editor/contrib/format/test/formatCommand.test.ts index d6f23056dd..bff970540e 100644 --- a/src/vs/editor/contrib/format/test/formatCommand.test.ts +++ b/src/vs/editor/contrib/format/test/formatCommand.test.ts @@ -11,6 +11,7 @@ import { ISingleEditOperation } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import { EditOperationsCommand } from 'vs/editor/contrib/format/formatCommand'; import { testCommand } from 'vs/editor/test/browser/testCommand'; +import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text: string[]): ISingleEditOperation { return { @@ -310,4 +311,52 @@ suite('FormatCommand', () => { ); }); + test('issue #44870', () => { + const initialText = [ + '[', + ' {},{', + ' }', + ']', + ]; + withTestCodeEditor(initialText, {}, (editor) => { + editor.setSelection(new Selection(2, 8, 2, 8)); + EditOperationsCommand.execute(editor, [ + editOp(2, 8, 2, 8, ['', ' ']), + editOp(2, 9, 3, 5, ['']), + ]); + assert.equal(editor.getValue(), [ + '[', + ' {},', + ' {}', + ']', + ].join('\n')); + assert.deepEqual(editor.getSelection(), new Selection(3, 5, 3, 5)); + }); + }); + + test('issue #47382: full model replace moves cursor to end of file', () => { + const initialText = [ + 'just some', + 'Text', + '...more text' + ]; + withTestCodeEditor(initialText, {}, (editor) => { + editor.setSelection(new Selection(2, 1, 2, 1)); + EditOperationsCommand.execute(editor, [{ + range: new Range(1, 1, 3, 13), + text: [ + 'just some', + '\tText', + '...more text' + ].join('\n') + }]); + assert.equal(editor.getValue(), [ + 'just some', + '\tText', + '...more text' + ].join('\n')); + assert.deepEqual(editor.getSelection(), new Selection(2, 1, 2, 1)); + }); + }); + }); diff --git a/src/vs/editor/contrib/goToDeclaration/clickLinkGesture.ts b/src/vs/editor/contrib/goToDeclaration/clickLinkGesture.ts index 425da16131..5b3cae2737 100644 --- a/src/vs/editor/contrib/goToDeclaration/clickLinkGesture.ts +++ b/src/vs/editor/contrib/goToDeclaration/clickLinkGesture.ts @@ -12,7 +12,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ICodeEditor, IEditorMouseEvent, IMouseTarget } from 'vs/editor/browser/editorBrowser'; import { Disposable } from 'vs/base/common/lifecycle'; import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as platform from 'vs/base/common/platform'; function hasModifier(e: { ctrlKey: boolean; shiftKey: boolean; altKey: boolean; metaKey: boolean }, modifier: 'ctrlKey' | 'shiftKey' | 'altKey' | 'metaKey'): boolean { diff --git a/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts b/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts index d179b1537d..a4feb98638 100644 --- a/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts +++ b/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts @@ -193,7 +193,7 @@ export class GoToDefinitionAction extends DefinitionAction { EditorContextKeys.hasDefinitionProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: goToDeclarationKb }, menuOpts: { @@ -217,7 +217,7 @@ export class OpenDefinitionToSideAction extends DefinitionAction { EditorContextKeys.hasDefinitionProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, goToDeclarationKb) } }); @@ -235,7 +235,7 @@ export class PeekDefinitionAction extends DefinitionAction { PeekContext.notInPeekEditor, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.F12, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.F10 } }, @@ -276,7 +276,7 @@ export class GoToImplementationAction extends ImplementationAction { EditorContextKeys.hasImplementationProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.F12 } }); @@ -296,7 +296,7 @@ export class PeekImplementationAction extends ImplementationAction { EditorContextKeys.hasImplementationProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.F12 } }); @@ -332,7 +332,7 @@ export class GoToTypeDefintionAction extends TypeDefinitionAction { EditorContextKeys.hasTypeDefinitionProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: 0 }, menuOpts: { @@ -356,7 +356,7 @@ export class PeekTypeDefinitionAction extends TypeDefinitionAction { EditorContextKeys.hasTypeDefinitionProvider, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: 0 } }); diff --git a/src/vs/editor/contrib/gotoError/gotoError.ts b/src/vs/editor/contrib/gotoError/gotoError.ts index dcc67ab889..84d4caf8c4 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/gotoError.ts @@ -5,31 +5,27 @@ 'use strict'; -import 'vs/css!./gotoError'; import * as nls from 'vs/nls'; import { Emitter } from 'vs/base/common/event'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; -import * as dom from 'vs/base/browser/dom'; import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IMarker, IMarkerService } from 'vs/platform/markers/common/markers'; +import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; -import { registerColor, oneOf } from 'vs/platform/theme/common/colorRegistry'; -import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; -import { Color } from 'vs/base/common/color'; +import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { AccessibilitySupport } from 'vs/base/common/platform'; -import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoForeground, editorInfoBorder } from 'vs/editor/common/view/editorColorRegistry'; -import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; -import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { MarkerNavigationWidget } from './gotoErrorWidget'; +import { compare } from 'vs/base/common/strings'; +import { binarySearch } from 'vs/base/common/arrays'; +import { IEditorService } from 'vs/platform/editor/common/editor'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { onUnexpectedError } from 'vs/base/common/errors'; class MarkerModel { @@ -38,8 +34,8 @@ class MarkerModel { private _nextIdx: number; private _toUnbind: IDisposable[]; private _ignoreSelectionChange: boolean; - private _onCurrentMarkerChanged: Emitter<IMarker>; - private _onMarkerSetChanged: Emitter<MarkerModel>; + private readonly _onCurrentMarkerChanged: Emitter<IMarker>; + private readonly _onMarkerSetChanged: Emitter<MarkerModel>; constructor(editor: ICodeEditor, markers: IMarker[]) { this._editor = editor; @@ -54,9 +50,13 @@ class MarkerModel { // listen on editor this._toUnbind.push(this._editor.onDidDispose(() => this.dispose())); this._toUnbind.push(this._editor.onDidChangeCursorPosition(() => { - if (!this._ignoreSelectionChange) { - this._nextIdx = -1; + if (this._ignoreSelectionChange) { + return; } + if (this.currentMarker && Range.containsPosition(this.currentMarker, this._editor.getPosition())) { + return; + } + this._nextIdx = -1; })); } @@ -69,13 +69,15 @@ class MarkerModel { } public setMarkers(markers: IMarker[]): void { - // assign + + let oldMarker = this._nextIdx >= 0 ? this._markers[this._nextIdx] : undefined; this._markers = markers || []; - - // sort markers - this._markers.sort((left, right) => Severity.compare(left.severity, right.severity) || Range.compareRangesUsingStarts(left, right)); - - this._nextIdx = -1; + this._markers.sort(MarkerNavigationAction.compareMarker); + if (!oldMarker) { + this._nextIdx = -1; + } else { + this._nextIdx = Math.max(-1, binarySearch(this._markers, oldMarker, MarkerNavigationAction.compareMarker)); + } this._onMarkerSetChanged.fire(this); } @@ -102,7 +104,7 @@ class MarkerModel { } if (range.containsPosition(position) || position.isBeforeOrEqual(range.getStartPosition())) { - this._nextIdx = i + (fwd ? 0 : -1); + this._nextIdx = i; found = true; break; } @@ -116,42 +118,49 @@ class MarkerModel { } } - private move(fwd: boolean): void { + get currentMarker(): IMarker { + return this.canNavigate() ? this._markers[this._nextIdx] : undefined; + } + + public move(fwd: boolean, inCircles: boolean): boolean { if (!this.canNavigate()) { this._onCurrentMarkerChanged.fire(undefined); - return; + return !inCircles; } + let oldIdx = this._nextIdx; + let atEdge = false; + if (this._nextIdx === -1) { this._initIdx(fwd); } else if (fwd) { - this._nextIdx += 1; - if (this._nextIdx >= this._markers.length) { - this._nextIdx = 0; + if (inCircles || this._nextIdx + 1 < this._markers.length) { + this._nextIdx = (this._nextIdx + 1) % this._markers.length; + } else { + atEdge = true; } - } else { - this._nextIdx -= 1; - if (this._nextIdx < 0) { - this._nextIdx = this._markers.length - 1; + + } else if (!fwd) { + if (inCircles || this._nextIdx > 0) { + this._nextIdx = (this._nextIdx - 1 + this._markers.length) % this._markers.length; + } else { + atEdge = true; } } - const marker = this._markers[this._nextIdx]; - this._onCurrentMarkerChanged.fire(marker); + + if (oldIdx !== this._nextIdx) { + const marker = this._markers[this._nextIdx]; + this._onCurrentMarkerChanged.fire(marker); + } + + return atEdge; } public canNavigate(): boolean { return this._markers.length > 0; } - public next(): void { - this.move(true); - } - - public previous(): void { - this.move(false); - } - public findMarkerAtPosition(pos: Position): IMarker { for (const marker of this._markers) { if (Range.containsPosition(marker, pos)) { @@ -169,251 +178,11 @@ class MarkerModel { return 1 + this._markers.indexOf(marker); } - public reveal(): void { - - if (this._nextIdx === -1) { - return; - } - - this.withoutWatchingEditorPosition(() => { - const pos = new Position(this._markers[this._nextIdx].startLineNumber, this._markers[this._nextIdx].startColumn); - this._editor.setPosition(pos); - this._editor.revealPositionInCenter(pos, editorCommon.ScrollType.Smooth); - }); - } - public dispose(): void { this._toUnbind = dispose(this._toUnbind); } } -class MessageWidget { - - lines: number = 0; - longestLineLength: number = 0; - - private readonly _editor: ICodeEditor; - private readonly _domNode: HTMLElement; - private readonly _scrollable: ScrollableElement; - private readonly _disposables: IDisposable[] = []; - - constructor(parent: HTMLElement, editor: ICodeEditor) { - this._editor = editor; - - this._domNode = document.createElement('span'); - this._domNode.className = 'descriptioncontainer'; - this._domNode.setAttribute('aria-live', 'assertive'); - this._domNode.setAttribute('role', 'alert'); - - this._scrollable = new ScrollableElement(this._domNode, { - horizontal: ScrollbarVisibility.Auto, - vertical: ScrollbarVisibility.Hidden, - useShadows: false, - horizontalScrollbarSize: 3 - }); - dom.addClass(this._scrollable.getDomNode(), 'block'); - parent.appendChild(this._scrollable.getDomNode()); - this._disposables.push(this._scrollable.onScroll(e => this._domNode.style.left = `-${e.scrollLeft}px`)); - this._disposables.push(this._scrollable); - } - - dispose(): void { - dispose(this._disposables); - } - - update({ source, message }: IMarker): void { - - if (source) { - this.lines = 0; - this.longestLineLength = 0; - const indent = new Array(source.length + 3 + 1).join(' '); - const lines = message.split(/\r\n|\r|\n/g); - for (let i = 0; i < lines.length; i++) { - let line = lines[i]; - this.lines += 1; - this.longestLineLength = Math.max(line.length, this.longestLineLength); - if (i === 0) { - message = `[${source}] ${line}`; - } else { - message += `\n${indent}${line}`; - } - } - } else { - this.lines = 1; - this.longestLineLength = message.length; - } - - this._domNode.innerText = message; - this._editor.applyFontInfo(this._domNode); - const width = Math.floor(this._editor.getConfiguration().fontInfo.typicalFullwidthCharacterWidth * this.longestLineLength); - this._scrollable.setScrollDimensions({ scrollWidth: width }); - } - - layout(height: number, width: number): void { - this._scrollable.setScrollDimensions({ width }); - } -} - -class MarkerNavigationWidget extends ZoneWidget { - - private _parentContainer: HTMLElement; - private _container: HTMLElement; - private _title: HTMLElement; - private _message: MessageWidget; - private _callOnDispose: IDisposable[] = []; - private _severity: Severity; - private _backgroundColor: Color; - - constructor( - editor: ICodeEditor, - private _model: MarkerModel, - private _themeService: IThemeService - ) { - super(editor, { showArrow: true, showFrame: true, isAccessible: true }); - this._severity = Severity.Warning; - this._backgroundColor = Color.white; - - this._applyTheme(_themeService.getTheme()); - this._callOnDispose.push(_themeService.onThemeChange(this._applyTheme.bind(this))); - - this.create(); - this._wireModelAndView(); - } - - private _applyTheme(theme: ITheme) { - this._backgroundColor = theme.getColor(editorMarkerNavigationBackground); - let colorId = editorMarkerNavigationError; - if (this._severity === Severity.Warning) { - colorId = editorMarkerNavigationWarning; - } else if (this._severity === Severity.Info) { - colorId = editorMarkerNavigationInfo; - } - let frameColor = theme.getColor(colorId); - this.style({ - arrowColor: frameColor, - frameColor: frameColor - }); // style() will trigger _applyStyles - } - - protected _applyStyles(): void { - if (this._parentContainer) { - this._parentContainer.style.backgroundColor = this._backgroundColor.toString(); - } - super._applyStyles(); - } - - dispose(): void { - this._callOnDispose = dispose(this._callOnDispose); - super.dispose(); - } - - focus(): void { - this._parentContainer.focus(); - } - - protected _fillContainer(container: HTMLElement): void { - this._parentContainer = container; - dom.addClass(container, 'marker-widget'); - this._parentContainer.tabIndex = 0; - this._parentContainer.setAttribute('role', 'tooltip'); - - this._container = document.createElement('div'); - container.appendChild(this._container); - - this._title = document.createElement('div'); - this._title.className = 'block title'; - this._container.appendChild(this._title); - - this._message = new MessageWidget(this._container, this.editor); - this._disposables.push(this._message); - } - - show(where: Position, heightInLines: number): void { - super.show(where, heightInLines); - if (this.editor.getConfiguration().accessibilitySupport !== AccessibilitySupport.Disabled) { - this.focus(); - } - } - - private _wireModelAndView(): void { - // listen to events - this._model.onCurrentMarkerChanged(this.showAtMarker, this, this._callOnDispose); - this._model.onMarkerSetChanged(this._onMarkersChanged, this, this._callOnDispose); - } - - public showAtMarker(marker: IMarker): void { - - if (!marker) { - return; - } - - // update: - // * title - // * message - this._container.classList.remove('stale'); - this._title.innerHTML = nls.localize('title.wo_source', "({0}/{1})", this._model.indexOf(marker), this._model.total); - this._message.update(marker); - - this._model.withoutWatchingEditorPosition(() => { - // update frame color (only applied on 'show') - this._severity = marker.severity; - this._applyTheme(this._themeService.getTheme()); - - this.show(new Position(marker.startLineNumber, marker.startColumn), this.computeRequiredHeight()); - }); - } - - private _onMarkersChanged(): void { - const marker = this._model.findMarkerAtPosition(this.position); - if (marker) { - this._container.classList.remove('stale'); - this._message.update(marker); - } else { - this._container.classList.add('stale'); - } - this._relayout(); - } - - protected _doLayout(heightInPixel: number, widthInPixel: number): void { - this._message.layout(heightInPixel, widthInPixel); - } - - protected _relayout(): void { - super._relayout(this.computeRequiredHeight()); - } - - private computeRequiredHeight() { - return 1 + this._message.lines; - } -} - -class MarkerNavigationAction extends EditorAction { - - private _isNext: boolean; - - constructor(next: boolean, opts: IActionOptions) { - super(opts); - this._isNext = next; - } - - public run(accessor: ServicesAccessor, editor: ICodeEditor): void { - const controller = MarkerController.get(editor); - if (!controller) { - return; - } - - let model = controller.getOrCreateModel(); - if (model) { - if (this._isNext) { - model.next(); - } else { - model.previous(); - } - model.reveal(); - } - } -} - class MarkerController implements editorCommon.IEditorContribution { private static readonly ID = 'editor.contrib.markerController'; @@ -424,18 +193,19 @@ class MarkerController implements editorCommon.IEditorContribution { private _editor: ICodeEditor; private _model: MarkerModel; - private _zone: MarkerNavigationWidget; - private _callOnClose: IDisposable[] = []; - private _markersNavigationVisible: IContextKey<boolean>; + private _widget: MarkerNavigationWidget; + private _widgetVisible: IContextKey<boolean>; + private _disposeOnClose: IDisposable[] = []; constructor( editor: ICodeEditor, @IMarkerService private readonly _markerService: IMarkerService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, - @IThemeService private readonly _themeService: IThemeService + @IThemeService private readonly _themeService: IThemeService, + @IEditorService private readonly _editorService: IEditorService ) { this._editor = editor; - this._markersNavigationVisible = CONTEXT_MARKERS_NAVIGATION_VISIBLE.bindTo(this._contextKeyService); + this._widgetVisible = CONTEXT_MARKERS_NAVIGATION_VISIBLE.bindTo(this._contextKeyService); } public getId(): string { @@ -447,9 +217,9 @@ class MarkerController implements editorCommon.IEditorContribution { } private _cleanUp(): void { - this._markersNavigationVisible.reset(); - this._callOnClose = dispose(this._callOnClose); - this._zone = null; + this._widgetVisible.reset(); + this._disposeOnClose = dispose(this._disposeOnClose); + this._widget = null; this._model = null; } @@ -461,21 +231,48 @@ class MarkerController implements editorCommon.IEditorContribution { const markers = this._getMarkers(); this._model = new MarkerModel(this._editor, markers); - this._zone = new MarkerNavigationWidget(this._editor, this._model, this._themeService); - this._markersNavigationVisible.set(true); + this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._disposeOnClose); - this._callOnClose.push(this._model); - this._callOnClose.push(this._zone); + this._widget = new MarkerNavigationWidget(this._editor, this._themeService); + this._widgetVisible.set(true); + + this._disposeOnClose.push(this._model); + this._disposeOnClose.push(this._widget); + this._disposeOnClose.push(this._widget.onDidSelectRelatedInformation(related => { + this._editorService.openEditor({ + resource: related.resource, + options: { pinned: true, revealIfOpened: true, selection: Range.lift(related).collapseToStart() } + }).then(undefined, onUnexpectedError); + this.closeMarkersNavigation(false); + })); + this._disposeOnClose.push(this._editor.onDidChangeModel(() => this._cleanUp())); + + this._disposeOnClose.push(this._model.onCurrentMarkerChanged(marker => { + if (!marker) { + this._cleanUp(); + } else { + this._model.withoutWatchingEditorPosition(() => { + this._widget.showAtMarker(marker, this._model.indexOf(marker), this._model.total); + }); + } + })); + this._disposeOnClose.push(this._model.onMarkerSetChanged(() => { + const marker = this._model.findMarkerAtPosition(this._widget.position); + if (marker) { + this._widget.updateMarker(marker); + } else { + this._widget.showStale(); + } + })); - this._callOnClose.push(this._editor.onDidChangeModel(() => this._cleanUp())); - this._model.onCurrentMarkerChanged(marker => !marker && this._cleanUp(), undefined, this._callOnClose); - this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._callOnClose); return this._model; } - public closeMarkersNavigation(): void { + public closeMarkersNavigation(focusEditor: boolean = true): void { this._cleanUp(); - this._editor.focus(); + if (focusEditor) { + this._editor.focus(); + } } private _onMarkerChanged(changedResources: URI[]): void { @@ -486,7 +283,87 @@ class MarkerController implements editorCommon.IEditorContribution { } private _getMarkers(): IMarker[] { - return this._markerService.read({ resource: this._editor.getModel().uri }); + return this._markerService.read({ + resource: this._editor.getModel().uri, + severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info + }); + } +} + +class MarkerNavigationAction extends EditorAction { + + private _isNext: boolean; + + constructor(next: boolean, opts: IActionOptions) { + super(opts); + this._isNext = next; + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> { + + const markerService = accessor.get(IMarkerService); + const editorService = accessor.get(IEditorService); + const controller = MarkerController.get(editor); + if (!controller) { + return undefined; + } + + const model = controller.getOrCreateModel(); + const atEdge = model.move(this._isNext, false); + if (!atEdge) { + return undefined; + } + + // try with the next/prev file + let markers = markerService.read({ severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info }).sort(MarkerNavigationAction.compareMarker); + if (markers.length === 0) { + return undefined; + } + + let oldMarker = model.currentMarker || <IMarker>{ resource: editor.getModel().uri, severity: MarkerSeverity.Error, startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }; + let idx = binarySearch(markers, oldMarker, MarkerNavigationAction.compareMarker); + if (idx < 0) { + // find best match... + idx = ~idx; + idx %= markers.length; + } else if (this._isNext) { + idx = (idx + 1) % markers.length; + } else { + idx = (idx + markers.length - 1) % markers.length; + } + + let newMarker = markers[idx]; + if (newMarker.resource.toString() === editor.getModel().uri.toString()) { + // the next `resource` is this resource which + // means we cycle within this file + model.move(this._isNext, true); + return undefined; + } + + // close the widget for this editor-instance, open the resource + // for the next marker and re-start marker navigation in there + controller.closeMarkersNavigation(); + + return editorService.openEditor({ + resource: newMarker.resource, + options: { pinned: false, revealIfOpened: true, revealInCenterIfOutsideViewport: true, selection: newMarker } + }).then(editor => { + if (!editor || !isCodeEditor(editor.getControl())) { + return undefined; + } + return (<ICodeEditor>editor.getControl()).getAction(this.id).run(); + }); + } + + static compareMarker(a: IMarker, b: IMarker): number { + let res = compare(a.resource.toString(), b.resource.toString()); + if (res === 0) { + res = MarkerSeverity.compare(a.severity, b.severity); + } + if (res === 0) { + res = Range.compareRangesUsingStarts(a, b); + } + return res; } } @@ -539,14 +416,3 @@ registerEditorCommand(new MarkerCommand({ secondary: [KeyMod.Shift | KeyCode.Escape] } })); - -// theming - -let errorDefault = oneOf(editorErrorForeground, editorErrorBorder); -let warningDefault = oneOf(editorWarningForeground, editorWarningBorder); -let infoDefault = oneOf(editorInfoForeground, editorInfoBorder); - -export const editorMarkerNavigationError = registerColor('editorMarkerNavigationError.background', { dark: errorDefault, light: errorDefault, hc: errorDefault }, nls.localize('editorMarkerNavigationError', 'Editor marker navigation widget error color.')); -export const editorMarkerNavigationWarning = registerColor('editorMarkerNavigationWarning.background', { dark: warningDefault, light: warningDefault, hc: warningDefault }, nls.localize('editorMarkerNavigationWarning', 'Editor marker navigation widget warning color.')); -export const editorMarkerNavigationInfo = registerColor('editorMarkerNavigationInfo.background', { dark: infoDefault, light: infoDefault, hc: infoDefault }, nls.localize('editorMarkerNavigationInfo', 'Editor marker navigation widget info color.')); -export const editorMarkerNavigationBackground = registerColor('editorMarkerNavigation.background', { dark: '#2D2D30', light: Color.white, hc: '#0C141F' }, nls.localize('editorMarkerNavigationBackground', 'Editor marker navigation widget background.')); diff --git a/src/vs/editor/contrib/gotoError/gotoError.css b/src/vs/editor/contrib/gotoError/gotoErrorWidget.css similarity index 89% rename from src/vs/editor/contrib/gotoError/gotoError.css rename to src/vs/editor/contrib/gotoError/gotoErrorWidget.css index 4296b3fadd..d6ab264b19 100644 --- a/src/vs/editor/contrib/gotoError/gotoError.css +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.css @@ -32,3 +32,8 @@ -webkit-user-select: text; user-select: text; } + +.monaco-editor .marker-widget .descriptioncontainer .filename { + cursor: pointer; + opacity: 0.6; +} diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts new file mode 100644 index 0000000000..b9b6c74e9c --- /dev/null +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -0,0 +1,275 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'vs/css!./gotoErrorWidget'; +import * as nls from 'vs/nls'; +import * as dom from 'vs/base/browser/dom'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers'; +import { Position } from 'vs/editor/common/core/position'; +import { Range } from 'vs/editor/common/core/range'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; +import { registerColor, oneOf } from 'vs/platform/theme/common/colorRegistry'; +import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; +import { Color } from 'vs/base/common/color'; +import { AccessibilitySupport } from 'vs/base/common/platform'; +import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoForeground, editorInfoBorder } from 'vs/editor/common/view/editorColorRegistry'; +import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { ScrollType } from 'vs/editor/common/editorCommon'; +import { getBaseLabel, getPathLabel } from 'vs/base/common/labels'; +import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { Event, Emitter } from 'vs/base/common/event'; + +class MessageWidget { + + lines: number = 0; + longestLineLength: number = 0; + + private readonly _editor: ICodeEditor; + private readonly _messageBlock: HTMLSpanElement; + private readonly _relatedBlock: HTMLSpanElement; + private readonly _scrollable: ScrollableElement; + private readonly _relatedDiagnostics = new WeakMap<HTMLElement, IRelatedInformation>(); + private readonly _disposables: IDisposable[] = []; + + constructor(parent: HTMLElement, editor: ICodeEditor, onRelatedInformation: (related: IRelatedInformation) => void, ) { + this._editor = editor; + + const domNode = document.createElement('div'); + domNode.className = 'descriptioncontainer'; + domNode.setAttribute('aria-live', 'assertive'); + domNode.setAttribute('role', 'alert'); + + this._messageBlock = document.createElement('span'); + domNode.appendChild(this._messageBlock); + + this._relatedBlock = document.createElement('div'); + domNode.appendChild(this._relatedBlock); + this._disposables.push(dom.addStandardDisposableListener(this._relatedBlock, 'click', event => { + event.preventDefault(); + const related = this._relatedDiagnostics.get(event.target); + if (related) { + onRelatedInformation(related); + } + })); + + this._scrollable = new ScrollableElement(domNode, { + horizontal: ScrollbarVisibility.Auto, + vertical: ScrollbarVisibility.Hidden, + useShadows: false, + horizontalScrollbarSize: 3 + }); + dom.addClass(this._scrollable.getDomNode(), 'block'); + parent.appendChild(this._scrollable.getDomNode()); + this._disposables.push(this._scrollable.onScroll(e => domNode.style.left = `-${e.scrollLeft}px`)); + this._disposables.push(this._scrollable); + } + + dispose(): void { + dispose(this._disposables); + } + + update({ source, message, relatedInformation }: IMarker): void { + + if (source) { + this.lines = 0; + this.longestLineLength = 0; + const indent = new Array(source.length + 3 + 1).join(' '); + const lines = message.split(/\r\n|\r|\n/g); + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + this.lines += 1; + this.longestLineLength = Math.max(line.length, this.longestLineLength); + if (i === 0) { + message = `[${source}] ${line}`; + } else { + message += `\n${indent}${line}`; + } + } + } else { + this.lines = 1; + this.longestLineLength = message.length; + } + + dom.clearNode(this._relatedBlock); + + if (!isFalsyOrEmpty(relatedInformation)) { + this._relatedBlock.style.paddingTop = `${Math.floor(this._editor.getConfiguration().lineHeight * .66)}px`; + this.lines += 1; + + for (const related of relatedInformation) { + + let container = document.createElement('div'); + + let relatedResource = document.createElement('span'); + dom.addClass(relatedResource, 'filename'); + relatedResource.innerHTML = `${getBaseLabel(related.resource)}(${related.startLineNumber}, ${related.startColumn}): `; + relatedResource.title = getPathLabel(related.resource); + this._relatedDiagnostics.set(relatedResource, related); + + let relatedMessage = document.createElement('span'); + relatedMessage.innerText = related.message; + this._editor.applyFontInfo(relatedMessage); + + container.appendChild(relatedResource); + container.appendChild(relatedMessage); + + this.lines += 1; + this._relatedBlock.appendChild(container); + } + } + + this._messageBlock.innerText = message; + this._editor.applyFontInfo(this._messageBlock); + const width = Math.floor(this._editor.getConfiguration().fontInfo.typicalFullwidthCharacterWidth * this.longestLineLength); + this._scrollable.setScrollDimensions({ scrollWidth: width }); + } + + layout(height: number, width: number): void { + this._scrollable.setScrollDimensions({ width }); + } +} + +export class MarkerNavigationWidget extends ZoneWidget { + + private _parentContainer: HTMLElement; + private _container: HTMLElement; + private _title: HTMLElement; + private _message: MessageWidget; + private _callOnDispose: IDisposable[] = []; + private _severity: MarkerSeverity; + private _backgroundColor: Color; + private _onDidSelectRelatedInformation = new Emitter<IRelatedInformation>(); + + readonly onDidSelectRelatedInformation: Event<IRelatedInformation> = this._onDidSelectRelatedInformation.event; + + constructor( + editor: ICodeEditor, + private _themeService: IThemeService + ) { + super(editor, { showArrow: true, showFrame: true, isAccessible: true }); + this._severity = MarkerSeverity.Warning; + this._backgroundColor = Color.white; + + this._applyTheme(_themeService.getTheme()); + this._callOnDispose.push(_themeService.onThemeChange(this._applyTheme.bind(this))); + + this.create(); + } + + private _applyTheme(theme: ITheme) { + this._backgroundColor = theme.getColor(editorMarkerNavigationBackground); + let colorId = editorMarkerNavigationError; + if (this._severity === MarkerSeverity.Warning) { + colorId = editorMarkerNavigationWarning; + } else if (this._severity === MarkerSeverity.Info) { + colorId = editorMarkerNavigationInfo; + } + let frameColor = theme.getColor(colorId); + this.style({ + arrowColor: frameColor, + frameColor: frameColor + }); // style() will trigger _applyStyles + } + + protected _applyStyles(): void { + if (this._parentContainer) { + this._parentContainer.style.backgroundColor = this._backgroundColor.toString(); + } + super._applyStyles(); + } + + dispose(): void { + this._callOnDispose = dispose(this._callOnDispose); + super.dispose(); + } + + focus(): void { + this._parentContainer.focus(); + } + + protected _fillContainer(container: HTMLElement): void { + this._parentContainer = container; + dom.addClass(container, 'marker-widget'); + this._parentContainer.tabIndex = 0; + this._parentContainer.setAttribute('role', 'tooltip'); + + this._container = document.createElement('div'); + container.appendChild(this._container); + + this._title = document.createElement('div'); + this._title.className = 'block title'; + this._container.appendChild(this._title); + + this._message = new MessageWidget(this._container, this.editor, related => this._onDidSelectRelatedInformation.fire(related)); + this._disposables.push(this._message); + } + + show(where: Position, heightInLines: number): void { + throw new Error('call showAtMarker'); + } + + showAtMarker(marker: IMarker, markerIdx: number, markerCount: number): void { + // update: + // * title + // * message + this._container.classList.remove('stale'); + this._title.innerHTML = nls.localize('title.wo_source', "({0}/{1})", markerIdx, markerCount); + this._message.update(marker); + + // update frame color (only applied on 'show') + this._severity = marker.severity; + this._applyTheme(this._themeService.getTheme()); + + // show + let range = Range.lift(marker); + let position = range.containsPosition(this.editor.getPosition()) ? this.editor.getPosition() : range.getStartPosition(); + super.show(position, this.computeRequiredHeight()); + + this.editor.revealPositionInCenter(position, ScrollType.Smooth); + + if (this.editor.getConfiguration().accessibilitySupport !== AccessibilitySupport.Disabled) { + this.focus(); + } + } + + updateMarker(marker: IMarker): void { + this._container.classList.remove('stale'); + this._message.update(marker); + } + + showStale() { + this._container.classList.add('stale'); + this._relayout(); + } + + protected _doLayout(heightInPixel: number, widthInPixel: number): void { + this._message.layout(heightInPixel, widthInPixel); + this._container.style.height = `${heightInPixel}px`; + } + + protected _relayout(): void { + super._relayout(this.computeRequiredHeight()); + } + + private computeRequiredHeight() { + return 1 + this._message.lines; + } +} + +// theming + +let errorDefault = oneOf(editorErrorForeground, editorErrorBorder); +let warningDefault = oneOf(editorWarningForeground, editorWarningBorder); +let infoDefault = oneOf(editorInfoForeground, editorInfoBorder); + +export const editorMarkerNavigationError = registerColor('editorMarkerNavigationError.background', { dark: errorDefault, light: errorDefault, hc: errorDefault }, nls.localize('editorMarkerNavigationError', 'Editor marker navigation widget error color.')); +export const editorMarkerNavigationWarning = registerColor('editorMarkerNavigationWarning.background', { dark: warningDefault, light: warningDefault, hc: warningDefault }, nls.localize('editorMarkerNavigationWarning', 'Editor marker navigation widget warning color.')); +export const editorMarkerNavigationInfo = registerColor('editorMarkerNavigationInfo.background', { dark: infoDefault, light: infoDefault, hc: infoDefault }, nls.localize('editorMarkerNavigationInfo', 'Editor marker navigation widget info color.')); +export const editorMarkerNavigationBackground = registerColor('editorMarkerNavigation.background', { dark: '#2D2D30', light: Color.white, hc: '#0C141F' }, nls.localize('editorMarkerNavigationBackground', 'Editor marker navigation widget background.')); diff --git a/src/vs/editor/contrib/hover/hover.ts b/src/vs/editor/contrib/hover/hover.ts index 5eca5b2232..e2b62c2295 100644 --- a/src/vs/editor/contrib/hover/hover.ts +++ b/src/vs/editor/contrib/hover/hover.ts @@ -19,10 +19,11 @@ import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/brows import { ModesContentHoverWidget } from './modesContentHover'; import { ModesGlyphHoverWidget } from './modesGlyphHover'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; import { editorHoverHighlight, editorHoverBackground, editorHoverBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer'; +import { IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget'; export class ModesHoverController implements editorCommon.IEditorContribution { @@ -57,7 +58,8 @@ export class ModesHoverController implements editorCommon.IEditorContribution { constructor(editor: ICodeEditor, @IOpenerService private readonly _openerService: IOpenerService, - @IModeService private readonly _modeService: IModeService + @IModeService private readonly _modeService: IModeService, + @IThemeService private readonly _themeService: IThemeService ) { this._editor = editor; @@ -113,8 +115,8 @@ export class ModesHoverController implements editorCommon.IEditorContribution { } private _onEditorMouseMove(mouseEvent: IEditorMouseEvent): void { - var targetType = mouseEvent.target.type; - var stopKey = platform.isMacintosh ? 'metaKey' : 'ctrlKey'; + let targetType = mouseEvent.target.type; + let stopKey = platform.isMacintosh ? 'metaKey' : 'ctrlKey'; if (this._isMouseDown && this._hoverClicked && this.contentWidget.isColorPickerVisible()) { return; @@ -130,6 +132,15 @@ export class ModesHoverController implements editorCommon.IEditorContribution { return; } + if (targetType === MouseTargetType.CONTENT_EMPTY) { + const epsilon = this._editor.getConfiguration().fontInfo.typicalHalfwidthCharacterWidth / 2; + const data = <IEmptyContentData>mouseEvent.target.detail; + if (data && !data.isAfterLines && typeof data.horizontalDistanceToText === 'number' && data.horizontalDistanceToText < epsilon) { + // Let hover kick in even when the mouse is technically in the empty area after a line, given the distance is small enough + targetType = MouseTargetType.CONTENT_TEXT; + } + } + if (this._editor.getConfiguration().contribInfo.hover && targetType === MouseTargetType.CONTENT_TEXT) { this.glyphWidget.hide(); this.contentWidget.startShowingAt(mouseEvent.target.range, false); @@ -159,7 +170,7 @@ export class ModesHoverController implements editorCommon.IEditorContribution { private _createHoverWidget() { const renderer = new MarkdownRenderer(this._editor, this._modeService, this._openerService); - this._contentWidget = new ModesContentHoverWidget(this._editor, renderer); + this._contentWidget = new ModesContentHoverWidget(this._editor, renderer, this._themeService); this._glyphWidget = new ModesGlyphHoverWidget(this._editor, renderer); } @@ -189,11 +200,17 @@ class ShowHoverAction extends EditorAction { constructor() { super({ id: 'editor.action.showHover', - label: nls.localize('showHover', "Show Hover"), + label: nls.localize({ + key: 'showHover', + comment: [ + 'Label for action that will trigger the showing of a hover in the editor.', + 'This allows for users to show the hover without using the mouse.' + ] + }, "Show Hover"), alias: 'Show Hover', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_I) } }); diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 361d13365d..11f46ec950 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -23,6 +23,7 @@ import { ColorDetector } from 'vs/editor/contrib/colorPicker/colorDetector'; import { Color, RGBA } from 'vs/base/common/color'; import { IDisposable, empty as EmptyDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { getColorPresentations } from 'vs/editor/contrib/colorPicker/color'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; const $ = dom.$; class ColorHover { @@ -169,7 +170,11 @@ export class ModesContentHoverWidget extends ContentHoverWidget { private renderDisposable: IDisposable = EmptyDisposable; private toDispose: IDisposable[] = []; - constructor(editor: ICodeEditor, markdownRenderner: MarkdownRenderer) { + constructor( + editor: ICodeEditor, + markdownRenderner: MarkdownRenderer, + private readonly _themeService: IThemeService + ) { super(ModesContentHoverWidget.ID, editor); this._computer = new ModesContentComputer(this._editor); @@ -300,6 +305,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { isEmptyHoverContent = true; let containColorPicker = false; + let markdownDisposeable: IDisposable; messages.forEach((msg) => { if (!msg.range) { return; @@ -313,7 +319,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget { .filter(contents => !isEmptyMarkdownString(contents)) .forEach(contents => { const renderedContents = this._markdownRenderer.render(contents); - fragment.appendChild($('div.hover-row', null, renderedContents)); + markdownDisposeable = renderedContents; + fragment.appendChild($('div.hover-row', null, renderedContents.element)); isEmptyHoverContent = false; }); } else { @@ -329,7 +336,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { // create blank olor picker model and widget first to ensure it's positioned correctly. const model = new ColorPickerModel(color, [], 0); - const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio); + const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio, this._themeService); getColorPresentations(editorModel, colorInfo, msg.provider).then(colorPresentations => { model.colorPresentations = colorPresentations; @@ -388,7 +395,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this.updateContents(fragment); this._colorPicker.layout(); - this.renderDisposable = combinedDisposable([colorListener, colorChangeListener, widget]); + this.renderDisposable = combinedDisposable([colorListener, colorChangeListener, widget, markdownDisposeable]); }); } }); diff --git a/src/vs/editor/contrib/hover/modesGlyphHover.ts b/src/vs/editor/contrib/hover/modesGlyphHover.ts index 64bdfdb445..40f814cb08 100644 --- a/src/vs/editor/contrib/hover/modesGlyphHover.ts +++ b/src/vs/editor/contrib/hover/modesGlyphHover.ts @@ -10,6 +10,7 @@ import { GlyphHoverWidget } from './hoverWidgets'; import { $ } from 'vs/base/browser/dom'; import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer'; import { IMarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; export interface IHoverMessage { value: IMarkdownString; @@ -91,6 +92,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget { private _markdownRenderer: MarkdownRenderer; private _computer: MarginComputer; private _hoverOperation: HoverOperation<IHoverMessage[]>; + private _renderDisposeables: IDisposable[]; constructor(editor: ICodeEditor, markdownRenderer: MarkdownRenderer) { super(ModesGlyphHoverWidget.ID, editor); @@ -110,6 +112,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget { } public dispose(): void { + this._renderDisposeables = dispose(this._renderDisposeables); this._hoverOperation.cancel(); super.dispose(); } @@ -156,12 +159,15 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget { } private _renderMessages(lineNumber: number, messages: IHoverMessage[]): void { + dispose(this._renderDisposeables); + this._renderDisposeables = []; const fragment = document.createDocumentFragment(); messages.forEach((msg) => { const renderedContents = this._markdownRenderer.render(msg.value); - fragment.appendChild($('div.hover-row', null, renderedContents)); + this._renderDisposeables.push(renderedContents); + fragment.appendChild($('div.hover-row', null, renderedContents.element)); }); this.updateContents(fragment); diff --git a/src/vs/editor/contrib/inPlaceReplace/inPlaceReplace.ts b/src/vs/editor/contrib/inPlaceReplace/inPlaceReplace.ts index a94df31793..699db10a11 100644 --- a/src/vs/editor/contrib/inPlaceReplace/inPlaceReplace.ts +++ b/src/vs/editor/contrib/inPlaceReplace/inPlaceReplace.ts @@ -10,7 +10,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; -import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { registerEditorAction, ServicesAccessor, EditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { IInplaceReplaceSupportResult } from 'vs/editor/common/modes'; @@ -131,9 +130,7 @@ class InPlaceReplaceController implements IEditorContribution { this.decorationRemover.cancel(); this.decorationRemover = TPromise.timeout(350); this.decorationRemover.then(() => { - this.editor.changeDecorations((accessor: IModelDecorationsChangeAccessor) => { - this.decorationIds = accessor.deltaDecorations(this.decorationIds, []); - }); + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []); }); }); } @@ -148,7 +145,7 @@ class InPlaceReplaceUp extends EditorAction { alias: 'Replace with Previous Value', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_COMMA } }); @@ -172,7 +169,7 @@ class InPlaceReplaceDown extends EditorAction { alias: 'Replace with Next Value', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_DOT } }); diff --git a/src/vs/editor/contrib/indentation/indentation.ts b/src/vs/editor/contrib/indentation/indentation.ts index fd98361145..64c9636f4a 100644 --- a/src/vs/editor/contrib/indentation/indentation.ts +++ b/src/vs/editor/contrib/indentation/indentation.ts @@ -225,7 +225,7 @@ export class ChangeIndentationSizeAction extends EditorAction { return undefined; } - let creationOpts = modelService.getCreationOptions(model.getLanguageIdentifier().language, model.uri); + let creationOpts = modelService.getCreationOptions(model.getLanguageIdentifier().language, model.uri, model.isForSimpleWidget); const picks = [1, 2, 3, 4, 5, 6, 7, 8].map(n => ({ id: n.toString(), label: n.toString(), @@ -298,7 +298,7 @@ export class DetectIndentation extends EditorAction { return; } - let creationOpts = modelService.getCreationOptions(model.getLanguageIdentifier().language, model.uri); + let creationOpts = modelService.getCreationOptions(model.getLanguageIdentifier().language, model.uri, model.isForSimpleWidget); model.detectIndentation(creationOpts.insertSpaces, creationOpts.tabSize); } } @@ -586,18 +586,27 @@ function getIndentationEditOperations(model: ITextModel, builder: IEditOperation spaces += ' '; } - const content = model.getLinesContent(); - for (let i = 0; i < content.length; i++) { - let lastIndentationColumn = model.getLineFirstNonWhitespaceColumn(i + 1); + let spacesRegExp = new RegExp(spaces, 'gi'); + + for (let lineNumber = 1, lineCount = model.getLineCount(); lineNumber <= lineCount; lineNumber++) { + let lastIndentationColumn = model.getLineFirstNonWhitespaceColumn(lineNumber); if (lastIndentationColumn === 0) { - lastIndentationColumn = model.getLineMaxColumn(i + 1); + lastIndentationColumn = model.getLineMaxColumn(lineNumber); } - const text = (tabsToSpaces ? content[i].substr(0, lastIndentationColumn).replace(/\t/ig, spaces) : - content[i].substr(0, lastIndentationColumn).replace(new RegExp(spaces, 'gi'), '\t')) + - content[i].substr(lastIndentationColumn); + if (lastIndentationColumn === 1) { + continue; + } - builder.addEditOperation(new Range(i + 1, 1, i + 1, model.getLineMaxColumn(i + 1)), text); + const originalIndentationRange = new Range(lineNumber, 1, lineNumber, lastIndentationColumn); + const originalIndentation = model.getValueInRange(originalIndentationRange); + const newIndentation = ( + tabsToSpaces + ? originalIndentation.replace(/\t/ig, spaces) + : originalIndentation.replace(spacesRegExp, '\t') + ); + + builder.addEditOperation(originalIndentationRange, newIndentation); } } diff --git a/src/vs/editor/contrib/indentation/test/indentation.test.ts b/src/vs/editor/contrib/indentation/test/indentation.test.ts index e4a0a0d9e5..51f219ac45 100644 --- a/src/vs/editor/contrib/indentation/test/indentation.test.ts +++ b/src/vs/editor/contrib/indentation/test/indentation.test.ts @@ -57,7 +57,7 @@ suite('Editor Contrib - Indentation to Spaces', () => { 'fourth line', 'fifth' ], - new Selection(1, 5, 1, 5) + new Selection(1, 9, 1, 9) ); }); @@ -79,7 +79,7 @@ suite('Editor Contrib - Indentation to Spaces', () => { ' fourth line', 'fifth' ], - new Selection(1, 5, 1, 5) + new Selection(1, 7, 1, 7) ); }); @@ -157,7 +157,7 @@ suite('Editor Contrib - Indentation to Tabs', () => { ' fourth line', 'fifth' ], - new Selection(1, 5, 1, 5), + new Selection(1, 8, 1, 8), 2, [ '\t\t\tfirst ', @@ -169,4 +169,18 @@ suite('Editor Contrib - Indentation to Tabs', () => { new Selection(1, 5, 1, 5) ); }); + + test('issue #45996', function () { + testIndentationToSpacesCommand( + [ + '\tabc', + ], + new Selection(1, 3, 1, 3), + 4, + [ + ' abc', + ], + new Selection(1, 6, 1, 6) + ); + }); }); diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index e0dc198954..f5c469cc3a 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -58,7 +58,7 @@ class CopyLinesUpAction extends AbstractCopyLinesAction { alias: 'Copy Line Up', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyMod.Shift | KeyCode.UpArrow, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.UpArrow } } @@ -74,7 +74,7 @@ class CopyLinesDownAction extends AbstractCopyLinesAction { alias: 'Copy Line Down', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyMod.Shift | KeyCode.DownArrow, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.DownArrow } } @@ -117,7 +117,7 @@ class MoveLinesUpAction extends AbstractMoveLinesAction { alias: 'Move Line Up', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.UpArrow, linux: { primary: KeyMod.Alt | KeyCode.UpArrow } } @@ -133,7 +133,7 @@ class MoveLinesDownAction extends AbstractMoveLinesAction { alias: 'Move Line Down', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.DownArrow, linux: { primary: KeyMod.Alt | KeyCode.DownArrow } } @@ -203,7 +203,7 @@ export class TrimTrailingWhitespaceAction extends EditorAction { alias: 'Trim Trailing Whitespace', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_X) } }); @@ -286,7 +286,7 @@ class DeleteLinesAction extends AbstractRemoveLinesAction { alias: 'Delete Line', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_K } }); @@ -315,7 +315,7 @@ export class IndentLinesAction extends EditorAction { alias: 'Indent Line', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET } }); @@ -336,7 +336,7 @@ class OutdentLinesAction extends EditorAction { alias: 'Outdent Line', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET } }); @@ -355,7 +355,7 @@ export class InsertLineBeforeAction extends EditorAction { alias: 'Insert Line Above', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter } }); @@ -375,7 +375,7 @@ export class InsertLineAfterAction extends EditorAction { alias: 'Insert Line Below', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.Enter } }); @@ -434,7 +434,7 @@ export class DeleteAllLeftAction extends AbstractDeleteAllToBoundaryAction { alias: 'Delete All Left', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: null, mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace } } @@ -487,7 +487,7 @@ export class DeleteAllRightAction extends AbstractDeleteAllToBoundaryAction { alias: 'Delete All Right', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: null, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_K, secondary: [KeyMod.CtrlCmd | KeyCode.Delete] } } @@ -544,7 +544,7 @@ export class JoinLinesAction extends EditorAction { alias: 'Join Lines', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_J } } diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index b94689cf48..02ea2200e4 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -8,12 +8,12 @@ import * as assert from 'assert'; import { Selection } from 'vs/editor/common/core/selection'; import { Position } from 'vs/editor/common/core/position'; import { Handler } from 'vs/editor/common/editorCommon'; -import { ITextModel, DefaultEndOfLine } from 'vs/editor/common/model'; +import { ITextModel } from 'vs/editor/common/model'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction, DeleteAllRightAction, InsertLineBeforeAction, InsertLineAfterAction, IndentLinesAction, SortLinesAscendingAction, SortLinesDescendingAction } from 'vs/editor/contrib/linesOperations/linesOperations'; import { Cursor } from 'vs/editor/common/controller/cursor'; -import { TextModel } from 'vs/editor/common/model/textModel'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; +import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; suite('Editor Contrib - Line Operations', () => { suite('SortLinesAscendingAction', () => { @@ -746,16 +746,12 @@ suite('Editor Contrib - Line Operations', () => { test('Bug 18276:[editor] Indentation broken when selection is empty', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'function baz() {' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true } ); diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index e45c62ece3..5fa67ced3d 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -38,8 +38,17 @@ const HOVER_MESSAGE_COMMAND_META = new MarkdownString().appendText( : nls.localize('links.command', "Ctrl + click to execute command") ); -const HOVER_MESSAGE_GENERAL_ALT = new MarkdownString().appendText(nls.localize('links.navigate.al', "Alt + click to follow link")); -const HOVER_MESSAGE_COMMAND_ALT = new MarkdownString().appendText(nls.localize('links.command.al', "Alt + click to execute command")); +const HOVER_MESSAGE_GENERAL_ALT = new MarkdownString().appendText( + platform.isMacintosh + ? nls.localize('links.navigate.al.mac', "Option + click to follow link") + : nls.localize('links.navigate.al', "Alt + click to follow link") +); + +const HOVER_MESSAGE_COMMAND_ALT = new MarkdownString().appendText( + platform.isMacintosh + ? nls.localize('links.command.al.mac', "Option + click to execute command") + : nls.localize('links.command.al', "Alt + click to execute command") +); const decoration = { meta: ModelDecorationOptions.register({ @@ -242,32 +251,30 @@ class LinkDetector implements editorCommon.IEditorContribution { private updateDecorations(links: Link[]): void { const useMetaKey = (this.editor.getConfiguration().multiCursorModifier === 'altKey'); - this.editor.changeDecorations((changeAccessor: IModelDecorationsChangeAccessor) => { - var oldDecorations: string[] = []; - let keys = Object.keys(this.currentOccurrences); - for (let i = 0, len = keys.length; i < len; i++) { - let decorationId = keys[i]; - let occurance = this.currentOccurrences[decorationId]; - oldDecorations.push(occurance.decorationId); - } + let oldDecorations: string[] = []; + let keys = Object.keys(this.currentOccurrences); + for (let i = 0, len = keys.length; i < len; i++) { + let decorationId = keys[i]; + let occurance = this.currentOccurrences[decorationId]; + oldDecorations.push(occurance.decorationId); + } - var newDecorations: IModelDeltaDecoration[] = []; - if (links) { - // Not sure why this is sometimes null - for (var i = 0; i < links.length; i++) { - newDecorations.push(LinkOccurrence.decoration(links[i], useMetaKey)); - } + let newDecorations: IModelDeltaDecoration[] = []; + if (links) { + // Not sure why this is sometimes null + for (let i = 0; i < links.length; i++) { + newDecorations.push(LinkOccurrence.decoration(links[i], useMetaKey)); } + } - var decorations = changeAccessor.deltaDecorations(oldDecorations, newDecorations); + let decorations = this.editor.deltaDecorations(oldDecorations, newDecorations); - this.currentOccurrences = {}; - this.activeLinkDecorationId = null; - for (let i = 0, len = decorations.length; i < len; i++) { - var occurance = new LinkOccurrence(links[i], decorations[i]); - this.currentOccurrences[occurance.decorationId] = occurance; - } - }); + this.currentOccurrences = {}; + this.activeLinkDecorationId = null; + for (let i = 0, len = decorations.length; i < len; i++) { + let occurance = new LinkOccurrence(links[i], decorations[i]); + this.currentOccurrences[occurance.decorationId] = occurance; + } } private _onEditorMouseMove(mouseEvent: ClickLinkMouseEvent, withKey?: ClickLinkKeyboardEvent): void { diff --git a/src/vs/editor/contrib/markdown/markdownRenderer.ts b/src/vs/editor/contrib/markdown/markdownRenderer.ts index 5039a5e99a..06d7721b88 100644 --- a/src/vs/editor/contrib/markdown/markdownRenderer.ts +++ b/src/vs/editor/contrib/markdown/markdownRenderer.ts @@ -15,33 +15,39 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { optional } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; + +export interface IMarkdownRenderResult extends IDisposable { + element: HTMLElement; +} export class MarkdownRenderer { private _onDidRenderCodeBlock = new Emitter<void>(); readonly onDidRenderCodeBlock: Event<void> = this._onDidRenderCodeBlock.event; - private readonly _options: RenderOptions; - constructor( - editor: ICodeEditor, + private readonly _editor: ICodeEditor, @IModeService private readonly _modeService: IModeService, @optional(IOpenerService) private readonly _openerService: IOpenerService = NullOpenerService, ) { - this._options = { + } + + private getOptions(disposeables: IDisposable[]): RenderOptions { + return { codeBlockRenderer: (languageAlias, value): TPromise<string> => { // In markdown, // it is possible that we stumble upon language aliases (e.g.js instead of javascript) // it is possible no alias is given in which case we fall back to the current editor lang const modeId = languageAlias ? this._modeService.getModeIdForLanguageName(languageAlias) - : editor.getModel().getLanguageIdentifier().language; + : this._editor.getModel().getLanguageIdentifier().language; return this._modeService.getOrCreateMode(modeId).then(_ => { return tokenizeToString(value, modeId); }).then(code => { - return `<span style="font-family: ${editor.getConfiguration().fontInfo.fontFamily}">${code}</span>`; + return `<span style="font-family: ${this._editor.getConfiguration().fontInfo.fontFamily}">${code}</span>`; }); }, codeBlockRenderCallback: () => this._onDidRenderCodeBlock.fire(), @@ -49,16 +55,24 @@ export class MarkdownRenderer { callback: (content) => { this._openerService.open(URI.parse(content)).then(void 0, onUnexpectedError); }, - disposeables: [] // TODO + disposeables } }; } - render(markdown: IMarkdownString): HTMLElement { + render(markdown: IMarkdownString): IMarkdownRenderResult { + let disposeables: IDisposable[] = []; + + let element: HTMLElement; if (!markdown) { - return document.createElement('span'); + element = document.createElement('span'); + } else { + element = renderMarkdown(markdown, this.getOptions(disposeables)); } - return renderMarkdown(markdown, this._options); + return { + element, + dispose: () => dispose(disposeables) + }; } } diff --git a/src/vs/editor/contrib/message/messageController.ts b/src/vs/editor/contrib/message/messageController.ts index 3e412170a0..490d34b6f4 100644 --- a/src/vs/editor/contrib/message/messageController.ts +++ b/src/vs/editor/contrib/message/messageController.ts @@ -6,9 +6,10 @@ 'use strict'; import 'vs/css!./messageController'; +import * as nls from 'vs/nls'; import { setDisposableTimeout } from 'vs/base/common/async'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; @@ -20,11 +21,11 @@ import { registerThemingParticipant, HIGH_CONTRAST } from 'vs/platform/theme/com import { inputValidationInfoBorder, inputValidationInfoBackground } from 'vs/platform/theme/common/colorRegistry'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; -export class MessageController implements editorCommon.IEditorContribution { +export class MessageController extends Disposable implements editorCommon.IEditorContribution { private static readonly _id = 'editor.contrib.messageController'; - static CONTEXT_SNIPPET_MODE = new RawContextKey<boolean>('messageVisible', false); + static MESSAGE_VISIBLE = new RawContextKey<boolean>('messageVisible', false); static get(editor: ICodeEditor): MessageController { return editor.getContribution<MessageController>(MessageController._id); @@ -43,11 +44,14 @@ export class MessageController implements editorCommon.IEditorContribution { editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService ) { + super(); this._editor = editor; - this._visible = MessageController.CONTEXT_SNIPPET_MODE.bindTo(contextKeyService); + this._visible = MessageController.MESSAGE_VISIBLE.bindTo(contextKeyService); + this._register(this._editor.onDidAttemptReadOnlyEdit(() => this._onDidAttemptReadOnlyEdit())); } dispose(): void { + super.dispose(); this._visible.reset(); } @@ -96,6 +100,10 @@ export class MessageController implements editorCommon.IEditorContribution { this._messageListeners = dispose(this._messageListeners); this._messageListeners.push(MessageWidget.fadeOut(this._messageWidget)); } + + private _onDidAttemptReadOnlyEdit(): void { + this.showMessage(nls.localize('editor.readonly', "Cannot edit in read-only editor"), this._editor.getPosition()); + } } const MessageCommand = EditorCommand.bindToContribution<MessageController>(MessageController.get); @@ -103,7 +111,7 @@ const MessageCommand = EditorCommand.bindToContribution<MessageController>(Messa registerEditorCommand(new MessageCommand({ id: 'leaveEditorMessage', - precondition: MessageController.CONTEXT_SNIPPET_MODE, + precondition: MessageController.MESSAGE_VISIBLE, handler: c => c.closeMessage(), kbOpts: { weight: KeybindingsRegistry.WEIGHT.editorContrib(30), diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index 751eadc314..e32af3fa7c 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -34,7 +34,7 @@ export class InsertCursorAbove extends EditorAction { alias: 'Add Cursor Above', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.UpArrow, linux: { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.UpArrow, @@ -70,7 +70,7 @@ export class InsertCursorBelow extends EditorAction { alias: 'Add Cursor Below', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.DownArrow, linux: { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.DownArrow, @@ -107,35 +107,31 @@ class InsertCursorAtEndOfEachLineSelected extends EditorAction { alias: 'Add Cursors to Line Ends', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_I } }); } - private getCursorsForSelection(selection: Selection, editor: ICodeEditor): Selection[] { + private getCursorsForSelection(selection: Selection, model: ITextModel, result: Selection[]): void { if (selection.isEmpty()) { - return []; + return; } - let model = editor.getModel(); - let newSelections: Selection[] = []; for (let i = selection.startLineNumber; i < selection.endLineNumber; i++) { let currentLineMaxColumn = model.getLineMaxColumn(i); - newSelections.push(new Selection(i, currentLineMaxColumn, i, currentLineMaxColumn)); + result.push(new Selection(i, currentLineMaxColumn, i, currentLineMaxColumn)); } if (selection.endColumn > 1) { - newSelections.push(new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn)); + result.push(new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn)); } - - return newSelections; } public run(accessor: ServicesAccessor, editor: ICodeEditor): void { - let selections = editor.getSelections(); - let newSelections = selections - .map((selection) => this.getCursorsForSelection(selection, editor)) - .reduce((prev, curr) => { return prev.concat(curr); }); + const model = editor.getModel(); + const selections = editor.getSelections(); + let newSelections: Selection[] = []; + selections.forEach((sel) => this.getCursorsForSelection(sel, model, newSelections)); if (newSelections.length > 0) { editor.setSelections(newSelections); @@ -603,7 +599,7 @@ export class CompatChangeAll extends MultiCursorSelectionControllerAction { alias: 'Change All Occurrences', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyCode.F2 }, menuOpts: { @@ -803,9 +799,7 @@ export class SelectionHighlighter extends Disposable implements IEditorContribut this.state = state; if (!this.state) { - if (this.decorations.length > 0) { - this.decorations = this.editor.deltaDecorations(this.decorations, []); - } + this.decorations = this.editor.deltaDecorations(this.decorations, []); return; } diff --git a/src/vs/editor/contrib/parameterHints/parameterHints.ts b/src/vs/editor/contrib/parameterHints/parameterHints.ts index 57edc20704..0b60016678 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHints.ts @@ -67,7 +67,7 @@ export class TriggerParameterHintsAction extends EditorAction { alias: 'Trigger Parameter Hints', precondition: EditorContextKeys.hasSignatureHelpProvider, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Space } }); @@ -94,7 +94,7 @@ registerEditorCommand(new ParameterHintsCommand({ handler: x => x.cancel(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] } @@ -105,7 +105,7 @@ registerEditorCommand(new ParameterHintsCommand({ handler: x => x.previous(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.UpArrow, secondary: [KeyMod.Alt | KeyCode.UpArrow], mac: { primary: KeyCode.UpArrow, secondary: [KeyMod.Alt | KeyCode.UpArrow, KeyMod.WinCtrl | KeyCode.KEY_P] } @@ -117,7 +117,7 @@ registerEditorCommand(new ParameterHintsCommand({ handler: x => x.next(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.DownArrow, secondary: [KeyMod.Alt | KeyCode.DownArrow], mac: { primary: KeyCode.DownArrow, secondary: [KeyMod.Alt | KeyCode.DownArrow, KeyMod.WinCtrl | KeyCode.KEY_N] } diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index ea6b875bca..48c4295df7 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -6,16 +6,16 @@ 'use strict'; import 'vs/css!./parameterHints'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; -import aria = require('vs/base/browser/ui/aria/aria'); +import * as aria from 'vs/base/browser/ui/aria/aria'; import { SignatureHelp, SignatureInformation, SignatureHelpProviderRegistry } from 'vs/editor/common/modes'; import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; import { RunOnceScheduler } from 'vs/base/common/async'; import { onUnexpectedError } from 'vs/base/common/errors'; -import Event, { Emitter, chain } from 'vs/base/common/event'; +import { Event, Emitter, chain } from 'vs/base/common/event'; import { domEvent, stop } from 'vs/base/browser/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Context, provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp'; @@ -50,6 +50,7 @@ export class ParameterHintsModel extends Disposable { private triggerCharactersListeners: IDisposable[]; private active: boolean; private throttledDelayer: RunOnceScheduler; + private provideSignatureHelpRequest?: TPromise<boolean, any>; constructor(editor: ICodeEditor) { super(); @@ -80,6 +81,11 @@ export class ParameterHintsModel extends Disposable { if (!silent) { this._onCancel.fire(void 0); } + + if (this.provideSignatureHelpRequest) { + this.provideSignatureHelpRequest.cancel(); + this.provideSignatureHelpRequest = undefined; + } } trigger(delay = ParameterHintsModel.DELAY): void { @@ -92,7 +98,11 @@ export class ParameterHintsModel extends Disposable { } private doTrigger(): void { - provideSignatureHelp(this.editor.getModel(), this.editor.getPosition()) + if (this.provideSignatureHelpRequest) { + this.provideSignatureHelpRequest.cancel(); + } + + this.provideSignatureHelpRequest = provideSignatureHelp(this.editor.getModel(), this.editor.getPosition()) .then(null, onUnexpectedError) .then(result => { if (!result || !result.signatures || result.signatures.length === 0) { @@ -173,6 +183,7 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { private static readonly ID = 'editor.widget.parameterHintsWidget'; private markdownRenderer: MarkdownRenderer; + private renderDisposeables: IDisposable[]; private model: ParameterHintsModel; private keyVisible: IContextKey<boolean>; private keyMultipleSignatures: IContextKey<boolean>; @@ -337,6 +348,9 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { this.renderParameters(code, signature, this.hints.activeParameter); } + dispose(this.renderDisposeables); + this.renderDisposeables = []; + const activeParameter = signature.parameters[this.hints.activeParameter]; if (activeParameter && activeParameter.documentation) { @@ -346,7 +360,9 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { documentation.textContent = activeParameter.documentation; } else { dom.addClass(this.docs, 'markdown-docs'); - documentation.appendChild(this.markdownRenderer.render(activeParameter.documentation)); + const renderedContents = this.markdownRenderer.render(activeParameter.documentation); + this.renderDisposeables.push(renderedContents); + documentation.appendChild(renderedContents.element); } dom.append(this.docs, $('p', null, documentation)); } @@ -356,7 +372,9 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { if (typeof signature.documentation === 'string') { dom.append(this.docs, $('p', null, signature.documentation)); } else { - dom.append(this.docs, this.markdownRenderer.render(signature.documentation)); + const renderedContents = this.markdownRenderer.render(signature.documentation); + this.renderDisposeables.push(renderedContents); + dom.append(this.docs, renderedContents.element); } let currentOverload = String(this.currentSignature + 1); @@ -498,8 +516,12 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { dispose(): void { this.disposables = dispose(this.disposables); - this.model.dispose(); - this.model = null; + this.renderDisposeables = dispose(this.renderDisposeables); + + if (this.model) { + this.model.dispose(); + this.model = null; + } } } diff --git a/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts new file mode 100644 index 0000000000..d77bf4e80c --- /dev/null +++ b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import URI from 'vs/base/common/uri'; +import { Position } from 'vs/editor/common/core/position'; +import { ITextModel } from 'vs/editor/common/model'; +import { TextModel } from 'vs/editor/common/model/textModel'; +import { SignatureHelp, SignatureHelpProvider, SignatureHelpProviderRegistry } from 'vs/editor/common/modes'; +import { MockScopeLocation, TestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import { IStorageService, NullStorageService } from 'vs/platform/storage/common/storage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; +import { ParameterHintsModel } from '../parameterHintsWidget'; + +function createMockEditor(model: TextModel): TestCodeEditor { + const contextKeyService = new MockContextKeyService(); + const telemetryService = NullTelemetryService; + const notificationService = new TestNotificationService(); + const instantiationService = new InstantiationService(new ServiceCollection( + [IContextKeyService, contextKeyService], + [ITelemetryService, telemetryService], + [IStorageService, NullStorageService], + [INotificationService, TestNotificationService] + )); + + const editor = new TestCodeEditor(new MockScopeLocation(), {}, false, instantiationService, contextKeyService, notificationService); + editor.setModel(model); + return editor; +} + + +suite('ParameterHintsModel', () => { + let disposables: IDisposable[] = []; + + + setup(function () { + disposables = dispose(disposables); + }); + + test('Should cancel existing request when new request comes in', () => { + const textModel = TextModel.createFromString('abc def', undefined, undefined, URI.parse('test:somefile.ttt')); + disposables.push(textModel); + + const editor = createMockEditor(textModel); + const hintsModel = new ParameterHintsModel(editor); + + let didRequestCancellationOf = -1; + let invokeCount = 0; + const longRunningProvider = new class implements SignatureHelpProvider { + signatureHelpTriggerCharacters: string[] = []; + + provideSignatureHelp(model: ITextModel, position: Position, token: CancellationToken): SignatureHelp | Thenable<SignatureHelp> { + const count = invokeCount++; + token.onCancellationRequested(() => { didRequestCancellationOf = count; }); + + // retrigger on first request + if (count === 0) { + hintsModel.trigger(0); + } + + return new Promise<SignatureHelp>(resolve => { + setTimeout(() => { + resolve({ + signatures: [{ + label: '' + count, + parameters: [] + }], + activeParameter: 0, + activeSignature: 0 + }); + }, 100); + }); + } + }; + + disposables.push(SignatureHelpProviderRegistry.register({ scheme: 'test' }, longRunningProvider)); + + hintsModel.trigger(0); + assert.strictEqual(-1, didRequestCancellationOf); + + return new Promise((resolve, reject) => + hintsModel.onHint(e => { + try { + assert.strictEqual(0, didRequestCancellationOf); + assert.strictEqual('1', e.hints.signatures[0].label); + resolve(); + } catch (e) { + reject(e); + } + })); + }); +}); diff --git a/src/vs/editor/contrib/referenceSearch/peekViewWidget.ts b/src/vs/editor/contrib/referenceSearch/peekViewWidget.ts index b8f969bf9b..e999f49478 100644 --- a/src/vs/editor/contrib/referenceSearch/peekViewWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/peekViewWidget.ts @@ -11,7 +11,7 @@ import { Action } from 'vs/base/common/actions'; import * as strings from 'vs/base/common/strings'; import * as objects from 'vs/base/common/objects'; import { $ } from 'vs/base/browser/builder'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as dom from 'vs/base/browser/dom'; import { ActionBar, IActionBarOptions } from 'vs/base/browser/ui/actionbar/actionbar'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -133,7 +133,7 @@ export abstract class PeekViewWidget extends ZoneWidget { const actionsContainer = $('.peekview-actions').appendTo(this._headElement); const actionBarOptions = this._getActionBarOptions(); - this._actionbarWidget = new ActionBar(actionsContainer, actionBarOptions); + this._actionbarWidget = new ActionBar(actionsContainer.getHTMLElement(), actionBarOptions); this._disposables.push(this._actionbarWidget); this._actionbarWidget.push(new Action('peekview.close', nls.localize('label.close', "Close"), 'close-peekview-action', true, () => { diff --git a/src/vs/editor/contrib/referenceSearch/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/referenceSearch.ts index 593e1d479a..87d014d9ac 100644 --- a/src/vs/editor/contrib/referenceSearch/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/referenceSearch.ts @@ -68,7 +68,7 @@ export class ReferenceAction extends EditorAction { PeekContext.notInPeekEditor, EditorContextKeys.isInEmbeddedEditor.toNegated()), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyCode.F12 }, menuOpts: { @@ -194,6 +194,54 @@ function withController(accessor: ServicesAccessor, fn: (controller: ReferencesC fn(controller); } +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'goToNextReference', + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(50), + primary: KeyCode.F4, + when: ctxReferenceSearchVisible, + handler(accessor) { + withController(accessor, controller => { + controller.goToNextOrPreviousReference(true); + }); + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'goToNextReferenceFromEmbeddedEditor', + weight: KeybindingsRegistry.WEIGHT.editorContrib(50), + primary: KeyCode.F4, + when: PeekContext.inPeekEditor, + handler(accessor) { + withController(accessor, controller => { + controller.goToNextOrPreviousReference(true); + }); + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'goToPreviousReference', + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(50), + primary: KeyMod.Shift | KeyCode.F4, + when: ctxReferenceSearchVisible, + handler(accessor) { + withController(accessor, controller => { + controller.goToNextOrPreviousReference(false); + }); + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'goToPreviousReferenceFromEmbeddedEditor', + weight: KeybindingsRegistry.WEIGHT.editorContrib(50), + primary: KeyMod.Shift | KeyCode.F4, + when: PeekContext.inPeekEditor, + handler(accessor) { + withController(accessor, controller => { + controller.goToNextOrPreviousReference(false); + }); + } +}); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'closeReferenceSearch', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(50), diff --git a/src/vs/editor/contrib/referenceSearch/referencesController.ts b/src/vs/editor/contrib/referenceSearch/referencesController.ts index 877ca45441..be5882263c 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesController.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesController.ts @@ -16,7 +16,6 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { ReferencesModel } from './referencesModel'; import { ReferenceWidget, LayoutData } from './referencesWidget'; import { Range } from 'vs/editor/common/core/range'; @@ -34,7 +33,7 @@ export interface RequestOptions { onGoto?: (reference: Location) => TPromise<any>; } -export class ReferencesController implements editorCommon.IEditorContribution { +export abstract class ReferencesController implements editorCommon.IEditorContribution { private static readonly ID = 'editor.contrib.referencesController'; @@ -52,6 +51,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { } public constructor( + private _defaultTreeKeyboardSupport: boolean, editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService, @IEditorService private readonly _editorService: IEditorService, @@ -103,7 +103,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { })); const storageKey = 'peekViewLayout'; const data = <LayoutData>JSON.parse(this._storageService.get(storageKey, undefined, '{}')); - this._widget = new ReferenceWidget(this._editor, data, this._textModelResolverService, this._contextService, this._themeService, this._instantiationService, this._environmentService); + this._widget = new ReferenceWidget(this._editor, this._defaultTreeKeyboardSupport, data, this._textModelResolverService, this._contextService, this._themeService, this._instantiationService, this._environmentService); this._widget.setTitle(nls.localize('labelLoading', "Loading...")); this._widget.show(range); this._disposables.push(this._widget.onDidClose(() => { @@ -155,16 +155,17 @@ export class ReferencesController implements editorCommon.IEditorContribution { // show widget return this._widget.setModel(this._model).then(() => { + if (this._widget) { // might have been closed + // set title + this._widget.setMetaTitle(options.getMetaTitle(this._model)); - // set title - this._widget.setMetaTitle(options.getMetaTitle(this._model)); - - // set 'best' selection - let uri = this._editor.getModel().uri; - let pos = new Position(range.startLineNumber, range.startColumn); - let selection = this._model.nearestReference(uri, pos); - if (selection) { - return this._widget.setSelection(selection); + // set 'best' selection + let uri = this._editor.getModel().uri; + let pos = new Position(range.startLineNumber, range.startColumn); + let selection = this._model.nearestReference(uri, pos); + if (selection) { + return this._widget.setSelection(selection); + } } return undefined; }); @@ -174,6 +175,19 @@ export class ReferencesController implements editorCommon.IEditorContribution { }); } + public async goToNextOrPreviousReference(fwd: boolean) { + if (this._model) { // can be called while still resolving... + let source = this._model.nearestReference(this._editor.getModel().uri, this._widget.position); + let target = this._model.nextOrPreviousReference(source, fwd); + let editorFocus = this._editor.isFocused(); + await this._widget.setSelection(target); + await this._gotoReference(target); + if (editorFocus) { + this._editor.focus(); + } + } + } + public closeWidget(): void { if (this._widget) { this._widget.dispose(); @@ -189,16 +203,16 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._requestIdPool += 1; // Cancel pending requests } - private _gotoReference(ref: Location): void { + private _gotoReference(ref: Location): TPromise<any> { this._widget.hide(); this._ignoreModelChangeEvent = true; - const { uri, range } = ref; + const range = Range.lift(ref.range).collapseToStart(); - this._editorService.openEditor({ - resource: uri, + return this._editorService.openEditor({ + resource: ref.uri, options: { selection: range } - }).done(openedEditor => { + }).then(openedEditor => { this._ignoreModelChangeEvent = false; if (!openedEditor || openedEditor.getControl() !== this._editor) { @@ -235,5 +249,3 @@ export class ReferencesController implements editorCommon.IEditorContribution { } } } - -registerEditorContribution(ReferencesController); diff --git a/src/vs/editor/contrib/referenceSearch/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/referencesModel.ts index 4f32d574ee..fea85433c1 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesModel.ts @@ -5,7 +5,7 @@ 'use strict'; import { localize } from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { basename, dirname } from 'vs/base/common/paths'; import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; @@ -253,20 +253,32 @@ export class ReferencesModel implements IDisposable { } } - public nextReference(reference: OneReference): OneReference { + public nextOrPreviousReference(reference: OneReference, next: boolean): OneReference { - var idx = reference.parent.children.indexOf(reference), - len = reference.parent.children.length, - totalLength = reference.parent.parent.groups.length; + let { parent } = reference; - if (idx + 1 < len || totalLength === 1) { - return reference.parent.children[(idx + 1) % len]; + let idx = parent.children.indexOf(reference); + let childCount = parent.children.length; + let groupCount = parent.parent.groups.length; + + if (groupCount === 1 || next && idx + 1 < childCount || !next && idx > 0) { + // cycling within one file + if (next) { + idx = (idx + 1) % childCount; + } else { + idx = (idx + childCount - 1) % childCount; + } + return parent.children[idx]; } - idx = reference.parent.parent.groups.indexOf(reference.parent); - idx = (idx + 1) % totalLength; - - return reference.parent.parent.groups[idx].children[0]; + idx = parent.parent.groups.indexOf(parent); + if (next) { + idx = (idx + 1) % groupCount; + return parent.parent.groups[idx].children[0]; + } else { + idx = (idx + groupCount - 1) % groupCount; + return parent.parent.groups[idx].children[parent.parent.groups[idx].children.length - 1]; + } } public nearestReference(resource: URI, position: Position): OneReference { diff --git a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts index c242fd8cec..3baa089359 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/referencesWidget'; import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import { getPathLabel } from 'vs/base/common/labels'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import * as strings from 'vs/base/common/strings'; @@ -35,7 +35,7 @@ import { FileReferences, OneReference, ReferencesModel } from './referencesModel import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { registerColor, activeContrastBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant, ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { attachListStyler, attachBadgeStyler } from 'vs/platform/theme/common/styler'; +import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import URI from 'vs/base/common/uri'; @@ -84,28 +84,25 @@ class DecorationsManager implements IDisposable { private _addDecorations(reference: FileReferences): void { this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged())); - this._editor.changeDecorations(accessor => { + const newDecorations: IModelDeltaDecoration[] = []; + const newDecorationsActualIndex: number[] = []; - const newDecorations: IModelDeltaDecoration[] = []; - const newDecorationsActualIndex: number[] = []; - - for (let i = 0, len = reference.children.length; i < len; i++) { - let oneReference = reference.children[i]; - if (this._decorationIgnoreSet.has(oneReference.id)) { - continue; - } - newDecorations.push({ - range: oneReference.range, - options: DecorationsManager.DecorationOptions - }); - newDecorationsActualIndex.push(i); + for (let i = 0, len = reference.children.length; i < len; i++) { + let oneReference = reference.children[i]; + if (this._decorationIgnoreSet.has(oneReference.id)) { + continue; } + newDecorations.push({ + range: oneReference.range, + options: DecorationsManager.DecorationOptions + }); + newDecorationsActualIndex.push(i); + } - const decorations = accessor.deltaDecorations([], newDecorations); - for (let i = 0; i < decorations.length; i++) { - this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]); - } - }); + const decorations = this._editor.deltaDecorations([], newDecorations); + for (let i = 0; i < decorations.length; i++) { + this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]); + } } private _onDecorationChanged(): void { @@ -143,21 +140,19 @@ class DecorationsManager implements IDisposable { } }); - this._editor.changeDecorations((accessor) => { - for (let i = 0, len = toRemove.length; i < len; i++) { - this._decorations.delete(toRemove[i]); - } - accessor.deltaDecorations(toRemove, []); - }); + for (let i = 0, len = toRemove.length; i < len; i++) { + this._decorations.delete(toRemove[i]); + } + this._editor.deltaDecorations(toRemove, []); } public removeDecorations(): void { - this._editor.changeDecorations(accessor => { - this._decorations.forEach((value, key) => { - accessor.removeDecoration(key); - }); - this._decorations.clear(); + let toRemove: string[] = []; + this._decorations.forEach((value, key) => { + toRemove.push(key); }); + this._editor.deltaDecorations(toRemove, []); + this._decorations.clear(); } } @@ -533,17 +528,18 @@ export class ReferenceWidget extends PeekViewWidget { constructor( editor: ICodeEditor, + private _defaultTreeKeyboardSupport: boolean, public layoutData: LayoutData, private _textModelResolverService: ITextModelService, private _contextService: IWorkspaceContextService, - private _themeService: IThemeService, + themeService: IThemeService, private _instantiationService: IInstantiationService, private _environmentService: IEnvironmentService ) { super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true }); - this._applyTheme(_themeService.getTheme()); - this._callOnDispose.push(_themeService.onThemeChange(this._applyTheme.bind(this))); + this._applyTheme(themeService.getTheme()); + this._callOnDispose.push(themeService.onThemeChange(this._applyTheme.bind(this))); this.create(); } @@ -575,7 +571,7 @@ export class ReferenceWidget extends PeekViewWidget { } focus(): void { - this._tree.DOMFocus(); + this._tree.domFocus(); } protected _onTitleClick(e: MouseEvent): void { @@ -635,7 +631,7 @@ export class ReferenceWidget extends PeekViewWidget { // tree container.div({ 'class': 'ref-tree inline' }, (div: Builder) => { - var controller = this._instantiationService.createInstance(Controller, { clickBehavior: ClickBehavior.ON_MOUSE_UP /* our controller already deals with this */ }); + var controller = this._instantiationService.createInstance(Controller, { keyboardSupport: this._defaultTreeKeyboardSupport, clickBehavior: ClickBehavior.ON_MOUSE_UP /* our controller already deals with this */ }); this._callOnDispose.push(controller); var config = <tree.ITreeConfiguration>{ @@ -651,7 +647,6 @@ export class ReferenceWidget extends PeekViewWidget { }; this._tree = this._instantiationService.createInstance(WorkbenchTree, div.getHTMLElement(), config, options); - this._callOnDispose.push(attachListStyler(this._tree, this._themeService)); ctxReferenceWidgetSearchTreeFocused.bindTo(this._tree.contextKeyService); @@ -659,7 +654,7 @@ export class ReferenceWidget extends PeekViewWidget { var onEvent = (element: any, kind: 'show' | 'goto' | 'side') => { if (element instanceof OneReference) { if (kind === 'show') { - this._revealReference(element); + this._revealReference(element, false); } this._onDidSelectReference.fire({ element, kind, source: 'tree' }); } @@ -711,7 +706,7 @@ export class ReferenceWidget extends PeekViewWidget { } public setSelection(selection: OneReference): TPromise<any> { - return this._revealReference(selection).then(() => { + return this._revealReference(selection, true).then(() => { // show in tree this._tree.setSelection([selection]); @@ -781,7 +776,7 @@ export class ReferenceWidget extends PeekViewWidget { return undefined; } - private _revealReference(reference: OneReference): TPromise<void> { + private async _revealReference(reference: OneReference, revealParent: boolean): TPromise<void> { // Update widget header if (reference.uri.scheme !== Schemas.inMemory) { @@ -792,6 +787,10 @@ export class ReferenceWidget extends PeekViewWidget { const promise = this._textModelResolverService.createModelReference(reference.uri); + if (revealParent) { + await this._tree.reveal(reference.parent); + } + return TPromise.join([promise, this._tree.reveal(reference)]).then(values => { const ref = values[0]; @@ -837,6 +836,7 @@ export const peekViewEditorGutterBackground = registerColor('peekViewEditorGutte export const peekViewResultsMatchHighlight = registerColor('peekViewResult.matchHighlightBackground', { dark: '#ea5c004d', light: '#ea5c004d', hc: null }, nls.localize('peekViewResultsMatchHighlight', 'Match highlight color in the peek view result list.')); export const peekViewEditorMatchHighlight = registerColor('peekViewEditor.matchHighlightBackground', { dark: '#ff8f0099', light: '#f5d802de', hc: null }, nls.localize('peekViewEditorMatchHighlight', 'Match highlight color in the peek view editor.')); +export const peekViewEditorMatchHighlightBorder = registerColor('peekViewEditor.matchHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('peekViewEditorMatchHighlightBorder', 'Match highlight border in the peek view editor.')); registerThemingParticipant((theme, collector) => { @@ -848,10 +848,13 @@ registerThemingParticipant((theme, collector) => { if (referenceHighlightColor) { collector.addRule(`.monaco-editor .reference-zone-widget .preview .reference-decoration { background-color: ${referenceHighlightColor}; }`); } + let referenceHighlightBorder = theme.getColor(peekViewEditorMatchHighlightBorder); + if (referenceHighlightBorder) { + collector.addRule(`.monaco-editor .reference-zone-widget .preview .reference-decoration { border: 2px solid ${referenceHighlightBorder}; box-sizing: border-box; }`); + } let hcOutline = theme.getColor(activeContrastBorder); if (hcOutline) { collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { border: 1px dotted ${hcOutline}; box-sizing: border-box; }`); - collector.addRule(`.monaco-editor .reference-zone-widget .preview .reference-decoration { border: 2px solid ${hcOutline}; box-sizing: border-box; }`); } let resultsBackground = theme.getColor(peekViewResultsBackground); if (resultsBackground) { diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index 74d7797072..8946b8d4ec 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -6,7 +6,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import { isPromiseCanceledError, illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors'; +import { illegalArgument } from 'vs/base/common/errors'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { TPromise } from 'vs/base/common/winjs.base'; import { IFileService } from 'vs/platform/files/common/files'; @@ -22,8 +22,8 @@ import RenameInputField from './renameInputField'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { optional } from 'vs/platform/instantiation/common/instantiation'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { sequence, asWinJsPromise } from 'vs/base/common/async'; -import { WorkspaceEdit, RenameProviderRegistry, RenameInitialValue } from 'vs/editor/common/modes'; +import { asWinJsPromise } from 'vs/base/common/async'; +import { WorkspaceEdit, RenameProviderRegistry, RenameProvider, RenameLocation } from 'vs/editor/common/modes'; import { Position } from 'vs/editor/common/core/position'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { Range } from 'vs/editor/common/core/range'; @@ -32,67 +32,65 @@ import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorS import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { INotificationService } from 'vs/platform/notification/common/notification'; +class RenameSkeleton { -export function rename(model: ITextModel, position: Position, newName: string): TPromise<WorkspaceEdit> { + private _provider: RenameProvider[]; - const supports = RenameProviderRegistry.ordered(model); - const rejects: string[] = []; - let hasResult = false; + constructor( + readonly model: ITextModel, + readonly position: Position + ) { + this._provider = RenameProviderRegistry.ordered(model); + } - const factory = supports.map(support => { - return (): TPromise<WorkspaceEdit> => { - if (!hasResult) { - return asWinJsPromise((token) => { - return support.provideRenameEdits(model, position, newName, token); - }).then(result => { - if (!result) { - // ignore - } else if (!result.rejectReason) { - hasResult = true; - return result; - } else { - rejects.push(result.rejectReason); - } - return undefined; - }); + hasProvider() { + return this._provider.length > 0; + } + + async resolveRenameLocation(): TPromise<RenameLocation> { + + let [provider] = this._provider; + let res: RenameLocation; + + if (provider.resolveRenameLocation) { + res = await asWinJsPromise(token => provider.resolveRenameLocation(this.model, this.position, token)); + } + + if (!res) { + let word = this.model.getWordAtPosition(this.position); + if (word) { + res = { + range: new Range(this.position.lineNumber, word.startColumn, this.position.lineNumber, word.endColumn), + text: word.word + }; } - return undefined; - }; - }); + } - return sequence(factory).then((values): WorkspaceEdit => { - let result = values[0]; - if (rejects.length > 0) { + return res; + } + + async provideRenameEdits(newName: string, i: number = 0, rejects: string[] = [], position: Position = this.position): TPromise<WorkspaceEdit> { + + if (i >= this._provider.length) { return { edits: undefined, rejectReason: rejects.join('\n') }; - } else if (!result) { - return { - edits: undefined, - rejectReason: nls.localize('no result', "No result.") - }; - } else { - return result; } - }); + + let provider = this._provider[i]; + let result = await asWinJsPromise((token) => provider.provideRenameEdits(this.model, this.position, newName, token)); + if (!result) { + return this.provideRenameEdits(newName, i + 1, rejects.concat(nls.localize('no result', "No result."))); + } else if (result.rejectReason) { + return this.provideRenameEdits(newName, i + 1, rejects.concat(result.rejectReason)); + } + return result; + } } -// TODO@joh -// merge this into above function to make we always -// use the same provider for resolving and renamin -function resolveInitialRenameValue(model: ITextModel, position: Position): TPromise<RenameInitialValue> { - const [first] = RenameProviderRegistry.ordered(model); - if (!first || typeof first.resolveInitialRenameValue !== 'function') { - return TPromise.as(null); - } - //Use first rename provider so that we always use the same for resolving the location and for the actual rename - return asWinJsPromise(token => first.resolveInitialRenameValue(model, position, token)).then(result => { - return !result ? undefined : result; - }, err => { - onUnexpectedExternalError(err); - return TPromise.wrapError<RenameInitialValue>(new Error('provider failed')); - }); +export async function rename(model: ITextModel, position: Position, newName: string): TPromise<WorkspaceEdit> { + return new RenameSkeleton(model, position).provideRenameEdits(newName); } // --- register actions and commands @@ -132,70 +130,48 @@ class RenameController implements IEditorContribution { } public async run(): TPromise<void> { - const selection = this.editor.getSelection(); - let lineNumber = selection.startLineNumber, - selectionStart = 0, - selectionEnd = 0, - wordRange: Range, - word: string; - - let initialValue = await resolveInitialRenameValue(this.editor.getModel(), this.editor.getPosition()); - - if (initialValue) { - lineNumber = initialValue.range.startLineNumber; - if (initialValue.text) { - word = initialValue.text; - } - else { - word = this.editor.getModel().getValueInRange(initialValue.range); - } - selectionEnd = word.length; - - if (!selection.isEmpty() && selection.startLineNumber === selection.endLineNumber) { - selectionStart = Math.max(0, selection.startColumn - initialValue.range.startColumn); - selectionEnd = Math.min(initialValue.range.endColumn, selection.endColumn) - initialValue.range.startColumn; - } - - wordRange = new Range( - lineNumber, - initialValue.range.startColumn, - lineNumber, - initialValue.range.endColumn - ); + const position = this.editor.getPosition(); + const skeleton = new RenameSkeleton(this.editor.getModel(), position); + let loc: RenameLocation; + try { + loc = await skeleton.resolveRenameLocation(); + } catch (e) { + MessageController.get(this.editor).showMessage(e, position); + return undefined; } - else { - const wordAtPosition = this.editor.getModel().getWordAtPosition(selection.getStartPosition()); - if (!wordAtPosition) { - return undefined; - } - word = wordAtPosition.word; - selectionEnd = word.length; + if (!loc) { + return undefined; + } - if (!selection.isEmpty() && selection.startLineNumber === selection.endLineNumber) { - selectionStart = Math.max(0, selection.startColumn - wordAtPosition.startColumn); - selectionEnd = Math.min(wordAtPosition.endColumn, selection.endColumn) - wordAtPosition.startColumn; - } + let selection = this.editor.getSelection(); + let selectionStart = 0; + let selectionEnd = loc.text.length; - wordRange = new Range( - lineNumber, - wordAtPosition.startColumn, - lineNumber, - wordAtPosition.endColumn - ); + if (!Range.isEmpty(selection) && !Range.spansMultipleLines(selection) && Range.containsRange(loc.range, selection)) { + selectionStart = Math.max(0, selection.startColumn - loc.range.startColumn); + selectionEnd = Math.min(loc.range.endColumn, selection.endColumn) - loc.range.startColumn; } this._renameInputVisible.set(true); - return this._renameInputField.getInput(wordRange, word, selectionStart, selectionEnd).then(newName => { + return this._renameInputField.getInput(loc.range, loc.text, selectionStart, selectionEnd).then(newNameOrFocusFlag => { this._renameInputVisible.reset(); + + if (typeof newNameOrFocusFlag === 'boolean') { + if (newNameOrFocusFlag) { + this.editor.focus(); + } + return undefined; + } + this.editor.focus(); const edit = new BulkEdit(this.editor, null, this._textModelResolverService, this._fileService); const state = new EditorState(this.editor, CodeEditorStateFlag.Position | CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection | CodeEditorStateFlag.Scroll); - const renameOperation = rename(this.editor.getModel(), this.editor.getPosition(), newName).then(result => { + const renameOperation = skeleton.provideRenameEdits(newNameOrFocusFlag, 0, [], Range.lift(loc.range).getStartPosition()).then(result => { if (result.rejectReason) { if (state.validate(this.editor)) { MessageController.get(this.editor).showMessage(result.rejectReason, this.editor.getPosition()); @@ -211,7 +187,7 @@ class RenameController implements IEditorContribution { this.editor.setSelection(selection); } // alert - alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", word, newName, edit.ariaMessage())); + alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc.text, newNameOrFocusFlag, edit.ariaMessage())); }); }, err => { @@ -224,12 +200,7 @@ class RenameController implements IEditorContribution { }, err => { this._renameInputVisible.reset(); - this.editor.focus(); - - if (!isPromiseCanceledError(err)) { - return TPromise.wrapError(err); - } - return undefined; + return TPromise.wrapError(err); }); } @@ -238,7 +209,7 @@ class RenameController implements IEditorContribution { } public cancelRenameInput(): void { - this._renameInputField.cancelInput(); + this._renameInputField.cancelInput(true); } } @@ -253,7 +224,7 @@ export class RenameAction extends EditorAction { alias: 'Rename Symbol', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasRenameProvider), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.F2 }, menuOpts: { diff --git a/src/vs/editor/contrib/rename/renameInputField.ts b/src/vs/editor/contrib/rename/renameInputField.ts index 195a3f5eb4..aef725153d 100644 --- a/src/vs/editor/contrib/rename/renameInputField.ts +++ b/src/vs/editor/contrib/rename/renameInputField.ts @@ -7,10 +7,9 @@ import 'vs/css!./renameInputField'; import { localize } from 'vs/nls'; -import { canceled } from 'vs/base/common/errors'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Range } from 'vs/editor/common/core/range'; +import { Range, IRange } from 'vs/editor/common/core/range'; import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { inputBackground, inputBorder, inputForeground, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; @@ -110,7 +109,7 @@ export default class RenameInputField implements IContentWidget, IDisposable { } private _currentAcceptInput: () => void = null; - private _currentCancelInput: () => void = null; + private _currentCancelInput: (focusEditor) => void = null; public acceptInput(): void { if (this._currentAcceptInput) { @@ -118,13 +117,13 @@ export default class RenameInputField implements IContentWidget, IDisposable { } } - public cancelInput(): void { + public cancelInput(focusEditor: boolean): void { if (this._currentCancelInput) { - this._currentCancelInput(); + this._currentCancelInput(focusEditor); } } - public getInput(where: Range, value: string, selectionStart: number, selectionEnd: number): TPromise<string> { + public getInput(where: IRange, value: string, selectionStart: number, selectionEnd: number): TPromise<string | boolean> { this._position = new Position(where.startLineNumber, where.startColumn); this._inputField.value = value; @@ -140,39 +139,41 @@ export default class RenameInputField implements IContentWidget, IDisposable { this._hide(); }; - return new TPromise<string>((c, e) => { + return new TPromise<string>(resolve => { - this._currentCancelInput = () => { + this._currentCancelInput = (focusEditor) => { this._currentAcceptInput = null; this._currentCancelInput = null; - e(canceled()); + resolve(focusEditor); return true; }; this._currentAcceptInput = () => { if (this._inputField.value.trim().length === 0 || this._inputField.value === value) { // empty or whitespace only or not changed - this.cancelInput(); + this.cancelInput(true); return; } this._currentAcceptInput = null; this._currentCancelInput = null; - c(this._inputField.value); + resolve(this._inputField.value); }; let onCursorChanged = () => { if (!Range.containsPosition(where, this._editor.getPosition())) { - this.cancelInput(); + this.cancelInput(true); } }; disposeOnDone.push(this._editor.onDidChangeCursorSelection(onCursorChanged)); - disposeOnDone.push(this._editor.onDidBlurEditor(() => this.cancelInput())); + disposeOnDone.push(this._editor.onDidBlurEditor(() => this.cancelInput(false))); this._show(); - }, this._currentCancelInput).then(newValue => { + }, () => { + this._currentCancelInput(true); + }).then(newValue => { always(); return newValue; }, err => { @@ -191,7 +192,7 @@ export default class RenameInputField implements IContentWidget, IDisposable { this._inputField.setSelectionRange( parseInt(this._inputField.getAttribute('selectionStart')), parseInt(this._inputField.getAttribute('selectionEnd'))); - }, 25); + }, 100); } private _hide(): void { diff --git a/src/vs/editor/contrib/smartSelect/smartSelect.ts b/src/vs/editor/contrib/smartSelect/smartSelect.ts index 4c72f80537..9761ec73da 100644 --- a/src/vs/editor/contrib/smartSelect/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/smartSelect.ts @@ -171,7 +171,7 @@ class GrowSelectionAction extends AbstractSmartSelect { alias: 'Expand Select', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyMod.Shift | KeyCode.RightArrow } } @@ -187,7 +187,7 @@ class ShrinkSelectionAction extends AbstractSmartSelect { alias: 'Shrink Select', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyMod.Shift | KeyCode.LeftArrow } } diff --git a/src/vs/editor/contrib/smartSelect/tokenSelectionSupport.ts b/src/vs/editor/contrib/smartSelect/tokenSelectionSupport.ts index 8a1edc99cc..43668292dd 100644 --- a/src/vs/editor/contrib/smartSelect/tokenSelectionSupport.ts +++ b/src/vs/editor/contrib/smartSelect/tokenSelectionSupport.ts @@ -24,7 +24,7 @@ export class TokenSelectionSupport { private _modelService: IModelService; - constructor( @IModelService modelService: IModelService) { + constructor(@IModelService modelService: IModelService) { this._modelService = modelService; } diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index 10812a2914..b52a663a05 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -14,6 +14,7 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { showSimpleSuggestions } from 'vs/editor/contrib/suggest/suggest'; import { ISuggestion } from 'vs/editor/common/modes'; import { Selection } from 'vs/editor/common/core/selection'; +import { Range } from 'vs/editor/common/core/range'; import { Choice } from 'vs/editor/contrib/snippet/snippetParser'; import { repeat } from 'vs/base/common/strings'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -203,6 +204,13 @@ export class SnippetController2 implements IEditorContribution { this._session.next(); this._updateState(); } + + getSessionEnclosingRange(): Range { + if (this._session) { + return this._session.getEnclosingRange(); + } + return undefined; + } } @@ -216,7 +224,7 @@ registerEditorCommand(new CommandCtor({ handler: ctrl => ctrl.next(), kbOpts: { weight: KeybindingsRegistry.WEIGHT.editorContrib(30), - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.Tab } })); @@ -226,7 +234,7 @@ registerEditorCommand(new CommandCtor({ handler: ctrl => ctrl.prev(), kbOpts: { weight: KeybindingsRegistry.WEIGHT.editorContrib(30), - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyCode.Tab } })); @@ -236,7 +244,7 @@ registerEditorCommand(new CommandCtor({ handler: ctrl => ctrl.cancel(), kbOpts: { weight: KeybindingsRegistry.WEIGHT.editorContrib(30), - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] } diff --git a/src/vs/editor/contrib/snippet/snippetParser.ts b/src/vs/editor/contrib/snippet/snippetParser.ts index 0181d0e9cb..1818431ffc 100644 --- a/src/vs/editor/contrib/snippet/snippetParser.ts +++ b/src/vs/editor/contrib/snippet/snippetParser.ts @@ -568,7 +568,7 @@ export class SnippetParser { if (marker instanceof Placeholder) { placeholderCount += 1; if (marker.isFinalTabstop) { - placeholderDefaultValues.set(0); + placeholderDefaultValues.set(0, undefined); } else if (!placeholderDefaultValues.has(marker.index) && marker.children.length > 0) { placeholderDefaultValues.set(marker.index, marker.children); } else { diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts index bf918af6c0..058c4b55df 100644 --- a/src/vs/editor/contrib/snippet/snippetSession.ts +++ b/src/vs/editor/contrib/snippet/snippetSession.ts @@ -50,7 +50,9 @@ export class OneSnippet { dispose(): void { if (this._placeholderDecorations) { - this._editor.changeDecorations(accessor => this._placeholderDecorations.forEach(handle => accessor.removeDecoration(handle))); + let toRemove: string[] = []; + this._placeholderDecorations.forEach(handle => toRemove.push(handle)); + this._editor.deltaDecorations(toRemove, []); } this._placeholderGroups.length = 0; } @@ -224,6 +226,20 @@ export class OneSnippet { this._placeholderGroups = groupBy(this._snippet.placeholders, Placeholder.compareByIndex); }); } + + public getEnclosingRange(): Range { + let result: Range; + const model = this._editor.getModel(); + this._placeholderDecorations.forEach((decorationId) => { + const placeholderRange = model.getDecorationRange(decorationId); + if (!result) { + result = placeholderRange; + } else { + result = result.plusRange(placeholderRange); + } + }); + return result; + } } export class SnippetSession { @@ -365,13 +381,15 @@ export class SnippetSession { const { edits, snippets } = SnippetSession.createEditsAndSnippets(this._editor, this._template, this._overwriteBefore, this._overwriteAfter, false); this._snippets = snippets; - this._editor.setSelections(model.pushEditOperations(this._editor.getSelections(), edits, undoEdits => { + const selections = model.pushEditOperations(this._editor.getSelections(), edits, undoEdits => { if (this._snippets[0].hasPlaceholder) { return this._move(true); } else { return undoEdits.map(edit => Selection.fromPositions(edit.range.getEndPosition())); } - })); + }); + this._editor.setSelections(selections); + this._editor.revealRange(selections[0]); } merge(template: string, overwriteBefore: number = 0, overwriteAfter: number = 0): void { @@ -506,4 +524,17 @@ export class SnippetSession { // have any left, we don't have a selection anymore return allPossibleSelections.size > 0; } + + public getEnclosingRange(): Range { + let result: Range; + for (const snippet of this._snippets) { + const snippetRange = snippet.getEnclosingRange(); + if (!result) { + result = snippetRange; + } else { + result = result.plusRange(snippetRange); + } + } + return result; + } } diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index b1611e187a..a10ced4ed8 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -5,6 +5,7 @@ 'use strict'; +import * as nls from 'vs/nls'; import { basename, dirname } from 'vs/base/common/paths'; import { ITextModel } from 'vs/editor/common/model'; import { Selection } from 'vs/editor/common/core/selection'; @@ -20,6 +21,10 @@ export const KnownSnippetVariableNames = Object.freeze({ 'CURRENT_HOUR': true, 'CURRENT_MINUTE': true, 'CURRENT_SECOND': true, + 'CURRENT_DAY_NAME': true, + 'CURRENT_DAY_NAME_SHORT': true, + 'CURRENT_MONTH_NAME': true, + 'CURRENT_MONTH_NAME_SHORT': true, 'SELECTION': true, 'CLIPBOARD': true, 'TM_SELECTED_TEXT': true, @@ -180,6 +185,11 @@ export class ClipboardBasedVariableResolver implements VariableResolver { export class TimeBasedVariableResolver implements VariableResolver { + private static readonly dayNames = [nls.localize('Sunday', "Sunday"), nls.localize('Monday', "Monday"), nls.localize('Tuesday', "Tuesday"), nls.localize('Wednesday', "Wednesday"), nls.localize('Thursday', "Thursday"), nls.localize('Friday', "Friday"), nls.localize('Saturday', "Saturday")]; + private static readonly dayNamesShort = [nls.localize('SundayShort', "Sun"), nls.localize('MondayShort', "Mon"), nls.localize('TuesdayShort', "Tue"), nls.localize('WednesdayShort', "Wed"), nls.localize('ThursdayShort', "Thu"), nls.localize('FridayShort', "Fri"), nls.localize('SaturdayShort', "Sat")]; + private static readonly monthNames = [nls.localize('January', "January"), nls.localize('February', "February"), nls.localize('March', "March"), nls.localize('April', "April"), nls.localize('May', "May"), nls.localize('June', "June"), nls.localize('July', "July"), nls.localize('August', "August"), nls.localize('September', "September"), nls.localize('October', "October"), nls.localize('November', "November"), nls.localize('December', "December")]; + private static readonly monthNamesShort = [nls.localize('JanuaryShort', "Jan"), nls.localize('FebruaryShort', "Feb"), nls.localize('MarchShort', "Mar"), nls.localize('AprilShort', "Apr"), nls.localize('MayShort', "May"), nls.localize('JuneShort', "Jun"), nls.localize('JulyShort', "Jul"), nls.localize('AugustShort', "Aug"), nls.localize('SeptemberShort', "Sep"), nls.localize('OctoberShort', "Oct"), nls.localize('NovemberShort', "Nov"), nls.localize('DecemberShort', "Dec")]; + resolve(variable: Variable): string { const { name } = variable; @@ -197,6 +207,14 @@ export class TimeBasedVariableResolver implements VariableResolver { return pad(new Date().getMinutes().valueOf(), 2); } else if (name === 'CURRENT_SECOND') { return pad(new Date().getSeconds().valueOf(), 2); + } else if (name === 'CURRENT_DAY_NAME') { + return TimeBasedVariableResolver.dayNames[new Date().getDay()]; + } else if (name === 'CURRENT_DAY_NAME_SHORT') { + return TimeBasedVariableResolver.dayNamesShort[new Date().getDay()]; + } else if (name === 'CURRENT_MONTH_NAME') { + return TimeBasedVariableResolver.monthNames[new Date().getMonth()]; + } else if (name === 'CURRENT_MONTH_NAME_SHORT') { + return TimeBasedVariableResolver.monthNamesShort[new Date().getMonth()]; } return undefined; diff --git a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts index 348d9b5953..94b402bbd0 100644 --- a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts @@ -276,7 +276,7 @@ suite('Snippet Variables Resolver', function () { assert.equal(variable.resolve(resolver), true, `${varName} failed to resolve`); } - test('Add time variables for snippets #41631', function () { + test('Add time variables for snippets #41631, #43140', function () { const resolver = new TimeBasedVariableResolver; @@ -287,5 +287,9 @@ suite('Snippet Variables Resolver', function () { assertVariableResolve3(resolver, 'CURRENT_HOUR'); assertVariableResolve3(resolver, 'CURRENT_MINUTE'); assertVariableResolve3(resolver, 'CURRENT_SECOND'); + assertVariableResolve3(resolver, 'CURRENT_DAY_NAME'); + assertVariableResolve3(resolver, 'CURRENT_DAY_NAME_SHORT'); + assertVariableResolve3(resolver, 'CURRENT_MONTH_NAME'); + assertVariableResolve3(resolver, 'CURRENT_MONTH_NAME_SHORT'); }); }); diff --git a/src/vs/editor/contrib/suggest/completionModel.ts b/src/vs/editor/contrib/suggest/completionModel.ts index 245802a918..bd4836e826 100644 --- a/src/vs/editor/contrib/suggest/completionModel.ts +++ b/src/vs/editor/contrib/suggest/completionModel.ts @@ -20,9 +20,9 @@ export interface ICompletionItem extends ISuggestionItem { /* __GDPR__FRAGMENT__ "ICompletionStats" : { - "suggestionCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "snippetCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "textCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "suggestionCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "snippetCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "textCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ // __GDPR__TODO__: This is a dynamically extensible structure which can not be declared statically. @@ -174,6 +174,7 @@ export class CompletionModel { // use a score of `-100` because that is out of the // bound of values `fuzzyScore` will return item.score = -100; + item.matches = undefined; } else if (typeof suggestion.filterText === 'string') { // when there is a `filterText` it must match the `word`. diff --git a/src/vs/editor/contrib/suggest/suggest.ts b/src/vs/editor/contrib/suggest/suggest.ts index 4c0be5ac6f..6f2dc82f55 100644 --- a/src/vs/editor/contrib/suggest/suggest.ts +++ b/src/vs/editor/contrib/suggest/suggest.ts @@ -210,13 +210,20 @@ registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, positio suggestions: [] }; + let resolving: Thenable<any>[] = []; + let maxItemsToResolve = args['maxItemsToResolve'] || 0; + return provideSuggestionItems(model, position).then(items => { - - for (const { container, suggestion } of items) { - result.incomplete = result.incomplete || container.incomplete; - result.suggestions.push(suggestion); + for (const item of items) { + if (resolving.length < maxItemsToResolve) { + resolving.push(item.resolve()); + } + result.incomplete = result.incomplete || item.container.incomplete; + result.suggestions.push(item.suggestion); } - + }).then(() => { + return TPromise.join(resolving); + }).then(() => { return result; }); }); diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index c773a655ed..6235a25ed0 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -222,7 +222,7 @@ export class SuggestController implements IEditorContribution { } else if (suggestion.command.id === TriggerSuggestAction.id) { // retigger - this._model.trigger({ auto: this._model.state === State.Auto }, true); + this._model.trigger({ auto: true }, true); } else { // exec command, done @@ -318,7 +318,7 @@ export class TriggerSuggestAction extends EditorAction { alias: 'Trigger Suggest', precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCompletionItemProvider), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Space, mac: { primary: KeyMod.WinCtrl | KeyCode.Space } } @@ -350,7 +350,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.acceptSelectedSuggestion(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Tab } })); @@ -361,7 +361,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.acceptSelectedSuggestion(), kbOpts: { weight: weight, - kbExpr: ContextKeyExpr.and(EditorContextKeys.textFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), + kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), primary: KeyCode.Enter } })); @@ -372,7 +372,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.cancelSuggestWidget(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] } @@ -384,7 +384,7 @@ registerEditorCommand(new SuggestCommand({ handler: c => c.selectNextSuggestion(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.DownArrow, secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow], mac: { primary: KeyCode.DownArrow, secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow, KeyMod.WinCtrl | KeyCode.KEY_N] } @@ -397,7 +397,7 @@ registerEditorCommand(new SuggestCommand({ handler: c => c.selectNextPageSuggestion(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.PageDown, secondary: [KeyMod.CtrlCmd | KeyCode.PageDown] } @@ -415,7 +415,7 @@ registerEditorCommand(new SuggestCommand({ handler: c => c.selectPrevSuggestion(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.UpArrow, secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow], mac: { primary: KeyCode.UpArrow, secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.WinCtrl | KeyCode.KEY_P] } @@ -428,7 +428,7 @@ registerEditorCommand(new SuggestCommand({ handler: c => c.selectPrevPageSuggestion(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.PageUp, secondary: [KeyMod.CtrlCmd | KeyCode.PageUp] } @@ -446,7 +446,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.toggleSuggestionDetails(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Space, mac: { primary: KeyMod.WinCtrl | KeyCode.Space } } @@ -458,7 +458,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.toggleSuggestionFocus(), kbOpts: { weight: weight, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Space, mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Space } } diff --git a/src/vs/editor/contrib/suggest/suggestMemory.ts b/src/vs/editor/contrib/suggest/suggestMemory.ts index bf2f6b0fdd..501ccc02f3 100644 --- a/src/vs/editor/contrib/suggest/suggestMemory.ts +++ b/src/vs/editor/contrib/suggest/suggestMemory.ts @@ -58,7 +58,7 @@ export class LRUMemory extends Memory { this._cache.set(key, { touch: this._seq++, type: item.suggestion.type, - insertText: undefined + insertText: item.suggestion.insertText }); } @@ -66,18 +66,24 @@ export class LRUMemory extends Memory { // in order of completions, select the first // that has been used in the past let { word } = model.getWordUntilPosition(pos); + if (word.length !== 0) { + return 0; + } + + let lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1); + if (/\s$/.test(lineSuffix)) { + return 0; + } let res = 0; let seq = -1; - if (word.length === 0) { - for (let i = 0; i < items.length; i++) { - const { suggestion } = items[i]; - const key = `${model.getLanguageIdentifier().language}/${suggestion.label}`; - const item = this._cache.get(key); - if (item && item.touch > seq && item.type === suggestion.type) { - seq = item.touch; - res = i; - } + for (let i = 0; i < items.length; i++) { + const { suggestion } = items[i]; + const key = `${model.getLanguageIdentifier().language}/${suggestion.label}`; + const item = this._cache.get(key); + if (item && item.touch > seq && item.type === suggestion.type && item.insertText === suggestion.insertText) { + seq = item.touch; + res = i; } } return res; @@ -192,7 +198,9 @@ export class SuggestMemories { try { const raw = this._storageService.get(`${this._storagePrefix}/${this._mode}`, StorageScope.WORKSPACE); - this._strategy.fromJSON(JSON.parse(raw)); + if (raw) { + this._strategy.fromJSON(JSON.parse(raw)); + } } catch (e) { // things can go wrong with JSON... } diff --git a/src/vs/editor/contrib/suggest/suggestModel.ts b/src/vs/editor/contrib/suggest/suggestModel.ts index 8da73668b5..2babc4e6d2 100644 --- a/src/vs/editor/contrib/suggest/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/suggestModel.ts @@ -7,12 +7,13 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { TimeoutTimer } from 'vs/base/common/async'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModel, IWordAtPosition } from 'vs/editor/common/model'; import { ISuggestSupport, SuggestRegistry, StandardTokenType, SuggestTriggerKind, SuggestContext } from 'vs/editor/common/modes'; import { Position } from 'vs/editor/common/core/position'; +import { Selection } from 'vs/editor/common/core/selection'; import { provideSuggestionItems, getSuggestionComparator, ISuggestionItem } from './suggest'; import { CompletionModel } from './completionModel'; import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; @@ -46,6 +47,7 @@ export class LineContext { } const pos = editor.getPosition(); model.tokenizeIfCheap(pos.lineNumber); + const word = model.getWordAtPosition(pos); if (!word) { return false; @@ -92,12 +94,12 @@ export class SuggestModel implements IDisposable { private _requestPromise: TPromise<void>; private _context: LineContext; - private _currentPosition: Position; + private _currentSelection: Selection; private _completionModel: CompletionModel; - private _onDidCancel: Emitter<ICancelEvent> = new Emitter<ICancelEvent>(); - private _onDidTrigger: Emitter<ITriggerEvent> = new Emitter<ITriggerEvent>(); - private _onDidSuggest: Emitter<ISuggestEvent> = new Emitter<ISuggestEvent>(); + private readonly _onDidCancel: Emitter<ICancelEvent> = new Emitter<ICancelEvent>(); + private readonly _onDidTrigger: Emitter<ITriggerEvent> = new Emitter<ITriggerEvent>(); + private readonly _onDidSuggest: Emitter<ISuggestEvent> = new Emitter<ISuggestEvent>(); readonly onDidCancel: Event<ICancelEvent> = this._onDidCancel.event; readonly onDidTrigger: Event<ITriggerEvent> = this._onDidTrigger.event; @@ -110,7 +112,7 @@ export class SuggestModel implements IDisposable { this._requestPromise = null; this._completionModel = null; this._context = null; - this._currentPosition = this._editor.getPosition() || new Position(1, 1); + this._currentSelection = this._editor.getSelection() || new Selection(1, 1, 1, 1); // wire up various listeners this._toDispose.push(this._editor.onDidChangeModel(() => { @@ -243,8 +245,8 @@ export class SuggestModel implements IDisposable { private _onCursorChange(e: ICursorSelectionChangedEvent): void { - const prevPosition = this._currentPosition; - this._currentPosition = this._editor.getPosition(); + const prevSelection = this._currentSelection; + this._currentSelection = this._editor.getSelection(); if (!e.selection.isEmpty() || e.reason !== CursorChangeReason.NotSet @@ -272,9 +274,9 @@ export class SuggestModel implements IDisposable { // trigger 24x7 IntelliSense when idle, enabled, when cursor // moved RIGHT, and when at a good position if (this._editor.getConfiguration().contribInfo.quickSuggestions !== false - && prevPosition.isBefore(this._currentPosition) + && (prevSelection.containsRange(this._currentSelection) + || prevSelection.getEndPosition().isBeforeOrEqual(this._currentSelection.getPosition())) ) { - this.cancel(); this._triggerAutoSuggestPromise = TPromise.timeout(this._quickSuggestDelay); @@ -404,6 +406,12 @@ export class SuggestModel implements IDisposable { return; } + if (ctx.leadingWord.startColumn < this._context.leadingWord.startColumn) { + // happens when the current word gets outdented + this.cancel(); + return; + } + if (ctx.column < this._context.column) { // typed -> moved cursor LEFT -> retrigger if still on a word if (ctx.leadingWord.word) { diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index fb99e0019b..3173fb9251 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -9,7 +9,7 @@ import 'vs/css!./media/suggest'; import * as nls from 'vs/nls'; import { createMatches } from 'vs/base/common/filters'; import * as strings from 'vs/base/common/strings'; -import Event, { Emitter, chain } from 'vs/base/common/event'; +import { Event, Emitter, chain } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; @@ -207,6 +207,7 @@ class SuggestionDetails { private docs: HTMLElement; private ariaLabel: string; private disposables: IDisposable[]; + private renderDisposeable: IDisposable; private borderWidth: number = 1; constructor( @@ -247,6 +248,8 @@ class SuggestionDetails { } render(item: ICompletionItem): void { + this.renderDisposeable = dispose(this.renderDisposeable); + if (!item || !canExpandCompletionItem(item)) { this.type.textContent = ''; this.docs.textContent = ''; @@ -261,7 +264,9 @@ class SuggestionDetails { } else { addClass(this.docs, 'markdown-docs'); this.docs.innerHTML = ''; - this.docs.appendChild(this.markdownRenderer.render(item.suggestion.documentation)); + const renderedContents = this.markdownRenderer.render(item.suggestion.documentation); + this.renderDisposeable = renderedContents; + this.docs.appendChild(renderedContents.element); } if (item.suggestion.detail) { @@ -338,6 +343,7 @@ class SuggestionDetails { dispose(): void { this.disposables = dispose(this.disposables); + this.renderDisposeable = dispose(this.renderDisposeable); } } @@ -361,7 +367,6 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> private isAuto: boolean; private loadingTimeout: number; private currentSuggestionDetails: TPromise<void>; - private focusedItemIndex: number; private focusedItem: ICompletionItem; private ignoreFocusEvents = false; private completionModel: CompletionModel; @@ -440,7 +445,8 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> this.list = new List(this.listElement, this, [renderer], { useShadows: false, selectOnMouseDown: true, - focusOnMouseDown: false + focusOnMouseDown: false, + openController: { shouldOpen: () => false } }); this.toDispose = [ @@ -592,27 +598,17 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> this.suggestionSupportsAutoAccept.set(!item.suggestion.noAutoAccept); - const oldFocus = this.focusedItem; - const oldFocusIndex = this.focusedItemIndex; - this.focusedItemIndex = index; this.focusedItem = item; - if (oldFocus) { - this.ignoreFocusEvents = true; - this.list.splice(oldFocusIndex, 1, [oldFocus]); - this.ignoreFocusEvents = false; - } - this.list.reveal(index); this.currentSuggestionDetails = item.resolve() .then(() => { + // item can have extra information, so re-render this.ignoreFocusEvents = true; this.list.splice(index, 1, [item]); - this.ignoreFocusEvents = false; - this.list.setFocus([index]); - this.list.reveal(index); + this.ignoreFocusEvents = false; if (this.expandDocsSettingFromStorage()) { this.showDetails(); @@ -641,6 +637,7 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> case State.Hidden: hide(this.messageElement, this.details.element, this.listElement); this.hide(); + this.listHeight = 0; if (stateChanged) { this.list.splice(0, this.list.length); } @@ -725,7 +722,7 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> stats['wasAutomaticallyTriggered'] = !!isAuto; /* __GDPR__ "suggestWidget" : { - "wasAutomaticallyTriggered" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "wasAutomaticallyTriggered" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "${include}": [ "${ICompletionStats}", "${EditorTelemetryData}" @@ -735,7 +732,6 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem> this.telemetryService.publicLog('suggestWidget', { ...stats, ...this.editor.getTelemetryData() }); this.focusedItem = null; - this.focusedItemIndex = null; this.list.splice(0, this.list.length, this.completionModel.items); if (isFrozen) { diff --git a/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts b/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts index 1716774819..86a2ce6b4c 100644 --- a/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts +++ b/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts @@ -21,7 +21,7 @@ suite('SuggestMemories', function () { setup(function () { pos = { lineNumber: 1, column: 1 }; - buffer = TextModel.createFromString('This is some text'); + buffer = TextModel.createFromString('This is some text.\nthis.\nfoo: ,'); items = [ createSuggestItem('foo', 0), createSuggestItem('bar', 0) @@ -39,7 +39,9 @@ suite('SuggestMemories', function () { mem.memorize(buffer, pos, null); }); - test('ShyMemories', function () { + test('LRUMemory', function () { + + pos = { lineNumber: 2, column: 6 }; const mem = new LRUMemory(); mem.memorize(buffer, pos, items[1]); @@ -59,7 +61,19 @@ suite('SuggestMemories', function () { createSuggestItem('new1', 0), createSuggestItem('new2', 0) ]), 0); + }); + test('intellisense is not showing top options first #43429', function () { + // ensure we don't memorize for whitespace prefixes + + pos = { lineNumber: 2, column: 6 }; + const mem = new LRUMemory(); + + mem.memorize(buffer, pos, items[1]); + assert.equal(mem.select(buffer, pos, items), 1); + + assert.equal(mem.select(buffer, { lineNumber: 3, column: 5 }, items), 0); // foo: |, + assert.equal(mem.select(buffer, { lineNumber: 3, column: 6 }, items), 1); // foo: ,| }); test('PrefixMemory', function () { diff --git a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts index eeaf8807a3..2f31f4a49c 100644 --- a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts +++ b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts @@ -5,12 +5,12 @@ 'use strict'; import * as assert from 'assert'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { TextModel } from 'vs/editor/common/model/textModel'; import { Handler } from 'vs/editor/common/editorCommon'; -import { ISuggestSupport, ISuggestResult, SuggestRegistry, SuggestTriggerKind } from 'vs/editor/common/modes'; +import { ISuggestSupport, ISuggestResult, SuggestRegistry, SuggestTriggerKind, LanguageIdentifier, TokenizationRegistry, IState, MetadataConsts } from 'vs/editor/common/modes'; import { SuggestModel, LineContext } from 'vs/editor/contrib/suggest/suggestModel'; import { TestCodeEditor, MockScopeLocation } from 'vs/editor/test/browser/testCodeEditor'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -21,54 +21,121 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Range } from 'vs/editor/common/core/range'; +import { Selection } from 'vs/editor/common/core/selection'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { IStorageService, NullStorageService } from 'vs/platform/storage/common/storage'; import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; import { ISelectedSuggestion } from 'vs/editor/contrib/suggest/suggestWidget'; +import { MockMode } from 'vs/editor/test/common/mocks/mockMode'; +import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { TokenizationResult2 } from 'vs/editor/common/core/token'; +import { NULL_STATE } from 'vs/editor/common/modes/nullMode'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; function createMockEditor(model: TextModel): TestCodeEditor { const contextKeyService = new MockContextKeyService(); const telemetryService = NullTelemetryService; + const notificationService = new TestNotificationService(); const instantiationService = new InstantiationService(new ServiceCollection( [IContextKeyService, contextKeyService], [ITelemetryService, telemetryService], - [IStorageService, NullStorageService] + [IStorageService, NullStorageService], + [INotificationService, TestNotificationService] )); - const editor = new TestCodeEditor(new MockScopeLocation(), {}, instantiationService, contextKeyService); + const editor = new TestCodeEditor(new MockScopeLocation(), {}, false, instantiationService, contextKeyService, notificationService); editor.setModel(model); return editor; } suite('SuggestModel - Context', function () { + const OUTER_LANGUAGE_ID = new LanguageIdentifier('outerMode', 3); + const INNER_LANGUAGE_ID = new LanguageIdentifier('innerMode', 4); - let model: TextModel; + class OuterMode extends MockMode { + constructor() { + super(OUTER_LANGUAGE_ID); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {})); - setup(function () { - model = TextModel.createFromString('Das Pferd frisst keinen Gurkensalat - Philipp Reis 1861.\nWer hat\'s erfunden?'); + this._register(TokenizationRegistry.register(this.getLanguageIdentifier().language, { + getInitialState: (): IState => NULL_STATE, + tokenize: undefined, + tokenize2: (line: string, state: IState): TokenizationResult2 => { + const tokensArr: number[] = []; + let prevLanguageId: LanguageIdentifier = undefined; + for (let i = 0; i < line.length; i++) { + const languageId = (line.charAt(i) === 'x' ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID); + if (prevLanguageId !== languageId) { + tokensArr.push(i); + tokensArr.push((languageId.id << MetadataConsts.LANGUAGEID_OFFSET)); + } + prevLanguageId = languageId; + } + + const tokens = new Uint32Array(tokensArr.length); + for (let i = 0; i < tokens.length; i++) { + tokens[i] = tokensArr[i]; + } + return new TokenizationResult2(tokens, state); + } + })); + } + } + + class InnerMode extends MockMode { + constructor() { + super(INNER_LANGUAGE_ID); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {})); + } + } + + const assertAutoTrigger = (model: TextModel, offset: number, expected: boolean, message?: string): void => { + const pos = model.getPositionAt(offset); + const editor = createMockEditor(model); + editor.setPosition(pos); + assert.equal(LineContext.shouldAutoTrigger(editor), expected, message); + editor.dispose(); + }; + + let disposables: Disposable[] = []; + + setup(() => { + disposables = []; }); teardown(function () { - model.dispose(); + dispose(disposables); + disposables = []; }); test('Context - shouldAutoTrigger', function () { + const model = TextModel.createFromString('Das Pferd frisst keinen Gurkensalat - Philipp Reis 1861.\nWer hat\'s erfunden?'); + disposables.push(model); - function assertAutoTrigger(offset: number, expected: boolean): void { - const pos = model.getPositionAt(offset); - const editor = createMockEditor(model); - editor.setPosition(pos); - assert.equal(LineContext.shouldAutoTrigger(editor), expected); - editor.dispose(); - } - - assertAutoTrigger(3, true); // end of word, Das| - assertAutoTrigger(4, false); // no word Das | - assertAutoTrigger(1, false); // middle of word D|as - assertAutoTrigger(55, false); // number, 1861| + assertAutoTrigger(model, 3, true, 'end of word, Das|'); + assertAutoTrigger(model, 4, false, 'no word Das |'); + assertAutoTrigger(model, 1, false, 'middle of word D|as'); + assertAutoTrigger(model, 55, false, 'number, 1861|'); }); + test('shouldAutoTrigger at embedded language boundaries', () => { + const outerMode = new OuterMode(); + const innerMode = new InnerMode(); + disposables.push(outerMode, innerMode); + + const model = TextModel.createFromString('a<xx>a<x>', undefined, outerMode.getLanguageIdentifier()); + disposables.push(model); + + assertAutoTrigger(model, 1, true, 'a|<x — should trigger at end of word'); + assertAutoTrigger(model, 2, false, 'a<|x — should NOT trigger at start of word'); + assertAutoTrigger(model, 3, false, 'a<x|x — should NOT trigger in middle of word'); + assertAutoTrigger(model, 4, true, 'a<xx|> — should trigger at boundary between languages'); + assertAutoTrigger(model, 5, false, 'a<xx>|a — should NOT trigger at start of word'); + assertAutoTrigger(model, 6, true, 'a<xx>a|< — should trigger at end of word'); + assertAutoTrigger(model, 8, true, 'a<xx>a<x|> — should trigger at end of word at boundary'); + }); }); suite('SuggestModel - TriggerAndCancelOracle', function () { @@ -616,4 +683,24 @@ suite('SuggestModel - TriggerAndCancelOracle', function () { ); }); }); + + test('Completion unexpectedly triggers on second keypress of an edit group in a snippet #43523', function () { + + disposables.push(SuggestRegistry.register({ scheme: 'test' }, alwaysSomethingSupport)); + + return withOracle((model, editor) => { + return assertEvent(model.onDidSuggest, () => { + editor.setValue('d'); + editor.setSelection(new Selection(1, 1, 1, 2)); + editor.trigger('keyboard', Handler.Type, { text: 'e' }); + + }, event => { + assert.equal(event.auto, true); + assert.equal(event.completionModel.items.length, 1); + const [first] = event.completionModel.items; + + assert.equal(first.support, alwaysSomethingSupport); + }); + }); + }); }); diff --git a/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts index 7640f7efa2..27abc92df3 100644 --- a/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { sequence, asWinJsPromise } from 'vs/base/common/async'; import { onUnexpectedExternalError } from 'vs/base/common/errors'; @@ -32,8 +32,8 @@ export const editorWordHighlightStrong = registerColor('editor.wordHighlightStro export const editorWordHighlightBorder = registerColor('editor.wordHighlightBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('wordHighlightBorder', 'Border color of a symbol during read-access, like reading a variable.')); export const editorWordHighlightStrongBorder = registerColor('editor.wordHighlightStrongBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('wordHighlightStrongBorder', 'Border color of a symbol during write-access, like writing to a variable.')); -export const overviewRulerWordHighlightForeground = registerColor('editorOverviewRuler.wordHighlightForeground', { dark: '#A0A0A0', light: '#A0A0A0', hc: '#A0A0A0' }, nls.localize('overviewRulerWordHighlightForeground', 'Overview ruler marker color for symbol highlights.')); -export const overviewRulerWordHighlightStrongForeground = registerColor('editorOverviewRuler.wordHighlightStrongForeground', { dark: '#C0A0C0', light: '#C0A0C0', hc: '#C0A0C0' }, nls.localize('overviewRulerWordHighlightStrongForeground', 'Overview ruler marker color for write-access symbol highlights.')); +export const overviewRulerWordHighlightForeground = registerColor('editorOverviewRuler.wordHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerWordHighlightForeground', 'Overview ruler marker color for symbol highlights. The color must not be opaque to not hide underlying decorations.'), true); +export const overviewRulerWordHighlightStrongForeground = registerColor('editorOverviewRuler.wordHighlightStrongForeground', { dark: '#C0A0C0CC', light: '#C0A0C0CC', hc: '#C0A0C0CC' }, nls.localize('overviewRulerWordHighlightStrongForeground', 'Overview ruler marker color for write-access symbol highlights. The color must not be opaque to not hide underlying decorations.'), true); export const ctxHasWordHighlights = new RawContextKey<boolean>('hasWordHighlights', false); @@ -477,7 +477,7 @@ class NextWordHighlightAction extends WordHighlightNavigationAction { alias: 'Go to Next Symbol Highlight', precondition: ctxHasWordHighlights, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.F7 } }); @@ -492,7 +492,7 @@ class PrevWordHighlightAction extends WordHighlightNavigationAction { alias: 'Go to Previous Symbol Highlight', precondition: ctxHasWordHighlights, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyCode.F7 } }); @@ -504,30 +504,34 @@ registerEditorAction(NextWordHighlightAction); registerEditorAction(PrevWordHighlightAction); registerThemingParticipant((theme, collector) => { - let selectionHighlight = theme.getColor(editorSelectionHighlight); + const selectionHighlight = theme.getColor(editorSelectionHighlight); if (selectionHighlight) { collector.addRule(`.monaco-editor .focused .selectionHighlight { background-color: ${selectionHighlight}; }`); collector.addRule(`.monaco-editor .selectionHighlight { background-color: ${selectionHighlight.transparent(0.5)}; }`); } - let wordHighlight = theme.getColor(editorWordHighlight); + + const wordHighlight = theme.getColor(editorWordHighlight); if (wordHighlight) { collector.addRule(`.monaco-editor .wordHighlight { background-color: ${wordHighlight}; }`); } - let wordHighlightStrong = theme.getColor(editorWordHighlightStrong); + + const wordHighlightStrong = theme.getColor(editorWordHighlightStrong); if (wordHighlightStrong) { collector.addRule(`.monaco-editor .wordHighlightStrong { background-color: ${wordHighlightStrong}; }`); } - let selectionHighlightBorder = theme.getColor(editorSelectionHighlightBorder); + + const selectionHighlightBorder = theme.getColor(editorSelectionHighlightBorder); if (selectionHighlightBorder) { - collector.addRule(`.monaco-editor .selectionHighlight { border: 1px dotted ${selectionHighlightBorder}; box-sizing: border-box; }`); - } - let wordHighlightBorder = theme.getColor(editorWordHighlightBorder); - if (wordHighlightBorder) { - collector.addRule(`.monaco-editor .wordHighlight { border: 1px dashed ${wordHighlightBorder}; box-sizing: border-box; }`); - } - let wordHighlightStrongBorder = theme.getColor(editorWordHighlightStrongBorder); - if (wordHighlightStrongBorder) { - collector.addRule(`.monaco-editor .wordHighlightStrong { border: 1px dashed ${wordHighlightStrongBorder}; box-sizing: border-box; }`); + collector.addRule(`.monaco-editor .selectionHighlight { border: 1px ${theme.type === 'hc' ? 'dotted' : 'solid'} ${selectionHighlightBorder}; box-sizing: border-box; }`); } + const wordHighlightBorder = theme.getColor(editorWordHighlightBorder); + if (wordHighlightBorder) { + collector.addRule(`.monaco-editor .wordHighlight { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${wordHighlightBorder}; box-sizing: border-box; }`); + } + + const wordHighlightStrongBorder = theme.getColor(editorWordHighlightStrongBorder); + if (wordHighlightStrongBorder) { + collector.addRule(`.monaco-editor .wordHighlightStrong { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${wordHighlightStrongBorder}; box-sizing: border-box; }`); + } }); diff --git a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts index e3dad8c471..629d7d4a2c 100644 --- a/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts +++ b/src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts @@ -141,7 +141,6 @@ suite('WordOperations', () => { moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 + '.length + 1, '002'); moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 '.length + 1, '003'); moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-'.length + 1, '004'); - moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5'.length + 1, '005'); moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +'.length + 1, '006'); moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 '.length + 1, '007'); moveWordLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= '.length + 1, '008'); @@ -165,7 +164,6 @@ suite('WordOperations', () => { moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 + '.length + 1, '002'); moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 '.length + 1, '003'); moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-'.length + 1, '004'); - moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5'.length + 1, '005'); moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +'.length + 1, '006'); moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 '.length + 1, '007'); moveWordStartLeft(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= '.length + 1, '008'); @@ -267,9 +265,7 @@ suite('WordOperations', () => { moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a'.length + 1, '007'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+='.length + 1, '008'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3'.length + 1, '009'); - moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +'.length + 1, '010'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5'.length + 1, '011'); - moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-'.length + 1, '012'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3'.length + 1, '013'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 +'.length + 1, '014'); moveWordRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 + 7'.length + 1, '015'); @@ -279,6 +275,31 @@ suite('WordOperations', () => { }); }); + test('issue #41199: moveWordRight', () => { + withTestCodeEditor([ + 'console.log(err)' + ], {}, (editor, _) => { + editor.setPosition(new Position(1, 1)); + + moveWordRight(editor); assert.equal(editor.getPosition().column, 'console'.length + 1, '001'); + moveWordRight(editor); assert.equal(editor.getPosition().column, 'console.log'.length + 1, '002'); + moveWordRight(editor); assert.equal(editor.getPosition().column, 'console.log(err'.length + 1, '003'); + moveWordRight(editor); assert.equal(editor.getPosition().column, 'console.log(err)'.length + 1, '004'); + }); + }); + + test('issue #48046: Word selection doesn\'t work as usual', () => { + withTestCodeEditor([ + 'deep.object.property' + ], {}, (editor, _) => { + editor.setPosition(new Position(1, 21)); + + moveWordLeft(editor); assert.equal(editor.getPosition().column, 'deep.object.'.length + 1, '001'); + moveWordLeft(editor); assert.equal(editor.getPosition().column, 'deep.'.length + 1, '002'); + moveWordLeft(editor); assert.equal(editor.getPosition().column, ''.length + 1, '003'); + }); + }); + test('moveWordEndRight', () => { withTestCodeEditor([ ' /* Just some more text a+= 3 +5-3 + 7 */ ' @@ -293,9 +314,7 @@ suite('WordOperations', () => { moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a'.length + 1, '007'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+='.length + 1, '008'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3'.length + 1, '009'); - moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +'.length + 1, '010'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5'.length + 1, '011'); - moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-'.length + 1, '012'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3'.length + 1, '013'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 +'.length + 1, '014'); moveWordEndRight(editor); assert.equal(editor.getPosition().column, ' /* Just some more text a+= 3 +5-3 + 7'.length + 1, '015'); diff --git a/src/vs/editor/contrib/wordOperations/wordOperations.ts b/src/vs/editor/contrib/wordOperations/wordOperations.ts index 7ed4f6b0b1..735cc019d2 100644 --- a/src/vs/editor/contrib/wordOperations/wordOperations.ts +++ b/src/vs/editor/contrib/wordOperations/wordOperations.ts @@ -98,7 +98,7 @@ export class CursorWordStartLeft extends WordLeftCommand { id: 'cursorWordStartLeft', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.LeftArrow, mac: { primary: KeyMod.Alt | KeyCode.LeftArrow } } @@ -136,7 +136,7 @@ export class CursorWordStartLeftSelect extends WordLeftCommand { id: 'cursorWordStartLeftSelect', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow, mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow } } @@ -185,7 +185,7 @@ export class CursorWordEndRight extends WordRightCommand { id: 'cursorWordEndRight', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.RightArrow, mac: { primary: KeyMod.Alt | KeyCode.RightArrow } } @@ -223,7 +223,7 @@ export class CursorWordEndRightSelect extends WordRightCommand { id: 'cursorWordEndRightSelect', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow, mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow } } @@ -328,7 +328,7 @@ export class DeleteWordLeft extends DeleteWordLeftCommand { id: 'deleteWordLeft', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Backspace, mac: { primary: KeyMod.Alt | KeyCode.Backspace } } @@ -366,7 +366,7 @@ export class DeleteWordRight extends DeleteWordRightCommand { id: 'deleteWordRight', precondition: EditorContextKeys.writable, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Delete, mac: { primary: KeyMod.Alt | KeyCode.Delete } } diff --git a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts index b062e9f9be..4c15dba524 100644 --- a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts @@ -210,6 +210,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { } this.editor.deltaDecorations(this._positionMarkerId, []); + this._positionMarkerId = []; } public create(): void { @@ -280,10 +281,14 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { public get position(): Position { const [id] = this._positionMarkerId; - if (id) { - return this.editor.getModel().getDecorationRange(id).getStartPosition(); + if (!id) { + return undefined; } - return undefined; + const range = this.editor.getModel().getDecorationRange(id); + if (!range) { + return undefined; + } + return range.getStartPosition(); } protected _isShowing: boolean = false; diff --git a/src/vs/editor/editor.all.ts b/src/vs/editor/editor.all.ts index 56d9d49574..e9d56fa565 100644 --- a/src/vs/editor/editor.all.ts +++ b/src/vs/editor/editor.all.ts @@ -32,7 +32,7 @@ import 'vs/editor/contrib/linesOperations/linesOperations'; import 'vs/editor/contrib/links/links'; import 'vs/editor/contrib/multicursor/multicursor'; import 'vs/editor/contrib/parameterHints/parameterHints'; -import 'vs/editor/contrib/quickFix/quickFixCommands'; +import 'vs/editor/contrib/codeAction/codeActionContributions'; import 'vs/editor/contrib/referenceSearch/referenceSearch'; import 'vs/editor/contrib/rename/rename'; import 'vs/editor/contrib/smartSelect/smartSelect'; diff --git a/src/vs/editor/editor.api.ts b/src/vs/editor/editor.api.ts new file mode 100644 index 0000000000..0e7647083c --- /dev/null +++ b/src/vs/editor/editor.api.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { createMonacoBaseAPI } from 'vs/editor/common/standalone/standaloneBase'; +import { createMonacoEditorAPI } from 'vs/editor/standalone/browser/standaloneEditor'; +import { createMonacoLanguagesAPI } from 'vs/editor/standalone/browser/standaloneLanguages'; +import { EDITOR_DEFAULTS, WrappingIndent } from 'vs/editor/common/config/editorOptions'; +import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise'; + +var global: any = self; + +// When missing, polyfill the native promise +// with our winjs-based polyfill +if (typeof global.Promise === 'undefined') { + global.Promise = PolyfillPromise; +} + +// Set defaults for standalone editor +(<any>EDITOR_DEFAULTS).wrappingIndent = WrappingIndent.None; +(<any>EDITOR_DEFAULTS.viewInfo).glyphMargin = false; +(<any>EDITOR_DEFAULTS).autoIndent = false; + +const api = createMonacoBaseAPI(); +api.editor = createMonacoEditorAPI(); +api.languages = createMonacoLanguagesAPI(); +export const CancellationTokenSource = api.CancellationTokenSource; +export const Emitter = api.Emitter; +export const KeyCode = api.KeyCode; +export const KeyMod = api.KeyMod; +export const Position = api.Position; +export const Range = api.Range; +export const Selection = api.Selection; +export const SelectionDirection = api.SelectionDirection; +export const Severity = api.Severity; +export const MarkerSeverity = api.MarkerSeverity; +export const Promise = api.Promise; +export const Uri = api.Uri; +export const Token = api.Token; +export const editor = api.editor; +export const languages = api.languages; + +global.monaco = api; + +if (typeof global.require !== 'undefined' && typeof global.require.config === 'function') { + global.require.config({ + ignoreDuplicateModules: [ + 'vscode-languageserver-types', + 'vscode-languageserver-types/main', + 'vscode-nls', + 'vscode-nls/vscode-nls', + 'jsonc-parser', + 'jsonc-parser/main', + 'vscode-uri', + 'vscode-uri/index' + ] + }); +} diff --git a/src/vs/editor/editor.main.ts b/src/vs/editor/editor.main.ts index d52da9e0c3..b2e5be09d6 100644 --- a/src/vs/editor/editor.main.ts +++ b/src/vs/editor/editor.main.ts @@ -13,49 +13,6 @@ import 'vs/editor/standalone/browser/quickOpen/quickOutline'; import 'vs/editor/standalone/browser/quickOpen/gotoLine'; import 'vs/editor/standalone/browser/quickOpen/quickCommand'; import 'vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast'; +import 'vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch'; -import { createMonacoBaseAPI } from 'vs/editor/common/standalone/standaloneBase'; -import { createMonacoEditorAPI } from 'vs/editor/standalone/browser/standaloneEditor'; -import { createMonacoLanguagesAPI } from 'vs/editor/standalone/browser/standaloneLanguages'; -import { EDITOR_DEFAULTS, WrappingIndent } from 'vs/editor/common/config/editorOptions'; - -declare var exports: any; -var global: any = self; -global.monaco = exports; - -// When missing, polyfill the native promise -// with our winjs-based polyfill -import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise'; -if (typeof global.Promise === 'undefined') { - global.Promise = PolyfillPromise; -} - -// Set defaults for standalone editor -(<any>EDITOR_DEFAULTS).wrappingIndent = WrappingIndent.None; -(<any>EDITOR_DEFAULTS.contribInfo).folding = false; -(<any>EDITOR_DEFAULTS.viewInfo).glyphMargin = false; -(<any>EDITOR_DEFAULTS).autoIndent = false; - -let base = createMonacoBaseAPI(); -for (let prop in base) { - if (base.hasOwnProperty(prop)) { - exports[prop] = (base as any)[prop]; - } -} -exports.editor = createMonacoEditorAPI(); -exports.languages = createMonacoLanguagesAPI(); - -if (typeof global.require !== 'undefined' && typeof global.require.config === 'function') { - global.require.config({ - ignoreDuplicateModules: [ - 'vscode-languageserver-types', - 'vscode-languageserver-types/main', - 'vscode-nls', - 'vscode-nls/vscode-nls', - 'jsonc-parser', - 'jsonc-parser/main', - 'vscode-uri', - 'vscode-uri/index' - ] - }); -} +export * from 'vs/editor/editor.api'; diff --git a/src/vs/editor/editor.worker.ts b/src/vs/editor/editor.worker.ts new file mode 100644 index 0000000000..5154b9c40c --- /dev/null +++ b/src/vs/editor/editor.worker.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { EditorSimpleWorkerImpl } from 'vs/editor/common/services/editorSimpleWorker'; +import { SimpleWorkerServer } from 'vs/base/common/worker/simpleWorker'; + +let initialized = false; + +export function initialize(foreignModule: any) { + if (initialized) { + return; + } + initialized = true; + + const editorWorker = new EditorSimpleWorkerImpl(foreignModule); + const simpleWorker = new SimpleWorkerServer((msg) => { + (<any>self).postMessage(msg); + }, editorWorker); + + self.onmessage = (e) => { + simpleWorker.onmessage(e.data); + }; +} + +self.onmessage = (e) => { + // Ignore first message in this case and initialize if not yet initialized + if (!initialized) { + initialize(null); + } +}; diff --git a/src/vs/editor/standalone/browser/colorizer.ts b/src/vs/editor/standalone/browser/colorizer.ts index 55eb3fccb8..b757fbabfb 100644 --- a/src/vs/editor/standalone/browser/colorizer.ts +++ b/src/vs/editor/standalone/browser/colorizer.ts @@ -13,6 +13,7 @@ import { renderViewLine2 as renderViewLine, RenderLineInput } from 'vs/editor/co import { LineTokens, IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import * as strings from 'vs/base/common/strings'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; +import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel'; export interface IColorizerOptions { tabSize?: number; @@ -93,11 +94,14 @@ export class Colorizer { }); } - public static colorizeLine(line: string, mightContainRTL: boolean, tokens: IViewLineTokens, tabSize: number = 4): string { + public static colorizeLine(line: string, mightContainNonBasicASCII: boolean, mightContainRTL: boolean, tokens: IViewLineTokens, tabSize: number = 4): string { + const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, mightContainNonBasicASCII); + const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, mightContainRTL); let renderResult = renderViewLine(new RenderLineInput( false, line, - mightContainRTL, + isBasicASCII, + containsRTL, 0, tokens, [], @@ -116,7 +120,7 @@ export class Colorizer { model.forceTokenization(lineNumber); let tokens = model.getLineTokens(lineNumber); let inflatedTokens = tokens.inflate(); - return this.colorizeLine(content, model.mightContainRTL(), inflatedTokens, tabSize); + return this.colorizeLine(content, model.mightContainNonBasicASCII(), model.mightContainRTL(), inflatedTokens, tabSize); } } @@ -143,10 +147,13 @@ function _fakeColorize(lines: string[], tabSize: number): string { tokens[0] = line.length; const lineTokens = new LineTokens(tokens, line); + const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */true); + const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */true); let renderResult = renderViewLine(new RenderLineInput( false, line, - false, + isBasicASCII, + containsRTL, 0, lineTokens, [], @@ -174,10 +181,13 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport: let tokenizeResult = tokenizationSupport.tokenize2(line, state, 0); LineTokens.convertToEndOffset(tokenizeResult.tokens, line.length); let lineTokens = new LineTokens(tokenizeResult.tokens, line); + const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */true); + const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */true); let renderResult = renderViewLine(new RenderLineInput( false, line, - true/* check for RTL */, + isBasicASCII, + containsRTL, 0, lineTokens.inflate(), [], diff --git a/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts b/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts index 88f1ee1980..0b03450549 100644 --- a/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts +++ b/src/vs/editor/standalone/browser/quickOpen/editorQuickOpen.ts @@ -14,7 +14,7 @@ import { registerEditorContribution, IActionOptions, EditorAction } from 'vs/edi import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Range } from 'vs/editor/common/core/range'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; -import { IModelDecorationsChangeAccessor, IModelDeltaDecoration } from 'vs/editor/common/model'; +import { IModelDeltaDecoration } from 'vs/editor/common/model'; export interface IQuickOpenControllerOpts { inputAriaLabel: string; @@ -100,31 +100,27 @@ export class QuickOpenController implements editorCommon.IEditorContribution, ID }); public decorateLine(range: Range, editor: ICodeEditor): void { - editor.changeDecorations((changeAccessor: IModelDecorationsChangeAccessor) => { - const oldDecorations: string[] = []; - if (this.rangeHighlightDecorationId) { - oldDecorations.push(this.rangeHighlightDecorationId); - this.rangeHighlightDecorationId = null; + const oldDecorations: string[] = []; + if (this.rangeHighlightDecorationId) { + oldDecorations.push(this.rangeHighlightDecorationId); + this.rangeHighlightDecorationId = null; + } + + const newDecorations: IModelDeltaDecoration[] = [ + { + range: range, + options: QuickOpenController._RANGE_HIGHLIGHT_DECORATION } + ]; - const newDecorations: IModelDeltaDecoration[] = [ - { - range: range, - options: QuickOpenController._RANGE_HIGHLIGHT_DECORATION - } - ]; - - const decorations = changeAccessor.deltaDecorations(oldDecorations, newDecorations); - this.rangeHighlightDecorationId = decorations[0]; - }); + const decorations = editor.deltaDecorations(oldDecorations, newDecorations); + this.rangeHighlightDecorationId = decorations[0]; } public clearDecorations(): void { if (this.rangeHighlightDecorationId) { - this.editor.changeDecorations((changeAccessor: IModelDecorationsChangeAccessor) => { - changeAccessor.deltaDecorations([this.rangeHighlightDecorationId], []); - this.rangeHighlightDecorationId = null; - }); + this.editor.deltaDecorations([this.rangeHighlightDecorationId], []); + this.rangeHighlightDecorationId = null; } } } diff --git a/src/vs/editor/standalone/browser/quickOpen/gotoLine.css b/src/vs/editor/standalone/browser/quickOpen/gotoLine.css index 824f1b47a4..958652fc3d 100644 --- a/src/vs/editor/standalone/browser/quickOpen/gotoLine.css +++ b/src/vs/editor/standalone/browser/quickOpen/gotoLine.css @@ -3,6 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.quick-open-widget { +.monaco-quick-open-widget { font-size: 13px; } \ No newline at end of file diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts index 589b87eecf..39a0196b69 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { $, Dimension } from 'vs/base/browser/builder'; import { QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenWidget } from 'vs/base/parts/quickopen/browser/quickOpenWidget'; import { IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen'; @@ -13,6 +12,7 @@ import { attachQuickOpenStyler } from 'vs/platform/theme/common/styler'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { foreground } from 'vs/platform/theme/common/colorRegistry'; +import { Dimension } from 'vs/base/browser/dom'; export interface IQuickOpenEditorWidgetOptions { inputAriaLabel: string; @@ -37,7 +37,7 @@ export class QuickOpenEditorWidget implements IOverlayWidget { } private create(onOk: () => void, onCancel: () => void, onType: (value: string) => void, configuration: IQuickOpenEditorWidgetOptions): void { - this.domNode = $().div().getHTMLElement(); + this.domNode = document.createElement('div'); this.quickOpenWidget = new QuickOpenWidget( this.domNode, diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.css b/src/vs/editor/standalone/browser/quickOpen/quickOutline.css index 6cb5f67578..e7e351e0f2 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.css +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.css @@ -3,93 +3,93 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.quick-open-widget { +.monaco-quick-open-widget { font-size: 13px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon, -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon, +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { background-image: url('symbol-sprite.svg'); background-repeat: no-repeat; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -4px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -4px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -3px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -4px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -4px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -3px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -3px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -4px; } -.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -3px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -3px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -3px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -4px; } +.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -4px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -24px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -24px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -23px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -24px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -24px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -23px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -23px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -24px; } -.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -23px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -23px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -23px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -24px; } +.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -24px; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon { background: none; display: inline; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon:before { height: 16px; width: 16px; display: inline-block; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method:before, -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function:before, -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method:before, +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function:before, +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0IxODBENyIgZD0iTTUuNSAzbC00LjUgMi44NTd2NC4yODVsNC41IDIuODU4IDQuNS0yLjg1N3YtNC4yODZsLTQuNS0yLjg1N3ptLS41IDguNDk4bC0zLTEuOTA1di0yLjgxNmwzIDEuOTA1djIuODE2em0tMi4zNTgtNS40OThsMi44NTgtMS44MTUgMi44NTggMS44MTUtMi44NTggMS44MTUtMi44NTgtMS44MTV6bTYuMzU4IDMuNTkzbC0zIDEuOTA1di0yLjgxNWwzLTEuOTA1djIuODE1eiIvPjwvc3ZnPg=="); margin-left: 2px; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field:before, -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field:before, +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzc1QkVGRiIgZD0iTTEgNnY0bDQgMiA2LTN2LTRsLTQtMi02IDN6bTQgMWwtMi0xIDQtMiAyIDEtNCAyeiIvPjwvc3ZnPg=="); margin-left: 2px; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBvbHlnb24gZmlsbD0iI0U4QUI1MyIgcG9pbnRzPSIxMS45OTgsMTEuMDAyIDksMTEgOSw3IDExLDcgMTAsOCAxMiwxMCAxNSw3IDEzLDUgMTIsNiA3LDYgOSw0IDYsMSAxLDYgNCw5IDYsNyA4LDcgOCwxMiAxMSwxMiAxMCwxMyAxMiwxNSAxNSwxMiAxMywxMCIvPjwvc3ZnPg=="); } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzc1QkVGRiIgZD0iTTExLjUgNGMtMS43NTkgMC0zLjIwNCAxLjMwOC0zLjQ0OSAzaC0zLjEyMmMtLjIyMy0uODYxLS45OTgtMS41LTEuOTI5LTEuNS0xLjEwNCAwLTIgLjg5NS0yIDIgMCAxLjEwNC44OTYgMiAyIDIgLjkzMSAwIDEuNzA2LS42MzkgMS45MjktMS41aDMuMTIyYy4yNDUgMS42OTEgMS42OSAzIDMuNDQ5IDMgMS45MyAwIDMuNS0xLjU3IDMuNS0zLjUgMC0xLjkzMS0xLjU3LTMuNS0zLjUtMy41em0wIDVjLS44MjcgMC0xLjUtLjY3NC0xLjUtMS41IDAtLjgyOC42NzMtMS41IDEuNS0xLjVzMS41LjY3MiAxLjUgMS41YzAgLjgyNi0uNjczIDEuNS0xLjUgMS41eiIvPjwvc3ZnPg=="); } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTkgMTF2LTFjMC0uODM0LjQ5Ni0xLjczOCAxLTItLjUwNC0uMjctMS0xLjE2OC0xLTJ2LTFjMC0uODQtLjU4NC0xLTEtMXYtMWMyLjA4MyAwIDIgMS4xNjYgMiAydjFjMCAuOTY5LjcwMy45OCAxIDF2MmMtLjMyMi4wMi0xIC4wNTMtMSAxdjFjMCAuODM0LjA4MyAyLTIgMnYtMWMuODMzIDAgMS0xIDEtMXptLTYgMHYtMWMwLS44MzQtLjQ5Ni0xLjczOC0xLTIgLjUwNC0uMjcgMS0xLjE2OCAxLTJ2LTFjMC0uODQuNTg0LTEgMS0xdi0xYy0yLjA4MyAwLTIgMS4xNjYtMiAydjFjMCAuOTY5LS43MDMuOTgtMSAxdjJjLjMyMi4wMiAxIC4wNTMgMSAxdjFjMCAuODM0LS4wODMgMiAyIDJ2LTFjLS44MzMgMC0xLTEtMS0xeiIvPjwvc3ZnPg=="); margin-left: 2px; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTEyLjA5IDQuMzU5bC0yLjY0MSAyLjY0MS0yLTIgMi42NDEtMi42NDFjLS41MDItLjIyNi0xLjA1NS0uMzU5LTEuNjQxLS4zNTktMi4yMDkgMC00IDEuNzkxLTQgNCAwIC41ODYuMTMzIDEuMTM5LjM1OSAxLjY0bC0zLjM1OSAzLjM2cy0xIDEgMCAyaDJsMy4zNTktMy4zNmMuNTAzLjIyNiAxLjA1NS4zNiAxLjY0MS4zNiAyLjIwOSAwIDQtMS43OTEgNC00IDAtLjU4Ni0uMTMzLTEuMTM5LS4zNTktMS42NDF6Ii8+PC9zdmc+"); margin-left: 1px; } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.value:before, -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.value:before, +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PGcgZmlsbD0iIzc1QkVGRiI+PHBhdGggZD0iTTEyIDNoLTRsLTEgMXYyaDV2MWgtMnYxaDJsMS0xdi0zbC0xLTF6bTAgMmgtNHYtMWg0djF6TTMgMTJoNnYtNWgtNnY1em0xLTNoNHYxaC00di0xeiIvPjwvZz48L3N2Zz4="); } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxMiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTEwIDVoLTh2LTJoOHYyem0wIDFoLTZ2MWg2di0xem0wIDJoLTZ2MWg2di0xeiIvPjwvc3ZnPg=="); } -.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file:before { +.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file:before { content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTkuNjc2IDJoLTYuNjc2djEyaDEwdi05bC0zLjMyNC0zem0yLjMyNCAxMWgtOHYtMTBoNXYzaDN2N3oiLz48L3N2Zz4="); } \ No newline at end of file diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index 516b91090a..8a4b3175d5 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -15,7 +15,7 @@ import { IContext, IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/ba import { IAutoFocus, Mode } from 'vs/base/parts/quickopen/common/quickOpen'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { SymbolInformation, DocumentSymbolProviderRegistry, symbolKindToCssClass, IOutline } from 'vs/editor/common/modes'; +import { SymbolInformation, DocumentSymbolProviderRegistry, symbolKindToCssClass, IOutline, Location } from 'vs/editor/common/modes'; import { BaseEditorQuickOpenAction, IDecorator } from './editorQuickOpen'; import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen'; import { registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; @@ -25,7 +25,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; let SCOPE_PREFIX = ':'; -class SymbolEntry extends QuickOpenEntryGroup { +export class SymbolEntry extends QuickOpenEntryGroup { private name: string; private type: string; private description: string; @@ -167,6 +167,10 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { }); } + private symbolEntry(name: string, type: string, description: string, location: Location, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator): SymbolEntry { + return new SymbolEntry(name, type, description, Range.lift(location.range), highlights, editor, decorator); + } + private toQuickOpenEntries(editor: ICodeEditor, flattened: SymbolInformation[], searchValue: string): SymbolEntry[] { const controller = this.getController(editor); @@ -193,7 +197,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { } // Add - results.push(new SymbolEntry(label, symbolKindToCssClass(element.kind), description, Range.lift(element.location.range), highlights, editor, controller)); + results.push(this.symbolEntry(label, symbolKindToCssClass(element.kind), description, element.location, highlights, editor, controller)); } } diff --git a/src/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.ts b/src/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.ts new file mode 100644 index 0000000000..008ac832d9 --- /dev/null +++ b/src/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IEditorService } from 'vs/platform/editor/common/editor'; +import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ReferencesController } from 'vs/editor/contrib/referenceSearch/referencesController'; + +export class StandaloneReferencesController extends ReferencesController { + + public constructor( + editor: ICodeEditor, + @IContextKeyService contextKeyService: IContextKeyService, + @IEditorService editorService: IEditorService, + @ITextModelService textModelResolverService: ITextModelService, + @INotificationService notificationService: INotificationService, + @IInstantiationService instantiationService: IInstantiationService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, + @optional(IEnvironmentService) environmentService: IEnvironmentService + ) { + super( + true, + editor, + contextKeyService, + editorService, + textModelResolverService, + notificationService, + instantiationService, + contextService, + storageService, + themeService, + configurationService, + environmentService + ); + } +} + +registerEditorContribution(StandaloneReferencesController); diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 2dc56ac6f0..5bf78f05c2 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -20,7 +20,7 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo import { IWorkspaceContextService, IWorkspace, WorkbenchState, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { ICodeEditor, IDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Configuration, DefaultConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; @@ -39,7 +39,7 @@ import { OS } from 'vs/base/common/platform'; import { IRange } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; import { INotificationService, INotification, INotificationHandle, NoOpNotification, IPromptChoice } from 'vs/platform/notification/common/notification'; -import { IConfirmation, IConfirmationResult, IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { IPosition, Position as Pos } from 'vs/editor/common/core/position'; export class SimpleEditor implements IEditor { @@ -73,7 +73,7 @@ export class SimpleEditor implements IEditor { export class SimpleModel implements ITextEditorModel { private model: ITextModel; - private _onDispose: Emitter<void>; + private readonly _onDispose: Emitter<void>; constructor(model: ITextModel) { this.model = model; @@ -236,11 +236,20 @@ export class SimpleProgressService implements IProgressService { } } -export class SimpleConfirmationService implements IConfirmationService { +export class SimpleDialogService implements IDialogService { public _serviceBrand: any; - public confirm(confirmation: IConfirmation): TPromise<boolean> { + public confirm(confirmation: IConfirmation): TPromise<IConfirmationResult> { + return this.doConfirm(confirmation).then(confirmed => { + return { + confirmed, + checkboxChecked: false // unsupported + } as IConfirmationResult; + }); + } + + private doConfirm(confirmation: IConfirmation): TPromise<boolean> { let messageText = confirmation.message; if (confirmation.detail) { messageText = messageText + '\n\n' + confirmation.detail; @@ -249,13 +258,8 @@ export class SimpleConfirmationService implements IConfirmationService { return TPromise.wrap(window.confirm(messageText)); } - public confirmWithCheckbox(confirmation: IConfirmation): TPromise<IConfirmationResult> { - return this.confirm(confirmation).then(confirmed => { - return { - confirmed, - checkboxChecked: false // unsupported - } as IConfirmationResult; - }); + public show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): TPromise<number> { + return TPromise.as(0); } } @@ -304,7 +308,7 @@ export class StandaloneCommandService implements ICommandService { private readonly _instantiationService: IInstantiationService; private _dynamicCommands: { [id: string]: ICommand; }; - private _onWillExecuteCommand: Emitter<ICommandEvent> = new Emitter<ICommandEvent>(); + private readonly _onWillExecuteCommand: Emitter<ICommandEvent> = new Emitter<ICommandEvent>(); public readonly onWillExecuteCommand: Event<ICommandEvent> = this._onWillExecuteCommand.event; constructor(instantiationService: IInstantiationService) { @@ -468,7 +472,7 @@ export class SimpleConfigurationService implements IConfigurationService { _serviceBrand: any; private _onDidChangeConfiguration = new Emitter<IConfigurationChangeEvent>(); - public onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event; + public readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event; private _configuration: Configuration; diff --git a/src/vs/editor/standalone/browser/standalone-tokens.css b/src/vs/editor/standalone/browser/standalone-tokens.css index ed96674d4c..e8a6299bc7 100644 --- a/src/vs/editor/standalone/browser/standalone-tokens.css +++ b/src/vs/editor/standalone/browser/standalone-tokens.css @@ -192,19 +192,23 @@ } /* squiggles */ - .monaco-editor.vs .squiggly-c-error, - .monaco-editor.vs-dark .squiggly-c-error { + .monaco-editor.vs .squiggly-d-error, + .monaco-editor.vs-dark .squiggly-d-error { background: transparent !important; border-bottom: 4px double #E47777; } - .monaco-editor.vs .squiggly-b-warning, - .monaco-editor.vs-dark .squiggly-b-warning { + .monaco-editor.vs .squiggly-c-warning, + .monaco-editor.vs-dark .squiggly-c-warning { border-bottom: 4px double #71B771; } - .monaco-editor.vs .squiggly-a-info, - .monaco-editor.vs-dark .squiggly-a-info { + .monaco-editor.vs .squiggly-b-info, + .monaco-editor.vs-dark .squiggly-b-info { border-bottom: 4px double #71B771; } + .monaco-editor.vs .squiggly-a-hint, + .monaco-editor.vs-dark .squiggly-a-hint { + border-bottom: 4px double #6c6c6c; + } /* contextmenu */ .monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus, diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index 06d3674989..ce075c61f4 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -164,7 +164,8 @@ export class StandaloneCodeEditor extends CodeEditor implements IStandaloneCodeE @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService ) { options = options || {}; options.ariaLabel = options.ariaLabel || nls.localize('editorViewAccessibleLabel', "Editor content"); @@ -173,7 +174,7 @@ export class StandaloneCodeEditor extends CodeEditor implements IStandaloneCodeE ? nls.localize('accessibilityHelpMessageIE', "Press Ctrl+F1 for Accessibility Options.") : nls.localize('accessibilityHelpMessage', "Press Alt+F1 for Accessibility Options.") ); - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService); + super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService); if (keybindingService instanceof StandaloneKeybindingService) { this._standaloneKeybindingService = keybindingService; @@ -295,7 +296,8 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, @IContextViewService contextViewService: IContextViewService, - @IStandaloneThemeService themeService: IStandaloneThemeService + @IStandaloneThemeService themeService: IStandaloneThemeService, + @INotificationService notificationService: INotificationService, ) { options = options || {}; if (typeof options.theme === 'string') { @@ -303,7 +305,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon } let model: ITextModel = options.model; delete options.model; - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService); + super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService); this._contextViewService = <IEditorContextViewService>contextViewService; this._register(toDispose); diff --git a/src/vs/editor/standalone/browser/standaloneEditor.ts b/src/vs/editor/standalone/browser/standaloneEditor.ts index 51fec64a8f..4c5c38339f 100644 --- a/src/vs/editor/standalone/browser/standaloneEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneEditor.ts @@ -89,7 +89,8 @@ export function create(domElement: HTMLElement, options?: IEditorConstructionOpt services.get(IContextKeyService), services.get(IKeybindingService), services.get(IContextViewService), - services.get(IStandaloneThemeService) + services.get(IStandaloneThemeService), + services.get(INotificationService) ); }); } diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 10346cae3c..0b6d828633 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -24,6 +24,7 @@ import { IMarkerData } from 'vs/platform/markers/common/markers'; import { Token, TokenizationResult, TokenizationResult2 } from 'vs/editor/common/core/token'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import * as model from 'vs/editor/common/model'; +import { IMarkdownString } from 'vs/base/common/htmlContent'; /** * Register information about a new language. @@ -390,12 +391,11 @@ export function registerColorProvider(languageId: string, provider: modes.Docume } /** - * Register a folding provider + * Register a folding range provider */ -/*export function registerFoldingProvider(languageId: string, provider: modes.FoldingProvider): IDisposable { - return modes.FoldingProviderRegistry.register(languageId, provider); -}*/ - +export function registerFoldingRangeProvider(languageId: string, provider: modes.FoldingRangeProvider): IDisposable { + return modes.FoldingRangeProviderRegistry.register(languageId, provider); +} /** * Contains additional diagnostic information about the context in which @@ -494,7 +494,7 @@ export interface CompletionItem { /** * A human-readable string that represents a doc-comment. */ - documentation?: string; + documentation?: string | IMarkdownString; /** * A command that should be run upon acceptance of this item. */ @@ -527,6 +527,12 @@ export interface CompletionItem { * [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems). */ range?: Range; + /** + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + commitCharacters?: string[]; /** * @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`. * @@ -544,12 +550,6 @@ export interface CompletionItem { * nor with themselves. */ additionalTextEdits?: model.ISingleEditOperation[]; - /** - * An optional set of characters that when pressed while this completion is active will accept it first and - * then type that character. *Note* that all commit characters should have `length=1` and that superfluous - * characters will be ignored. - */ - commitCharacters?: string[]; } /** * Represents a collection of [completion items](#CompletionItem) to be presented @@ -786,12 +786,14 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { registerOnTypeFormattingEditProvider: registerOnTypeFormattingEditProvider, registerLinkProvider: registerLinkProvider, registerColorProvider: registerColorProvider, + registerFoldingRangeProvider: registerFoldingRangeProvider, // enums DocumentHighlightKind: modes.DocumentHighlightKind, CompletionItemKind: CompletionItemKind, SymbolKind: modes.SymbolKind, IndentAction: IndentAction, - SuggestTriggerKind: modes.SuggestTriggerKind + SuggestTriggerKind: modes.SuggestTriggerKind, + FoldingRangeKind: modes.FoldingRangeKind }; } diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 607064d23d..318092aa26 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -33,7 +33,7 @@ import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServ import { SimpleConfigurationService, SimpleResourceConfigurationService, SimpleMenuService, SimpleProgressService, StandaloneCommandService, StandaloneKeybindingService, SimpleNotificationService, - StandaloneTelemetryService, SimpleWorkspaceContextService, SimpleConfirmationService + StandaloneTelemetryService, SimpleWorkspaceContextService, SimpleDialogService } from 'vs/editor/standalone/browser/simpleServices'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; import { IMenuService } from 'vs/platform/actions/common/actions'; @@ -41,7 +41,8 @@ import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneT import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IListService, ListService } from 'vs/platform/list/browser/listService'; export interface IEditorContextViewService extends IContextViewService { dispose(): void; @@ -126,7 +127,7 @@ export module StaticServices { export const telemetryService = define(ITelemetryService, () => new StandaloneTelemetryService()); - export const confirmationService = define(IConfirmationService, () => new SimpleConfirmationService()); + export const dialogService = define(IDialogService, () => new SimpleDialogService()); export const notificationService = define(INotificationService, () => new SimpleNotificationService()); @@ -180,6 +181,8 @@ export class DynamicStandaloneServices extends Disposable { let contextKeyService = ensure(IContextKeyService, () => this._register(new ContextKeyService(configurationService))); + ensure(IListService, () => new ListService(contextKeyService)); + let commandService = ensure(ICommandService, () => new StandaloneCommandService(this._instantiationService)); ensure(IKeybindingService, () => this._register(new StandaloneKeybindingService(contextKeyService, commandService, telemetryService, notificationService, domElement))); diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index d42b3ecb5c..e1b3d78065 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -13,13 +13,13 @@ import { Color } from 'vs/base/common/color'; import { Extensions, IColorRegistry, ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Extensions as ThemingExtensions, IThemingRegistry, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { Registry } from 'vs/platform/registry/common/platform'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; const VS_THEME_NAME = 'vs'; const VS_DARK_THEME_NAME = 'vs-dark'; const HC_BLACK_THEME_NAME = 'hc-black'; -const colorRegistry = <IColorRegistry>Registry.as(Extensions.ColorContribution); +const colorRegistry = Registry.as<IColorRegistry>(Extensions.ColorContribution); const themingRegistry = Registry.as<IThemingRegistry>(ThemingExtensions.ThemingContribution); class StandaloneTheme implements IStandaloneTheme { @@ -118,7 +118,7 @@ export class StandaloneThemeServiceImpl implements IStandaloneThemeService { private _knownThemes: Map<string, StandaloneTheme>; private _styleElement: HTMLStyleElement; private _theme: IStandaloneTheme; - private _onThemeChange: Emitter<IStandaloneTheme>; + private readonly _onThemeChange: Emitter<IStandaloneTheme>; constructor() { diff --git a/src/vs/editor/standalone/common/themes.ts b/src/vs/editor/standalone/common/themes.ts index 449dd91ef1..96ab41bb34 100644 --- a/src/vs/editor/standalone/common/themes.ts +++ b/src/vs/editor/standalone/common/themes.ts @@ -7,7 +7,7 @@ import { IStandaloneThemeData } from 'vs/editor/standalone/common/standaloneThemeService'; import { editorBackground, editorForeground, editorSelectionHighlight, editorInactiveSelection } from 'vs/platform/theme/common/colorRegistry'; -import { editorIndentGuides } from 'vs/editor/common/view/editorColorRegistry'; +import { editorIndentGuides, editorActiveIndentGuides } from 'vs/editor/common/view/editorColorRegistry'; /* -------------------------------- Begin vs theme -------------------------------- */ export const vs: IStandaloneThemeData = { @@ -74,6 +74,7 @@ export const vs: IStandaloneThemeData = { [editorForeground]: '#000000', [editorInactiveSelection]: '#E5EBF1', [editorIndentGuides]: '#D3D3D3', + [editorActiveIndentGuides]: '#939393', [editorSelectionHighlight]: '#ADD6FF4D' } }; @@ -144,6 +145,7 @@ export const vs_dark: IStandaloneThemeData = { [editorForeground]: '#D4D4D4', [editorInactiveSelection]: '#3A3D41', [editorIndentGuides]: '#404040', + [editorActiveIndentGuides]: '#707070', [editorSelectionHighlight]: '#ADD6FF26' } }; @@ -205,6 +207,7 @@ export const hc_black: IStandaloneThemeData = { [editorBackground]: '#000000', [editorForeground]: '#FFFFFF', [editorIndentGuides]: '#FFFFFF', + [editorActiveIndentGuides]: '#FFFFFF', } }; /* -------------------------------- End hc-black theme -------------------------------- */ diff --git a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts index 41fac28ec8..1fcd315734 100644 --- a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts +++ b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { TokenizationSupport2Adapter, TokensProvider, ILineTokens, IToken } from 'vs/editor/standalone/browser/standaloneLanguages'; import { IStandaloneThemeService, IStandaloneThemeData, IStandaloneTheme } from 'vs/editor/standalone/common/standaloneThemeService'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { ITheme, LIGHT } from 'vs/platform/theme/common/themeService'; import { LanguageIdentifier, LanguageId, IState, MetadataConsts } from 'vs/editor/common/modes'; import { Token } from 'vs/editor/common/core/token'; @@ -58,7 +58,7 @@ suite('TokenizationSupport2Adapter', () => { } }; } - public onThemeChange: Event<ITheme> = null; + public readonly onThemeChange: Event<ITheme> = null; } class MockState implements IState { diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index f83a5ea913..628392d222 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -11,18 +11,22 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { Handler, ICommand, IEditOperationBuilder, ICursorStateComputerData } from 'vs/editor/common/editorCommon'; -import { EndOfLinePreference, DefaultEndOfLine, ITextModelCreationOptions, ITextModel, EndOfLineSequence } from 'vs/editor/common/model'; +import { EndOfLinePreference, ITextModel, EndOfLineSequence } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import { IndentAction, IndentationRule } from 'vs/editor/common/modes/languageConfiguration'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration'; import { MockMode } from 'vs/editor/test/common/mocks/mockMode'; -import { LanguageIdentifier } from 'vs/editor/common/modes'; +import { LanguageIdentifier, ITokenizationSupport, IState, TokenizationRegistry } from 'vs/editor/common/modes'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { CoreNavigationCommands, CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; -let H = Handler; +import { NULL_STATE } from 'vs/editor/common/modes/nullMode'; +import { TokenizationResult2 } from 'vs/editor/common/core/token'; +import { createTextModel, IRelaxedTextModelCreationOptions } from 'vs/editor/test/common/editorTestUtils'; + +const H = Handler; // --------- utils @@ -146,7 +150,7 @@ suite('Editor Controller - Cursor', () => { LINE4 + '\r\n' + LINE5; - thisModel = TextModel.createFromString(text); + thisModel = createTextModel(text); thisConfiguration = new TestConfiguration(null); thisViewModel = new ViewModel(0, thisConfiguration, thisModel, null); @@ -722,7 +726,7 @@ suite('Editor Controller - Cursor', () => { }); test('issue #4905 - column select is biased to the right', () => { - const model = TextModel.createFromString([ + const model = createTextModel([ 'var gulp = require("gulp");', 'var path = require("path");', 'var rimraf = require("rimraf");', @@ -758,7 +762,7 @@ suite('Editor Controller - Cursor', () => { }); test('issue #20087: column select with mouse', () => { - const model = TextModel.createFromString([ + const model = createTextModel([ '<property id="SomeThing" key="SomeKey" value="000"/>', '<property id="SomeThing" key="SomeKey" value="000"/>', '<property id="SomeThing" Key="SomeKey" value="000"/>', @@ -820,7 +824,7 @@ suite('Editor Controller - Cursor', () => { }); test('issue #20087: column select with keyboard', () => { - const model = TextModel.createFromString([ + const model = createTextModel([ '<property id="SomeThing" key="SomeKey" value="000"/>', '<property id="SomeThing" key="SomeKey" value="000"/>', '<property id="SomeThing" Key="SomeKey" value="000"/>', @@ -872,7 +876,7 @@ suite('Editor Controller - Cursor', () => { }); test('column select with keyboard', () => { - const model = TextModel.createFromString([ + const model = createTextModel([ 'var gulp = require("gulp");', 'var path = require("path");', 'var rimraf = require("rimraf");', @@ -1128,17 +1132,13 @@ class IndentRulesMode extends MockMode { suite('Editor Controller - Regression tests', () => { test('issue Microsoft/monaco-editor#443: Indentation of a single row deletes selected text in some cases', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'Hello world!', 'another line' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, - insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: false + insertSpaces: false }, ); @@ -1154,15 +1154,12 @@ suite('Editor Controller - Regression tests', () => { }); test('Bug 9121: Auto indent + undo + redo is funky', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, trimAutoWhitespace: false }, ); @@ -1217,19 +1214,99 @@ suite('Editor Controller - Regression tests', () => { model.dispose(); }); + test('issue #47733: Undo mangles unicode characters', () => { + const languageId = new LanguageIdentifier('myMode', 3); + class MyMode extends MockMode { + constructor() { + super(languageId); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), { + surroundingPairs: [{ open: '"', close: '"' }] + })); + } + } + + const mode = new MyMode(); + const model = createTextModel('\'👁\'', undefined, languageId); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + editor.setSelection(new Selection(1, 1, 1, 2)); + + cursorCommand(cursor, H.Type, { text: '"' }, 'keyboard'); + assert.equal(model.getValue(EndOfLinePreference.LF), '"\'"👁\'', 'assert1'); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getValue(EndOfLinePreference.LF), '\'👁\'', 'assert2'); + }); + + model.dispose(); + mode.dispose(); + }); + + test('issue #46208: Allow empty selections in the undo/redo stack', () => { + let model = createTextModel(''); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + cursorCommand(cursor, H.Type, { text: 'Hello' }, 'keyboard'); + cursorCommand(cursor, H.Type, { text: ' ' }, 'keyboard'); + cursorCommand(cursor, H.Type, { text: 'world' }, 'keyboard'); + cursorCommand(cursor, H.Type, { text: ' ' }, 'keyboard'); + assert.equal(model.getLineContent(1), 'Hello world '); + assertCursor(cursor, new Position(1, 13)); + + moveLeft(cursor); + moveRight(cursor); + + model.pushEditOperations([], [EditOperation.replaceMove(new Range(1, 12, 1, 13), '')], () => []); + assert.equal(model.getLineContent(1), 'Hello world'); + assertCursor(cursor, new Position(1, 12)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'Hello world '); + assertCursor(cursor, new Position(1, 13)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'Hello world'); + assertCursor(cursor, new Position(1, 12)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), 'Hello'); + assertCursor(cursor, new Position(1, 6)); + + cursorCommand(cursor, H.Undo, {}); + assert.equal(model.getLineContent(1), ''); + assertCursor(cursor, new Position(1, 1)); + + cursorCommand(cursor, H.Redo, {}); + assert.equal(model.getLineContent(1), 'Hello'); + assertCursor(cursor, new Position(1, 6)); + + cursorCommand(cursor, H.Redo, {}); + assert.equal(model.getLineContent(1), 'Hello world'); + assertCursor(cursor, new Position(1, 12)); + + cursorCommand(cursor, H.Redo, {}); + assert.equal(model.getLineContent(1), 'Hello world '); + assertCursor(cursor, new Position(1, 13)); + + cursorCommand(cursor, H.Redo, {}); + assert.equal(model.getLineContent(1), 'Hello world'); + assertCursor(cursor, new Position(1, 12)); + + cursorCommand(cursor, H.Redo, {}); + assert.equal(model.getLineContent(1), 'Hello world'); + assertCursor(cursor, new Position(1, 12)); + }); + + model.dispose(); + }); + test('bug #16815:Shift+Tab doesn\'t go back to tabstop', () => { let mode = new OnEnterMode(IndentAction.IndentOutdent); - let model = TextModel.createFromString( + let model = createTextModel( [ ' function baz() {' ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - }, + undefined, mode.getLanguageIdentifier() ); @@ -1247,17 +1324,10 @@ suite('Editor Controller - Regression tests', () => { }); test('Bug #18293:[regression][editor] Can\'t outdent whitespace line', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' ' - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -1273,7 +1343,7 @@ suite('Editor Controller - Regression tests', () => { }); test('Bug #16657: [editor] Tab on empty line of zero indentation moves cursor to position (1,1)', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'function baz() {', '\tfunction hello() { // something here', @@ -1284,11 +1354,7 @@ suite('Editor Controller - Regression tests', () => { '' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, ); @@ -1348,8 +1414,7 @@ suite('Editor Controller - Regression tests', () => { text: [ 'hello' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { tabSize: 4, insertSpaces: true, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 1, 3, false); moveTo(cursor, 1, 5, true); @@ -1366,19 +1431,12 @@ suite('Editor Controller - Regression tests', () => { test('issue #1140: Backspace stops prematurely', () => { let mode = new SurroundingMode(); - let model = TextModel.createFromString( + let model = createTextModel( [ 'function baz() {', ' return 1;', '};' - ].join('\n'), - { - tabSize: 4, - insertSpaces: true, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - }, + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -1486,20 +1544,61 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #46440: (1) Pasting a multi-line selection pastes entire selection into every insertion point', () => { + usingCursor({ + text: [ + 'line1', + 'line2', + 'line3' + ], + }, (model, cursor) => { + cursor.setSelections('test', [new Selection(1, 1, 1, 1), new Selection(2, 1, 2, 1), new Selection(3, 1, 3, 1)]); + + cursorCommand(cursor, H.Paste, { + text: 'a\nb\nc', + pasteOnNewLine: false, + multicursorText: null + }); + + assert.equal(model.getValue(), [ + 'aline1', + 'bline2', + 'cline3' + ].join('\n')); + }); + }); + + test('issue #46440: (2) Pasting a multi-line selection pastes entire selection into every insertion point', () => { + usingCursor({ + text: [ + 'line1', + 'line2', + 'line3' + ], + }, (model, cursor) => { + cursor.setSelections('test', [new Selection(1, 1, 1, 1), new Selection(2, 1, 2, 1), new Selection(3, 1, 3, 1)]); + + cursorCommand(cursor, H.Paste, { + text: 'a\nb\nc\n', + pasteOnNewLine: false, + multicursorText: null + }); + + assert.equal(model.getValue(), [ + 'aline1', + 'bline2', + 'cline3' + ].join('\n')); + }); + }); + test('issue #3071: Investigate why undo stack gets corrupted', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'some lines', 'and more lines', 'just some text', - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -1551,8 +1650,7 @@ suite('Editor Controller - Regression tests', () => { 'and more lines', 'just some text', ], - languageIdentifier: null, - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: null }, (model, cursor) => { moveTo(cursor, 3, 1, false); @@ -1567,21 +1665,14 @@ suite('Editor Controller - Regression tests', () => { }); test('issue #3463: pressing tab adds spaces, but not as many as for a tab', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'function a() {', '\tvar a = {', '\t\tx: 3', '\t};', '}', - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -1594,17 +1685,13 @@ suite('Editor Controller - Regression tests', () => { }); test('issue #4312: trying to type a tab character over a sequence of spaces results in unexpected behaviour', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'var foo = 123; // this is a comment', 'var bar = 4; // another comment' ].join('\n'), { insertSpaces: false, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true } ); @@ -1698,7 +1785,7 @@ suite('Editor Controller - Regression tests', () => { }); test('issue #33788: Wrong cursor position when double click to select a word', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'Just some text' ].join('\n') @@ -1715,6 +1802,21 @@ suite('Editor Controller - Regression tests', () => { model.dispose(); }); + test('issue #12887: Double-click highlighting separating white space', () => { + let model = createTextModel( + [ + 'abc def' + ].join('\n') + ); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + CoreNavigationCommands.WordSelect.runCoreEditorCommand(cursor, { position: new Position(1, 5) }); + assert.deepEqual(cursor.getSelection(), new Selection(1, 5, 1, 8)); + }); + + model.dispose(); + }); + test('issue #9675: Undo/Redo adds a stop in between CHN Characters', () => { usingCursor({ text: [ @@ -1854,7 +1956,7 @@ suite('Editor Controller - Regression tests', () => { }); test('issue #41573 - delete across multiple lines does not shrink the selection when word wraps', () => { - const model = TextModel.createFromString([ + const model = createTextModel([ 'Authorization: \'Bearer pHKRfCTFSnGxs6akKlb9ddIXcca0sIUSZJutPHYqz7vEeHdMTMh0SGN0IGU3a0n59DXjTLRsj5EJ2u33qLNIFi9fk5XF8pK39PndLYUZhPt4QvHGLScgSkK0L4gwzkzMloTQPpKhqiikiIOvyNNSpd2o8j29NnOmdTUOKi9DVt74PD2ohKxyOrWZ6oZprTkb3eKajcpnS0LABKfaw2rmv4\',' ].join('\n')); const config = new TestConfiguration({ @@ -1864,8 +1966,6 @@ suite('Editor Controller - Regression tests', () => { const viewModel = new ViewModel(0, config, model, null); const cursor = new Cursor(config, model, viewModel); - console.log(viewModel.getLineCount()); - moveTo(cursor, 1, 43, false); moveTo(cursor, 1, 147, true); assertCursor(cursor, new Selection(1, 43, 1, 147)); @@ -1908,17 +2008,10 @@ suite('Editor Controller - Regression tests', () => { }); test('issue #44805: Should not be able to undo in readonly editor', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '' - ].join('\n'), - { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, - insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { readOnly: true, model: model }, (editor, cursor) => { @@ -1934,6 +2027,141 @@ suite('Editor Controller - Regression tests', () => { model.dispose(); }); + + test('issue #46314: ViewModel is out of sync with Model!', () => { + + const tokenizationSupport: ITokenizationSupport = { + getInitialState: () => NULL_STATE, + tokenize: undefined, + tokenize2: (line: string, state: IState): TokenizationResult2 => { + return new TokenizationResult2(null, state); + } + }; + + const LANGUAGE_ID = 'modelModeTest1'; + const languageRegistration = TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport); + let model = createTextModel('Just text', undefined, new LanguageIdentifier(LANGUAGE_ID, 0)); + + withTestCodeEditor(null, { model: model }, (editor1, cursor1) => { + withTestCodeEditor(null, { model: model }, (editor2, cursor2) => { + + editor1.onDidChangeCursorPosition(() => { + model.tokenizeIfCheap(1); + }); + + model.applyEdits([{ range: new Range(1, 1, 1, 1), text: '-' }]); + }); + }); + + languageRegistration.dispose(); + model.dispose(); + }); + + test('issue #37967: problem replacing consecutive characters', () => { + let model = createTextModel( + [ + 'const a = "foo";', + 'const b = ""' + ].join('\n') + ); + + withTestCodeEditor(null, { multiCursorMergeOverlapping: false, model: model }, (editor, cursor) => { + editor.setSelections([ + new Selection(1, 12, 1, 12), + new Selection(1, 16, 1, 16), + new Selection(2, 12, 2, 12), + new Selection(2, 13, 2, 13), + ]); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + + assertCursor(cursor, [ + new Selection(1, 11, 1, 11), + new Selection(1, 14, 1, 14), + new Selection(2, 11, 2, 11), + new Selection(2, 11, 2, 11), + ]); + + cursorCommand(cursor, H.Type, { text: '\'' }, 'keyboard'); + + assert.equal(model.getLineContent(1), 'const a = \'foo\';'); + assert.equal(model.getLineContent(2), 'const b = \'\''); + }); + + model.dispose(); + }); + + test('issue #15761: Cursor doesn\'t move in a redo operation', () => { + let model = createTextModel( + [ + 'hello' + ].join('\n') + ); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + editor.setSelections([ + new Selection(1, 4, 1, 4) + ]); + + editor.executeEdits('test', [{ + range: new Range(1, 1, 1, 1), + text: '*', + forceMoveMarkers: true + }]); + assertCursor(cursor, [ + new Selection(1, 5, 1, 5), + ]); + + cursorCommand(cursor, H.Undo, null, 'keyboard'); + assertCursor(cursor, [ + new Selection(1, 4, 1, 4), + ]); + + cursorCommand(cursor, H.Redo, null, 'keyboard'); + assertCursor(cursor, [ + new Selection(1, 5, 1, 5), + ]); + }); + + model.dispose(); + }); + + test('issue #42783: API Calls with Undo Leave Cursor in Wrong Position', () => { + let model = createTextModel( + [ + 'ab' + ].join('\n') + ); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + editor.setSelections([ + new Selection(1, 1, 1, 1) + ]); + + editor.executeEdits('test', [{ + range: new Range(1, 1, 1, 3), + text: '' + }]); + assertCursor(cursor, [ + new Selection(1, 1, 1, 1), + ]); + + cursorCommand(cursor, H.Undo, null, 'keyboard'); + assertCursor(cursor, [ + new Selection(1, 1, 1, 1), + ]); + + editor.executeEdits('test', [{ + range: new Range(1, 1, 1, 2), + text: '' + }]); + assertCursor(cursor, [ + new Selection(1, 1, 1, 1), + ]); + }); + + model.dispose(); + }); }); suite('Editor Controller - Cursor Configuration', () => { @@ -1946,8 +2174,7 @@ suite('Editor Controller - Cursor Configuration', () => { ' Third Line', '', '1' - ], - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + ] }, (model, cursor) => { CoreNavigationCommands.MoveTo.runCoreEditorCommand(cursor, { position: new Position(1, 21), source: 'keyboard' }); cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); @@ -1957,7 +2184,7 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('Cursor honors insertSpaces configuration on tab', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' \tMy First Line\t ', 'My Second Line123', @@ -1966,11 +2193,7 @@ suite('Editor Controller - Cursor Configuration', () => { '1' ].join('\n'), { - insertSpaces: true, tabSize: 13, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true } ); @@ -2039,8 +2262,7 @@ suite('Editor Controller - Cursor Configuration', () => { text: [ '\thello' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 1, 7, false); assertCursor(cursor, new Selection(1, 7, 1, 7)); @@ -2057,8 +2279,7 @@ suite('Editor Controller - Cursor Configuration', () => { text: [ '\thello' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 1, 7, false); assertCursor(cursor, new Selection(1, 7, 1, 7)); @@ -2075,8 +2296,7 @@ suite('Editor Controller - Cursor Configuration', () => { text: [ '\thell()' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 1, 7, false); assertCursor(cursor, new Selection(1, 7, 1, 7)); @@ -2093,10 +2313,6 @@ suite('Editor Controller - Cursor Configuration', () => { ' some line abc ' ], modelOpts: { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: false } }, (model, cursor) => { @@ -2119,14 +2335,7 @@ suite('Editor Controller - Cursor Configuration', () => { usingCursor({ text: [ ' ' - ], - modelOpts: { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ] }, (model, cursor) => { moveTo(cursor, 1, model.getLineContent(1).length + 1); cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); @@ -2146,13 +2355,6 @@ suite('Editor Controller - Cursor Configuration', () => { text: [ 'function foo (params: string) {}' ], - modelOpts: { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - }, languageIdentifier: mode.getLanguageIdentifier(), }, (model, cursor) => { @@ -2186,21 +2388,14 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('removeAutoWhitespace on: removes only whitespace the cursor added 2', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' if (a) {', ' ', '', '', ' }' - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -2234,17 +2429,10 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('removeAutoWhitespace on: test 1', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' some line abc ' - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model }, (editor, cursor) => { @@ -2298,19 +2486,12 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('UseTabStops is off', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' x', ' a ', ' ' - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, cursor) => { @@ -2324,19 +2505,12 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('Backspace removes whitespaces with tab size', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ ' \t \t x', ' a ', ' ' - ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - } + ].join('\n') ); withTestCodeEditor(null, { model: model, useTabStops: true }, (editor, cursor) => { @@ -2397,16 +2571,12 @@ suite('Editor Controller - Cursor Configuration', () => { }); test('PR #5423: Auto indent + undo + redo is funky', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true } ); @@ -2482,7 +2652,7 @@ suite('Editor Controller - Indentation Rules', () => { '\tif (true) {' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, + modelOpts: { insertSpaces: false }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 1, 12, false); @@ -2506,7 +2676,6 @@ suite('Editor Controller - Indentation Rules', () => { '\t' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 2, 2, false); @@ -2525,7 +2694,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t\t\treturn true' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, + modelOpts: { insertSpaces: false }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 2, 15, false); @@ -2545,7 +2714,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t\t\t\treturn true' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, + modelOpts: { insertSpaces: false }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 2, 14, false); @@ -2563,17 +2732,13 @@ suite('Editor Controller - Indentation Rules', () => { }); test('Enter honors indentNextLinePattern 2', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'if (true)', '\tif (true)' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -2602,7 +2767,6 @@ suite('Editor Controller - Indentation Rules', () => { '}}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 3, 13, false); @@ -2623,7 +2787,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 4, 3, false); moveTo(cursor, 4, 4, true); @@ -2642,7 +2806,7 @@ suite('Editor Controller - Indentation Rules', () => { '\tif (true) {' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 2, 12, false); moveTo(cursor, 2, 13, true); @@ -2663,7 +2827,6 @@ suite('Editor Controller - Indentation Rules', () => { '\tif (true) {' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } }, (model, cursor) => { moveTo(cursor, 1, 12, false); assertCursor(cursor, new Selection(1, 12, 1, 12)); @@ -2688,7 +2851,6 @@ suite('Editor Controller - Indentation Rules', () => { ' if (true) {' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } }, (model, cursor) => { moveTo(cursor, 1, 12, false); assertCursor(cursor, new Selection(1, 12, 1, 12)); @@ -2712,7 +2874,7 @@ suite('Editor Controller - Indentation Rules', () => { ' if (true) {' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 1, 12, false); assertCursor(cursor, new Selection(1, 12, 1, 12)); @@ -2740,7 +2902,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, + modelOpts: { insertSpaces: false }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 5, 4, false); @@ -2761,7 +2923,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 3, 9, false); assertCursor(cursor, new Selection(3, 9, 3, 9)); @@ -2781,7 +2943,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 3, 3, false); assertCursor(cursor, new Selection(3, 3, 3, 3)); @@ -2800,8 +2962,7 @@ suite('Editor Controller - Indentation Rules', () => { ' return true;', ' }a}' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 2, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 3, 11, false); assertCursor(cursor, new Selection(3, 11, 3, 11)); @@ -2821,7 +2982,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 3, 2, false); assertCursor(cursor, new Selection(3, 2, 3, 2)); @@ -2848,7 +3009,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t\t}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 3, 4, false); assertCursor(cursor, new Selection(3, 4, 3, 4)); @@ -2874,8 +3035,7 @@ suite('Editor Controller - Indentation Rules', () => { ' return true;', '}a}' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 2, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 3, 2, false); assertCursor(cursor, new Selection(3, 2, 3, 2)); @@ -2905,7 +3065,7 @@ suite('Editor Controller - Indentation Rules', () => { '}a}' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 2, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { tabSize: 2 } }, (model, cursor) => { moveTo(cursor, 3, 3, false); assertCursor(cursor, new Selection(3, 3, 3, 3)); @@ -2931,7 +3091,7 @@ suite('Editor Controller - Indentation Rules', () => { '' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: true, tabSize: 2, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { tabSize: 2 } }, (model, cursor) => { moveTo(cursor, 3, 5, false); moveTo(cursor, 4, 3, true); @@ -2952,11 +3112,7 @@ suite('Editor Controller - Indentation Rules', () => { '}' ], modelOpts: { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, languageIdentifier: mode.getLanguageIdentifier(), }, (model, cursor) => { @@ -2979,11 +3135,7 @@ suite('Editor Controller - Indentation Rules', () => { '}' ], modelOpts: { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, languageIdentifier: mode.getLanguageIdentifier(), }, (model, cursor) => { @@ -3007,7 +3159,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}', '?>' ], - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 5, 3, false); assertCursor(cursor, new Selection(5, 3, 5, 3)); @@ -3026,7 +3178,7 @@ suite('Editor Controller - Indentation Rules', () => { ' return 5;', ' ' ], - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + modelOpts: { insertSpaces: false } }, (model, cursor) => { moveTo(cursor, 3, 2, false); assertCursor(cursor, new Selection(3, 2, 3, 2)); @@ -3038,7 +3190,7 @@ suite('Editor Controller - Indentation Rules', () => { }); test('bug #16543: Tab should indent to correct indentation spot immediately', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'function baz() {', '\tfunction hello() { // something here', @@ -3048,11 +3200,7 @@ suite('Editor Controller - Indentation Rules', () => { '}' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -3070,7 +3218,7 @@ suite('Editor Controller - Indentation Rules', () => { test('bug #2938 (1): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '\tfunction baz() {', '\t\tfunction hello() { // something here', @@ -3080,11 +3228,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -3102,7 +3246,7 @@ suite('Editor Controller - Indentation Rules', () => { test('bug #2938 (2): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '\tfunction baz() {', '\t\tfunction hello() { // something here', @@ -3112,11 +3256,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -3133,7 +3273,7 @@ suite('Editor Controller - Indentation Rules', () => { }); test('bug #2938 (3): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '\tfunction baz() {', '\t\tfunction hello() { // something here', @@ -3143,11 +3283,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -3164,7 +3300,7 @@ suite('Editor Controller - Indentation Rules', () => { }); test('bug #2938 (4): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ '\tfunction baz() {', '\t\tfunction hello() { // something here', @@ -3174,11 +3310,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t}' ].join('\n'), { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, insertSpaces: false, - tabSize: 4, - trimAutoWhitespace: true }, mode.getLanguageIdentifier() ); @@ -3196,7 +3328,7 @@ suite('Editor Controller - Indentation Rules', () => { test('bug #31015: When pressing Tab on lines and Enter rules are avail, indent straight to the right spotTab', () => { let mode = new OnEnterMode(IndentAction.Indent); - let model = TextModel.createFromString( + let model = createTextModel( [ ' if (a) {', ' ', @@ -3204,13 +3336,7 @@ suite('Editor Controller - Indentation Rules', () => { '', ' }' ].join('\n'), - { - insertSpaces: true, - tabSize: 4, - detectIndentation: false, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true - }, + undefined, mode.getLanguageIdentifier() ); @@ -3233,20 +3359,14 @@ suite('Editor Controller - Indentation Rules', () => { increaseIndentPattern: /^\s*((begin|class|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while)|(.*\sdo\b))\b[^\{;]*$/, decreaseIndentPattern: /^\s*([}\]]([,)]?\s*(#|$)|\.[a-zA-Z_]\w*\b)|(end|rescue|ensure|else|elsif|when)\b)/ }); - let model = TextModel.createFromString( + let model = createTextModel( [ 'class Greeter', ' def initialize(name)', ' @name = name', ' en' ].join('\n'), - { - defaultEOL: DefaultEndOfLine.LF, - detectIndentation: false, - insertSpaces: true, - tabSize: 2, - trimAutoWhitespace: true - }, + undefined, rubyMode.getLanguageIdentifier() ); @@ -3271,8 +3391,7 @@ suite('Editor Controller - Indentation Rules', () => { '\t\tconsole.log()', '\t}' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 5, 3, false); assertCursor(cursor, new Selection(5, 3, 5, 3)); @@ -3293,8 +3412,7 @@ suite('Editor Controller - Indentation Rules', () => { ') {', '}' ], - languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } + languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 2, 3, false); assertCursor(cursor, new Selection(2, 3, 2, 3)); @@ -3313,7 +3431,6 @@ suite('Editor Controller - Indentation Rules', () => { '\t\t' ], languageIdentifier: mode.getLanguageIdentifier(), - modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }, editorOpts: { autoIndent: true } }, (model, cursor) => { moveTo(cursor, 3, 3, false); @@ -3372,7 +3489,7 @@ suite('Editor Controller - Indentation Rules', () => { } let mode = new JSMode(); - let model = TextModel.createFromString( + let model = createTextModel( [ 'class ItemCtrl {', ' getPropertiesByItemId(id) {', @@ -3432,7 +3549,7 @@ suite('Editor Controller - Indentation Rules', () => { } let mode = new CppMode(); - let model = TextModel.createFromString( + let model = createTextModel( [ 'int main() {', ' return 0;', @@ -3444,7 +3561,7 @@ suite('Editor Controller - Indentation Rules', () => { '', ')', ].join('\n'), - { insertSpaces: true, detectIndentation: false, tabSize: 2, trimAutoWhitespace: false, defaultEOL: DefaultEndOfLine.LF }, + { tabSize: 2 }, mode.getLanguageIdentifier() ); @@ -3477,12 +3594,12 @@ suite('Editor Controller - Indentation Rules', () => { interface ICursorOpts { text: string[]; languageIdentifier?: LanguageIdentifier; - modelOpts?: ITextModelCreationOptions; + modelOpts?: IRelaxedTextModelCreationOptions; editorOpts?: IEditorOptions; } function usingCursor(opts: ICursorOpts, callback: (model: TextModel, cursor: Cursor) => void): void { - let model = TextModel.createFromString(opts.text.join('\n'), opts.modelOpts, opts.languageIdentifier); + let model = createTextModel(opts.text.join('\n'), opts.modelOpts, opts.languageIdentifier); model.forceTokenization(model.getLineCount()); let config = new TestConfiguration(opts.editorOpts); let viewModel = new ViewModel(0, config, model, null); @@ -4044,7 +4161,7 @@ suite('autoClosingPairs', () => { test('All cursors should do the same thing when deleting left', () => { let mode = new AutoClosingMode(); - let model = TextModel.createFromString( + let model = createTextModel( [ 'var a = ()' ].join('\n'), @@ -4068,7 +4185,7 @@ suite('autoClosingPairs', () => { }); test('issue #7100: Mouse word selection is strange when non-word character is at the end of line', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'before.a', 'before', @@ -4098,7 +4215,7 @@ suite('autoClosingPairs', () => { suite('Undo stops', () => { test('there is an undo stop between typing and deleting left', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4127,7 +4244,7 @@ suite('Undo stops', () => { }); test('there is an undo stop between typing and deleting right', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4156,7 +4273,7 @@ suite('Undo stops', () => { }); test('there is an undo stop between deleting left and typing', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4190,7 +4307,7 @@ suite('Undo stops', () => { }); test('there is an undo stop between deleting left and deleting right', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4228,7 +4345,7 @@ suite('Undo stops', () => { }); test('there is an undo stop between deleting right and typing', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4259,7 +4376,7 @@ suite('Undo stops', () => { }); test('there is an undo stop between deleting right and deleting left', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', @@ -4295,7 +4412,7 @@ suite('Undo stops', () => { }); test('inserts undo stop when typing space', () => { - let model = TextModel.createFromString( + let model = createTextModel( [ 'A line', 'Another line', diff --git a/src/vs/editor/test/browser/controller/textAreaState.test.ts b/src/vs/editor/test/browser/controller/textAreaState.test.ts index 3f11a80175..333cfc3ea9 100644 --- a/src/vs/editor/test/browser/controller/textAreaState.test.ts +++ b/src/vs/editor/test/browser/controller/textAreaState.test.ts @@ -82,7 +82,7 @@ suite('TextAreaState', () => { textArea._value = 'Hello world!'; textArea._selectionStart = 1; textArea._selectionEnd = 12; - let actual = TextAreaState.EMPTY.readFromTextArea(textArea); + let actual = TextAreaState.readFromTextArea(textArea); assertTextAreaState(actual, 'Hello world!', 1, 12); assert.equal(actual.value, 'Hello world!'); @@ -124,7 +124,7 @@ suite('TextAreaState', () => { textArea.dispose(); }); - function testDeduceInput(prevState: TextAreaState, value: string, selectionStart: number, selectionEnd: number, expected: string, expectedCharReplaceCnt: number): void { + function testDeduceInput(prevState: TextAreaState, value: string, selectionStart: number, selectionEnd: number, couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean, expected: string, expectedCharReplaceCnt: number): void { prevState = prevState || TextAreaState.EMPTY; let textArea = new MockTextAreaWrapper(); @@ -132,8 +132,8 @@ suite('TextAreaState', () => { textArea._selectionStart = selectionStart; textArea._selectionEnd = selectionEnd; - let newState = prevState.readFromTextArea(textArea); - let actual = TextAreaState.deduceInput(prevState, newState, true); + let newState = TextAreaState.readFromTextArea(textArea); + let actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput, couldBeTypingAtOffset0); assert.equal(actual.text, expected); assert.equal(actual.replaceCharCnt, expectedCharReplaceCnt); @@ -154,7 +154,7 @@ suite('TextAreaState', () => { testDeduceInput( TextAreaState.EMPTY, 's', - 0, 1, + 0, 1, true, false, 's', 0 ); @@ -164,7 +164,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('s', 0, 1, null, null), 'せ', - 0, 1, + 0, 1, true, false, 'せ', 1 ); @@ -174,7 +174,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せ', 0, 1, null, null), 'せn', - 0, 2, + 0, 2, true, false, 'せn', 1 ); @@ -184,7 +184,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せn', 0, 2, null, null), 'せん', - 0, 2, + 0, 2, true, false, 'せん', 2 ); @@ -194,7 +194,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せん', 0, 2, null, null), 'せんs', - 0, 3, + 0, 3, true, false, 'せんs', 2 ); @@ -204,7 +204,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんs', 0, 3, null, null), 'せんせ', - 0, 3, + 0, 3, true, false, 'せんせ', 3 ); @@ -214,7 +214,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんせ', 0, 3, null, null), 'せんせ', - 0, 3, + 0, 3, true, false, 'せんせ', 3 ); @@ -224,7 +224,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんせ', 0, 3, null, null), 'せんせい', - 0, 4, + 0, 4, true, false, 'せんせい', 3 ); @@ -234,7 +234,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんせい', 0, 4, null, null), 'せんせい', - 4, 4, + 4, 4, true, false, '', 0 ); }); @@ -253,7 +253,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんせい', 0, 4, null, null), 'せんせい', - 0, 4, + 0, 4, true, false, 'せんせい', 4 ); @@ -263,7 +263,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('せんせい', 0, 4, null, null), '先生', - 0, 2, + 0, 2, true, false, '先生', 4 ); @@ -273,7 +273,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('先生', 0, 2, null, null), '先生', - 2, 2, + 2, 2, true, false, '', 0 ); }); @@ -282,7 +282,7 @@ suite('TextAreaState', () => { testDeduceInput( null, 'a', - 0, 1, + 0, 1, true, false, 'a', 0 ); }); @@ -291,7 +291,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState(']\n', 1, 2, null, null), ']\n', - 2, 2, + 2, 2, true, false, '\n', 0 ); }); @@ -300,7 +300,7 @@ suite('TextAreaState', () => { testDeduceInput( null, 'a', - 1, 1, + 1, 1, true, false, 'a', 0 ); }); @@ -309,7 +309,7 @@ suite('TextAreaState', () => { testDeduceInput( TextAreaState.EMPTY, 'a', - 0, 1, + 0, 1, true, false, 'a', 0 ); }); @@ -318,7 +318,7 @@ suite('TextAreaState', () => { testDeduceInput( TextAreaState.EMPTY, 'a', - 1, 1, + 1, 1, true, false, 'a', 0 ); }); @@ -327,7 +327,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 0, 12, null, null), 'H', - 1, 1, + 1, 1, true, false, 'H', 0 ); }); @@ -336,7 +336,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 12, 12, null, null), 'Hello world!a', - 13, 13, + 13, 13, true, false, 'a', 0 ); }); @@ -345,7 +345,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 0, 0, null, null), 'aHello world!', - 1, 1, + 1, 1, true, false, 'a', 0 ); }); @@ -354,7 +354,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 6, 11, null, null), 'Hello other!', - 11, 11, + 11, 11, true, false, 'other', 0 ); }); @@ -363,7 +363,7 @@ suite('TextAreaState', () => { testDeduceInput( TextAreaState.EMPTY, 'これは', - 3, 3, + 3, 3, true, false, 'これは', 0 ); }); @@ -372,7 +372,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 0, 0, null, null), 'Aello world!', - 1, 1, + 1, 1, true, false, 'A', 0 ); }); @@ -381,7 +381,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 5, 5, null, null), 'Hellö world!', - 4, 5, + 4, 5, true, false, 'ö', 0 ); }); @@ -390,7 +390,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 5, 5, null, null), 'Hellöö world!', - 5, 5, + 5, 5, true, false, 'öö', 1 ); }); @@ -399,7 +399,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 5, 5, null, null), 'Helöö world!', - 5, 5, + 5, 5, true, false, 'öö', 2 ); }); @@ -408,7 +408,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('Hello world!', 5, 5, null, null), 'Hellö world!', - 5, 5, + 5, 5, true, false, 'ö', 1 ); }); @@ -417,7 +417,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('a', 0, 1, null, null), 'a', - 1, 1, + 1, 1, true, false, 'a', 0 ); }); @@ -426,7 +426,7 @@ suite('TextAreaState', () => { testDeduceInput( new TextAreaState('x x', 0, 1, null, null), 'x x', - 1, 1, + 1, 1, true, false, 'x', 0 ); }); @@ -456,7 +456,7 @@ suite('TextAreaState', () => { 'some6 text', 'some7 text' ].join('\n'), - 4, 4, + 4, 4, true, false, '📅', 0 ); }); @@ -470,7 +470,7 @@ suite('TextAreaState', () => { null, null ), 'some💊1 text', - 6, 6, + 6, 6, true, false, '💊', 0 ); }); @@ -484,7 +484,7 @@ suite('TextAreaState', () => { null, null ), 'qwertyu\nasdfghj\nzxcvbnm🎈', - 25, 25, + 25, 25, true, false, '🎈', 0 ); }); @@ -499,11 +499,25 @@ suite('TextAreaState', () => { null, null ), 'some⌨️1 text', - 6, 6, + 6, 6, true, false, '⌨️', 0 ); }); + test('issue #42251: Minor issue, character swapped when typing', () => { + // Typing on OSX occurs at offset 0 after moving the window using the custom (non-native) titlebar. + testDeduceInput( + new TextAreaState( + 'ab', + 2, 2, + null, null + ), + 'cab', + 1, 1, true, true, + 'c', 0 + ); + }); + suite('PagedScreenReaderStrategy', () => { function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void { diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts index 88076a7baf..ffb9099400 100644 --- a/src/vs/editor/test/browser/testCodeEditor.ts +++ b/src/vs/editor/test/browser/testCodeEditor.ts @@ -17,13 +17,15 @@ import { TextModel } from 'vs/editor/common/model/textModel'; import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { IPosition } from 'vs/editor/common/core/position'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; export class TestCodeEditor extends CommonCodeEditor implements editorBrowser.ICodeEditor { @@ -168,12 +170,14 @@ export function createTestCodeEditor(model: ITextModel): TestCodeEditor { function _createTestCodeEditor(options: TestCodeEditorCreationOptions): TestCodeEditor { let contextKeyService = new MockContextKeyService(); + let notificationService = new TestNotificationService(); let services = options.serviceCollection || new ServiceCollection(); services.set(IContextKeyService, contextKeyService); + services.set(INotificationService, notificationService); let instantiationService = new InstantiationService(services); - let editor = new TestCodeEditor(new MockScopeLocation(), options, instantiationService, contextKeyService); + let editor = new TestCodeEditor(new MockScopeLocation(), options, false, instantiationService, contextKeyService, notificationService); editor.setModel(options.model); return editor; } diff --git a/src/vs/editor/test/common/config/commonEditorConfig.test.ts b/src/vs/editor/test/common/config/commonEditorConfig.test.ts index 642e5dd254..96734f7962 100644 --- a/src/vs/editor/test/common/config/commonEditorConfig.test.ts +++ b/src/vs/editor/test/common/config/commonEditorConfig.test.ts @@ -89,7 +89,7 @@ suite('Common Editor Config', () => { wordWrap: <any>true }); // {{SQL CARBON EDIT}} - assertWrapping(config, true, 89); + assertWrapping(config, true, 88); }); test('wordWrap on', () => { @@ -97,7 +97,7 @@ suite('Common Editor Config', () => { wordWrap: 'on' }); // {{SQL CARBON EDIT}} - assertWrapping(config, true, 89); + assertWrapping(config, true, 88); }); test('wordWrap on without minimap', () => { @@ -107,7 +107,7 @@ suite('Common Editor Config', () => { enabled: false } }); - assertWrapping(config, true, 89); + assertWrapping(config, true, 88); }); test('wordWrap on does not use wordWrapColumn', () => { @@ -116,7 +116,7 @@ suite('Common Editor Config', () => { wordWrapColumn: 10 }); // {{SQL CARBON EDIT}} - assertWrapping(config, true, 89); + assertWrapping(config, true, 88); }); test('wordWrap off', () => { diff --git a/src/vs/editor/test/common/core/viewLineToken.ts b/src/vs/editor/test/common/core/viewLineToken.ts index 346b531c85..8e96c5fd74 100644 --- a/src/vs/editor/test/common/core/viewLineToken.ts +++ b/src/vs/editor/test/common/core/viewLineToken.ts @@ -92,6 +92,10 @@ export class ViewLineTokens implements IViewLineTokens { public getInlineStyle(tokenIndex: number, colorMap: string[]): string { return this._actual[tokenIndex].getInlineStyle(colorMap); } + + public findTokenIndexAtOffset(offset: number): number { + throw new Error('Not implemented'); + } } export class ViewLineTokenFactory { diff --git a/src/vs/editor/test/common/diff/diffComputer.test.ts b/src/vs/editor/test/common/diff/diffComputer.test.ts index 291bdf5304..1e5e38ee3a 100644 --- a/src/vs/editor/test/common/diff/diffComputer.test.ts +++ b/src/vs/editor/test/common/diff/diffComputer.test.ts @@ -673,4 +673,23 @@ suite('Editor Diff - DiffComputer', () => { ]; assertDiff(original, modified, expected, true, false); }); + + test('issue #43922', () => { + let original = [ + ' * `yarn [install]` -- Install project NPM dependencies. This is automatically done when you first create the project. You should only need to run this if you add dependencies in `package.json`.', + ]; + let modified = [ + ' * `yarn` -- Install project NPM dependencies. You should only need to run this if you add dependencies in `package.json`.', + ]; + var expected = [ + createLineChange( + 1, 1, 1, 1, + [ + createCharChange(1, 9, 1, 19, 0, 0, 0, 0), + createCharChange(1, 58, 1, 120, 0, 0, 0, 0), + ] + ) + ]; + assertDiff(original, modified, expected, true, false); + }); }); diff --git a/src/vs/editor/test/common/editorTestUtils.ts b/src/vs/editor/test/common/editorTestUtils.ts index 2b1e3f3712..bc0baae881 100644 --- a/src/vs/editor/test/common/editorTestUtils.ts +++ b/src/vs/editor/test/common/editorTestUtils.ts @@ -5,9 +5,35 @@ 'use strict'; import { TextModel } from 'vs/editor/common/model/textModel'; +import { DefaultEndOfLine, ITextModelCreationOptions } from 'vs/editor/common/model'; +import { LanguageIdentifier } from 'vs/editor/common/modes'; +import URI from 'vs/base/common/uri'; export function withEditorModel(text: string[], callback: (model: TextModel) => void): void { var model = TextModel.createFromString(text.join('\n')); callback(model); model.dispose(); } + +export interface IRelaxedTextModelCreationOptions { + tabSize?: number; + insertSpaces?: boolean; + detectIndentation?: boolean; + trimAutoWhitespace?: boolean; + defaultEOL?: DefaultEndOfLine; + isForSimpleWidget?: boolean; + largeFileOptimizations?: boolean; +} + +export function createTextModel(text: string, _options: IRelaxedTextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): TextModel { + const options: ITextModelCreationOptions = { + tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize), + insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces), + detectIndentation: (typeof _options.detectIndentation === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.detectIndentation : _options.detectIndentation), + trimAutoWhitespace: (typeof _options.trimAutoWhitespace === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.trimAutoWhitespace : _options.trimAutoWhitespace), + defaultEOL: (typeof _options.defaultEOL === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL : _options.defaultEOL), + isForSimpleWidget: (typeof _options.isForSimpleWidget === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.isForSimpleWidget : _options.isForSimpleWidget), + largeFileOptimizations: (typeof _options.largeFileOptimizations === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.largeFileOptimizations : _options.largeFileOptimizations), + }; + return TextModel.createFromString(text, options, languageIdentifier, uri); +} diff --git a/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts index 55380ec870..de934bb21a 100644 --- a/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts +++ b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts @@ -4,9 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ITextBufferBuilder, ITextBufferFactory, ITextBuffer, DefaultEndOfLine } from 'vs/editor/common/model'; -import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; -import { ChunksTextBufferBuilder } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder'; export function doBenchmark<T>(id: string, ts: T[], fn: (t: T) => void) { let columns: string[] = [id]; @@ -57,7 +55,7 @@ export class BenchmarkSuite { for (let i = 0; i < this.benchmarks.length; i++) { let benchmark = this.benchmarks[i]; let columns: string[] = [benchmark.name]; - [new LinesTextBufferBuilder(), new PieceTreeTextBufferBuilder(), new ChunksTextBufferBuilder()].forEach((builder: ITextBufferBuilder) => { + [new PieceTreeTextBufferBuilder()].forEach((builder: ITextBufferBuilder) => { let timeDiffTotal = 0.0; for (let j = 0; j < this.iterations; j++) { let factory = benchmark.buildBuffer(builder); diff --git a/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts b/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts index c31586fad5..c46771c835 100644 --- a/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts +++ b/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts @@ -4,13 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; import { ITextBufferBuilder } from 'vs/editor/common/model'; import { generateRandomChunkWithLF } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; import { doBenchmark } from 'vs/editor/test/common/model/benchmark/benchmarkUtils'; -let linesTextBufferBuilder = new LinesTextBufferBuilder(); let pieceTreeTextBufferBuilder = new PieceTreeTextBufferBuilder(); let chunks = []; @@ -30,5 +28,5 @@ let modelBuildBenchmark = function (id: string, builders: ITextBufferBuilder[], console.log(`|model builder\t|line buffer\t|piece table\t|`); console.log('|---|---|---|'); for (let i of [10, 100]) { - modelBuildBenchmark(`${i} random chunks`, [linesTextBufferBuilder, pieceTreeTextBufferBuilder], i); + modelBuildBenchmark(`${i} random chunks`, [pieceTreeTextBufferBuilder], i); } diff --git a/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts b/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts deleted file mode 100644 index ebbe9801b3..0000000000 --- a/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 assert from 'assert'; -import { BufferPiece } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; - -suite('BufferPiece', () => { - test('findLineStartBeforeOffset', () => { - let piece = new BufferPiece([ - 'Line1\r\n', - 'l2\n', - 'another\r', - 'and\r\n', - 'finally\n', - 'last' - ].join('')); - - assert.equal(piece.length(), 35); - assert.deepEqual(piece.findLineStartBeforeOffset(0), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(1), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(2), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(3), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(4), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(5), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(6), -1); - assert.deepEqual(piece.findLineStartBeforeOffset(7), 0); - assert.deepEqual(piece.findLineStartBeforeOffset(8), 0); - assert.deepEqual(piece.findLineStartBeforeOffset(9), 0); - assert.deepEqual(piece.findLineStartBeforeOffset(10), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(11), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(12), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(13), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(14), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(15), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(16), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(17), 1); - assert.deepEqual(piece.findLineStartBeforeOffset(18), 2); - assert.deepEqual(piece.findLineStartBeforeOffset(19), 2); - assert.deepEqual(piece.findLineStartBeforeOffset(20), 2); - assert.deepEqual(piece.findLineStartBeforeOffset(21), 2); - assert.deepEqual(piece.findLineStartBeforeOffset(22), 2); - assert.deepEqual(piece.findLineStartBeforeOffset(23), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(24), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(25), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(26), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(27), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(28), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(29), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(30), 3); - assert.deepEqual(piece.findLineStartBeforeOffset(31), 4); - assert.deepEqual(piece.findLineStartBeforeOffset(32), 4); - assert.deepEqual(piece.findLineStartBeforeOffset(33), 4); - assert.deepEqual(piece.findLineStartBeforeOffset(34), 4); - assert.deepEqual(piece.findLineStartBeforeOffset(35), 4); - assert.deepEqual(piece.findLineStartBeforeOffset(36), 4); - }); -}); diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 758e714ddf..548056394f 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; -import { EndOfLineSequence, IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; +import { EndOfLineSequence, IIdentifiedSingleEditOperation, EndOfLinePreference } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import { MirrorTextModel } from 'vs/editor/common/model/mirrorTextModel'; import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils'; @@ -1069,4 +1069,48 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { model.dispose(); mirrorModel2.dispose(); }); + + test('issue #47733: Undo mangles unicode characters', () => { + let model = createEditableTextModelFromString('\'👁\''); + + model.applyEdits([ + { range: new Range(1, 1, 1, 1), text: '"' }, + { range: new Range(1, 2, 1, 2), text: '"' }, + ]); + + assert.equal(model.getValue(EndOfLinePreference.LF), '"\'"👁\''); + + assert.deepEqual(model.validateRange(new Range(1, 3, 1, 4)), new Range(1, 3, 1, 4)); + + model.applyEdits([ + { range: new Range(1, 1, 1, 2), text: null }, + { range: new Range(1, 3, 1, 4), text: null }, + ]); + + assert.equal(model.getValue(EndOfLinePreference.LF), '\'👁\''); + + model.dispose(); + }); + + test('issue #48741: Broken undo stack with move lines up with multiple cursors', () => { + let model = createEditableTextModelFromString([ + 'line1', + 'line2', + 'line3', + '', + ].join('\n')); + + const undoEdits = model.applyEdits([ + { range: new Range(4, 1, 4, 1), text: 'line3', }, + { range: new Range(3, 1, 3, 6), text: null, }, + { range: new Range(2, 1, 3, 1), text: null, }, + { range: new Range(3, 6, 3, 6), text: '\nline2' } + ]); + + model.applyEdits(undoEdits); + + assert.deepEqual(model.getValue(), 'line1\nline2\nline3\n'); + + model.dispose(); + }); }); diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index f13c33536b..a4897a73fb 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -31,8 +31,17 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent assert.deepEqual(model.getValue(EndOfLinePreference.LF), originalStr); if (!inputEditsAreInvalid) { + const simplifyEdit = (edit: IIdentifiedSingleEditOperation) => { + return { + identifier: edit.identifier, + range: edit.range, + text: edit.text, + forceMoveMarkers: edit.forceMoveMarkers, + isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit + }; + }; // Assert the inverse of the inverse edits are the original edits - assert.deepEqual(inverseInverseEdits, edits); + assert.deepEqual(inverseInverseEdits.map(simplifyEdit), edits.map(simplifyEdit)); } assertMirrorModels(); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts index e1e8ed330e..051816f836 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts @@ -7,9 +7,11 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; -import { LinesTextBuffer, IValidatedEditOperation } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer'; +import { PieceTreeTextBuffer, IValidatedEditOperation } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; +import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; +import { DefaultEndOfLine } from 'vs/editor/common/model'; -suite('LinesTextBuffer._getInverseEdits', () => { +suite('PieceTreeTextBuffer._getInverseEdits', () => { function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text: string[]): IValidatedEditOperation { return { @@ -29,7 +31,7 @@ suite('LinesTextBuffer._getInverseEdits', () => { } function assertInverseEdits(ops: IValidatedEditOperation[], expected: Range[]): void { - var actual = LinesTextBuffer._getInverseEditRanges(ops); + var actual = PieceTreeTextBuffer._getInverseEditRanges(ops); assert.deepEqual(actual, expected); } @@ -260,7 +262,7 @@ suite('LinesTextBuffer._getInverseEdits', () => { }); }); -suite('LinesTextBuffer._toSingleEditOperation', () => { +suite('PieceTreeTextBuffer._toSingleEditOperation', () => { function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, rangeOffset: number, rangeLength: number, text: string[]): IValidatedEditOperation { return { @@ -276,13 +278,7 @@ suite('LinesTextBuffer._toSingleEditOperation', () => { } function testToSingleEditOperation(original: string[], edits: IValidatedEditOperation[], expected: IValidatedEditOperation): void { - const textBuffer = new LinesTextBuffer({ - BOM: '', - EOL: '\n', - containsRTL: false, - isBasicASCII: true, - lines: original - }); + const textBuffer = <PieceTreeTextBuffer>createTextBufferFactory(original.join('\n')).create(DefaultEndOfLine.LF); const actual = textBuffer._toSingleEditOperation(edits); assert.deepEqual(actual, expected); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts index bc5facd908..97148b545b 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts @@ -5,150 +5,69 @@ 'use strict'; import * as assert from 'assert'; -import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; -import { ITextModelCreationOptions } from 'vs/editor/common/model'; -import { TextModel } from 'vs/editor/common/model/textModel'; +import { DefaultEndOfLine } from 'vs/editor/common/model'; +import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; import * as strings from 'vs/base/common/strings'; -import { IRawTextSource } from 'vs/editor/common/model/linesTextBuffer/textSource'; +import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; -class RawTextSource { - public static fromString(rawText: string): IRawTextSource { - // Count the number of lines that end with \r\n - let carriageReturnCnt = 0; - let lastCarriageReturnIndex = -1; - while ((lastCarriageReturnIndex = rawText.indexOf('\r', lastCarriageReturnIndex + 1)) !== -1) { - carriageReturnCnt++; - } +export function testTextBufferFactory(text: string, eol: string, mightContainNonBasicASCII: boolean, mightContainRTL: boolean): void { + const textBuffer = <PieceTreeTextBuffer>createTextBufferFactory(text).create(DefaultEndOfLine.LF); - const containsRTL = strings.containsRTL(rawText); - const isBasicASCII = (containsRTL ? false : strings.isBasicASCII(rawText)); - - // Split the text into lines - const lines = rawText.split(/\r\n|\r|\n/); - - // Remove the BOM (if present) - let BOM = ''; - if (strings.startsWithUTF8BOM(lines[0])) { - BOM = strings.UTF8_BOM_CHARACTER; - lines[0] = lines[0].substr(1); - } - - return { - BOM: BOM, - lines: lines, - containsRTL: containsRTL, - isBasicASCII: isBasicASCII, - totalCRCount: carriageReturnCnt - }; - } -} - -export function testModelBuilder(chunks: string[], opts: ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS): void { - let expectedTextSource = RawTextSource.fromString(chunks.join('')); - - let builder = new LinesTextBufferBuilder(); - for (let i = 0, len = chunks.length; i < len; i++) { - builder.acceptChunk(chunks[i]); - } - let actual = builder.finish(); - - assert.deepEqual(actual.rawTextSource, expectedTextSource); + assert.equal(textBuffer.mightContainNonBasicASCII(), mightContainNonBasicASCII); + assert.equal(textBuffer.mightContainRTL(), mightContainRTL); + assert.equal(textBuffer.getEOL(), eol); } suite('ModelBuilder', () => { - test('no chunks', () => { - testModelBuilder([]); + test('t1', () => { + testTextBufferFactory('', '\n', false, false); }); - test('single empty chunk', () => { - testModelBuilder(['']); + test('t2', () => { + testTextBufferFactory('Hello world', '\n', false, false); }); - test('single line in one chunk', () => { - testModelBuilder(['Hello world']); + test('t3', () => { + testTextBufferFactory('Hello world\nHow are you?', '\n', false, false); }); - test('single line in multiple chunks', () => { - testModelBuilder(['Hello', ' ', 'world']); - }); - - test('two lines in single chunk', () => { - testModelBuilder(['Hello world\nHow are you?']); - }); - - test('two lines in multiple chunks 1', () => { - testModelBuilder(['Hello worl', 'd\nHow are you?']); - }); - - test('two lines in multiple chunks 2', () => { - testModelBuilder(['Hello worl', 'd', '\n', 'H', 'ow are you?']); - }); - - test('two lines in multiple chunks 3', () => { - testModelBuilder(['Hello worl', 'd', '\nHow are you?']); - }); - - test('multiple lines in single chunks', () => { - testModelBuilder(['Hello world\nHow are you?\nIs everything good today?\nDo you enjoy the weather?']); - }); - - test('multiple lines in multiple chunks 1', () => { - testModelBuilder(['Hello world\nHow are you', '?\nIs everything good today?\nDo you enjoy the weather?']); - }); - - test('multiple lines in multiple chunks 1', () => { - testModelBuilder(['Hello world', '\nHow are you', '?\nIs everything good today?', '\nDo you enjoy the weather?']); - }); - - test('multiple lines in multiple chunks 1', () => { - testModelBuilder(['Hello world\n', 'How are you', '?\nIs everything good today?', '\nDo you enjoy the weather?']); + test('t4', () => { + testTextBufferFactory('Hello world\nHow are you?\nIs everything good today?\nDo you enjoy the weather?', '\n', false, false); }); test('carriage return detection (1 \\r\\n 2 \\n)', () => { - testModelBuilder(['Hello world\r\n', 'How are you', '?\nIs everything good today?', '\nDo you enjoy the weather?']); + testTextBufferFactory('Hello world\r\nHow are you?\nIs everything good today?\nDo you enjoy the weather?', '\n', false, false); }); test('carriage return detection (2 \\r\\n 1 \\n)', () => { - testModelBuilder(['Hello world\r\n', 'How are you', '?\r\nIs everything good today?', '\nDo you enjoy the weather?']); + testTextBufferFactory('Hello world\r\nHow are you?\r\nIs everything good today?\nDo you enjoy the weather?', '\r\n', false, false); }); test('carriage return detection (3 \\r\\n 0 \\n)', () => { - testModelBuilder(['Hello world\r\n', 'How are you', '?\r\nIs everything good today?', '\r\nDo you enjoy the weather?']); - }); - - test('carriage return detection (isolated \\r)', () => { - testModelBuilder(['Hello world', '\r', '\n', 'How are you', '?', '\r', '\n', 'Is everything good today?', '\r', '\n', 'Do you enjoy the weather?']); + testTextBufferFactory('Hello world\r\nHow are you?\r\nIs everything good today?\r\nDo you enjoy the weather?', '\r\n', false, false); }); test('BOM handling', () => { - testModelBuilder([strings.UTF8_BOM_CHARACTER + 'Hello world!']); + testTextBufferFactory(strings.UTF8_BOM_CHARACTER + 'Hello world!', '\n', false, false); }); test('BOM handling', () => { - testModelBuilder([strings.UTF8_BOM_CHARACTER, 'Hello world!']); - }); - - test('RTL handling 1', () => { - testModelBuilder(['Hello world!', 'זוהי עובדה מבוססת שדעתו']); + testTextBufferFactory(strings.UTF8_BOM_CHARACTER + 'Hello world!', '\n', false, false); }); test('RTL handling 2', () => { - testModelBuilder(['Hello world!זוהי עובדה מבוססת שדעתו']); + testTextBufferFactory('Hello world!זוהי עובדה מבוססת שדעתו', '\n', true, true); }); test('RTL handling 3', () => { - testModelBuilder(['Hello world!זוהי \nעובדה מבוססת שדעתו']); + testTextBufferFactory('Hello world!זוהי \nעובדה מבוססת שדעתו', '\n', true, true); }); test('ASCII handling 1', () => { - testModelBuilder(['Hello world!!\nHow do you do?']); + testTextBufferFactory('Hello world!!\nHow do you do?', '\n', false, false); }); - test('ASCII handling 1', () => { - testModelBuilder(['Hello world!!\nHow do you do?Züricha📚📚b']); - }); - - test('issue #32819: some special string cannot be displayed completely', () => { - testModelBuilder(['AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA123']); + test('ASCII handling 2', () => { + testTextBufferFactory('Hello world!!\nHow do you do?Züricha📚📚b', '\n', true, false); }); }); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts deleted file mode 100644 index d268560bf7..0000000000 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { testModelBuilder } from './linesTextBufferBuilder.test'; -import { getRandomInt, getRandomEOLSequence, getRandomString } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; - -const GENERATE_TESTS = false; - -suite('ModelBuilder Auto Tests', () => { - - test('auto1', () => { - testModelBuilder(['sarjniow', '\r', '\nbpb', 'ofb', '\njzldgxx', '\r\nkzwfjysng']); - }); - - test('auto2', () => { - testModelBuilder(['i', 'yyernubi\r\niimgn\n', 'ut\r']); - }); - -}); - -function generateRandomFile(): string { - let lineCount = getRandomInt(1, 10); - let mixedEOLSequence = getRandomInt(1, 2) === 1 ? true : false; - let fixedEOL = getRandomEOLSequence(); - let lines: string[] = []; - for (let i = 0; i < lineCount; i++) { - if (i !== 0) { - if (mixedEOLSequence) { - lines.push(getRandomEOLSequence()); - } else { - lines.push(fixedEOL); - } - } - lines.push(getRandomString(0, 10)); - - } - return lines.join(''); -} - -function generateRandomChunks(file: string): string[] { - let result: string[] = []; - let cnt = getRandomInt(1, 20); - - let maxOffset = file.length; - - while (cnt > 0 && maxOffset > 0) { - - let offset = getRandomInt(0, maxOffset); - result.unshift(file.substring(offset, maxOffset)); - // let length = getRandomInt(0, maxOffset - offset); - // let text = generateFile(true); - - // result.push({ - // offset: offset, - // length: length, - // text: text - // }); - - maxOffset = offset; - cnt--; - } - if (maxOffset !== 0) { - result.unshift(file.substring(0, maxOffset)); - } - return result; -} - -function testRandomFile(file: string): boolean { - let tests = getRandomInt(5, 10); - for (let i = 0; i < tests; i++) { - let chunks = generateRandomChunks(file); - try { - testModelBuilder(chunks); - } catch (err) { - console.log(err); - console.log(JSON.stringify(chunks)); - return false; - } - } - return true; -} - -if (GENERATE_TESTS) { - let number = 1; - while (true) { - console.log('------BEGIN NEW TEST: ' + number); - - if (!testRandomFile(generateRandomFile())) { - break; - } - - console.log('------END NEW TEST: ' + (number++)); - } -} diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index 29d29fb7b7..f459d3f0bd 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -13,6 +13,12 @@ import { ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents'; import { TextModel } from 'vs/editor/common/model/textModel'; +import { LanguageIdentifier, TokenizationRegistry, IState, MetadataConsts } from 'vs/editor/common/modes'; +import { MockMode } from 'vs/editor/test/common/mocks/mockMode'; +import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { TokenizationResult2 } from 'vs/editor/common/core/token'; +import { NULL_STATE } from 'vs/editor/common/modes/nullMode'; +import { dispose, Disposable } from 'vs/base/common/lifecycle'; // --------- utils @@ -103,7 +109,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -122,7 +128,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -199,7 +205,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -218,7 +224,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -237,7 +243,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -257,7 +263,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -308,7 +314,7 @@ suite('Editor Model - Model', () => { let e: ModelRawContentChangedEvent = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { - assert.fail(); + assert.fail('Unexpected assertion error'); } e = _e; }); @@ -322,6 +328,16 @@ suite('Editor Model - Model', () => { false )); }); + + test('issue #46342: Maintain edit operation order in applyEdits', () => { + let res = thisModel.applyEdits([ + { range: new Range(2, 1, 2, 1), text: 'a' }, + { range: new Range(1, 1, 1, 1), text: 'b' }, + ]); + + assert.deepEqual(res[0].range, new Range(2, 1, 2, 2)); + assert.deepEqual(res[1].range, new Range(1, 1, 1, 2)); + }); }); @@ -365,18 +381,62 @@ suite('Editor Model - Model Line Separators', () => { suite('Editor Model - Words', () => { - var thisModel: TextModel; + const OUTER_LANGUAGE_ID = new LanguageIdentifier('outerMode', 3); + const INNER_LANGUAGE_ID = new LanguageIdentifier('innerMode', 4); + + class OuterMode extends MockMode { + constructor() { + super(OUTER_LANGUAGE_ID); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {})); + + this._register(TokenizationRegistry.register(this.getLanguageIdentifier().language, { + getInitialState: (): IState => NULL_STATE, + tokenize: undefined, + tokenize2: (line: string, state: IState): TokenizationResult2 => { + const tokensArr: number[] = []; + let prevLanguageId: LanguageIdentifier = undefined; + for (let i = 0; i < line.length; i++) { + const languageId = (line.charAt(i) === 'x' ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID); + if (prevLanguageId !== languageId) { + tokensArr.push(i); + tokensArr.push((languageId.id << MetadataConsts.LANGUAGEID_OFFSET)); + } + prevLanguageId = languageId; + } + + const tokens = new Uint32Array(tokensArr.length); + for (let i = 0; i < tokens.length; i++) { + tokens[i] = tokensArr[i]; + } + return new TokenizationResult2(tokens, state); + } + })); + } + } + + class InnerMode extends MockMode { + constructor() { + super(INNER_LANGUAGE_ID); + this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {})); + } + } + + let disposables: Disposable[] = []; setup(() => { - var text = ['This text has some words. ']; - thisModel = TextModel.createFromString(text.join('\n')); + disposables = []; }); teardown(() => { - thisModel.dispose(); + dispose(disposables); + disposables = []; }); test('Get word at position', () => { + const text = ['This text has some words. ']; + const thisModel = TextModel.createFromString(text.join('\n')); + disposables.push(thisModel); + assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: 'This', startColumn: 1, endColumn: 5 }); assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 2)), { word: 'This', startColumn: 1, endColumn: 5 }); assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 4)), { word: 'This', startColumn: 1, endColumn: 5 }); @@ -389,4 +449,21 @@ suite('Editor Model - Words', () => { assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 27)), null); assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 28)), null); }); + + test('getWordAtPosition at embedded language boundaries', () => { + const outerMode = new OuterMode(); + const innerMode = new InnerMode(); + disposables.push(outerMode, innerMode); + + const model = TextModel.createFromString('ab<xx>ab<x>', undefined, outerMode.getLanguageIdentifier()); + disposables.push(model); + + assert.deepEqual(model.getWordAtPosition(new Position(1, 1)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 2)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 3)), { word: 'ab', startColumn: 1, endColumn: 3 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 4)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 5)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 6)), { word: 'xx', startColumn: 4, endColumn: 6 }); + assert.deepEqual(model.getWordAtPosition(new Position(1, 7)), { word: 'ab', startColumn: 7, endColumn: 9 }); + }); }); diff --git a/src/vs/editor/test/common/model/modelEditOperation.test.ts b/src/vs/editor/test/common/model/modelEditOperation.test.ts index 6781fc234d..22796a2613 100644 --- a/src/vs/editor/test/common/model/modelEditOperation.test.ts +++ b/src/vs/editor/test/common/model/modelEditOperation.test.ts @@ -68,7 +68,16 @@ suite('Editor Model - Model Edit Operation', () => { assert.equal(model.getLineContent(4), LINE4); assert.equal(model.getLineContent(5), LINE5); - assert.deepEqual(originalOp, editOp); + const simplifyEdit = (edit: IIdentifiedSingleEditOperation) => { + return { + identifier: edit.identifier, + range: edit.range, + text: edit.text, + forceMoveMarkers: edit.forceMoveMarkers, + isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit + }; + }; + assert.deepEqual(originalOp.map(simplifyEdit), editOp.map(simplifyEdit)); } test('Insert inline', () => { diff --git a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts index f9f31dc7a7..a07efe8770 100644 --- a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts @@ -12,6 +12,10 @@ import { DefaultEndOfLine } from 'vs/editor/common/model'; import { PieceTreeBase } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; import { SENTINEL, NodeColor, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase'; import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; +import { TextModel } from 'vs/editor/common/model/textModel'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; +import { SearchData } from 'vs/editor/common/model/textModelSearch'; +import { WordCharacterClassifier } from 'vs/editor/common/controller/wordCharacterClassifier'; const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n'; @@ -1441,11 +1445,44 @@ suite('centralized lineStarts with CRLF', () => { }); suite('random is unsupervised', () => { + test('splitting large change buffer', function () { + let pieceTable = createTextBuffer([''], false); + let str = ''; + + pieceTable.insert(0, 'WUZ\nXVZY\n'); + str = str.substring(0, 0) + 'WUZ\nXVZY\n' + str.substring(0); + pieceTable.insert(8, '\r\r\nZXUWVW'); + str = str.substring(0, 8) + '\r\r\nZXUWVW' + str.substring(8); + pieceTable.delete(10, 7); + str = str.substring(0, 10) + str.substring(10 + 7); + pieceTable.delete(10, 1); + str = str.substring(0, 10) + str.substring(10 + 1); + pieceTable.insert(4, 'VX\r\r\nWZVZ'); + str = str.substring(0, 4) + 'VX\r\r\nWZVZ' + str.substring(4); + pieceTable.delete(11, 3); + str = str.substring(0, 11) + str.substring(11 + 3); + pieceTable.delete(12, 4); + str = str.substring(0, 12) + str.substring(12 + 4); + pieceTable.delete(8, 0); + str = str.substring(0, 8) + str.substring(8 + 0); + pieceTable.delete(10, 2); + str = str.substring(0, 10) + str.substring(10 + 2); + pieceTable.insert(0, 'VZXXZYZX\r'); + str = str.substring(0, 0) + 'VZXXZYZX\r' + str.substring(0); + + assert.equal(pieceTable.getLinesRawContent(), str); + + testLineStarts(str, pieceTable); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random insert delete', function () { this.timeout(500000); let str = ''; let pieceTable = createTextBuffer([str], false); + // let output = ''; for (let i = 0; i < 1000; i++) { if (Math.random() < 0.6) { // insert @@ -1453,6 +1490,8 @@ suite('random is unsupervised', () => { let pos = randomInt(str.length + 1); pieceTable.insert(pos, text); str = str.substring(0, pos) + text + str.substring(pos); + // output += `pieceTable.insert(${pos}, '${text.replace(/\n/g, '\\n').replace(/\r/g, '\\r')}');\n`; + // output += `str = str.substring(0, ${pos}) + '${text.replace(/\n/g, '\\n').replace(/\r/g, '\\r')}' + str.substring(${pos});\n`; } else { // delete let pos = randomInt(str.length); @@ -1462,8 +1501,12 @@ suite('random is unsupervised', () => { ); pieceTable.delete(pos, length); str = str.substring(0, pos) + str.substring(pos + length); + // output += `pieceTable.delete(${pos}, ${length});\n`; + // output += `str = str.substring(0, ${pos}) + str.substring(${pos} + ${length});\n` + } } + // console.log(output); assert.equal(pieceTable.getLinesRawContent(), str); @@ -1567,6 +1610,37 @@ suite('buffer api', () => { assert(!a.equal(b)); }); + + test('getLineCharCode - issue #45735', () => { + let pieceTable = createTextBuffer(['LINE1\nline2']); + assert.equal(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); + assert.equal(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); + assert.equal(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); + assert.equal(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); + assert.equal(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); + assert.equal(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); + assert.equal(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); + assert.equal(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); + assert.equal(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); + assert.equal(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); + assert.equal(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); + }); + + + test('getLineCharCode - issue #47733', () => { + let pieceTable = createTextBuffer(['', 'LINE1\n', 'line2']); + assert.equal(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L'); + assert.equal(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I'); + assert.equal(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N'); + assert.equal(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E'); + assert.equal(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1'); + assert.equal(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n'); + assert.equal(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l'); + assert.equal(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i'); + assert.equal(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n'); + assert.equal(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e'); + assert.equal(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2'); + }); }); suite('search offset cache', () => { @@ -1674,4 +1748,154 @@ suite('search offset cache', () => { assertTreeInvariants(pieceTable); }); +}); + +function getValueInSnapshot(snapshot: ITextSnapshot) { + let ret = ''; + let tmp = snapshot.read(); + + while (tmp !== null) { + ret += tmp; + tmp = snapshot.read(); + } + + return ret; +} +suite('snapshot', () => { + test('bug #45564, piece tree pieces should be immutable', () => { + const model = TextModel.createFromString('\n'); + model.applyEdits([ + { + range: new Range(2, 1, 2, 1), + text: '!' + } + ]); + const snapshot = model.createSnapshot(); + const snapshot1 = model.createSnapshot(); + assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + + model.applyEdits([ + { + range: new Range(2, 1, 2, 2), + text: '' + } + ]); + model.applyEdits([ + { + range: new Range(2, 1, 2, 1), + text: '!' + } + ]); + + assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot1)); + }); + + test('immutable snapshot 1', () => { + const model = TextModel.createFromString('abc\ndef'); + const snapshot = model.createSnapshot(); + model.applyEdits([ + { + range: new Range(2, 1, 2, 4), + text: '' + } + ]); + + model.applyEdits([ + { + range: new Range(1, 1, 2, 1), + text: 'abc\ndef' + } + ]); + + assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + }); + + test('immutable snapshot 2', () => { + const model = TextModel.createFromString('abc\ndef'); + const snapshot = model.createSnapshot(); + model.applyEdits([ + { + range: new Range(2, 1, 2, 1), + text: '!' + } + ]); + + model.applyEdits([ + { + range: new Range(2, 1, 2, 2), + text: '' + } + ]); + + assert.equal(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + }); + + test('immutable snapshot 3', () => { + const model = TextModel.createFromString('abc\ndef'); + model.applyEdits([ + { + range: new Range(2, 4, 2, 4), + text: '!' + } + ]); + const snapshot = model.createSnapshot(); + model.applyEdits([ + { + range: new Range(2, 5, 2, 5), + text: '!' + } + ]); + + assert.notEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot)); + }); +}); + +suite('chunk based search', () => { + test('#45892. For some cases, the buffer is empty but we still try to search', () => { + let pieceTree = createTextBuffer(['']); + pieceTree.delete(0, 1); + let ret = pieceTree.findMatchesLineByLine(new Range(1, 1, 1, 1), new SearchData(/abc/, new WordCharacterClassifier(',./'), 'abc'), true, 1000); + assert.equal(ret.length, 0); + }); + + test('#45770. FindInNode should not cross node boundary.', () => { + let pieceTree = createTextBuffer([ + [ + 'balabalababalabalababalabalaba', + 'balabalababalabalababalabalaba', + '', + '* [ ] task1', + '* [x] task2 balabalaba', + '* [ ] task 3' + ].join('\n') + ]); + pieceTree.delete(0, 62); + pieceTree.delete(16, 1); + + pieceTree.insert(16, ' '); + let ret = pieceTree.findMatchesLineByLine(new Range(1, 1, 4, 13), new SearchData(/\[/gi, new WordCharacterClassifier(',./'), '['), true, 1000); + assert.equal(ret.length, 3); + + assert.deepEqual(ret[0].range, new Range(2, 3, 2, 4)); + assert.deepEqual(ret[1].range, new Range(3, 3, 3, 4)); + assert.deepEqual(ret[2].range, new Range(4, 3, 4, 4)); + }); + + test('search searching from the middle', () => { + let pieceTree = createTextBuffer([ + [ + 'def', + 'dbcabc' + ].join('\n') + ]); + pieceTree.delete(4, 1); + let ret = pieceTree.findMatchesLineByLine(new Range(2, 3, 2, 6), new SearchData(/a/gi, null, 'a'), true, 1000); + assert.equal(ret.length, 1); + assert.deepEqual(ret[0].range, new Range(2, 3, 2, 4)); + + pieceTree.delete(4, 1); + ret = pieceTree.findMatchesLineByLine(new Range(2, 2, 2, 5), new SearchData(/a/gi, null, 'a'), true, 1000); + assert.equal(ret.length, 1); + assert.deepEqual(ret[0].range, new Range(2, 2, 2, 3)); + }); }); \ No newline at end of file diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 5f656f30f9..a08064a3b2 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -8,18 +8,16 @@ import * as assert from 'assert'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; -import { DefaultEndOfLine } from 'vs/editor/common/model'; import { UTF8_BOM_CHARACTER } from 'vs/base/common/strings'; +import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; function testGuessIndentation(defaultInsertSpaces: boolean, defaultTabSize: number, expectedInsertSpaces: boolean, expectedTabSize: number, text: string[], msg?: string): void { - var m = TextModel.createFromString( + var m = createTextModel( text.join('\n'), { tabSize: defaultTabSize, insertSpaces: defaultInsertSpaces, - detectIndentation: true, - defaultEOL: DefaultEndOfLine.LF, - trimAutoWhitespace: true + detectIndentation: true } ); var r = m.getOptions(); @@ -705,13 +703,9 @@ suite('Editor Model - TextModel', () => { }); test('normalizeIndentation 1', () => { - let model = TextModel.createFromString('', + let model = createTextModel('', { - detectIndentation: false, - tabSize: 4, - insertSpaces: false, - trimAutoWhitespace: true, - defaultEOL: DefaultEndOfLine.LF + insertSpaces: false } ); @@ -741,15 +735,7 @@ suite('Editor Model - TextModel', () => { }); test('normalizeIndentation 2', () => { - let model = TextModel.createFromString('', - { - detectIndentation: false, - tabSize: 4, - insertSpaces: true, - trimAutoWhitespace: true, - defaultEOL: DefaultEndOfLine.LF - } - ); + let model = createTextModel(''); assert.equal(model.normalizeIndentation('\ta'), ' a'); assert.equal(model.normalizeIndentation(' a'), ' a'); diff --git a/src/vs/editor/test/common/model/textModelWithTokens.test.ts b/src/vs/editor/test/common/model/textModelWithTokens.test.ts index 5113f4dda1..8fbbaf1bef 100644 --- a/src/vs/editor/test/common/model/textModelWithTokens.test.ts +++ b/src/vs/editor/test/common/model/textModelWithTokens.test.ts @@ -366,6 +366,31 @@ suite('TextModelWithTokens regression tests', () => { model.dispose(); registration.dispose(); }); + + test('issue #11856: Bracket matching does not work as expected if the opening brace symbol is contained in the closing brace symbol', () => { + + const languageIdentifier = new LanguageIdentifier('testMode', LanguageId.PlainText); + + let registration = LanguageConfigurationRegistry.register(languageIdentifier, { + brackets: [ + ['sequence', 'endsequence'], + ['feature', 'endfeature'] + ] + }); + + let model = TextModel.createFromString([ + 'sequence "outer"', + ' sequence "inner"', + ' endsequence', + 'endsequence', + ].join('\n'), undefined, languageIdentifier); + + let actual = model.matchBracket(new Position(3, 9)); + assert.deepEqual(actual, [new Range(3, 6, 3, 17), new Range(2, 6, 2, 14)]); + + model.dispose(); + registration.dispose(); + }); }); suite('TextModel.getLineIndentGuide', () => { @@ -380,10 +405,39 @@ suite('TextModel.getLineIndentGuide', () => { actual[line - 1] = [actualIndents[line - 1], model.getLineContent(line)]; } - // let expected = lines.map(l => l[0]); - assert.deepEqual(actual, lines); + // Also test getActiveIndentGuide + for (let lineNumber = 1; lineNumber <= model.getLineCount(); lineNumber++) { + let startLineNumber = lineNumber; + let endLineNumber = lineNumber; + let indent = actualIndents[lineNumber - 1]; + + if (indent !== 0) { + for (let i = lineNumber - 1; i >= 1; i--) { + const currIndent = actualIndents[i - 1]; + if (currIndent >= indent) { + startLineNumber = i; + } else { + break; + } + } + for (let i = lineNumber + 1; i <= model.getLineCount(); i++) { + const currIndent = actualIndents[i - 1]; + if (currIndent >= indent) { + endLineNumber = i; + } else { + break; + } + } + } + + const expected = { startLineNumber, endLineNumber, indent }; + const actual = model.getActiveIndentGuide(lineNumber, 1, model.getLineCount()); + + assert.deepEqual(actual, expected, `line number ${lineNumber}`); + } + model.dispose(); } diff --git a/src/vs/editor/test/common/modes/languageSelector.test.ts b/src/vs/editor/test/common/modes/languageSelector.test.ts index de5294c8fd..9732e3bb3b 100644 --- a/src/vs/editor/test/common/modes/languageSelector.test.ts +++ b/src/vs/editor/test/common/modes/languageSelector.test.ts @@ -17,18 +17,18 @@ suite('LanguageSelector', function () { }; test('score, invalid selector', function () { - assert.equal(score({}, model.uri, model.language), 0); - assert.equal(score(undefined, model.uri, model.language), 0); - assert.equal(score(null, model.uri, model.language), 0); - assert.equal(score('', model.uri, model.language), 0); + assert.equal(score({}, model.uri, model.language, true), 0); + assert.equal(score(undefined, model.uri, model.language, true), 0); + assert.equal(score(null, model.uri, model.language, true), 0); + assert.equal(score('', model.uri, model.language, true), 0); }); test('score, any language', function () { - assert.equal(score({ language: '*' }, model.uri, model.language), 5); - assert.equal(score('*', model.uri, model.language), 5); + assert.equal(score({ language: '*' }, model.uri, model.language, true), 5); + assert.equal(score('*', model.uri, model.language, true), 5); - assert.equal(score('*', URI.parse('foo:bar'), model.language), 5); - assert.equal(score('farboo', URI.parse('foo:bar'), model.language), 10); + assert.equal(score('*', URI.parse('foo:bar'), model.language, true), 5); + assert.equal(score('farboo', URI.parse('foo:bar'), model.language, true), 10); }); test('score, default schemes', function () { @@ -36,49 +36,64 @@ suite('LanguageSelector', function () { const uri = URI.parse('git:foo/file.txt'); const language = 'farboo'; - assert.equal(score('*', uri, language), 5); - assert.equal(score('farboo', uri, language), 10); - assert.equal(score({ language: 'farboo', scheme: '' }, uri, language), 10); - assert.equal(score({ language: 'farboo', scheme: 'git' }, uri, language), 10); - assert.equal(score({ language: 'farboo', scheme: '*' }, uri, language), 10); - assert.equal(score({ language: 'farboo' }, uri, language), 10); - assert.equal(score({ language: '*' }, uri, language), 5); + assert.equal(score('*', uri, language, true), 5); + assert.equal(score('farboo', uri, language, true), 10); + assert.equal(score({ language: 'farboo', scheme: '' }, uri, language, true), 10); + assert.equal(score({ language: 'farboo', scheme: 'git' }, uri, language, true), 10); + assert.equal(score({ language: 'farboo', scheme: '*' }, uri, language, true), 10); + assert.equal(score({ language: 'farboo' }, uri, language, true), 10); + assert.equal(score({ language: '*' }, uri, language, true), 5); - assert.equal(score({ scheme: '*' }, uri, language), 5); - assert.equal(score({ scheme: 'git' }, uri, language), 10); + assert.equal(score({ scheme: '*' }, uri, language, true), 5); + assert.equal(score({ scheme: 'git' }, uri, language, true), 10); }); test('score, filter', function () { - assert.equal(score('farboo', model.uri, model.language), 10); - assert.equal(score({ language: 'farboo' }, model.uri, model.language), 10); - assert.equal(score({ language: 'farboo', scheme: 'file' }, model.uri, model.language), 10); - assert.equal(score({ language: 'farboo', scheme: 'http' }, model.uri, model.language), 0); + assert.equal(score('farboo', model.uri, model.language, true), 10); + assert.equal(score({ language: 'farboo' }, model.uri, model.language, true), 10); + assert.equal(score({ language: 'farboo', scheme: 'file' }, model.uri, model.language, true), 10); + assert.equal(score({ language: 'farboo', scheme: 'http' }, model.uri, model.language, true), 0); - assert.equal(score({ pattern: '**/*.fb' }, model.uri, model.language), 10); - assert.equal(score({ pattern: '**/*.fb', scheme: 'file' }, model.uri, model.language), 10); - assert.equal(score({ pattern: '**/*.fb' }, URI.parse('foo:bar'), model.language), 0); - assert.equal(score({ pattern: '**/*.fb', scheme: 'foo' }, URI.parse('foo:bar'), model.language), 0); + assert.equal(score({ pattern: '**/*.fb' }, model.uri, model.language, true), 10); + assert.equal(score({ pattern: '**/*.fb', scheme: 'file' }, model.uri, model.language, true), 10); + assert.equal(score({ pattern: '**/*.fb' }, URI.parse('foo:bar'), model.language, true), 0); + assert.equal(score({ pattern: '**/*.fb', scheme: 'foo' }, URI.parse('foo:bar'), model.language, true), 0); let doc = { uri: URI.parse('git:/my/file.js'), langId: 'javascript' }; - assert.equal(score('javascript', doc.uri, doc.langId), 10); // 0; - assert.equal(score({ language: 'javascript', scheme: 'git' }, doc.uri, doc.langId), 10); // 10; - assert.equal(score('*', doc.uri, doc.langId), 5); // 5 - assert.equal(score('fooLang', doc.uri, doc.langId), 0); // 0 - assert.equal(score(['fooLang', '*'], doc.uri, doc.langId), 5); // 5 + assert.equal(score('javascript', doc.uri, doc.langId, true), 10); // 0; + assert.equal(score({ language: 'javascript', scheme: 'git' }, doc.uri, doc.langId, true), 10); // 10; + assert.equal(score('*', doc.uri, doc.langId, true), 5); // 5 + assert.equal(score('fooLang', doc.uri, doc.langId, true), 0); // 0 + assert.equal(score(['fooLang', '*'], doc.uri, doc.langId, true), 5); // 5 }); test('score, max(filters)', function () { let match = { language: 'farboo', scheme: 'file' }; let fail = { language: 'farboo', scheme: 'http' }; - assert.equal(score(match, model.uri, model.language), 10); - assert.equal(score(fail, model.uri, model.language), 0); - assert.equal(score([match, fail], model.uri, model.language), 10); - assert.equal(score([fail, fail], model.uri, model.language), 0); - assert.equal(score(['farboo', '*'], model.uri, model.language), 10); - assert.equal(score(['*', 'farboo'], model.uri, model.language), 10); + assert.equal(score(match, model.uri, model.language, true), 10); + assert.equal(score(fail, model.uri, model.language, true), 0); + assert.equal(score([match, fail], model.uri, model.language, true), 10); + assert.equal(score([fail, fail], model.uri, model.language, true), 0); + assert.equal(score(['farboo', '*'], model.uri, model.language, true), 10); + assert.equal(score(['*', 'farboo'], model.uri, model.language, true), 10); + }); + + test('score hasAccessToAllModels', function () { + let doc = { + uri: URI.parse('file:/my/file.js'), + langId: 'javascript' + }; + assert.equal(score('javascript', doc.uri, doc.langId, false), 0); + assert.equal(score({ language: 'javascript', scheme: 'file' }, doc.uri, doc.langId, false), 0); + assert.equal(score('*', doc.uri, doc.langId, false), 0); + assert.equal(score('fooLang', doc.uri, doc.langId, false), 0); + assert.equal(score(['fooLang', '*'], doc.uri, doc.langId, false), 0); + + assert.equal(score({ language: 'javascript', scheme: 'file', hasAccessToAllModels: true }, doc.uri, doc.langId, false), 10); + assert.equal(score(['fooLang', '*', { language: '*', hasAccessToAllModels: true }], doc.uri, doc.langId, false), 5); }); }); diff --git a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts index 8879fab4b1..06725a8c58 100644 --- a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts +++ b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts @@ -32,7 +32,7 @@ suite('EditorSimpleWorker', () => { let model: ICommonModel; setup(() => { - worker = new WorkerWithModels(); + worker = new WorkerWithModels(null); model = worker.addModel([ 'This is line one', //16 'and this is line number two', //27 @@ -168,4 +168,25 @@ suite('EditorSimpleWorker', () => { assert.equal(suggestions[0].label, 'foobar'); }); }); + + test('get words via iterator, issue #46930', function () { + + let model = worker.addModel([ + 'one line', // 1 + 'two line', // 2 + '', + 'past empty', + 'single', + '', + 'and now we are done' + ]); + + let words: string[] = []; + + for (let iter = model.createWordIterator(/[a-z]+/img), e = iter.next(); !e.done; e = iter.next()) { + words.push(e.value); + } + + assert.deepEqual(words, ['one', 'line', 'two', 'line', 'past', 'empty', 'single', 'and', 'now', 'we', 'are', 'done']); + }); }); diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index b96d6005ee..3cc697e720 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -93,7 +93,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); assert.deepEqual(actual, [ - EditOperation.replace(new Range(1, 1, 2, 1), 'This is line One\n') + EditOperation.replaceMove(new Range(1, 1, 2, 1), 'This is line One\n') ]); }); @@ -147,7 +147,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); assert.deepEqual(actual, [ - EditOperation.replace( + EditOperation.replaceMove( new Range(1, 1, 4, 1), [ 'This is line One', @@ -182,7 +182,7 @@ suite('ModelService', () => { const actual = ModelServiceImpl._computeEdits(model, textBuffer); assert.deepEqual(actual, [ - EditOperation.replace(new Range(3, 2, 3, 2), '\r\n') + EditOperation.replaceMove(new Range(3, 2, 3, 2), '\r\n') ]); }); diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index 725c80a421..809fa593b3 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -58,7 +58,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 99, + viewportColumn: 98, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -174,7 +174,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 89, + viewportColumn: 88, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -232,7 +232,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 89, + viewportColumn: 88, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -290,7 +290,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 89, + viewportColumn: 88, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -348,7 +348,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 84, + viewportColumn: 83, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -406,7 +406,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 84, + viewportColumn: 83, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -464,7 +464,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 83, + viewportColumn: 82, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -522,7 +522,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 172, + viewportColumn: 171, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -580,7 +580,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { renderMinimap: RenderMinimap.None, minimapLeft: 0, minimapWidth: 0, - viewportColumn: 170, + viewportColumn: 169, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -632,13 +632,13 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { decorationsHeight: 800, contentLeft: 10, - contentWidth: 900, + contentWidth: 901, contentHeight: 800, renderMinimap: RenderMinimap.Small, - minimapLeft: 910, - minimapWidth: 90, - viewportColumn: 90, + minimapLeft: 911, + minimapWidth: 89, + viewportColumn: 89, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -690,13 +690,13 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { decorationsHeight: 800, contentLeft: 10, - contentWidth: 900, + contentWidth: 901, contentHeight: 800, renderMinimap: RenderMinimap.Large, - minimapLeft: 910, - minimapWidth: 90, - viewportColumn: 90, + minimapLeft: 911, + minimapWidth: 89, + viewportColumn: 89, verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, @@ -825,4 +825,63 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { } }); }); + + test('issue #31312: When wrapping, leave 2px for the cursor', () => { + doTest({ + outerWidth: 1201, + outerHeight: 422, + showGlyphMargin: true, + lineHeight: 30, + showLineNumbers: true, + lineNumbersMinChars: 3, + lineNumbersDigitCount: 1, + lineDecorationsWidth: 26, + typicalHalfwidthCharacterWidth: 12.04296875, + maxDigitWidth: 12.04296875, + verticalScrollbarWidth: 14, + horizontalScrollbarHeight: 10, + scrollbarArrowSize: 11, + verticalScrollbarHasArrows: false, + minimap: true, + minimapSide: 'right', + minimapRenderCharacters: true, + minimapMaxColumn: 120, + pixelRatio: 2 + }, { + width: 1201, + height: 422, + + glyphMarginLeft: 0, + glyphMarginWidth: 30, + glyphMarginHeight: 422, + + lineNumbersLeft: 30, + lineNumbersWidth: 36, + lineNumbersHeight: 422, + + decorationsLeft: 66, + decorationsWidth: 26, + decorationsHeight: 422, + + contentLeft: 92, + contentWidth: 1026, + contentHeight: 422, + + renderMinimap: RenderMinimap.Large, + minimapLeft: 1104, + minimapWidth: 83, + viewportColumn: 83, + + verticalScrollbarWidth: 14, + horizontalScrollbarHeight: 10, + + overviewRuler: { + top: 0, + width: 14, + height: 422, + right: 0 + } + }); + + }); }); diff --git a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts index 1dcd6b567d..3ed7c766ae 100644 --- a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts +++ b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts @@ -12,6 +12,7 @@ import { MetadataConsts } from 'vs/editor/common/modes'; import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations'; import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; +import * as strings from 'vs/base/common/strings'; function createViewLineTokens(viewLineTokens: ViewLineToken[]): IViewLineTokens { return new ViewLineTokens(viewLineTokens); @@ -29,6 +30,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineContent, + strings.isBasicASCII(lineContent), false, 0, createViewLineTokens([new ViewLineToken(lineContent.length, 0)]), @@ -75,6 +77,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens(parts), @@ -111,6 +114,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, 'Hello world!', + true, false, 0, createViewLineTokens([ @@ -212,6 +216,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineText, + true, false, 0, lineParts, @@ -271,6 +276,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineText, + true, false, 0, lineParts, @@ -330,6 +336,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineText, + true, false, 0, lineParts, @@ -366,6 +373,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( false, lineText, + false, true, 0, lineParts, @@ -393,6 +401,7 @@ suite('viewLineRenderer.renderLine', () => { let actual = renderViewLine(new RenderLineInput( false, lineText, + true, false, 0, lineParts, @@ -490,6 +499,7 @@ suite('viewLineRenderer.renderLine', () => { let actual = renderViewLine(new RenderLineInput( false, lineText, + true, false, 0, lineParts, @@ -524,6 +534,7 @@ suite('viewLineRenderer.renderLine', () => { false, lineText, false, + false, 0, lineParts, [], @@ -535,11 +546,7 @@ suite('viewLineRenderer.renderLine', () => { false )); let expectedOutput = [ - '<span class="mtk1">a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', - '<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', - '<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', - '<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', - '<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', + '<span class="mtk1">a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>', ]; assert.equal(actual.html, '<span>' + expectedOutput.join('') + '</span>'); }); @@ -553,6 +560,7 @@ suite('viewLineRenderer.renderLine', () => { let actual = renderViewLine(new RenderLineInput( false, lineText, + false, true, 0, lineParts, @@ -596,6 +604,7 @@ suite('viewLineRenderer.renderLine', () => { let _actual = renderViewLine(new RenderLineInput( true, lineText, + true, false, 4, lineParts, @@ -676,6 +685,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( fontIsMonospace, lineContent, + true, false, fauxIndentLength, createViewLineTokens(tokens), @@ -698,6 +708,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens([createPart(21, 3)]), @@ -726,6 +737,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( true, lineContent, + true, false, 0, createViewLineTokens([ @@ -990,6 +1002,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( false, 'Hello world', + true, false, 0, createViewLineTokens([createPart(11, 0)]), @@ -1031,6 +1044,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens([createPart(4, 3)]), @@ -1060,6 +1074,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens([createPart(4, 3)]), @@ -1090,6 +1105,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens([createPart(0, 3)]), @@ -1117,6 +1133,7 @@ suite('viewLineRenderer.renderLine 2', () => { true, ' 1. 🙏', false, + false, 0, createViewLineTokens([createPart(7, 3)]), [new LineDecoration(7, 8, 'inline-folded', InlineDecorationType.After)], @@ -1143,6 +1160,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( true, '', + true, false, 0, createViewLineTokens([createPart(0, 3)]), @@ -1172,6 +1190,7 @@ suite('viewLineRenderer.renderLine 2', () => { let actual = renderViewLine(new RenderLineInput( true, '\t}', + true, false, 0, createViewLineTokens([createPart(2, 3)]), @@ -1203,6 +1222,7 @@ suite('viewLineRenderer.renderLine 2', () => { true, 'asd = "擦"\t\t#asd', false, + false, 0, createViewLineTokens([createPart(15, 3)]), [], @@ -1229,6 +1249,7 @@ suite('viewLineRenderer.renderLine 2', () => { true, 'asd = "擦"\t\t#asd', false, + false, 0, createViewLineTokens([createPart(15, 3)]), [], @@ -1255,10 +1276,96 @@ suite('viewLineRenderer.renderLine 2', () => { assert.deepEqual(actual.html, expected); }); + test('issue #22352: COMBINING ACUTE ACCENT (U+0301)', () => { + + let actual = renderViewLine(new RenderLineInput( + true, + '12345689012345678901234568901234567890123456890abába', + false, + false, + 0, + createViewLineTokens([createPart(53, 3)]), + [], + 4, + 10, + 10000, + 'none', + false, + false + )); + + let expected = [ + '<span>', + '<span class="mtk3">12345689012345678901234568901234567890123456890abába</span>', + '</span>' + ].join(''); + + assert.deepEqual(actual.html, expected); + }); + + test('issue #22352: Partially Broken Complex Script Rendering of Tamil', () => { + + let actual = renderViewLine(new RenderLineInput( + true, + ' JoyShareல் பின்தொடர்ந்து, விடீயோ, ஜோக்குகள், அனிமேசன், நகைச்சுவை படங்கள் மற்றும் செய்திகளை பெறுவீர்', + false, + false, + 0, + createViewLineTokens([createPart(100, 3)]), + [], + 4, + 10, + 10000, + 'none', + false, + false + )); + + let expected = [ + '<span>', + '<span class="mtk3">\u00a0JoyShareல்\u00a0பின்தொடர்ந்து,\u00a0விடீயோ,\u00a0ஜோக்குகள்,\u00a0அனிமேசன்,\u00a0நகைச்சுவை\u00a0படங்கள்\u00a0மற்றும்\u00a0செய்திகளை\u00a0பெறுவீர்</span>', + '</span>' + ].join(''); + + let _expected = expected.split('').map(c => c.charCodeAt(0)); + let _actual = actual.html.split('').map(c => c.charCodeAt(0)); + assert.deepEqual(_actual, _expected); + + assert.deepEqual(actual.html, expected); + }); + + test('issue #42700: Hindi characters are not being rendered properly', () => { + + let actual = renderViewLine(new RenderLineInput( + true, + ' वो ऐसा क्या है जो हमारे अंदर भी है और बाहर भी है। जिसकी वजह से हम सब हैं। जिसने इस सृष्टि की रचना की है।', + false, + false, + 0, + createViewLineTokens([createPart(105, 3)]), + [], + 4, + 10, + 10000, + 'none', + false, + false + )); + + let expected = [ + '<span>', + '<span class="mtk3">\u00a0वो\u00a0ऐसा\u00a0क्या\u00a0है\u00a0जो\u00a0हमारे\u00a0अंदर\u00a0भी\u00a0है\u00a0और\u00a0बाहर\u00a0भी\u00a0है।\u00a0जिसकी\u00a0वजह\u00a0से\u00a0हम\u00a0सब\u00a0हैं।\u00a0जिसने\u00a0इस\u00a0सृष्टि\u00a0की\u00a0रचना\u00a0की\u00a0है।</span>', + '</span>' + ].join(''); + + assert.deepEqual(actual.html, expected); + }); + function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[], expectedPartLengths: number[]): (partIndex: number, partLength: number, offset: number, expected: number) => void { let renderLineOutput = renderViewLine(new RenderLineInput( false, lineContent, + true, false, 0, createViewLineTokens(parts), diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index 90b8251a24..e3b52a9a1a 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -780,6 +780,9 @@ function createModel(text: string): ISimpleModel { getLineContent: (lineNumber: number) => { return text; }, + getLineLength: (lineNumber: number) => { + return text.length; + }, getLineMinColumn: (lineNumber: number) => { return 1; }, diff --git a/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts b/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts index 04993bf979..51f1406c8e 100644 --- a/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts +++ b/src/vs/editor/test/common/viewModel/viewModelImpl.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; import { testViewModel } from 'vs/editor/test/common/viewModel/testViewModel'; +import { EndOfLineSequence } from 'vs/editor/common/model'; suite('ViewModel', () => { @@ -109,7 +110,7 @@ suite('ViewModel', () => { function assertGetPlainTextToCopy(text: string[], ranges: Range[], emptySelectionClipboard: boolean, expected: string | string[]): void { testViewModel(text, {}, (viewModel, model) => { - let actual = viewModel.getPlainTextToCopy(ranges, emptySelectionClipboard); + let actual = viewModel.getPlainTextToCopy(ranges, emptySelectionClipboard, false); assert.deepEqual(actual, expected); }); } @@ -250,4 +251,12 @@ suite('ViewModel', () => { 'line2\nline3\n' ); }); + + test('issue #22688 - always use CRLF for clipboard on Windows', () => { + testViewModel(USUAL_TEXT, {}, (viewModel, model) => { + model.setEOL(EndOfLineSequence.LF); + let actual = viewModel.getPlainTextToCopy([new Range(2, 1, 5, 1)], true, true); + assert.deepEqual(actual, 'line2\r\nline3\r\nline4\r\n'); + }); + }); }); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 9a42e5e46d..4ed6f38527 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3,9 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare module monaco { +declare namespace monaco { - type Thenable<T> = PromiseLike<T>; + export type Thenable<T> = PromiseLike<T>; export interface IDisposable { dispose(): void; @@ -32,6 +32,14 @@ declare module monaco { Error = 3, } + export enum MarkerSeverity { + Hint = 1, + Info = 2, + Warning = 4, + Error = 8, + } + + export type TValueCallback<T = any> = (value: T | PromiseLike<T>) => void; @@ -758,7 +766,7 @@ declare module monaco { } } -declare module monaco.editor { +declare namespace monaco.editor { /** @@ -1068,7 +1076,7 @@ declare module monaco.editor { export interface IMarker { owner: string; resource: Uri; - severity: Severity; + severity: MarkerSeverity; code?: string; message: string; source?: string; @@ -1076,6 +1084,7 @@ declare module monaco.editor { startColumn: number; endLineNumber: number; endColumn: number; + relatedInformation?: IRelatedInformation[]; } /** @@ -1083,13 +1092,26 @@ declare module monaco.editor { */ export interface IMarkerData { code?: string; - severity: Severity; + severity: MarkerSeverity; message: string; source?: string; startLineNumber: number; startColumn: number; endLineNumber: number; endColumn: number; + relatedInformation?: IRelatedInformation[]; + } + + /** + * + */ + export interface IRelatedInformation { + resource: Uri; + message: string; + startLineNumber: number; + startColumn: number; + endLineNumber: number; + endColumn: number; } export interface IColorizerOptions { @@ -1171,6 +1193,11 @@ declare module monaco.editor { * Should the decoration expand to encompass a whole line. */ isWholeLine?: boolean; + /** + * Specifies the stack order of a decoration. + * A decoration with greater stack order is always in front of a decoration with a lower stack order. + */ + zIndex?: number; /** * If set, render this decoration in the overview ruler. */ @@ -1193,6 +1220,10 @@ declare module monaco.editor { * to have a background color decoration. */ inlineClassName?: string; + /** + * If there is an `inlineClassName` which affects letter spacing. + */ + inlineClassNameAffectsLetterSpacing?: boolean; /** * If set, the decoration will be rendered before the text with this CSS class name. */ @@ -1461,6 +1492,10 @@ declare module monaco.editor { * Get the text for a certain line. */ getLineContent(lineNumber: number): string; + /** + * Get the text length for a certain line. + */ + getLineLength(lineNumber: number): number; /** * Get the text for all lines. */ @@ -1905,9 +1940,13 @@ declare module monaco.editor { * A (serializable) state of the view. */ export interface IViewState { - scrollTop: number; - scrollTopWithoutViewZones: number; + /** written by previous versions */ + scrollTop?: number; + /** written by previous versions */ + scrollTopWithoutViewZones?: number; scrollLeft: number; + firstPosition: IPosition; + firstPositionDeltaTop: number; } /** @@ -2165,6 +2204,10 @@ declare module monaco.editor { * The range that got replaced. */ readonly range: IRange; + /** + * The offset of the range that got replaced. + */ + readonly rangeOffset: number; /** * The length of the range that got replaced. */ @@ -2428,6 +2471,13 @@ declare module monaco.editor { enabled?: boolean; } + /** + * Configuration map for codeActionsOnSave + */ + export interface ICodeActionsOnSaveOptions { + [kind: string]: boolean; + } + /** * Configuration options for the editor. */ @@ -2662,6 +2712,11 @@ declare module monaco.editor { * Defaults to 'alt' */ multiCursorModifier?: 'ctrlCmd' | 'alt'; + /** + * Merge overlapping selections. + * Defaults to true + */ + multiCursorMergeOverlapping?: boolean; /** * Configure the editor's accessibility support. * Defaults to 'auto'. It is best to leave this to 'auto'. @@ -2745,7 +2800,7 @@ declare module monaco.editor { /** * The history mode for suggestions. */ - suggestSelection?: string; + suggestSelection?: 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix'; /** * The font size for the suggest widget. * Defaults to the editor font size. @@ -2775,11 +2830,24 @@ declare module monaco.editor { * Control the behavior and rendering of the code action lightbulb. */ lightbulb?: IEditorLightbulbOptions; + /** + * Code action kinds to be run on save. + */ + codeActionsOnSave?: ICodeActionsOnSaveOptions; + /** + * Timeout for running code actions on save. + */ + codeActionsOnSaveTimeout?: number; /** * Enable code folding - * Defaults to true in vscode and to false in monaco-editor. + * Defaults to true. */ folding?: boolean; + /** + * Selects the folding strategy. 'auto' uses the strategies contributed for the current document, 'indentation' uses the indentation based folding strategy. + * Defaults to 'auto'. + */ + foldingStrategy?: 'auto' | 'indentation'; /** * Controls whether the fold actions in the gutter stay always visible or hide unless the mouse is over the gutter. * Defaults to 'mouseover'. @@ -3059,11 +3127,14 @@ declare module monaco.editor { readonly occurrencesHighlight: boolean; readonly codeLens: boolean; readonly folding: boolean; + readonly foldingStrategy: 'auto' | 'indentation'; readonly showFoldingControls: 'always' | 'mouseover'; readonly matchBrackets: boolean; readonly find: InternalEditorFindOptions; readonly colorDecorators: boolean; readonly lightbulbEnabled: boolean; + readonly codeActionsOnSave: ICodeActionsOnSaveOptions; + readonly codeActionsOnSaveTimeout: number; } /** @@ -3077,6 +3148,7 @@ declare module monaco.editor { readonly lineHeight: number; readonly readOnly: boolean; readonly multiCursorModifier: 'altKey' | 'ctrlKey' | 'metaKey'; + readonly multiCursorMergeOverlapping: boolean; readonly wordSeparators: string; readonly autoClosingBrackets: boolean; readonly autoIndent: boolean; @@ -3214,6 +3286,7 @@ declare module monaco.editor { readonly readOnly: boolean; readonly accessibilitySupport: boolean; readonly multiCursorModifier: boolean; + readonly multiCursorMergeOverlapping: boolean; readonly wordSeparators: boolean; readonly autoClosingBrackets: boolean; readonly autoIndent: boolean; @@ -3730,10 +3803,6 @@ declare module monaco.editor { * Get the layout info for the editor. */ getLayoutInfo(): EditorLayoutInfo; - /** - * Returns the range that is currently centered in the view port. - */ - getCenteredRangeInViewport(): Range; /** * Returns the ranges that are currently visible. * Does not account for horizontal scrolling. @@ -3896,7 +3965,7 @@ declare module monaco.editor { export type IModel = ITextModel; } -declare module monaco.languages { +declare namespace monaco.languages { /** @@ -4053,8 +4122,10 @@ declare module monaco.languages { export function registerColorProvider(languageId: string, provider: DocumentColorProvider): IDisposable; /** - * Register a folding provider + * Register a folding range provider */ + export function registerFoldingRangeProvider(languageId: string, provider: FoldingRangeProvider): IDisposable; + /** * Contains additional diagnostic information about the context in which * a [code action](#CodeActionProvider.provideCodeActions) is run. @@ -4149,7 +4220,7 @@ declare module monaco.languages { /** * A human-readable string that represents a doc-comment. */ - documentation?: string; + documentation?: string | IMarkdownString; /** * A command that should be run upon acceptance of this item. */ @@ -4182,6 +4253,12 @@ declare module monaco.languages { * [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems). */ range?: Range; + /** + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + commitCharacters?: string[]; /** * @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`. * @@ -4199,12 +4276,6 @@ declare module monaco.languages { * nor with themselves. */ additionalTextEdits?: editor.ISingleEditOperation[]; - /** - * An optional set of characters that when pressed while this completion is active will accept it first and - * then type that character. *Note* that all commit characters should have `length=1` and that superfluous - * characters will be ignored. - */ - commitCharacters?: string[]; } /** @@ -4504,7 +4575,7 @@ declare module monaco.languages { * editor will use the range at the current position or the * current position itself. */ - range: IRange; + range?: IRange; } /** @@ -4948,6 +5019,60 @@ declare module monaco.languages { provideColorPresentations(model: editor.ITextModel, colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable<IColorPresentation[]>; } + export interface FoldingContext { + } + + /** + * A provider of colors for editor models. + */ + export interface FoldingRangeProvider { + /** + * Provides the color ranges for a specific model. + */ + provideFoldingRanges(model: editor.ITextModel, context: FoldingContext, token: CancellationToken): FoldingRange[] | Thenable<FoldingRange[]>; + } + + export interface FoldingRange { + /** + * The zero-based start line of the range to fold. The folded area starts after the line's last character. + */ + start: number; + /** + * The zero-based end line of the range to fold. The folded area ends with the line's last character. + */ + end: number; + /** + * Describes the [Kind](#FoldingRangeKind) of the folding range such as [Comment](#FoldingRangeKind.Comment) or + * [Region](#FoldingRangeKind.Region). The kind is used to categorize folding ranges and used by commands + * like 'Fold all comments'. See + * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. + */ + kind?: FoldingRangeKind; + } + + export class FoldingRangeKind { + value: string; + /** + * Kind for folding range representing a comment. The value of the kind is 'comment'. + */ + static readonly Comment: FoldingRangeKind; + /** + * Kind for folding range representing a import. The value of the kind is 'imports'. + */ + static readonly Imports: FoldingRangeKind; + /** + * Kind for folding range representing regions (for example marked by `#region`, `#endregion`). + * The value of the kind is 'region'. + */ + static readonly Region: FoldingRangeKind; + /** + * Creates a new [FoldingRangeKind](#FoldingRangeKind). + * + * @param value of the kind. + */ + constructor(value: string); + } + export interface ResourceFileEdit { oldUri: Uri; newUri: Uri; @@ -4964,14 +5089,14 @@ declare module monaco.languages { rejectReason?: string; } - export interface RenameInitialValue { + export interface RenameLocation { range: IRange; - text?: string; + text: string; } export interface RenameProvider { provideRenameEdits(model: editor.ITextModel, position: Position, newName: string, token: CancellationToken): WorkspaceEdit | Thenable<WorkspaceEdit>; - resolveInitialRenameValue?(model: editor.ITextModel, position: Position, token: CancellationToken): RenameInitialValue | Thenable<RenameInitialValue>; + resolveRenameLocation?(model: editor.ITextModel, position: Position, token: CancellationToken): RenameLocation | Thenable<RenameLocation>; } export interface Command { @@ -5119,7 +5244,7 @@ declare module monaco.languages { } -declare module monaco.worker { +declare namespace monaco.worker { export interface IMirrorModel { diff --git a/src/vs/nls.mock.ts b/src/vs/nls.mock.ts new file mode 100644 index 0000000000..ba355e013d --- /dev/null +++ b/src/vs/nls.mock.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface ILocalizeInfo { + key: string; + comment: string[]; +} + +function _format(message: string, args: any[]): string { + let result: string; + if (args.length === 0) { + result = message; + } else { + result = message.replace(/\{(\d+)\}/g, function (match, rest) { + const index = rest[0]; + return typeof args[index] !== 'undefined' ? args[index] : match; + }); + } + return result; +} + +export function localize(data: ILocalizeInfo | string, message: string, ...args: any[]): string { + return _format(message, args); +} diff --git a/src/vs/platform/actions/browser/menuItemActionItem.ts b/src/vs/platform/actions/browser/menuItemActionItem.ts index 4c0d33de9a..cf8eb27791 100644 --- a/src/vs/platform/actions/browser/menuItemActionItem.ts +++ b/src/vs/platform/actions/browser/menuItemActionItem.ts @@ -14,24 +14,24 @@ import { ActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { domEvent } from 'vs/base/browser/event'; import { Emitter } from 'vs/base/common/event'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { memoize } from 'vs/base/common/decorators'; import { IdGenerator } from 'vs/base/common/idGenerator'; import { createCSSRule } from 'vs/base/browser/dom'; import URI from 'vs/base/common/uri'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { isWindows } from 'vs/base/common/platform'; +import { isWindows, isLinux } from 'vs/base/common/platform'; // The alternative key on all platforms is alt. On windows we also support shift as an alternative key #44136 class AlternativeKeyEmitter extends Emitter<boolean> { private _subscriptions: IDisposable[] = []; private _isPressed: boolean; + private static instance: AlternativeKeyEmitter; private constructor(contextMenuService: IContextMenuService) { super(); this._subscriptions.push(domEvent(document.body, 'keydown')(e => { - this.isPressed = e.altKey || (isWindows && e.shiftKey); + this.isPressed = e.altKey || ((isWindows || isLinux) && e.shiftKey); })); this._subscriptions.push(domEvent(document.body, 'keyup')(e => this.isPressed = false)); this._subscriptions.push(domEvent(document.body, 'mouseleave')(e => this.isPressed = false)); @@ -49,9 +49,12 @@ class AlternativeKeyEmitter extends Emitter<boolean> { this.fire(this._isPressed); } - @memoize static getInstance(contextMenuService: IContextMenuService) { - return new AlternativeKeyEmitter(contextMenuService); + if (!AlternativeKeyEmitter.instance) { + AlternativeKeyEmitter.instance = new AlternativeKeyEmitter(contextMenuService); + } + + return AlternativeKeyEmitter.instance; } dispose() { diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 00fd4bf544..c2773f51b3 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -12,7 +12,7 @@ import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry' import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export interface ILocalizedString { value: string; @@ -59,6 +59,7 @@ export class MenuId { static readonly ViewTitle = new MenuId(); static readonly ViewItemContext = new MenuId(); static readonly TouchBarContext = new MenuId(); + static readonly SearchContext = new MenuId(); readonly id: string = String(MenuId.ID++); } diff --git a/src/vs/platform/actions/common/menu.ts b/src/vs/platform/actions/common/menu.ts index bae1d620cb..0fa492c9e7 100644 --- a/src/vs/platform/actions/common/menu.ts +++ b/src/vs/platform/actions/common/menu.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 3eced2052b..89c62cfc6c 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -7,11 +7,10 @@ import * as assert from 'assert'; import * as platform from 'vs/base/common/platform'; -import fs = require('fs'); -import os = require('os'); -import path = require('path'); -import extfs = require('vs/base/node/extfs'); -import pfs = require('vs/base/node/pfs'); +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import * as pfs from 'vs/base/node/pfs'; import Uri from 'vs/base/common/uri'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; @@ -86,23 +85,22 @@ suite('BackupMainService', () => { let service: TestBackupMainService; let configService: TestConfigurationService; - setup(done => { + setup(() => { configService = new TestConfigurationService(); service = new TestBackupMainService(backupHome, backupWorkspacesPath, configService); // Delete any existing backups completely and then re-create it. - extfs.del(backupHome, os.tmpdir(), () => { - pfs.mkdirp(backupHome).then(() => { - done(); - }); + return pfs.del(backupHome, os.tmpdir()).then(() => { + return pfs.mkdirp(backupHome); }); }); - teardown(done => { - extfs.del(backupHome, os.tmpdir(), done); + teardown(() => { + return pfs.del(backupHome, os.tmpdir()); }); - test('service validates backup workspaces on startup and cleans up (folder workspaces)', done => { + test('service validates backup workspaces on startup and cleans up (folder workspaces)', function () { + this.timeout(1000 * 10); // increase timeout for this test // 1) backup workspace path does not exist service.registerFolderBackupSync(fooFile.fsPath); @@ -145,11 +143,10 @@ suite('BackupMainService', () => { service.loadSync(); assert.equal(service.getFolderBackupPaths().length, 0); assert.equal(service.getEmptyWindowBackupPaths().length, 1); - - done(); }); - test('service validates backup workspaces on startup and cleans up (root workspaces)', done => { + test('service validates backup workspaces on startup and cleans up (root workspaces)', function () { + this.timeout(1000 * 10); // increase timeout for this test // 1) backup workspace path does not exist service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath)); @@ -192,11 +189,9 @@ suite('BackupMainService', () => { service.loadSync(); assert.equal(service.getWorkspaceBackups().length, 0); assert.equal(service.getEmptyWindowBackupPaths().length, 1); - - done(); }); - test('service supports to migrate backup data from another location', done => { + test('service supports to migrate backup data from another location', () => { const backupPathToMigrate = service.toBackupPath(fooFile.fsPath); fs.mkdirSync(backupPathToMigrate); fs.writeFileSync(path.join(backupPathToMigrate, 'backup.txt'), 'Some Data'); @@ -210,11 +205,9 @@ suite('BackupMainService', () => { const emptyBackups = service.getEmptyWindowBackupPaths(); assert.equal(0, emptyBackups.length); - - done(); }); - test('service backup migration makes sure to preserve existing backups', done => { + test('service backup migration makes sure to preserve existing backups', () => { const backupPathToMigrate = service.toBackupPath(fooFile.fsPath); fs.mkdirSync(backupPathToMigrate); fs.writeFileSync(path.join(backupPathToMigrate, 'backup.txt'), 'Some Data'); @@ -234,8 +227,6 @@ suite('BackupMainService', () => { const emptyBackups = service.getEmptyWindowBackupPaths(); assert.equal(1, emptyBackups.length); assert.equal(1, fs.readdirSync(path.join(backupHome, emptyBackups[0])).length); - - done(); }); suite('loadSync', () => { @@ -434,18 +425,17 @@ suite('BackupMainService', () => { }); suite('registerWindowForBackups', () => { - test('should persist paths to workspaces.json (folder workspace)', done => { + test('should persist paths to workspaces.json (folder workspace)', () => { service.registerFolderBackupSync(fooFile.fsPath); service.registerFolderBackupSync(barFile.fsPath); assert.deepEqual(service.getFolderBackupPaths(), [fooFile.fsPath, barFile.fsPath]); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.folderWorkspaces, [fooFile.fsPath, barFile.fsPath]); - done(); }); }); - test('should persist paths to workspaces.json (root workspace)', done => { + test('should persist paths to workspaces.json (root workspace)', () => { const ws1 = toWorkspace(fooFile.fsPath); service.registerWorkspaceBackupSync(ws1); const ws2 = toWorkspace(barFile.fsPath); @@ -455,98 +445,90 @@ suite('BackupMainService', () => { assert.equal(ws1.id, service.getWorkspaceBackups()[0].id); assert.equal(ws2.id, service.getWorkspaceBackups()[1].id); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath, barFile.fsPath]); assert.equal(ws1.id, json.rootWorkspaces[0].id); assert.equal(ws2.id, json.rootWorkspaces[1].id); - - done(); }); }); - test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (folder workspace)', done => { + test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (folder workspace)', () => { service.registerFolderBackupSync(fooFile.fsPath.toUpperCase()); assert.deepEqual(service.getFolderBackupPaths(), [fooFile.fsPath.toUpperCase()]); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.folderWorkspaces, [fooFile.fsPath.toUpperCase()]); - done(); }); }); - test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (root workspace)', done => { + test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (root workspace)', () => { service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath.toUpperCase())); assert.deepEqual(service.getWorkspaceBackups().map(b => b.configPath), [fooFile.fsPath.toUpperCase()]); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath.toUpperCase()]); - done(); }); }); }); suite('removeBackupPathSync', () => { - test('should remove folder workspaces from workspaces.json (folder workspace)', done => { + test('should remove folder workspaces from workspaces.json (folder workspace)', () => { service.registerFolderBackupSync(fooFile.fsPath); service.registerFolderBackupSync(barFile.fsPath); service.removeBackupPathSync(fooFile.fsPath, service.backupsData.folderWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.folderWorkspaces, [barFile.fsPath]); service.removeBackupPathSync(barFile.fsPath, service.backupsData.folderWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { const json2 = <IBackupWorkspacesFormat>JSON.parse(content); assert.deepEqual(json2.folderWorkspaces, []); - done(); }); }); }); - test('should remove folder workspaces from workspaces.json (root workspace)', done => { + test('should remove folder workspaces from workspaces.json (root workspace)', () => { const ws1 = toWorkspace(fooFile.fsPath); service.registerWorkspaceBackupSync(ws1); const ws2 = toWorkspace(barFile.fsPath); service.registerWorkspaceBackupSync(ws2); service.removeBackupPathSync(ws1, service.backupsData.rootWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.rootWorkspaces.map(r => r.configPath), [barFile.fsPath]); service.removeBackupPathSync(ws2, service.backupsData.rootWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { const json2 = <IBackupWorkspacesFormat>JSON.parse(content); assert.deepEqual(json2.rootWorkspaces, []); - done(); }); }); }); - test('should remove empty workspaces from workspaces.json', done => { + test('should remove empty workspaces from workspaces.json', () => { service.registerEmptyWindowBackupSync('foo'); service.registerEmptyWindowBackupSync('bar'); service.removeBackupPathSync('foo', service.backupsData.emptyWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => { const json = <IBackupWorkspacesFormat>JSON.parse(buffer); assert.deepEqual(json.emptyWorkspaces, ['bar']); service.removeBackupPathSync('bar', service.backupsData.emptyWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { const json2 = <IBackupWorkspacesFormat>JSON.parse(content); assert.deepEqual(json2.emptyWorkspaces, []); - done(); }); }); }); - test('should fail gracefully when removing a path that doesn\'t exist', done => { + test('should fail gracefully when removing a path that doesn\'t exist', () => { const workspacesJson: IBackupWorkspacesFormat = { rootWorkspaces: [], folderWorkspaces: [fooFile.fsPath], emptyWorkspaces: [] }; - pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => { + return pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => { service.removeBackupPathSync(barFile.fsPath, service.backupsData.folderWorkspaces); service.removeBackupPathSync('test', service.backupsData.emptyWorkspaces); - pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { + return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => { const json = <IBackupWorkspacesFormat>JSON.parse(content); assert.deepEqual(json.folderWorkspaces, [fooFile.fsPath]); - done(); }); }); }); @@ -574,7 +556,7 @@ suite('BackupMainService', () => { }); suite('mixed path casing', () => { - test('should handle case insensitive paths properly (registerWindowForBackupsSync) (folder workspace)', done => { + test('should handle case insensitive paths properly (registerWindowForBackupsSync) (folder workspace)', () => { service.registerFolderBackupSync(fooFile.fsPath); service.registerFolderBackupSync(fooFile.fsPath.toUpperCase()); @@ -583,11 +565,9 @@ suite('BackupMainService', () => { } else { assert.equal(service.getFolderBackupPaths().length, 1); } - - done(); }); - test('should handle case insensitive paths properly (registerWindowForBackupsSync) (root workspace)', done => { + test('should handle case insensitive paths properly (registerWindowForBackupsSync) (root workspace)', () => { service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath)); service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath.toUpperCase())); @@ -596,11 +576,9 @@ suite('BackupMainService', () => { } else { assert.equal(service.getWorkspaceBackups().length, 1); } - - done(); }); - test('should handle case insensitive paths properly (removeBackupPathSync) (folder workspace)', done => { + test('should handle case insensitive paths properly (removeBackupPathSync) (folder workspace)', () => { // same case service.registerFolderBackupSync(fooFile.fsPath); @@ -616,8 +594,6 @@ suite('BackupMainService', () => { } else { assert.equal(service.getFolderBackupPaths().length, 0); } - - done(); }); }); }); \ No newline at end of file diff --git a/src/vs/platform/broadcast/electron-browser/broadcastService.ts b/src/vs/platform/broadcast/electron-browser/broadcastService.ts index adef2c10cf..e841c9514c 100644 --- a/src/vs/platform/broadcast/electron-browser/broadcastService.ts +++ b/src/vs/platform/broadcast/electron-browser/broadcastService.ts @@ -6,7 +6,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ipcRenderer as ipc } from 'electron'; import { ILogService } from 'vs/platform/log/common/log'; @@ -29,7 +29,7 @@ export interface IBroadcastService { export class BroadcastService implements IBroadcastService { public _serviceBrand: any; - private _onBroadcast: Emitter<IBroadcast>; + private readonly _onBroadcast: Emitter<IBroadcast>; constructor( private windowId: number, diff --git a/src/vs/platform/commands/common/commands.ts b/src/vs/platform/commands/common/commands.ts index d135b22b83..04fb97a0dd 100644 --- a/src/vs/platform/commands/common/commands.ts +++ b/src/vs/platform/commands/common/commands.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { TypeConstraint, validateConstraints } from 'vs/base/common/types'; import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { LinkedList } from 'vs/base/common/linkedList'; export const ICommandService = createDecorator<ICommandService>('commandService'); diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 0819c8b612..51fa047c1c 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -7,12 +7,12 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as objects from 'vs/base/common/objects'; import * as types from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry'; -import { StrictResourceMap } from 'vs/base/common/map'; +import { ResourceMap } from 'vs/base/common/map'; export const IConfigurationService = createDecorator<IConfigurationService>('configurationService'); @@ -47,7 +47,7 @@ export interface IConfigurationChangeEvent { // Following data is used for Extension host configuration event changedConfiguration: IConfigurationModel; - changedConfigurationByResource: StrictResourceMap<IConfigurationModel>; + changedConfigurationByResource: ResourceMap<IConfigurationModel>; } export interface IConfigurationService { @@ -112,6 +112,7 @@ export interface IConfigurationData { user: IConfigurationModel; workspace: IConfigurationModel; folders: { [folder: string]: IConfigurationModel }; + isComplete: boolean; } export function compare(from: IConfigurationModel, to: IConfigurationModel): { added: string[], removed: string[], updated: string[] } { diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index bbfc2b5ecb..805af2c02e 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -5,7 +5,7 @@ 'use strict'; import * as json from 'vs/base/common/json'; -import { StrictResourceMap } from 'vs/base/common/map'; +import { ResourceMap } from 'vs/base/common/map'; import * as arrays from 'vs/base/common/arrays'; import * as types from 'vs/base/common/types'; import * as objects from 'vs/base/common/objects'; @@ -85,7 +85,7 @@ export class ConfigurationModel implements IConfigurationModel { if (override) { this.mergeContents(override.contents, otherOverride.contents); } else { - overrides.push(otherOverride); + overrides.push(objects.deepClone(otherOverride)); } } for (const key of other.keys) { @@ -279,15 +279,16 @@ export class ConfigurationModelParser { export class Configuration { private _workspaceConsolidatedConfiguration: ConfigurationModel = null; - private _foldersConsolidatedConfigurations: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>(); + private _foldersConsolidatedConfigurations: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(); constructor( private _defaultConfiguration: ConfigurationModel, private _userConfiguration: ConfigurationModel, private _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(), - private _folderConfigurations: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>(), + private _folderConfigurations: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(), private _memoryConfiguration: ConfigurationModel = new ConfigurationModel(), - private _memoryConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>()) { + private _memoryConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(), + private _freeze: boolean = true) { } getValue(section: string, overrides: IConfigurationOverrides, workspace: Workspace): any { @@ -394,7 +395,7 @@ export class Configuration { return this._workspaceConfiguration; } - protected get folders(): StrictResourceMap<ConfigurationModel> { + protected get folders(): ResourceMap<ConfigurationModel> { return this._folderConfigurations; } @@ -422,7 +423,10 @@ export class Configuration { private getWorkspaceConsolidatedConfiguration(): ConfigurationModel { if (!this._workspaceConsolidatedConfiguration) { - this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this._userConfiguration).merge(this._workspaceConfiguration).merge(this._memoryConfiguration).freeze(); + this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this._userConfiguration, this._workspaceConfiguration, this._memoryConfiguration); + if (this._freeze) { + this._workspaceConfiguration = this._workspaceConfiguration.freeze(); + } } return this._workspaceConsolidatedConfiguration; } @@ -433,7 +437,10 @@ export class Configuration { const workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration(); const folderConfiguration = this._folderConfigurations.get(folder); if (folderConfiguration) { - folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration).freeze(); + folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration); + if (this._freeze) { + folderConsolidatedConfiguration = folderConsolidatedConfiguration.freeze(); + } this._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration); } else { folderConsolidatedConfiguration = workspaceConsolidateConfiguration; @@ -473,7 +480,8 @@ export class Configuration { const { contents, overrides, keys } = this._folderConfigurations.get(folder); result[folder.toString()] = { contents, overrides, keys }; return result; - }, Object.create({})) + }, Object.create({})), + isComplete: true }; } @@ -494,21 +502,6 @@ export class Configuration { } return all; } - - public static parse(data: IConfigurationData): Configuration { - const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults); - const userConfiguration = Configuration.parseConfigurationModel(data.user); - const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace); - const folders: StrictResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => { - result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key])); - return result; - }, new StrictResourceMap<ConfigurationModel>()); - return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders); - } - - private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel { - return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze(); - } } export class AbstractConfigurationChangeEvent { @@ -542,7 +535,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i constructor( private _changedConfiguration: ConfigurationModel = new ConfigurationModel(), - private _changedConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>()) { + private _changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>()) { super(); } @@ -550,7 +543,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i return this._changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap<IConfigurationModel> { + get changedConfigurationByResource(): ResourceMap<IConfigurationModel> { return this._changedConfigurationByResource; } diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 67f93fec2c..cd8893de13 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -4,14 +4,13 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); -import Event, { Emitter } from 'vs/base/common/event'; +import * as nls from 'vs/nls'; +import { Event, Emitter } from 'vs/base/common/event'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Registry } from 'vs/platform/registry/common/platform'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import * as strings from 'vs/base/common/strings'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import { deepClone } from 'vs/base/common/objects'; export const Extensions = { Configuration: 'base.contributions.configuration' @@ -63,13 +62,13 @@ export interface IConfigurationRegistry { } export enum ConfigurationScope { - WINDOW = 1, - RESOURCE + APPLICATION = 1, + WINDOW, + RESOURCE, } export interface IConfigurationPropertySchema extends IJSONSchema { overridable?: boolean; - isExecutable?: boolean; scope?: ConfigurationScope; notMultiRootAdopted?: boolean; included?: boolean; @@ -93,8 +92,10 @@ export interface IDefaultConfigurationExtension { defaults: { [key: string]: {} }; } -export const settingsSchema: IJSONSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; -export const resourceSettingsSchema: IJSONSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; +export const allSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; +export const applicationSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; +export const windowSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; +export const resourceSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const editorConfigurationSchemaId = 'vscode://schemas/settings/editor'; const contributionRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution); @@ -108,7 +109,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { private overrideIdentifiers: string[] = []; private overridePropertyPattern: string; - private _onDidRegisterConfiguration: Emitter<string[]> = new Emitter<string[]>(); + private readonly _onDidRegisterConfiguration: Emitter<string[]> = new Emitter<string[]>(); readonly onDidRegisterConfiguration: Event<string[]> = this._onDidRegisterConfiguration.event; constructor() { @@ -239,10 +240,17 @@ class ConfigurationRegistry implements IConfigurationRegistry { let properties = configuration.properties; if (properties) { for (let key in properties) { - settingsSchema.properties[key] = properties[key]; - resourceSettingsSchema.properties[key] = deepClone(properties[key]); - if (properties[key].scope !== ConfigurationScope.RESOURCE) { - resourceSettingsSchema.properties[key].doNotSuggest = true; + allSettings.properties[key] = properties[key]; + switch (properties[key].scope) { + case ConfigurationScope.APPLICATION: + applicationSettings.properties[key] = properties[key]; + break; + case ConfigurationScope.WINDOW: + windowSettings.properties[key] = properties[key]; + break; + case ConfigurationScope.RESOURCE: + resourceSettings.properties[key] = properties[key]; + break; } } } @@ -262,7 +270,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { } private updateOverridePropertyPatternKey(): void { - let patternProperties: IJSONSchema = settingsSchema.patternProperties[this.overridePropertyPattern]; + let patternProperties: IJSONSchema = allSettings.patternProperties[this.overridePropertyPattern]; if (!patternProperties) { patternProperties = { type: 'object', @@ -271,11 +279,18 @@ class ConfigurationRegistry implements IConfigurationRegistry { $ref: editorConfigurationSchemaId }; } - delete settingsSchema.patternProperties[this.overridePropertyPattern]; + + delete allSettings.patternProperties[this.overridePropertyPattern]; + delete applicationSettings.patternProperties[this.overridePropertyPattern]; + delete windowSettings.patternProperties[this.overridePropertyPattern]; + delete resourceSettings.patternProperties[this.overridePropertyPattern]; + this.computeOverridePropertyPattern(); - settingsSchema.patternProperties[this.overridePropertyPattern] = patternProperties; - resourceSettingsSchema.patternProperties[this.overridePropertyPattern] = patternProperties; + allSettings.patternProperties[this.overridePropertyPattern] = patternProperties; + applicationSettings.patternProperties[this.overridePropertyPattern] = patternProperties; + windowSettings.patternProperties[this.overridePropertyPattern] = patternProperties; + resourceSettings.patternProperties[this.overridePropertyPattern] = patternProperties; } private update(configuration: IConfigurationNode): void { diff --git a/src/vs/platform/configuration/node/configuration.ts b/src/vs/platform/configuration/node/configuration.ts index 014de4e557..0a0e2ac587 100644 --- a/src/vs/platform/configuration/node/configuration.ts +++ b/src/vs/platform/configuration/node/configuration.ts @@ -7,14 +7,14 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { onUnexpectedError } from 'vs/base/common/errors'; import { ConfigurationModelParser, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { ConfigWatcher } from 'vs/base/node/config'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; export class UserConfiguration extends Disposable { private userConfigModelWatcher: ConfigWatcher<ConfigurationModelParser>; - private _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>()); + private readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>()); readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event; constructor(settingsPath: string) { diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index ed735897a1..bf4590a02f 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -9,7 +9,7 @@ import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/co import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration'; import { DefaultConfigurationModel, Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { TPromise } from 'vs/base/common/winjs.base'; import { equals } from 'vs/base/common/objects'; @@ -23,7 +23,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe private _configuration: Configuration; private userConfiguration: UserConfiguration; - private _onDidChangeConfiguration: Emitter<IConfigurationChangeEvent> = this._register(new Emitter<IConfigurationChangeEvent>()); + private readonly _onDidChangeConfiguration: Emitter<IConfigurationChangeEvent> = this._register(new Emitter<IConfigurationChangeEvent>()); readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event; constructor( diff --git a/src/vs/platform/configuration/test/common/configurationModels.test.ts b/src/vs/platform/configuration/test/common/configurationModels.test.ts index 9c55f61289..5bda83b0f4 100644 --- a/src/vs/platform/configuration/test/common/configurationModels.test.ts +++ b/src/vs/platform/configuration/test/common/configurationModels.test.ts @@ -199,6 +199,17 @@ suite('ConfigurationModel', () => { assert.deepEqual(result.keys, ['a.b', 'f']); }); + test('merge overrides when frozen', () => { + let model1 = new ConfigurationModel({ 'a': { 'b': 1 }, 'f': 1 }, ['a.b', 'f'], [{ identifiers: ['c'], contents: { 'a': { 'd': 1 } } }]).freeze(); + let model2 = new ConfigurationModel({ 'a': { 'b': 2 } }, ['a.b'], [{ identifiers: ['c'], contents: { 'a': { 'e': 2 } } }]).freeze(); + let result = new ConfigurationModel().merge(model1, model2); + + assert.deepEqual(result.contents, { 'a': { 'b': 2 }, 'f': 1 }); + assert.deepEqual(result.overrides, [{ identifiers: ['c'], contents: { 'a': { 'd': 1, 'e': 2 } } }]); + assert.deepEqual(result.override('c').contents, { 'a': { 'b': 2, 'd': 1, 'e': 2 }, 'f': 1 }); + assert.deepEqual(result.keys, ['a.b', 'f']); + }); + test('Test contents while getting an existing property', () => { let testObject = new ConfigurationModel({ 'a': 1 }); assert.deepEqual(testObject.getValue('a'), 1); @@ -349,24 +360,6 @@ suite('CustomConfigurationModel', () => { }); assert.equal(true, new DefaultConfigurationModel().getValue('a')); }); - - test('Test registering the language property', () => { - Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({ - 'id': '[a]', - 'order': 1, - 'title': 'a', - 'type': 'object', - 'properties': { - '[a]': { - 'description': 'a', - 'type': 'boolean', - 'default': false, - } - } - }); - assert.equal(undefined, new DefaultConfigurationModel().getValue('[a]')); - }); - }); suite('ConfigurationChangeEvent', () => { diff --git a/src/vs/platform/configuration/test/node/configurationService.test.ts b/src/vs/platform/configuration/test/node/configurationService.test.ts index 68b0e808c1..4e65084237 100644 --- a/src/vs/platform/configuration/test/node/configurationService.test.ts +++ b/src/vs/platform/configuration/test/node/configurationService.test.ts @@ -5,20 +5,19 @@ 'use strict'; -import assert = require('assert'); -import os = require('os'); -import path = require('path'); -import fs = require('fs'); +import * as assert from 'assert'; +import * as os from 'os'; +import * as path from 'path'; +import * as fs from 'fs'; import { Registry } from 'vs/platform/registry/common/platform'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { parseArgs } from 'vs/platform/environment/node/argv'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import extfs = require('vs/base/node/extfs'); -import uuid = require('vs/base/common/uuid'); +import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { mkdirp } from 'vs/base/node/pfs'; +import { testFile } from 'vs/base/test/node/utils'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -31,22 +30,11 @@ class SettingsTestEnvironmentService extends EnvironmentService { suite('ConfigurationService - Node', () => { - function testFile(callback: (path: string, cleanUp: (callback: () => void) => void) => void): void { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'config', id); - const testFile = path.join(newDir, 'config.json'); + test('simple', () => { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '{ "foo": "bar" }'); - const onMkdirp = error => callback(testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback)); - - mkdirp(newDir, 493).done(() => onMkdirp(null), error => onMkdirp(error)); - } - - test('simple', (done: () => void) => { - testFile((testFile, cleanUp) => { - fs.writeFileSync(testFile, '{ "foo": "bar" }'); - - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, res.testFile)); const config = service.getValue<{ foo: string }>(); assert.ok(config); @@ -54,15 +42,15 @@ suite('ConfigurationService - Node', () => { service.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); - test('config gets flattened', (done: () => void) => { - testFile((testFile, cleanUp) => { - fs.writeFileSync(testFile, '{ "testworkbench.editor.tabs": true }'); + test('config gets flattened', () => { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }'); - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, res.testFile)); const config = service.getValue<{ testworkbench: { editor: { tabs: boolean } } }>(); assert.ok(config); @@ -72,22 +60,22 @@ suite('ConfigurationService - Node', () => { service.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); - test('error case does not explode', (done: () => void) => { - testFile((testFile, cleanUp) => { - fs.writeFileSync(testFile, ',,,,'); + test('error case does not explode', () => { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, ',,,,'); - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, res.testFile)); const config = service.getValue<{ foo: string }>(); assert.ok(config); service.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); @@ -105,17 +93,17 @@ suite('ConfigurationService - Node', () => { service.dispose(); }); - test('reloadConfiguration', (done: () => void) => { - testFile((testFile, cleanUp) => { - fs.writeFileSync(testFile, '{ "foo": "bar" }'); + test('reloadConfiguration', () => { + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '{ "foo": "bar" }'); - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, res.testFile)); let config = service.getValue<{ foo: string }>(); assert.ok(config); assert.equal(config.foo, 'bar'); - fs.writeFileSync(testFile, '{ "foo": "changed" }'); + fs.writeFileSync(res.testFile, '{ "foo": "changed" }'); // still outdated config = service.getValue<{ foo: string }>(); @@ -123,19 +111,19 @@ suite('ConfigurationService - Node', () => { assert.equal(config.foo, 'bar'); // force a reload to get latest - service.reloadConfiguration().then(() => { + return service.reloadConfiguration().then(() => { config = service.getValue<{ foo: string }>(); assert.ok(config); assert.equal(config.foo, 'changed'); service.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); }); - test('model defaults', (done: () => void) => { + test('model defaults', () => { interface ITestSetting { configuration: { service: { @@ -144,7 +132,7 @@ suite('ConfigurationService - Node', () => { }; } - const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration); + const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': '_test', 'type': 'object', @@ -162,19 +150,19 @@ suite('ConfigurationService - Node', () => { assert.ok(setting); assert.equal(setting.configuration.service.testSetting, 'isSet'); - testFile((testFile, cleanUp) => { - fs.writeFileSync(testFile, '{ "testworkbench.editor.tabs": true }'); + return testFile('config', 'config.json').then(res => { + fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }'); - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, res.testFile)); let setting = service.getValue<ITestSetting>(); assert.ok(setting); assert.equal(setting.configuration.service.testSetting, 'isSet'); - fs.writeFileSync(testFile, '{ "configuration.service.testSetting": "isChanged" }'); + fs.writeFileSync(res.testFile, '{ "configuration.service.testSetting": "isChanged" }'); - service.reloadConfiguration().then(() => { + return service.reloadConfiguration().then(() => { let setting = service.getValue<ITestSetting>(); assert.ok(setting); @@ -183,13 +171,13 @@ suite('ConfigurationService - Node', () => { service.dispose(); serviceWithoutFile.dispose(); - cleanUp(done); + return res.cleanUp(); }); }); }); - test('lookup', (done: () => void) => { - const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration); + test('lookup', () => { + const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': '_test', 'type': 'object', @@ -201,8 +189,8 @@ suite('ConfigurationService - Node', () => { } }); - testFile((testFile, cleanUp) => { - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + return testFile('config', 'config.json').then(r => { + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, r.testFile)); let res = service.inspect('something.missing'); assert.strictEqual(res.value, void 0); @@ -214,7 +202,7 @@ suite('ConfigurationService - Node', () => { assert.strictEqual(res.value, 'isSet'); assert.strictEqual(res.user, void 0); - fs.writeFileSync(testFile, '{ "lookup.service.testSetting": "bar" }'); + fs.writeFileSync(r.testFile, '{ "lookup.service.testSetting": "bar" }'); return service.reloadConfiguration().then(() => { res = service.inspect('lookup.service.testSetting'); @@ -224,13 +212,13 @@ suite('ConfigurationService - Node', () => { service.dispose(); - cleanUp(done); + return r.cleanUp(); }); }); }); - test('lookup with null', (done: () => void) => { - const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration); + test('lookup with null', () => { + const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': '_testNull', 'type': 'object', @@ -241,15 +229,15 @@ suite('ConfigurationService - Node', () => { } }); - testFile((testFile, cleanUp) => { - const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile)); + return testFile('config', 'config.json').then(r => { + const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, r.testFile)); let res = service.inspect('lookup.service.testNullSetting'); assert.strictEqual(res.default, null); assert.strictEqual(res.value, null); assert.strictEqual(res.user, void 0); - fs.writeFileSync(testFile, '{ "lookup.service.testNullSetting": null }'); + fs.writeFileSync(r.testFile, '{ "lookup.service.testNullSetting": null }'); return service.reloadConfiguration().then(() => { res = service.inspect('lookup.service.testNullSetting'); @@ -259,7 +247,7 @@ suite('ConfigurationService - Node', () => { service.dispose(); - cleanUp(done); + return r.cleanUp(); }); }); }); diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 15a6cca81c..3971a0265c 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -7,9 +7,9 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'; -import { IContextKey, IContext, IContextKeyServiceTarget, IContextKeyService, SET_CONTEXT_COMMAND_ID, ContextKeyExpr, IContextKeyChangeEvent } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKey, IContext, IContextKeyServiceTarget, IContextKeyService, SET_CONTEXT_COMMAND_ID, ContextKeyExpr, IContextKeyChangeEvent, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService, IConfigurationChangeEvent, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent } from 'vs/base/common/event'; const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context'; @@ -179,7 +179,7 @@ export class ContextKeyChangeEvent implements IContextKeyChangeEvent { this._keys = this._keys.concat(oneOrManyKeys); } - affectsSome(keys: Set<string>): boolean { + affectsSome(keys: IReadableSet<string>): boolean { for (const key of this._keys) { if (keys.has(key)) { return true; @@ -271,7 +271,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon private _toDispose: IDisposable[] = []; - constructor( @IConfigurationService configurationService: IConfigurationService) { + constructor(@IConfigurationService configurationService: IConfigurationService) { super(0); this._lastContextId = 0; this._contexts = Object.create(null); diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 838f385a09..11c1b8a622 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -5,7 +5,7 @@ 'use strict'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; export enum ContextKeyExprType { @@ -112,8 +112,9 @@ export abstract class ContextKeyExpr { } let value = serializedValue.slice(start + 1, end); + let caseIgnoreFlag = serializedValue[end + 1] === 'i' ? 'i' : ''; try { - return new RegExp(value); + return new RegExp(value, caseIgnoreFlag); } catch (e) { console.warn(`bad regexp-value '${serializedValue}', parse error: ${e}`); return null; @@ -400,7 +401,7 @@ export class ContextKeyRegexExpr implements ContextKeyExpr { } public serialize(): string { - return `${this.key} =~ /${this.regexp ? this.regexp.source : '<invalid>'}/`; + return `${this.key} =~ /${this.regexp ? this.regexp.source : '<invalid>'}/${this.regexp.ignoreCase ? 'i' : ''}`; } public keys(): string[] { @@ -553,8 +554,12 @@ export interface IContextKeyServiceTarget { export const IContextKeyService = createDecorator<IContextKeyService>('contextKeyService'); +export interface IReadableSet<T> { + has(value: T): boolean; +} + export interface IContextKeyChangeEvent { - affectsSome(keys: Set<string>): boolean; + affectsSome(keys: IReadableSet<string>): boolean; } export interface IContextKeyService { diff --git a/src/vs/platform/contextkey/test/common/contextkey.test.ts b/src/vs/platform/contextkey/test/common/contextkey.test.ts index eddc7a4bd4..0f2950d630 100644 --- a/src/vs/platform/contextkey/test/common/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/common/contextkey.test.ts @@ -81,6 +81,7 @@ suite('ContextKeyExpr', () => { testExpression(expr + ' != 5', value != <any>'5'); testExpression('!' + expr, !value); testExpression(expr + ' =~ /d.*/', /d.*/.test(value)); + testExpression(expr + ' =~ /D/i', /D/i.test(value)); } testBatch('a', true); @@ -92,7 +93,7 @@ suite('ContextKeyExpr', () => { testExpression('a && !b', true && !false); testExpression('a && b', true && false); testExpression('a && !b && c == 5', true && !false && '5' == '5'); - testExpression('dddd =~ d.*', false); + testExpression('d =~ /e.*/', false); /* tslint:enable:triple-equals */ }); }); diff --git a/src/vs/platform/contextview/browser/contextMenuService.ts b/src/vs/platform/contextview/browser/contextMenuService.ts index 7b4dd26a9d..419d992d44 100644 --- a/src/vs/platform/contextview/browser/contextMenuService.ts +++ b/src/vs/platform/contextview/browser/contextMenuService.ts @@ -7,7 +7,7 @@ import { ContextMenuHandler } from './contextMenuHandler'; import { IContextViewService, IContextMenuService } from './contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IContextMenuDelegate } from 'vs/base/browser/contextmenu'; diff --git a/src/vs/platform/contextview/browser/contextView.ts b/src/vs/platform/contextview/browser/contextView.ts index d486127184..9081bb82a4 100644 --- a/src/vs/platform/contextview/browser/contextView.ts +++ b/src/vs/platform/contextview/browser/contextView.ts @@ -5,7 +5,7 @@ 'use strict'; import { IDisposable } from 'vs/base/common/lifecycle'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IContextMenuDelegate } from 'vs/base/browser/contextmenu'; diff --git a/src/vs/platform/dialogs/common/choiceIpc.ts b/src/vs/platform/dialogs/common/choiceIpc.ts deleted file mode 100644 index 3493c03f47..0000000000 --- a/src/vs/platform/dialogs/common/choiceIpc.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { TPromise } from 'vs/base/common/winjs.base'; -import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import Severity from 'vs/base/common/severity'; - -export interface IChoiceChannel extends IChannel { - call(command: 'choose'): TPromise<number>; - call(command: string, arg?: any): TPromise<any>; -} - -export class ChoiceChannel implements IChoiceChannel { - - constructor( @IChoiceService private choiceService: IChoiceService) { - } - - call(command: string, args?: [Severity, string, string[], number, boolean]): TPromise<any> { - switch (command) { - case 'choose': return this.choiceService.choose(args[0], args[1], args[2], args[3], args[4]); - } - return TPromise.wrapError(new Error('invalid command')); - } -} - -export class ChoiceChannelClient implements IChoiceService { - - _serviceBrand: any; - - constructor(private channel: IChoiceChannel) { } - - choose(severity: Severity, message: string, options: string[], cancelId?: number, modal?: boolean): TPromise<number> { - return this.channel.call('choose', [severity, message, options, cancelId, modal]); - } -} \ No newline at end of file diff --git a/src/vs/platform/dialogs/common/dialogIpc.ts b/src/vs/platform/dialogs/common/dialogIpc.ts new file mode 100644 index 0000000000..c7dc091575 --- /dev/null +++ b/src/vs/platform/dialogs/common/dialogIpc.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { IChannel } from 'vs/base/parts/ipc/common/ipc'; +import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; +import Severity from 'vs/base/common/severity'; + +export interface IDialogChannel extends IChannel { + call(command: 'show'): TPromise<number>; + call(command: 'confirm'): TPromise<IConfirmationResult>; + call(command: string, arg?: any): TPromise<any>; +} + +export class DialogChannel implements IDialogChannel { + + constructor(@IDialogService private dialogService: IDialogService) { + } + + call(command: string, args?: any[]): TPromise<any> { + switch (command) { + case 'show': return this.dialogService.show(args[0], args[1], args[2]); + case 'confirm': return this.dialogService.confirm(args[0]); + } + return TPromise.wrapError(new Error('invalid command')); + } +} + +export class DialogChannelClient implements IDialogService { + + _serviceBrand: any; + + constructor(private channel: IDialogChannel) { } + + show(severity: Severity, message: string, options: string[]): TPromise<number> { + return this.channel.call('show', [severity, message, options]); + } + + confirm(confirmation: IConfirmation): TPromise<IConfirmationResult> { + return this.channel.call('confirm', [confirmation]); + } +} \ No newline at end of file diff --git a/src/vs/platform/dialogs/common/dialogs.ts b/src/vs/platform/dialogs/common/dialogs.ts index ea5d026c7d..2f26cabcda 100644 --- a/src/vs/platform/dialogs/common/dialogs.ts +++ b/src/vs/platform/dialogs/common/dialogs.ts @@ -7,6 +7,9 @@ import { TPromise } from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import URI from 'vs/base/common/uri'; +import { basename } from 'vs/base/common/paths'; +import { localize } from 'vs/nls'; export interface IConfirmation { title?: string; @@ -22,63 +25,66 @@ export interface IConfirmation { } export interface IConfirmationResult { + + /** + * Will be true if the dialog was confirmed with the primary button + * pressed. + */ confirmed: boolean; + + /** + * This will only be defined if the confirmation was created + * with the checkox option defined. + */ checkboxChecked?: boolean; } -export const IConfirmationService = createDecorator<IConfirmationService>('confirmationService'); +export const IDialogService = createDecorator<IDialogService>('dialogService'); -export interface IConfirmationService { +export interface IDialogOptions { + cancelId?: number; + detail?: string; +} + +/** + * A service to bring up modal dialogs. + * + * Note: use the `INotificationService.prompt()` method for a non-modal way to ask + * the user for input. + */ +export interface IDialogService { _serviceBrand: any; /** * Ask the user for confirmation with a modal dialog. */ - confirm(confirmation: IConfirmation): TPromise<boolean>; + confirm(confirmation: IConfirmation): TPromise<IConfirmationResult>; /** - * Ask the user for confirmation with a checkbox in a modal dialog. + * Present a modal dialog to the user. + * + * @returns A promise with the selected choice index. If the user refused to choose, + * then a promise with index of `cancelId` option is returned. If there is no such + * option then promise with index `0` is returned. */ - confirmWithCheckbox(confirmation: IConfirmation): TPromise<IConfirmationResult>; + show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): TPromise<number>; } -export const IChoiceService = createDecorator<IChoiceService>('choiceService'); +const MAX_CONFIRM_FILES = 10; +export function getConfirmMessage(start: string, resourcesToConfirm: URI[]): string { + const message = [start]; + message.push(''); + message.push(...resourcesToConfirm.slice(0, MAX_CONFIRM_FILES).map(r => basename(r.fsPath))); -/** - * The choices to present to the user. The `ISecondaryChoice` hint allows to control where - * choices appear when the `modal` option is set to `false`. In that case, the choices - * are presented as part of a notification and secondary choices will appear less - * prominent. - */ -export interface SecondaryChoice { - label: string; - keepOpen?: boolean; -} -export type PrimaryChoice = string; -export type Choice = PrimaryChoice | SecondaryChoice; + if (resourcesToConfirm.length > MAX_CONFIRM_FILES) { + if (resourcesToConfirm.length - MAX_CONFIRM_FILES === 1) { + message.push(localize('moreFile', "...1 additional file not shown")); + } else { + message.push(localize('moreFiles', "...{0} additional files not shown", resourcesToConfirm.length - MAX_CONFIRM_FILES)); + } + } -export interface IChoiceService { - - _serviceBrand: any; - - /** - * Prompt the user for a choice between multiple choices. - * - * @param choices the choices to present to the user. The `isSecondary` hint allows - * to control where are presented as part of a notification and secondary choices will - * appear less choices appear when the `modal` option is set to `false`. In that case, - * the choices prominent. - * - * @param when `modal` is true, this will block the user until chooses. - * - * @returns A promise with the selected choice index. The promise is cancellable - * which hides the message. The promise can return an error, meaning that - * the user refused to choose. - * - * When `modal` is true and user refused to choose, then promise with index of - * `Cancel` option is returned. If there is no such option then promise with - * `0` index is returned. - */ - choose(severity: Severity, message: string, choices: Choice[], cancelId?: number, modal?: boolean): TPromise<number>; + message.push(''); + return message.join('\n'); } \ No newline at end of file diff --git a/src/vs/platform/dialogs/node/choiceCli.ts b/src/vs/platform/dialogs/node/dialogService.ts similarity index 72% rename from src/vs/platform/dialogs/node/choiceCli.ts rename to src/vs/platform/dialogs/node/dialogService.ts index a1192a1029..108ca083b1 100644 --- a/src/vs/platform/dialogs/node/choiceCli.ts +++ b/src/vs/platform/dialogs/node/dialogService.ts @@ -5,14 +5,15 @@ import * as readline from 'readline'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; +import { localize } from 'vs/nls'; -export class ChoiceCliService implements IChoiceService { +export class CommandLineDialogService implements IDialogService { _serviceBrand: any; - choose(severity: Severity, message: string, options: string[]): TPromise<number> { + show(severity: Severity, message: string, options: string[]): TPromise<number> { const promise = new TPromise<number>((c, e) => { const rl = readline.createInterface({ input: process.stdin, @@ -55,4 +56,12 @@ export class ChoiceCliService implements IChoiceService { } return -1; } + + confirm(confirmation: IConfirmation): TPromise<IConfirmationResult> { + return this.show(Severity.Info, confirmation.message, [confirmation.primaryButton, confirmation.secondaryButton || localize('cancel', "Cancel")]).then(index => { + return { + confirmed: index === 0 + } as IConfirmationResult; + }); + } } \ No newline at end of file diff --git a/src/vs/platform/driver/common/driver.ts b/src/vs/platform/driver/common/driver.ts new file mode 100644 index 0000000000..83b5874e4c --- /dev/null +++ b/src/vs/platform/driver/common/driver.ts @@ -0,0 +1,287 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IChannel } from 'vs/base/parts/ipc/common/ipc'; + +export const ID = 'driverService'; +export const IDriver = createDecorator<IDriver>(ID); + +// !! Do not remove the following START and END markers, they are parsed by the smoketest build + +//*START +export interface IElement { + tagName: string; + className: string; + textContent: string; + attributes: { [name: string]: string; }; + children: IElement[]; +} + +export interface IDriver { + _serviceBrand: any; + + getWindowIds(): TPromise<number[]>; + capturePage(windowId: number): TPromise<string>; + reloadWindow(windowId: number): TPromise<void>; + dispatchKeybinding(windowId: number, keybinding: string): TPromise<void>; + click(windowId: number, selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>; + doubleClick(windowId: number, selector: string): TPromise<void>; + move(windowId: number, selector: string): TPromise<void>; + setValue(windowId: number, selector: string, text: string): TPromise<void>; + paste(windowId: number, selector: string, text: string): TPromise<void>; + getTitle(windowId: number): TPromise<string>; + isActiveElement(windowId: number, selector: string): TPromise<boolean>; + getElements(windowId: number, selector: string, recursive?: boolean): TPromise<IElement[]>; + typeInEditor(windowId: number, selector: string, text: string): TPromise<void>; + getTerminalBuffer(windowId: number, selector: string): TPromise<string[]>; +} +//*END + +export interface IDriverChannel extends IChannel { + call(command: 'getWindowIds'): TPromise<number[]>; + call(command: 'capturePage'): TPromise<string>; + call(command: 'reloadWindow', arg: number): TPromise<void>; + call(command: 'dispatchKeybinding', arg: [number, string]): TPromise<void>; + call(command: 'click', arg: [number, string, number | undefined, number | undefined]): TPromise<void>; + call(command: 'doubleClick', arg: [number, string]): TPromise<void>; + call(command: 'move', arg: [number, string]): TPromise<void>; + call(command: 'setValue', arg: [number, string, string]): TPromise<void>; + call(command: 'paste', arg: [number, string, string]): TPromise<void>; + call(command: 'getTitle', arg: [number]): TPromise<string>; + call(command: 'isActiveElement', arg: [number, string]): TPromise<boolean>; + call(command: 'getElements', arg: [number, string, boolean]): TPromise<IElement[]>; + call(command: 'typeInEditor', arg: [number, string, string]): TPromise<void>; + call(command: 'getTerminalBuffer', arg: [number, string]): TPromise<string[]>; + call(command: string, arg: any): TPromise<any>; +} + +export class DriverChannel implements IDriverChannel { + + constructor(private driver: IDriver) { } + + call(command: string, arg?: any): TPromise<any> { + switch (command) { + case 'getWindowIds': return this.driver.getWindowIds(); + case 'capturePage': return this.driver.capturePage(arg); + case 'reloadWindow': return this.driver.reloadWindow(arg); + case 'dispatchKeybinding': return this.driver.dispatchKeybinding(arg[0], arg[1]); + case 'click': return this.driver.click(arg[0], arg[1], arg[2], arg[3]); + case 'doubleClick': return this.driver.doubleClick(arg[0], arg[1]); + case 'move': return this.driver.move(arg[0], arg[1]); + case 'setValue': return this.driver.setValue(arg[0], arg[1], arg[2]); + case 'paste': return this.driver.paste(arg[0], arg[1], arg[2]); + case 'getTitle': return this.driver.getTitle(arg[0]); + case 'isActiveElement': return this.driver.isActiveElement(arg[0], arg[1]); + case 'getElements': return this.driver.getElements(arg[0], arg[1], arg[2]); + case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1], arg[2]); + case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg[0], arg[1]); + } + + return undefined; + } +} + +export class DriverChannelClient implements IDriver { + + _serviceBrand: any; + + constructor(private channel: IDriverChannel) { } + + getWindowIds(): TPromise<number[]> { + return this.channel.call('getWindowIds'); + } + + capturePage(windowId: number): TPromise<string> { + return this.channel.call('capturePage', windowId); + } + + reloadWindow(windowId: number): TPromise<void> { + return this.channel.call('reloadWindow', windowId); + } + + dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> { + return this.channel.call('dispatchKeybinding', [windowId, keybinding]); + } + + click(windowId: number, selector: string, xoffset: number | undefined, yoffset: number | undefined): TPromise<void> { + return this.channel.call('click', [windowId, selector, xoffset, yoffset]); + } + + doubleClick(windowId: number, selector: string): TPromise<void> { + return this.channel.call('doubleClick', [windowId, selector]); + } + + move(windowId: number, selector: string): TPromise<void> { + return this.channel.call('move', [windowId, selector]); + } + + setValue(windowId: number, selector: string, text: string): TPromise<void> { + return this.channel.call('setValue', [windowId, selector, text]); + } + + paste(windowId: number, selector: string, text: string): TPromise<void> { + return this.channel.call('paste', [windowId, selector, text]); + } + + getTitle(windowId: number): TPromise<string> { + return this.channel.call('getTitle', [windowId]); + } + + isActiveElement(windowId: number, selector: string): TPromise<boolean> { + return this.channel.call('isActiveElement', [windowId, selector]); + } + + getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> { + return this.channel.call('getElements', [windowId, selector, recursive]); + } + + typeInEditor(windowId: number, selector: string, text: string): TPromise<void> { + return this.channel.call('typeInEditor', [windowId, selector, text]); + } + + getTerminalBuffer(windowId: number, selector: string): TPromise<string[]> { + return this.channel.call('getTerminalBuffer', [windowId, selector]); + } +} + +export interface IWindowDriverRegistry { + registerWindowDriver(windowId: number): TPromise<void>; + reloadWindowDriver(windowId: number): TPromise<void>; +} + +export interface IWindowDriverRegistryChannel extends IChannel { + call(command: 'registerWindowDriver', arg: number): TPromise<void>; + call(command: 'reloadWindowDriver', arg: number): TPromise<void>; + call(command: string, arg: any): TPromise<any>; +} + +export class WindowDriverRegistryChannel implements IWindowDriverRegistryChannel { + + constructor(private registry: IWindowDriverRegistry) { } + + call(command: string, arg?: any): TPromise<any> { + switch (command) { + case 'registerWindowDriver': return this.registry.registerWindowDriver(arg); + case 'reloadWindowDriver': return this.registry.reloadWindowDriver(arg); + } + + return undefined; + } +} + +export class WindowDriverRegistryChannelClient implements IWindowDriverRegistry { + + _serviceBrand: any; + + constructor(private channel: IWindowDriverRegistryChannel) { } + + registerWindowDriver(windowId: number): TPromise<void> { + return this.channel.call('registerWindowDriver', windowId); + } + + reloadWindowDriver(windowId: number): TPromise<void> { + return this.channel.call('reloadWindowDriver', windowId); + } +} + +export interface IWindowDriver { + click(selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>; + doubleClick(selector: string): TPromise<void>; + move(selector: string): TPromise<void>; + setValue(selector: string, text: string): TPromise<void>; + paste(selector: string, text: string): TPromise<void>; + getTitle(): TPromise<string>; + isActiveElement(selector: string): TPromise<boolean>; + getElements(selector: string, recursive: boolean): TPromise<IElement[]>; + typeInEditor(selector: string, text: string): TPromise<void>; + getTerminalBuffer(selector: string): TPromise<string[]>; +} + +export interface IWindowDriverChannel extends IChannel { + call(command: 'click', arg: [string, number | undefined, number | undefined]): TPromise<void>; + call(command: 'doubleClick', arg: string): TPromise<void>; + call(command: 'move', arg: string): TPromise<void>; + call(command: 'setValue', arg: [string, string]): TPromise<void>; + call(command: 'paste', arg: [string, string]): TPromise<void>; + call(command: 'getTitle'): TPromise<string>; + call(command: 'isActiveElement', arg: string): TPromise<boolean>; + call(command: 'getElements', arg: [string, boolean]): TPromise<IElement[]>; + call(command: 'typeInEditor', arg: [string, string]): TPromise<void>; + call(command: 'getTerminalBuffer', arg: string): TPromise<string[]>; + call(command: string, arg: any): TPromise<any>; +} + +export class WindowDriverChannel implements IWindowDriverChannel { + + constructor(private driver: IWindowDriver) { } + + call(command: string, arg?: any): TPromise<any> { + switch (command) { + case 'click': return this.driver.click(arg[0], arg[1], arg[2]); + case 'doubleClick': return this.driver.doubleClick(arg); + case 'move': return this.driver.move(arg); + case 'setValue': return this.driver.setValue(arg[0], arg[1]); + case 'paste': return this.driver.paste(arg[0], arg[1]); + case 'getTitle': return this.driver.getTitle(); + case 'isActiveElement': return this.driver.isActiveElement(arg); + case 'getElements': return this.driver.getElements(arg[0], arg[1]); + case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1]); + case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg); + } + + return undefined; + } +} + +export class WindowDriverChannelClient implements IWindowDriver { + + _serviceBrand: any; + + constructor(private channel: IWindowDriverChannel) { } + + click(selector: string, xoffset?: number, yoffset?: number): TPromise<void> { + return this.channel.call('click', [selector, xoffset, yoffset]); + } + + doubleClick(selector: string): TPromise<void> { + return this.channel.call('doubleClick', selector); + } + + move(selector: string): TPromise<void> { + return this.channel.call('move', selector); + } + + setValue(selector: string, text: string): TPromise<void> { + return this.channel.call('setValue', [selector, text]); + } + + paste(selector: string, text: string): TPromise<void> { + return this.channel.call('paste', [selector, text]); + } + + getTitle(): TPromise<string> { + return this.channel.call('getTitle'); + } + + isActiveElement(selector: string): TPromise<boolean> { + return this.channel.call('isActiveElement', selector); + } + + getElements(selector: string, recursive: boolean): TPromise<IElement[]> { + return this.channel.call('getElements', [selector, recursive]); + } + + typeInEditor(selector: string, text: string): TPromise<void> { + return this.channel.call('typeInEditor', [selector, text]); + } + + getTerminalBuffer(selector: string): TPromise<string[]> { + return this.channel.call('getTerminalBuffer', selector); + } +} \ No newline at end of file diff --git a/src/vs/platform/driver/electron-browser/driver.ts b/src/vs/platform/driver/electron-browser/driver.ts new file mode 100644 index 0000000000..699093c582 --- /dev/null +++ b/src/vs/platform/driver/electron-browser/driver.ts @@ -0,0 +1,204 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/common/driver'; +import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { getTopLeftOffset, getClientArea } from 'vs/base/browser/dom'; +import * as electron from 'electron'; + +function serializeElement(element: Element, recursive: boolean): IElement { + const attributes = Object.create(null); + + for (let j = 0; j < element.attributes.length; j++) { + const attr = element.attributes.item(j); + attributes[attr.name] = attr.value; + } + + const children = []; + + if (recursive) { + for (let i = 0; i < element.children.length; i++) { + children.push(serializeElement(element.children.item(i), true)); + } + } + + return { + tagName: element.tagName, + className: element.className, + textContent: element.textContent || '', + attributes, + children + }; +} + +class WindowDriver implements IWindowDriver { + + constructor() { } + + async click(selector: string, xoffset?: number, yoffset?: number): TPromise<void> { + return this._click(selector, 1, xoffset, yoffset); + } + + doubleClick(selector: string): TPromise<void> { + return this._click(selector, 2); + } + + private async _getElementXY(selector: string, xoffset?: number, yoffset?: number): TPromise<{ x: number; y: number; }> { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Element not found'); + } + + const { left, top } = getTopLeftOffset(element as HTMLElement); + const { width, height } = getClientArea(element as HTMLElement); + let x: number, y: number; + + if ((typeof xoffset === 'number') || (typeof yoffset === 'number')) { + x = left + xoffset; + y = top + yoffset; + } else { + x = left + (width / 2); + y = top + (height / 2); + } + + x = Math.round(x); + y = Math.round(y); + + return { x, y }; + } + + private async _click(selector: string, clickCount: number, xoffset?: number, yoffset?: number): TPromise<void> { + const { x, y } = await this._getElementXY(selector, xoffset, yoffset); + const webContents = electron.remote.getCurrentWebContents(); + webContents.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount } as any); + webContents.sendInputEvent({ type: 'mouseUp', x, y, button: 'left', clickCount } as any); + + await TPromise.timeout(100); + } + + async move(selector: string): TPromise<void> { + const { x, y } = await this._getElementXY(selector); + const webContents = electron.remote.getCurrentWebContents(); + webContents.sendInputEvent({ type: 'mouseMove', x, y } as any); + + await TPromise.timeout(100); + } + + async setValue(selector: string, text: string): TPromise<void> { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Element not found'); + } + + const inputElement = element as HTMLInputElement; + inputElement.value = text; + + const event = new Event('input', { bubbles: true, cancelable: true }); + inputElement.dispatchEvent(event); + } + + async paste(selector: string, text: string): TPromise<void> { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Element not found'); + } + + const inputElement = element as HTMLInputElement; + const clipboardData = new DataTransfer(); + clipboardData.setData('text/plain', text); + const event = new ClipboardEvent('paste', { clipboardData } as any); + + inputElement.dispatchEvent(event); + } + + async getTitle(): TPromise<string> { + return document.title; + } + + async isActiveElement(selector: string): TPromise<boolean> { + const element = document.querySelector(selector); + return element === document.activeElement; + } + + async getElements(selector: string, recursive: boolean): TPromise<IElement[]> { + const query = document.querySelectorAll(selector); + const result: IElement[] = []; + + for (let i = 0; i < query.length; i++) { + const element = query.item(i); + result.push(serializeElement(element, recursive)); + } + + return result; + } + + async typeInEditor(selector: string, text: string): TPromise<void> { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Editor not found: ' + selector); + } + + const textarea = element as HTMLTextAreaElement; + const start = textarea.selectionStart; + const newStart = start + text.length; + const value = textarea.value; + const newValue = value.substr(0, start) + text + value.substr(start); + + textarea.value = newValue; + textarea.setSelectionRange(newStart, newStart); + + const event = new Event('input', { 'bubbles': true, 'cancelable': true }); + textarea.dispatchEvent(event); + } + + async getTerminalBuffer(selector: string): TPromise<string[]> { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Terminal not found: ' + selector); + } + + const xterm = (element as any).xterm; + + if (!xterm) { + throw new Error('Xterm not found: ' + selector); + } + + const lines: string[] = []; + + for (let i = 0; i < xterm.buffer.lines.length; i++) { + lines.push(xterm.buffer.translateBufferLineToString(i, true)); + } + + return lines; + } +} + +export async function registerWindowDriver( + client: IPCClient, + windowId: number, + instantiationService: IInstantiationService +): TPromise<IDisposable> { + const windowDriver = instantiationService.createInstance(WindowDriver); + const windowDriverChannel = new WindowDriverChannel(windowDriver); + client.registerChannel('windowDriver', windowDriverChannel); + + const windowDriverRegistryChannel = client.getChannel('windowDriverRegistry'); + const windowDriverRegistry = new WindowDriverRegistryChannelClient(windowDriverRegistryChannel); + + await windowDriverRegistry.registerWindowDriver(windowId); + + const disposable = toDisposable(() => windowDriverRegistry.reloadWindowDriver(windowId)); + return combinedDisposable([disposable, client]); +} \ No newline at end of file diff --git a/src/vs/platform/driver/electron-main/driver.ts b/src/vs/platform/driver/electron-main/driver.ts new file mode 100644 index 0000000000..87f16bb0f1 --- /dev/null +++ b/src/vs/platform/driver/electron-main/driver.ts @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { IDriver, DriverChannel, IElement, IWindowDriverChannel, WindowDriverChannelClient, IWindowDriverRegistry, WindowDriverRegistryChannel, IWindowDriver } from 'vs/platform/driver/common/driver'; +import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; +import { serve as serveNet } from 'vs/base/parts/ipc/node/ipc.net'; +import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IPCServer, IClientRouter } from 'vs/base/parts/ipc/common/ipc'; +import { SimpleKeybinding, KeyCode } from 'vs/base/common/keyCodes'; +import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; +import { OS } from 'vs/base/common/platform'; +import { Emitter, toPromise } from 'vs/base/common/event'; + +// TODO@joao: bad layering! +import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; +import { ScanCodeBinding } from 'vs/workbench/services/keybinding/common/scanCode'; +import { NativeImage } from 'electron'; + +class WindowRouter implements IClientRouter { + + constructor(private windowId: number) { } + + route(command: string, arg: any): string { + return `window:${this.windowId}`; + } +} + +function isSilentKeyCode(keyCode: KeyCode) { + return keyCode < KeyCode.KEY_0; +} + +export class Driver implements IDriver, IWindowDriverRegistry { + + _serviceBrand: any; + + private registeredWindowIds = new Set<number>(); + private reloadingWindowIds = new Set<number>(); + private onDidReloadingChange = new Emitter<void>(); + + constructor( + private windowServer: IPCServer, + @IWindowsMainService private windowsService: IWindowsMainService + ) { } + + async registerWindowDriver(windowId: number): TPromise<void> { + this.registeredWindowIds.add(windowId); + this.reloadingWindowIds.delete(windowId); + this.onDidReloadingChange.fire(); + } + + async reloadWindowDriver(windowId: number): TPromise<void> { + this.reloadingWindowIds.add(windowId); + } + + async getWindowIds(): TPromise<number[]> { + return this.windowsService.getWindows() + .map(w => w.id) + .filter(id => this.registeredWindowIds.has(id) && !this.reloadingWindowIds.has(id)); + } + + async capturePage(windowId: number): TPromise<string> { + await this.whenUnfrozen(windowId); + + const window = this.windowsService.getWindowById(windowId); + const webContents = window.win.webContents; + const image = await new Promise<NativeImage>(c => webContents.capturePage(c)); + const buffer = image.toPNG(); + + return buffer.toString('base64'); + } + + async reloadWindow(windowId: number): TPromise<void> { + await this.whenUnfrozen(windowId); + + const window = this.windowsService.getWindowById(windowId); + this.reloadingWindowIds.add(windowId); + this.windowsService.reload(window); + } + + async dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> { + await this.whenUnfrozen(windowId); + + const [first, second] = KeybindingIO._readUserBinding(keybinding); + + await this._dispatchKeybinding(windowId, first); + + if (second) { + await this._dispatchKeybinding(windowId, second); + } + } + + private async _dispatchKeybinding(windowId: number, keybinding: SimpleKeybinding | ScanCodeBinding): TPromise<void> { + if (keybinding instanceof ScanCodeBinding) { + throw new Error('ScanCodeBindings not supported'); + } + + const window = this.windowsService.getWindowById(windowId); + const webContents = window.win.webContents; + const noModifiedKeybinding = new SimpleKeybinding(false, false, false, false, keybinding.keyCode); + const resolvedKeybinding = new USLayoutResolvedKeybinding(noModifiedKeybinding, OS); + const keyCode = resolvedKeybinding.getElectronAccelerator(); + + const modifiers = []; + + if (keybinding.ctrlKey) { + modifiers.push('ctrl'); + } + + if (keybinding.metaKey) { + modifiers.push('meta'); + } + + if (keybinding.shiftKey) { + modifiers.push('shift'); + } + + if (keybinding.altKey) { + modifiers.push('alt'); + } + + webContents.sendInputEvent({ type: 'keyDown', keyCode, modifiers } as any); + + if (!isSilentKeyCode(keybinding.keyCode)) { + webContents.sendInputEvent({ type: 'char', keyCode, modifiers } as any); + } + + webContents.sendInputEvent({ type: 'keyUp', keyCode, modifiers } as any); + + await TPromise.timeout(100); + } + + async click(windowId: number, selector: string, xoffset?: number, yoffset?: number): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.click(selector, xoffset, yoffset); + } + + async doubleClick(windowId: number, selector: string): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.doubleClick(selector); + } + + async move(windowId: number, selector: string): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.move(selector); + } + + async setValue(windowId: number, selector: string, text: string): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.setValue(selector, text); + } + + async paste(windowId: number, selector: string, text: string): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.paste(selector, text); + } + + async getTitle(windowId: number): TPromise<string> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.getTitle(); + } + + async isActiveElement(windowId: number, selector: string): TPromise<boolean> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.isActiveElement(selector); + } + + async getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.getElements(selector, recursive); + } + + async typeInEditor(windowId: number, selector: string, text: string): TPromise<void> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.typeInEditor(selector, text); + } + + async getTerminalBuffer(windowId: number, selector: string): TPromise<string[]> { + const windowDriver = await this.getWindowDriver(windowId); + return windowDriver.getTerminalBuffer(selector); + } + + private async getWindowDriver(windowId: number): TPromise<IWindowDriver> { + await this.whenUnfrozen(windowId); + + const router = new WindowRouter(windowId); + const windowDriverChannel = this.windowServer.getChannel<IWindowDriverChannel>('windowDriver', router); + return new WindowDriverChannelClient(windowDriverChannel); + } + + private async whenUnfrozen(windowId: number): TPromise<void> { + while (this.reloadingWindowIds.has(windowId)) { + await toPromise(this.onDidReloadingChange.event); + } + } +} + +export async function serve( + windowServer: IPCServer, + handle: string, + instantiationService: IInstantiationService +): TPromise<IDisposable> { + const driver = instantiationService.createInstance(Driver, windowServer); + + const windowDriverRegistryChannel = new WindowDriverRegistryChannel(driver); + windowServer.registerChannel('windowDriverRegistry', windowDriverRegistryChannel); + + const server = await serveNet(handle); + const channel = new DriverChannel(driver); + server.registerChannel('driver', channel); + + return combinedDisposable([server, windowServer]); +} \ No newline at end of file diff --git a/src/vs/platform/driver/node/driver.ts b/src/vs/platform/driver/node/driver.ts new file mode 100644 index 0000000000..30bbeed223 --- /dev/null +++ b/src/vs/platform/driver/node/driver.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise } from 'vs/base/common/winjs.base'; +import { IDriver, DriverChannelClient } from 'vs/platform/driver/common/driver'; +import { connect as connectNet, Client } from 'vs/base/parts/ipc/node/ipc.net'; + +export async function connect(handle: string): TPromise<{ client: Client, driver: IDriver }> { + const client = await connectNet(handle, 'driverClient'); + const channel = client.getChannel('driver'); + const driver = new DriverChannelClient(channel); + return { client, driver }; +} diff --git a/src/vs/platform/editor/common/editor.ts b/src/vs/platform/editor/common/editor.ts index c1e37e9b41..eb9793e80e 100644 --- a/src/vs/platform/editor/common/editor.ts +++ b/src/vs/platform/editor/common/editor.ts @@ -7,7 +7,7 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; export const IEditorService = createDecorator<IEditorService>('editorService'); @@ -259,28 +259,28 @@ export interface IEditorOptions { * Tells the editor to not receive keyboard focus when the editor is being opened. By default, * the editor will receive keyboard focus on open. */ - preserveFocus?: boolean; + readonly preserveFocus?: boolean; /** * Tells the editor to replace the editor input in the editor even if it is identical to the one * already showing. By default, the editor will not replace the input if it is identical to the * one showing. */ - forceOpen?: boolean; + readonly forceOpen?: boolean; /** * Will reveal the editor if it is already opened and visible in any of the opened editor groups. Note * that this option is just a hint that might be ignored if the user wants to open an editor explicitly * to the side of another one. */ - revealIfVisible?: boolean; + readonly revealIfVisible?: boolean; /** * Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups. Note * that this option is just a hint that might be ignored if the user wants to open an editor explicitly * to the side of another one. */ - revealIfOpened?: boolean; + readonly revealIfOpened?: boolean; /** * An editor that is pinned remains in the editor stack even when another editor is being opened. @@ -291,13 +291,13 @@ export interface IEditorOptions { /** * The index in the document stack where to insert the editor into when opening. */ - index?: number; + readonly index?: number; /** * An active editor that is opened will show its contents directly. Set to true to open an editor * in the background. */ - inactive?: boolean; + readonly inactive?: boolean; } export interface ITextEditorSelection { diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index aea99a1c4c..668e7bab89 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -57,6 +57,7 @@ export interface ParsedArgs { 'file-write'?: boolean; 'file-chmod'?: boolean; 'upload-logs'?: string; + 'driver'?: string; } export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService'); @@ -130,4 +131,6 @@ export interface IEnvironmentService { installSourcePath: string; disableUpdates: boolean; disableCrashReporter: boolean; + + driverHandle: string; } diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index a123886dad..ca29b4da72 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -29,7 +29,8 @@ const options: minimist.Opts = { 'enable-proposed-api', 'export-default-configuration', 'install-source', - 'upload-logs' + 'upload-logs', + 'driver' ], boolean: [ 'help', @@ -153,7 +154,7 @@ const extensionsHelp: { [name: string]: string; } = { '--show-versions': localize('showVersions', "Show versions of installed extensions, when using --list-extension."), '--install-extension (<extension-id> | <extension-vsix-path>)': localize('installExtension', "Installs an extension."), '--uninstall-extension (<extension-id> | <extension-vsix-path>)': localize('uninstallExtension', "Uninstalls an extension."), - '--enable-proposed-api <extension-id>': localize('experimentalApis', "Enables proposed api features for an extension.") + '--enable-proposed-api <extension-id>': localize('experimentalApis', "Enables proposed API features for an extension.") }; const troubleshootingHelp: { [name: string]: string; } = { @@ -163,8 +164,8 @@ const troubleshootingHelp: { [name: string]: string; } = { '-p, --performance': localize('performance', "Start with the 'Developer: Startup Performance' command enabled."), '--prof-startup': localize('prof-startup', "Run CPU profiler during startup"), '--disable-extensions': localize('disableExtensions', "Disable all installed extensions."), - '--inspect-extensions': localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection uri."), - '--inspect-brk-extensions': localize('inspect-brk-extensions', "Allow debugging and profiling of extensions with the extension host being paused after start. Check the developer tools for the connection uri."), + '--inspect-extensions': localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI."), + '--inspect-brk-extensions': localize('inspect-brk-extensions', "Allow debugging and profiling of extensions with the extension host being paused after start. Check the developer tools for the connection URI."), '--disable-gpu': localize('disableGPU', "Disable GPU hardware acceleration."), '--upload-logs': localize('uploadLogs', "Uploads logs from current session to a secure endpoint."), '--max-memory': localize('maxMemory', "Max memory size for a window (in Mbytes).") diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index db740ddad2..d3d98bc040 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -170,6 +170,8 @@ export class EnvironmentService implements IEnvironmentService { get disableUpdates(): boolean { return !!this._args['disable-updates']; } get disableCrashReporter(): boolean { return !!this._args['disable-crash-reporter']; } + get driverHandle(): string { return this._args['driver']; } + constructor(private _args: ParsedArgs, private _execPath: string) { if (!process.env['VSCODE_LOGS']) { const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, ''); diff --git a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts index 65b6f67731..620d731c3f 100644 --- a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts @@ -5,11 +5,10 @@ import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import { distinct, coalesce } from 'vs/base/common/arrays'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState, ILocalExtension, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { adoptToGalleryExtensionId, getIdFromLocalExtensionId, areSameExtensions, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState, ILocalExtension, isIExtensionIdentifier, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { getIdFromLocalExtensionId, areSameExtensions, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -24,7 +23,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService { private disposables: IDisposable[] = []; private _onEnablementChanged = new Emitter<IExtensionIdentifier>(); - public onEnablementChanged: Event<IExtensionIdentifier> = this._onEnablementChanged.event; + public readonly onEnablementChanged: Event<IExtensionIdentifier> = this._onEnablementChanged.event; constructor( @IStorageService private storageService: IStorageService, @@ -58,10 +57,11 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return TPromise.as(result); } - getEnablementState(identifier: IExtensionIdentifier): EnablementState { - if (this.environmentService.disableExtensions) { + getEnablementState(extension: ILocalExtension): EnablementState { + if (this.environmentService.disableExtensions && extension.type === LocalExtensionType.User) { return EnablementState.Disabled; } + const identifier = this._getIdentifier(extension); if (this.hasWorkspace) { if (this._getEnabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) { return EnablementState.WorkspaceEnabled; @@ -78,18 +78,24 @@ export class ExtensionEnablementService implements IExtensionEnablementService { } canChangeEnablement(extension: ILocalExtension): boolean { - return !this.environmentService.disableExtensions && !(extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length); + if (extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) { + return false; + } + if (extension.type === LocalExtensionType.User && this.environmentService.disableExtensions) { + return false; + } + return true; } setEnablement(arg: ILocalExtension | IExtensionIdentifier, newState: EnablementState): TPromise<boolean> { - let identifier; + let identifier: IExtensionIdentifier; if (isIExtensionIdentifier(arg)) { identifier = arg; } else { if (!this.canChangeEnablement(arg)) { return TPromise.wrap(false); } - identifier = { id: getGalleryExtensionIdFromLocal(arg), uuid: arg.identifier.uuid }; + identifier = this._getIdentifier(arg); } const workspace = newState === EnablementState.WorkspaceDisabled || newState === EnablementState.WorkspaceEnabled; @@ -97,7 +103,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return TPromise.wrapError<boolean>(new Error(localize('noWorkspace', "No workspace."))); } - const currentState = this.getEnablementState(identifier); + const currentState = this._getEnablementState(identifier); if (currentState === newState) { return TPromise.as(false); @@ -123,16 +129,29 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return TPromise.as(true); } - isEnabled(identifier: IExtensionIdentifier): boolean { - const enablementState = this.getEnablementState(identifier); + isEnabled(extension: ILocalExtension): boolean { + const enablementState = this.getEnablementState(extension); return enablementState === EnablementState.WorkspaceEnabled || enablementState === EnablementState.Enabled; } - migrateToIdentifiers(installed: IExtensionIdentifier[]): void { - this._migrateDisabledExtensions(installed, StorageScope.GLOBAL); + private _getEnablementState(identifier: IExtensionIdentifier): EnablementState { if (this.hasWorkspace) { - this._migrateDisabledExtensions(installed, StorageScope.WORKSPACE); + if (this._getEnabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) { + return EnablementState.WorkspaceEnabled; + } + + if (this._getDisabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) { + return EnablementState.WorkspaceDisabled; + } } + if (this._getDisabledExtensions(StorageScope.GLOBAL).filter(e => areSameExtensions(e, identifier))[0]) { + return EnablementState.Disabled; + } + return EnablementState.Enabled; + } + + private _getIdentifier(extension: ILocalExtension): IExtensionIdentifier { + return { id: getGalleryExtensionIdFromLocal(extension), uuid: extension.identifier.uuid }; } private _enableExtension(identifier: IExtensionIdentifier): void { @@ -227,8 +246,8 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return this._getExtensions(DISABLED_EXTENSIONS_STORAGE_PATH, scope); } - private _setDisabledExtensions(disabledExtensions: IExtensionIdentifier[], scope: StorageScope, extension: IExtensionIdentifier, fireEvent = true): void { - this._setExtensions(DISABLED_EXTENSIONS_STORAGE_PATH, disabledExtensions, scope, extension, fireEvent); + private _setDisabledExtensions(disabledExtensions: IExtensionIdentifier[], scope: StorageScope, extension: IExtensionIdentifier): void { + this._setExtensions(DISABLED_EXTENSIONS_STORAGE_PATH, disabledExtensions, scope, extension); } private _getExtensions(storageId: string, scope: StorageScope): IExtensionIdentifier[] { @@ -239,30 +258,12 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return value ? JSON.parse(value) : []; } - private _setExtensions(storageId: string, extensions: IExtensionIdentifier[], scope: StorageScope, extension: IExtensionIdentifier, fireEvent = true): void { + private _setExtensions(storageId: string, extensions: IExtensionIdentifier[], scope: StorageScope, extension: IExtensionIdentifier): void { if (extensions.length) { this.storageService.store(storageId, JSON.stringify(extensions.map(({ id, uuid }) => (<IExtensionIdentifier>{ id, uuid }))), scope); } else { this.storageService.remove(storageId, scope); } - if (fireEvent) { - this._onEnablementChanged.fire(extension); - } - } - - private _migrateDisabledExtensions(installedExtensions: IExtensionIdentifier[], scope: StorageScope): void { - const oldValue = this.storageService.get('extensions/disabled', scope, ''); - if (oldValue) { - const extensionIdentifiers = coalesce(distinct(oldValue.split(',')).map(id => { - id = adoptToGalleryExtensionId(id); - const matched = installedExtensions.filter(installed => areSameExtensions({ id }, { id: installed.id }))[0]; - return matched ? { id: matched.id, uuid: matched.uuid } : null; - })); - if (extensionIdentifiers.length) { - this.storageService.store(DISABLED_EXTENSIONS_STORAGE_PATH, JSON.stringify(extensionIdentifiers), scope); - } - } - this.storageService.remove('extensions/disabled', scope); } private _onDidUninstallExtension({ identifier, error }: DidUninstallExtensionEvent): void { diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 207069bef8..f9775d6368 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IPager } from 'vs/base/common/paging'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ILocalization } from 'vs/platform/localizations/common/localizations'; @@ -118,6 +118,12 @@ export interface IExtensionManifest { activationEvents?: string[]; extensionDependencies?: string[]; contributes?: IExtensionContributions; + repository?: { + url: string; + }; + bugs?: { + url: string; + }; } export interface IGalleryExtensionProperties { @@ -149,6 +155,12 @@ export function isIExtensionIdentifier(thing: any): thing is IExtensionIdentifie && (!thing.uuid || typeof thing.uuid === 'string'); } +/* __GDPR__FRAGMENT__ + "ExtensionIdentifier" : { + "id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "uuid": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ export interface IExtensionIdentifier { id: string; uuid?: string; @@ -274,10 +286,10 @@ export interface IExtensionManagementService { onUninstallExtension: Event<IExtensionIdentifier>; onDidUninstallExtension: Event<DidUninstallExtensionEvent>; - install(zipPath: string): TPromise<void>; - installFromGallery(extension: IGalleryExtension): TPromise<void>; + install(zipPath: string): TPromise<ILocalExtension>; + installFromGallery(extension: IGalleryExtension): TPromise<ILocalExtension>; uninstall(extension: ILocalExtension, force?: boolean): TPromise<void>; - reinstall(extension: ILocalExtension): TPromise<void>; + reinstallFromGallery(extension: ILocalExtension): TPromise<ILocalExtension>; getInstalled(type?: LocalExtensionType): TPromise<ILocalExtension[]>; getExtensionsReport(): TPromise<IReportedExtension[]>; @@ -311,7 +323,7 @@ export interface IExtensionEnablementService { /** * Returns the enablement state for the given extension */ - getEnablementState(identifier: IExtensionIdentifier): EnablementState; + getEnablementState(extension: ILocalExtension): EnablementState; /** * Returns `true` if the enablement can be changed. @@ -321,7 +333,7 @@ export interface IExtensionEnablementService { /** * Returns `true` if the given extension identifier is enabled. */ - isEnabled(identifier: IExtensionIdentifier): boolean; + isEnabled(extension: ILocalExtension): boolean; /** * Enable or disable the given extension. @@ -333,12 +345,6 @@ export interface IExtensionEnablementService { * Throws error if enablement is requested for workspace and there is no workspace */ setEnablement(extension: ILocalExtension, state: EnablementState): TPromise<boolean>; - /** - * TODO: @Sandy. Use setEnablement(extension: ILocalExtension, state: EnablementState): TPromise<boolean>. Use one model for extension management and runtime - */ - setEnablement(identifier: IExtensionIdentifier, state: EnablementState): TPromise<boolean>; - - migrateToIdentifiers(installed: IExtensionIdentifier[]): void; } export const IExtensionTipsService = createDecorator<IExtensionTipsService>('extensionTipsService'); diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index f2d07a9ae0..a76c6c121c 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -8,16 +8,17 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from './extensionManagement'; -import Event, { buffer } from 'vs/base/common/event'; +import { Event, buffer } from 'vs/base/common/event'; export interface IExtensionManagementChannel extends IChannel { call(command: 'event:onInstallExtension'): TPromise<void>; call(command: 'event:onDidInstallExtension'): TPromise<void>; call(command: 'event:onUninstallExtension'): TPromise<void>; call(command: 'event:onDidUninstallExtension'): TPromise<void>; - call(command: 'install', path: string): TPromise<void>; - call(command: 'installFromGallery', extension: IGalleryExtension): TPromise<void>; + call(command: 'install', path: string): TPromise<ILocalExtension>; + call(command: 'installFromGallery', extension: IGalleryExtension): TPromise<ILocalExtension>; call(command: 'uninstall', args: [ILocalExtension, boolean]): TPromise<void>; + call(command: 'reinstallFromGallery', args: [ILocalExtension]): TPromise<ILocalExtension>; call(command: 'getInstalled'): TPromise<ILocalExtension[]>; call(command: 'getExtensionsReport'): TPromise<IReportedExtension[]>; call(command: string, arg?: any): TPromise<any>; @@ -46,7 +47,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel { case 'install': return this.service.install(arg); case 'installFromGallery': return this.service.installFromGallery(arg[0]); case 'uninstall': return this.service.uninstall(arg[0], arg[1]); - case 'reinstall': return this.service.reinstall(arg[0]); + case 'reinstallFromGallery': return this.service.reinstallFromGallery(arg[0]); case 'getInstalled': return this.service.getInstalled(arg); case 'updateMetadata': return this.service.updateMetadata(arg[0], arg[1]); case 'getExtensionsReport': return this.service.getExtensionsReport(); @@ -73,11 +74,11 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer private _onDidUninstallExtension = eventFromCall<DidUninstallExtensionEvent>(this.channel, 'event:onDidUninstallExtension'); get onDidUninstallExtension(): Event<DidUninstallExtensionEvent> { return this._onDidUninstallExtension; } - install(zipPath: string): TPromise<void> { + install(zipPath: string): TPromise<ILocalExtension> { return this.channel.call('install', zipPath); } - installFromGallery(extension: IGalleryExtension): TPromise<void> { + installFromGallery(extension: IGalleryExtension): TPromise<ILocalExtension> { return this.channel.call('installFromGallery', [extension]); } @@ -85,8 +86,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer return this.channel.call('uninstall', [extension, force]); } - reinstall(extension: ILocalExtension): TPromise<void> { - return this.channel.call('reinstall', [extension]); + reinstallFromGallery(extension: ILocalExtension): TPromise<ILocalExtension> { + return this.channel.call('reinstallFromGallery', [extension]); } getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> { diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index d423603f86..4b11328e86 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -82,10 +82,10 @@ export function getLocalExtensionTelemetryData(extension: ILocalExtension): any "id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "name": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "galleryId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "publisherId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "publisherName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "publisherDisplayName": { "classification": "PublicPersonalData", "purpose": "FeatureInsight" }, - "dependencies": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "publisherId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "publisherName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "publisherDisplayName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "dependencies": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "${include}": [ "${GalleryExtensionTelemetryData2}" ] diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index 9d447dcdd8..d4608496da 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -18,7 +18,7 @@ import { IPager } from 'vs/base/common/paging'; import { IRequestOptions, IRequestContext, download, asJson, asText } from 'vs/base/node/request'; import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; -import { isVersionValid } from 'vs/platform/extensions/node/extensionValidator'; +import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { readFile } from 'vs/base/node/pfs'; import { writeFileAndFlushSync } from 'vs/base/node/extfs'; @@ -324,7 +324,7 @@ function toExtension(galleryExtension: IRawGalleryExtension, extensionsGalleryUr }, /* __GDPR__FRAGMENT__ "GalleryExtensionTelemetryData2" : { - "index" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "index" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "searchText": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "querySource": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } @@ -586,7 +586,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { const startTime = new Date().getTime(); /* __GDPR__ "galleryService:downloadVSIX" : { - "duration": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "duration": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "${include}": [ "${GalleryExtensionTelemetryData}" ] @@ -622,7 +622,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } loadCompatibleVersion(extension: IGalleryExtension): TPromise<IGalleryExtension> { - if (extension.properties.engine && this.isEngineValid(extension.properties.engine)) { + if (extension.properties.engine && isEngineValid(extension.properties.engine)) { return TPromise.wrap(extension); } @@ -738,7 +738,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { /* __GDPR__ "galleryService:requestError" : { "url" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "cdn": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "cdn": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "message": { "classification": "CallstackOrException", "purpose": "FeatureInsight" } } */ @@ -786,7 +786,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { if (!engine) { return null; } - if (this.isEngineValid(engine)) { + if (isEngineValid(engine)) { return TPromise.wrap(version); } } @@ -807,7 +807,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { .then(manifest => { const engine = manifest.engines.vscode; - if (!this.isEngineValid(engine)) { + if (!isEngineValid(engine)) { return this.getLastValidExtensionVersionReccursively(extension, versions.slice(1)); } @@ -817,11 +817,6 @@ export class ExtensionGalleryService implements IExtensionGalleryService { }); } - private isEngineValid(engine: string): boolean { - // TODO@joao: discuss with alex '*' doesn't seem to be a valid engine version - return engine === '*' || isVersionValid(pkg.version, engine); - } - private static hasExtensionByName(extensions: IGalleryExtension[], name: string): boolean { for (const extension of extensions) { if (`${extension.publisher}.${extension.name}` === name) { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 558ded104b..014cdd8236 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -5,14 +5,14 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as path from 'path'; import * as pfs from 'vs/base/node/pfs'; import * as errors from 'vs/base/common/errors'; import { assign } from 'vs/base/common/objects'; import { toDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { flatten, distinct, coalesce } from 'vs/base/common/arrays'; -import { extract, buffer } from 'vs/base/node/zip'; +import { flatten, distinct } from 'vs/base/common/arrays'; +import { extract, buffer, ExtractError } from 'vs/base/node/zip'; import { TPromise } from 'vs/base/common/winjs.base'; import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, @@ -22,21 +22,23 @@ import { IExtensionIdentifier, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { getGalleryExtensionIdFromLocal, adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { getGalleryExtensionIdFromLocal, adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getLocalExtensionId, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localizeManifest } from '../common/extensionNls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { Limiter } from 'vs/base/common/async'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Limiter, always } from 'vs/base/common/async'; +import { Event, Emitter } from 'vs/base/common/event'; import * as semver from 'semver'; import URI from 'vs/base/common/uri'; import pkg from 'vs/platform/node/package'; -import { isMacintosh } from 'vs/base/common/platform'; +import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/extensionsManifestCache'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle'; import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator'; const SystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', 'extensions')); const ERROR_SCANNING_SYS_EXTENSIONS = 'scanningSystem'; @@ -48,10 +50,9 @@ const INSTALL_ERROR_VALIDATING = 'validating'; const INSTALL_ERROR_GALLERY = 'gallery'; const INSTALL_ERROR_LOCAL = 'local'; const INSTALL_ERROR_EXTRACTING = 'extracting'; +const INSTALL_ERROR_RENAMING = 'renaming'; const INSTALL_ERROR_DELETING = 'deleting'; -const INSTALL_ERROR_READING_EXTENSION_FROM_DISK = 'readingExtension'; -const INSTALL_ERROR_SAVING_METADATA = 'savingMetadata'; -const INSTALL_ERROR_UNKNOWN = 'unknown'; +const ERROR_UNKNOWN = 'unknown'; export class ExtensionManagementError extends Error { constructor(message: string, readonly code: string) { @@ -101,6 +102,11 @@ interface InstallableExtension { metadata?: IGalleryMetadata; } +enum Operation { + Install = 1, + Update +} + export class ExtensionManagementService extends Disposable implements IExtensionManagementService { _serviceBrand: any; @@ -110,6 +116,7 @@ export class ExtensionManagementService extends Disposable implements IExtension private uninstalledFileLimiter: Limiter<void>; private reportedExtensions: TPromise<IReportedExtension[]> | undefined; private lastReportTimestamp = 0; + private readonly installationStartTime: Map<string, number> = new Map<string, number>(); private readonly installingExtensions: Map<string, TPromise<ILocalExtension>> = new Map<string, TPromise<ILocalExtension>>(); private readonly manifestCache: ExtensionsManifestCache; private readonly extensionLifecycle: ExtensionsLifecycle; @@ -128,9 +135,10 @@ export class ExtensionManagementService extends Disposable implements IExtension constructor( @IEnvironmentService environmentService: IEnvironmentService, - @IChoiceService private choiceService: IChoiceService, + @IDialogService private dialogService: IDialogService, @IExtensionGalleryService private galleryService: IExtensionGalleryService, - @ILogService private logService: ILogService + @ILogService private logService: ILogService, + @ITelemetryService private telemetryService: ITelemetryService, ) { super(); this.extensionsPath = environmentService.extensionsPath; @@ -141,13 +149,17 @@ export class ExtensionManagementService extends Disposable implements IExtension this.extensionLifecycle = this._register(new ExtensionsLifecycle(this.logService)); } - install(zipPath: string): TPromise<void> { + install(zipPath: string): TPromise<ILocalExtension> { zipPath = path.resolve(zipPath); return validateLocalExtension(zipPath) .then(manifest => { const identifier = { id: getLocalExtensionIdFromManifest(manifest) }; - return this.unsetUninstalledAndRemove(identifier.id) + // {{SQL CARBON EDIT - Remove VS Code version check}} + // if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode)) { + // return TPromise.wrapError<ILocalExtension>(new Error(nls.localize('incompatible', "Unable to install Extension '{0}' as it is not compatible with Code '{1}'.", identifier.id, pkg.version))); + // } + return this.removeIfExists(identifier.id) .then( () => this.checkOutdated(manifest) .then(validated => { @@ -175,18 +187,10 @@ export class ExtensionManagementService extends Disposable implements IExtension }); } - private unsetUninstalledAndRemove(id: string): TPromise<void> { - return this.isUninstalled(id) - .then(isUninstalled => { - if (isUninstalled) { - this.logService.trace('Removing the extension:', id); - const extensionPath = path.join(this.extensionsPath, id); - return pfs.rimraf(extensionPath) - .then(() => this.unsetUninstalled(id)) - .then(() => this.logService.info('Removed the extension:', id)); - } - return null; - }); + private removeIfExists(id: string): TPromise<void> { + return this.getInstalled(LocalExtensionType.User) + .then(installed => installed.filter(i => i.identifier.id === id)[0]) + .then(existing => existing ? this.removeExtension(existing, 'existing') : null); } private checkOutdated(manifest: IExtensionManifest): TPromise<boolean> { @@ -196,11 +200,11 @@ export class ExtensionManagementService extends Disposable implements IExtension const newer = installedExtensions.filter(local => areSameExtensions(extensionIdentifier, { id: getGalleryExtensionIdFromLocal(local) }) && semver.gt(local.manifest.version, manifest.version))[0]; if (newer) { const message = nls.localize('installingOutdatedExtension', "A newer version of this extension is already installed. Would you like to override this with the older version?"); - const options = [ + const buttons = [ nls.localize('override', "Override"), nls.localize('cancel', "Cancel") ]; - return this.choiceService.choose(Severity.Info, message, options, 1, true) + return this.dialogService.show(Severity.Info, message, buttons, { cancelId: 1 }) .then<boolean>(value => { if (value === 0) { return this.uninstall(newer, true).then(() => true); @@ -212,58 +216,65 @@ export class ExtensionManagementService extends Disposable implements IExtension }); } - private installFromZipPath(identifier: IExtensionIdentifier, zipPath: string, metadata: IGalleryMetadata, manifest: IExtensionManifest): TPromise<void> { + private installFromZipPath(identifier: IExtensionIdentifier, zipPath: string, metadata: IGalleryMetadata, manifest: IExtensionManifest): TPromise<ILocalExtension> { return this.installExtension({ zipPath, id: identifier.id, metadata }) .then(local => { if (this.galleryService.isEnabled() && local.manifest.extensionDependencies && local.manifest.extensionDependencies.length) { return this.getDependenciesToInstall(local.manifest.extensionDependencies) .then(dependenciesToInstall => this.downloadAndInstallExtensions(metadata ? dependenciesToInstall.filter(d => d.identifier.uuid !== metadata.id) : dependenciesToInstall)) .then(() => local, error => { - this.uninstallExtension(local); + this.setUninstalled(local); return TPromise.wrapError(new Error(nls.localize('errorInstallingDependencies', "Error while installing dependencies. {0}", error instanceof Error ? error.message : error))); }); } return local; }) .then( - local => this._onDidInstallExtension.fire({ identifier, zipPath, local }), - error => { this._onDidInstallExtension.fire({ identifier, zipPath, error }); return TPromise.wrapError(error); } + local => { this._onDidInstallExtension.fire({ identifier, zipPath, local }); return local; }, + error => { this._onDidInstallExtension.fire({ identifier, zipPath, error }); return TPromise.wrapError(error); } ); } - installFromGallery(extension: IGalleryExtension): TPromise<void> { + installFromGallery(extension: IGalleryExtension): TPromise<ILocalExtension> { this.onInstallExtensions([extension]); - return this.collectExtensionsToInstall(extension) - .then( - extensionsToInstall => { - if (extensionsToInstall.length > 1) { - this.onInstallExtensions(extensionsToInstall.slice(1)); - } - return this.downloadAndInstallExtensions(extensionsToInstall) - .then( - locals => this.onDidInstallExtensions(extensionsToInstall, locals, []), - errors => this.onDidInstallExtensions(extensionsToInstall, [], errors)); - }, - error => this.onDidInstallExtensions([extension], [], [error])); + return this.getInstalled(LocalExtensionType.User) + .then(installed => this.collectExtensionsToInstall(extension) + .then( + extensionsToInstall => { + if (extensionsToInstall.length > 1) { + this.onInstallExtensions(extensionsToInstall.slice(1)); + } + const operataions: Operation[] = extensionsToInstall.map(e => this.getOperation(e, installed)); + return this.downloadAndInstallExtensions(extensionsToInstall) + .then( + locals => this.onDidInstallExtensions(extensionsToInstall, locals, operataions, []) + .then(() => locals.filter(l => areSameExtensions({ id: getGalleryExtensionIdFromLocal(l), uuid: l.identifier.uuid }, extension.identifier)[0])), + errors => this.onDidInstallExtensions(extensionsToInstall, [], operataions, errors)); + }, + error => this.onDidInstallExtensions([extension], [], [this.getOperation(extension, installed)], [error]))); } - reinstall(extension: ILocalExtension): TPromise<void> { + reinstallFromGallery(extension: ILocalExtension): TPromise<ILocalExtension> { if (!this.galleryService.isEnabled()) { return TPromise.wrapError(new Error(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled"))); } return this.findGalleryExtension(extension) .then(galleryExtension => { if (galleryExtension) { - return this.uninstallExtension(extension) + return this.setUninstalled(extension) .then(() => this.removeUninstalledExtension(extension) .then( - () => this.installFromGallery(galleryExtension), - e => TPromise.wrapError(new Error(nls.localize('removeError', "Error while removing the extension: {0}. Please Quit and Start VS Code before trying again.", toErrorMessage(e)))))); + () => this.installFromGallery(galleryExtension), + e => TPromise.wrapError(new Error(nls.localize('removeError', "Error while removing the extension: {0}. Please Quit and Start VS Code before trying again.", toErrorMessage(e)))))); } - return TPromise.wrapError(new Error(nls.localize('Not Market place extension', "Only Market place Extensions can be reinstalled"))); + return TPromise.wrapError(new Error(nls.localize('Not a Marketplace extension', "Only Marketplace Extensions can be reinstalled"))); }); } + private getOperation(extensionToInstall: IGalleryExtension, installed: ILocalExtension[]): Operation { + return installed.some(i => areSameExtensions({ id: getGalleryExtensionIdFromLocal(i), uuid: i.identifier.uuid }, extensionToInstall.identifier)) ? Operation.Update : Operation.Install; + } + private collectExtensionsToInstall(extension: IGalleryExtension): TPromise<IGalleryExtension[]> { return this.galleryService.loadCompatibleVersion(extension) .then(compatible => { @@ -273,10 +284,10 @@ export class ExtensionManagementService extends Disposable implements IExtension } return this.getDependenciesToInstall(compatible.properties.dependencies) .then( - dependenciesToInstall => ([compatible, ...dependenciesToInstall.filter(d => d.identifier.uuid !== compatible.identifier.uuid)]), - error => TPromise.wrapError<IGalleryExtension[]>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); + dependenciesToInstall => ([compatible, ...dependenciesToInstall.filter(d => d.identifier.uuid !== compatible.identifier.uuid)]), + error => TPromise.wrapError<IGalleryExtension[]>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); }, - error => TPromise.wrapError<IGalleryExtension[]>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); + error => TPromise.wrapError<IGalleryExtension[]>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); } private downloadAndInstallExtensions(extensions: IGalleryExtension[]): TPromise<ILocalExtension[]> { @@ -298,8 +309,8 @@ export class ExtensionManagementService extends Disposable implements IExtension .then(extension => this.downloadInstallableExtension(extension)) .then(installableExtension => this.installExtension(installableExtension)) .then( - local => { this.installingExtensions.delete(extension.identifier.id); return local; }, - e => { this.installingExtensions.delete(extension.identifier.id); return TPromise.wrapError(e); } + local => { this.installingExtensions.delete(extension.identifier.id); return local; }, + e => { this.installingExtensions.delete(extension.identifier.id); return TPromise.wrapError(e); } ); this.installingExtensions.set(extension.identifier.id, installingExtension); @@ -316,36 +327,37 @@ export class ExtensionManagementService extends Disposable implements IExtension return this.galleryService.loadCompatibleVersion(extension) .then( - compatible => { - if (compatible) { - this.logService.trace('Started downloading extension:', extension.name); - return this.galleryService.download(extension) - .then( - zipPath => { - this.logService.info('Downloaded extension:', extension.name); - return validateLocalExtension(zipPath) - .then( - manifest => (<InstallableExtension>{ zipPath, id: getLocalExtensionIdFromManifest(manifest), metadata }), - error => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_VALIDATING)) - ); - }, - error => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_DOWNLOADING))); - } else { - return TPromise.wrapError<InstallableExtension>(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install because, the depending extension '{0}' compatible with current version '{1}' of VS Code is not found.", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE)); - } - }, - error => TPromise.wrapError<InstallableExtension>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); + compatible => { + if (compatible) { + this.logService.trace('Started downloading extension:', extension.name); + return this.galleryService.download(extension) + .then( + zipPath => { + this.logService.info('Downloaded extension:', extension.name); + return validateLocalExtension(zipPath) + .then( + manifest => (<InstallableExtension>{ zipPath, id: getLocalExtensionIdFromManifest(manifest), metadata }), + error => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_VALIDATING)) + ); + }, + error => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_DOWNLOADING))); + } else { + return TPromise.wrapError<InstallableExtension>(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install because, the depending extension '{0}' compatible with current version '{1}' of VS Code is not found.", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE)); + } + }, + error => TPromise.wrapError<InstallableExtension>(new ExtensionManagementError(this.joinErrors(error).message, INSTALL_ERROR_GALLERY))); } private onInstallExtensions(extensions: IGalleryExtension[]): void { for (const extension of extensions) { this.logService.info('Installing extension:', extension.name); + this.installationStartTime.set(extension.identifier.id, new Date().getTime()); const id = getLocalExtensionIdFromGallery(extension, extension.version); this._onInstallExtension.fire({ identifier: { id, uuid: extension.identifier.uuid }, gallery: extension }); } } - private onDidInstallExtensions(extensions: IGalleryExtension[], locals: ILocalExtension[], errors: Error[]): TPromise<any> { + private onDidInstallExtensions(extensions: IGalleryExtension[], locals: ILocalExtension[], operations: Operation[], errors: Error[]): TPromise<any> { extensions.forEach((gallery, index) => { const identifier = { id: getLocalExtensionIdFromGallery(gallery, gallery.version), uuid: gallery.identifier.uuid }; const local = locals[index]; @@ -354,10 +366,13 @@ export class ExtensionManagementService extends Disposable implements IExtension this.logService.info(`Extensions installed successfully:`, gallery.identifier.id); this._onDidInstallExtension.fire({ identifier, gallery, local }); } else { - const errorCode = error && (<ExtensionManagementError>error).code ? (<ExtensionManagementError>error).code : INSTALL_ERROR_UNKNOWN; + const errorCode = error && (<ExtensionManagementError>error).code ? (<ExtensionManagementError>error).code : ERROR_UNKNOWN; this.logService.error(`Failed to install extension:`, gallery.identifier.id, error ? error.message : errorCode); this._onDidInstallExtension.fire({ identifier, gallery, error: errorCode }); } + const startTime = this.installationStartTime.get(gallery.identifier.id); + this.reportTelemetry(operations[index] === Operation.Install ? 'extensionGallery:install' : 'extensionGallery:update', getGalleryExtensionTelemetryData(gallery), startTime ? new Date().getTime() - startTime : void 0, error); + this.installationStartTime.delete(gallery.identifier.id); }); return errors.length ? TPromise.wrapError(this.joinErrors(errors)) : TPromise.as(null); } @@ -383,18 +398,18 @@ export class ExtensionManagementService extends Disposable implements IExtension private installExtension(installableExtension: InstallableExtension): TPromise<ILocalExtension> { return this.unsetUninstalledAndGetLocal(installableExtension.id) .then( - local => { - if (local) { - return local; - } - return this.extractAndInstall(installableExtension); - }, - e => { - if (isMacintosh) { - return TPromise.wrapError<ILocalExtension>(new ExtensionManagementError(nls.localize('quitCode', "Unable to install the extension. Please Quit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED)); - } - return TPromise.wrapError<ILocalExtension>(new ExtensionManagementError(nls.localize('exitCode', "Unable to install the extension. Please Exit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED)); - }); + local => { + if (local) { + return local; + } + return this.extractAndInstall(installableExtension); + }, + e => { + if (isMacintosh) { + return TPromise.wrapError<ILocalExtension>(new ExtensionManagementError(nls.localize('quitCode', "Unable to install the extension. Please Quit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED)); + } + return TPromise.wrapError<ILocalExtension>(new ExtensionManagementError(nls.localize('exitCode', "Unable to install the extension. Please Exit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED)); + }); } private unsetUninstalledAndGetLocal(id: string): TPromise<ILocalExtension> { @@ -415,43 +430,53 @@ export class ExtensionManagementService extends Disposable implements IExtension } private extractAndInstall({ zipPath, id, metadata }: InstallableExtension): TPromise<ILocalExtension> { + const tempPath = path.join(this.extensionsPath, `.${id}`); const extensionPath = path.join(this.extensionsPath, id); - return pfs.rimraf(extensionPath) + return this.extractAndRename(id, zipPath, tempPath, extensionPath) .then(() => { - this.logService.trace(`Started extracting the extension from ${zipPath} to ${extensionPath}`); - return extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }) - .then( - () => { - this.logService.info(`Extracted extension to ${extensionPath}:`, id); - return this.completeInstall(id, extensionPath, metadata); - }, - e => TPromise.wrapError(new ExtensionManagementError(e.message, INSTALL_ERROR_EXTRACTING))) - .then(null, e => { - this.logService.info('Deleting the extracted extension', id); - return pfs.rimraf(extensionPath).then(() => TPromise.wrapError(e), () => TPromise.wrapError(e)); - }); - }, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING))); + this.logService.info('Installation completed.', id); + return this.scanExtension(id, this.extensionsPath, LocalExtensionType.User); + }) + .then(local => { + if (metadata) { + local.metadata = metadata; + return this.saveMetadataForLocalExtension(local); + } + return local; + }); } - private completeInstall(id: string, extensionPath: string, metadata: IGalleryMetadata): TPromise<ILocalExtension> { - return TPromise.join([readManifest(extensionPath), pfs.readdir(extensionPath)]) - .then(null, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_READING_EXTENSION_FROM_DISK))) - .then(([{ manifest }, children]) => { - const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; - const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)).toString() : null; - const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0]; - const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)).toString() : null; - const type = LocalExtensionType.User; - const identifier = { id, uuid: metadata ? metadata.id : null }; + private extractAndRename(id: string, zipPath: string, extractPath: string, renamePath: string): TPromise<void> { + return this.extract(id, zipPath, extractPath) + .then(() => this.rename(id, extractPath, renamePath, Date.now() + (30 * 1000) /* Retry for 30 seconds */) + .then( + () => this.logService.info('Renamed to', renamePath), + e => { + this.logService.info('Rename failed. Deleting from extracted location', extractPath); + return always(pfs.rimraf(extractPath), () => null).then(() => TPromise.wrapError(e)); + })); + } - const local: ILocalExtension = { type, identifier, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl }; + private extract(id: string, zipPath: string, extractPath: string): TPromise<void> { + this.logService.trace(`Started extracting the extension from ${zipPath} to ${extractPath}`); + return pfs.rimraf(extractPath) + .then( + () => extract(zipPath, extractPath, { sourcePath: 'extension', overwrite: true }, this.logService) + .then( + () => this.logService.info(`Extracted extension to ${extractPath}:`, id), + e => always(pfs.rimraf(extractPath), () => null) + .then(() => TPromise.wrapError(new ExtensionManagementError(e.message, e instanceof ExtractError ? e.type : INSTALL_ERROR_EXTRACTING)))), + e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING))); + } - this.logService.trace(`Updating metadata of the extension:`, id); - return this.saveMetadataForLocalExtension(local) - .then(() => { - this.logService.info(`Updated metadata of the extension:`, id); - return local; - }, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_SAVING_METADATA))); + private rename(id: string, extractPath: string, renamePath: string, retryUntil: number): TPromise<void> { + return pfs.rename(extractPath, renamePath) + .then(null, error => { + if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) { + this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`); + return this.rename(id, extractPath, renamePath, retryUntil); + } + return TPromise.wrapError(new ExtensionManagementError(error.message || nls.localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || INSTALL_ERROR_RENAMING)); }); } @@ -459,7 +484,7 @@ export class ExtensionManagementService extends Disposable implements IExtension return this.getInstalled(LocalExtensionType.User) .then(installed => TPromise.join(installed.filter(local => extensions.some(galleryExtension => local.identifier.id === getLocalExtensionIdFromGallery(galleryExtension, galleryExtension.version))) // Only check id (pub.name-version) because we want to rollback the exact version - .map(local => this.uninstallExtension(local)))) + .map(local => this.setUninstalled(local)))) .then(() => null, () => null); } @@ -529,10 +554,10 @@ export class ExtensionManagementService extends Disposable implements IExtension return this.preUninstallExtension(extension) .then(() => this.hasDependencies(extension, installed) ? this.promptForDependenciesAndUninstall(extension, installed, force) : this.promptAndUninstall(extension, installed, force)) .then(() => this.postUninstallExtension(extension), - error => { - this.postUninstallExtension(extension, INSTALL_ERROR_LOCAL); - return TPromise.wrapError(error); - }); + error => { + this.postUninstallExtension(extension, new ExtensionManagementError(error instanceof Error ? error.message : error, INSTALL_ERROR_LOCAL)); + return TPromise.wrapError(error); + }); } private hasDependencies(extension: ILocalExtension, installed: ILocalExtension[]): boolean { @@ -549,13 +574,13 @@ export class ExtensionManagementService extends Disposable implements IExtension } const message = nls.localize('uninstallDependeciesConfirmation', "Would you like to uninstall '{0}' only or its dependencies also?", extension.manifest.displayName || extension.manifest.name); - const options = [ - nls.localize('uninstallOnly', "Only"), - nls.localize('uninstallAll', "All"), + const buttons = [ + nls.localize('uninstallOnly', "Extension Only"), + nls.localize('uninstallAll', "Uninstall All"), nls.localize('cancel', "Cancel") ]; this.logService.info('Requesting for confirmation to uninstall extension with dependencies', extension.identifier.id); - return this.choiceService.choose(Severity.Info, message, options, 2, true) + return this.dialogService.show(Severity.Info, message, buttons, { cancelId: 2 }) .then<void>(value => { if (value === 0) { return this.uninstallWithDependencies(extension, [], installed); @@ -575,12 +600,12 @@ export class ExtensionManagementService extends Disposable implements IExtension } const message = nls.localize('uninstallConfirmation', "Are you sure you want to uninstall '{0}'?", extension.manifest.displayName || extension.manifest.name); - const options = [ + const buttons = [ nls.localize('ok', "OK"), nls.localize('cancel', "Cancel") ]; this.logService.info('Requesting for confirmation to uninstall extension', extension.identifier.id); - return this.choiceService.choose(Severity.Info, message, options, 1, true) + return this.dialogService.show(Severity.Info, message, buttons, { cancelId: 1 }) .then<void>(value => { if (value === 0) { return this.uninstallWithDependencies(extension, [], installed); @@ -649,10 +674,10 @@ export class ExtensionManagementService extends Disposable implements IExtension return this.preUninstallExtension(extension) .then(() => this.uninstallExtension(extension)) .then(() => this.postUninstallExtension(extension), - error => { - this.postUninstallExtension(extension, INSTALL_ERROR_LOCAL); - return TPromise.wrapError(error); - }); + error => { + this.postUninstallExtension(extension, new ExtensionManagementError(error instanceof Error ? error.message : error, INSTALL_ERROR_LOCAL)); + return TPromise.wrapError(error); + }); } private preUninstallExtension(extension: ILocalExtension): TPromise<void> { @@ -665,12 +690,14 @@ export class ExtensionManagementService extends Disposable implements IExtension } private uninstallExtension(local: ILocalExtension): TPromise<void> { - return this.setUninstalled(local.identifier.id); + // Set all versions of the extension as uninstalled + return this.scanUserExtensions(false) + .then(userExtensions => this.setUninstalled(...userExtensions.filter(u => areSameExtensions({ id: getGalleryExtensionIdFromLocal(u), uuid: u.identifier.uuid }, { id: getGalleryExtensionIdFromLocal(local), uuid: local.identifier.uuid })))); } - private async postUninstallExtension(extension: ILocalExtension, error?: string): TPromise<void> { + private async postUninstallExtension(extension: ILocalExtension, error?: Error): TPromise<void> { if (error) { - this.logService.error('Failed to uninstall extension:', extension.identifier.id, error); + this.logService.error('Failed to uninstall extension:', extension.identifier.id, error.message); } else { this.logService.info('Successfully uninstalled extension:', extension.identifier.id); // only report if extension has a mapped gallery extension. UUID identifies the gallery extension. @@ -678,7 +705,9 @@ export class ExtensionManagementService extends Disposable implements IExtension await this.galleryService.reportStatistic(extension.manifest.publisher, extension.manifest.name, extension.manifest.version, StatisticType.Uninstall); } } - this._onDidUninstallExtension.fire({ identifier: extension.identifier, error }); + this.reportTelemetry('extensionGallery:uninstall', getLocalExtensionTelemetryData(extension), void 0, error); + const errorcode = error ? error instanceof ExtensionManagementError ? error.code : ERROR_UNKNOWN : void 0; + this._onDidUninstallExtension.fire({ identifier: extension.identifier, error: errorcode }); } getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> { @@ -721,11 +750,14 @@ export class ExtensionManagementService extends Disposable implements IExtension private scanExtensions(root: string, type: LocalExtensionType): TPromise<ILocalExtension[]> { const limiter = new Limiter(10); return pfs.readdir(root) - .then(extensionsFolders => TPromise.join(extensionsFolders.map(extensionFolder => limiter.queue(() => this.scanExtension(extensionFolder, root, type))))) - .then(extensions => coalesce(extensions)); + .then(extensionsFolders => TPromise.join<ILocalExtension>(extensionsFolders.map(extensionFolder => limiter.queue(() => this.scanExtension(extensionFolder, root, type))))) + .then(extensions => extensions.filter(e => e && e.identifier)); } private scanExtension(folderName: string, root: string, type: LocalExtensionType): TPromise<ILocalExtension> { + if (type === LocalExtensionType.User && folderName.indexOf('.') === 0) { // Do not consider user exension folder starting with `.` + return TPromise.as(null); + } const extensionPath = path.join(root, folderName); return pfs.readdir(extensionPath) .then(children => readManifest(extensionPath) @@ -798,7 +830,8 @@ export class ExtensionManagementService extends Disposable implements IExtension }); } - private setUninstalled(...ids: string[]): TPromise<void> { + private setUninstalled(...extensions: ILocalExtension[]): TPromise<void> { + const ids = extensions.map(e => e.identifier.id); return this.withUninstalledExtensions(uninstalled => assign(uninstalled, ids.reduce((result, id) => { result[id] = true; return result; }, {}))); } @@ -852,6 +885,31 @@ export class ExtensionManagementService extends Disposable implements IExtension return []; }); } + + private reportTelemetry(eventName: string, extensionData: any, duration: number, error?: Error): void { + const errorcode = error ? error instanceof ExtensionManagementError ? error.code : ERROR_UNKNOWN : void 0; + /* __GDPR__ + "extensionGallery:install" : { + "success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "${include}": [ + "${GalleryExtensionTelemetryData}" + ] + } + */ + /* __GDPR__ + "extensionGallery:uninstall" : { + "success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "${include}": [ + "${GalleryExtensionTelemetryData}" + ] + } + */ + this.telemetryService.publicLog(eventName, assign(extensionData, { success: !error, duration, errorcode })); + } } export function getLocalExtensionIdFromGallery(extension: IGalleryExtension, version: string): string { @@ -860,4 +918,4 @@ export function getLocalExtensionIdFromGallery(extension: IGalleryExtension, ver export function getLocalExtensionIdFromManifest(manifest: IExtensionManifest): string { return getLocalExtensionId(getGalleryExtensionId(manifest.publisher, manifest.name), manifest.version); -} \ No newline at end of file +} diff --git a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts index e3ca60c43a..d4d5c0574c 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { IExtensionManagementService, IExtensionEnablementService, DidUninstallExtensionEvent, EnablementState, IExtensionContributions, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, IExtensionEnablementService, DidUninstallExtensionEvent, EnablementState, IExtensionContributions, ILocalExtension, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { Emitter } from 'vs/base/common/event'; @@ -98,13 +98,13 @@ suite('ExtensionEnablementService Test', () => { test('test state of globally disabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled)); }); test('test state of globally enabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled)); }); test('test disable an extension for workspace', () => { @@ -126,59 +126,59 @@ suite('ExtensionEnablementService Test', () => { test('test state of workspace disabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled)); }); test('test state of workspace and globally disabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled)); }); test('test state of workspace enabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceEnabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceEnabled)); }); test('test state of globally disabled and workspace enabled extension', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceEnabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceEnabled)); }); test('test state of an extension when disabled for workspace from workspace enabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled)); }); test('test state of an extension when disabled globally from workspace enabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled)); }); test('test state of an extension when disabled globally from workspace disabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled)); }); test('test state of an extension when enabled globally from workspace enabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled)); }); test('test state of an extension when enabled globally from workspace disabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) - .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); + .then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled)); }); test('test disable an extension for workspace and then globally', () => { @@ -223,11 +223,10 @@ suite('ExtensionEnablementService Test', () => { .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))); }); - test('test disable an extension for workspace when there is no workspace throws error', (done) => { + test('test disable an extension for workspace when there is no workspace throws error', () => { instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY); return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) - .then(() => assert.fail('should throw an error'), error => assert.ok(error)) - .then(done, done); + .then(() => assert.fail('should throw an error'), error => assert.ok(error)); }); test('test enable an extension globally', () => { @@ -237,26 +236,23 @@ suite('ExtensionEnablementService Test', () => { .then(extensions => assert.deepEqual([], extensions)); }); - test('test enable an extension globally return truthy promise', (done) => { - testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + test('test enable an extension globally return truthy promise', () => { + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) - .then(value => assert.ok(value)) - .then(done, done); + .then(value => assert.ok(value)); }); - test('test enable an extension globally triggers change event', (done) => { + test('test enable an extension globally triggers change event', () => { const target = sinon.spy(); - testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.onEnablementChanged(target)) .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))) - .then(done, done); + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))); }); - test('test enable an extension globally when already enabled return falsy promise', (done) => { - testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled) - .then(value => assert.ok(!value)) - .then(done, done); + test('test enable an extension globally when already enabled return falsy promise', () => { + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled) + .then(value => assert.ok(!value)); }); test('test enable an extension for workspace', () => { @@ -311,23 +307,37 @@ suite('ExtensionEnablementService Test', () => { test('test isEnabled return false extension is disabled globally', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) - .then(() => assert.ok(!testObject.isEnabled({ id: 'pub.a' }))); + .then(() => assert.ok(!testObject.isEnabled(aLocalExtension('pub.a')))); }); test('test isEnabled return false extension is disabled in workspace', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) - .then(() => assert.ok(!testObject.isEnabled({ id: 'pub.a' }))); + .then(() => assert.ok(!testObject.isEnabled(aLocalExtension('pub.a')))); }); test('test isEnabled return true extension is not disabled', () => { return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.setEnablement(aLocalExtension('pub.c'), EnablementState.Disabled)) - .then(() => assert.ok(testObject.isEnabled({ id: 'pub.b' }))); + .then(() => assert.ok(testObject.isEnabled(aLocalExtension('pub.b')))); }); test('test canChangeEnablement return false for language packs', () => { assert.equal(testObject.canChangeEnablement(aLocalExtension('pub.a', { localizations: [{ languageId: 'gr', translations: [{ id: 'vscode', path: 'path' }] }] })), false); }); + + test('test canChangeEnablement return false when extensions are disabled in environment', () => { + instantiationService.stub(IEnvironmentService, { disableExtensions: true } as IEnvironmentService); + testObject = new TestExtensionEnablementService(instantiationService); + assert.equal(testObject.canChangeEnablement(aLocalExtension('pub.a')), false); + }); + + test('test canChangeEnablement return true for system extensions when extensions are disabled in environment', () => { + instantiationService.stub(IEnvironmentService, { disableExtensions: true } as IEnvironmentService); + testObject = new TestExtensionEnablementService(instantiationService); + const extension = aLocalExtension('pub.a'); + extension.type = LocalExtensionType.System; + assert.equal(testObject.canChangeEnablement(extension), true); + }); }); function aLocalExtension(id: string, contributes?: IExtensionContributions): ILocalExtension { @@ -338,6 +348,7 @@ function aLocalExtension(id: string, contributes?: IExtensionContributions): ILo name, publisher, contributes - } + }, + type: LocalExtensionType.User }); } diff --git a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts index 644ba0684e..ced71ae02c 100644 --- a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import * as os from 'os'; -import extfs = require('vs/base/node/extfs'); +import * as extfs from 'vs/base/node/extfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; @@ -27,7 +27,7 @@ suite('Extension Gallery Service', () => { extfs.del(marketplaceHome, os.tmpdir(), () => { mkdirp(marketplaceHome).then(() => { done(); - }); + }, error => done(error)); }); }); @@ -35,7 +35,7 @@ suite('Extension Gallery Service', () => { extfs.del(marketplaceHome, os.tmpdir(), done); }); - test('marketplace machine id', done => { + test('marketplace machine id', () => { const args = ['--user-data-dir', marketplaceHome]; const environmentService = new EnvironmentService(parseArgs(args), process.execPath); @@ -44,8 +44,6 @@ suite('Extension Gallery Service', () => { return resolveMarketplaceHeaders(environmentService).then(headers2 => { assert.equal(headers['X-Market-User-Id'], headers2['X-Market-User-Id']); - - done(); }); }); }); diff --git a/src/vs/platform/extensions/node/extensionValidator.ts b/src/vs/platform/extensions/node/extensionValidator.ts index f2cabd473e..744ef50edf 100644 --- a/src/vs/platform/extensions/node/extensionValidator.ts +++ b/src/vs/platform/extensions/node/extensionValidator.ts @@ -5,6 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; +import pkg from 'vs/platform/node/package'; export interface IParsedVersion { hasCaret: boolean; @@ -222,11 +223,16 @@ export function isValidExtensionVersion(version: string, extensionDesc: IReduced return (extensionDesc.engines.sqlops && extensionDesc.engines.sqlops === '*') || isVersionValid(version, extensionDesc.engines.sqlops, notices); } +export function isEngineValid(engine: string): boolean { + // TODO@joao: discuss with alex '*' doesn't seem to be a valid engine version + return engine === '*' || isVersionValid(pkg.version, engine); +} + export function isVersionValid(currentVersion: string, requestedVersion: string, notices: string[] = []): boolean { let desiredVersion = normalizeVersion(parseVersion(requestedVersion)); if (!desiredVersion) { - notices.push(nls.localize('versionSyntax', "Could not parse `engines.vscode` value {0}. Please use, for example: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x, etc.", requestedVersion)); + notices.push(nls.localize('versionSyntax', "Could not parse `engines.vscode` value {0}. Please use, for example: ^1.22.0, ^1.22.x, etc.", requestedVersion)); return false; } diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 73e0dce017..afce7e031f 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -5,23 +5,31 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import URI from 'vs/base/common/uri'; -import glob = require('vs/base/common/glob'); +import * as glob from 'vs/base/common/glob'; import { isLinux } from 'vs/base/common/platform'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; -import { beginsWithIgnoreCase } from 'vs/base/common/strings'; -import { IProgress } from 'vs/platform/progress/common/progress'; +import { Event } from 'vs/base/common/event'; +import { startsWithIgnoreCase } from 'vs/base/common/strings'; import { IDisposable } from 'vs/base/common/lifecycle'; import { isEqualOrParent, isEqual } from 'vs/base/common/resources'; import { isUndefinedOrNull } from 'vs/base/common/types'; export const IFileService = createDecorator<IFileService>('fileService'); +export interface IResourceEncodings { + getWriteEncoding(resource: URI, preferredEncoding?: string): string; +} + export interface IFileService { _serviceBrand: any; + /** + * Helper to determine read/write encoding for resources. + */ + encoding: IResourceEncodings; + /** * Allows to listen for file changes. The event will fire for every file within the opened workspace * (if any) as well as all files that have been watched explicitly using the #watchFileChanges() API. @@ -33,15 +41,20 @@ export interface IFileService { */ onAfterOperation: Event<FileOperationEvent>; + /** + * An event that is fired when a file system provider is added or removed + */ + onDidChangeFileSystemProviderRegistrations: Event<IFileSystemProviderRegistrationEvent>; + /** * Registeres a file system provider for a certain scheme. */ - registerProvider?(scheme: string, provider: IFileSystemProvider): IDisposable; + registerProvider(scheme: string, provider: IFileSystemProvider): IDisposable; /** * Checks if this file service can handle the given resource. */ - canHandleResource?(resource: URI): boolean; + canHandleResource(resource: URI): boolean; /** * Resolve the properties of a file identified by the resource. @@ -120,23 +133,12 @@ export interface IFileService { */ rename(resource: URI, newName: string): TPromise<IFileStat>; - /** - * Creates a new empty file if the given path does not exist and otherwise - * will set the mtime and atime of the file to the current date. - */ - touchFile(resource: URI): TPromise<IFileStat>; - /** * Deletes the provided file. The optional useTrash parameter allows to * move the file to trash. */ del(resource: URI, useTrash?: boolean): TPromise<void>; - /** - * Imports the file to the parent identified by the resource. - */ - importFile(source: URI, targetFolder: URI): TPromise<IImportResult>; - /** * Allows to start a watcher that reports file change events on the provided resource. */ @@ -147,59 +149,83 @@ export interface IFileService { */ unwatchFileChanges(resource: URI): void; - /** - * Configures the file service with the provided options. - */ - updateOptions(options: object): void; - - /** - * Returns the preferred encoding to use for a given resource. - */ - getEncoding(resource: URI, preferredEncoding?: string): string; - /** * Frees up any resources occupied by this service. */ dispose(): void; } +export interface FileOverwriteOptions { + overwrite: boolean; +} + +export interface FileWriteOptions { + overwrite: boolean; + create: boolean; +} export enum FileType { - File = 0, - Dir = 1, - Symlink = 2 + Unknown = 0, + File = 1, + Directory = 2, + SymbolicLink = 64 } + export interface IStat { - id: number | string; - mtime: number; - size: number; type: FileType; + mtime: number; + ctime: number; + size: number; +} + +export interface IWatchOptions { + recursive: boolean; + excludes: string[]; +} + +export enum FileSystemProviderCapabilities { + FileReadWrite = 1 << 1, + FileOpenReadWriteClose = 1 << 2, + FileFolderCopy = 1 << 3, + + PathCaseSensitive = 1 << 10 } export interface IFileSystemProvider { - onDidChange?: Event<IFileChange[]>; + readonly capabilities: FileSystemProviderCapabilities; + + onDidChangeFile: Event<IFileChange[]>; + watch(resource: URI, opts: IWatchOptions): IDisposable; - // more... - // - utimes(resource: URI, mtime: number, atime: number): TPromise<IStat>; stat(resource: URI): TPromise<IStat>; - read(resource: URI, offset: number, count: number, progress: IProgress<Uint8Array>): TPromise<number>; - write(resource: URI, content: Uint8Array): TPromise<void>; - move(from: URI, to: URI): TPromise<IStat>; - mkdir(resource: URI): TPromise<IStat>; - readdir(resource: URI): TPromise<[URI, IStat][]>; - rmdir(resource: URI): TPromise<void>; - unlink(resource: URI): TPromise<void>; + mkdir(resource: URI): TPromise<void>; + readdir(resource: URI): TPromise<[string, FileType][]>; + delete(resource: URI): TPromise<void>; + + rename(from: URI, to: URI, opts: FileOverwriteOptions): TPromise<void>; + copy?(from: URI, to: URI, opts: FileOverwriteOptions): TPromise<void>; + + readFile?(resource: URI): TPromise<Uint8Array>; + writeFile?(resource: URI, content: Uint8Array, opts: FileWriteOptions): TPromise<void>; + + open?(resource: URI): TPromise<number>; + close?(fd: number): TPromise<void>; + read?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): TPromise<number>; + write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): TPromise<number>; } +export interface IFileSystemProviderRegistrationEvent { + added: boolean; + scheme: string; + provider?: IFileSystemProvider; +} export enum FileOperation { CREATE, DELETE, MOVE, - COPY, - IMPORT + COPY } export class FileOperationEvent { @@ -348,31 +374,12 @@ export function isParent(path: string, candidate: string, ignoreCase?: boolean): } if (ignoreCase) { - return beginsWithIgnoreCase(path, candidate); + return startsWithIgnoreCase(path, candidate); } return path.indexOf(candidate) === 0; } - - -export function indexOf(path: string, candidate: string, ignoreCase?: boolean): number { - if (candidate.length > path.length) { - return -1; - } - - if (path === candidate) { - return 0; - } - - if (ignoreCase) { - path = path.toLowerCase(); - candidate = candidate.toLowerCase(); - } - - return path.indexOf(candidate); -} - export interface IBaseStat { /** @@ -474,6 +481,14 @@ export interface ITextSnapshot { read(): string; } +export class StringSnapshot implements ITextSnapshot { + constructor(private _value: string) { } + read(): string { + let ret = this._value; + this._value = null; + return ret; + } +} /** * Helper method to convert a snapshot into its full string form. */ @@ -512,9 +527,10 @@ export interface IResolveContentOptions { acceptTextOnly?: boolean; /** - * The optional etag parameter allows to return a 304 (Not Modified) if the etag matches - * with the remote resource. It is the task of the caller to makes sure to handle this - * error case from the promise. + * The optional etag parameter allows to return early from resolving the resource if + * the contents on disk match the etag. This prevents accumulated reading of resources + * that have been read already with the same etag. + * It is the task of the caller to makes sure to handle this error case from the promise. */ etag?: string; @@ -568,6 +584,11 @@ export interface IUpdateContentOptions { * The etag of the file. This can be used to prevent dirty writes. */ etag?: string; + + /** + * Run mkdirp before saving. + */ + mkdirp?: boolean; } export interface IResolveFileOptions { @@ -584,11 +605,6 @@ export interface ICreateFileOptions { overwrite?: boolean; } -export interface IImportResult { - stat: IFileStat; - isNew: boolean; -} - export class FileOperationError extends Error { constructor(message: string, public fileOperationResult: FileOperationResult, public options?: IResolveContentOptions & IUpdateContentOptions & ICreateFileOptions) { super(message); diff --git a/src/vs/platform/files/test/files.test.ts b/src/vs/platform/files/test/files.test.ts index 7eb45c91ef..9b2ef061a5 100644 --- a/src/vs/platform/files/test/files.test.ts +++ b/src/vs/platform/files/test/files.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; import { join, isEqual, isEqualOrParent } from 'vs/base/common/paths'; -import { FileChangeType, FileChangesEvent, isParent, indexOf } from 'vs/platform/files/common/files'; +import { FileChangeType, FileChangesEvent, isParent } from 'vs/platform/files/common/files'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; suite('Files', () => { @@ -187,16 +187,4 @@ suite('Files', () => { assert(!isEqualOrParent('foo/bar/test.ts', 'foo/BAR/test.', true)); } }); - - test('indexOf (ignorecase)', function () { - assert.equal(indexOf('/some/path', '/some/path', true), 0); - assert.equal(indexOf('/some/path/more', '/some/path', true), 0); - - assert.equal(indexOf('c:\\some\\path', 'c:\\some\\path', true), 0); - assert.equal(indexOf('c:\\some\\path\\more', 'c:\\some\\path', true), 0); - - assert.equal(indexOf('/some/path', '/some/other/path', true), -1); - - assert.equal(indexOf('/some/path', '/some/PATH', true), 0); - }); }); \ No newline at end of file diff --git a/src/vs/platform/history/common/history.ts b/src/vs/platform/history/common/history.ts index 2494778ca2..076a2c0700 100644 --- a/src/vs/platform/history/common/history.ts +++ b/src/vs/platform/history/common/history.ts @@ -6,7 +6,7 @@ 'use strict'; import { IPath } from 'vs/platform/windows/common/windows'; -import CommonEvent from 'vs/base/common/event'; +import { Event as CommonEvent } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; diff --git a/src/vs/platform/history/electron-main/historyMainService.ts b/src/vs/platform/history/electron-main/historyMainService.ts index 3214417358..35c131295c 100644 --- a/src/vs/platform/history/electron-main/historyMainService.ts +++ b/src/vs/platform/history/electron-main/historyMainService.ts @@ -14,7 +14,7 @@ import { app } from 'electron'; import { ILogService } from 'vs/platform/log/common/log'; import { getPathLabel, getBaseLabel } from 'vs/base/common/labels'; import { IPath } from 'vs/platform/windows/common/windows'; -import CommonEvent, { Emitter } from 'vs/base/common/event'; +import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import { isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, IWorkspacesMainService, getWorkspaceLabel, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceSavedEvent } from 'vs/platform/workspaces/common/workspaces'; import { IHistoryMainService, IRecentlyOpened } from 'vs/platform/history/common/history'; diff --git a/src/vs/platform/instantiation/test/common/instantiationService.test.ts b/src/vs/platform/instantiation/test/common/instantiationService.test.ts index 6ed0ee3910..9b167bfc0a 100644 --- a/src/vs/platform/instantiation/test/common/instantiationService.test.ts +++ b/src/vs/platform/instantiation/test/common/instantiationService.test.ts @@ -5,7 +5,7 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; import { createDecorator, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -56,7 +56,7 @@ interface IDependentService { class DependentService implements IDependentService { _serviceBrand: any; - constructor( @IService1 service: IService1) { + constructor(@IService1 service: IService1) { assert.equal(service.c, 1); } @@ -65,7 +65,7 @@ class DependentService implements IDependentService { class Service1Consumer { - constructor( @IService1 service1: IService1) { + constructor(@IService1 service1: IService1) { assert.ok(service1); assert.equal(service1.c, 1); } @@ -73,7 +73,7 @@ class Service1Consumer { class Target2Dep { - constructor( @IService1 service1: IService1, @IService2 service2) { + constructor(@IService1 service1: IService1, @IService2 service2) { assert.ok(service1 instanceof Service1); assert.ok(service2 instanceof Service2); } @@ -88,12 +88,12 @@ class TargetWithStaticParam { } class TargetNotOptional { - constructor( @IService1 service1: IService1, @IService2 service2: IService2) { + constructor(@IService1 service1: IService1, @IService2 service2: IService2) { } } class TargetOptional { - constructor( @IService1 service1: IService1, @optional(IService2) service2: IService2) { + constructor(@IService1 service1: IService1, @optional(IService2) service2: IService2) { assert.ok(service1); assert.equal(service1.c, 1); assert.ok(service2 === void 0); @@ -101,14 +101,14 @@ class TargetOptional { } class DependentServiceTarget { - constructor( @IDependentService d) { + constructor(@IDependentService d) { assert.ok(d); assert.equal(d.name, 'farboo'); } } class DependentServiceTarget2 { - constructor( @IDependentService d: IDependentService, @IService1 s: IService1) { + constructor(@IDependentService d: IDependentService, @IService1 s: IService1) { assert.ok(d); assert.equal(d.name, 'farboo'); assert.ok(s); @@ -121,7 +121,7 @@ class ServiceLoop1 implements IService1 { _serviceBrand: any; c = 1; - constructor( @IService2 s: IService2) { + constructor(@IService2 s: IService2) { } } @@ -130,7 +130,7 @@ class ServiceLoop2 implements IService2 { _serviceBrand: any; d = true; - constructor( @IService1 s: IService1) { + constructor(@IService1 s: IService1) { } } diff --git a/src/vs/platform/integrity/node/integrityServiceImpl.ts b/src/vs/platform/integrity/node/integrityServiceImpl.ts index 8ffe821dcf..7a764bc7bc 100644 --- a/src/vs/platform/integrity/node/integrityServiceImpl.ts +++ b/src/vs/platform/integrity/node/integrityServiceImpl.ts @@ -14,7 +14,7 @@ import URI from 'vs/base/common/uri'; import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService } from 'vs/platform/notification/common/notification'; interface IStorageData { dontShowPrompt: boolean; @@ -62,7 +62,7 @@ export class IntegrityServiceImpl implements IIntegrityService { private _isPurePromise: Thenable<IntegrityTestResult>; constructor( - @IChoiceService private choiceService: IChoiceService, + @INotificationService private notificationService: INotificationService, @IStorageService storageService: IStorageService, @ILifecycleService private lifecycleService: ILifecycleService ) { @@ -82,26 +82,24 @@ export class IntegrityServiceImpl implements IIntegrityService { private _prompt(): void { const storedData = this._storage.get(); if (storedData && storedData.dontShowPrompt && storedData.commit === product.commit) { - // Do not prompt - return; + return; // Do not prompt } - const choices: Choice[] = [nls.localize('integrity.moreInformation', "More Information"), { label: nls.localize('integrity.dontShowAgain', "Don't Show Again") }]; - - this.choiceService.choose(Severity.Warning, nls.localize('integrity.prompt', "Your {0} installation appears to be corrupt. Please reinstall.", product.nameShort), choices).then(choice => { - switch (choice) { - case 0 /* More Information */: - const uri = URI.parse(product.checksumFailMoreInfoUrl); - window.open(uri.toString(true)); - break; - case 1 /* Do not show again */: - this._storage.set({ - dontShowPrompt: true, - commit: product.commit - }); - break; - } - }); + this.notificationService.prompt( + Severity.Warning, + nls.localize('integrity.prompt', "Your {0} installation appears to be corrupt. Please reinstall.", product.nameShort), + [ + { + label: nls.localize('integrity.moreInformation', "More Information"), + run: () => window.open(URI.parse(product.checksumFailMoreInfoUrl).toString(true)) + }, + { + label: nls.localize('integrity.dontShowAgain', "Don't Show Again"), + isSecondary: true, + run: () => this._storage.set({ dontShowPrompt: true, commit: product.commit }) + } + ] + ); } public isPure(): Thenable<IntegrityTestResult> { diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts index cbb0056e02..71393cbaaf 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -11,6 +11,15 @@ import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensio export const IIssueService = createDecorator<IIssueService>('issueService'); +export interface WindowStyles { + backgroundColor: string; + color: string; +} +export interface WindowData { + styles: WindowStyles; + zoomLevel: number; +} + export enum IssueType { Bug, PerformanceIssue, @@ -18,9 +27,7 @@ export enum IssueType { SettingsSearchIssue } -export interface IssueReporterStyles { - backgroundColor: string; - color: string; +export interface IssueReporterStyles extends WindowStyles { textLinkColor: string; inputBackground: string; inputForeground: string; @@ -35,9 +42,8 @@ export interface IssueReporterStyles { sliderActiveColor: string; } -export interface IssueReporterData { +export interface IssueReporterData extends WindowData { styles: IssueReporterStyles; - zoomLevel: number; enabledExtensions: ILocalExtension[]; issueType?: IssueType; } @@ -58,7 +64,18 @@ export interface ISettingsSearchIssueReporterData extends IssueReporterData { export interface IssueReporterFeatures { } +export interface ProcessExplorerStyles extends WindowStyles { + hoverBackground: string; + hoverForeground: string; + highlightForeground: string; +} + +export interface ProcessExplorerData extends WindowData { + styles: ProcessExplorerStyles; +} + export interface IIssueService { _serviceBrand: any; openReporter(data: IssueReporterData): TPromise<void>; + openProcessExplorer(data: ProcessExplorerData): TPromise<void>; } diff --git a/src/vs/platform/issue/common/issueIpc.ts b/src/vs/platform/issue/common/issueIpc.ts index 33e5ce7f08..0f1efc890e 100644 --- a/src/vs/platform/issue/common/issueIpc.ts +++ b/src/vs/platform/issue/common/issueIpc.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IIssueService, IssueReporterData } from './issue'; +import { IIssueService, IssueReporterData, ProcessExplorerData } from './issue'; export interface IIssueChannel extends IChannel { call(command: 'openIssueReporter', arg: IssueReporterData): TPromise<void>; @@ -23,6 +23,8 @@ export class IssueChannel implements IIssueChannel { switch (command) { case 'openIssueReporter': return this.service.openReporter(arg); + case 'openProcessExplorer': + return this.service.openProcessExplorer(arg); } return undefined; } @@ -37,4 +39,8 @@ export class IssueChannelClient implements IIssueService { openReporter(data: IssueReporterData): TPromise<void> { return this.channel.call('openIssueReporter', data); } + + openProcessExplorer(data: ProcessExplorerData): TPromise<void> { + return this.channel.call('openProcessExplorer', data); + } } \ No newline at end of file diff --git a/src/vs/platform/issue/electron-main/issueService.ts b/src/vs/platform/issue/electron-main/issueService.ts index 73e451b754..9da13811ce 100644 --- a/src/vs/platform/issue/electron-main/issueService.ts +++ b/src/vs/platform/issue/electron-main/issueService.ts @@ -9,12 +9,12 @@ import { TPromise, Promise } from 'vs/base/common/winjs.base'; import { localize } from 'vs/nls'; import * as objects from 'vs/base/common/objects'; import { parseArgs } from 'vs/platform/environment/node/argv'; -import { IIssueService, IssueReporterData, IssueReporterFeatures } from 'vs/platform/issue/common/issue'; +import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue'; import { BrowserWindow, ipcMain, screen } from 'electron'; import { ILaunchService } from 'vs/code/electron-main/launch'; import { getPerformanceInfo, PerformanceInfo, getSystemInfo, SystemInfo } from 'vs/code/electron-main/diagnostics'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { isMacintosh } from 'vs/base/common/platform'; +import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; const DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; @@ -22,13 +22,15 @@ const DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; export class IssueService implements IIssueService { _serviceBrand: any; _issueWindow: BrowserWindow; - _parentWindow: BrowserWindow; + _issueParentWindow: BrowserWindow; + _processExplorerWindow: BrowserWindow; constructor( private machineId: string, + private userEnv: IProcessEnvironment, @IEnvironmentService private environmentService: IEnvironmentService, @ILaunchService private launchService: ILaunchService, - @ILogService private logService: ILogService + @ILogService private logService: ILogService, ) { } openReporter(data: IssueReporterData): TPromise<void> { @@ -45,11 +47,11 @@ export class IssueService implements IIssueService { }); ipcMain.on('workbenchCommand', (event, arg) => { - this._parentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' }); + this._issueParentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' }); }); - this._parentWindow = BrowserWindow.getFocusedWindow(); - const position = this.getWindowPosition(); + this._issueParentWindow = BrowserWindow.getFocusedWindow(); + const position = this.getWindowPosition(this._issueParentWindow, 800, 900); this._issueWindow = new BrowserWindow({ width: position.width, height: position.height, @@ -72,7 +74,54 @@ export class IssueService implements IIssueService { return TPromise.as(null); } - private getWindowPosition() { + openProcessExplorer(data: ProcessExplorerData): TPromise<void> { + // Create as singleton + if (!this._processExplorerWindow) { + const position = this.getWindowPosition(BrowserWindow.getFocusedWindow(), 800, 300); + this._processExplorerWindow = new BrowserWindow({ + skipTaskbar: true, + resizable: true, + width: position.width, + height: position.height, + minWidth: 300, + minHeight: 200, + x: position.x, + y: position.y, + backgroundColor: data.styles.backgroundColor, + title: localize('processExplorer', "Process Explorer") + }); + + this._processExplorerWindow.setMenuBarVisibility(false); + + const windowConfiguration = { + appRoot: this.environmentService.appRoot, + nodeCachedDataDir: this.environmentService.nodeCachedDataDir, + windowId: this._processExplorerWindow.id, + userEnv: this.userEnv, + machineId: this.machineId, + data + }; + + const environment = parseArgs(process.argv); + const config = objects.assign(environment, windowConfiguration); + for (let key in config) { + if (config[key] === void 0 || config[key] === null || config[key] === '') { + delete config[key]; // only send over properties that have a true value + } + } + + this._processExplorerWindow.loadURL(`${require.toUrl('vs/code/electron-browser/processExplorer/processExplorer.html')}?config=${encodeURIComponent(JSON.stringify(config))}`); + + this._processExplorerWindow.on('close', () => this._processExplorerWindow = void 0); + } + + // Focus + this._processExplorerWindow.focus(); + + return TPromise.as(null); + } + + private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number) { // We want the new window to open on the same display that the parent is in let displayToUse: Electron.Display; const displays = screen.getAllDisplays(); @@ -92,8 +141,8 @@ export class IssueService implements IIssueService { } // if we have a last active window, use that display for the new window - if (!displayToUse && this._parentWindow) { - displayToUse = screen.getDisplayMatching(this._parentWindow.getBounds()); + if (!displayToUse && parentWindow) { + displayToUse = screen.getDisplayMatching(parentWindow.getBounds()); } // fallback to primary display or first display @@ -103,8 +152,8 @@ export class IssueService implements IIssueService { } let state = { - width: 800, - height: 900, + width: defaultWidth, + height: defaultHeight, x: undefined, y: undefined }; @@ -171,6 +220,7 @@ export class IssueService implements IIssueService { nodeCachedDataDir: this.environmentService.nodeCachedDataDir, windowId: this._issueWindow.id, machineId: this.machineId, + userEnv: this.userEnv, data, features }; diff --git a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts index bdc04b58f1..28c1e9ceb2 100644 --- a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts +++ b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts @@ -6,7 +6,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import * as platform from 'vs/platform/registry/common/platform'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export const Extensions = { JSONContribution: 'base.contributions.json' @@ -55,7 +55,7 @@ class JSONContributionRegistry implements IJSONContributionRegistry { private schemasById: { [id: string]: IJSONSchema }; - private _onDidChangeSchema: Emitter<string> = new Emitter<string>(); + private readonly _onDidChangeSchema: Emitter<string> = new Emitter<string>(); readonly onDidChangeSchema: Event<string> = this._onDidChangeSchema.event; constructor() { diff --git a/src/vs/platform/keybinding/common/abstractKeybindingService.ts b/src/vs/platform/keybinding/common/abstractKeybindingService.ts index 009b0ca3e0..f6c5210516 100644 --- a/src/vs/platform/keybinding/common/abstractKeybindingService.ts +++ b/src/vs/platform/keybinding/common/abstractKeybindingService.ts @@ -12,7 +12,7 @@ import { KeybindingResolver, IResolveResult } from 'vs/platform/keybinding/commo import { IKeybindingEvent, IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey'; import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { INotificationService } from 'vs/platform/notification/common/notification'; diff --git a/src/vs/platform/keybinding/common/keybinding.ts b/src/vs/platform/keybinding/common/keybinding.ts index 7fe0917652..38e6851180 100644 --- a/src/vs/platform/keybinding/common/keybinding.ts +++ b/src/vs/platform/keybinding/common/keybinding.ts @@ -9,7 +9,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey'; import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export interface IUserFriendlyKeybinding { key: string; diff --git a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts index 1d6afe242c..1963402cee 100644 --- a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts +++ b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts @@ -21,8 +21,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { super(); this._os = OS; if (actual === null) { - this._firstPart = null; - this._chordPart = null; + throw new Error(`Invalid USLayoutResolvedKeybinding`); } else if (actual.type === KeybindingType.Chord) { this._firstPart = actual.firstPart; this._chordPart = actual.chordPart; diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index a3b1d542c2..3e9876f583 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -139,7 +139,7 @@ suite('AbstractKeybindingService', () => { showMessageCalls.push({ sev: Severity.Error, message }); return new NoOpNotification(); }, - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): any { + prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void) { throw new Error('not implemented'); } }; diff --git a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts index e78a6835d9..87127b7f34 100644 --- a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts +++ b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts @@ -5,7 +5,7 @@ 'use strict'; import { ResolvedKeybinding, Keybinding, SimpleKeybinding } from 'vs/base/common/keyCodes'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IKeybindingService, IKeybindingEvent, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { IContextKey, IContextKeyService, IContextKeyServiceTarget, ContextKeyExpr, IContextKeyChangeEvent } from 'vs/platform/contextkey/common/contextkey'; import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver'; @@ -120,4 +120,8 @@ export class MockKeybindingService implements IKeybindingService { public softDispatch(keybinding: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult { return null; } + + dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean { + return false; + } } diff --git a/src/vs/platform/lifecycle/common/lifecycle.ts b/src/vs/platform/lifecycle/common/lifecycle.ts index 566f6324c2..82a9ca25e9 100644 --- a/src/vs/platform/lifecycle/common/lifecycle.ts +++ b/src/vs/platform/lifecycle/common/lifecycle.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILifecycleService = createDecorator<ILifecycleService>('lifecycleService'); diff --git a/src/vs/platform/lifecycle/electron-browser/lifecycleService.ts b/src/vs/platform/lifecycle/electron-browser/lifecycleService.ts index 0db2a0d77b..4027191aaf 100644 --- a/src/vs/platform/lifecycle/electron-browser/lifecycleService.ts +++ b/src/vs/platform/lifecycle/electron-browser/lifecycleService.ts @@ -9,7 +9,7 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { ILifecycleService, ShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase, handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ipcRenderer as ipc } from 'electron'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { mark } from 'vs/base/common/performance'; import { Barrier } from 'vs/base/common/async'; diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts index b08766e9ba..ed583570d2 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts @@ -9,11 +9,12 @@ import { ipcMain as ipc, app } from 'electron'; import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/common/state'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { ReadyState } from 'vs/platform/windows/common/windows'; import { handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; +import { isMacintosh, isWindows } from 'vs/base/common/platform'; export const ILifecycleService = createDecorator<ILifecycleService>('lifecycleService'); @@ -38,12 +39,24 @@ export interface ILifecycleService { */ wasRestarted: boolean; + /** + * Will be true if the program was requested to quit. + */ + isQuitRequested: boolean; + /** * Due to the way we handle lifecycle with eventing, the general app.on('before-quit') - * event cannot be used because it can be called twice on shutdown. Instead the onBeforeQuit + * event cannot be used because it can be called twice on shutdown. Instead the onBeforeShutdown * handler in this module can be used and it is only called once on a shutdown sequence. */ - onBeforeQuit: Event<void>; + onBeforeShutdown: Event<void>; + + /** + * An event that fires after the onBeforeShutdown event has been fired and after no window has + * vetoed the shutdown sequence. At this point listeners are ensured that the application will + * quit without veto. + */ + onShutdown: Event<void>; /** * We provide our own event when we close a window because the general window.on('close') @@ -65,7 +78,6 @@ export interface ILifecycleService { relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): void; quit(fromUpdate?: boolean): TPromise<boolean /* veto */>; - isQuitRequested(): boolean; kill(code?: number): void; } @@ -82,9 +94,13 @@ export class LifecycleService implements ILifecycleService { private pendingQuitPromiseComplete: TValueCallback<boolean>; private oneTimeListenerTokenGenerator: number; private _wasRestarted: boolean; + private windowCounter: number; - private _onBeforeQuit = new Emitter<void>(); - onBeforeQuit: Event<void> = this._onBeforeQuit.event; + private _onBeforeShutdown = new Emitter<void>(); + onBeforeShutdown: Event<void> = this._onBeforeShutdown.event; + + private _onShutdown = new Emitter<void>(); + onShutdown: Event<void> = this._onShutdown.event; private _onBeforeWindowClose = new Emitter<ICodeWindow>(); onBeforeWindowClose: Event<ICodeWindow> = this._onBeforeWindowClose.event; @@ -100,6 +116,7 @@ export class LifecycleService implements ILifecycleService { this.quitRequested = false; this.oneTimeListenerTokenGenerator = 0; this._wasRestarted = false; + this.windowCounter = 0; this.handleRestarted(); } @@ -116,6 +133,10 @@ export class LifecycleService implements ILifecycleService { return this._wasRestarted; } + public get isQuitRequested(): boolean { + return !!this.quitRequested; + } + public ready(): void { this.registerListeners(); } @@ -126,11 +147,23 @@ export class LifecycleService implements ILifecycleService { app.on('before-quit', e => { this.logService.trace('Lifecycle#before-quit'); - if (!this.quitRequested) { - this._onBeforeQuit.fire(); // only send this if this is the first quit request we have + if (this.quitRequested) { + this.logService.trace('Lifecycle#before-quit - returning because quit was already requested'); + return; } this.quitRequested = true; + + // Emit event to indicate that we are about to shutdown + this.logService.trace('Lifecycle#onBeforeShutdown.fire()'); + this._onBeforeShutdown.fire(); + + // macOS: can run without any window open. in that case we fire + // the onShutdown() event directly because there is no veto to be expected. + if (isMacintosh && this.windowCounter === 0) { + this.logService.trace('Lifecycle#onShutdown.fire()'); + this._onShutdown.fire(); + } }); // window-all-closed @@ -147,6 +180,9 @@ export class LifecycleService implements ILifecycleService { public registerWindow(window: ICodeWindow): void { + // track window count + this.windowCounter++; + // Window Before Closing: Main -> Renderer window.win.on('close', e => { const windowId = window.id; @@ -166,7 +202,10 @@ export class LifecycleService implements ILifecycleService { this.unload(window, UnloadReason.CLOSE).done(veto => { if (!veto) { this.windowToCloseRequest[windowId] = true; + + this.logService.trace('Lifecycle#onBeforeWindowClose.fire()'); this._onBeforeWindowClose.fire(window); + window.close(); } else { this.quitRequested = false; @@ -174,6 +213,23 @@ export class LifecycleService implements ILifecycleService { } }); }); + + // Window After Closing + window.win.on('closed', e => { + const windowId = window.id; + this.logService.trace('Lifecycle#window-closed', windowId); + + // update window count + this.windowCounter--; + + // if there are no more code windows opened, fire the onShutdown event, unless + // we are on macOS where it is perfectly fine to close the last window and + // the application continues running (unless quit was actually requested) + if (this.windowCounter === 0 && (!isMacintosh || this.isQuitRequested)) { + this.logService.trace('Lifecycle#onShutdown.fire()'); + this._onShutdown.fire(); + } + }); } public unload(window: ICodeWindow, reason: UnloadReason): TPromise<boolean /* veto */> { @@ -279,7 +335,10 @@ export class LifecycleService implements ILifecycleService { // Store as field to access it from a window cancellation this.pendingQuitPromiseComplete = c; + // The will-quit event is fired when all windows have closed without veto app.once('will-quit', () => { + this.logService.trace('Lifecycle#will-quit'); + if (this.pendingQuitPromiseComplete) { if (fromUpdate) { this.stateService.setItem(LifecycleService.QUIT_FROM_RESTART_MARKER, true); @@ -291,8 +350,13 @@ export class LifecycleService implements ILifecycleService { } }); + // Calling app.quit() will trigger the close handlers of each opened window + // and only if no window vetoed the shutdown, we will get the will-quit event + this.logService.trace('Lifecycle#quit() - calling app.quit()'); app.quit(); }); + } else { + this.logService.trace('Lifecycle#quit() - a pending quit was found'); } return this.pendingQuitPromise; @@ -325,6 +389,19 @@ export class LifecycleService implements ILifecycleService { app.once('quit', () => { if (!vetoed) { this.stateService.setItem(LifecycleService.QUIT_FROM_RESTART_MARKER, true); + + // Windows: we are about to restart and as such we need to restore the original + // current working directory we had on startup to get the exact same startup + // behaviour. As such, we briefly change back to the VSCODE_CWD and then when + // Code starts it will set it back to the installation directory again. + try { + if (isWindows) { + process.chdir(process.env['VSCODE_CWD']); + } + } catch (err) { + this.logService.error(err); + } + app.relaunch({ args }); } }); @@ -333,8 +410,4 @@ export class LifecycleService implements ILifecycleService { vetoed = veto; }); } - - public isQuitRequested(): boolean { - return !!this.quitRequested; - } } diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index f26a0020d0..9bea91171d 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -5,25 +5,26 @@ 'use strict'; import { ITree, ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree'; -import { List, IListOptions, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, IMultipleSelectionController, IOpenController } from 'vs/base/browser/ui/list/listWidget'; +import { List, IListOptions, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, IMultipleSelectionController, IOpenController, DefaultStyleController } from 'vs/base/browser/ui/list/listWidget'; import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, combinedDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { PagedList, IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; import { IDelegate, IRenderer, IListMouseEvent, IListTouchEvent } from 'vs/base/browser/ui/list/list'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; -import { attachListStyler } from 'vs/platform/theme/common/styler'; +import { attachListStyler, defaultListStyles, computeStyles } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { InputFocusedContextKey } from 'vs/platform/workbench/common/contextkeys'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { mixin } from 'vs/base/common/objects'; import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { DefaultController, IControllerOptions, OpenMode, ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults'; +import { DefaultController, IControllerOptions, OpenMode, ClickBehavior, DefaultTreestyler } from 'vs/base/parts/tree/browser/treeDefaults'; import { isUndefinedOrNull } from 'vs/base/common/types'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; +import { createStyleSheet } from 'vs/base/browser/dom'; +import { ScrollbarVisibility } from 'vs/base/common/scrollable'; export type ListWidget = List<any> | PagedList<any> | ITree; @@ -55,7 +56,7 @@ export class ListService implements IListService { return this._lastFocusedWidget; } - constructor( @IContextKeyService contextKeyService: IContextKeyService) { } + constructor(@IContextKeyService contextKeyService: IContextKeyService) { } register(widget: ListWidget, extraContextKeys?: (IContextKey<boolean>)[]): IDisposable { if (this.lists.some(l => l.widget === widget)) { @@ -73,7 +74,13 @@ export class ListService implements IListService { const result = combinedDisposable([ widget.onDidFocus(() => this._lastFocusedWidget = widget), - toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)) + toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)), + widget.onDidDispose(() => { + this.lists = this.lists.filter(l => l !== registeredList); + if (this._lastFocusedWidget === widget) { + this._lastFocusedWidget = undefined; + } + }) ]); return result; @@ -99,6 +106,7 @@ function createScopedContextKeyService(contextKeyService: IContextKeyService, wi export const multiSelectModifierSettingKey = 'workbench.list.multiSelectModifier'; export const openModeSettingKey = 'workbench.list.openMode'; +export const horizontalScrollingKey = 'workbench.tree.horizontalScrolling'; function useAltAsMultipleSelectionModifier(configurationService: IConfigurationService): boolean { return configurationService.getValue(multiSelectModifierSettingKey) === 'alt'; @@ -157,11 +165,33 @@ function handleListControllers<T>(options: IListOptions<T>, configurationService return options; } +let sharedListStyleSheet: HTMLStyleElement; +function getSharedListStyleSheet(): HTMLStyleElement { + if (!sharedListStyleSheet) { + sharedListStyleSheet = createStyleSheet(); + } + + return sharedListStyleSheet; +} + +let sharedTreeStyleSheet: HTMLStyleElement; +function getSharedTreeStyleSheet(): HTMLStyleElement { + if (!sharedTreeStyleSheet) { + sharedTreeStyleSheet = createStyleSheet(); + } + + return sharedTreeStyleSheet; +} + function handleTreeController(configuration: ITreeConfiguration, instantiationService: IInstantiationService): ITreeConfiguration { if (!configuration.controller) { configuration.controller = instantiationService.createInstance(WorkbenchTreeController, {}); } + if (!configuration.styler) { + configuration.styler = new DefaultTreestyler(getSharedTreeStyleSheet()); + } + return configuration; } @@ -184,7 +214,15 @@ export class WorkbenchList<T> extends List<T> { @IThemeService themeService: IThemeService, @IConfigurationService private configurationService: IConfigurationService ) { - super(container, delegate, renderers, mixin(handleListControllers(options, configurationService), { keyboardSupport: false, selectOnMouseDown: true } as IListOptions<T>, false)); + super(container, delegate, renderers, + { + keyboardSupport: false, + selectOnMouseDown: true, + styleController: new DefaultStyleController(getSharedListStyleSheet()), + ...computeStyles(themeService.getTheme(), defaultListStyles), + ...handleListControllers(options, configurationService) + } as IListOptions<T> + ); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService); @@ -206,10 +244,6 @@ export class WorkbenchList<T> extends List<T> { this.registerListeners(); } - public get useAltAsMultipleSelectionModifier(): boolean { - return this._useAltAsMultipleSelectionModifier; - } - private registerListeners(): void { this.disposables.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(multiSelectModifierSettingKey)) { @@ -217,6 +251,10 @@ export class WorkbenchList<T> extends List<T> { } })); } + + get useAltAsMultipleSelectionModifier(): boolean { + return this._useAltAsMultipleSelectionModifier; + } } export class WorkbenchPagedList<T> extends PagedList<T> { @@ -237,7 +275,15 @@ export class WorkbenchPagedList<T> extends PagedList<T> { @IThemeService themeService: IThemeService, @IConfigurationService private configurationService: IConfigurationService ) { - super(container, delegate, renderers, mixin(handleListControllers(options, configurationService), { keyboardSupport: false, selectOnMouseDown: true } as IListOptions<T>, false)); + super(container, delegate, renderers, + { + keyboardSupport: false, + selectOnMouseDown: true, + styleController: new DefaultStyleController(getSharedListStyleSheet()), + ...computeStyles(themeService.getTheme(), defaultListStyles), + ...handleListControllers(options, configurationService) + } as IListOptions<T> + ); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); @@ -252,10 +298,6 @@ export class WorkbenchPagedList<T> extends PagedList<T> { this.registerListeners(); } - public get useAltAsMultipleSelectionModifier(): boolean { - return this._useAltAsMultipleSelectionModifier; - } - private registerListeners(): void { this.disposables.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(multiSelectModifierSettingKey)) { @@ -264,7 +306,13 @@ export class WorkbenchPagedList<T> extends PagedList<T> { })); } + get useAltAsMultipleSelectionModifier(): boolean { + return this._useAltAsMultipleSelectionModifier; + } + dispose(): void { + super.dispose(); + this.disposables = dispose(this.disposables); } } @@ -273,7 +321,7 @@ export class WorkbenchTree extends Tree { readonly contextKeyService: IContextKeyService; - protected disposables: IDisposable[] = []; + protected disposables: IDisposable[]; private listDoubleSelection: IContextKey<boolean>; private listMultiSelection: IContextKey<boolean>; @@ -289,10 +337,20 @@ export class WorkbenchTree extends Tree { @IListService listService: IListService, @IThemeService themeService: IThemeService, @IInstantiationService instantiationService: IInstantiationService, - @IConfigurationService private configurationService: IConfigurationService + @IConfigurationService configurationService: IConfigurationService ) { - super(container, handleTreeController(configuration, instantiationService), mixin(options, { keyboardSupport: false } as ITreeOptions, false)); + const config = handleTreeController(configuration, instantiationService); + const horizontalScrollMode = configurationService.getValue(horizontalScrollingKey) ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden; + const opts = { + horizontalScrollMode, + keyboardSupport: false, + ...computeStyles(themeService.getTheme(), defaultListStyles), + ...options + }; + super(container, config, opts); + + this.disposables = []; this.contextKeyService = createScopedContextKeyService(contextKeyService, this); this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService); this.listMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService); @@ -306,36 +364,34 @@ export class WorkbenchTree extends Tree { attachListStyler(this, themeService) ); - this.registerListeners(); - } - - public get openOnSingleClick(): boolean { - return this._openOnSingleClick; - } - - public get useAltAsMultipleSelectionModifier(): boolean { - return this._useAltAsMultipleSelectionModifier; - } - - private registerListeners(): void { this.disposables.push(this.onDidChangeSelection(() => { const selection = this.getSelection(); this.listDoubleSelection.set(selection && selection.length === 2); this.listMultiSelection.set(selection && selection.length > 1); })); - this.disposables.push(this.configurationService.onDidChangeConfiguration(e => { + this.disposables.push(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(openModeSettingKey)) { - this._openOnSingleClick = useSingleClickToOpen(this.configurationService); + this._openOnSingleClick = useSingleClickToOpen(configurationService); } if (e.affectsConfiguration(multiSelectModifierSettingKey)) { - this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService); + this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService); } })); } + get openOnSingleClick(): boolean { + return this._openOnSingleClick; + } + + get useAltAsMultipleSelectionModifier(): boolean { + return this._useAltAsMultipleSelectionModifier; + } + dispose(): void { + super.dispose(); + this.disposables = dispose(this.disposables); } } @@ -399,8 +455,8 @@ export interface IResourceResultsNavigationOptions { export class TreeResourceNavigator extends Disposable { - private _openResource: Emitter<IOpenResourceOptions> = new Emitter<IOpenResourceOptions>(); - public readonly openResource: Event<IOpenResourceOptions> = this._openResource.event; + private readonly _openResource: Emitter<IOpenResourceOptions> = new Emitter<IOpenResourceOptions>(); + readonly openResource: Event<IOpenResourceOptions> = this._openResource.event; constructor(private tree: WorkbenchTree, private options?: IResourceResultsNavigationOptions) { super(); @@ -424,7 +480,8 @@ export class TreeResourceNavigator extends Disposable { const isMouseEvent = payload && payload.origin === 'mouse'; const isDoubleClick = isMouseEvent && originalEvent && originalEvent.detail === 2; - if (!isMouseEvent || this.tree.openOnSingleClick || isDoubleClick) { + const preventOpen = payload && payload.preventOpenOnFocus; + if (!preventOpen && (!isMouseEvent || this.tree.openOnSingleClick || isDoubleClick)) { this._openResource.fire({ editorOptions: { preserveFocus: true, @@ -477,7 +534,7 @@ configurationRegistry.registerConfiguration({ 'title': localize('workbenchConfigurationTitle', "Workbench"), 'type': 'object', 'properties': { - 'workbench.list.multiSelectModifier': { + [multiSelectModifierSettingKey]: { 'type': 'string', 'enum': ['ctrlCmd', 'alt'], 'enumDescriptions': [ @@ -493,7 +550,7 @@ configurationRegistry.registerConfiguration({ ] }, "The modifier to be used to add an item in trees and lists to a multi-selection with the mouse (for example in the explorer, open editors and scm view). `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on macOS. The 'Open to Side' mouse gestures - if supported - will adapt such that they do not conflict with the multiselect modifier.") }, - 'workbench.list.openMode': { + [openModeSettingKey]: { 'type': 'string', 'enum': ['singleClick', 'doubleClick'], 'enumDescriptions': [ @@ -505,6 +562,11 @@ configurationRegistry.registerConfiguration({ key: 'openModeModifier', comment: ['`singleClick` and `doubleClick` refers to a value the setting can take and should not be localized.'] }, "Controls how to open items in trees and lists using the mouse (if supported). Set to `singleClick` to open items with a single mouse click and `doubleClick` to only open via mouse double click. For parents with children in trees, this setting will control if a single click expands the parent or a double click. Note that some trees and lists might choose to ignore this setting if it is not applicable. ") + }, + [horizontalScrollingKey]: { + 'type': 'boolean', + 'default': false, + 'description': localize('horizontalScrolling setting', "Controls whether trees support horizontal scrolling in the workbench.") } } }); diff --git a/src/vs/platform/localizations/common/localizations.ts b/src/vs/platform/localizations/common/localizations.ts index 396654f794..63fec08cec 100644 --- a/src/vs/platform/localizations/common/localizations.ts +++ b/src/vs/platform/localizations/common/localizations.ts @@ -6,7 +6,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export interface ILocalization { languageId: string; @@ -20,12 +20,17 @@ export interface ITranslation { path: string; } +export enum LanguageType { + Core = 1, + Contributed +} + export const ILocalizationsService = createDecorator<ILocalizationsService>('localizationsService'); export interface ILocalizationsService { _serviceBrand: any; readonly onDidLanguagesChange: Event<void>; - getLanguageIds(): TPromise<string[]>; + getLanguageIds(type?: LanguageType): TPromise<string[]>; } export function isValidLocalization(localization: ILocalization): boolean { diff --git a/src/vs/platform/localizations/common/localizationsIpc.ts b/src/vs/platform/localizations/common/localizationsIpc.ts index 4619c31e7f..5f68f18885 100644 --- a/src/vs/platform/localizations/common/localizationsIpc.ts +++ b/src/vs/platform/localizations/common/localizationsIpc.ts @@ -7,8 +7,8 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import Event, { buffer } from 'vs/base/common/event'; -import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; +import { Event, buffer } from 'vs/base/common/event'; +import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; export interface ILocalizationsChannel extends IChannel { call(command: 'event:onDidLanguagesChange'): TPromise<void>; @@ -27,7 +27,7 @@ export class LocalizationsChannel implements ILocalizationsChannel { call(command: string, arg?: any): TPromise<any> { switch (command) { case 'event:onDidLanguagesChange': return eventToCall(this.onDidLanguagesChange); - case 'getLanguageIds': return this.service.getLanguageIds(); + case 'getLanguageIds': return this.service.getLanguageIds(arg); } return undefined; } @@ -42,7 +42,7 @@ export class LocalizationsChannelClient implements ILocalizationsService { private _onDidLanguagesChange = eventFromCall<void>(this.channel, 'event:onDidLanguagesChange'); get onDidLanguagesChange(): Event<void> { return this._onDidLanguagesChange; } - getLanguageIds(): TPromise<string[]> { - return this.channel.call('getLanguageIds'); + getLanguageIds(type?: LanguageType): TPromise<string[]> { + return this.channel.call('getLanguageIds', type); } } \ No newline at end of file diff --git a/src/vs/platform/localizations/node/localizations.ts b/src/vs/platform/localizations/node/localizations.ts index d5469b84a9..8347522ae0 100644 --- a/src/vs/platform/localizations/node/localizations.ts +++ b/src/vs/platform/localizations/node/localizations.ts @@ -13,10 +13,10 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Limiter } from 'vs/base/common/async'; import { areSameExtensions, getGalleryExtensionIdFromLocal, getIdFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ILogService } from 'vs/platform/log/common/log'; -import { isValidLocalization, ILocalizationsService } from 'vs/platform/localizations/common/localizations'; +import { isValidLocalization, ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; import product from 'vs/platform/node/product'; import { distinct, equals } from 'vs/base/common/arrays'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; interface ILanguagePack { hash: string; @@ -27,7 +27,7 @@ interface ILanguagePack { translations: { [id: string]: string }; } -const systemLanguages: string[] = ['de', 'en', 'en-US', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-CN', 'zh-TW']; +const systemLanguages: string[] = ['de', 'en', 'en-US', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-CN', 'zh-Hans', 'zh-TW', 'zh-Hant']; if (product.quality !== 'stable') { systemLanguages.push('hu'); } @@ -55,10 +55,13 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe this.extensionManagementService.getInstalled().then(installed => this.cache.update(installed)); } - getLanguageIds(): TPromise<string[]> { + getLanguageIds(type: LanguageType): TPromise<string[]> { + if (type === LanguageType.Core) { + return TPromise.as([...systemLanguages]); + } return this.cache.getLanguagePacks() .then(languagePacks => { - const languages = [...systemLanguages, ...Object.keys(languagePacks)]; + const languages = type === LanguageType.Contributed ? Object.keys(languagePacks) : [...systemLanguages, ...Object.keys(languagePacks)]; return TPromise.as(distinct(languages)); }); } diff --git a/src/vs/platform/log/common/log.ts b/src/vs/platform/log/common/log.ts index 2b390210f4..2a616e810b 100644 --- a/src/vs/platform/log/common/log.ts +++ b/src/vs/platform/log/common/log.ts @@ -8,7 +8,7 @@ import { createDecorator as createServiceDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { isWindows } from 'vs/base/common/platform'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; export const ILogService = createServiceDecorator<ILogService>('logService'); @@ -300,7 +300,6 @@ export class NullLogService implements ILogService { dispose(): void { } } - export function getLogLevel(environmentService: IEnvironmentService): LogLevel { if (environmentService.verbose) { return LogLevel.Trace; diff --git a/src/vs/platform/log/common/logIpc.ts b/src/vs/platform/log/common/logIpc.ts index 4c1c6ee0c6..66caab45cb 100644 --- a/src/vs/platform/log/common/logIpc.ts +++ b/src/vs/platform/log/common/logIpc.ts @@ -6,7 +6,7 @@ import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; import { TPromise } from 'vs/base/common/winjs.base'; import { LogLevel, ILogService, DelegatedLogService } from 'vs/platform/log/common/log'; -import Event, { buffer } from 'vs/base/common/event'; +import { Event, buffer } from 'vs/base/common/event'; export interface ILogLevelSetterChannel extends IChannel { call(command: 'event:onDidChangeLogLevel'): TPromise<LogLevel>; diff --git a/src/vs/platform/log/node/spdlogService.ts b/src/vs/platform/log/node/spdlogService.ts index effa5bdae8..514776eee2 100644 --- a/src/vs/platform/log/node/spdlogService.ts +++ b/src/vs/platform/log/node/spdlogService.ts @@ -7,13 +7,15 @@ import * as path from 'path'; import { ILogService, LogLevel, NullLogService, AbstractLogService } from 'vs/platform/log/common/log'; -import { RotatingLogger, setAsyncMode } from 'spdlog'; +import * as spdlog from 'spdlog'; export function createSpdLogService(processName: string, logLevel: LogLevel, logsFolder: string): ILogService { + // Do not crash if spdlog cannot be loaded try { - setAsyncMode(8192, 2000); + const _spdlog: typeof spdlog = require.__$__nodeRequire('spdlog'); + _spdlog.setAsyncMode(8192, 2000); const logfilePath = path.join(logsFolder, `${processName}.log`); - const logger = new RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6); + const logger = new _spdlog.RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6); logger.setLevel(0); return new SpdLogService(logger, logLevel); @@ -28,7 +30,7 @@ class SpdLogService extends AbstractLogService implements ILogService { _serviceBrand: any; constructor( - private readonly logger: RotatingLogger, + private readonly logger: spdlog.RotatingLogger, level: LogLevel = LogLevel.Error ) { super(); diff --git a/src/vs/platform/markers/common/markerService.ts b/src/vs/platform/markers/common/markerService.ts index 28aab3d51e..ab8b5e7b6c 100644 --- a/src/vs/platform/markers/common/markerService.ts +++ b/src/vs/platform/markers/common/markerService.ts @@ -9,9 +9,8 @@ import { Schemas } from 'vs/base/common/network'; import { IDisposable } from 'vs/base/common/lifecycle'; import { isEmptyObject } from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; -import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; -import Severity from 'vs/base/common/severity'; -import { IMarkerService, IMarkerData, IResourceMarker, IMarker, MarkerStatistics } from './markers'; +import { Event, Emitter, debounceEvent } from 'vs/base/common/event'; +import { IMarkerService, IMarkerData, IResourceMarker, IMarker, MarkerStatistics, MarkerSeverity } from './markers'; interface MapMap<V> { [key: string]: { [key: string]: V }; @@ -88,11 +87,11 @@ class MarkerStats implements MarkerStatistics { } for (const { severity } of this._service.read({ resource })) { - if (severity === Severity.Error) { + if (severity === MarkerSeverity.Error) { result.errors += 1; - } else if (severity === Severity.Warning) { + } else if (severity === MarkerSeverity.Warning) { result.warnings += 1; - } else if (severity === Severity.Info) { + } else if (severity === MarkerSeverity.Info) { result.infos += 1; } else { result.unknowns += 1; @@ -180,7 +179,12 @@ export class MarkerService implements IMarkerService { } private static _toMarker(owner: string, resource: URI, data: IMarkerData): IMarker { - let { code, severity, message, source, startLineNumber, startColumn, endLineNumber, endColumn } = data; + let { + code, severity, + message, source, + startLineNumber, startColumn, endLineNumber, endColumn, + relatedInformation + } = data; if (!message) { return undefined; @@ -203,7 +207,8 @@ export class MarkerService implements IMarkerService { startLineNumber, startColumn, endLineNumber, - endColumn + endColumn, + relatedInformation }; } @@ -257,9 +262,9 @@ export class MarkerService implements IMarkerService { } } - read(filter: { owner?: string; resource?: URI; take?: number; } = Object.create(null)): IMarker[] { + read(filter: { owner?: string; resource?: URI; severities?: number, take?: number; } = Object.create(null)): IMarker[] { - let { owner, resource, take } = filter; + let { owner, resource, severities, take } = filter; if (!take || take < 0) { take = -1; @@ -267,11 +272,20 @@ export class MarkerService implements IMarkerService { if (owner && resource) { // exactly one owner AND resource - const result = MapMap.get(this._byResource, resource.toString(), owner); - if (!result) { + const data = MapMap.get(this._byResource, resource.toString(), owner); + if (!data) { return []; } else { - return result.slice(0, take > 0 ? take : undefined); + const result: IMarker[] = []; + for (const marker of data) { + if (MarkerService._accept(marker, severities)) { + const newLen = result.push(marker); + if (take > 0 && newLen === take) { + break; + } + } + } + return result; } } else if (!owner && !resource) { @@ -280,10 +294,11 @@ export class MarkerService implements IMarkerService { for (const key1 in this._byResource) { for (const key2 in this._byResource[key1]) { for (const data of this._byResource[key1][key2]) { - const newLen = result.push(data); - - if (take > 0 && newLen === take) { - return result; + if (MarkerService._accept(data, severities)) { + const newLen = result.push(data); + if (take > 0 && newLen === take) { + return result; + } } } } @@ -303,10 +318,11 @@ export class MarkerService implements IMarkerService { const result: IMarker[] = []; for (const key in map) { for (const data of map[key]) { - const newLen = result.push(data); - - if (take > 0 && newLen === take) { - return result; + if (MarkerService._accept(data, severities)) { + const newLen = result.push(data); + if (take > 0 && newLen === take) { + return result; + } } } } @@ -314,6 +330,10 @@ export class MarkerService implements IMarkerService { } } + private static _accept(marker: IMarker, severities?: number): boolean { + return severities === void 0 || (severities & marker.severity) === marker.severity; + } + // --- event debounce logic private static _dedupeMap: { [uri: string]: boolean }; diff --git a/src/vs/platform/markers/common/markers.ts b/src/vs/platform/markers/common/markers.ts index b773dba006..dce636db56 100644 --- a/src/vs/platform/markers/common/markers.ts +++ b/src/vs/platform/markers/common/markers.ts @@ -5,9 +5,10 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { localize } from 'vs/nls'; +import Severity from 'vs/base/common/severity'; export interface IMarkerService { _serviceBrand: any; @@ -20,23 +21,68 @@ export interface IMarkerService { remove(owner: string, resources: URI[]): void; - read(filter?: { owner?: string; resource?: URI; take?: number; }): IMarker[]; + read(filter?: { owner?: string; resource?: URI; severities?: number, take?: number; }): IMarker[]; onMarkerChanged: Event<URI[]>; } +/** + * + */ +export interface IRelatedInformation { + resource: URI; + message: string; + startLineNumber: number; + startColumn: number; + endLineNumber: number; + endColumn: number; +} + +export enum MarkerSeverity { + Hint = 1, + Info = 2, + Warning = 4, + Error = 8, +} + +export namespace MarkerSeverity { + + export function compare(a: MarkerSeverity, b: MarkerSeverity): number { + return b - a; + } + + const _displayStrings: { [value: number]: string; } = Object.create(null); + _displayStrings[MarkerSeverity.Error] = localize('sev.error', "Error"); + _displayStrings[MarkerSeverity.Warning] = localize('sev.warning', "Warning"); + _displayStrings[MarkerSeverity.Info] = localize('sev.info', "Info"); + + export function toString(a: MarkerSeverity): string { + return _displayStrings[a] || ''; + } + + export function fromSeverity(severity: Severity): MarkerSeverity { + switch (severity) { + case Severity.Error: return MarkerSeverity.Error; + case Severity.Warning: return MarkerSeverity.Warning; + case Severity.Info: return MarkerSeverity.Info; + case Severity.Ignore: return MarkerSeverity.Hint; + } + } +} + /** * A structure defining a problem/warning/etc. */ export interface IMarkerData { code?: string; - severity: Severity; + severity: MarkerSeverity; message: string; source?: string; startLineNumber: number; startColumn: number; endLineNumber: number; endColumn: number; + relatedInformation?: IRelatedInformation[]; } export interface IResourceMarker { @@ -47,7 +93,7 @@ export interface IResourceMarker { export interface IMarker { owner: string; resource: URI; - severity: Severity; + severity: MarkerSeverity; code?: string; message: string; source?: string; @@ -55,6 +101,7 @@ export interface IMarker { startColumn: number; endLineNumber: number; endColumn: number; + relatedInformation?: IRelatedInformation[]; } export interface MarkerStatistics { @@ -79,7 +126,7 @@ export namespace IMarkerData { result.push(emptyString); } if (markerData.severity !== void 0 && markerData.severity !== null) { - result.push(Severity.toString(markerData.severity)); + result.push(MarkerSeverity.toString(markerData.severity)); } else { result.push(emptyString); } diff --git a/src/vs/platform/markers/test/common/markerService.test.ts b/src/vs/platform/markers/test/common/markerService.test.ts index 4aa6d6657f..6516c35fcf 100644 --- a/src/vs/platform/markers/test/common/markerService.test.ts +++ b/src/vs/platform/markers/test/common/markerService.test.ts @@ -5,14 +5,14 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import markerService = require('vs/platform/markers/common/markerService'); -import { IMarkerData } from 'vs/platform/markers/common/markers'; +import * as markerService from 'vs/platform/markers/common/markerService'; +import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; -function randomMarkerData(): IMarkerData { +function randomMarkerData(severity = MarkerSeverity.Error): IMarkerData { return { - severity: 1, + severity, message: Math.random().toString(16), startLineNumber: 1, startColumn: 1, @@ -29,7 +29,7 @@ suite('Marker Service', () => { service.changeAll('far', [{ resource: URI.parse('file:///c/test/file.cs'), - marker: randomMarkerData() + marker: randomMarkerData(MarkerSeverity.Error) }]); assert.equal(service.read().length, 1); @@ -40,12 +40,18 @@ suite('Marker Service', () => { service.changeAll('boo', [{ resource: URI.parse('file:///c/test/file.cs'), - marker: randomMarkerData() + marker: randomMarkerData(MarkerSeverity.Warning) }]); assert.equal(service.read().length, 2); assert.equal(service.read({ owner: 'far' }).length, 1); assert.equal(service.read({ owner: 'boo' }).length, 1); + + assert.equal(service.read({ severities: MarkerSeverity.Error }).length, 1); + assert.equal(service.read({ severities: MarkerSeverity.Warning }).length, 1); + assert.equal(service.read({ severities: MarkerSeverity.Hint }).length, 0); + assert.equal(service.read({ severities: MarkerSeverity.Error | MarkerSeverity.Warning }).length, 2); + }); diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index cf3a45e7d6..3faabca2db 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -5,13 +5,12 @@ 'use strict'; -import Severity from 'vs/base/common/severity'; +import BaseSeverity from 'vs/base/common/severity'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IDisposable } from 'vs/base/common/lifecycle'; import { IAction } from 'vs/base/common/actions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; -export import Severity = Severity; +export import Severity = BaseSeverity; export const INotificationService = createDecorator<INotificationService>('notificationService'); @@ -44,7 +43,7 @@ export interface INotification { * close automatically when invoking a secondary action. * * **Note:** If your intent is to show a message with actions to the user, consider - * the `IChoiceService` and `IConfirmationService` instead which are optimized for + * the `INotificationService.prompt()` method instead which are optimized for * this usecase and much easier to use! */ actions?: INotificationActions; @@ -150,6 +149,11 @@ export interface IPromptChoice { run: () => void; } +/** + * A service to bring up notifications and non-modal prompts. + * + * Note: use the `IDialogService` for a modal way to ask the user for input. + */ export interface INotificationService { _serviceBrand: any; @@ -159,8 +163,10 @@ export interface INotificationService { * can be used to control the notification afterwards. * * **Note:** If your intent is to show a message with actions to the user, consider - * the `IChoiceService` and `IConfirmationService` instead which are optimized for + * the `INotificationService.prompt()` method instead which are optimized for * this usecase and much easier to use! + * + * @returns a handle on the notification to e.g. hide it or update message, buttons, etc. */ notify(notification: INotification): INotificationHandle; diff --git a/src/vs/platform/notification/test/common/testNotificationService.ts b/src/vs/platform/notification/test/common/testNotificationService.ts new file mode 100644 index 0000000000..f75a7684b2 --- /dev/null +++ b/src/vs/platform/notification/test/common/testNotificationService.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice } from 'vs/platform/notification/common/notification'; + +export class TestNotificationService implements INotificationService { + + public _serviceBrand: any; + + private static readonly NO_OP: INotificationHandle = new NoOpNotification(); + + public info(message: string): INotificationHandle { + return this.notify({ severity: Severity.Info, message }); + } + + public warn(message: string): INotificationHandle { + return this.notify({ severity: Severity.Warning, message }); + } + + public error(error: string | Error): INotificationHandle { + return this.notify({ severity: Severity.Error, message: error }); + } + + public notify(notification: INotification): INotificationHandle { + return TestNotificationService.NO_OP; + } + + public prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + return TestNotificationService.NO_OP; + } +} \ No newline at end of file diff --git a/src/vs/platform/progress/common/progress.ts b/src/vs/platform/progress/common/progress.ts index 24e1f29b59..e8615006e1 100644 --- a/src/vs/platform/progress/common/progress.ts +++ b/src/vs/platform/progress/common/progress.ts @@ -66,18 +66,21 @@ export enum ProgressLocation { Explorer = 1, Scm = 3, Extensions = 5, - Window = 10 + Window = 10, + Notification = 15 } export interface IProgressOptions { location: ProgressLocation; title?: string; - tooltip?: string; + source?: string; + total?: number; + cancellable?: boolean; } export interface IProgressStep { message?: string; - percentage?: number; + increment?: number; } export const IProgressService2 = createDecorator<IProgressService2>('progressService2'); @@ -86,5 +89,5 @@ export interface IProgressService2 { _serviceBrand: any; - withProgress<P extends Thenable<R>, R=any>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => P): P; + withProgress<P extends Thenable<R>, R=any>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => P, onDidCancel?: () => void): P; } diff --git a/src/vs/platform/quickOpen/common/quickOpen.ts b/src/vs/platform/quickOpen/common/quickOpen.ts index f5d955a497..2c2115ce81 100644 --- a/src/vs/platform/quickOpen/common/quickOpen.ts +++ b/src/vs/platform/quickOpen/common/quickOpen.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import uri from 'vs/base/common/uri'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IQuickNavigateConfiguration, IAutoFocus, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -33,6 +33,7 @@ export interface IPickOpenEntry { run?: (context: IEntryRunContext) => void; action?: IAction; payload?: any; + picked?: boolean; } export interface IPickOpenItem { @@ -84,6 +85,11 @@ export interface IPickOptions { * a context key to set when this picker is active */ contextKey?: string; + + /** + * an optional flag to make this picker multi-select (honoured by extension API) + */ + canSelectMany?: boolean; } export interface IInputOptions { diff --git a/src/vs/platform/quickinput/common/quickInput.ts b/src/vs/platform/quickinput/common/quickInput.ts new file mode 100644 index 0000000000..651e204d02 --- /dev/null +++ b/src/vs/platform/quickinput/common/quickInput.ts @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IPickOptions, IPickOpenEntry, IInputOptions } from 'vs/platform/quickOpen/common/quickOpen'; +import { CancellationToken } from 'vs/base/common/cancellation'; + +export const IQuickInputService = createDecorator<IQuickInputService>('quickInputService'); + +export interface IQuickInputService { + + _serviceBrand: any; + + pick<T extends IPickOpenEntry>(picks: TPromise<T[]>, options?: IPickOptions, token?: CancellationToken): TPromise<T[]>; + input(options?: IInputOptions, token?: CancellationToken): TPromise<string>; + focus(): void; + accept(): TPromise<void>; + cancel(): TPromise<void>; +} diff --git a/src/vs/platform/registry/common/platform.ts b/src/vs/platform/registry/common/platform.ts index ee9eb30b53..6cfee5ff21 100644 --- a/src/vs/platform/registry/common/platform.ts +++ b/src/vs/platform/registry/common/platform.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Types = require('vs/base/common/types'); -import Assert = require('vs/base/common/assert'); +import * as Types from 'vs/base/common/types'; +import * as Assert from 'vs/base/common/assert'; export interface IRegistry { @@ -27,7 +27,6 @@ export interface IRegistry { * Returns the extension functions and properties defined by the specified key or null. * @param id an extension identifier */ - as(id: string): any; as<T>(id: string): T; } diff --git a/src/vs/platform/registry/test/common/platform.test.ts b/src/vs/platform/registry/test/common/platform.test.ts index ccee31a365..6a817d9965 100644 --- a/src/vs/platform/registry/test/common/platform.test.ts +++ b/src/vs/platform/registry/test/common/platform.test.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import assert = require('assert'); -import Platform = require('vs/platform/registry/common/platform'); -import Types = require('vs/base/common/types'); +import * as assert from 'assert'; +import * as Platform from 'vs/platform/registry/common/platform'; +import * as Types from 'vs/base/common/types'; suite('Platform / Registry', () => { @@ -21,8 +21,8 @@ suite('Platform / Registry', () => { Platform.Registry.add('foo', { bar: true }); assert.ok(Platform.Registry.knows('foo')); - assert.ok(Platform.Registry.as('foo').bar); - assert.equal(Platform.Registry.as('foo').bar, true); + assert.ok(Platform.Registry.as<any>('foo').bar); + assert.equal(Platform.Registry.as<any>('foo').bar, true); }); test('registry - knows, as', function () { diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts index a94868c4d9..2a88599e8a 100644 --- a/src/vs/platform/request/node/requestService.ts +++ b/src/vs/platform/request/node/requestService.ts @@ -11,7 +11,7 @@ import { IRequestOptions, IRequestContext, IRequestFunction, request } from 'vs/ import { getProxyAgent } from 'vs/base/node/proxy'; import { IRequestService, IHTTPConfiguration } from 'vs/platform/request/node/request'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ILogService } from '../../log/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; /** * This service exposes the `request` API, while using the global diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts index 45966648f9..8c96b3f014 100644 --- a/src/vs/platform/search/common/search.ts +++ b/src/vs/platform/search/common/search.ts @@ -82,11 +82,12 @@ export enum QueryType { /* __GDPR__FRAGMENT__ "IPatternInfo" : { "pattern" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "isRegExp": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "isWordMatch": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "isRegExp": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "isWordMatch": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "wordSeparators": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "isMultiline": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "isCaseSensitive": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "isMultiline": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "isCaseSensitive": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "isSmartCase": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ export interface IPatternInfo { diff --git a/src/vs/platform/state/node/stateService.ts b/src/vs/platform/state/node/stateService.ts index 03c62c39b1..d7fdcce564 100644 --- a/src/vs/platform/state/node/stateService.ts +++ b/src/vs/platform/state/node/stateService.ts @@ -92,7 +92,7 @@ export class StateService implements IStateService { private fileStorage: FileStorage; - constructor( @IEnvironmentService environmentService: IEnvironmentService, @ILogService logService: ILogService) { + constructor(@IEnvironmentService environmentService: IEnvironmentService, @ILogService logService: ILogService) { this.fileStorage = new FileStorage(path.join(environmentService.userDataPath, 'storage.json'), error => logService.error(error)); } diff --git a/src/vs/platform/state/test/node/state.test.ts b/src/vs/platform/state/test/node/state.test.ts index 833c06a550..ecdefad96c 100644 --- a/src/vs/platform/state/test/node/state.test.ts +++ b/src/vs/platform/state/test/node/state.test.ts @@ -6,11 +6,10 @@ 'use strict'; import * as assert from 'assert'; -import os = require('os'); -import path = require('path'); -import extfs = require('vs/base/node/extfs'); +import * as os from 'os'; +import * as path from 'path'; +import * as extfs from 'vs/base/node/extfs'; import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; -import { writeFileAndFlushSync, mkdirp } from 'vs/base/node/extfs'; import { FileStorage } from 'vs/platform/state/node/stateService'; suite('StateService', () => { @@ -21,9 +20,9 @@ suite('StateService', () => { extfs.del(parentDir, os.tmpdir(), done); }); - test('Basics', done => { - return mkdirp(parentDir).then(() => { - writeFileAndFlushSync(storageFile, ''); + test('Basics', () => { + return extfs.mkdirp(parentDir).then(() => { + extfs.writeFileAndFlushSync(storageFile, ''); let service = new FileStorage(storageFile, () => null); @@ -49,8 +48,6 @@ suite('StateService', () => { service.setItem('some.null.key', null); assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default'); - - done(); }); }); }); \ No newline at end of file diff --git a/src/vs/platform/storage/common/storageService.ts b/src/vs/platform/storage/common/storageService.ts index 994ffc50e4..bc4a447200 100644 --- a/src/vs/platform/storage/common/storageService.ts +++ b/src/vs/platform/storage/common/storageService.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); -import strings = require('vs/base/common/strings'); +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; +import * as strings from 'vs/base/common/strings'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import * as perf from 'vs/base/common/performance'; diff --git a/src/vs/platform/telemetry/browser/errorTelemetry.ts b/src/vs/platform/telemetry/browser/errorTelemetry.ts index 63157cc585..b59d778901 100644 --- a/src/vs/platform/telemetry/browser/errorTelemetry.ts +++ b/src/vs/platform/telemetry/browser/errorTelemetry.ts @@ -9,25 +9,40 @@ import { binarySearch } from 'vs/base/common/arrays'; import { globals } from 'vs/base/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; -import Errors = require('vs/base/common/errors'); +import * as Errors from 'vs/base/common/errors'; import { safeStringify } from 'vs/base/common/objects'; +/* __GDPR__FRAGMENT__ + "ErrorEvent" : { + "stack": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" }, + "message" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" }, + "filename" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" }, + "callstack": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "msg" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "file" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "line": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "column": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "uncaught_error_name": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "uncaught_error_msg": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "count": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true } + } + */ interface ErrorEvent { - stack: string; - message?: string; - filename?: string; + callstack: string; + msg?: string; + file?: string; line?: number; column?: number; - error?: { name: string; message: string; }; - + uncaught_error_name?: string; + uncaught_error_msg?: string; count?: number; } namespace ErrorEvent { export function compare(a: ErrorEvent, b: ErrorEvent) { - if (a.stack < b.stack) { + if (a.callstack < b.callstack) { return -1; - } else if (a.stack > b.stack) { + } else if (a.callstack > b.callstack) { return 1; } return 0; @@ -89,32 +104,35 @@ export default class ErrorTelemetry { } // work around behavior in workerServer.ts that breaks up Error.stack - let stack = Array.isArray(err.stack) ? err.stack.join('\n') : err.stack; - let message = err.message ? err.message : safeStringify(err); + let callstack = Array.isArray(err.stack) ? err.stack.join('\n') : err.stack; + let msg = err.message ? err.message : safeStringify(err); // errors without a stack are not useful telemetry - if (!stack) { + if (!callstack) { return; } - this._enqueue({ message, stack }); + this._enqueue({ msg, callstack }); } - private _onUncaughtError(message: string, filename: string, line: number, column?: number, err?: any): void { + private _onUncaughtError(msg: string, file: string, line: number, column?: number, err?: any): void { let data: ErrorEvent = { - stack: message, - message, - filename, + callstack: msg, + msg, + file, line, column }; if (err) { let { name, message, stack } = err; - data.error = { name, message }; + data.uncaught_error_name = name; + if (message) { + data.uncaught_error_msg = message; + } if (stack) { - data.stack = Array.isArray(err.stack) + data.callstack = Array.isArray(err.stack) ? err.stack = err.stack.join('\n') : err.stack; } @@ -145,16 +163,10 @@ export default class ErrorTelemetry { for (let error of this._buffer) { /* __GDPR__ "UnhandledError" : { - "message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "name": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "stack": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "id": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "line": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "column": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" } + "${include}": [ "${ErrorEvent}" ] } */ - // __GDPR__TODO__ what's the complete set of properties? - this._telemetryService.publicLog('UnhandledError', error); + this._telemetryService.publicLog('UnhandledError', error, true); } this._buffer.length = 0; } diff --git a/src/vs/platform/telemetry/common/experiments.ts b/src/vs/platform/telemetry/common/experiments.ts index 505c8f7e0c..e5c414a65b 100644 --- a/src/vs/platform/telemetry/common/experiments.ts +++ b/src/vs/platform/telemetry/common/experiments.ts @@ -11,7 +11,6 @@ import { deepClone } from 'vs/base/common/objects'; /* __GDPR__FRAGMENT__ "IExperiments" : { - "deployToAzureQuickLink" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ export interface IExperiments { diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index d1742ac8ea..dc399e07e2 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -29,7 +29,7 @@ export interface ITelemetryService { * Sends a telemetry event that has been privacy approved. * Do not call this unless you have been given approval. */ - publicLog(eventName: string, data?: ITelemetryData): TPromise<void>; + publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): TPromise<void>; getTelemetryInfo(): TPromise<ITelemetryInfo>; diff --git a/src/vs/platform/telemetry/common/telemetryService.ts b/src/vs/platform/telemetry/common/telemetryService.ts index 1edc80d563..89eac88d42 100644 --- a/src/vs/platform/telemetry/common/telemetryService.ts +++ b/src/vs/platform/telemetry/common/telemetryService.ts @@ -37,7 +37,7 @@ export class TelemetryService implements ITelemetryService { private _userOptIn: boolean; private _disposables: IDisposable[] = []; - private _cleanupPatterns: [RegExp, string][] = []; + private _cleanupPatterns: RegExp[] = []; constructor( config: ITelemetryServiceConfig, @@ -48,18 +48,11 @@ export class TelemetryService implements ITelemetryService { this._piiPaths = config.piiPaths || []; this._userOptIn = typeof config.userOptIn === 'undefined' ? true : config.userOptIn; - // static cleanup patterns for: - // #1 `file:///DANGEROUS/PATH/resources/app/Useful/Information` - // #2 // Any other file path that doesn't match the approved form above should be cleaned. - // #3 "Error: ENOENT; no such file or directory" is often followed with PII, clean it - this._cleanupPatterns.push( - [/file:\/\/\/.*?\/resources\/app\//gi, ''], - [/file:\/\/\/.*/gi, ''], - [/ENOENT: no such file or directory.*?\'([^\']+)\'/gi, 'ENOENT: no such file or directory'] - ); + // static cleanup pattern for: `file:///DANGEROUS/PATH/resources/app/Useful/Information` + this._cleanupPatterns = [/file:\/\/\/.*?\/resources\/app\//gi]; for (let piiPath of this._piiPaths) { - this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(piiPath), 'gi'), '']); + this._cleanupPatterns.push(new RegExp(escapeRegExpCharacters(piiPath), 'gi')); } if (this._configurationService) { @@ -67,7 +60,7 @@ export class TelemetryService implements ITelemetryService { this._configurationService.onDidChangeConfiguration(this._updateUserOptIn, this, this._disposables); /* __GDPR__ "optInStatus" : { - "optIn" : { "classification": "SystemMetaData", "purpose": "BusinessInsight" } + "optIn" : { "classification": "SystemMetaData", "purpose": "BusinessInsight", "isMeasurement": true } } */ this.publicLog('optInStatus', { optIn: this._userOptIn }); @@ -98,7 +91,7 @@ export class TelemetryService implements ITelemetryService { this._disposables = dispose(this._disposables); } - publicLog(eventName: string, data?: ITelemetryData): TPromise<any> { + publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): TPromise<any> { // don't send events when the user is optout if (!this._userOptIn) { return TPromise.as(undefined); @@ -112,7 +105,7 @@ export class TelemetryService implements ITelemetryService { // (last) remove all PII from data data = cloneAndChange(data, value => { if (typeof value === 'string') { - return this._cleanupInfo(value); + return this._cleanupInfo(value, anonymizeFilePaths); } return undefined; }); @@ -125,15 +118,41 @@ export class TelemetryService implements ITelemetryService { }); } - private _cleanupInfo(stack: string): string { + private _cleanupInfo(stack: string, anonymizeFilePaths?: boolean): string { + let updatedStack = stack; - // sanitize with configured cleanup patterns - for (let tuple of this._cleanupPatterns) { - let [regexp, replaceValue] = tuple; - stack = stack.replace(regexp, replaceValue); + if (anonymizeFilePaths) { + const cleanUpIndexes: [number, number][] = []; + for (let regexp of this._cleanupPatterns) { + while (true) { + const result = regexp.exec(stack); + if (!result) { + break; + } + cleanUpIndexes.push([result.index, regexp.lastIndex]); + } + } + + const nodeModulesRegex = /^[\\\/]?(node_modules|node_modules\.asar)[\\\/]/; + const fileRegex = /(file:\/\/)?([a-zA-Z]:(\\\\|\\|\/)|(\\\\|\\|\/))?([\w-\._]+(\\\\|\\|\/))+[\w-\._]*/g; + + while (true) { + const result = fileRegex.exec(stack); + if (!result) { + break; + } + // Anoynimize user file paths that do not need to be retained or cleaned up. + if (!nodeModulesRegex.test(result[0]) && cleanUpIndexes.every(([x, y]) => result.index < x || result.index >= y)) { + updatedStack = updatedStack.slice(0, result.index) + result[0].replace(/./g, 'a') + updatedStack.slice(fileRegex.lastIndex); + } + } } - return stack; + // sanitize with configured cleanup patterns + for (let regexp of this._cleanupPatterns) { + updatedStack = updatedStack.replace(regexp, ''); + } + return updatedStack; } } diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 21899d45af..de5a6bc37d 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { guessMimeTypes } from 'vs/base/common/mime'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import URI from 'vs/base/common/uri'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/common/keybinding'; @@ -42,7 +42,7 @@ export const NullAppender: ITelemetryAppender = { log: () => null }; "URIDescriptor" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "path": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ export interface URIDescriptor { diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index 97eddf9066..2ea30a30bf 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -29,13 +29,11 @@ export function resolveCommonProperties(commit: string, version: string, machine result['version'] = version; // __GDPR__COMMON__ "common.platformVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } result['common.platformVersion'] = (os.release() || '').replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, '$1$2$3'); - // __GDPR__COMMON__ "common.osVersion" : { "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" } - result['common.osVersion'] = result['common.platformVersion']; // TODO: Drop this after the move to Nova // __GDPR__COMMON__ "common.platform" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } result['common.platform'] = Platform.Platform[Platform.platform]; - // __GDPR__COMMON__ "common.nodePlatform" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.nodePlatform" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } result['common.nodePlatform'] = process.platform; - // __GDPR__COMMON__ "common.nodeArch" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.nodeArch" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } result['common.nodeArch'] = process.arch; // {{SQL CARBON EDIT}} @@ -50,12 +48,12 @@ export function resolveCommonProperties(commit: string, version: string, machine get: () => new Date(), enumerable: true }, - // __GDPR__COMMON__ "common.timesincesessionstart" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.timesincesessionstart" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } 'common.timesincesessionstart': { get: () => Date.now() - startTime, enumerable: true }, - // __GDPR__COMMON__ "common.sequence" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.sequence" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } 'common.sequence': { get: () => seq++, enumerable: true diff --git a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts index 9416b091c8..771651e7a4 100644 --- a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts +++ b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts @@ -14,9 +14,9 @@ import * as Utils from 'sql/common/telemetryUtilities'; export function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string, version: string, machineId: string, installSourcePath: string): TPromise<{ [name: string]: string }> { return resolveCommonProperties(commit, version, machineId, installSourcePath).then(result => { - // __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } result['common.version.shell'] = process.versions && (<any>process).versions['electron']; - // __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } result['common.version.renderer'] = process.versions && (<any>process).versions['chrome']; // {{SQL CARBON EDIT}} result['common.application.name'] = product.nameLong; diff --git a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts index d7d0c4ff2e..061b65fa6d 100644 --- a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts @@ -8,13 +8,13 @@ import * as assert from 'assert'; import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; -import { TPromise } from 'vs/base/common/winjs.base'; import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; import { del } from 'vs/base/node/extfs'; import { mkdirp } from 'vs/base/node/pfs'; +import { timeout } from 'vs/base/common/async'; suite('Telemetry - common properties', function () { const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'telemetryservice'); @@ -97,7 +97,7 @@ suite('Telemetry - common properties', function () { assert.ok(value1 !== value2, 'timestamp'); value1 = props['common.timesincesessionstart']; - return TPromise.timeout(10).then(_ => { + return timeout(10).then(_ => { value2 = props['common.timesincesessionstart']; assert.ok(value1 !== value2, 'timesincesessionstart'); }); diff --git a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts index a04e40776a..ce05e7e967 100644 --- a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; import { NullAppender, ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils'; -import Errors = require('vs/base/common/errors'); +import * as Errors from 'vs/base/common/errors'; import * as sinon from 'sinon'; import { getConfigurationValue } from 'vs/platform/configuration/common/configuration'; @@ -50,6 +50,10 @@ class ErrorTestingSettings { public noSuchFilePrefix: string; public noSuchFileMessage: string; public stack: string[]; + public randomUserFile: string = 'a/path/that/doe_snt/con-tain/code/names.js'; + public anonymizedRandomUserFile: string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + public nodeModulePathToRetain: string = 'node_modules/path/that/shouldbe/retained/names.js:14:15854'; + public nodeModuleAsarPathToRetain: string = 'node_modules.asar/path/that/shouldbe/retained/names.js:14:12354'; constructor() { this.personalInfo = 'DANGEROUS/PATH'; @@ -64,20 +68,20 @@ class ErrorTestingSettings { this.noSuchFilePrefix = 'ENOENT: no such file or directory'; this.noSuchFileMessage = this.noSuchFilePrefix + ' \'' + this.personalInfo + '\''; - this.stack = ['at e._modelEvents (a/path/that/doesnt/contain/code/names.js:11:7309)', - ' at t.AllWorkers (a/path/that/doesnt/contain/code/names.js:6:8844)', - ' at e.(anonymous function) [as _modelEvents] (a/path/that/doesnt/contain/code/names.js:5:29552)', - ' at Function.<anonymous> (a/path/that/doesnt/contain/code/names.js:6:8272)', - ' at e.dispatch (a/path/that/doesnt/contain/code/names.js:5:26931)', - ' at e.request (a/path/that/doesnt/contain/code/names.js:14:1745)', - ' at t._handleMessage (another/path/that/doesnt/contain/code/names.js:14:17447)', - ' at t._onmessage (another/path/that/doesnt/contain/code/names.js:14:16976)', - ' at t.onmessage (another/path/that/doesnt/contain/code/names.js:14:15854)', - ' at DedicatedWorkerGlobalScope.self.onmessage', - this.dangerousPathWithImportantInfo, - this.dangerousPathWithoutImportantInfo, - this.missingModelMessage, - this.noSuchFileMessage]; + this.stack = [`at e._modelEvents (${this.randomUserFile}:11:7309)`, + ` at t.AllWorkers (${this.randomUserFile}:6:8844)`, + ` at e.(anonymous function) [as _modelEvents] (${this.randomUserFile}:5:29552)`, + ` at Function.<anonymous> (${this.randomUserFile}:6:8272)`, + ` at e.dispatch (${this.randomUserFile}:5:26931)`, + ` at e.request (/${this.nodeModuleAsarPathToRetain})`, + ` at t._handleMessage (${this.nodeModuleAsarPathToRetain})`, + ` at t._onmessage (/${this.nodeModulePathToRetain})`, + ` at t.onmessage (${this.nodeModulePathToRetain})`, + ` at DedicatedWorkerGlobalScope.self.onmessage`, + this.dangerousPathWithImportantInfo, + this.dangerousPathWithoutImportantInfo, + this.missingModelMessage, + this.noSuchFileMessage]; } } @@ -224,7 +228,7 @@ suite('TelemetryService', () => { this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); assert.equal(testAppender.getEventsCount(), 1); assert.equal(testAppender.events[0].eventName, 'UnhandledError'); - assert.equal(testAppender.events[0].data.message, 'This is a test.'); + assert.equal(testAppender.events[0].data.msg, 'This is a test.'); errorTelemetry.dispose(); service.dispose(); @@ -254,7 +258,7 @@ suite('TelemetryService', () => { // // assert.equal(testAppender.getEventsCount(), 1); // assert.equal(testAppender.events[0].eventName, 'UnhandledError'); - // assert.equal(testAppender.events[0].data.message, 'This should get logged'); + // assert.equal(testAppender.events[0].data.msg, 'This should get logged'); // // service.dispose(); // } finally { @@ -279,11 +283,33 @@ suite('TelemetryService', () => { assert.equal(testAppender.getEventsCount(), 1); assert.equal(testAppender.events[0].eventName, 'UnhandledError'); - assert.equal(testAppender.events[0].data.message, 'Error Message'); - assert.equal(testAppender.events[0].data.filename, 'file.js'); + assert.equal(testAppender.events[0].data.msg, 'Error Message'); + assert.equal(testAppender.events[0].data.file, 'file.js'); assert.equal(testAppender.events[0].data.line, 2); assert.equal(testAppender.events[0].data.column, 42); - assert.equal(testAppender.events[0].data.error.message, 'test'); + assert.equal(testAppender.events[0].data.uncaught_error_msg, 'test'); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test('Error Telemetry removes PII from filename with spaces', sinon.test(function (this: any) { + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: testAppender }, undefined); + const errorTelemetry = new ErrorTelemetry(service); + + let personInfoWithSpaces = settings.personalInfo.slice(0, 2) + ' ' + settings.personalInfo.slice(2); + let dangerousFilenameError: any = new Error('dangerousFilename'); + dangerousFilenameError.stack = settings.stack; + (<any>window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces) + '/test.js', 2, 42, dangerousFilenameError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + + assert.equal(errorStub.callCount, 1); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces)), -1); + assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); errorTelemetry.dispose(); service.dispose(); @@ -303,7 +329,7 @@ suite('TelemetryService', () => { this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); assert.equal(errorStub.callCount, 1); - assert.equal(testAppender.events[0].data.filename.indexOf(settings.dangerousPathWithImportantInfo), -1); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); dangerousFilenameError = new Error('dangerousFilename'); dangerousFilenameError.stack = settings.stack; @@ -311,8 +337,8 @@ suite('TelemetryService', () => { this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); assert.equal(errorStub.callCount, 2); - assert.equal(testAppender.events[0].data.filename.indexOf(settings.dangerousPathWithImportantInfo), -1); - assert.equal(testAppender.events[0].data.filename, settings.importantInfo + '/test.js'); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); + assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); errorTelemetry.dispose(); service.dispose(); @@ -332,13 +358,13 @@ suite('TelemetryService', () => { Errors.onUnexpectedError(dangerousPathWithoutImportantInfoError); this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -363,12 +389,12 @@ suite('TelemetryService', () => { assert.equal(errorStub.callCount, 1); // Test that no file information remains, esp. personal info - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -392,14 +418,14 @@ suite('TelemetryService', () => { Errors.onUnexpectedError(dangerousPathWithImportantInfoError); this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -424,19 +450,75 @@ suite('TelemetryService', () => { assert.equal(errorStub.callCount, 1); // Test that important information remains but personal info does not - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); })); + test('Unexpected Error Telemetry removes PII but preserves Code file path with node modules', sinon.test(function (this: any) { + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: testAppender }, undefined); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); + dangerousPathWithImportantInfoError.stack = settings.stack; + + + Errors.onUnexpectedError(dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); + + errorTelemetry.dispose(); + service.dispose(); + } + finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(function (this: any) { + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: testAppender }, undefined); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); + dangerousPathWithImportantInfoError.stack = settings.stack; + (<any>window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + + assert.equal(errorStub.callCount, 1); + + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test('Unexpected Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(function (this: any) { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); @@ -455,14 +537,14 @@ suite('TelemetryService', () => { Errors.onUnexpectedError(dangerousPathWithImportantInfoError); this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -487,14 +569,14 @@ suite('TelemetryService', () => { assert.equal(errorStub.callCount, 1); // Test that important information remains but personal info does not - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.importantInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -519,14 +601,14 @@ suite('TelemetryService', () => { Errors.onUnexpectedError(missingModelError); this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.missingModelPrefix), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.missingModelPrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -551,14 +633,14 @@ suite('TelemetryService', () => { assert.equal(errorStub.callCount, 1); // Test that no file information remains, but this particular // error message does (Received model events for missing model) - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.missingModelPrefix), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.missingModelPrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -583,14 +665,14 @@ suite('TelemetryService', () => { Errors.onUnexpectedError(noSuchFileError); this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.noSuchFilePrefix), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.noSuchFilePrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); @@ -620,14 +702,14 @@ suite('TelemetryService', () => { // Test that no file information remains, but this particular // error message does (ENOENT: no such file or directory) Errors.onUnexpectedError(noSuchFileError); - assert.notEqual(testAppender.events[0].data.message.indexOf(settings.noSuchFilePrefix), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.message.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.noSuchFilePrefix), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.personalInfo), -1); - assert.equal(testAppender.events[0].data.stack.indexOf(settings.filePrefix), -1); - assert.notEqual(testAppender.events[0].data.stack.indexOf(settings.stack[4]), -1); - assert.equal(testAppender.events[0].data.stack.split('\n').length, settings.stack.length); + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); errorTelemetry.dispose(); service.dispose(); diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index 10f8fddd61..085640b4e8 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import platform = require('vs/platform/registry/common/platform'); +import * as platform from 'vs/platform/registry/common/platform'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Color, RGBA } from 'vs/base/common/color'; import { ITheme } from 'vs/platform/theme/common/themeService'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; // ------ API types @@ -86,10 +86,14 @@ class ColorRegistry implements IColorRegistry { this.colorsById = {}; } - public registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency = false): ColorIdentifier { + public registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency = false, deprecationMessage?: string): ColorIdentifier { let colorContribution = { id, description, defaults, needsTransparency }; this.colorsById[id] = colorContribution; - this.colorSchema.properties[id] = { type: 'string', description, format: 'color-hex', default: '#ff0000' }; + let propertySchema: IJSONSchema = { type: 'string', description, format: 'color-hex', default: '#ff0000' }; + if (deprecationMessage) { + propertySchema.deprecationMessage = deprecationMessage; + } + this.colorSchema.properties[id] = propertySchema; this.colorReferenceSchema.enum.push(id); this.colorReferenceSchema.enumDescriptions.push(description); return id; @@ -134,8 +138,8 @@ class ColorRegistry implements IColorRegistry { const colorRegistry = new ColorRegistry(); platform.Registry.add(Extensions.ColorContribution, colorRegistry); -export function registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency?: boolean): ColorIdentifier { - return colorRegistry.registerColor(id, defaults, description, needsTransparency); +export function registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency?: boolean, deprecationMessage?: string): ColorIdentifier { + return colorRegistry.registerColor(id, defaults, description, needsTransparency, deprecationMessage); } export function getColorRegistry(): IColorRegistry { @@ -178,7 +182,7 @@ export const inputPlaceholderForeground = registerColor('input.placeholderForegr export const inputValidationInfoBackground = registerColor('inputValidation.infoBackground', { dark: '#063B49', light: '#D6ECF2', hc: Color.black }, nls.localize('inputValidationInfoBackground', "Input validation background color for information severity.")); export const inputValidationInfoBorder = registerColor('inputValidation.infoBorder', { dark: '#007acc', light: '#007acc', hc: contrastBorder }, nls.localize('inputValidationInfoBorder', "Input validation border color for information severity.")); -export const inputValidationWarningBackground = registerColor('inputValidation.warningBackground', { dark: '#352A05', light: '#F6F5D2', hc: Color.black }, nls.localize('inputValidationWarningBackground', "Input validation background color for information warning.")); +export const inputValidationWarningBackground = registerColor('inputValidation.warningBackground', { dark: '#352A05', light: '#F6F5D2', hc: Color.black }, nls.localize('inputValidationWarningBackground', "Input validation background color for warning severity.")); export const inputValidationWarningBorder = registerColor('inputValidation.warningBorder', { dark: '#B89500', light: '#B89500', hc: contrastBorder }, nls.localize('inputValidationWarningBorder', "Input validation border color for warning severity.")); export const inputValidationErrorBackground = registerColor('inputValidation.errorBackground', { dark: '#5A1D1D', light: '#F2DEDE', hc: Color.black }, nls.localize('inputValidationErrorBackground', "Input validation background color for error severity.")); export const inputValidationErrorBorder = registerColor('inputValidation.errorBorder', { dark: '#BE1100', light: '#BE1100', hc: contrastBorder }, nls.localize('inputValidationErrorBorder', "Input validation border color for error severity.")); @@ -195,7 +199,6 @@ export const listActiveSelectionForeground = registerColor('list.activeSelection export const listInactiveSelectionBackground = registerColor('list.inactiveSelectionBackground', { dark: '#3F3F46', light: '#CCCEDB', hc: null }, nls.localize('listInactiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); export const listInactiveSelectionForeground = registerColor('list.inactiveSelectionForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); export const listInactiveFocusBackground = registerColor('list.inactiveFocusBackground', { dark: '#313135', light: '#d8dae6', hc: null }, nls.localize('listInactiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); -export const listInactiveFocusForeground = registerColor('list.inactiveFocusForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")); export const listHoverBackground = registerColor('list.hoverBackground', { dark: '#2A2D2E', light: '#F0F0F0', hc: null }, nls.localize('listHoverBackground', "List/Tree background when hovering over items using the mouse.")); export const listHoverForeground = registerColor('list.hoverForeground', { dark: null, light: null, hc: null }, nls.localize('listHoverForeground', "List/Tree foreground when hovering over items using the mouse.")); export const listDropBackground = registerColor('list.dropBackground', { dark: listFocusBackground, light: listFocusBackground, hc: null }, nls.localize('listDropBackground', "List/Tree drag and drop background when moving items around using the mouse.")); @@ -253,10 +256,10 @@ export const editorSelectionHighlightBorder = registerColor('editor.selectionHig */ export const editorFindMatch = registerColor('editor.findMatchBackground', { light: '#A8AC94', dark: '#515C6A', hc: null }, nls.localize('editorFindMatch', "Color of the current search match.")); export const editorFindMatchHighlight = registerColor('editor.findMatchHighlightBackground', { light: '#EA5C0055', dark: '#EA5C0055', hc: null }, nls.localize('findMatchHighlight', "Color of the other search matches. The color must not be opaque to not hide underlying decorations."), true); -export const editorFindRangeHighlight = registerColor('editor.findRangeHighlightBackground', { dark: '#3a3d4166', light: '#b4b4b44d', hc: null }, nls.localize('findRangeHighlight', "Color the range limiting the search. The color must not be opaque to not hide underlying decorations."), true); +export const editorFindRangeHighlight = registerColor('editor.findRangeHighlightBackground', { dark: '#3a3d4166', light: '#b4b4b44d', hc: null }, nls.localize('findRangeHighlight', "Color of the range limiting the search. The color must not be opaque to not hide underlying decorations."), true); export const editorFindMatchBorder = registerColor('editor.findMatchBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('editorFindMatchBorder', "Border color of the current search match.")); export const editorFindMatchHighlightBorder = registerColor('editor.findMatchHighlightBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('findMatchHighlightBorder', "Border color of the other search matches.")); -export const editorFindRangeHighlightBorder = registerColor('editor.findRangeHighlightBorder', { dark: null, light: null, hc: transparent(activeContrastBorder, 0.4) }, nls.localize('findRangeHighlightBorder', "Border color the range limiting the search. The color must not be opaque to not hide underlying decorations."), true); +export const editorFindRangeHighlightBorder = registerColor('editor.findRangeHighlightBorder', { dark: null, light: null, hc: transparent(activeContrastBorder, 0.4) }, nls.localize('findRangeHighlightBorder', "Border color of the range limiting the search. The color must not be opaque to not hide underlying decorations."), true); /** * Editor hover @@ -298,7 +301,7 @@ export const mergeCurrentContentBackground = registerColor('merge.currentContent export const mergeIncomingHeaderBackground = registerColor('merge.incomingHeaderBackground', { dark: incomingBaseColor, light: incomingBaseColor, hc: null }, nls.localize('mergeIncomingHeaderBackground', 'Incoming header background in inline merge-conflicts. The color must not be opaque to not hide underlying decorations.'), true); export const mergeIncomingContentBackground = registerColor('merge.incomingContentBackground', { dark: transparent(mergeIncomingHeaderBackground, contentTransparency), light: transparent(mergeIncomingHeaderBackground, contentTransparency), hc: transparent(mergeIncomingHeaderBackground, contentTransparency) }, nls.localize('mergeIncomingContentBackground', 'Incoming content background in inline merge-conflicts. The color must not be opaque to not hide underlying decorations.'), true); export const mergeCommonHeaderBackground = registerColor('merge.commonHeaderBackground', { dark: commonBaseColor, light: commonBaseColor, hc: null }, nls.localize('mergeCommonHeaderBackground', 'Common ancestor header background in inline merge-conflicts. The color must not be opaque to not hide underlying decorations.'), true); -export const mergeCommonContentBackground = registerColor('merge.commonContentBackground', { dark: transparent(mergeCommonHeaderBackground, contentTransparency), light: transparent(mergeCommonHeaderBackground, contentTransparency), hc: transparent(mergeCommonHeaderBackground, contentTransparency) }, nls.localize('mergeCommonContentBackground', 'Common ancester content background in inline merge-conflicts. The color must not be opaque to not hide underlying decorations.'), true); +export const mergeCommonContentBackground = registerColor('merge.commonContentBackground', { dark: transparent(mergeCommonHeaderBackground, contentTransparency), light: transparent(mergeCommonHeaderBackground, contentTransparency), hc: transparent(mergeCommonHeaderBackground, contentTransparency) }, nls.localize('mergeCommonContentBackground', 'Common ancestor content background in inline merge-conflicts. The color must not be opaque to not hide underlying decorations.'), true); export const mergeBorder = registerColor('merge.border', { dark: null, light: null, hc: '#C3DF6F' }, nls.localize('mergeBorder', 'Border color on headers and the splitter in inline merge-conflicts.')); @@ -307,9 +310,9 @@ export const overviewRulerIncomingContentForeground = registerColor('editorOverv export const overviewRulerCommonContentForeground = registerColor('editorOverviewRuler.commonContentForeground', { dark: transparent(mergeCommonHeaderBackground, rulerTransparency), light: transparent(mergeCommonHeaderBackground, rulerTransparency), hc: mergeBorder }, nls.localize('overviewRulerCommonContentForeground', 'Common ancestor overview ruler foreground for inline merge-conflicts.')); const findMatchColorDefault = new Color(new RGBA(246, 185, 77, 0.7)); -export const overviewRulerFindMatchForeground = registerColor('editorOverviewRuler.findMatchForeground', { dark: findMatchColorDefault, light: findMatchColorDefault, hc: findMatchColorDefault }, nls.localize('overviewRulerFindMatchForeground', 'Overview ruler marker color for find matches.')); +export const overviewRulerFindMatchForeground = registerColor('editorOverviewRuler.findMatchForeground', { dark: findMatchColorDefault, light: findMatchColorDefault, hc: findMatchColorDefault }, nls.localize('overviewRulerFindMatchForeground', 'Overview ruler marker color for find matches. The color must not be opaque to not hide underlying decorations.'), true); -export const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0', light: '#A0A0A0', hc: '#A0A0A0' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights.')); +export const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights. The color must not be opaque to not hide underlying decorations.'), true); // ----- color functions diff --git a/src/vs/platform/theme/common/styler.ts b/src/vs/platform/theme/common/styler.ts index df6a7af441..08c131e939 100644 --- a/src/vs/platform/theme/common/styler.ts +++ b/src/vs/platform/theme/common/styler.ts @@ -6,10 +6,12 @@ 'use strict'; import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusForeground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, lighten, badgeBackground, badgeForeground, progressBarBackground } from 'vs/platform/theme/common/colorRegistry'; +import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, lighten, badgeBackground, badgeForeground, progressBarBackground } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { Color } from 'vs/base/common/color'; +import { mixin } from 'vs/base/common/objects'; -export type styleFn = (colors: { [name: string]: ColorIdentifier }) => void; +export type styleFn = (colors: { [name: string]: Color }) => void; export interface IStyleOverrides { [color: string]: ColorIdentifier; @@ -23,17 +25,27 @@ export interface IColorMapping { [optionsKey: string]: ColorIdentifier | ColorFunction | undefined; } -export function attachStyler<T extends IColorMapping>(themeService: IThemeService, optionsMapping: T, widgetOrCallback: IThemable | styleFn): IDisposable { - function applyStyles(theme: ITheme): void { - const styles = Object.create(null); - for (let key in optionsMapping) { - const value = optionsMapping[key as string]; - if (typeof value === 'string') { - styles[key] = theme.getColor(value); - } else if (typeof value === 'function') { - styles[key] = value(theme); - } +export interface IComputedStyles { + [color: string]: Color; +} + +export function computeStyles(theme: ITheme, styleMap: IColorMapping): IComputedStyles { + const styles = Object.create(null) as IComputedStyles; + for (let key in styleMap) { + const value = styleMap[key as string]; + if (typeof value === 'string') { + styles[key] = theme.getColor(value); + } else if (typeof value === 'function') { + styles[key] = value(theme); } + } + + return styles; +} + +export function attachStyler<T extends IColorMapping>(themeService: IThemeService, styleMap: T, widgetOrCallback: IThemable | styleFn): IDisposable { + function applyStyles(theme: ITheme): void { + const styles = computeStyles(themeService.getTheme(), styleMap); if (typeof widgetOrCallback === 'function') { widgetOrCallback(styles); @@ -172,7 +184,6 @@ export function attachQuickOpenStyler(widget: IThemable, themeService: IThemeSer listInactiveSelectionBackground: (style && style.listInactiveSelectionBackground) || listInactiveSelectionBackground, listInactiveSelectionForeground: (style && style.listInactiveSelectionForeground) || listInactiveSelectionForeground, listInactiveFocusBackground: (style && style.listInactiveFocusBackground) || listInactiveFocusBackground, - listInactiveFocusForeground: (style && style.listInactiveFocusForeground) || listInactiveFocusForeground, listHoverBackground: (style && style.listHoverBackground) || listHoverBackground, listHoverForeground: (style && style.listHoverForeground) || listHoverForeground, listDropBackground: (style && style.listDropBackground) || listDropBackground, @@ -192,7 +203,6 @@ export interface IListStyleOverrides extends IStyleOverrides { listInactiveSelectionBackground?: ColorIdentifier; listInactiveSelectionForeground?: ColorIdentifier; listInactiveFocusBackground?: ColorIdentifier; - listInactiveFocusForeground?: ColorIdentifier; listHoverBackground?: ColorIdentifier; listHoverForeground?: ColorIdentifier; listDropBackground?: ColorIdentifier; @@ -202,28 +212,28 @@ export interface IListStyleOverrides extends IStyleOverrides { listHoverOutline?: ColorIdentifier; } -export function attachListStyler(widget: IThemable, themeService: IThemeService, style?: IListStyleOverrides): IDisposable { - return attachStyler(themeService, { - listFocusBackground: (style && style.listFocusBackground) || listFocusBackground, - listFocusForeground: (style && style.listFocusForeground) || listFocusForeground, - listActiveSelectionBackground: (style && style.listActiveSelectionBackground) || lighten(listActiveSelectionBackground, 0.1), - listActiveSelectionForeground: (style && style.listActiveSelectionForeground) || listActiveSelectionForeground, - listFocusAndSelectionBackground: style && style.listFocusAndSelectionBackground || listActiveSelectionBackground, - listFocusAndSelectionForeground: (style && style.listFocusAndSelectionForeground) || listActiveSelectionForeground, - listInactiveSelectionBackground: (style && style.listInactiveSelectionBackground) || listInactiveSelectionBackground, - listInactiveSelectionForeground: (style && style.listInactiveSelectionForeground) || listInactiveSelectionForeground, - listInactiveFocusBackground: (style && style.listInactiveFocusBackground) || listInactiveFocusBackground, - listInactiveFocusForeground: (style && style.listInactiveFocusForeground) || listInactiveFocusForeground, - listHoverBackground: (style && style.listHoverBackground) || listHoverBackground, - listHoverForeground: (style && style.listHoverForeground) || listHoverForeground, - listDropBackground: (style && style.listDropBackground) || listDropBackground, - listFocusOutline: (style && style.listFocusOutline) || activeContrastBorder, - listSelectionOutline: (style && style.listSelectionOutline) || activeContrastBorder, - listHoverOutline: (style && style.listHoverOutline) || activeContrastBorder, - listInactiveFocusOutline: style && style.listInactiveFocusOutline // not defined by default, only opt-in - } as IListStyleOverrides, widget); +export function attachListStyler(widget: IThemable, themeService: IThemeService, overrides?: IListStyleOverrides): IDisposable { + return attachStyler(themeService, mixin(overrides || Object.create(null), defaultListStyles, false) as IListStyleOverrides, widget); } +export const defaultListStyles: IColorMapping = { + listFocusBackground: listFocusBackground, + listFocusForeground: listFocusForeground, + listActiveSelectionBackground: lighten(listActiveSelectionBackground, 0.1), + listActiveSelectionForeground: listActiveSelectionForeground, + listFocusAndSelectionBackground: listActiveSelectionBackground, + listFocusAndSelectionForeground: listActiveSelectionForeground, + listInactiveSelectionBackground: listInactiveSelectionBackground, + listInactiveSelectionForeground: listInactiveSelectionForeground, + listInactiveFocusBackground: listInactiveFocusBackground, + listHoverBackground: listHoverBackground, + listHoverForeground: listHoverForeground, + listDropBackground: listDropBackground, + listFocusOutline: activeContrastBorder, + listSelectionOutline: activeContrastBorder, + listHoverOutline: activeContrastBorder +}; + export interface IButtonStyleOverrides extends IStyleOverrides { buttonForeground?: ColorIdentifier; buttonBackground?: ColorIdentifier; diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index 1fea7d8a92..b25e404351 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -7,9 +7,9 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Color } from 'vs/base/common/color'; import { IDisposable } from 'vs/base/common/lifecycle'; -import platform = require('vs/platform/registry/common/platform'); +import * as platform from 'vs/platform/registry/common/platform'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export const IThemeService = createDecorator<IThemeService>('themeService'); @@ -100,7 +100,7 @@ export interface IThemingRegistry { class ThemingRegistry implements IThemingRegistry { private themingParticipants: IThemingParticipant[] = []; - private onThemingParticipantAddedEmitter: Emitter<IThemingParticipant>; + private readonly onThemingParticipantAddedEmitter: Emitter<IThemingParticipant>; constructor() { this.themingParticipants = []; diff --git a/src/vs/platform/theme/test/common/testThemeService.ts b/src/vs/platform/theme/test/common/testThemeService.ts index 28f46d239c..a7fb41e1a3 100644 --- a/src/vs/platform/theme/test/common/testThemeService.ts +++ b/src/vs/platform/theme/test/common/testThemeService.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IThemeService, ITheme, DARK } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; diff --git a/src/vs/platform/update/common/update.ts b/src/vs/platform/update/common/update.ts index 88dccf1a4d..549408aa15 100644 --- a/src/vs/platform/update/common/update.ts +++ b/src/vs/platform/update/common/update.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { NodeEventEmitter } from 'vs/base/common/event'; +import { Event, NodeEventEmitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; diff --git a/src/vs/platform/update/common/updateIpc.ts b/src/vs/platform/update/common/updateIpc.ts index 224f065cd1..4701a19dce 100644 --- a/src/vs/platform/update/common/updateIpc.ts +++ b/src/vs/platform/update/common/updateIpc.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IUpdateService, State } from './update'; diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index dc30bda542..c54ba7f9fc 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Throttler } from 'vs/base/common/async'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts index 9640e56ede..a95b0780b6 100644 --- a/src/vs/platform/update/electron-main/updateService.darwin.ts +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -7,7 +7,7 @@ import * as electron from 'electron'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { fromNodeEventEmitter } from 'vs/base/common/event'; +import { Event, fromNodeEventEmitter } from 'vs/base/common/event'; import { memoize } from 'vs/base/common/decorators'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; @@ -94,7 +94,7 @@ export class DarwinUpdateService extends AbstractUpdateService { /* __GDPR__ "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('update:notAvailable', { explicit: !!this.state.context }); diff --git a/src/vs/platform/update/electron-main/updateService.linux.ts b/src/vs/platform/update/electron-main/updateService.linux.ts index 8d08762453..9f87033116 100644 --- a/src/vs/platform/update/electron-main/updateService.linux.ts +++ b/src/vs/platform/update/electron-main/updateService.linux.ts @@ -53,7 +53,7 @@ export class LinuxUpdateService extends AbstractUpdateService { if (!update || !update.url || !update.version || !update.productVersion) { /* __GDPR__ "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('update:notAvailable', { explicit: !!context }); @@ -68,7 +68,7 @@ export class LinuxUpdateService extends AbstractUpdateService { /* __GDPR__ "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('update:notAvailable', { explicit: !!context }); diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts index dbe52af6d0..c186cc3759 100644 --- a/src/vs/platform/update/electron-main/updateService.win32.ts +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -90,7 +90,7 @@ export class Win32UpdateService extends AbstractUpdateService { if (!update || !update.url || !update.version) { /* __GDPR__ "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('update:notAvailable', { explicit: !!context }); @@ -135,7 +135,7 @@ export class Win32UpdateService extends AbstractUpdateService { this.logService.error(err); /* __GDPR__ "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('update:notAvailable', { explicit: !!context }); diff --git a/src/vs/platform/update/node/update.config.contribution.ts b/src/vs/platform/update/node/update.config.contribution.ts index eeb81c6fe4..c1a3ab5aad 100644 --- a/src/vs/platform/update/node/update.config.contribution.ts +++ b/src/vs/platform/update/node/update.config.contribution.ts @@ -6,11 +6,10 @@ 'use strict'; import * as nls from 'vs/nls'; -import product from 'vs/platform/node/product'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration); +const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': 'update', 'order': 15, @@ -21,11 +20,13 @@ configurationRegistry.registerConfiguration({ 'type': 'string', 'enum': ['none', 'default'], 'default': 'default', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('updateChannel', "Configure whether you receive automatic updates from an update channel. Requires a restart after change.") }, 'update.enableWindowsBackgroundUpdates': { 'type': 'boolean', - 'default': product.quality === 'insider', + 'default': true, + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('enableWindowsBackgroundUpdates', "Enables Windows background updates.") } } diff --git a/src/vs/platform/url/common/url.ts b/src/vs/platform/url/common/url.ts index 53611bd330..b6c7569059 100644 --- a/src/vs/platform/url/common/url.ts +++ b/src/vs/platform/url/common/url.ts @@ -5,15 +5,21 @@ 'use strict'; -import Event from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { TPromise } from 'vs/base/common/winjs.base'; export const ID = 'urlService'; export const IURLService = createDecorator<IURLService>(ID); +export interface IURLHandler { + handleURL(uri: URI): TPromise<boolean>; +} + export interface IURLService { _serviceBrand: any; - open(url: string): void; - onOpenURL: Event<URI>; + + open(url: URI): TPromise<boolean>; + registerHandler(handler: IURLHandler): IDisposable; } diff --git a/src/vs/platform/url/common/urlIpc.ts b/src/vs/platform/url/common/urlIpc.ts index 081e7e19a4..4ca1d4591d 100644 --- a/src/vs/platform/url/common/urlIpc.ts +++ b/src/vs/platform/url/common/urlIpc.ts @@ -6,61 +6,65 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IChannel, eventToCall, eventFromCall, Serializer, Deserializer } from 'vs/base/parts/ipc/common/ipc'; -import { IURLService } from './url'; -import Event, { filterEvent } from 'vs/base/common/event'; -import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IChannel } from 'vs/base/parts/ipc/common/ipc'; +import { IURLHandler, IURLService } from './url'; import URI from 'vs/base/common/uri'; +import { IDisposable } from 'vs/base/common/lifecycle'; -const URISerializer: Serializer<URI, any> = uri => uri.toJSON(); -const URIDeserializer: Deserializer<URI, any> = raw => URI.revive(raw); - -export interface IURLChannel extends IChannel { - call(command: 'event:onOpenURL'): TPromise<void>; +export interface IURLServiceChannel extends IChannel { + call(command: 'open', url: string): TPromise<boolean>; call(command: string, arg?: any): TPromise<any>; } -export class URLChannel implements IURLChannel { +export class URLServiceChannel implements IURLServiceChannel { - private focusedWindowId: number; - - constructor( - private service: IURLService, - @IWindowsService windowsService: IWindowsService - ) { - windowsService.onWindowFocus(id => this.focusedWindowId = id); - } + constructor(private service: IURLService) { } call(command: string, arg?: any): TPromise<any> { switch (command) { - case 'event:onOpenURL': return eventToCall(filterEvent(this.service.onOpenURL, () => this.isWindowFocused(arg)), URISerializer); + case 'open': return this.service.open(URI.revive(arg)); } return undefined; } - - /** - * We only want the focused window to get pinged with the onOpenUrl event. - * The idea here is to filter the onOpenUrl event with the knowledge of which - * was the last window to be focused. When first listening to the event, - * each client sends its window ID via the arguments to `call(...)`. - * When the event fires, the server has enough knowledge to filter the event - * and fire it only to the focused window. - */ - private isWindowFocused(windowID: number): boolean { - return this.focusedWindowId === windowID; - } } -export class URLChannelClient implements IURLService { +export class URLServiceChannelClient implements IURLService { _serviceBrand: any; - constructor(private channel: IChannel, private windowID: number) { } + constructor(private channel: IChannel) { } - private _onOpenURL = eventFromCall<URI>(this.channel, 'event:onOpenURL', this.windowID, URIDeserializer); - get onOpenURL(): Event<URI> { return this._onOpenURL; } + open(url: URI): TPromise<boolean, any> { + return this.channel.call('open', url.toJSON()); + } - open(url: string): void { - return; // not implemented + registerHandler(handler: IURLHandler): IDisposable { + throw new Error('Not implemented.'); + } +} + +export interface IURLHandlerChannel extends IChannel { + call(command: 'handleURL', arg: any): TPromise<boolean>; + call(command: string, arg?: any): TPromise<any>; +} + +export class URLHandlerChannel implements IURLHandlerChannel { + + constructor(private handler: IURLHandler) { } + + call(command: string, arg?: any): TPromise<any> { + switch (command) { + case 'handleURL': return this.handler.handleURL(URI.revive(arg)); + } + return undefined; + } +} + +export class URLHandlerChannelClient implements IURLHandler { + + constructor(private channel: IChannel) { } + + handleURL(uri: URI): TPromise<boolean> { + return this.channel.call('handleURL', uri.toJSON()); } } \ No newline at end of file diff --git a/src/vs/platform/url/common/urlService.ts b/src/vs/platform/url/common/urlService.ts new file mode 100644 index 0000000000..b192fe2fc1 --- /dev/null +++ b/src/vs/platform/url/common/urlService.ts @@ -0,0 +1,54 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import URI from 'vs/base/common/uri'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { TPromise } from 'vs/base/common/winjs.base'; + +declare module Array { + function from<T>(set: Set<T>): T[]; +} + +export class URLService implements IURLService { + + _serviceBrand: any; + + private handlers = new Set<IURLHandler>(); + + async open(uri: URI): TPromise<boolean> { + const handlers = Array.from(this.handlers); + + for (const handler of handlers) { + if (await handler.handleURL(uri)) { + return true; + } + } + + return false; + } + + registerHandler(handler: IURLHandler): IDisposable { + this.handlers.add(handler); + return toDisposable(() => this.handlers.delete(handler)); + } +} + +export class RelayURLService extends URLService implements IURLHandler { + + constructor(private urlService: IURLService) { + super(); + } + + async open(uri: URI): TPromise<boolean> { + return this.urlService.open(uri); + } + + handleURL(uri: URI): TPromise<boolean> { + return super.open(uri); + } +} \ No newline at end of file diff --git a/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts b/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts new file mode 100644 index 0000000000..c77a4d3e12 --- /dev/null +++ b/src/vs/platform/url/electron-browser/inactiveExtensionUrlHandler.ts @@ -0,0 +1,149 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { localize } from 'vs/nls'; + +const FIVE_MINUTES = 5 * 60 * 1000; +const THIRTY_SECONDS = 30 * 1000; + +function isExtensionId(value: string): boolean { + return /^[a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*$/i.test(value); +} + +export const IExtensionUrlHandler = createDecorator<IExtensionUrlHandler>('inactiveExtensionUrlHandler'); + +export interface IExtensionUrlHandler { + readonly _serviceBrand: any; + registerExtensionHandler(extensionId: string, handler: IURLHandler): void; + unregisterExtensionHandler(extensionId: string): void; +} + +/** + * This class handles URLs which are directed towards inactive extensions. + * If a URL is directed towards an inactive extension, it buffers it, + * activates the extension and re-opens the URL once the extension registers + * a URL handler. If the extension never registers a URL handler, the urls + * will eventually be garbage collected. + * + * It also makes sure the user confirms opening URLs directed towards extensions. + */ +export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { + + readonly _serviceBrand: any; + + private extensionHandlers = new Map<string, IURLHandler>(); + private uriBuffer = new Map<string, { timestamp: number, uri: URI }[]>(); + private disposable: IDisposable; + + constructor( + @IURLService urlService: IURLService, + @IExtensionService private extensionService: IExtensionService, + @IDialogService private dialogService: IDialogService + ) { + const interval = setInterval(() => this.garbageCollect(), THIRTY_SECONDS); + + this.disposable = combinedDisposable([ + urlService.registerHandler(this), + toDisposable(() => clearInterval(interval)) + ]); + } + + async handleURL(uri: URI): TPromise<boolean> { + if (!isExtensionId(uri.authority)) { + return false; + } + + const extensionId = uri.authority; + const wasHandlerAvailable = this.extensionHandlers.has(extensionId); + + const extensions = await this.extensionService.getExtensions(); + const extension = extensions.filter(e => e.id === extensionId)[0]; + + if (!extension) { + return false; + } + + const result = await this.dialogService.confirm({ + message: localize('confirmUrl', "Allow an extension to open this URL?", extensionId), + detail: `${extension.displayName || extension.name} (${extensionId}) wants to open a URL:\n\n${uri.toString()}` + }); + + if (!result.confirmed) { + return true; + } + + const handler = this.extensionHandlers.get(extensionId); + if (handler) { + if (!wasHandlerAvailable) { + // forward it directly + return handler.handleURL(uri); + } + + // let the ExtensionUrlHandler instance handle this + return TPromise.as(false); + } + + // collect URI for eventual extension activation + const timestamp = new Date().getTime(); + let uris = this.uriBuffer.get(extensionId); + + if (!uris) { + uris = []; + this.uriBuffer.set(extensionId, uris); + } + + uris.push({ timestamp, uri }); + + // activate the extension + await this.extensionService.activateByEvent(`onUri:${extensionId}`); + + return true; + } + + registerExtensionHandler(extensionId: string, handler: IURLHandler): void { + this.extensionHandlers.set(extensionId, handler); + + const uris = this.uriBuffer.get(extensionId) || []; + + for (const { uri } of uris) { + handler.handleURL(uri); + } + + this.uriBuffer.delete(extensionId); + } + + unregisterExtensionHandler(extensionId: string): void { + this.extensionHandlers.delete(extensionId); + } + + // forget about all uris buffered more than 5 minutes ago + private garbageCollect(): void { + const now = new Date().getTime(); + const uriBuffer = new Map<string, { timestamp: number, uri: URI }[]>(); + + this.uriBuffer.forEach((uris, extensionId) => { + uris = uris.filter(({ timestamp }) => now - timestamp < FIVE_MINUTES); + + if (uris.length > 0) { + uriBuffer.set(extensionId, uris); + } + }); + + this.uriBuffer = uriBuffer; + } + + dispose(): void { + this.disposable.dispose(); + this.extensionHandlers.clear(); + this.uriBuffer.clear(); + } +} \ No newline at end of file diff --git a/src/vs/platform/url/electron-main/electronUrlListener.ts b/src/vs/platform/url/electron-main/electronUrlListener.ts new file mode 100644 index 0000000000..be370f96d0 --- /dev/null +++ b/src/vs/platform/url/electron-main/electronUrlListener.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { mapEvent, fromNodeEventEmitter, filterEvent, once } from 'vs/base/common/event'; +import { IURLService } from 'vs/platform/url/common/url'; +import product from 'vs/platform/node/product'; +import { app } from 'electron'; +import URI from 'vs/base/common/uri'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; +import { ReadyState } from 'vs/platform/windows/common/windows'; + +function uriFromRawUrl(url: string): URI | null { + try { + return URI.parse(url); + } catch (e) { + return null; + } +} + +export class ElectronURLListener { + + private disposables: IDisposable[] = []; + + constructor( + initial: string | string[], + @IURLService private urlService: IURLService, + @IWindowsMainService windowsService: IWindowsMainService + ) { + const globalBuffer = ((<any>global).getOpenUrls() || []) as string[]; + const rawBuffer = [ + ...(typeof initial === 'string' ? [initial] : initial), + ...globalBuffer + ]; + + const buffer = rawBuffer.map(uriFromRawUrl).filter(uri => !!uri); + const flush = () => buffer.forEach(uri => urlService.open(uri)); + + app.setAsDefaultProtocolClient(product.urlProtocol, process.execPath, ['--open-url', '--']); + + const onOpenElectronUrl = mapEvent( + fromNodeEventEmitter(app, 'open-url', (event: Electron.Event, url: string) => ({ event, url })), + ({ event, url }) => { + // always prevent default and return the url as string + event.preventDefault(); + return url; + }); + + const onOpenUrl = filterEvent(mapEvent(onOpenElectronUrl, uriFromRawUrl), uri => !!uri); + onOpenUrl(this.urlService.open, this.urlService, this.disposables); + + const isWindowReady = windowsService.getWindows() + .filter(w => w.readyState === ReadyState.READY) + .length > 0; + + if (isWindowReady) { + flush(); + } else { + once(windowsService.onWindowReady)(flush); + } + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} \ No newline at end of file diff --git a/src/vs/platform/url/electron-main/urlService.ts b/src/vs/platform/url/electron-main/urlService.ts deleted file mode 100644 index 8e8162befb..0000000000 --- a/src/vs/platform/url/electron-main/urlService.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 Event, { mapEvent, chain, echo, Emitter, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event'; -import { IURLService } from 'vs/platform/url/common/url'; -import product from 'vs/platform/node/product'; -import { app } from 'electron'; -import URI from 'vs/base/common/uri'; -import { ILogService } from '../../log/common/log'; - -export class URLService implements IURLService { - - _serviceBrand: any; - - private openUrlEmitter: Emitter<string> = new Emitter<string>(); - onOpenURL: Event<URI>; - - constructor( - initial: string | string[], - @ILogService private logService: ILogService - ) { - const globalBuffer = (global.getOpenUrls() || []) as string[]; - const initialBuffer = [ - ...(typeof initial === 'string' ? [initial] : initial), - ...globalBuffer - ]; - - app.setAsDefaultProtocolClient(product.urlProtocol, process.execPath, ['--open-url', '--']); - - const rawOnOpenUrl = fromNodeEventEmitter(app, 'open-url', (event: Electron.Event, url: string) => ({ event, url })); - - // always prevent default and return the url as string - const preventedOnOpenUrl = mapEvent(rawOnOpenUrl, ({ event, url }) => { - event.preventDefault(); - return url; - }); - - // echo all `onOpenUrl` events to each listener - const bufferedOnOpenUrl = echo(preventedOnOpenUrl, true, initialBuffer); - - this.onOpenURL = chain(anyEvent(bufferedOnOpenUrl, this.openUrlEmitter.event)) - .map(url => { - try { - return URI.parse(url); - } catch (e) { - return null; - } - }) - .filter(uri => !!uri) - .event; - } - - open(url: string): void { - this.logService.trace('urlService#open', url); - this.openUrlEmitter.fire(url); - } -} diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index b863adaea4..f84a122009 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event, latch, anyEvent } from 'vs/base/common/event'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; @@ -16,6 +16,7 @@ import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ICommandAction } from 'vs/platform/actions/common/actions'; import { PerformanceEntry } from 'vs/base/common/performance'; import { LogLevel } from 'vs/platform/log/common/log'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; export const IWindowsService = createDecorator<IWindowsService>('windowsService'); @@ -213,6 +214,7 @@ export interface IWindowsConfiguration { export interface IWindowSettings { openFilesInNewWindow: 'on' | 'off' | 'default'; openFoldersInNewWindow: 'on' | 'off' | 'default'; + openWithoutArgumentsInNewWindow: 'on' | 'off'; restoreWindows: 'all' | 'folders' | 'one' | 'none'; restoreFullscreen: boolean; zoomLevel: number; @@ -223,6 +225,8 @@ export interface IWindowSettings { nativeTabs: boolean; enableMenuBarMnemonics: boolean; closeWhenEmpty: boolean; + smoothScrollingWorkaround: boolean; + clickThroughInactive: boolean; } export enum OpenContext { @@ -291,6 +295,7 @@ export interface IOpenFileRequest { filesToCreate?: IPath[]; filesToDiff?: IPath[]; filesToWait?: IPathsToWaitFor; + termProgram?: string; } export interface IAddFoldersRequest { @@ -331,3 +336,26 @@ export interface IRunActionInWindowRequest { id: string; from: 'menu' | 'touchbar' | 'mouse'; } + +export class ActiveWindowManager implements IDisposable { + + private disposables: IDisposable[] = []; + private _activeWindowId: number; + + constructor(@IWindowsService windowsService: IWindowsService) { + const onActiveWindowChange = latch(anyEvent(windowsService.onWindowOpen, windowsService.onWindowFocus)); + onActiveWindowChange(this.setActiveWindow, this, this.disposables); + } + + private setActiveWindow(windowId: number) { + this._activeWindowId = windowId; + } + + get activeClientId(): string { + return `window:${this._activeWindowId}`; + } + + dispose() { + this.disposables = dispose(this.disposables); + } +} \ No newline at end of file diff --git a/src/vs/platform/windows/common/windowsIpc.ts b/src/vs/platform/windows/common/windowsIpc.ts index 3f2fde7451..70a5fd0854 100644 --- a/src/vs/platform/windows/common/windowsIpc.ts +++ b/src/vs/platform/windows/common/windowsIpc.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { buffer } from 'vs/base/common/event'; +import { Event, buffer } from 'vs/base/common/event'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions } from 'vs/platform/windows/common/windows'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; diff --git a/src/vs/platform/windows/electron-browser/windowService.ts b/src/vs/platform/windows/electron-browser/windowService.ts index c310f98120..dd025b3fa2 100644 --- a/src/vs/platform/windows/electron-browser/windowService.ts +++ b/src/vs/platform/windows/electron-browser/windowService.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { filterEvent, mapEvent, anyEvent } from 'vs/base/common/event'; +import { Event, filterEvent, mapEvent, anyEvent } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWindowService, IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { IRecentlyOpened } from 'vs/platform/history/common/history'; diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index e60148b7c4..be1d509061 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -8,12 +8,28 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { OpenContext, IWindowConfiguration, ReadyState, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult } from 'vs/platform/windows/common/windows'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; import { ICommandAction } from 'vs/platform/actions/common/actions'; +export interface IWindowState { + width?: number; + height?: number; + x?: number; + y?: number; + mode?: WindowMode; + display?: number; +} + +export enum WindowMode { + Maximized, + Normal, + Minimized, // not used anymore, but also cannot remove due to existing stored UI state (needs migration) + Fullscreen +} + export interface ICodeWindow { id: number; win: Electron.BrowserWindow; @@ -21,13 +37,24 @@ export interface ICodeWindow { openedFolderPath: string; openedWorkspace: IWorkspaceIdentifier; + backupPath: string; + + isExtensionDevelopmentHost: boolean; + isExtensionTestHost: boolean; lastFocusTime: number; readyState: ReadyState; + ready(): TPromise<ICodeWindow>; + load(config: IWindowConfiguration, isReload?: boolean): void; + reload(configuration?: IWindowConfiguration, cli?: ParsedArgs): void; + + focus(): void; close(): void; + getBounds(): Electron.Rectangle; + send(channel: string, ...args: any[]): void; sendWhenReady(channel: string, ...args: any[]): void; @@ -38,6 +65,11 @@ export interface ICodeWindow { onWindowTitleDoubleClick(): void; updateTouchBar(items: ICommandAction[][]): void; + + setReady(): void; + serializeWindowState(): IWindowState; + + dispose(): void; } export const IWindowsMainService = createDecorator<IWindowsMainService>('windowsMainService'); @@ -75,7 +107,7 @@ export interface IWindowsMainService { focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow; getLastActiveWindow(): ICodeWindow; waitForWindowCloseOrLoad(windowId: number): TPromise<void>; - openNewWindow(context: OpenContext): void; + openNewWindow(context: OpenContext): ICodeWindow[]; sendToFocused(channel: string, ...args: any[]): void; sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void; getFocusedWindow(): ICodeWindow; diff --git a/src/vs/platform/windows/electron-main/windowsService.ts b/src/vs/platform/windows/electron-main/windowsService.ts index 96b55ca391..7f2055c501 100644 --- a/src/vs/platform/windows/electron-main/windowsService.ts +++ b/src/vs/platform/windows/electron-main/windowsService.ts @@ -14,8 +14,8 @@ import product from 'vs/platform/node/product'; import { IWindowsService, OpenContext, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult } from 'vs/platform/windows/common/windows'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { shell, crashReporter, app, Menu, clipboard } from 'electron'; -import Event, { chain, fromNodeEventEmitter } from 'vs/base/common/event'; -import { IURLService } from 'vs/platform/url/common/url'; +import { Event, fromNodeEventEmitter, mapEvent, filterEvent, anyEvent } from 'vs/base/common/event'; +import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IWindowsMainService, ISharedProcess } from 'vs/platform/windows/electron-main/windows'; import { IHistoryMainService, IRecentlyOpened } from 'vs/platform/history/common/history'; @@ -24,17 +24,21 @@ import { ICommandAction } from 'vs/platform/actions/common/actions'; import { Schemas } from 'vs/base/common/network'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { isWindows } from 'vs/base/common/platform'; -import { ILogService } from '../../log/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; -export class WindowsService implements IWindowsService, IDisposable { +export class WindowsService implements IWindowsService, IURLHandler, IDisposable { _serviceBrand: any; private disposables: IDisposable[] = []; - readonly onWindowOpen: Event<number> = fromNodeEventEmitter(app, 'browser-window-created', (_, w: Electron.BrowserWindow) => w.id); - readonly onWindowFocus: Event<number> = fromNodeEventEmitter(app, 'browser-window-focus', (_, w: Electron.BrowserWindow) => w.id); - readonly onWindowBlur: Event<number> = fromNodeEventEmitter(app, 'browser-window-blur', (_, w: Electron.BrowserWindow) => w.id); + readonly onWindowOpen: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-created', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id)); + readonly onWindowFocus: Event<number> = anyEvent( + mapEvent(filterEvent(mapEvent(this.windowsMainService.onWindowsCountChanged, () => this.windowsMainService.getLastActiveWindow()), w => !!w), w => w.id), + filterEvent(fromNodeEventEmitter(app, 'browser-window-focus', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id)) + ); + + readonly onWindowBlur: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-blur', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id)); constructor( private sharedProcess: ISharedProcess, @@ -45,17 +49,7 @@ export class WindowsService implements IWindowsService, IDisposable { @IHistoryMainService private historyService: IHistoryMainService, @ILogService private logService: ILogService ) { - // Catch file URLs - chain(urlService.onOpenURL) - .filter(uri => uri.authority === Schemas.file && !!uri.path) - .map(uri => URI.file(uri.fsPath)) - .on(this.openFileForURI, this, this.disposables); - - // Catch extension URLs when there are no windows open - chain(urlService.onOpenURL) - .filter(uri => /^extension/.test(uri.path)) - .filter(() => this.windowsMainService.getWindowCount() === 0) - .on(this.openExtensionForURI, this, this.disposables); + urlService.registerHandler(this); } pickFileFolderAndOpen(options: INativeOpenDialogOptions): TPromise<void> { @@ -496,27 +490,21 @@ export class WindowsService implements IWindowsService, IDisposable { return TPromise.as(null); } - private openFileForURI(uri: URI): TPromise<void> { + async handleURL(uri: URI): TPromise<boolean> { + // Catch file URLs + if (uri.authority === Schemas.file && !!uri.path) { + return this.openFileForURI(URI.file(uri.fsPath)); + } + + return false; + } + + private async openFileForURI(uri: URI): TPromise<boolean> { const cli = assign(Object.create(null), this.environmentService.args, { goto: true }); const pathsToOpen = [uri.fsPath]; this.windowsMainService.open({ context: OpenContext.API, cli, pathsToOpen }); - return TPromise.as(null); - } - - /** - * This should only fire whenever an extension URL is open - * and there are no windows to handle it. - */ - private async openExtensionForURI(uri: URI): TPromise<void> { - const cli = assign(Object.create(null), this.environmentService.args); - const window = await this.windowsMainService.open({ context: OpenContext.API, cli })[0]; - - if (!window) { - return; - } - - window.win.show(); + return true; } dispose(): void { diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 917670ba16..b024ce584d 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -9,7 +9,7 @@ import * as paths from 'vs/base/common/paths'; import * as resources from 'vs/base/common/resources'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TernarySearchTree } from 'vs/base/common/map'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, IStoredWorkspaceFolder, isRawFileWorkspaceFolder, isRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { coalesce, distinct } from 'vs/base/common/arrays'; import { isLinux } from 'vs/base/common/platform'; diff --git a/src/vs/platform/workspaces/common/workspaces.ts b/src/vs/platform/workspaces/common/workspaces.ts index ba03673b8a..826a4dbd10 100644 --- a/src/vs/platform/workspaces/common/workspaces.ts +++ b/src/vs/platform/workspaces/common/workspaces.ts @@ -12,7 +12,7 @@ import { localize } from 'vs/nls'; import { basename, dirname, join } from 'vs/base/common/paths'; import { isLinux } from 'vs/base/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { tildify, getPathLabel } from 'vs/base/common/labels'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import URI from 'vs/base/common/uri'; diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index 9c8e6a46f5..c103cbfc37 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -14,7 +14,7 @@ import { mkdirp, writeFile, readFile } from 'vs/base/node/pfs'; import { readFileSync, existsSync, mkdirSync } from 'fs'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { delSync, readdirSync, writeFileAndFlushSync } from 'vs/base/node/extfs'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; import { isEqual } from 'vs/base/common/paths'; import { coalesce } from 'vs/base/common/arrays'; @@ -37,8 +37,8 @@ export class WorkspacesMainService implements IWorkspacesMainService { protected workspacesHome: string; - private _onWorkspaceSaved: Emitter<IWorkspaceSavedEvent>; - private _onUntitledWorkspaceDeleted: Emitter<IWorkspaceIdentifier>; + private readonly _onWorkspaceSaved: Emitter<IWorkspaceSavedEvent>; + private readonly _onUntitledWorkspaceDeleted: Emitter<IWorkspaceIdentifier>; constructor( @IEnvironmentService private environmentService: IEnvironmentService, diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 7a528792e3..9dc0c507a8 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -6,16 +6,16 @@ 'use strict'; import * as assert from 'assert'; -import fs = require('fs'); -import os = require('os'); -import path = require('path'); -import extfs = require('vs/base/node/extfs'); -import pfs = require('vs/base/node/pfs'); +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import * as extfs from 'vs/base/node/extfs'; +import * as pfs from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; import { WorkspacesMainService, IStoredWorkspace } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { WORKSPACE_EXTENSION, IWorkspaceSavedEvent, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; -import { ConsoleLogMainService } from 'vs/platform/log/common/log'; +import { NullLogService } from 'vs/platform/log/common/log'; import URI from 'vs/base/common/uri'; import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; import { isWindows } from 'vs/base/common/platform'; @@ -50,23 +50,21 @@ suite('WorkspacesMainService', () => { } const environmentService = new TestEnvironmentService(parseArgs(process.argv), process.execPath); - const logService = new ConsoleLogMainService(); + const logService = new NullLogService(); let service: TestWorkspacesMainService; - setup(done => { + setup(() => { service = new TestWorkspacesMainService(environmentService, logService); // Delete any existing backups completely and then re-create it. - extfs.del(workspacesHome, os.tmpdir(), () => { - pfs.mkdirp(workspacesHome).then(() => { - done(); - }); + return pfs.del(workspacesHome, os.tmpdir()).then(() => { + return pfs.mkdirp(workspacesHome); }); }); - teardown(done => { - extfs.del(workspacesHome, os.tmpdir(), done); + teardown(() => { + return pfs.del(workspacesHome, os.tmpdir()); }); function assertPathEquals(p1: string, p2): void { @@ -78,7 +76,7 @@ suite('WorkspacesMainService', () => { assert.equal(p1, p2); } - test('createWorkspace (folders)', done => { + test('createWorkspace (folders)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { assert.ok(workspace); assert.ok(fs.existsSync(workspace.configPath)); @@ -91,12 +89,10 @@ suite('WorkspacesMainService', () => { assert.ok(!(<IRawFileWorkspaceFolder>ws.folders[0]).name); assert.ok(!(<IRawFileWorkspaceFolder>ws.folders[1]).name); - - done(); }); }); - test('createWorkspace (folders with name)', done => { + test('createWorkspace (folders with name)', () => { return createWorkspace([process.cwd(), os.tmpdir()], ['currentworkingdirectory', 'tempdir']).then(workspace => { assert.ok(workspace); assert.ok(fs.existsSync(workspace.configPath)); @@ -109,8 +105,6 @@ suite('WorkspacesMainService', () => { assert.equal((<IRawFileWorkspaceFolder>ws.folders[0]).name, 'currentworkingdirectory'); assert.equal((<IRawFileWorkspaceFolder>ws.folders[1]).name, 'tempdir'); - - done(); }); }); @@ -175,7 +169,7 @@ suite('WorkspacesMainService', () => { assert.ok(!(<IRawFileWorkspaceFolder>ws.folders[1]).name); }); - test('resolveWorkspaceSync', done => { + test('resolveWorkspaceSync', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { assert.ok(service.resolveWorkspaceSync(workspace.configPath)); @@ -192,56 +186,46 @@ suite('WorkspacesMainService', () => { fs.writeFileSync(workspace.configPath, JSON.stringify({ something: 'something' })); // invalid workspace const resolvedInvalid = service.resolveWorkspaceSync(workspace.configPath); assert.ok(!resolvedInvalid); - - done(); }); }); - test('resolveWorkspaceSync (support relative paths)', done => { + test('resolveWorkspaceSync (support relative paths)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib' }] })); const resolved = service.resolveWorkspaceSync(workspace.configPath); assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath); - - done(); }); }); - test('resolveWorkspaceSync (support relative paths #2)', done => { + test('resolveWorkspaceSync (support relative paths #2)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib/../other' }] })); const resolved = service.resolveWorkspaceSync(workspace.configPath); assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'other')).fsPath); - - done(); }); }); - test('resolveWorkspaceSync (support relative paths #3)', done => { + test('resolveWorkspaceSync (support relative paths #3)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: 'ticino-playground/lib' }] })); const resolved = service.resolveWorkspaceSync(workspace.configPath); assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath); - - done(); }); }); - test('resolveWorkspaceSync (support invalid JSON via fault tolerant parsing)', done => { + test('resolveWorkspaceSync (support invalid JSON via fault tolerant parsing)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { fs.writeFileSync(workspace.configPath, '{ "folders": [ { "path": "./ticino-playground/lib" } , ] }'); // trailing comma const resolved = service.resolveWorkspaceSync(workspace.configPath); assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath); - - done(); }); }); - test('saveWorkspace (untitled)', done => { + test('saveWorkspace (untitled)', () => { let savedEvent: IWorkspaceSavedEvent; const listener = service.onWorkspaceSaved(e => { savedEvent = e; @@ -277,13 +261,11 @@ suite('WorkspacesMainService', () => { listener2.dispose(); extfs.delSync(workspaceConfigPath); - - done(); }); }); }); - test('saveWorkspace (saved workspace)', done => { + test('saveWorkspace (saved workspace)', () => { return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); @@ -302,14 +284,12 @@ suite('WorkspacesMainService', () => { extfs.delSync(workspaceConfigPath); extfs.delSync(newWorkspaceConfigPath); - - done(); }); }); }); }); - test('saveWorkspace (saved workspace, preserves comments)', done => { + test('saveWorkspace (saved workspace, preserves comments)', () => { return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); @@ -328,14 +308,12 @@ suite('WorkspacesMainService', () => { extfs.delSync(workspaceConfigPath); extfs.delSync(newWorkspaceConfigPath); - - done(); }); }); }); }); - test('saveWorkspace (saved workspace, preserves forward slashes)', done => { + test('saveWorkspace (saved workspace, preserves forward slashes)', () => { return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); @@ -354,26 +332,22 @@ suite('WorkspacesMainService', () => { extfs.delSync(workspaceConfigPath); extfs.delSync(newWorkspaceConfigPath); - - done(); }); }); }); }); - test('deleteUntitledWorkspaceSync (untitled)', done => { + test('deleteUntitledWorkspaceSync (untitled)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { assert.ok(fs.existsSync(workspace.configPath)); service.deleteUntitledWorkspaceSync(workspace); assert.ok(!fs.existsSync(workspace.configPath)); - - done(); }); }); - test('deleteUntitledWorkspaceSync (saved)', done => { + test('deleteUntitledWorkspaceSync (saved)', () => { return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); @@ -383,13 +357,11 @@ suite('WorkspacesMainService', () => { service.deleteUntitledWorkspaceSync(savedWorkspace); assert.ok(fs.existsSync(savedWorkspace.configPath)); - - done(); }); }); }); - test('getUntitledWorkspaceSync', done => { + test('getUntitledWorkspaceSync', () => { let untitled = service.getUntitledWorkspacesSync(); assert.equal(0, untitled.length); @@ -411,8 +383,6 @@ suite('WorkspacesMainService', () => { service.deleteUntitledWorkspaceSync(untitledTwo); untitled = service.getUntitledWorkspacesSync(); assert.equal(0, untitled.length); - - done(); }); }); }); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 7f1d8e287b..fbb7af8930 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -88,9 +88,13 @@ declare module 'vscode' { export interface TextDocument { /** - * The associated URI for this document. Most documents have the __file__-scheme, indicating that they - * represent files on disk. However, some documents may have other schemes indicating that they are not - * available on disk. + * The associated uri for this document. + * + * *Note* that most documents use the `file`-scheme, which means they are files on disk. However, **not** all documents are + * saved on disk and therefore the `scheme` must be checked before trying to access the underlying file or siblings on disk. + * + * @see [FileSystemProvider](#FileSystemProvider) + * @see [TextDocumentContentProvider](#TextDocumentContentProvider) */ readonly uri: Uri; @@ -101,7 +105,9 @@ declare module 'vscode' { readonly fileName: string; /** - * Is this document representing an untitled file. + * Is this document representing an untitled file which has never been saved yet. *Note* that + * this does not mean the document will be saved to disk, use [`uri.scheme`](#Uri.scheme) + * to figure out where a document will be [saved](#FileSystemProvider), e.g. `file`, `ftp` etc. */ readonly isUntitled: boolean; @@ -537,6 +543,20 @@ declare module 'vscode' { kind?: TextEditorSelectionChangeKind; } + /** + * Represents an event describing the change in a [text editor's visible ranges](#TextEditor.visibleRanges). + */ + export interface TextEditorVisibleRangesChangeEvent { + /** + * The [text editor](#TextEditor) for which the visible ranges have changed. + */ + textEditor: TextEditor; + /** + * The new value for the [text editor's visible ranges](#TextEditor.visibleRanges). + */ + visibleRanges: Range[]; + } + /** * Represents an event describing the change in a [text editor's options](#TextEditor.options). */ @@ -879,6 +899,11 @@ declare module 'vscode' { */ color?: string | ThemeColor; + /** + * CSS styling property that will be applied to text enclosed by a decoration. + */ + opacity?: string; + /** * CSS styling property that will be applied to text enclosed by a decoration. */ @@ -1062,6 +1087,12 @@ declare module 'vscode' { */ selections: Selection[]; + /** + * The current visible ranges in the editor (vertically). + * This accounts only for vertical scrolling, and not for horizontal scrolling. + */ + readonly visibleRanges: Range[]; + /** * Text editor options. */ @@ -1329,7 +1360,7 @@ declare module 'vscode' { cancel(): void; /** - * Dispose object and free resources. Will call [cancel](#CancellationTokenSource.cancel). + * Dispose object and free resources. */ dispose(): void; } @@ -1502,12 +1533,20 @@ declare module 'vscode' { /** * A human readable string which is rendered less prominent. */ - description: string; + description?: string; /** * A human readable string which is rendered less prominent. */ detail?: string; + + /** + * Optional flag indicating if this item is picked initially. + * (Only honored when the picker allows multiple selections.) + * + * @see [QuickPickOptions.canPickMany](#QuickPickOptions.canPickMany) + */ + picked?: boolean; } /** @@ -1534,6 +1573,11 @@ declare module 'vscode' { */ ignoreFocusOut?: boolean; + /** + * An optional flag to make the picker accept multiple selections, if true the result is an array of picks. + */ + canPickMany?: boolean; + /** * An optional function that is invoked whenever an item is selected. */ @@ -1771,7 +1815,7 @@ declare module 'vscode' { * its resource, or a glob-pattern that is applied to the [path](#TextDocument.fileName). * * @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` - * @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**​/package.json' }` + * @sample A language filter that applies to all package.json paths: `{ language: 'json', scheme: 'untitled', pattern: '**​/package.json' }` */ export interface DocumentFilter { @@ -1796,10 +1840,14 @@ declare module 'vscode' { * A language selector is the combination of one or many language identifiers * and [language filters](#DocumentFilter). * - * @sample `let sel:DocumentSelector = 'typescript'`; - * @sample `let sel:DocumentSelector = ['typescript', { language: 'json', pattern: '**​/tsconfig.json' }]`; + * *Note* that a document selector that is just a language identifier selects *all* + * documents, even those that are not saved on disk. Only use such selectors when + * a feature works without further context, e.g without the need to resolve related + * 'files'. + * + * @sample `let sel:DocumentSelector = { scheme: 'file', language: 'typescript' }`; */ - export type DocumentSelector = string | DocumentFilter | (string | DocumentFilter)[]; + export type DocumentSelector = DocumentFilter | string | Array<DocumentFilter | string>; /** * A provider result represents the values a provider, like the [`HoverProvider`](#HoverProvider), @@ -1845,17 +1893,17 @@ declare module 'vscode' { static readonly Empty: CodeActionKind; /** - * Base kind for quickfix actions. + * Base kind for quickfix actions: `quickfix` */ static readonly QuickFix: CodeActionKind; /** - * Base kind for refactoring actions. + * Base kind for refactoring actions: `refactor` */ static readonly Refactor: CodeActionKind; /** - * Base kind for refactoring extraction actions. + * Base kind for refactoring extraction actions: `refactor.extract` * * Example extract actions: * @@ -1868,7 +1916,7 @@ declare module 'vscode' { static readonly RefactorExtract: CodeActionKind; /** - * Base kind for refactoring inline actions. + * Base kind for refactoring inline actions: `refactor.inline` * * Example inline actions: * @@ -1880,7 +1928,7 @@ declare module 'vscode' { static readonly RefactorInline: CodeActionKind; /** - * Base kind for refactoring rewrite actions. + * Base kind for refactoring rewrite actions: `refactor.rewrite` * * Example rewrite actions: * @@ -1893,6 +1941,18 @@ declare module 'vscode' { */ static readonly RefactorRewrite: CodeActionKind; + /** + * Base kind for source actions: `source` + * + * Source code actions apply to the entire file. + */ + static readonly Source: CodeActionKind; + + /** + * Base kind for an organize imports source action: `source.organizeImports` + */ + static readonly SourceOrganizeImports: CodeActionKind; + private constructor(value: string); /** @@ -1989,7 +2049,6 @@ declare module 'vscode' { * A code action can be any command that is [known](#commands.getCommands) to the system. */ export interface CodeActionProvider { - /** * Provide commands for the given document and range. * @@ -2003,6 +2062,19 @@ declare module 'vscode' { provideCodeActions(document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): ProviderResult<(Command | CodeAction)[]>; } + /** + * Metadata about the type of code actions that a [CodeActionProvider](#CodeActionProvider) providers + */ + export interface CodeActionProviderMetadata { + /** + * [CodeActionKinds](#CodeActionKind) that this provider may return. + * + * The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the provider + * may list our every specific kind they provide, such as `CodeActionKind.Refactor.Extract.append('function`)` + */ + readonly providedCodeActionKinds?: ReadonlyArray<CodeActionKind>; + } + /** * A code lens represents a [command](#Command) that should be shown along with * source text, like the number of references, a way to run tests, etc. @@ -2685,6 +2757,18 @@ declare module 'vscode' { * signaled by returning `undefined` or `null`. */ provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): ProviderResult<WorkspaceEdit>; + + /** + * Optional function for resolving and validating a position *before* running rename. The result can + * be a range or a range and a placeholder text. The placeholder text should be the identifier of the symbol + * which is being renamed - when omitted the text in the returned range is used. + * + * @param document The document in which rename will be invoked. + * @param position The position at which rename will be invoked. + * @param token A cancellation token. + * @return The range or range and placeholder text of the identifier that is to be renamed. The lack of a result can signaled by returning `undefined` or `null`. + */ + prepareRename?(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Range | { range: Range, placeholder: string }>; } /** @@ -3311,6 +3395,68 @@ declare module 'vscode' { provideColorPresentations(color: Color, context: { document: TextDocument, range: Range }, token: CancellationToken): ProviderResult<ColorPresentation[]>; } + export class FoldingRange { + + /** + * The zero-based start line of the range to fold. The folded area starts after the line's last character. + */ + start: number; + + /** + * The zero-based end line of the range to fold. The folded area ends with the line's last character. + */ + end: number; + + /** + * Describes the [Kind](#FoldingRangeKind) of the folding range such as [Comment](#FoldingRangeKind.Comment) or + * [Region](#FoldingRangeKind.Region). The kind is used to categorize folding ranges and used by commands + * like 'Fold all comments'. See + * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of all kinds. + */ + kind?: FoldingRangeKind; + + /** + * Creates a new folding range. + * + * @param start The start line of the folded range. + * @param end The end line of the folded range. + * @param kind The kind of the folding range. + */ + constructor(start: number, end: number, kind?: FoldingRangeKind); + } + + export enum FoldingRangeKind { + /** + * Kind for folding range representing a comment. + */ + Comment = 1, + /** + * Kind for folding range representing a import. + */ + Imports = 2, + /** + * Kind for folding range representing regions (for example a folding range marked by `#region` and `#endregion`). + */ + Region = 3 + } + + /** + * Folding context (for future use) + */ + export interface FoldingContext { + } + + export interface FoldingRangeProvider { + /** + * Returns a list of folding ranges or null and undefined if the provider + * does not want to participate or was cancelled. + * @param document The document in which the command was invoked. + * @param context Additional context information (for future use) + * @param token A cancellation token. + */ + provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): ProviderResult<FoldingRange[]>; + } + /** * A tuple of two characters, like a pair of * opening and closing brackets. @@ -3647,6 +3793,17 @@ declare module 'vscode' { constructor(uri: Uri, rangeOrPosition: Range | Position); } + /** + * The event that is fired when diagnostics change. + */ + export interface DiagnosticChangeEvent { + + /** + * An array of resources for which diagnostics have changed. + */ + readonly uris: Uri[]; + } + /** * Represents the severity of diagnostics. */ @@ -3674,6 +3831,32 @@ declare module 'vscode' { Hint = 3 } + /** + * Represents a related message and source code location for a diagnostic. This should be + * used to point to code locations that cause or related to a diagnostics, e.g when duplicating + * a symbol in a scope. + */ + export class DiagnosticRelatedInformation { + + /** + * The location of this related diagnostic information. + */ + location: Location; + + /** + * The message of this related diagnostic information. + */ + message: string; + + /** + * Creates a new related diagnostic information object. + * + * @param location The location. + * @param message The message. + */ + constructor(location: Location, message: string); + } + /** * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects * are only valid in the scope of a file. @@ -3690,23 +3873,29 @@ declare module 'vscode' { */ message: string; - /** - * A human-readable string describing the source of this - * diagnostic, e.g. 'typescript' or 'super lint'. - */ - source: string; - /** * The severity, default is [error](#DiagnosticSeverity.Error). */ severity: DiagnosticSeverity; + /** + * A human-readable string describing the source of this + * diagnostic, e.g. 'typescript' or 'super lint'. + */ + source?: string; + /** * A code or identifier for this diagnostics. Will not be surfaced * to the user, but should be used for later processing, e.g. when * providing [code actions](#CodeActionContext). */ - code: string | number; + code?: string | number; + + /** + * An array of related diagnostic information, e.g. when symbol-names within + * a scope collide all definitions can be marked via this property. + */ + relatedInformation?: DiagnosticRelatedInformation[]; /** * Creates a new diagnostic object. @@ -3973,7 +4162,8 @@ declare module 'vscode' { /** * Report a progress update. - * @param value A progress item, like a message or an updated percentage value + * @param value A progress item, like a message and/or an + * report on how much work finished */ report(value: T): void; } @@ -4265,6 +4455,9 @@ declare module 'vscode' { * script: string; * } * ``` + * + * Note that type identifier starting with a '$' are reserved for internal + * usages and shouldn't be used by extensions. */ readonly type: string; @@ -4332,6 +4525,38 @@ declare module 'vscode' { options?: ProcessExecutionOptions; } + /** + * The shell quoting options. + */ + export interface ShellQuotingOptions { + + /** + * The character used to do character escaping. If a string is provided only spaces + * are escaped. If a `{ escapeChar, charsToEscape }` literal is provide all characters + * in `charsToEscape` are escaped using the `escapeChar`. + */ + escape?: string | { + /** + * The escape character. + */ + escapeChar: string; + /** + * The characters to escape. + */ + charsToEscape: string; + }; + + /** + * The character used for strong quoting. The string's length must be 1. + */ + strong?: string; + + /** + * The character used for weak quoting. The string's length must be 1. + */ + weak?: string; + } + /** * Options for a shell execution */ @@ -4346,6 +4571,11 @@ declare module 'vscode' { */ shellArgs?: string[]; + /** + * The shell quotes supported by this shell. + */ + shellQuoting?: ShellQuotingOptions; + /** * The current working directory of the executed shell. * If omitted the tools current workspace root is used. @@ -4360,10 +4590,55 @@ declare module 'vscode' { env?: { [key: string]: string }; } + /** + * Defines how an argument should be quoted if it contains + * spaces or unsuppoerted characters. + */ + export enum ShellQuoting { + + /** + * Character escaping should be used. This for example + * uses \ on bash and ` on PowerShell. + */ + Escape = 1, + + /** + * Strong string quoting should be used. This for example + * uses " for Windows cmd and ' for bash and PowerShell. + * Strong quoting treats arguments as literal strings. + * Under PowerShell echo 'The value is $(2 * 3)' will + * print `The value is $(2 * 3)` + */ + Strong = 2, + + /** + * Weak string quoting should be used. This for example + * uses " for Windows cmd, bash and PowerShell. Weak quoting + * still performs some kind of evaluation inside the quoted + * string. Under PowerShell echo "The value is $(2 * 3)" + * will print `The value is 6` + */ + Weak = 3 + } + + /** + * A string that will be quoted depending on the used shell. + */ + export interface ShellQuotedString { + /** + * The actual string value. + */ + value: string; + + /** + * The quoting style to use. + */ + quoting: ShellQuoting; + } export class ShellExecution { /** - * Creates a process execution. + * Creates a shell execution with a full command line. * * @param commandLine The command line to execute. * @param options Optional options for the started the shell. @@ -4371,10 +4646,32 @@ declare module 'vscode' { constructor(commandLine: string, options?: ShellExecutionOptions); /** - * The shell command line + * Creates a shell execution with a command and arguments. For the real execution VS Code will + * construct a command line from the command and the arguments. This is subject to interpretation + * especially when it comes to quoting. If full control over the command line is needed please + * use the constructor that creates a `ShellExecution` with the full command line. + * + * @param command The command to execute. + * @param args The command arguments. + * @param options Optional options for the started the shell. + */ + constructor(command: string | ShellQuotedString, args: (string | ShellQuotedString)[], options?: ShellExecutionOptions); + + /** + * The shell command line. Is `undefined` if created with a command and arguments. */ commandLine: string; + /** + * The shell command. Is `undefined` if created with a full command line. + */ + command: string | ShellQuotedString; + + /** + * The shell args. Is `undefined` if created with a full command line. + */ + args: (string | ShellQuotedString)[]; + /** * The shell options used when the command line is executed in a shell. * Defaults to undefined. @@ -4496,9 +4793,12 @@ declare module 'vscode' { /** * Resolves a task that has no [`execution`](#Task.execution) set. Tasks are - * often created from information found in the `task.json`-file. Such tasks miss + * often created from information found in the `tasks.json`-file. Such tasks miss * the information on how to execute them and a task provider must fill in - * the missing information in the `resolveTask`-method. + * the missing information in the `resolveTask`-method. This method will not be + * called for tasks returned from the above `provideTasks` method since those + * tasks are always fully resolved. A valid default implementation for the + * `resolveTask` method is to return `undefined`. * * @param task The task to resolve. * @param token A cancellation token. @@ -4507,6 +4807,441 @@ declare module 'vscode' { resolveTask(task: Task, token?: CancellationToken): ProviderResult<Task>; } + /** + * Enumeration of file types. The types `File` and `Directory` can also be + * a symbolic links, in that use `FileType.File | FileType.SymbolicLink` and + * `FileType.Directory | FileType.SymbolicLink`. + */ + export enum FileType { + /** + * The file type is unknown. + */ + Unknown = 0, + /** + * A regular file. + */ + File = 1, + /** + * A directory. + */ + Directory = 2, + /** + * A symbolic link to a file. + */ + SymbolicLink = 64 + } + + /** + * The `FileStat`-type represents metadata about a file + */ + export interface FileStat { + /** + * The type of the file, e.g. is a regular file, a directory, or symbolic link + * to a file. + */ + type: FileType; + /** + * The creation timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. + */ + ctime: number; + /** + * The modification timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. + */ + mtime: number; + /** + * The size in bytes. + */ + size: number; + } + + /** + * A type that filesystem providers should use to signal errors. + * + * This class has factory methods for common error-cases, like `EntryNotFound` when + * a file or folder doesn't exist, use them like so: `throw vscode.FileSystemError.EntryNotFound(someUri);` + */ + export class FileSystemError extends Error { + + /** + * Create an error to signal that a file or folder wasn't found. + * @param messageOrUri Message or uri. + */ + static FileNotFound(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that a file or folder already exists, e.g. when + * creating but not overwriting a file. + * @param messageOrUri Message or uri. + */ + static FileExists(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that a file is not a folder. + * @param messageOrUri Message or uri. + */ + static FileNotADirectory(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that a file is a folder. + * @param messageOrUri Message or uri. + */ + static FileIsADirectory(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that an operation lacks required permissions. + * @param messageOrUri Message or uri. + */ + static NoPermissions(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that the file system is unavailable or too busy to + * complete a request. + * @param messageOrUri Message or uri. + */ + static Unavailable(messageOrUri?: string | Uri): FileSystemError; + + /** + * Creates a new filesystem error. + * + * @param messageOrUri Message or uri. + */ + constructor(messageOrUri?: string | Uri); + } + + /** + * Enumeration of file change types. + */ + export enum FileChangeType { + + /** + * The contents or metadata of a file have changed. + */ + Changed = 1, + + /** + * A file has been created. + */ + Created = 2, + + /** + * A file has been deleted. + */ + Deleted = 3, + } + + /** + * The event filesystem providers must use to signal a file change. + */ + export interface FileChangeEvent { + + /** + * The type of change. + */ + type: FileChangeType; + + /** + * The uri of the file that has changed. + */ + uri: Uri; + } + + /** + * The filesystem provider defines what the editor needs to read, write, discover, + * and to manage files and folders. It allows extensions to serve files from remote places, + * like ftp-servers, and to seamlessly integrate those into the editor. + * + * * *Note 1:* The filesystem provider API works with [uris](#Uri) and assumes hierarchical + * paths, e.g. `foo:/my/path` is a child of `foo:/my/` and a parent of `foo:/my/path/deeper`. + * * *Note 2:* There is an activation event `onFileSystem:<scheme>` that fires when a file + * or folder is being accessed. + * * *Note 3:* The word 'file' is often used to denote all [kinds](#FileType) of files, e.g. + * folders, symbolic links, and regular files. + */ + export interface FileSystemProvider { + + /** + * An event to signal that a resource has been created, changed, or deleted. This + * event should fire for resources that are being [watched](#FileSystemProvider.watch) + * by clients of this provider. + */ + readonly onDidChangeFile: Event<FileChangeEvent[]>; + + /** + * Subscribe to events in the file or folder denoted by `uri`. + * + * The editor will call this function for files and folders. In the latter case, the + * options differ from defaults, e.g. what files/folders to exclude from watching + * and if subfolders, sub-subfolder, etc. should be watched (`recursive`). + * + * @param uri The uri of the file to be watched. + * @param options Configures the watch. + * @returns A disposable that tells the provider to stop watching the `uri`. + */ + watch(uri: Uri, options: { recursive: boolean; excludes: string[] }): Disposable; + + /** + * Retrieve metadata about a file. + * + * Note that the metadata for symbolic links should be the metadata of the file they refer to. + * Still, the [SymbolicLink](#FileType.SymbolicLink)-type must be used in addition to the actual type, e.g. + * `FileType.SymbolicLink | FileType.Directory`. + * + * @param uri The uri of the file to retrieve metadata about. + * @return The file metadata about the file. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `uri` doesn't exist. + */ + stat(uri: Uri): FileStat | Thenable<FileStat>; + + /** + * Retrieve all entries of a [directory](#FileType.Directory). + * + * @param uri The uri of the folder. + * @return An array of name/type-tuples or a thenable that resolves to such. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `uri` doesn't exist. + */ + readDirectory(uri: Uri): [string, FileType][] | Thenable<[string, FileType][]>; + + /** + * Create a new directory (Note, that new files are created via `write`-calls). + * + * @param uri The uri of the new folder. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when the parent of `uri` doesn't exist, e.g. no mkdirp-logic required. + * @throws [`FileExists`](#FileSystemError.FileExists) when `uri` already exists. + * @throws [`NoPermissions`](#FileSystemError.NoPermissions) when permissions aren't sufficient. + */ + createDirectory(uri: Uri): void | Thenable<void>; + + /** + * Read the entire contents of a file. + * + * @param uri The uri of the file. + * @return An array of bytes or a thenable that resolves to such. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `uri` doesn't exist. + */ + readFile(uri: Uri): Uint8Array | Thenable<Uint8Array>; + + /** + * Write data to a file, replacing its entire contents. + * + * @param uri The uri of the file. + * @param content The new content of the file. + * @param options Defines if missing files should or must be created. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `uri` doesn't exist and `create` is not set. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when the parent of `uri` doesn't exist and `create` is set, e.g. no mkdirp-logic required. + * @throws [`FileExists`](#FileSystemError.FileExists) when `uri` already exists, `create` is set but `overwrite` is not set. + * @throws [`NoPermissions`](#FileSystemError.NoPermissions) when permissions aren't sufficient. + */ + writeFile(uri: Uri, content: Uint8Array, options: { create: boolean, overwrite: boolean }): void | Thenable<void>; + + /** + * Delete a file. + * + * @param uri The resource that is to be deleted. + * @param options Defines if deletion of folders is recursive. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `uri` doesn't exist. + * @throws [`NoPermissions`](#FileSystemError.NoPermissions) when permissions aren't sufficient. + */ + delete(uri: Uri, options: { recursive: boolean }): void | Thenable<void>; + + /** + * Rename a file or folder. + * + * @param oldUri The existing file. + * @param newUri The new location. + * @param options Defines if existing files should be overwriten. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `oldUri` doesn't exist. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when parent of `newUri` doesn't exist, e.g. no mkdirp-logic required. + * @throws [`FileExists`](#FileSystemError.FileExists) when `newUri` exists and when the `overwrite` option is not `true`. + * @throws [`NoPermissions`](#FileSystemError.NoPermissions) when permissions aren't sufficient. + */ + rename(oldUri: Uri, newUri: Uri, options: { overwrite: boolean }): void | Thenable<void>; + + /** + * Copy files or folders. Implementing this function is optional but it will speedup + * the copy operation. + * + * @param source The existing file. + * @param destination The destination location. + * @param options Defines if existing files should be overwriten. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when `source` doesn't exist. + * @throws [`FileNotFound`](#FileSystemError.FileNotFound) when parent of `destination` doesn't exist, e.g. no mkdirp-logic required. + * @throws [`FileExists`](#FileSystemError.FileExists) when `destination` exists and when the `overwrite` option is not `true`. + * @throws [`NoPermissions`](#FileSystemError.NoPermissions) when permissions aren't sufficient. + */ + copy?(source: Uri, destination: Uri, options: { overwrite: boolean }): void | Thenable<void>; + } + + /** + * Content settings for a webview. + */ + export interface WebviewOptions { + /** + * Controls whether scripts are enabled in the webview content or not. + * + * Defaults to false (scripts-disabled). + */ + readonly enableScripts?: boolean; + + /** + * Controls whether command uris are enabled in webview content or not. + * + * Defaults to false. + */ + readonly enableCommandUris?: boolean; + + /** + * Root paths from which the webview can load local (filesystem) resources using the `vscode-resource:` scheme. + * + * Default to the root folders of the current workspace plus the extension's install directory. + * + * Pass in an empty array to disallow access to any local resources. + */ + readonly localResourceRoots?: ReadonlyArray<Uri>; + } + + /** + * A webview displays html content, like an iframe. + */ + export interface Webview { + /** + * Content settings for the webview. + */ + readonly options: WebviewOptions; + + /** + * Contents of the webview. + * + * Should be a complete html document. + */ + html: string; + + /** + * Fired when the webview content posts a message. + */ + readonly onDidReceiveMessage: Event<any>; + + /** + * Post a message to the webview content. + * + * Messages are only develivered if the webview is visible. + * + * @param message Body of the message. + */ + postMessage(message: any): Thenable<boolean>; + } + + /** + * Content settings for a webview panel. + */ + export interface WebviewPanelOptions { + /** + * Controls if the find widget is enabled in the panel. + * + * Defaults to false. + */ + readonly enableFindWidget?: boolean; + + /** + * Controls if the webview panel's content (iframe) is kept around even when the panel + * is no longer visible. + * + * Normally the webview panel's html context is created when the panel becomes visible + * and destroyed when it is is hidden. Extensions that have complex state + * or UI can set the `retainContextWhenHidden` to make VS Code keep the webview + * context around, even when the webview moves to a background tab. When a webview using + * `retainContextWhenHidden` becomes hidden, its scripts and other dynamic content are suspended. + * When the panel becomes visible again, the context is automatically restored + * in the exact same state it was in originally. You cannot send messages to a + * hidden webview, even with `retainContextWhenHidden` enabled. + * + * `retainContextWhenHidden` has a high memory overhead and should only be used if + * your panel's context cannot be quickly saved and restored. + */ + readonly retainContextWhenHidden?: boolean; + } + + /** + * A panel that contains a webview. + */ + interface WebviewPanel { + /** + * Identifies the type of the webview panel, such as `'markdown.preview'`. + */ + readonly viewType: string; + + /** + * Title of the panel shown in UI. + */ + title: string; + + /** + * Webview belonging to the panel. + */ + readonly webview: Webview; + + /** + * Content settings for the webview panel. + */ + readonly options: WebviewPanelOptions; + + /** + * Editor position of the panel. This property is only set if the webview is in + * one of the three editor view columns. + * + * @deprecated + */ + readonly viewColumn?: ViewColumn; + + /** + * Is the panel currently visible? + */ + readonly visible: boolean; + + /** + * Fired when the panel's view state changes. + */ + readonly onDidChangeViewState: Event<WebviewPanelOnDidChangeViewStateEvent>; + + /** + * Fired when the panel is disposed. + * + * This may be because the user closed the panel or because `.dispose()` was + * called on it. + * + * Trying to use the panel after it has been disposed throws an exception. + */ + readonly onDidDispose: Event<void>; + + /** + * Show the webview panel in a given column. + * + * A webview panel may only show in a single column at a time. If it is already showing, this + * method moves it to a new column. + * + * @param viewColumn View column to show the panel in. Shows in the current `viewColumn` if undefined. + */ + reveal(viewColumn?: ViewColumn): void; + + /** + * Dispose of the webview panel. + * + * This closes the panel if it showing and disposes of the resources owned by the webview. + * Webview panels are also disposed when the user closes the webview panel. Both cases + * fire the `onDispose` event. + */ + dispose(): any; + } + + /** + * Event fired when a webview panel's view state changes. + */ + export interface WebviewPanelOnDidChangeViewStateEvent { + /** + * Webview panel whose view state changed. + */ + readonly webviewPanel: WebviewPanel; + } + /** * Namespace describing the environment the editor runs in. */ @@ -4691,6 +5426,11 @@ declare module 'vscode' { */ export const onDidChangeTextEditorSelection: Event<TextEditorSelectionChangeEvent>; + /** + * An [event](#Event) which fires when the selection in an editor has changed. + */ + export const onDidChangeTextEditorVisibleRanges: Event<TextEditorVisibleRangesChangeEvent>; + /** * An [event](#Event) which fires when the options of an editor have changed. */ @@ -4897,6 +5637,16 @@ declare module 'vscode' { */ export function showErrorMessage<T extends MessageItem>(message: string, options: MessageOptions, ...items: T[]): Thenable<T | undefined>; + /** + * Shows a selection list allowing multiple selections. + * + * @param items An array of strings, or a promise that resolves to an array of strings. + * @param options Configures the behavior of the selection list. + * @param token A token that can be used to signal cancellation. + * @return A promise that resolves to the selected items or `undefined`. + */ + export function showQuickPick(items: string[] | Thenable<string[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable<string[] | undefined>; + /** * Shows a selection list. * @@ -4907,6 +5657,16 @@ declare module 'vscode' { */ export function showQuickPick(items: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>; + /** + * Shows a selection list allowing multiple selections. + * + * @param items An array of items, or a promise that resolves to an array of items. + * @param options Configures the behavior of the selection list. + * @param token A token that can be used to signal cancellation. + * @return A promise that resolves to the selected items or `undefined`. + */ + export function showQuickPick<T extends QuickPickItem>(items: T[] | Thenable<T[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable<T[] | undefined>; + /** * Shows a selection list. * @@ -4964,6 +5724,18 @@ declare module 'vscode' { */ export function createOutputChannel(name: string): OutputChannel; + /** + * Create and show a new webview panel. + * + * @param viewType Identifies the type of the webview panel. + * @param title Title of the panel. + * @param position Editor column to show the new panel in. + * @param options Settings for the new panel. + * + * @return New webview panel. + */ + export function createWebviewPanel(viewType: string, title: string, position: ViewColumn, options?: WebviewPanelOptions & WebviewOptions): WebviewPanel; + /** * Set a message to the status bar. This is a short hand for the more powerful * status bar [items](#window.createStatusBarItem). @@ -5015,9 +5787,19 @@ declare module 'vscode' { * * @param task A callback returning a promise. Progress state can be reported with * the provided [progress](#Progress)-object. + * + * To report discrete progress, use `increment` to indicate how much work has been completed. Each call with + * a `increment` value will be summed up and reflected as overall progress until 100% is reached (a value of + * e.g. `10` accounts for `10%` of work done). + * Note that currently only `ProgressLocation.Notification` is capable of showing discrete progress. + * + * To monitor if the operation has been cancelled by the user, use the provided [`CancellationToken`](#CancellationToken). + * Note that currently only `ProgressLocation.Notification` is supporting to show a cancel button to cancel the + * long running operation. + * * @return The thenable the task-callback returned. */ - export function withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; }>) => Thenable<R>): Thenable<R>; + export function withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable<R>): Thenable<R>; /** * Creates a status bar [item](#StatusBarItem). @@ -5050,12 +5832,40 @@ declare module 'vscode' { /** * Register a [TreeDataProvider](#TreeDataProvider) for the view contributed using the extension point `views`. + * This will allow you to contribute data to the [TreeView](#TreeView) and update if the data changes. + * + * **Note:** To get access to the [TreeView](#TreeView) and perform operations on it, use [createTreeView](#window.createTreeView). + * * @param viewId Id of the view contributed using the extension point `views`. * @param treeDataProvider A [TreeDataProvider](#TreeDataProvider) that provides tree data for the view */ export function registerTreeDataProvider<T>(viewId: string, treeDataProvider: TreeDataProvider<T>): Disposable; + + /** + * Create a [TreeView](#TreeView) for the view contributed using the extension point `views`. + * @param viewId Id of the view contributed using the extension point `views`. + * @param options Options object to provide [TreeDataProvider](#TreeDataProvider) for the view. + * @returns a [TreeView](#TreeView). + */ + export function createTreeView<T>(viewId: string, options: { treeDataProvider: TreeDataProvider<T> }): TreeView<T>; } + /** + * Represents a Tree view + */ + export interface TreeView<T> extends Disposable { + + /** + * Reveal an element. By default revealed element is selected. + * + * In order to not to select, set the option `select` to `false`. + * + * **NOTE:** [TreeDataProvider](#TreeDataProvider) is required to implement [getParent](#TreeDataProvider.getParent) method to access this API. + */ + reveal(element: T, options?: { select?: boolean }): Thenable<void>; + } + + /** * A data provider that provides tree data */ @@ -5082,6 +5892,17 @@ declare module 'vscode' { * @return Children of `element` or root if no element is passed. */ getChildren(element?: T): ProviderResult<T[]>; + + /** + * Optional method to return the parent of `element`. + * Return `null` or `undefined` if `element` is a child of root. + * + * **NOTE:** This method should be implemented in order to access [reveal](#TreeView.reveal) API. + * + * @param element The element for which the parent has to be returned. + * @return Parent of `element`. + */ + getParent?(element: T): ProviderResult<T>; } export class TreeItem { @@ -5216,14 +6037,19 @@ declare module 'vscode' { /** * Show progress for the source control viewlet, as overlay for the icon and as progress bar - * inside the viewlet (when visible). + * inside the viewlet (when visible). Neither supports cancellation nor discrete progress. */ SourceControl = 1, /** - * Show progress in the status bar of the editor. + * Show progress in the status bar of the editor. Neither supports cancellation nor discrete progress. */ - Window = 10 + Window = 10, + + /** + * Show progress as notifiation with an optional cancel button. Supports to show infinite and discrete progress. + */ + Notification = 15 } /** @@ -5241,6 +6067,14 @@ declare module 'vscode' { * operation. */ title?: string; + + /** + * Controls if a cancel button should show to allow the user to + * cancel the long running operation. Note that currently only + * `ProgressLocation.Notification` is supporting to show a cancel + * button. + */ + cancellable?: boolean; } /** @@ -5251,6 +6085,10 @@ declare module 'vscode' { * The range that got replaced. */ range: Range; + /** + * The offset of the range that got replaced. + */ + rangeOffset: number; /** * The length of the range that got replaced. */ @@ -5688,6 +6526,19 @@ declare module 'vscode' { * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ export function registerTaskProvider(type: string, provider: TaskProvider): Disposable; + + /** + * Register a filesystem provider for a given scheme, e.g. `ftp`. + * + * There can only be one provider per scheme and an error is being thrown when a scheme + * has been claimed by another provider or when it is reserved. + * + * @param scheme The uri-[scheme](#Uri.scheme) the provider registers for. + * @param provider The filesystem provider. + * @param options Immutable metadata about the provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider, options: { isCaseSensitive?: boolean }): Disposable; } /** @@ -5780,6 +6631,29 @@ declare module 'vscode' { */ export function match(selector: DocumentSelector, document: TextDocument): number; + /** + * An [event](#Event) which fires when the global set of diagnostics changes. This is + * newly added and removed diagnostics. + */ + export const onDidChangeDiagnostics: Event<DiagnosticChangeEvent>; + + /** + * Get all diagnostics for a given resource. *Note* that this includes diagnostics from + * all extensions but *not yet* from the task framework. + * + * @param resource A resource + * @returns An arrary of [diagnostics](#Diagnostic) objects or an empty array. + */ + export function getDiagnostics(resource: Uri): Diagnostic[]; + + /** + * Get all diagnostics. *Note* that this includes diagnostics from + * all extensions but *not yet* from the task framework. + * + * @returns An array of uri-diagnostics tuples or an empty array. + */ + export function getDiagnostics(): [Uri, Diagnostic[]][]; + /** * Create a diagnostics collection. * @@ -5813,9 +6687,10 @@ declare module 'vscode' { * * @param selector A selector that defines the documents this provider is applicable to. * @param provider A code action provider. + * @param metadata Metadata about the kind of code actions the provider providers. * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ - export function registerCodeActionsProvider(selector: DocumentSelector, provider: CodeActionProvider): Disposable; + export function registerCodeActionsProvider(selector: DocumentSelector, provider: CodeActionProvider, metadata?: CodeActionProviderMetadata): Disposable; /** * Register a code lens provider. @@ -6031,6 +6906,23 @@ declare module 'vscode' { */ export function registerColorProvider(selector: DocumentSelector, provider: DocumentColorProvider): Disposable; + /** + * Register a folding range provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. + * If multiple folding ranges start at the same position, only the range of the first registered provider is used. + * If a folding range overlaps with an other range that has a smaller position, it is also ignored. + * + * A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A folding range provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerFoldingRangeProvider(selector: DocumentSelector, provider: FoldingRangeProvider): Disposable; + /** * Set a [language configuration](#LanguageConfiguration) for a language. * diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 565f6ddb27..3e54529462 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -7,142 +7,55 @@ declare module 'vscode' { - export class FoldingRangeList { - - /** - * The folding ranges. - */ - ranges: FoldingRange[]; - - /** - * Creates mew folding range list. - * - * @param ranges The folding ranges - */ - constructor(ranges: FoldingRange[]); + export namespace window { + export function sampleFunction(): Thenable<any>; } + //#region Joh: file system provider (OLD) - export class FoldingRange { - - /** - * The start line number (0-based) - */ - startLine: number; - - /** - * The end line number (0-based) - */ - endLine: number; - - /** - * The actual color value for this color range. - */ - type?: FoldingRangeType | string; - - /** - * Creates a new folding range. - * - * @param startLineNumber The first line of the fold - * @param type The last line of the fold - */ - constructor(startLineNumber: number, endLineNumber: number, type?: FoldingRangeType | string); - } - - export enum FoldingRangeType { - /** - * Folding range for a comment - */ - Comment = 'comment', - /** - * Folding range for a imports or includes - */ - Imports = 'imports', - /** - * Folding range for a region (e.g. `#region`) - */ - Region = 'region' - } - - // export enum FileErrorCodes { - // /** - // * Not owner. - // */ - // EPERM = 1, - // /** - // * No such file or directory. - // */ - // ENOENT = 2, - // /** - // * I/O error. - // */ - // EIO = 5, - // /** - // * Permission denied. - // */ - // EACCES = 13, - // /** - // * File exists. - // */ - // EEXIST = 17, - // /** - // * Not a directory. - // */ - // ENOTDIR = 20, - // /** - // * Is a directory. - // */ - // EISDIR = 21, - // /** - // * File too large. - // */ - // EFBIG = 27, - // /** - // * No space left on device. - // */ - // ENOSPC = 28, - // /** - // * Directory is not empty. - // */ - // ENOTEMPTY = 66, - // /** - // * Invalid file handle. - // */ - // ESTALE = 70, - // /** - // * Illegal NFS file handle. - // */ - // EBADHANDLE = 10001, - // } - - export enum FileChangeType { + export enum DeprecatedFileChangeType { Updated = 0, Added = 1, Deleted = 2 } - - export interface FileChange { - type: FileChangeType; + export interface DeprecatedFileChange { + type: DeprecatedFileChangeType; resource: Uri; } - - export enum FileType { + export enum DeprecatedFileType { File = 0, Dir = 1, Symlink = 2 } - - export interface FileStat { + export interface DeprecatedFileStat { id: number | string; mtime: number; - // atime: number; size: number; - type: FileType; + type: DeprecatedFileType; } + export interface DeprecatedFileSystemProvider { + readonly onDidChange?: Event<DeprecatedFileChange[]>; + utimes(resource: Uri, mtime: number, atime: number): Thenable<DeprecatedFileStat>; + stat(resource: Uri): Thenable<DeprecatedFileStat>; + read(resource: Uri, offset: number, length: number, progress: Progress<Uint8Array>): Thenable<number>; + write(resource: Uri, content: Uint8Array): Thenable<void>; + move(resource: Uri, target: Uri): Thenable<DeprecatedFileStat>; + mkdir(resource: Uri): Thenable<DeprecatedFileStat>; + readdir(resource: Uri): Thenable<[Uri, DeprecatedFileStat][]>; + rmdir(resource: Uri): Thenable<void>; + unlink(resource: Uri): Thenable<void>; + } + export namespace workspace { + export function registerDeprecatedFileSystemProvider(scheme: string, provider: DeprecatedFileSystemProvider): Disposable; + } + + //#endregion + + //#region Joh: remote, search provider export interface TextSearchQuery { pattern: string; - isRegex?: boolean; + isRegExp?: boolean; isCaseSensitive?: boolean; isWordMatch?: boolean; } @@ -158,68 +71,18 @@ declare module 'vscode' { preview: { leading: string, matching: string, trailing: string }; } - // todo@joh discover files etc - // todo@joh CancellationToken everywhere - // todo@joh add open/close calls? - export interface FileSystemProvider { - - readonly onDidChange?: Event<FileChange[]>; - - // todo@joh - remove this - readonly root?: Uri; - - // more... - // - utimes(resource: Uri, mtime: number, atime: number): Thenable<FileStat>; - - stat(resource: Uri): Thenable<FileStat>; - - read(resource: Uri, offset: number, length: number, progress: Progress<Uint8Array>): Thenable<number>; - - // todo@joh - have an option to create iff not exist - // todo@remote - // offset - byte offset to start - // count - number of bytes to write - // Thenable<number> - number of bytes actually written - write(resource: Uri, content: Uint8Array): Thenable<void>; - - // todo@remote - // Thenable<FileStat> - move(resource: Uri, target: Uri): Thenable<FileStat>; - - // todo@remote - // helps with performance bigly - // copy?(from: Uri, to: Uri): Thenable<void>; - - // todo@remote - // Thenable<FileStat> - mkdir(resource: Uri): Thenable<FileStat>; - - readdir(resource: Uri): Thenable<[Uri, FileStat][]>; - - // todo@remote - // ? merge both - // ? recursive del - rmdir(resource: Uri): Thenable<void>; - unlink(resource: Uri): Thenable<void>; - - // todo@remote - // create(resource: Uri): Thenable<FileStat>; - - // find files by names - // todo@joh, move into its own provider - findFiles?(query: string, progress: Progress<Uri>, token: CancellationToken): Thenable<void>; + export interface SearchProvider { + provideFileSearchResults?(query: string, progress: Progress<Uri>, token: CancellationToken): Thenable<void>; provideTextSearchResults?(query: TextSearchQuery, options: TextSearchOptions, progress: Progress<TextSearchResult>, token: CancellationToken): Thenable<void>; } export namespace workspace { - export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider): Disposable; + export function registerSearchProvider(scheme: string, provider: SearchProvider): Disposable; } - export namespace window { + //#endregion - export function sampleFunction(): Thenable<any>; - } + //#region Joao: diff command /** * The contiguous set of modified lines in a diff. @@ -250,7 +113,9 @@ declare module 'vscode' { export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; } - //#region decorations + //#endregion + + //#region Joh: decorations //todo@joh -> make class export interface DecorationData { @@ -283,6 +148,10 @@ declare module 'vscode' { // remove debug namespace + //#endregion + + //#region Rob, Matt: logging + /** * The severity level of a log message */ @@ -300,10 +169,6 @@ declare module 'vscode' { * A logger for writing to an extension's log file, and accessing its dedicated log directory. */ export interface Logger { - readonly onDidChangeLogLevel: Event<LogLevel>; - readonly currentLevel: LogLevel; - readonly logDirectory: Thenable<string>; - trace(message: string, ...args: any[]): void; debug(message: string, ...args: any[]): void; info(message: string, ...args: any[]): void; @@ -317,36 +182,28 @@ declare module 'vscode' { * This extension's logger */ logger: Logger; - } - - export interface RenameInitialValue { - range: Range; - text?: string; - } - - export namespace languages { /** - * Register a folding provider. + * Path where an extension can write log files. * - * Multiple folding can be registered for a language. In that case providers are sorted - * by their [score](#languages.match) and the best-matching provider is used. Failure - * of the selected provider will cause a failure of the whole operation. - * - * @param selector A selector that defines the documents this provider is applicable to. - * @param provider A folding provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + * Extensions must create this directory before writing to it. The parent directory will always exist. */ - export function registerFoldingProvider(selector: DocumentSelector, provider: FoldingProvider): Disposable; + readonly logDirectory: string; + } - export interface RenameProvider2 extends RenameProvider { - resolveInitialRenameValue?(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<RenameInitialValue>; - } - } - export interface FoldingProvider { - provideFoldingRanges(document: TextDocument, token: CancellationToken): ProviderResult<FoldingRangeList>; + export namespace env { + /** + * Current logging level. + * + * @readonly + */ + export const logLevel: LogLevel; } + //#endregion + + //#region Joao: SCM validation + /** * Represents the validation type of the Source Control input. */ @@ -393,246 +250,218 @@ declare module 'vscode' { validateInput?(value: string, cursorPosition: number): ProviderResult<SourceControlInputBoxValidation | undefined | null>; } - /** - * Content settings for a webview. - */ - export interface WebviewOptions { - /** - * Should scripts be enabled in the webview content? - * - * Defaults to false (scripts-disabled). - */ - readonly enableScripts?: boolean; + //#endregion - /** - * Should command uris be enabled in webview content? - * - * Defaults to false. - */ - readonly enableCommandUris?: boolean; - - /** - * Should the webview's context be kept around even when the webview is no longer visible? - * - * Normally a webview's context is created when the webview becomes visible - * and destroyed when the webview is hidden. Apps that have complex state - * or UI can set the `retainContextWhenHidden` to make VS Code keep the webview - * context around, even when the webview moves to a background tab. When - * the webview becomes visible again, the context is automatically restored - * in the exact same state it was in originally. - * - * `retainContextWhenHidden` has a high memory overhead and should only be used if - * your webview's context cannot be quickly saved and restored. - */ - readonly retainContextWhenHidden?: boolean; - - /** - * Root paths from which the webview can load local (filesystem) resources using the `vscode-workspace-resource:` scheme. - * - * Default to the root folders of the current workspace. - * - * Pass in an empty array to disallow access to any local resources. - */ - readonly localResourceRoots?: Uri[]; - } + //#region Matt: WebView Serializer /** - * A webview is an editor with html content, like an iframe. + * Save and restore webview panels that have been persisted when vscode shuts down. */ - export interface Webview { + interface WebviewPanelSerializer { /** - * Type identifying the editor as a webview editor. - */ - readonly editorType: 'webview'; - - /** - * Unique identifer of the webview. - */ - readonly uri: Uri; - - /** - * Content settings for the webview. - */ - readonly options: WebviewOptions; - - /** - * Title of the webview shown in UI. - */ - title: string; - - /** - * Contents of the webview. + * Save a webview panel's `state`. * - * Should be a complete html document. - */ - html: string; - - /** - * The column in which the webview is showing. - */ - readonly viewColumn?: ViewColumn; - - /** - * Fired when the webview content posts a message. - */ - readonly onDidReceiveMessage: Event<any>; - - /** - * Fired when the webview is disposed. - */ - readonly onDidDispose: Event<void>; - - /** - * Fired when the webview's view column changes. - */ - readonly onDidChangeViewColumn: Event<ViewColumn>; - - /** - * Post a message to the webview content. + * Called before shutdown. Extensions have a 250ms timeframe to return a state. If serialization + * takes longer than 250ms, the panel will not be serialized. * - * Messages are only develivered if the webview is visible. + * @param webviewPanel webview Panel to serialize. May or may not be visible. * - * @param message Body of the message. + * @returns JSON serializable state blob. */ - postMessage(message: any): Thenable<boolean>; + serializeWebviewPanel(webviewPanel: WebviewPanel): Thenable<any>; /** - * Shows the webview in a given column. + * Restore a webview panel from its seriailzed `state`. * - * A webview may only show in a single column at a time. If it is already showing, this - * command moves it to a new column. - */ - show(viewColumn: ViewColumn): void; - - /** - * Dispose of the the webview. + * Called when a serialized webview first becomes visible. * - * This closes the webview if it showing and disposes of the resources owned by the webview. - * Webview are also disposed when the user closes the webview editor. Both cases fire `onDispose` - * event. Trying to use the webview after it has been disposed throws an exception. + * @param webviewPanel Webview panel to restore. The serializer should take ownership of this panel. + * @param state Persisted state. + * + * @return Thanble indicating that the webview has been fully restored. */ - dispose(): any; - } - - export interface TextEditor { - /** - * Type identifying the editor as a text editor. - */ - readonly editorType: 'texteditor'; + deserializeWebviewPanel(webviewPanel: WebviewPanel, state: any): Thenable<void>; } namespace window { /** - * Create and show a new webview. + * Registers a webview panel serializer. * - * @param uri Unique identifier for the webview. - * @param title Title of the webview. - * @param column Editor column to show the new webview in. - * @param options Content settings for the webview. + * Extensions that support reviving should have an `"onView:viewType"` activation method and + * make sure that [registerWebviewPanelSerializer](#registerWebviewPanelSerializer) is called during activation. + * + * Only a single serializer may be registered at a time for a given `viewType`. + * + * @param viewType Type of the webview panel that can be serialized. + * @param reviver Webview serializer. */ - export function createWebview(uri: Uri, title: string, column: ViewColumn, options: WebviewOptions): Webview; + export function registerWebviewPanelSerializer(viewType: string, reviver: WebviewPanelSerializer): Disposable; + } + + //#endregion + + //#region Tasks + + /** + * An object representing an executed Task. It can be used + * to terminate a task. + * + * This interface is not intended to be implemented. + */ + export interface TaskExecution { + /** + * The task that got started. + */ + task: Task; /** - * Event fired when the active editor changes. + * Terminates the task execution. */ - export const onDidChangeActiveEditor: Event<TextEditor | Webview | undefined>; + terminate(): void; + } + + /** + * An event signaling the start of a task execution. + * + * This interface is not intended to be implemented. + */ + interface TaskStartEvent { + /** + * The task item representing the task that got started. + */ + execution: TaskExecution; + } + + /** + * An event signaling the end of an executed task. + * + * This interface is not intended to be implemented. + */ + interface TaskEndEvent { + /** + * The task item representing the task that finished. + */ + execution: TaskExecution; + } + + export interface TaskFilter { + /** + * The task version as used in the tasks.json file. + * The string support the package.json semver notation. + */ + version?: string; + + /** + * The task type to return; + */ + type?: string; + } + + export namespace workspace { + + /** + * Fetches all task available in the systems. Thisweweb includes tasks + * from `tasks.json` files as well as tasks from task providers + * contributed through extensions. + * + * @param filter a filter to filter the return tasks. + */ + export function fetchTasks(filter?: TaskFilter): Thenable<Task[]>; + + /** + * Executes a task that is managed by VS Code. The returned + * task execution can be used to terminate the task. + * + * @param task the task to execute + */ + export function executeTask(task: Task): Thenable<TaskExecution>; + + /** + * The currently active task executions or an empty array. + * + * @readonly + */ + export let taskExecutions: ReadonlyArray<TaskExecution>; + + /** + * Fires when a task starts. + */ + export const onDidStartTask: Event<TaskStartEvent>; + + /** + * Fires when a task ends. + */ + export const onDidEndTask: Event<TaskEndEvent>; + } + + //#endregion + + //#region Terminal + + export interface Terminal { + /** + * Fires when the terminal's pty slave pseudo-device is written to. In other words, this + * provides access to the raw data stream from the process running within the terminal, + * including ANSI sequences. + */ + onData: Event<string>; + } + + export namespace window { + /** + * The currently active terminals or an empty array. + * + * @readonly + */ + export let terminals: Terminal[]; + + /** + * An [event](#Event) which fires when a terminal has been created, either through the + * [createTerminal](#window.createTerminal) API or commands. + */ + export const onDidOpenTerminal: Event<Terminal>; + } + + //#endregion + + //#region URLs + + export interface ProtocolHandler { + handleUri(uri: Uri): void; } export namespace window { /** - * Register a [TreeDataProvider](#TreeDataProvider) for the view contributed using the extension point `views`. - * @param viewId Id of the view contributed using the extension point `views`. - * @param treeDataProvider A [TreeDataProvider](#TreeDataProvider) that provides tree data for the view - * @return handle to the [treeview](#TreeView) that can be disposable. + * Registers a protocol handler capable of handling system-wide URIs. */ - export function registerTreeDataProvider<T>(viewId: string, treeDataProvider: TreeDataProvider<T>): TreeView<T>; - + export function registerProtocolHandler(handler: ProtocolHandler): Disposable; } - /** - * Represents a Tree view - */ - export interface TreeView<T> extends Disposable { + //#endregion - /** - * Reveal an element. By default revealed element is selected. - * - * In order to not to select, set the option `select` to `false`. - * - * **NOTE:** [TreeDataProvider](#TreeDataProvider) is required to implement [getParent](#TreeDataProvider.getParent) method to access this API. - */ - reveal(element: T, options?: { select?: boolean }): Thenable<void>; + //#region Joh: hierarchical document symbols, https://github.com/Microsoft/vscode/issues/34968 + + export class HierarchicalSymbolInformation { + name: string; + kind: SymbolKind; + location: Location; + range: Range; + children: HierarchicalSymbolInformation[]; + + constructor(name: string, kind: SymbolKind, location: Location, range: Range); } - /** - * A data provider that provides tree data - */ - export interface TreeDataProvider<T> { - /** - * An optional event to signal that an element or root has changed. - * This will trigger the view to update the changed element/root and its children recursively (if shown). - * To signal that root has changed, do not pass any argument or pass `undefined` or `null`. - */ - onDidChangeTreeData?: Event<T | undefined | null>; - - /** - * Get [TreeItem](#TreeItem) representation of the `element` - * - * @param element The element for which [TreeItem](#TreeItem) representation is asked for. - * @return [TreeItem](#TreeItem) representation of the element - */ - getTreeItem(element: T): TreeItem | Thenable<TreeItem>; - - /** - * Get the children of `element` or root if no element is passed. - * - * @param element The element from which the provider gets children. Can be `undefined`. - * @return Children of `element` or root if no element is passed. - */ - getChildren(element?: T): ProviderResult<T[]>; - - /** - * Optional method to return the parent of `element`. - * Return `null` or `undefined` if `element` is a child of root. - * - * **NOTE:** This method should be implemented in order to access [reveal](#TreeView.reveal) API. - * - * @param element The element for which the parent has to be returned. - * @return Parent of `element`. - */ - getParent?(element: T): ProviderResult<T>; + export interface DocumentSymbolProvider { + provideDocumentSymbols(document: TextDocument, token: CancellationToken): ProviderResult<HierarchicalSymbolInformation | SymbolInformation[]>; } - //#region TextEditor.visibleRange and related event + //#endregion - export interface TextEditor { - /** - * The current visible ranges in the editor (vertically). - * This accounts only for vertical scrolling, and not for horizontal scrolling. - */ - readonly visibleRanges: Range[]; - } + //#region Joh -> exclusive document filters - /** - * Represents an event describing the change in a [text editor's visible ranges](#TextEditor.visibleRanges). - */ - export interface TextEditorVisibleRangesChangeEvent { - /** - * The [text editor](#TextEditor) for which the visible ranges have changed. - */ - textEditor: TextEditor; - /** - * The new value for the [text editor's visible ranges](#TextEditor.visibleRanges). - */ - visibleRanges: Range[]; - } - - export namespace window { - /** - * An [event](#Event) which fires when the selection in an editor has changed. - */ - export const onDidChangeTextEditorVisibleRanges: Event<TextEditorVisibleRangesChangeEvent>; + export interface DocumentFilter { + exclusive?: boolean; } //#endregion diff --git a/src/vs/workbench/api/browser/media/test.svg b/src/vs/workbench/api/browser/media/test.svg new file mode 100644 index 0000000000..57cd408942 --- /dev/null +++ b/src/vs/workbench/api/browser/media/test.svg @@ -0,0 +1,10 @@ +<svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="Canvas" fill="none"> +<g id="beaker"> +<g id="Shape"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M 20.7596 21.885L 15.6896 10.5L 15.6896 4.5L 17.1896 4.5L 17.1896 3L 3.68959 3L 3.68959 4.5L 5.18959 4.5L 5.18959 10.5L 0.134588 21.885C -0.315412 22.875 0.419588 24 1.49959 24L 19.4096 24C 20.4896 24 21.2096 22.875 20.7746 21.885L 20.7596 21.885ZM 4.81458 15L 6.68958 10.5L 6.68958 4.5L 14.1896 4.5L 14.1896 10.5L 16.0646 15L 4.81458 15ZM 11.1896 12L 12.6896 12L 12.6896 13.5L 11.1896 13.5L 11.1896 12ZM 9.68958 10.5L 8.18958 10.5L 8.18958 9L 9.68958 9L 9.68958 10.5ZM 9.68958 6L 11.1896 6L 11.1896 7.5L 9.68958 7.5L 9.68958 6ZM 9.68958 1.5L 8.18958 1.5L 8.18958 0L 9.68958 0L 9.68958 1.5Z" transform="translate(0.810059 0)" fill="white"/> +</g> +</g> +</g> +</svg> + diff --git a/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts b/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts new file mode 100644 index 0000000000..06f790600b --- /dev/null +++ b/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts @@ -0,0 +1,206 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { localize } from 'vs/nls'; +import { IJSONSchema } from 'vs/base/common/jsonSchema'; +import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; +import { join } from 'vs/base/common/paths'; +import { createCSSRule } from 'vs/base/browser/dom'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, ToggleViewletAction } from 'vs/workbench/browser/viewlet'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IExtensionService, IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +import { ViewLocation } from 'vs/workbench/common/views'; +import { PersistentViewsViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet'; +import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { forEach } from 'vs/base/common/collections'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; + + +export interface IUserFriendlyViewsContainerDescriptor { + id: string; + title: string; + icon: string; +} + +const viewsContainerSchema: IJSONSchema = { + type: 'object', + properties: { + id: { + description: localize({ key: 'vscode.extension.contributes.views.containers.id', comment: ['Contribution refers to those that an extension contributes to VS Code through an extension/contribution point. '] }, "Unique id used to identify the container in which views can be contributed using 'views' contribution point"), + type: 'string', + pattern: '^[a-zA-Z0-9_-]+$' + }, + title: { + description: localize('vscode.extension.contributes.views.containers.title', 'Human readable string used to render the container'), + type: 'string' + }, + icon: { + description: localize('vscode.extension.contributes.views.containers.icon', "Path to the container icon. Icons are 24x24 centered on a 50x40 square and have a fill color of 'rgb(215, 218, 224)' or '#d7dae0'. It is recommended that icons be in SVG, though any image file type is accepted."), + type: 'string' + } + } +}; + +export const viewsContainersContribution: IJSONSchema = { + description: localize('vscode.extension.contributes.viewsContainers', 'Contributes views containers to the editor'), + type: 'object', + properties: { + 'activitybar': { + description: localize('views.container.activitybar', "Contribute views containers to Activity Bar"), + type: 'array', + items: viewsContainerSchema + } + } +}; + +export const viewsContainersExtensionPoint: IExtensionPoint<{ [loc: string]: IUserFriendlyViewsContainerDescriptor[] }> = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IUserFriendlyViewsContainerDescriptor[] }>('viewsContainers', [], viewsContainersContribution); + +const TEST_VIEW_CONTAINER_ORDER = 6; + +class ViewsContainersExtensionHandler implements IWorkbenchContribution { + + constructor() { + this.registerTestViewContainer(); + this.handleAndRegisterCustomViewContainers(); + } + + private registerTestViewContainer(): void { + const id = 'test'; + const title = localize('test', "Test"); + const cssClass = `extensionViewlet-${id}`; + const icon = require.toUrl('./media/test.svg'); + + this.registerCustomViewlet({ id, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass); + } + + private handleAndRegisterCustomViewContainers() { + viewsContainersExtensionPoint.setHandler((extensions) => { + for (let extension of extensions) { + const { value, collector } = extension; + forEach(value, entry => { + if (!this.isValidViewsContainer(entry.value, collector)) { + return; + } + switch (entry.key) { + case 'activitybar': + this.registerCustomViewContainers(entry.value, extension.description); + break; + } + }); + } + }); + } + + private isValidViewsContainer(viewsContainersDescriptors: IUserFriendlyViewsContainerDescriptor[], collector: ExtensionMessageCollector): boolean { + if (!Array.isArray(viewsContainersDescriptors)) { + collector.error(localize('requirearray', "views containers must be an array")); + return false; + } + + for (let descriptor of viewsContainersDescriptors) { + if (typeof descriptor.id !== 'string') { + collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id')); + return false; + } + if (!(/^[a-z0-9_-]+$/i.test(descriptor.id))) { + collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id')); + return false; + } + if (typeof descriptor.title !== 'string') { + collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'title')); + return false; + } + if (typeof descriptor.icon !== 'string') { + collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'icon')); + return false; + } + } + + return true; + } + + private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription) { + containers.forEach((descriptor, index) => { + const cssClass = `extensionViewlet-${descriptor.id}`; + const icon = join(extension.extensionFolderPath, descriptor.icon); + this.registerCustomViewlet({ id: descriptor.id, title: descriptor.title, icon }, TEST_VIEW_CONTAINER_ORDER + index + 1, cssClass); + }); + } + + private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor, order: number, cssClass: string): void { + const viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets); + const id = `workbench.view.extension.${descriptor.id}`; + + if (!viewletRegistry.getViewlet(id)) { + + const location: ViewLocation = ViewLocation.register(id); + + // Register as viewlet + class CustomViewlet extends PersistentViewsViewlet { + constructor( + @IPartService partService: IPartService, + @ITelemetryService telemetryService: ITelemetryService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IInstantiationService instantiationService: IInstantiationService, + @IContextKeyService contextKeyService: IContextKeyService, + @IThemeService themeService: IThemeService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService + ) { + super(id, location, `${id}.state`, true, partService, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService); + } + } + const viewletDescriptor = new ViewletDescriptor( + CustomViewlet, + id, + descriptor.title, + cssClass, + order + ); + + viewletRegistry.registerViewlet(viewletDescriptor); + + // Register Action to Open Viewlet + class OpenCustomViewletAction extends ToggleViewletAction { + constructor( + id: string, label: string, + @IViewletService viewletService: IViewletService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService + ) { + super(id, label, id, viewletService, editorService); + } + } + const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions); + registry.registerWorkbenchAction( + new SyncActionDescriptor(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", descriptor.title)), + 'View: Show {0}', + localize('view', "View") + ); + + // Generate CSS to show the icon in the activity bar + const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${cssClass}`; + createCSSRule(iconClass, `-webkit-mask: url('${descriptor.icon}') no-repeat 50% 50%`); + } + + } +} + +const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench); +workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting); \ No newline at end of file diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index bd532960e2..33d9efc210 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -12,11 +12,10 @@ import { ViewLocation, ViewsRegistry, ICustomViewDescriptor } from 'vs/workbench import { CustomTreeViewPanel } from 'vs/workbench/browser/parts/views/customViewPanel'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { coalesce, } from 'vs/base/common/arrays'; +import { viewsContainersExtensionPoint } from 'vs/workbench/api/browser/viewsContainersExtensionPoint'; namespace schema { - // --views contribution point - export interface IUserFriendlyViewDescriptor { id: string; name: string; @@ -70,20 +69,49 @@ namespace schema { type: 'object', properties: { 'explorer': { - description: localize('views.explorer', "Explorer View"), + description: localize('views.explorer', "Contributes views to Explorer container in the Activity bar"), type: 'array', - items: viewDescriptor + items: viewDescriptor, + default: [] }, 'debug': { - description: localize('views.debug', "Debug View"), + description: localize('views.debug', "Contributes views to Debug container in the Activity bar"), type: 'array', - items: viewDescriptor + items: viewDescriptor, + default: [] + }, + 'scm': { + description: localize('views.scm', "Contributes views to SCM container in the Activity bar"), + type: 'array', + items: viewDescriptor, + default: [] + }, + 'test': { + description: localize('views.test', "Contributes views to Test container in the Activity bar"), + type: 'array', + items: viewDescriptor, + default: [] } + }, + additionalProperties: { + description: localize('views.contributed', "Contributes views to contributed views container"), + type: 'array', + items: viewDescriptor, + default: [] } }; } -ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyViewDescriptor[] }>('views', [], schema.viewsContribution) +function getViewLocation(value: string): ViewLocation { + switch (value) { + case 'explorer': return ViewLocation.Explorer; + case 'debug': return ViewLocation.Debug; + case 'scm': return ViewLocation.SCM; + default: return ViewLocation.get(`workbench.view.extension.${value}`); + } +} + +ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyViewDescriptor[] }>('views', [viewsContainersExtensionPoint], schema.viewsContribution) .setHandler((extensions) => { for (let extension of extensions) { const { value, collector } = extension; @@ -93,12 +121,11 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyV return; } - const location = ViewLocation.getContributedViewLocation(entry.key); + let location = getViewLocation(entry.key); if (!location) { - collector.warn(localize('locationId.invalid', "`{0}` is not a valid view location", entry.key)); - return; + collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key)); + location = ViewLocation.Explorer; } - const registeredViews = ViewsRegistry.getViews(location); const viewIds = []; const viewDescriptors = coalesce(entry.value.map(item => { @@ -129,4 +156,4 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyV ViewsRegistry.registerViews(viewDescriptors); }); } - }); + }); \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts index cc867e693d..347a83b145 100644 --- a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts @@ -16,6 +16,7 @@ import { ColorExtensionPoint } from 'vs/workbench/services/themes/common/colorEx import { LanguageConfigurationFileHandler } from 'vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint'; // --- mainThread participants +import 'vs/workbench/api/node/apiCommands'; import './mainThreadCommands'; import './mainThreadConfiguration'; // {{SQL CARBON EDIT}} @@ -42,6 +43,7 @@ import './mainThreadOutputService'; import './mainThreadProgress'; import './mainThreadQuickOpen'; import './mainThreadSCM'; +import './mainThreadSearch'; import './mainThreadSaveParticipant'; import './mainThreadStatusBar'; import './mainThreadStorage'; @@ -51,6 +53,7 @@ import './mainThreadTerminalService'; import './mainThreadTreeViews'; import './mainThreadLogService'; import './mainThreadWebview'; +import './mainThreadUrls'; import './mainThreadWindow'; import './mainThreadWorkspace'; diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index 96b9175919..d199853633 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -9,7 +9,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import uri from 'vs/base/common/uri'; -import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IAdapterExecutable, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider } from 'vs/workbench/parts/debug/common/debug'; import { TPromise } from 'vs/base/common/winjs.base'; import { ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, @@ -17,13 +17,20 @@ import { } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import severity from 'vs/base/common/severity'; +import { AbstractDebugAdapter, convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/node/debugAdapter'; +import * as paths from 'vs/base/common/paths'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; + @extHostNamedCustomer(MainContext.MainThreadDebugService) -export class MainThreadDebugService implements MainThreadDebugServiceShape { +export class MainThreadDebugService implements MainThreadDebugServiceShape, IDebugAdapterProvider { private _proxy: ExtHostDebugServiceShape; private _toDispose: IDisposable[]; private _breakpointEventsActive: boolean; + private _debugAdapters: Map<number, ExtensionHostDebugAdapter>; + private _debugAdaptersHandleCounter = 1; + constructor( extHostContext: IExtHostContext, @@ -49,6 +56,26 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { } } })); + this._debugAdapters = new Map<number, ExtensionHostDebugAdapter>(); + } + + public $registerDebugTypes(debugTypes: string[]) { + this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterProvider(debugTypes, this)); + } + + createDebugAdapter(debugType: string, adapterInfo): IDebugAdapter { + const handle = this._debugAdaptersHandleCounter++; + const da = new ExtensionHostDebugAdapter(handle, this._proxy, debugType, adapterInfo); + this._debugAdapters.set(handle, da); + return da; + } + + substituteVariables(folder: IWorkspaceFolder, config: IConfig): TPromise<IConfig> { + return this._proxy.$substituteVariables(folder.uri, config); + } + + runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> { + return this._proxy.$runInTerminal(args, config); } public dispose(): void { @@ -102,9 +129,10 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { id: l.id, enabled: l.enabled, lineNumber: l.line + 1, - column: l.character > 0 ? l.character + 1 : 0, + column: l.character > 0 ? l.character + 1 : undefined, // a column value of 0 results in an omitted column attribute; see #46784 condition: l.condition, - hitCondition: l.hitCondition + hitCondition: l.hitCondition, + logMessage: l.logMessage } ); this.debugService.addBreakpoints(uri.revive(dto.uri), rawbps); @@ -121,7 +149,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { return void 0; } - private convertToDto(bps: (IBreakpoint | IFunctionBreakpoint)[]): (ISourceBreakpointDto | IFunctionBreakpointDto)[] { + private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): (ISourceBreakpointDto | IFunctionBreakpointDto)[] { return bps.map(bp => { if ('name' in bp) { const fbp = <IFunctionBreakpoint>bp; @@ -142,6 +170,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { enabled: sbp.enabled, condition: sbp.condition, hitCondition: sbp.hitCondition, + logMessage: sbp.logMessage, uri: sbp.uri, line: sbp.lineNumber > 0 ? sbp.lineNumber - 1 : 0, character: (typeof sbp.column === 'number' && sbp.column > 0) ? sbp.column - 1 : 0, @@ -209,6 +238,67 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { this.debugService.logToRepl(value, severity.Warning); return TPromise.wrap<void>(undefined); } + + public $acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage) { + + convertToVSCPaths(message, source => { + if (typeof source.path === 'object') { + source.path = uri.revive(source.path).toString(); + } + }); + + this._debugAdapters.get(handle).acceptMessage(message); + } + + public $acceptDAError(handle: number, name: string, message: string, stack: string) { + this._debugAdapters.get(handle).fireError(handle, new Error(`${name}: ${message}\n${stack}`)); + } + + public $acceptDAExit(handle: number, code: number, signal: string) { + this._debugAdapters.get(handle).fireExit(handle, code, signal); + } +} + +/** + * DebugAdapter that communicates via extension protocol with another debug adapter. + */ + +// {{SQL CARBON EDIT}} +/* +class ExtensionHostDebugAdapter extends AbstractDebugAdapter { + + constructor(private _handle: number, private _proxy: ExtHostDebugServiceShape, private _debugType: string, private _adapterExecutable: IAdapterExecutable | null) { + super(); + } + + public fireError(handle: number, err: Error) { + this._onError.fire(err); + } + + public fireExit(handle: number, code: number, signal: string) { + this._onExit.fire(code); + } + + public startSession(): TPromise<void> { + return this._proxy.$startDASession(this._handle, this._debugType, this._adapterExecutable); + } + + public sendMessage(message: DebugProtocol.ProtocolMessage): void { + + convertToDAPaths(message, source => { + if (paths.isAbsolute(source.path)) { + (<any>source).path = uri.file(source.path); + } else { + (<any>source).path = uri.parse(source.path); + } + }); + + this._proxy.$sendDAMessage(this._handle, message); + } + + public stopSession(): TPromise<void> { + return this._proxy.$stopDASession(this._handle); + } } // {{SQL CARBON EDIT}} */ diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts index 5f76a61675..d0535bafaa 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -10,11 +10,13 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape, DecorationData, DecorationRequest } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IDecorationsService, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { values } from 'vs/base/common/collections'; class DecorationRequestsQueue { private _idPool = 0; - private _requests: DecorationRequest[] = []; + private _requests: { [id: number]: DecorationRequest } = Object.create(null); private _resolver: { [id: number]: Function } = Object.create(null); private _timer: number; @@ -25,12 +27,15 @@ class DecorationRequestsQueue { // } - enqueue(handle: number, uri: URI): Thenable<DecorationData> { - return new Promise((resolve, reject) => { - const id = ++this._idPool; - this._requests.push({ id, handle, uri }); + enqueue(handle: number, uri: URI): TPromise<DecorationData> { + const id = ++this._idPool; + return new TPromise((resolve, reject) => { + this._requests[id] = { id, handle, uri }; this._resolver[id] = resolve; this._processQueue(); + }, () => { + delete this._requests[id]; + delete this._resolver[id]; }); } @@ -43,7 +48,7 @@ class DecorationRequestsQueue { // make request const requests = this._requests; const resolver = this._resolver; - this._proxy.$provideDecorations(requests).then(data => { + this._proxy.$provideDecorations(values(requests)).then(data => { for (const id in resolver) { resolver[id](data[id]); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDiagnostics.ts b/src/vs/workbench/api/electron-browser/mainThreadDiagnostics.ts index 76d59ad81e..e2113cde65 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDiagnostics.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDiagnostics.ts @@ -29,6 +29,15 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape { $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void { for (let entry of entries) { let [uri, markers] = entry; + if (markers) { + for (const marker of markers) { + if (marker.relatedInformation) { + for (const relatedInformation of marker.relatedInformation) { + relatedInformation.resource = URI.revive(relatedInformation.resource); + } + } + } + } this._markerService.changeOne(owner, URI.revive(uri), markers); } this._activeOwners.add(owner); diff --git a/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts b/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts index ed7815c0bc..6a01a2dd1d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDialogs.ts @@ -28,6 +28,7 @@ export class MainThreadDialogs implements MainThreadDiaglogsShape { $showOpenDialog(options: MainThreadDialogOpenOptions): Promise<string[]> { // TODO@joh what about remote dev setup? if (options.defaultUri && options.defaultUri.scheme !== 'file') { + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break return <any>Promise.reject(new Error('Not supported - Open-dialogs can only be opened on `file`-uris.')); } return new Promise<string[]>(resolve => { @@ -40,6 +41,7 @@ export class MainThreadDialogs implements MainThreadDiaglogsShape { $showSaveDialog(options: MainThreadDialogSaveOptions): Promise<string> { // TODO@joh what about remote dev setup? if (options.defaultUri && options.defaultUri.scheme !== 'file') { + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break return <any>Promise.reject(new Error('Not supported - Save-dialogs can only be opened on `file`-uris.')); } return new Promise<string>(resolve => { diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts index 02d27d6f86..3c4e8b9583 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocuments.ts @@ -6,7 +6,7 @@ import URI, { UriComponents } from 'vs/base/common/uri'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { IModelService } from 'vs/editor/common/services/modelService'; +import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; import { TextFileModelChangeEvent, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -132,12 +132,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { private _shouldHandleFileEvent(e: TextFileModelChangeEvent): boolean { const model = this._modelService.getModel(e.resource); - return model && !model.isTooLargeForHavingARichMode(); + return model && shouldSynchronizeModel(model); } private _onModelAdded(model: ITextModel): void { // Same filter as in mainThreadEditorsTracker - if (model.isTooLargeForHavingARichMode()) { + if (!shouldSynchronizeModel(model)) { // don't synchronize too large models return null; } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts index d5fa0ff766..dfcb4b597e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { IModelService } from 'vs/editor/common/services/modelService'; +import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; import { ITextModel } from 'vs/editor/common/model'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ExtHostContext, ExtHostDocumentsAndEditorsShape, IModelAddedData, ITextEditorAddData, IDocumentsAndEditorsDelta, IExtHostContext, MainContext } from '../node/extHost.protocol'; import { MainThreadTextEditor } from './mainThreadEditor'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -192,7 +192,7 @@ class MainThreadDocumentAndEditorStateComputer { } private _updateStateOnModelAdd(model: ITextModel): void { - if (model.isTooLargeForHavingARichMode()) { + if (!shouldSynchronizeModel(model)) { // ignore return; } @@ -222,7 +222,7 @@ class MainThreadDocumentAndEditorStateComputer { // models: ignore too large models const models = new Set<ITextModel>(); for (const model of this._modelService.getModels()) { - if (!model.isTooLargeForHavingARichMode()) { + if (shouldSynchronizeModel(model)) { models.add(model); } } @@ -233,8 +233,11 @@ class MainThreadDocumentAndEditorStateComputer { let activeEditor: string = null; for (const editor of this._codeEditorService.listCodeEditors()) { + if (editor.isSimpleWidget) { + continue; + } const model = editor.getModel(); - if (model && !model.isTooLargeForHavingARichMode() + if (model && shouldSynchronizeModel(model) && !model.isDisposed() // model disposed && Boolean(this._modelService.getModel(model.uri)) // model disposing, the flag didn't flip yet but the model service already removed it ) { diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts index b9d260c1f4..ad1d7d01ff 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts @@ -5,7 +5,7 @@ 'use strict'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IEditor } from 'vs/platform/editor/common/editor'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -185,7 +185,7 @@ export class MainThreadTextEditor { private _codeEditorListeners: IDisposable[]; private _properties: MainThreadTextEditorProperties; - private _onPropertiesChanged: Emitter<IEditorPropertiesChangeData>; + private readonly _onPropertiesChanged: Emitter<IEditorPropertiesChangeData>; constructor( id: string, @@ -322,7 +322,7 @@ export class MainThreadTextEditor { if (newConfiguration.tabSize === 'auto' || newConfiguration.insertSpaces === 'auto') { // one of the options was set to 'auto' => detect indentation - let creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri); + let creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri, this._model.isForSimpleWidget); let insertSpaces = creationOpts.insertSpaces; let tabSize = creationOpts.tabSize; diff --git a/src/vs/workbench/api/electron-browser/mainThreadErrors.ts b/src/vs/workbench/api/electron-browser/mainThreadErrors.ts index c85e01a36d..4eb4c7fc4d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadErrors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadErrors.ts @@ -16,7 +16,7 @@ export class MainThreadErrors implements MainThreadErrorsShape { } $onUnexpectedError(err: any | SerializedError): void { - if (err.$isError) { + if (err && err.$isError) { const { name, message, stack } = err; err = new Error(); err.message = message; diff --git a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts index 653d779bf2..a8b0f30a1d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts @@ -4,114 +4,63 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI, { UriComponents } from 'vs/base/common/uri'; -import { TPromise, PPromise } from 'vs/base/common/winjs.base'; -import { ExtHostContext, MainContext, IExtHostContext, MainThreadFileSystemShape, ExtHostFileSystemShape, IFileChangeDto } from '../node/extHost.protocol'; -import { IFileService, IFileSystemProvider, IStat, IFileChange } from 'vs/platform/files/common/files'; +import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions } from 'vs/platform/files/common/files'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import { IProgress } from 'vs/platform/progress/common/progress'; -import { ISearchResultProvider, ISearchQuery, ISearchComplete, ISearchProgressItem, QueryType, IFileMatch, ISearchService, ILineMatch } from 'vs/platform/search/common/search'; -import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; -import { onUnexpectedError } from 'vs/base/common/errors'; -import { values } from 'vs/base/common/map'; -import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../node/extHost.protocol'; @extHostNamedCustomer(MainContext.MainThreadFileSystem) export class MainThreadFileSystem implements MainThreadFileSystemShape { private readonly _proxy: ExtHostFileSystemShape; - private readonly _provider = new Map<number, RemoteFileSystemProvider>(); + private readonly _fileProvider = new Map<number, RemoteFileSystemProvider>(); constructor( extHostContext: IExtHostContext, - @IFileService private readonly _fileService: IFileService, - @ISearchService private readonly _searchService: ISearchService, - @IWorkspaceEditingService private readonly _workspaceEditingService: IWorkspaceEditingService + @IFileService private readonly _fileService: IFileService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystem); } dispose(): void { - this._provider.forEach(value => dispose()); - this._provider.clear(); + this._fileProvider.forEach(value => value.dispose()); + this._fileProvider.clear(); } - $registerFileSystemProvider(handle: number, scheme: string): void { - this._provider.set(handle, new RemoteFileSystemProvider(this._fileService, this._searchService, scheme, handle, this._proxy)); + $registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void { + this._fileProvider.set(handle, new RemoteFileSystemProvider(this._fileService, scheme, capabilities, handle, this._proxy)); } - $unregisterFileSystemProvider(handle: number): void { - dispose(this._provider.get(handle)); - this._provider.delete(handle); - } - - $onDidAddFileSystemRoot(data: UriComponents): void { - this._workspaceEditingService.addFolders([{ uri: URI.revive(data) }], true).done(null, onUnexpectedError); + $unregisterProvider(handle: number): void { + dispose(this._fileProvider.get(handle)); + this._fileProvider.delete(handle); } $onFileSystemChange(handle: number, changes: IFileChangeDto[]): void { - this._provider.get(handle).$onFileSystemChange(changes); - } - - $reportFileChunk(handle: number, session: number, chunk: number[]): void { - this._provider.get(handle).reportFileChunk(session, chunk); - } - - // --- search - - $handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void { - this._provider.get(handle).handleFindMatch(session, data); + this._fileProvider.get(handle).$onFileSystemChange(changes); } } -class FileReadOperation { - - private static _idPool = 0; - - constructor( - readonly progress: IProgress<Uint8Array>, - readonly id: number = ++FileReadOperation._idPool - ) { - // - } -} - -class SearchOperation { - - private static _idPool = 0; - - constructor( - readonly progress: (match: IFileMatch) => any, - readonly id: number = ++SearchOperation._idPool, - readonly matches = new Map<string, IFileMatch>() - ) { - // - } -} - -class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProvider { +class RemoteFileSystemProvider implements IFileSystemProvider { private readonly _onDidChange = new Emitter<IFileChange[]>(); private readonly _registrations: IDisposable[]; - private readonly _reads = new Map<number, FileReadOperation>(); - private readonly _searches = new Map<number, SearchOperation>(); - - readonly onDidChange: Event<IFileChange[]> = this._onDidChange.event; + readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChange.event; + readonly capabilities: FileSystemProviderCapabilities; constructor( fileService: IFileService, - searchService: ISearchService, - private readonly _scheme: string, + scheme: string, + capabilities: FileSystemProviderCapabilities, private readonly _handle: number, private readonly _proxy: ExtHostFileSystemShape ) { - this._registrations = [ - fileService.registerProvider(_scheme, this), - searchService.registerSearchResultProvider(this), - ]; + this.capabilities = capabilities; + this._registrations = [fileService.registerProvider(scheme, this)]; } dispose(): void { @@ -119,6 +68,16 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv this._onDidChange.dispose(); } + watch(resource: URI, opts: IWatchOptions) { + const session = Math.random(); + this._proxy.$watch(this._handle, session, resource, opts); + return { + dispose: () => { + this._proxy.$unwatch(this._handle, session); + } + }; + } + $onFileSystemChange(changes: IFileChangeDto[]): void { this._onDidChange.fire(changes.map(RemoteFileSystemProvider._createFileChange)); } @@ -129,98 +88,42 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv // --- forwarding calls - utimes(resource: URI, mtime: number, atime: number): TPromise<IStat, any> { - return this._proxy.$utimes(this._handle, resource, mtime, atime); - } - stat(resource: URI): TPromise<IStat, any> { - return this._proxy.$stat(this._handle, resource); - } - read(resource: URI, offset: number, count: number, progress: IProgress<Uint8Array>): TPromise<number, any> { - const read = new FileReadOperation(progress); - this._reads.set(read.id, read); - return this._proxy.$read(this._handle, read.id, offset, count, resource).then(value => { - this._reads.delete(read.id); - return value; + stat(resource: URI): TPromise<IStat> { + return this._proxy.$stat(this._handle, resource).then(undefined, err => { + throw err; }); } - reportFileChunk(session: number, chunk: number[]): void { - this._reads.get(session).progress.report(Buffer.from(chunk)); + + readFile(resource: URI): TPromise<Uint8Array, any> { + return this._proxy.$readFile(this._handle, resource).then(encoded => { + return Buffer.from(encoded, 'base64'); + }); } - write(resource: URI, content: Uint8Array): TPromise<void, any> { - return this._proxy.$write(this._handle, resource, [].slice.call(content)); + + writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): TPromise<void, any> { + let encoded = Buffer.isBuffer(content) + ? content.toString('base64') + : Buffer.from(content.buffer, content.byteOffset, content.byteLength).toString('base64'); + return this._proxy.$writeFile(this._handle, resource, encoded, opts); } - unlink(resource: URI): TPromise<void, any> { - return this._proxy.$unlink(this._handle, resource); + + delete(resource: URI): TPromise<void, any> { + return this._proxy.$delete(this._handle, resource); } - move(resource: URI, target: URI): TPromise<IStat, any> { - return this._proxy.$move(this._handle, resource, target); - } - mkdir(resource: URI): TPromise<IStat, any> { + + mkdir(resource: URI): TPromise<void, any> { return this._proxy.$mkdir(this._handle, resource); } - readdir(resource: URI): TPromise<[URI, IStat][], any> { - return this._proxy.$readdir(this._handle, resource).then(data => { - return data.map(tuple => <[URI, IStat]>[URI.revive(tuple[0]), tuple[1]]); - }); - } - rmdir(resource: URI): TPromise<void, any> { - return this._proxy.$rmdir(this._handle, resource); + + readdir(resource: URI): TPromise<[string, FileType][], any> { + return this._proxy.$readdir(this._handle, resource); } - // --- search - - search(query: ISearchQuery): PPromise<ISearchComplete, ISearchProgressItem> { - - if (isFalsyOrEmpty(query.folderQueries)) { - return PPromise.as(undefined); - } - - let includes = { ...query.includePattern }; - let excludes = { ...query.excludePattern }; - - for (const folderQuery of query.folderQueries) { - if (folderQuery.folder.scheme === this._scheme) { - includes = { ...includes, ...folderQuery.includePattern }; - excludes = { ...excludes, ...folderQuery.excludePattern }; - } - } - - return new PPromise((resolve, reject, report) => { - - const search = new SearchOperation(report); - this._searches.set(search.id, search); - - const promise = query.type === QueryType.File - ? this._proxy.$findFiles(this._handle, search.id, query.filePattern) - : this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, { excludes: Object.keys(excludes), includes: Object.keys(includes) }); - - promise.then(() => { - this._searches.delete(search.id); - resolve(({ results: values(search.matches), stats: undefined })); - }, err => { - this._searches.delete(search.id); - reject(err); - }); - }); + rename(resource: URI, target: URI, opts: FileOverwriteOptions): TPromise<void, any> { + return this._proxy.$rename(this._handle, resource, target, opts); } - handleFindMatch(session: number, dataOrUri: UriComponents | [UriComponents, ILineMatch]): void { - let resource: URI; - let match: ILineMatch; - - if (Array.isArray(dataOrUri)) { - resource = URI.revive(dataOrUri[0]); - match = dataOrUri[1]; - } else { - resource = URI.revive(dataOrUri); - } - - const { matches } = this._searches.get(session); - if (!matches.has(resource.toString())) { - matches.set(resource.toString(), { resource, lineMatches: [] }); - } - if (match) { - matches.get(resource.toString()).lineMatches.push(match); - } + copy(resource: URI, target: URI, opts: FileOverwriteOptions): TPromise<void, any> { + return this._proxy.$copy(this._handle, resource, target, opts); } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts index 9adf71f178..0e899e7903 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts @@ -8,7 +8,7 @@ import { ExtHostContext, ObjectIdentifier, IExtHostContext } from '../node/extHost.protocol'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { isThenable } from 'vs/base/common/async'; @@ -32,7 +32,7 @@ export class HeapService implements IHeapService { _serviceBrand: any; - private _onGarbageCollection: Emitter<number[]> = new Emitter<number[]>(); + private readonly _onGarbageCollection: Emitter<number[]> = new Emitter<number[]>(); public readonly onGarbageCollection: Event<number[]> = this._onGarbageCollection.event; private _activeSignals = new WeakMap<any, object>(); diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 2bcff17cb3..23914028db 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -7,7 +7,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; -import * as vscode from 'vscode'; import { ITextModel, ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { WorkspaceSymbolProviderRegistry, IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search'; @@ -15,7 +14,7 @@ import { wireCancellationToken } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Position as EditorPosition } from 'vs/editor/common/core/position'; import { Range as EditorRange } from 'vs/editor/common/core/range'; -import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter } from '../node/extHost.protocol'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { IHeapService } from './mainThreadHeapService'; @@ -97,7 +96,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- outline - $registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentSymbolProvider>{ provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => { return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)).then(MainThreadLanguageFeatures._reviveSymbolInformationDto); @@ -107,7 +106,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- code lens - $registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): void { + $registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void { const provider = <modes.CodeLensProvider>{ provideCodeLenses: (model: ITextModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => { @@ -136,7 +135,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- declaration - $registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.DefinitionProvider>{ provideDefinition: (model, position, token): Thenable<modes.Definition> => { return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); @@ -144,7 +143,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }); } - $registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.ImplementationProviderRegistry.register(toLanguageSelector(selector), <modes.ImplementationProvider>{ provideImplementation: (model, position, token): Thenable<modes.Definition> => { return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); @@ -152,7 +151,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }); } - $registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.TypeDefinitionProvider>{ provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => { return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); @@ -162,7 +161,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- extra info - $registerHoverProvider(handle: number, selector: vscode.DocumentSelector): void { + $registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.HoverProviderRegistry.register(toLanguageSelector(selector), <modes.HoverProvider>{ provideHover: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.Hover> => { return wireCancellationToken(token, this._proxy.$provideHover(handle, model.uri, position)); @@ -172,7 +171,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- occurrences - $registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): void { + $registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentHighlightProvider>{ provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => { return wireCancellationToken(token, this._proxy.$provideDocumentHighlights(handle, model.uri, position)); @@ -182,7 +181,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- references - $registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.ReferenceProviderRegistry.register(toLanguageSelector(selector), <modes.ReferenceProvider>{ provideReferences: (model: ITextModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => { return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context)).then(MainThreadLanguageFeatures._reviveLocationDto); @@ -192,17 +191,18 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- quick fix - $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], providedCodeActionKinds?: string[]): void { this._registrations[handle] = modes.CodeActionProviderRegistry.register(toLanguageSelector(selector), <modes.CodeActionProvider>{ provideCodeActions: (model: ITextModel, range: EditorRange, context: modes.CodeActionContext, token: CancellationToken): Thenable<modes.CodeAction[]> => { return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range, context))).then(MainThreadLanguageFeatures._reviveCodeActionDto); - } + }, + providedCodeActionKinds }); } // --- formatting - $registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentFormattingEditProvider>{ provideDocumentFormattingEdits: (model: ITextModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => { return wireCancellationToken(token, this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options)); @@ -210,7 +210,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }); } - $registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): void { + $registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentRangeFormattingEditProvider>{ provideDocumentRangeFormattingEdits: (model: ITextModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => { return wireCancellationToken(token, this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options)); @@ -218,7 +218,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }); } - $registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): void { + $registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void { this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.OnTypeFormattingEditProvider>{ autoFormatTriggerCharacters, @@ -251,20 +251,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- rename - $registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void { + $registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportResolveLocation: boolean): void { + this._registrations[handle] = modes.RenameProviderRegistry.register(toLanguageSelector(selector), <modes.RenameProvider>{ provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => { return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)).then(reviveWorkspaceEditDto); }, - resolveInitialRenameValue: supportsResolveInitialValues - ? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.RenameInitialValue> => wireCancellationToken(token, this._proxy.$resolveInitialRenameValue(handle, model.uri, position)) + resolveRenameLocation: supportResolveLocation + ? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.RenameLocation> => wireCancellationToken(token, this._proxy.$resolveRenameLocation(handle, model.uri, position)) : undefined }); } // --- suggest - $registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): void { + $registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void { this._registrations[handle] = modes.SuggestRegistry.register(toLanguageSelector(selector), <modes.ISuggestSupport>{ triggerCharacters, provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.SuggestContext, token: CancellationToken): Thenable<modes.ISuggestResult> => { @@ -287,7 +288,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- parameter hints - $registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): void { + $registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void { this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(toLanguageSelector(selector), <modes.SignatureHelpProvider>{ signatureHelpTriggerCharacters: triggerCharacter, @@ -301,7 +302,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- links - $registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): void { + $registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.LinkProviderRegistry.register(toLanguageSelector(selector), <modes.LinkProvider>{ provideLinks: (model, token) => { return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideDocumentLinks(handle, model.uri))); @@ -314,7 +315,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- colors - $registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): void { + $registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void { const proxy = this._proxy; this._registrations[handle] = modes.ColorProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentColorProvider>{ provideDocumentColors: (model, token) => { @@ -348,11 +349,11 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- folding - $registerFoldingProvider(handle: number, selector: vscode.DocumentSelector): void { + $registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void { const proxy = this._proxy; - this._registrations[handle] = modes.FoldingProviderRegistry.register(toLanguageSelector(selector), <modes.FoldingProvider>{ - provideFoldingRanges: (model, token) => { - return wireCancellationToken(token, proxy.$provideFoldingRanges(handle, model.uri)); + this._registrations[handle] = modes.FoldingRangeProviderRegistry.register(toLanguageSelector(selector), <modes.FoldingRangeProvider>{ + provideFoldingRanges: (model, context, token) => { + return wireCancellationToken(token, proxy.$provideFoldingRanges(handle, model.uri, context)); } }); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts b/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts index 3706f5c50a..3f4efa05ef 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadMessageService.ts @@ -4,18 +4,18 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import Severity from 'vs/base/common/severity'; import { Action, IAction } from 'vs/base/common/actions'; import { MainThreadMessageServiceShape, MainContext, IExtHostContext, MainThreadMessageOptions } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { once } from 'vs/base/common/event'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { localize } from 'vs/nls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { dispose } from 'vs/base/common/lifecycle'; @extHostNamedCustomer(MainContext.MainThreadMessageService) export class MainThreadMessageService implements MainThreadMessageServiceShape { @@ -24,7 +24,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { extHostContext: IExtHostContext, @INotificationService private readonly _notificationService: INotificationService, @ICommandService private readonly _commandService: ICommandService, - @IChoiceService private readonly _choiceService: IChoiceService, + @IDialogService private readonly _dialogService: IDialogService, @IEnvironmentService private readonly _environmentService: IEnvironmentService ) { // @@ -71,11 +71,11 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { let source: string; if (extension) { - source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name); + source = nls.localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name); } if (!source) { - source = localize('defaultSource', "Extension"); + source = nls.localize('defaultSource', "Extension"); } const secondaryActions: IAction[] = []; @@ -93,6 +93,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { // if promise has not been resolved yet, now is the time to ensure a return value // otherwise if already resolved it means the user clicked one of the buttons once(messageHandle.onDidClose)(() => { + dispose(...primaryActions, ...secondaryActions); resolve(undefined); }); }); @@ -101,7 +102,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { private _showModalMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> { let cancelId: number | undefined = void 0; - const options = commands.map((command, index) => { + const buttons = commands.map((command, index) => { if (command.isCloseAffordance === true) { cancelId = index; } @@ -110,16 +111,16 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape { }); if (cancelId === void 0) { - if (options.length > 0) { - options.push(nls.localize('cancel', "Cancel")); + if (buttons.length > 0) { + buttons.push(nls.localize('cancel', "Cancel")); } else { - options.push(nls.localize('ok', "OK")); + buttons.push(nls.localize('ok', "OK")); } - cancelId = options.length - 1; + cancelId = buttons.length - 1; } - return this._choiceService.choose(severity, message, options, cancelId, true) + return this._dialogService.show(severity, message, buttons, { cancelId }) .then(result => result === commands.length ? undefined : commands[result].handle); } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadProgress.ts b/src/vs/workbench/api/electron-browser/mainThreadProgress.ts index 83991742ad..182822c845 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadProgress.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadProgress.ts @@ -5,7 +5,7 @@ 'use strict'; import { IProgressService2, IProgress, IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress'; -import { MainThreadProgressShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; +import { MainThreadProgressShape, MainContext, IExtHostContext, ExtHostProgressShape, ExtHostContext } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; @extHostNamedCustomer(MainContext.MainThreadProgress) @@ -13,11 +13,13 @@ export class MainThreadProgress implements MainThreadProgressShape { private _progressService: IProgressService2; private _progress = new Map<number, { resolve: Function, progress: IProgress<IProgressStep> }>(); + private _proxy: ExtHostProgressShape; constructor( extHostContext: IExtHostContext, @IProgressService2 progressService: IProgressService2 ) { + this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostProgress); this._progressService = progressService; } @@ -28,7 +30,8 @@ export class MainThreadProgress implements MainThreadProgressShape { $startProgress(handle: number, options: IProgressOptions): void { const task = this._createTask(handle); - this._progressService.withProgress(options, task); + + this._progressService.withProgress(options, task, () => this._proxy.$acceptProgressCanceled(handle)); } $progressReport(handle: number, message: IProgressStep): void { diff --git a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts index 80ceec3d23..c9ec39f4a6 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadQuickOpen.ts @@ -7,6 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { asWinJsPromise } from 'vs/base/common/async'; import { IQuickOpenService, IPickOptions, IInputOptions } from 'vs/platform/quickOpen/common/quickOpen'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { InputBoxOptions } from 'vscode'; import { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems, MainContext, IExtHostContext } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; @@ -16,6 +17,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape { private _proxy: ExtHostQuickOpenShape; private _quickOpenService: IQuickOpenService; + private _quickInputService: IQuickInputService; private _doSetItems: (items: MyQuickPickItems[]) => any; private _doSetError: (error: Error) => any; private _contents: TPromise<MyQuickPickItems[]>; @@ -23,16 +25,18 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape { constructor( extHostContext: IExtHostContext, - @IQuickOpenService quickOpenService: IQuickOpenService + @IQuickOpenService quickOpenService: IQuickOpenService, + @IQuickInputService quickInputService: IQuickInputService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostQuickOpen); this._quickOpenService = quickOpenService; + this._quickInputService = quickInputService; } public dispose(): void { } - $show(options: IPickOptions): TPromise<number> { + $show(options: IPickOptions): TPromise<number | number[]> { const myToken = ++this._token; @@ -50,16 +54,29 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape { }; }); - return asWinJsPromise(token => this._quickOpenService.pick(this._contents, options, token)).then(item => { - if (item) { - return item.handle; - } - return undefined; - }, undefined, progress => { - if (progress) { - this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle); - } - }); + if (options.canSelectMany) { + return asWinJsPromise(token => this._quickInputService.pick(this._contents, options, token)).then(items => { + if (items) { + return items.map(item => item.handle); + } + return undefined; + }, undefined, progress => { + if (progress) { + this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle); + } + }); + } else { + return asWinJsPromise(token => this._quickOpenService.pick(this._contents, options, token)).then(item => { + if (item) { + return item.handle; + } + return undefined; + }, undefined, progress => { + if (progress) { + this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle); + } + }); + } } $setItems(items: MyQuickPickItems[]): TPromise<any> { @@ -97,6 +114,6 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape { }; } - return asWinJsPromise(token => this._quickOpenService.input(inputOptions, token)); + return asWinJsPromise(token => this._quickInputService.input(inputOptions, token)); } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 7f763050bd..0d3ae5472e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI, { UriComponents } from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { assign } from 'vs/base/common/objects'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/services/scm/common/scm'; diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index af78cd1088..5368cb7f47 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -28,6 +28,16 @@ import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common import { localize } from 'vs/nls'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { ILogService } from 'vs/platform/log/common/log'; +import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; +import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IFileService } from 'vs/platform/files/common/files'; +import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger'; +import { CodeAction } from 'vs/editor/common/modes'; +import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands'; +import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction'; +import { ICodeActionsOnSaveOptions } from 'vs/editor/common/config/editorOptions'; export interface ISaveParticipantParticipant extends ISaveParticipant { // progressMessage: string; @@ -49,7 +59,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { } private doTrimTrailingWhitespace(model: ITextModel, isAutoSaved: boolean): void { - let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)]; + let prevSelection: Selection[] = []; const cursors: Position[] = []; let editor = findEditor(model, this.codeEditorService); @@ -59,6 +69,12 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { prevSelection = editor.getSelections(); if (isAutoSaved) { cursors.push(...prevSelection.map(s => new Position(s.positionLineNumber, s.positionColumn))); + const snippetsRange = SnippetController2.get(editor).getSessionEnclosingRange(); + if (snippetsRange) { + for (let lineNumber = snippetsRange.startLineNumber; lineNumber <= snippetsRange.endLineNumber; lineNumber++) { + cursors.push(new Position(lineNumber, model.getLineMaxColumn(lineNumber))); + } + } } } @@ -113,7 +129,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant { return; } - let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)]; + let prevSelection: Selection[] = []; const editor = findEditor(model, this.codeEditorService); if (editor) { prevSelection = editor.getSelections(); @@ -150,7 +166,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant return; } - let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)]; + let prevSelection: Selection[] = []; const editor = findEditor(model, this.codeEditorService); if (editor) { prevSelection = editor.getSelections(); @@ -165,7 +181,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant currentLineIsEmptyOrWhitespace = strings.lastNonWhitespaceIndex(currentLine) === -1; } - const deletionRange = new Range(currentLineNumber + 1, 1, lineCount + 1, 1); + const deletionRange = model.validateRange(new Range(currentLineNumber + 1, 1, lineCount + 1, 1)); if (!deletionRange.isEmpty()) { model.pushEditOperations(prevSelection, [EditOperation.delete(deletionRange)], edits => prevSelection); } @@ -197,8 +213,10 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { const versionNow = model.getVersionId(); const { tabSize, insertSpaces } = model.getOptions(); + const timeout = this._configurationService.getValue('editor.formatOnSaveTimeout', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() }); + return new Promise<ISingleEditOperation[]>((resolve, reject) => { - setTimeout(reject, 750); + setTimeout(() => reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout)), timeout); getDocumentFormattingEdits(model, { tabSize, insertSpaces }) .then(edits => this._editorWorkerService.computeMoreMinimalEdits(model.uri, edits)) .then(resolve, err => { @@ -222,7 +240,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { } private _editsWithEditor(editor: ICodeEditor, edits: ISingleEditOperation[]): void { - EditOperationsCommand.execute(editor, edits, false); + EditOperationsCommand.execute(editor, edits); } private _editWithModel(model: ITextModel, edits: ISingleEditOperation[]): void { @@ -249,6 +267,59 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { } } +class CodeActionOnParticipant implements ISaveParticipant { + + constructor( + @ITextModelService private readonly _textModelService: ITextModelService, + @IFileService private readonly _fileService: IFileService, + @ICommandService private readonly _commandService: ICommandService, + @ICodeEditorService private readonly _codeEditorService: ICodeEditorService, + @IConfigurationService private readonly _configurationService: IConfigurationService + ) { } + + async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> { + if (env.reason === SaveReason.AUTO) { + return undefined; + } + + const model = editorModel.textEditorModel; + const editor = findEditor(model, this._codeEditorService); + if (!editor) { + return undefined; + } + + const settingsOverrides = { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() }; + const setting = this._configurationService.getValue<ICodeActionsOnSaveOptions>('editor.codeActionsOnSave', settingsOverrides); + if (!setting) { + return undefined; + } + + const codeActionsOnSave = Object.keys(setting).filter(x => setting[x]).map(x => new CodeActionKind(x)); + if (!codeActionsOnSave.length) { + return undefined; + } + + const timeout = this._configurationService.getValue<number>('editor.codeActionsOnSaveTimeout', settingsOverrides); + + return new Promise<CodeAction[]>((resolve, reject) => { + setTimeout(() => reject(localize('codeActionsOnSave.didTimeout', "Aborted codeActionsOnSave after {0}ms", timeout)), timeout); + this.getActionsToRun(model, codeActionsOnSave).then(resolve); + }).then(actionsToRun => this.applyCodeActions(actionsToRun, editor)); + } + + private async applyCodeActions(actionsToRun: CodeAction[], editor: ICodeEditor) { + for (const action of actionsToRun) { + await applyCodeAction(action, this._textModelService, this._fileService, this._commandService, editor); + } + } + + private async getActionsToRun(model: ITextModel, codeActionsOnSave: CodeActionKind[]) { + const actions = await getCodeActions(model, model.getFullModelRange(), { kind: CodeActionKind.Source, includeSourceActions: true }); + const actionsToRun = actions.filter(returnedAction => returnedAction.kind && codeActionsOnSave.some(onSaveKind => onSaveKind.contains(returnedAction.kind))); + return actionsToRun; + } +} + class ExtHostSaveParticipant implements ISaveParticipantParticipant { private _proxy: ExtHostDocumentSaveParticipantShape; @@ -259,14 +330,14 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant { participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> { - if (editorModel.textEditorModel.isTooLargeForHavingARichMode()) { + if (!shouldSynchronizeModel(editorModel.textEditorModel)) { // the model never made it to the extension // host meaning we cannot participate in its save return undefined; } return new Promise<any>((resolve, reject) => { - setTimeout(reject, 1750); + setTimeout(() => reject(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms")), 1750); this._proxy.$participateInSave(editorModel.getResource(), env.reason).then(values => { for (const success of values) { if (!success) { @@ -293,6 +364,7 @@ export class SaveParticipant implements ISaveParticipant { ) { this._saveParticipants = [ instantiationService.createInstance(TrimWhitespaceParticipant), + instantiationService.createInstance(CodeActionOnParticipant), instantiationService.createInstance(FormatOnSaveParticipant), instantiationService.createInstance(FinalNewLineParticipant), instantiationService.createInstance(TrimFinalNewLinesParticipant), @@ -312,7 +384,7 @@ export class SaveParticipant implements ISaveParticipant { const promiseFactory = this._saveParticipants.map(p => () => { return Promise.resolve(p.participate(model, env)); }); - return sequence(promiseFactory).then(() => { }, err => this._logService.error(err)); + return sequence(promiseFactory).then(() => { }, err => this._logService.warn(err)); }); } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadSearch.ts b/src/vs/workbench/api/electron-browser/mainThreadSearch.ts new file mode 100644 index 0000000000..7d93fd3713 --- /dev/null +++ b/src/vs/workbench/api/electron-browser/mainThreadSearch.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { values } from 'vs/base/common/map'; +import URI, { UriComponents } from 'vs/base/common/uri'; +import { PPromise, TPromise } from 'vs/base/common/winjs.base'; +import { IFileMatch, ILineMatch, ISearchComplete, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, QueryType } from 'vs/platform/search/common/search'; +import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { ExtHostContext, ExtHostSearchShape, IExtHostContext, MainContext, MainThreadSearchShape } from '../node/extHost.protocol'; + +@extHostNamedCustomer(MainContext.MainThreadSearch) +export class MainThreadSearch implements MainThreadSearchShape { + + private readonly _proxy: ExtHostSearchShape; + private readonly _searchProvider = new Map<number, RemoteSearchProvider>(); + + constructor( + extHostContext: IExtHostContext, + @ISearchService private readonly _searchService: ISearchService + ) { + this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSearch); + } + + dispose(): void { + this._searchProvider.forEach(value => dispose()); + this._searchProvider.clear(); + } + + $registerSearchProvider(handle: number, scheme: string): void { + this._searchProvider.set(handle, new RemoteSearchProvider(this._searchService, scheme, handle, this._proxy)); + } + + $unregisterProvider(handle: number): void { + dispose(this._searchProvider.get(handle)); + this._searchProvider.delete(handle); + } + + $handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void { + this._searchProvider.get(handle).handleFindMatch(session, data); + } +} + +class SearchOperation { + + private static _idPool = 0; + + constructor( + readonly progress: (match: IFileMatch) => any, + readonly id: number = ++SearchOperation._idPool, + readonly matches = new Map<string, IFileMatch>() + ) { + // + } + + addMatch(resource: URI, match: ILineMatch): void { + if (!this.matches.has(resource.toString())) { + this.matches.set(resource.toString(), { resource, lineMatches: [] }); + } + if (match) { + this.matches.get(resource.toString()).lineMatches.push(match); + } + this.progress(this.matches.get(resource.toString())); + } +} + +class RemoteSearchProvider implements ISearchResultProvider { + + private readonly _registrations: IDisposable[]; + private readonly _searches = new Map<number, SearchOperation>(); + + + constructor( + searchService: ISearchService, + private readonly _scheme: string, + private readonly _handle: number, + private readonly _proxy: ExtHostSearchShape + ) { + this._registrations = [searchService.registerSearchResultProvider(this)]; + } + + dispose(): void { + dispose(this._registrations); + } + + search(query: ISearchQuery): PPromise<ISearchComplete, ISearchProgressItem> { + + if (isFalsyOrEmpty(query.folderQueries)) { + return PPromise.as(undefined); + } + + let includes = { ...query.includePattern }; + let excludes = { ...query.excludePattern }; + + for (const folderQuery of query.folderQueries) { + if (folderQuery.folder.scheme === this._scheme) { + includes = { ...includes, ...folderQuery.includePattern }; + excludes = { ...excludes, ...folderQuery.excludePattern }; + } + } + + let outer: TPromise; + + return new PPromise((resolve, reject, report) => { + + const search = new SearchOperation(report); + this._searches.set(search.id, search); + + outer = query.type === QueryType.File + ? this._proxy.$provideFileSearchResults(this._handle, search.id, query.filePattern) + : this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, { excludes: Object.keys(excludes), includes: Object.keys(includes) }); + + outer.then(() => { + this._searches.delete(search.id); + resolve(({ results: values(search.matches), stats: undefined })); + }, err => { + this._searches.delete(search.id); + reject(err); + }); + }, () => { + if (outer) { + outer.cancel(); + } + }); + } + + handleFindMatch(session: number, dataOrUri: UriComponents | [UriComponents, ILineMatch]): void { + if (!this._searches.has(session)) { + // ignore... + return; + } + let resource: URI; + let match: ILineMatch; + + if (Array.isArray(dataOrUri)) { + resource = URI.revive(dataOrUri[0]); + match = dataOrUri[1]; + } else { + resource = URI.revive(dataOrUri); + } + + this._searches.get(session).addMatch(resource, match); + } +} diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index 05be000173..67fb007e75 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -4,16 +4,337 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { TPromise } from 'vs/base/common/winjs.base'; +import * as crypto from 'crypto'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import * as nls from 'vs/nls'; -import { ContributedTask, ExtensionTaskSourceTransfer } from 'vs/workbench/parts/tasks/common/tasks'; -import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService'; - -import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; -import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import URI from 'vs/base/common/uri'; +import * as Objects from 'vs/base/common/objects'; +import { TPromise } from 'vs/base/common/winjs.base'; +import * as Types from 'vs/base/common/types'; + +import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; + +import { + ContributedTask, ExtensionTaskSourceTransfer, TaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind, + PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource, RevealKind, PanelKind +} from 'vs/workbench/parts/tasks/common/tasks'; +import { ITaskService, TaskFilter } from 'vs/workbench/parts/tasks/common/taskService'; + + +import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; +import { + TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO, + ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO +} from 'vs/workbench/api/shared/tasks'; + +export { TaskDTO, TaskHandleDTO, TaskExecutionDTO, TaskFilterDTO }; + +namespace TaskExecutionDTO { + export function from(value: TaskExecution): TaskExecutionDTO { + return { + id: value.id, + task: TaskDTO.from(value.task) + }; + } + export function to(value: TaskExecutionDTO, workspace: IWorkspaceContextService): TaskExecution { + return { + id: value.id, + task: TaskDTO.to(value.task, workspace) + }; + } +} + +namespace TaskDefinitionDTO { + export function from(value: TaskIdentifier): TaskDefinitionDTO { + let result = Objects.assign(Object.create(null), value); + delete result._key; + return result; + } + export function to(value: TaskDefinitionDTO): TaskIdentifier { + const hash = crypto.createHash('md5'); + hash.update(JSON.stringify(value)); + let result = Objects.assign(Object.create(null), value); + result._key = hash.digest('hex'); + return result; + } +} + +namespace TaskPresentationOptionsDTO { + export function from(value: PresentationOptions): TaskPresentationOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + return Objects.assign(Object.create(null), value); + } + export function to(value: TaskPresentationOptionsDTO): PresentationOptions { + if (value === void 0 || value === null) { + return undefined; + } + return Objects.assign(Object.create(null), value); + } +} + +namespace ProcessExecutionOptionsDTO { + export function from(value: CommandOptions): ProcessExecutionOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + return { + cwd: value.cwd, + env: value.env + }; + } + export function to(value: ProcessExecutionOptionsDTO): CommandOptions { + if (value === void 0 || value === null) { + return undefined; + } + return { + cwd: value.cwd, + env: value.env + }; + } +} + +namespace ProcessExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO { + let candidate = value as ProcessExecutionDTO; + return candidate && !!candidate.process; + } + export function from(value: CommandConfiguration): ProcessExecutionDTO { + let process: string = Types.isString(value.name) ? value.name : value.name.value; + let args: string[] = value.args ? value.args.map(value => Types.isString(value) ? value : value.value) : []; + let result: ProcessExecutionDTO = { + process: process, + args: args + }; + if (value.options) { + result.options = ProcessExecutionOptionsDTO.from(value.options); + } + return result; + } + export function to(value: ProcessExecutionDTO): CommandConfiguration { + let result: CommandConfiguration = { + runtime: RuntimeType.Process, + name: value.process, + args: value.args, + presentation: undefined + }; + if (value.options) { + result.options = ProcessExecutionOptionsDTO.to(value.options); + } + return result; + } +} + +namespace ShellExecutionOptionsDTO { + export function from(value: CommandOptions): ShellExecutionOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + let result: ShellExecutionOptionsDTO = { + cwd: value.cwd, + env: value.env + }; + if (value.shell) { + result.executable = value.shell.executable; + result.shellArgs = value.shell.args; + result.shellQuoting = value.shell.quoting; + } + return result; + } + export function to(value: ShellExecutionOptionsDTO): CommandOptions { + if (value === void 0 || value === null) { + return undefined; + } + let result: CommandOptions = { + cwd: value.cwd, + env: value.env + }; + if (value.executable) { + result.shell = { + executable: value.executable + }; + if (value.shellArgs) { + result.shell.args = value.shellArgs; + } + if (value.shellQuoting) { + result.shell.quoting = value.shellQuoting; + } + } + return result; + } +} + +namespace ShellExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO { + let candidate = value as ShellExecutionDTO; + return candidate && (!!candidate.commandLine || !!candidate.command); + } + export function from(value: CommandConfiguration): ShellExecutionDTO { + let result: ShellExecutionDTO = {}; + if (value.name && Types.isString(value.name) && (value.args === void 0 || value.args === null || value.args.length === 0)) { + result.commandLine = value.name; + } else { + result.command = value.name; + result.args = value.args; + } + if (value.options) { + result.options = ShellExecutionOptionsDTO.from(value.options); + } + return result; + } + export function to(value: ShellExecutionDTO): CommandConfiguration { + let result: CommandConfiguration = { + runtime: RuntimeType.Shell, + name: value.commandLine ? value.commandLine : value.command, + args: value.args, + presentation: undefined + }; + if (value.options) { + result.options = ShellExecutionOptionsDTO.to(value.options); + } + return result; + } +} + +namespace TaskSourceDTO { + export function from(value: TaskSource): TaskSourceDTO { + let result: TaskSourceDTO = { + label: value.label + }; + if (value.kind === TaskSourceKind.Extension) { + result.extensionId = value.extension; + if (value.workspaceFolder) { + result.scope = value.workspaceFolder.uri; + } else { + result.scope = value.scope; + } + } else if (value.kind === TaskSourceKind.Workspace) { + result.extensionId = '$core'; + result.scope = value.config.workspaceFolder.uri; + } + return result; + } + export function to(value: TaskSourceDTO, workspace: IWorkspaceContextService): ExtensionTaskSource { + let scope: TaskScope; + let workspaceFolder: IWorkspaceFolder; + if (value.scope === void 0) { + if (workspace.getWorkspace().folders.length === 0) { + scope = TaskScope.Global; + workspaceFolder = undefined; + } else { + scope = TaskScope.Folder; + workspaceFolder = workspace.getWorkspace().folders[0]; + } + } else if (typeof value.scope === 'number') { + scope = value.scope; + } else { + scope = TaskScope.Folder; + workspaceFolder = workspace.getWorkspaceFolder(URI.revive(value.scope)); + } + let result: ExtensionTaskSource = { + kind: TaskSourceKind.Extension, + label: value.label, + extension: value.extensionId, + scope, + workspaceFolder + }; + return result; + } +} + +namespace TaskHandleDTO { + export function is(value: any): value is TaskHandleDTO { + let candidate: TaskHandleDTO = value; + return candidate && Types.isString(candidate.id) && !!candidate.workspaceFolder; + } +} + +namespace TaskDTO { + export function from(task: Task): TaskDTO { + if (task === void 0 || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) { + return undefined; + } + let result: TaskDTO = { + _id: task._id, + name: task.name, + definition: TaskDefinitionDTO.from(Task.getTaskDefinition(task)), + source: TaskSourceDTO.from(task._source), + execution: undefined, + presentationOptions: task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined, + isBackground: task.isBackground, + problemMatchers: [], + hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false + }; + if (task.group) { + result.group = task.group; + } + if (task.command) { + if (task.command.runtime === RuntimeType.Process) { + result.execution = ProcessExecutionDTO.from(task.command); + } else if (task.command.runtime === RuntimeType.Shell) { + result.execution = ShellExecutionDTO.from(task.command); + } + } + if (task.problemMatchers) { + for (let matcher of task.problemMatchers) { + if (Types.isString(matcher)) { + result.problemMatchers.push(matcher); + } + } + } + return result; + } + + export function to(task: TaskDTO, workspace: IWorkspaceContextService): Task { + if (typeof task.name !== 'string') { + return undefined; + } + let command: CommandConfiguration; + if (ShellExecutionDTO.is(task.execution)) { + command = ShellExecutionDTO.to(task.execution); + } else if (ProcessExecutionDTO.is(task.execution)) { + command = ProcessExecutionDTO.to(task.execution); + } + if (!command) { + return undefined; + } + command.presentation = TaskPresentationOptionsDTO.to(task.presentationOptions); + command.presentation = Objects.assign(command.presentation || {}, { echo: true, reveal: RevealKind.Always, focus: false, panel: PanelKind.Shared }); + + let source = TaskSourceDTO.to(task.source, workspace); + + let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); + let definition = TaskDefinitionDTO.to(task.definition); + let id = `${task.source.extensionId}.${definition._key}`; + let result: ContributedTask = { + _id: id, // uuidMap.getUUID(identifier), + _source: source, + _label: label, + type: definition.type, + defines: definition, + name: task.name, + identifier: label, + group: task.group, + command: command, + isBackground: !!task.isBackground, + problemMatchers: task.problemMatchers.slice(), + hasDefinedMatchers: task.hasDefinedMatchers + }; + return result; + } +} + +namespace TaskFilterDTO { + export function from(value: TaskFilter): TaskFilterDTO { + return value; + } + export function to(value: TaskFilterDTO): TaskFilter { + return value; + } +} @extHostNamedCustomer(MainContext.MainThreadTask) export class MainThreadTask implements MainThreadTaskShape { @@ -28,6 +349,14 @@ export class MainThreadTask implements MainThreadTaskShape { ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTask); this._activeHandles = Object.create(null); + this._taskService.onDidStateChange((event: TaskEvent) => { + let task = event.__task; + if (event.kind === TaskEventKind.Start) { + this._proxy.$taskStarted(TaskExecutionDTO.from(Task.getTaskExecution(task))); + } else if (event.kind === TaskEventKind.End) { + this._proxy.$taskEnded(TaskExecutionDTO.from(Task.getTaskExecution(task))); + } + }); } public dispose(): void { @@ -63,4 +392,61 @@ export class MainThreadTask implements MainThreadTaskShape { delete this._activeHandles[handle]; return TPromise.wrap<void>(undefined); } + + public $fetchTasks(filter?: TaskFilterDTO): TPromise<TaskDTO[]> { + return this._taskService.tasks(TaskFilterDTO.to(filter)).then((tasks) => { + let result: TaskDTO[] = []; + for (let task of tasks) { + let item = TaskDTO.from(task); + if (item) { + result.push(item); + } + } + return result; + }); + } + + public $executeTask(value: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO> { + return new TPromise<TaskExecutionDTO>((resolve, reject) => { + if (TaskHandleDTO.is(value)) { + let workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder)); + this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task) => { + this._taskService.run(task); + let result: TaskExecutionDTO = { + id: value.id, + task: TaskDTO.from(task) + }; + resolve(result); + }, (error) => { + reject(new Error('Task not found')); + }); + } else { + let task = TaskDTO.to(value, this._workspaceContextServer); + this._taskService.run(task); + let result: TaskExecutionDTO = { + id: task._id, + task: TaskDTO.from(task) + }; + resolve(result); + } + }); + } + + public $terminateTask(id: string): TPromise<void> { + return new TPromise<void>((resolve, reject) => { + this._taskService.getActiveTasks().then((tasks) => { + for (let task of tasks) { + if (id === task._id) { + this._taskService.terminate(task).then((value) => { + resolve(undefined); + }, (error) => { + reject(undefined); + }); + return; + } + } + reject(new Error('Task to terminate not found')); + }); + }); + } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTelemetry.ts b/src/vs/workbench/api/electron-browser/mainThreadTelemetry.ts index ccbaf039fe..42b9a83ef2 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTelemetry.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTelemetry.ts @@ -25,7 +25,7 @@ export class MainThreadTelemetry implements MainThreadTelemetryShape { } $publicLog(eventName: string, data: any = Object.create(null)): void { - // __GDPR__COMMON__ "pluginHostTelemetry" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + // __GDPR__COMMON__ "pluginHostTelemetry" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } data[MainThreadTelemetry._name] = true; this._telemetryService.publicLog(eventName, data); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts b/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts index 4d1934f973..92ec0d4bbc 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTerminalService.ts @@ -5,25 +5,39 @@ 'use strict'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { ITerminalService, ITerminalInstance, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest } from 'vs/workbench/parts/terminal/common/terminal'; import { TPromise } from 'vs/base/common/winjs.base'; -import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; +import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; @extHostNamedCustomer(MainContext.MainThreadTerminalService) export class MainThreadTerminalService implements MainThreadTerminalServiceShape { private _proxy: ExtHostTerminalServiceShape; - private _toDispose: IDisposable[]; + private _toDispose: IDisposable[] = []; + private _terminalProcesses: { [id: number]: ITerminalProcessExtHostProxy } = {}; + private _dataListeners: { [id: number]: IDisposable } = {}; constructor( extHostContext: IExtHostContext, @ITerminalService private terminalService: ITerminalService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalService); - this._toDispose = []; - this._toDispose.push(terminalService.onInstanceDisposed((terminalInstance) => this._onTerminalDisposed(terminalInstance))); - this._toDispose.push(terminalService.onInstanceProcessIdReady((terminalInstance) => this._onTerminalProcessIdReady(terminalInstance))); + this._toDispose.push(terminalService.onInstanceCreated((terminalInstance) => { + // Delay this message so the TerminalInstance constructor has a chance to finish and + // return the ID normally to the extension host. The ID that is passed here will be used + // to register non-extension API terminals in the extension host. + setTimeout(() => this._onTerminalOpened(terminalInstance), 100); + })); + this._toDispose.push(terminalService.onInstanceDisposed(terminalInstance => this._onTerminalDisposed(terminalInstance))); + this._toDispose.push(terminalService.onInstanceProcessIdReady(terminalInstance => this._onTerminalProcessIdReady(terminalInstance))); + this._toDispose.push(terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request))); + + // Set initial ext host state + this.terminalService.terminalInstances.forEach(t => { + this._onTerminalOpened(t); + t.processReady.then(() => this._onTerminalProcessIdReady(t)); + }); } public dispose(): void { @@ -43,7 +57,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape ignoreConfigurationCwd: true, env }; - return TPromise.as(this.terminalService.createInstance(shellLaunchConfig).id); + return TPromise.as(this.terminalService.createTerminal(shellLaunchConfig).id); } public $show(terminalId: number, preserveFocus: boolean): void { @@ -74,11 +88,59 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape } } + public $registerOnDataListener(terminalId: number): void { + let terminalInstance = this.terminalService.getInstanceFromId(terminalId); + if (terminalInstance) { + this._dataListeners[terminalId] = terminalInstance.onData(data => this._onTerminalData(terminalId, data)); + terminalInstance.onDisposed(instance => delete this._dataListeners[terminalId]); + } + } + + private _onTerminalData(terminalId: number, data: string): void { + this._proxy.$acceptTerminalProcessData(terminalId, data); + } + private _onTerminalDisposed(terminalInstance: ITerminalInstance): void { this._proxy.$acceptTerminalClosed(terminalInstance.id); } + private _onTerminalOpened(terminalInstance: ITerminalInstance): void { + this._proxy.$acceptTerminalOpened(terminalInstance.id, terminalInstance.title); + } + private _onTerminalProcessIdReady(terminalInstance: ITerminalInstance): void { this._proxy.$acceptTerminalProcessId(terminalInstance.id, terminalInstance.processId); } + + private _onTerminalRequestExtHostProcess(request: ITerminalProcessExtHostRequest): void { + this._terminalProcesses[request.proxy.terminalId] = request.proxy; + const shellLaunchConfigDto: ShellLaunchConfigDto = { + name: request.shellLaunchConfig.name, + executable: request.shellLaunchConfig.executable, + args: request.shellLaunchConfig.args, + cwd: request.shellLaunchConfig.cwd, + env: request.shellLaunchConfig.env + }; + this._proxy.$createProcess(request.proxy.terminalId, shellLaunchConfigDto, request.cols, request.rows); + request.proxy.onInput(data => this._proxy.$acceptProcessInput(request.proxy.terminalId, data)); + request.proxy.onResize((cols, rows) => this._proxy.$acceptProcessResize(request.proxy.terminalId, cols, rows)); + request.proxy.onShutdown(() => this._proxy.$acceptProcessShutdown(request.proxy.terminalId)); + } + + public $sendProcessTitle(terminalId: number, title: string): void { + this._terminalProcesses[terminalId].emitTitle(title); + } + + public $sendProcessData(terminalId: number, data: string): void { + this._terminalProcesses[terminalId].emitData(data); + } + + public $sendProcessPid(terminalId: number, pid: number): void { + this._terminalProcesses[terminalId].emitPid(pid); + } + + public $sendProcessExit(terminalId: number, exitCode: number): void { + this._terminalProcesses[terminalId].emitExit(exitCode); + delete this._terminalProcesses[terminalId]; + } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts index f1a10bcc7a..5676a70953 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/base/common/lifecycle'; import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; -import { ITreeViewDataProvider, ITreeItem, ICustomViewsService } from 'vs/workbench/common/views'; +import { ITreeViewDataProvider, ITreeItem, IViewsService } from 'vs/workbench/common/views'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { distinct } from 'vs/base/common/arrays'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -21,7 +21,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie constructor( extHostContext: IExtHostContext, - @ICustomViewsService private viewsService: ICustomViewsService, + @IViewsService private viewsService: IViewsService, @INotificationService private notificationService: INotificationService ) { super(); @@ -31,7 +31,12 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie $registerTreeViewDataProvider(treeViewId: string): void { const dataProvider = this._register(new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService)); this._dataProviders.set(treeViewId, dataProvider); - this.viewsService.getTreeViewer(treeViewId).dataProvider = dataProvider; + const treeViewer = this.viewsService.getTreeViewer(treeViewId); + if (treeViewer) { + treeViewer.dataProvider = dataProvider; + } else { + this.notificationService.error('No view is registered with id: ' + treeViewId); + } } $reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void> { @@ -59,10 +64,10 @@ type TreeItemHandle = string; class TreeViewDataProvider implements ITreeViewDataProvider { - private _onDidChange: Emitter<ITreeItem[] | undefined | null> = new Emitter<ITreeItem[] | undefined | null>(); + private readonly _onDidChange: Emitter<ITreeItem[] | undefined | null> = new Emitter<ITreeItem[] | undefined | null>(); readonly onDidChange: Event<ITreeItem[] | undefined | null> = this._onDidChange.event; - private _onDispose: Emitter<void> = new Emitter<void>(); + private readonly _onDispose: Emitter<void> = new Emitter<void>(); readonly onDispose: Event<void> = this._onDispose.event; private itemsMap: Map<TreeItemHandle, ITreeItem> = new Map<TreeItemHandle, ITreeItem>(); @@ -87,8 +92,8 @@ class TreeViewDataProvider implements ITreeViewDataProvider { } refresh(itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }) { + const itemsToRefresh: ITreeItem[] = []; if (itemsToRefreshByHandle) { - const itemsToRefresh: ITreeItem[] = []; for (const treeItemHandle of Object.keys(itemsToRefreshByHandle)) { const currentTreeItem = this.itemsMap.get(treeItemHandle); if (currentTreeItem) { // Refresh only if the item exists @@ -101,13 +106,16 @@ class TreeViewDataProvider implements ITreeViewDataProvider { // Update maps when handle is changed and refresh parent this.itemsMap.delete(treeItemHandle); this.itemsMap.set(currentTreeItem.handle, currentTreeItem); - itemsToRefresh.push(this.itemsMap.get(treeItem.parentHandle)); + const parent = treeItem.parentHandle ? this.itemsMap.get(treeItem.parentHandle) : null; + if (parent) { + itemsToRefresh.push(parent); + } } } - if (itemsToRefresh.length) { - this._onDidChange.fire(itemsToRefresh); - } } + } + if (itemsToRefresh.length) { + this._onDidChange.fire(itemsToRefresh); } else { this._onDidChange.fire(); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadUrls.ts b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts new file mode 100644 index 0000000000..f0d80a3df7 --- /dev/null +++ b/src/vs/workbench/api/electron-browser/mainThreadUrls.ts @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ExtHostContext, IExtHostContext, MainContext, MainThreadUrlsShape, ExtHostUrlsShape } from 'vs/workbench/api/node/extHost.protocol'; +import { extHostNamedCustomer } from './extHostCustomers'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; +import URI from 'vs/base/common/uri'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; + +class ExtensionUrlHandler implements IURLHandler { + + constructor( + private readonly proxy: ExtHostUrlsShape, + private readonly handle: number, + readonly extensionId: string + ) { } + + handleURL(uri: URI): TPromise<boolean> { + if (uri.authority !== this.extensionId) { + return TPromise.as(false); + } + + return this.proxy.$handleExternalUri(this.handle, uri).then(() => true); + } +} + +@extHostNamedCustomer(MainContext.MainThreadUrls) +export class MainThreadUrls implements MainThreadUrlsShape { + + private readonly proxy: ExtHostUrlsShape; + private handlers = new Map<number, { extensionId: string, disposable: IDisposable }>(); + + constructor( + context: IExtHostContext, + @IURLService private urlService: IURLService, + @IExtensionUrlHandler private inactiveExtensionUrlHandler: IExtensionUrlHandler + ) { + this.proxy = context.getProxy(ExtHostContext.ExtHostUrls); + } + + $registerProtocolHandler(handle: number, extensionId: string): TPromise<void> { + const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId); + const disposable = this.urlService.registerHandler(handler); + + this.handlers.set(handle, { extensionId, disposable }); + this.inactiveExtensionUrlHandler.registerExtensionHandler(extensionId, handler); + + return TPromise.as(null); + } + + $unregisterProtocolHandler(handle: number): TPromise<void> { + const tuple = this.handlers.get(handle); + + if (!tuple) { + return TPromise.as(null); + } + + const { extensionId, disposable } = tuple; + + this.inactiveExtensionUrlHandler.unregisterExtensionHandler(extensionId); + this.handlers.delete(handle); + disposable.dispose(); + + return TPromise.as(null); + } + + dispose(): void { + this.handlers.forEach(({ disposable }) => disposable.dispose()); + this.handlers.clear(); + } +} diff --git a/src/vs/workbench/api/electron-browser/mainThreadWebview.ts b/src/vs/workbench/api/electron-browser/mainThreadWebview.ts index 2148783325..f4ffdcb84e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWebview.ts @@ -2,501 +2,117 @@ * 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 { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as map from 'vs/base/common/map'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { MainThreadWebviewsShape, MainContext, IExtHostContext, ExtHostContext, ExtHostWebviewsShape, WebviewHandle } from 'vs/workbench/api/node/extHost.protocol'; -import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; -import { extHostNamedCustomer } from './extHostCustomers'; -import { EditorInput, EditorModel, EditorOptions } from 'vs/workbench/common/editor'; -import { IEditorModel, Position } from 'vs/platform/editor/common/editor'; -import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { WebviewEditor as BaseWebviewEditor, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE } from 'vs/workbench/parts/html/browser/webviewEditor'; -import { Builder, Dimension } from 'vs/base/browser/builder'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { localize } from 'vs/nls'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; -import * as vscode from 'vscode'; -import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import URI from 'vs/base/common/uri'; -import DOM = require('vs/base/browser/dom'); -import Event, { Emitter } from 'vs/base/common/event'; - - -interface WebviewEvents { - onMessage(message: any): void; - onDidChangePosition(newPosition: Position): void; - onDispose(): void; - onDidClickLink(link: URI, options: vscode.WebviewOptions): void; -} - -class WebviewInput extends EditorInput { - private static handlePool = 0; - - private readonly _resource: URI; - private _name: string; - private _options: vscode.WebviewOptions; - private _html: string; - private _currentWebviewHtml: string = ''; - private _events: WebviewEvents | undefined; - private _container: HTMLElement; - private _webview: Webview | undefined; - private _webviewOwner: any; - private _webviewDisposables: IDisposable[] = []; - private _position: Position; - - - public static create( - resource: URI, - name: string, - position: Position, - options: vscode.WebviewOptions, - html: string, - events: WebviewEvents, - partService: IPartService - ): WebviewInput { - const id = WebviewInput.handlePool++; - const webviewContainer = document.createElement('div'); - webviewContainer.id = `webview-${id}`; - - partService.getContainer(Parts.EDITOR_PART).appendChild(webviewContainer); - - return new WebviewInput(resource, name, position, options, html, events, webviewContainer, undefined); - } - - constructor( - resource: URI, - name: string, - position: Position, - options: vscode.WebviewOptions, - html: string, - events: WebviewEvents, - container: HTMLElement, - webview: Webview | undefined - ) { - super(); - this._resource = resource; - this._name = name; - this._position = position; - this._options = options; - this._html = html; - this._events = events; - - this._container = container; - this._webview = webview; - } - - public getTypeId(): string { - return 'webview'; - } - - public dispose() { - this.disposeWebview(); - - if (this._container) { - this._container.remove(); - this._container = undefined; - } - - if (this._events) { - this._events.onDispose(); - this._events = undefined; - } - - super.dispose(); - } - - public getResource(): URI { - return this._resource; - } - - public getName(): string { - return this._name; - } - - public setName(value: string): void { - this._name = value; - this._onDidChangeLabel.fire(); - } - - public get position(): Position { - return this._position; - } - - public get html(): string { - return this._html; - } - - public setHtml(value: string): void { - if (value === this._currentWebviewHtml) { - return; - } - - this._html = value; - - if (this._webview) { - this._webview.contents = value; - this._currentWebviewHtml = value; - } - } - - public get options(): vscode.WebviewOptions { - return this._options; - } - - public set options(value: vscode.WebviewOptions) { - this._options = value; - } - - public resolve(refresh?: boolean): TPromise<IEditorModel, any> { - return TPromise.as(new EditorModel()); - } - - public supportsSplitEditor() { - return false; - } - - public get container(): HTMLElement { - return this._container; - } - - public get webview(): Webview | undefined { - return this._webview; - } - - public set webview(value: Webview) { - this._webviewDisposables = dispose(this._webviewDisposables); - - this._webview = value; - - this._webview.onDidClickLink(link => { - if (this._events) { - this._events.onDidClickLink(link, this._options); - } - }, null, this._webviewDisposables); - - this._webview.onMessage(message => { - if (this._events) { - this._events.onMessage(message); - } - }, null, this._webviewDisposables); - } - - public claimWebview(owner: any) { - this._webviewOwner = owner; - } - - public releaseWebview(owner: any) { - if (this._webviewOwner === owner) { - this._webviewOwner = undefined; - if (this._options.retainContextWhenHidden) { - this.container.style.visibility = 'hidden'; - } else { - this.disposeWebview(); - } - } - } - - public disposeWebview() { - // The input owns the webview and its parent - if (this._webview) { - this._webview.dispose(); - this._webview = undefined; - } - - this._webviewDisposables = dispose(this._webviewDisposables); - - this._webviewOwner = undefined; - this.container.style.visibility = 'hidden'; - - this._currentWebviewHtml = ''; - } - - public onDidChangePosition(position: Position) { - if (this._events) { - this._events.onDidChangePosition(position); - } - this._position = position; - } -} - -class WebviewEditor extends BaseWebviewEditor { - - public static readonly ID = 'WebviewEditor'; - - private editorFrame: HTMLElement; - private webviewContent: HTMLElement; - private _onDidFocusWebview: Emitter<void>; - private _webviewFocusTracker?: DOM.IFocusTracker; - private _webviewFocusListenerDisposable?: IDisposable; - - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService storageService: IStorageService, - @IThemeService themeService: IThemeService, - @IContextKeyService private _contextKeyService: IContextKeyService, - @IPartService private readonly _partService: IPartService, - @IContextViewService private readonly _contextViewService: IContextViewService, - @IEnvironmentService private readonly _environmentService: IEnvironmentService, - @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService - ) { - super(WebviewEditor.ID, telemetryService, themeService, storageService, _contextKeyService); - - this._onDidFocusWebview = new Emitter<void>(); - } - - protected createEditor(parent: Builder): void { - this.editorFrame = parent.getHTMLElement(); - this.content = document.createElement('div'); - parent.append(this.content); - } - - private doUpdateContainer() { - const webviewContainer = this.input && (this.input as WebviewInput).container; - if (webviewContainer) { - const frameRect = this.editorFrame.getBoundingClientRect(); - const containerRect = webviewContainer.parentElement.getBoundingClientRect(); - - webviewContainer.style.position = 'absolute'; - webviewContainer.style.top = `${frameRect.top - containerRect.top}px`; - webviewContainer.style.left = `${frameRect.left - containerRect.left}px`; - webviewContainer.style.width = `${frameRect.width}px`; - webviewContainer.style.height = `${frameRect.height}px`; - } - } - - public layout(dimension: Dimension): void { - if (this._webview) { - this.doUpdateContainer(); - } - super.layout(dimension); - } - - public dispose(): void { - // Let the editor input dispose of the webview. - this._webview = undefined; - this.webviewContent = undefined; - - this._onDidFocusWebview.dispose(); - - if (this._webviewFocusTracker) { - this._webviewFocusTracker.dispose(); - } - - if (this._webviewFocusListenerDisposable) { - this._webviewFocusListenerDisposable.dispose(); - } - - super.dispose(); - } - - public sendMessage(data: any): void { - if (this._webview) { - this._webview.sendMessage(data); - } - } - - public get onDidFocus(): Event<any> { - return this._onDidFocusWebview.event; - } - - protected setEditorVisible(visible: boolean, position?: Position): void { - if (this.input && this.input instanceof WebviewInput) { - if (visible) { - this.input.claimWebview(this); - } else { - this.input.releaseWebview(this); - } - - this.updateWebview(this.input as WebviewInput); - } - - if (this.webviewContent) { - if (visible) { - this.webviewContent.style.visibility = 'visible'; - this.doUpdateContainer(); - } else { - this.webviewContent.style.visibility = 'hidden'; - } - } - - super.setEditorVisible(visible, position); - } - - public clearInput() { - if (this.input && this.input instanceof WebviewInput) { - this.input.releaseWebview(this); - } - - this._webview = undefined; - this.webviewContent = undefined; - - super.clearInput(); - } - - async setInput(input: WebviewInput, options: EditorOptions): TPromise<void> { - if (this.input && this.input.matches(input)) { - return undefined; - } - - if (this.input && this.input.getResource().fsPath !== input.getResource().fsPath) { - (this.input as WebviewInput).releaseWebview(this); - this._webview = undefined; - this.webviewContent = undefined; - } - - await super.setInput(input, options); - - input.onDidChangePosition(this.position); - this.updateWebview(input); - } - - private updateWebview(input: WebviewInput) { - const webview = this.getWebview(input); - input.claimWebview(this); - webview.options = { - allowScripts: input.options.enableScripts, - enableWrappedPostMessage: true, - useSameOriginForRoot: false, - localResourceRoots: (input && input.options.localResourceRoots) || this._contextService.getWorkspace().folders.map(x => x.uri) - }; - input.setHtml(input.html); - this.webviewContent.style.visibility = 'visible'; - this.doUpdateContainer(); - } - - private getWebview(input: WebviewInput): Webview { - if (this._webview) { - return this._webview; - } - - this.webviewContent = input.container; - const existing = input.webview; - if (existing) { - this._webview = existing; - return existing; - } - - this._webviewFocusTracker = DOM.trackFocus(this.webviewContent); - this._webviewFocusListenerDisposable = this._webviewFocusTracker.onDidFocus(() => { - this._onDidFocusWebview.fire(); - }); - - this._contextKeyService = this._contextKeyService.createScoped(this.webviewContent); - this.contextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS.bindTo(this._contextKeyService); - this.findInputFocusContextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED.bindTo(this._contextKeyService); - this.findWidgetVisible = KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE.bindTo(this._contextKeyService); - - this._webview = new Webview( - this.webviewContent, - this._partService.getContainer(Parts.EDITOR_PART), - this.themeService, - this._environmentService, - this._contextViewService, - this.contextKey, - this.findInputFocusContextKey, - { - enableWrappedPostMessage: true, - useSameOriginForRoot: false - }); - input.webview = this._webview; - - this.content.setAttribute('aria-flowto', this.webviewContent.id); - - this.doUpdateContainer(); - return this._webview; - } -} - +import { TPromise } from 'vs/base/common/winjs.base'; +import { localize } from 'vs/nls'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { Position } from 'vs/platform/editor/common/editor'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle } from 'vs/workbench/api/node/extHost.protocol'; +import { WebviewEditor } from 'vs/workbench/parts/webview/electron-browser/webviewEditor'; +import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput'; +import { IWebviewEditorService, WebviewInputOptions, WebviewReviver } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; +import { extHostNamedCustomer } from './extHostCustomers'; @extHostNamedCustomer(MainContext.MainThreadWebviews) -export class MainThreadWebviews implements MainThreadWebviewsShape { +export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviver { + + private static readonly serializeTimeout = 500; // ms + + private static readonly viewType = 'mainThreadWebview'; + private static readonly standardSupportedLinkSchemes = ['http', 'https', 'mailto']; - private _toDispose: Disposable[] = []; + private static revivalPool = 0; + + private _toDispose: IDisposable[] = []; private readonly _proxy: ExtHostWebviewsShape; - private readonly _webviews = new Map<WebviewHandle, WebviewInput>(); + private readonly _webviews = new Map<WebviewPanelHandle, WebviewEditorInput>(); + private readonly _revivers = new Set<string>(); - private _activeWebview: WebviewInput | undefined = undefined; + private _activeWebview: WebviewPanelHandle | undefined = undefined; constructor( context: IExtHostContext, - @IContextKeyService _contextKeyService: IContextKeyService, - @IPartService private readonly _partService: IPartService, + @IContextKeyService contextKeyService: IContextKeyService, + @IEditorGroupService editorGroupService: IEditorGroupService, + @ILifecycleService lifecycleService: ILifecycleService, @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, - @IEditorGroupService private readonly _editorGroupService: IEditorGroupService, - @IOpenerService private readonly _openerService: IOpenerService + @IWebviewEditorService private readonly _webviewService: IWebviewEditorService, + @IOpenerService private readonly _openerService: IOpenerService, + @IExtensionService private readonly _extensionService: IExtensionService, + ) { this._proxy = context.getProxy(ExtHostContext.ExtHostWebviews); - _editorGroupService.onEditorsChanged(this.onEditorsChanged, this, this._toDispose); + editorGroupService.onEditorsChanged(this.onEditorsChanged, this, this._toDispose); + editorGroupService.onEditorGroupMoved(this.onEditorGroupMoved, this, this._toDispose); + + this._toDispose.push(_webviewService.registerReviver(MainThreadWebviews.viewType, this)); + + lifecycleService.onWillShutdown(e => { + e.veto(this._onWillShutdown()); + }, this, this._toDispose); } dispose(): void { this._toDispose = dispose(this._toDispose); } - $createWebview(handle: WebviewHandle, uri: URI, title: string, column: Position, options: vscode.WebviewOptions): void { - const webviewInput = WebviewInput.create(URI.revive(uri), title, column, options, '', { - onMessage: message => this._proxy.$onMessage(handle, message), - onDidChangePosition: position => this._proxy.$onDidChangePosition(handle, position), - onDispose: () => { - this._proxy.$onDidDisposeWeview(handle).then(() => { - this._webviews.delete(handle); - }); - }, - onDidClickLink: (link, options) => this.onDidClickLink(link, options) - }, this._partService); + $createWebviewPanel( + handle: WebviewPanelHandle, + viewType: string, + title: string, + column: Position, + options: WebviewInputOptions, + extensionFolderPath: string + ): void { + const webview = this._webviewService.createWebview(MainThreadWebviews.viewType, title, column, options, extensionFolderPath, this.createWebviewEventDelegate(handle)); + webview.state = { + viewType: viewType, + state: undefined + }; - this._webviews.set(handle, webviewInput); - - this._editorService.openEditor(webviewInput, { pinned: true }, column); + this._webviews.set(handle, webview); + this._activeWebview = handle; } - $disposeWebview(handle: WebviewHandle): void { + $disposeWebview(handle: WebviewPanelHandle): void { const webview = this.getWebview(handle); - if (webview) { - this._editorService.closeEditor(webview.position, webview); - } + webview.dispose(); } - $setTitle(handle: WebviewHandle, value: string): void { + $setTitle(handle: WebviewPanelHandle, value: string): void { const webview = this.getWebview(handle); webview.setName(value); } - $setHtml(handle: WebviewHandle, value: string): void { + $setHtml(handle: WebviewPanelHandle, value: string): void { const webview = this.getWebview(handle); - webview.setHtml(value); + webview.html = value; } - $show(handle: WebviewHandle, column: Position): void { - const webviewInput = this.getWebview(handle); - if (webviewInput.position === column) { - this._editorService.openEditor(webviewInput, { preserveFocus: true }, column); - } else { - this._editorGroupService.moveEditor(webviewInput, webviewInput.position, column, { preserveFocus: true }); + $reveal(handle: WebviewPanelHandle, column: Position | null): void { + const webview = this.getWebview(handle); + if (webview.isDisposed()) { + return; } + + this._webviewService.revealWebview(webview, column); } - async $sendMessage(handle: WebviewHandle, message: any): Promise<boolean> { - const webviewInput = this.getWebview(handle); + async $postMessage(handle: WebviewPanelHandle, message: any): TPromise<boolean> { + const webview = this.getWebview(handle); const editors = this._editorService.getVisibleEditors() .filter(e => e instanceof WebviewEditor) .map(e => e as WebviewEditor) - .filter(e => e.input.matches(webviewInput)); + .filter(e => e.input.matches(webview)); for (const editor of editors) { editor.sendMessage(message); @@ -505,18 +121,91 @@ export class MainThreadWebviews implements MainThreadWebviewsShape { return (editors.length > 0); } - private getWebview(handle: number): WebviewInput { - const webviewInput = this._webviews.get(handle); - if (!webviewInput) { + $registerSerializer(viewType: string): void { + this._revivers.add(viewType); + } + + $unregisterSerializer(viewType: string): void { + this._revivers.delete(viewType); + } + + reviveWebview(webview: WebviewEditorInput): TPromise<void> { + const viewType = webview.state.viewType; + return this._extensionService.activateByEvent(`onView:${viewType}`).then(() => { + const handle = 'revival-' + MainThreadWebviews.revivalPool++; + this._webviews.set(handle, webview); + webview._events = this.createWebviewEventDelegate(handle); + + return this._proxy.$deserializeWebviewPanel(handle, webview.state.viewType, webview.getTitle(), webview.state.state, webview.position, webview.options) + .then(undefined, () => { + webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType); + }); + }); + } + + canRevive(webview: WebviewEditorInput): boolean { + if (webview.isDisposed()) { + return false; + } + + return this._revivers.has(webview.viewType) || webview.reviver !== null; + } + + private _onWillShutdown(): TPromise<boolean> { + const toRevive: WebviewPanelHandle[] = []; + this._webviews.forEach((view, key) => { + if (this.canRevive(view)) { + toRevive.push(key); + } + }); + + const reviveResponses = toRevive.map(handle => + TPromise.any([ + this._proxy.$serializeWebviewPanel(handle).then( + state => ({ handle, state }), + () => ({ handle, state: null })), + TPromise.timeout(MainThreadWebviews.serializeTimeout).then(() => ({ handle, state: null })) + ]).then(x => x.value)); + + return TPromise.join(reviveResponses).then(results => { + for (const result of results) { + const view = this._webviews.get(result.handle); + if (view) { + if (result.state) { + view.state.state = result.state; + } else { + view.state = null; + } + } + } + return false; // Don't veto shutdown + }); + } + + private createWebviewEventDelegate(handle: WebviewPanelHandle) { + return { + onDidClickLink: uri => this.onDidClickLink(handle, uri), + onMessage: message => this._proxy.$onMessage(handle, message), + onDispose: () => { + this._proxy.$onDidDisposeWebviewPanel(handle).then( + () => this._webviews.delete(handle), + () => this._webviews.delete(handle)); + } + }; + } + + private getWebview(handle: WebviewPanelHandle): WebviewEditorInput { + const webview = this._webviews.get(handle); + if (!webview) { throw new Error('Unknown webview handle:' + handle); } - return webviewInput; + return webview; } private onEditorsChanged() { const activeEditor = this._editorService.getActiveEditor(); - let newActiveWebview: { input: WebviewInput, handle: WebviewHandle } | undefined = undefined; - if (activeEditor && activeEditor.input instanceof WebviewInput) { + let newActiveWebview: { input: WebviewEditorInput, handle: WebviewPanelHandle } | undefined = undefined; + if (activeEditor && activeEditor.input instanceof WebviewEditorInput) { for (const handle of map.keys(this._webviews)) { const input = this._webviews.get(handle); if (input.matches(activeEditor.input)) { @@ -526,33 +215,64 @@ export class MainThreadWebviews implements MainThreadWebviewsShape { } } + if (newActiveWebview && newActiveWebview.handle === this._activeWebview) { + // Webview itself unchanged but position may have changed + this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, newActiveWebview.input.position); + return; + } + + // Broadcast view state update for currently active + if (typeof this._activeWebview !== 'undefined') { + const oldActiveWebview = this._webviews.get(this._activeWebview); + if (oldActiveWebview) { + this._proxy.$onDidChangeWebviewPanelViewState(this._activeWebview, false, oldActiveWebview.position); + } + } + + // Then for newly active if (newActiveWebview) { - if (!this._activeWebview || !newActiveWebview.input.matches(this._activeWebview)) { - this._proxy.$onDidChangeActiveWeview(newActiveWebview.handle); - this._activeWebview = newActiveWebview.input; - } + this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, activeEditor.position); + this._activeWebview = newActiveWebview.handle; } else { - if (this._activeWebview) { - this._proxy.$onDidChangeActiveWeview(undefined); - this._activeWebview = undefined; - } + this._activeWebview = undefined; } } - private onDidClickLink(link: URI, options: vscode.WebviewOptions): void { + private onEditorGroupMoved(): void { + for (const workbenchEditor of this._editorService.getVisibleEditors()) { + if (!workbenchEditor.input) { + return; + } + + this._webviews.forEach((input, handle) => { + if (workbenchEditor.input.matches(input) && input.position !== workbenchEditor.position) { + input.updatePosition(workbenchEditor.position); + this._proxy.$onDidChangeWebviewPanelViewState(handle, handle === this._activeWebview, workbenchEditor.position); + } + }); + } + } + private onDidClickLink(handle: WebviewPanelHandle, link: URI): void { if (!link) { return; } - const enableCommandUris = options.enableCommandUris; + const webview = this.getWebview(handle); + const enableCommandUris = webview.options.enableCommandUris; if (MainThreadWebviews.standardSupportedLinkSchemes.indexOf(link.scheme) >= 0 || enableCommandUris && link.scheme === 'command') { this._openerService.open(link); } } -} -(<IEditorRegistry>Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( - WebviewEditor, - WebviewEditor.ID, - localize('webview.editor.label', "webview editor")), - [new SyncDescriptor(WebviewInput)]); + private static getDeserializationFailedContents(viewType: string) { + return `<!DOCTYPE html> + <html> + <head> + <base href="https://code.visualstudio.com/raw/"> + <meta http-equiv="Content-type" content="text/html;charset=UTF-8"> + <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: data:; media-src https:; script-src 'none'; style-src vscode-core-resource: https: 'unsafe-inline'; child-src 'none'; frame-src 'none';"> + </head> + <body>${localize('errorMessage', "An error occurred while restoring view:{0}", viewType)}</body> + </html>`; + } +} diff --git a/src/vs/workbench/api/electron-browser/mainThreadWindow.ts b/src/vs/workbench/api/electron-browser/mainThreadWindow.ts index b3403b0a48..38628cf08b 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWindow.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWindow.ts @@ -9,6 +9,7 @@ import { IWindowService } from 'vs/platform/windows/common/windows'; import { MainThreadWindowShape, ExtHostWindowShape, ExtHostContext, MainContext, IExtHostContext } from '../node/extHost.protocol'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { latch } from 'vs/base/common/event'; @extHostNamedCustomer(MainContext.MainThreadWindow) export class MainThreadWindow implements MainThreadWindowShape { @@ -22,7 +23,8 @@ export class MainThreadWindow implements MainThreadWindowShape { ) { this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostWindow); - windowService.onDidChangeFocus(this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables); + latch(windowService.onDidChangeFocus) + (this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables); } $getWindowVisibility(): TPromise<boolean> { diff --git a/src/vs/workbench/api/node/apiCommands.ts b/src/vs/workbench/api/node/apiCommands.ts new file mode 100644 index 0000000000..63117c78cb --- /dev/null +++ b/src/vs/workbench/api/node/apiCommands.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * 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 URI from 'vs/base/common/uri'; +import * as vscode from 'vscode'; +import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters'; +import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands'; +import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor'; + +// ----------------------------------------------------------------- +// The following commands are registered on both sides separately. +// +// We are trying to maintain backwards compatibility for cases where +// API commands are encoded as markdown links, for example. +// ----------------------------------------------------------------- + +export interface ICommandsExecutor { + executeCommand<T>(id: string, ...args: any[]): Thenable<T>; +} + +function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler { + return (accessor, ...args: any[]) => { + return handler(accessor.get(ICommandService), ...args); + }; +} + +export class PreviewHTMLAPICommand { + public static ID = 'vscode.previewHtml'; + public static execute(executor: ICommandsExecutor, uri: URI, position?: vscode.ViewColumn, label?: string, options?: any): Thenable<any> { + return executor.executeCommand('_workbench.previewHtml', + uri, + typeof position === 'number' && typeConverters.fromViewColumn(position), + label, + options + ); + } +} +CommandsRegistry.registerCommand(PreviewHTMLAPICommand.ID, adjustHandler(PreviewHTMLAPICommand.execute)); + +export class OpenFolderAPICommand { + public static ID = 'vscode.openFolder'; + public static execute(executor: ICommandsExecutor, uri?: URI, forceNewWindow?: boolean): Thenable<any> { + if (!uri) { + return executor.executeCommand('_files.pickFolderAndOpen', forceNewWindow); + } + + return executor.executeCommand('_files.windowOpen', [uri.fsPath], forceNewWindow); + } +} +CommandsRegistry.registerCommand(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute)); + +export class DiffAPICommand { + public static ID = 'vscode.diff'; + public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions): Thenable<any> { + return executor.executeCommand('_workbench.diff', [ + left, right, + label, + undefined, + typeConverters.toTextEditorOptions(options), + options ? typeConverters.fromViewColumn(options.viewColumn) : undefined + ]); + } +} +CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute)); + +export class OpenAPICommand { + public static ID = 'vscode.open'; + public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions): Thenable<any> { + let options: ITextEditorOptions; + let column: EditorPosition; + + if (columnOrOptions) { + if (typeof columnOrOptions === 'number') { + column = typeConverters.fromViewColumn(columnOrOptions); + } else { + options = typeConverters.toTextEditorOptions(columnOrOptions); + column = typeConverters.fromViewColumn(columnOrOptions.viewColumn); + } + } + + return executor.executeCommand('_workbench.open', [ + resource, + options, + column + ]); + } +} +CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute)); + +export class RemoveFromRecentlyOpenedAPICommand { + public static ID = 'vscode.removeFromRecentlyOpened'; + public static execute(executor: ICommandsExecutor, path: string): Thenable<any> { + return executor.executeCommand('_workbench.removeFromRecentlyOpened', path); + } +} +CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute)); diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 904eecb615..27403e2f7b 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -46,6 +46,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import * as vscode from 'vscode'; import * as paths from 'vs/base/common/paths'; +import * as files from 'vs/platform/files/common/files'; import { MainContext, ExtHostContext, IInitData, IExtHostContext } from './extHost.protocol'; import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration'; import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions'; @@ -55,10 +56,11 @@ import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem'; import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations'; import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters'; import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionActivator'; -import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { OverviewRulerLane } from 'vs/editor/common/model'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview'; +import { ExtHostSearch } from './extHostSearch'; +import { ExtHostUrls } from './extHostUrls'; export interface IExtensionApiFactory { (extension: IExtensionDescription): typeof vscode; @@ -99,9 +101,10 @@ export function createApiFactory( const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService()); const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol)); const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol)); - const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol, extHostWebviews)); + const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol)); + const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol)); const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors)); - const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors)); + const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService)); const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadTextEditors))); const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors)); const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService)); @@ -111,15 +114,17 @@ export function createApiFactory( //const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace)); rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration); const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol)); - const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics)); + const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics)); const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures)); const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService()); const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands)); - const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol)); + const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService)); const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService)); + const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol)); const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace)); const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol)); rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService); + const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress))); // Check that no named customers are missing const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]); @@ -129,44 +134,51 @@ export function createApiFactory( const extHostMessageService = new ExtHostMessageService(rpcProtocol); const extHostDialogs = new ExtHostDialogs(rpcProtocol); const extHostStatusBar = new ExtHostStatusBar(rpcProtocol); - const extHostProgress = new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)); const extHostOutputService = new ExtHostOutputService(rpcProtocol); const extHostLanguages = new ExtHostLanguages(rpcProtocol); // Register API-ish commands - ExtHostApiCommands.register(extHostCommands); + ExtHostApiCommands.register(extHostCommands, extHostTask); return function (extension: IExtensionDescription): typeof vscode { - if (!isFalsyOrEmpty(product.extensionAllowedProposedApi) - && product.extensionAllowedProposedApi.indexOf(extension.id) >= 0 - ) { - // fast lane -> proposed api is available to all extensions - // that are listed in product.json-files - extension.enableProposedApi = true; - - } else if (extension.enableProposedApi && !extension.isBuiltin) { - if ( - !initData.environment.enableProposedApiForAll && - initData.environment.enableProposedApiFor.indexOf(extension.id) < 0 - ) { - extension.enableProposedApi = false; - console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`); - - } else { - // proposed api is available when developing or when an extension was explicitly - // spelled out via a command line argument - console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`); + // Check document selectors for being overly generic. Technically this isn't a problem but + // in practice many extensions say they support `fooLang` but need fs-access to do so. Those + // extension should specify then the `file`-scheme, e.g `{ scheme: 'fooLang', language: 'fooLang' }` + // We only inform once, it is not a warning because we just want to raise awareness and because + // we cannot say if the extension is doing it right or wrong... + let checkSelector = (function () { + let done = initData.environment.extensionDevelopmentPath !== extension.extensionFolderPath; + function informOnce(selector: vscode.DocumentSelector) { + if (!done) { + console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`); + done = true; + } } - } + return function perform(selector: vscode.DocumentSelector): vscode.DocumentSelector { + if (Array.isArray(selector)) { + selector.forEach(perform); + } else if (typeof selector === 'string') { + informOnce(selector); + } else { + if (typeof selector.scheme === 'undefined') { + informOnce(selector); + } + if (!extension.enableProposedApi && typeof selector.exclusive === 'boolean') { + throwProposedApiError(extension); + } + } + return selector; + }; + })(); // namespace: commands const commands: typeof vscode.commands = { registerCommand(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable { - return extHostCommands.registerCommand(id, command, thisArgs); + return extHostCommands.registerCommand(true, id, command, thisArgs); }, registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable { - return extHostCommands.registerCommand(id, (...args: any[]): any => { + return extHostCommands.registerCommand(true, id, (...args: any[]): any => { let activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); @@ -187,7 +199,7 @@ export function createApiFactory( }); }, registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => { - return extHostCommands.registerCommand(id, async (...args: any[]) => { + return extHostCommands.registerCommand(true, id, async (...args: any[]) => { let activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); @@ -213,6 +225,7 @@ export function createApiFactory( get language() { return Platform.language; }, get appName() { return product.nameLong; }, get appRoot() { return initData.environment.appRoot; }, + get logLevel() { return extHostLogService.getLevel(); } }); // namespace: extensions @@ -234,69 +247,75 @@ export function createApiFactory( createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { return extHostDiagnostics.createDiagnosticCollection(name); }, + get onDidChangeDiagnostics() { + return extHostDiagnostics.onDidChangeDiagnostics; + }, + getDiagnostics: (resource?) => { + return <any>extHostDiagnostics.getDiagnostics(resource); + }, getLanguages(): TPromise<string[]> { return extHostLanguages.getLanguages(); }, match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number { - return score(toLanguageSelector(selector), document.uri, document.languageId); + return score(toLanguageSelector(selector), document.uri, document.languageId, true); }, - registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable { - return extHostLanguageFeatures.registerCodeActionProvider(selector, provider); + registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable { + return extHostLanguageFeatures.registerCodeActionProvider(checkSelector(selector), provider, metadata); }, registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { - return extHostLanguageFeatures.registerCodeLensProvider(selector, provider); + return extHostLanguageFeatures.registerCodeLensProvider(checkSelector(selector), provider); }, registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDefinitionProvider(selector, provider); + return extHostLanguageFeatures.registerDefinitionProvider(checkSelector(selector), provider); }, registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable { - return extHostLanguageFeatures.registerImplementationProvider(selector, provider); + return extHostLanguageFeatures.registerImplementationProvider(checkSelector(selector), provider); }, registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable { - return extHostLanguageFeatures.registerTypeDefinitionProvider(selector, provider); + return extHostLanguageFeatures.registerTypeDefinitionProvider(checkSelector(selector), provider); }, registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { - return extHostLanguageFeatures.registerHoverProvider(selector, provider, extension.id); + return extHostLanguageFeatures.registerHoverProvider(checkSelector(selector), provider, extension.id); }, registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentHighlightProvider(selector, provider); + return extHostLanguageFeatures.registerDocumentHighlightProvider(checkSelector(selector), provider); }, registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { - return extHostLanguageFeatures.registerReferenceProvider(selector, provider); + return extHostLanguageFeatures.registerReferenceProvider(checkSelector(selector), provider); }, registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { - return extHostLanguageFeatures.registerRenameProvider(selector, provider, extension.enableProposedApi); + return extHostLanguageFeatures.registerRenameProvider(checkSelector(selector), provider); }, registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentSymbolProvider(selector, provider); + return extHostLanguageFeatures.registerDocumentSymbolProvider(checkSelector(selector), provider); }, registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { return extHostLanguageFeatures.registerWorkspaceSymbolProvider(provider); }, registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentFormattingEditProvider(selector, provider); + return extHostLanguageFeatures.registerDocumentFormattingEditProvider(checkSelector(selector), provider); }, registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider); + return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(checkSelector(selector), provider); }, registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable { - return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); + return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(checkSelector(selector), provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); }, registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable { - return extHostLanguageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters); + return extHostLanguageFeatures.registerSignatureHelpProvider(checkSelector(selector), provider, triggerCharacters); }, registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable { - return extHostLanguageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters); + return extHostLanguageFeatures.registerCompletionItemProvider(checkSelector(selector), provider, triggerCharacters); }, registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentLinkProvider(selector, provider); + return extHostLanguageFeatures.registerDocumentLinkProvider(checkSelector(selector), provider); }, registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable { - return extHostLanguageFeatures.registerColorProvider(selector, provider); + return extHostLanguageFeatures.registerColorProvider(checkSelector(selector), provider); + }, + registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable { + return extHostLanguageFeatures.registerFoldingRangeProvider(checkSelector(selector), provider); }, - registerFoldingProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable => { - return extHostLanguageFeatures.registerFoldingProvider(selector, provider); - }), setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => { return extHostLanguageFeatures.setLanguageConfiguration(language, configuration); } @@ -310,6 +329,9 @@ export function createApiFactory( get visibleTextEditors() { return extHostEditors.getVisibleTextEditors(); }, + get terminals() { + return proposedApiFunction(extension, extHostTerminalService.terminals); + }, showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> { let documentPromise: TPromise<vscode.TextDocument>; if (URI.isUri(documentOrUri)) { @@ -336,15 +358,18 @@ export function createApiFactory( onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) { return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables); }, - onDidChangeTextEditorVisibleRanges: proposedApiFunction(extension, (listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => { + onDidChangeTextEditorVisibleRanges(listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) { return extHostEditors.onDidChangeTextEditorVisibleRanges(listener, thisArgs, disposables); - }), + }, onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) { return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables); }, onDidCloseTerminal(listener, thisArg?, disposables?) { return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables); }, + onDidOpenTerminal: proposedApiFunction(extension, (listener, thisArg?, disposables?) => { + return extHostTerminalService.onDidOpenTerminal(listener, thisArg, disposables); + }), get state() { return extHostWindow.state; }, @@ -360,7 +385,7 @@ export function createApiFactory( showErrorMessage(message, first, ...rest) { return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest); }, - showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) { + showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken): any { return extHostQuickOpen.showQuickPick(items, options, token); }, showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) { @@ -385,20 +410,26 @@ export function createApiFactory( console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`); return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } })); }, - withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) { + withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) { return extHostProgress.withProgress(extension, options, task); }, createOutputChannel(name: string): vscode.OutputChannel { return extHostOutputService.createOutputChannel(name); }, + createWebviewPanel(viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel { + return extHostWebviews.createWebview(viewType, title, column, options, extension.extensionFolderPath); + }, createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { if (typeof nameOrOptions === 'object') { return extHostTerminalService.createTerminalFromOptions(<vscode.TerminalOptions>nameOrOptions); } return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs); }, - registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.TreeView<any> { - return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, (fn) => proposedApiFunction(extension, fn)); + registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable { + return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider); + }, + createTreeView(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<any> }): vscode.TreeView<any> { + return extHostTreeViews.createTreeView(viewId, options); }, // proposed API sampleFunction: proposedApiFunction(extension, () => { @@ -407,12 +438,11 @@ export function createApiFactory( registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => { return extHostDecorations.registerDecorationProvider(provider, extension.id); }), - // {{SQL CARBON EDIT}} - createWebview(uri: vscode.Uri, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions): vscode.Webview { - return extHostWebviews.createWebview(uri, title, column, options); - }, - onDidChangeActiveEditor: proposedApiFunction(extension, (listener, thisArg?, disposables?) => { - return extHostDocumentsAndEditors.onDidChangeActiveEditor(listener, thisArg, disposables); + registerWebviewPanelSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewPanelSerializer) => { + return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer); + }), + registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => { + return extHostUrls.registerProtocolHandler(extension.id, handler); }) }; @@ -512,8 +542,29 @@ export function createApiFactory( registerTaskProvider: (type: string, provider: vscode.TaskProvider) => { return extHostTask.registerTaskProvider(extension, provider); }, - registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => { - return extHostFileSystem.registerFileSystemProvider(authority, provider); + fetchTasks: proposedApiFunction(extension, (filter?: vscode.TaskFilter): Thenable<vscode.Task[]> => { + return extHostTask.fetchTasks(filter); + }), + executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => { + return extHostTask.executeTask(extension, task); + }), + get taskExecutions(): vscode.TaskExecution[] { + return extHostTask.taskExecutions; + }, + onDidStartTask: (listeners, thisArgs?, disposables?) => { + return extHostTask.onDidStartTask(listeners, thisArgs, disposables); + }, + onDidEndTask: (listeners, thisArgs?, disposables?) => { + return extHostTask.onDidEndTask(listeners, thisArgs, disposables); + }, + registerFileSystemProvider(scheme, provider, options) { + return extHostFileSystem.registerFileSystemProvider(scheme, provider, options); + }, + registerDeprecatedFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => { + return extHostFileSystem.registerDeprecatedFileSystemProvider(scheme, provider); + }), + registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => { + return extHostSearch.registerSearchProvider(scheme, provider); }) }; @@ -559,6 +610,7 @@ export function createApiFactory( // {{SQL CARBON EDIT}} // DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable, Diagnostic: extHostTypes.Diagnostic, + DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation, DiagnosticSeverity: extHostTypes.DiagnosticSeverity, Disposable: extHostTypes.Disposable, DocumentHighlight: extHostTypes.DocumentHighlight, @@ -582,6 +634,12 @@ export function createApiFactory( SourceBreakpoint: extHostTypes.SourceBreakpoint, StatusBarAlignment: extHostTypes.StatusBarAlignment, SymbolInformation: extHostTypes.SymbolInformation, + HierarchicalSymbolInformation: class extends extHostTypes.HierarchicalSymbolInformation { + constructor(name, kind, keyof, range) { + checkProposedApiEnabled(extension); + super(name, kind, keyof, range); + } + }, SymbolKind: extHostTypes.SymbolKind, SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType, TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason, @@ -605,16 +663,19 @@ export function createApiFactory( TaskGroup: extHostTypes.TaskGroup, ProcessExecution: extHostTypes.ProcessExecution, ShellExecution: extHostTypes.ShellExecution, + ShellQuoting: extHostTypes.ShellQuoting, TaskScope: extHostTypes.TaskScope, Task: extHostTypes.Task, ConfigurationTarget: extHostTypes.ConfigurationTarget, RelativePattern: extHostTypes.RelativePattern, + DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType, + DeprecatedFileType: extHostTypes.DeprecatedFileType, FileChangeType: extHostTypes.FileChangeType, - FileType: extHostTypes.FileType, - FoldingRangeList: extHostTypes.FoldingRangeList, + FileType: files.FileType, + FileSystemError: extHostTypes.FileSystemError, FoldingRange: extHostTypes.FoldingRange, - FoldingRangeType: extHostTypes.FoldingRangeType + FoldingRangeKind: extHostTypes.FoldingRangeKind }; }; } @@ -643,7 +704,7 @@ class Extension<T> implements vscode.Extension<T> { } activate(): Thenable<T> { - return this._extensionService.activateById(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports); + return this._extensionService.activateByIdWithErrors(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports); } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 0f0d457e7d..340659f846 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -24,7 +24,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; -import { IConfig, IAdapterExecutable } from 'vs/workbench/parts/debug/common/debug'; +import { IConfig, IAdapterExecutable, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug'; import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -42,22 +42,19 @@ import { ITreeItem } from 'vs/workbench/common/views'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { IDisposable } from 'vs/base/common/lifecycle'; import { SerializedError } from 'vs/base/common/errors'; -import { IStat, FileChangeType } from 'vs/platform/files/common/files'; +import { IStat, FileChangeType, IWatchOptions, FileSystemProviderCapabilities, FileWriteOptions, FileType, FileOverwriteOptions } from 'vs/platform/files/common/files'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/languageConfiguration'; import { ISingleEditOperation } from 'vs/editor/common/model'; import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search'; import { LogLevel } from 'vs/platform/log/common/log'; +import { TaskExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO } from 'vs/workbench/api/shared/tasks'; export interface IEnvironment { isExtensionDevelopmentDebug: boolean; - enableProposedApiForAll: boolean; - enableProposedApiFor: string | string[]; appRoot: string; appSettingsHome: string; disableExtensions: boolean; - userExtensionsHome: string; extensionDevelopmentPath: string; extensionTestsPath: string; } @@ -77,9 +74,8 @@ export interface IInitData { configuration: IConfigurationInitData; telemetryInfo: ITelemetryInfo; windowId: number; - args: ParsedArgs; - execPath: string; logLevel: LogLevel; + logsPath: string; } export interface IConfigurationInitData extends IConfigurationData { @@ -257,28 +253,36 @@ export interface ISerializedLanguageConfiguration { }; } +export interface ISerializedDocumentFilter { + $serialized: true; + language?: string; + scheme?: string; + pattern?: vscode.GlobPattern; + exclusive?: boolean; +} + export interface MainThreadLanguageFeaturesShape extends IDisposable { $unregister(handle: number): void; - $registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): void; + $registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void; $emitCodeLensEvent(eventHandle: number, event?: any): void; - $registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerHoverProvider(handle: number, selector: vscode.DocumentSelector): void; - $registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): void; - $registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): void; - $registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): void; + $registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], supportedKinds?: string[]): void; + $registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void; $registerNavigateTypeSupport(handle: number): void; - $registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void; - $registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): void; - $registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): void; - $registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): void; - $registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): void; - $registerFoldingProvider(handle: number, selector: vscode.DocumentSelector): void; + $registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportsResolveInitialValues: boolean): void; + $registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void; + $registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void; + $registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void; + $registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void; $setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void; } @@ -316,13 +320,19 @@ export interface MainThreadTerminalServiceShape extends IDisposable { $hide(terminalId: number): void; $sendText(terminalId: number, text: string, addNewLine: boolean): void; $show(terminalId: number, preserveFocus: boolean): void; + $registerOnDataListener(terminalId: number): void; + + $sendProcessTitle(terminalId: number, title: string): void; + $sendProcessData(terminalId: number, data: string): void; + $sendProcessPid(terminalId: number, pid: number): void; + $sendProcessExit(terminalId: number, exitCode: number): void; } export interface MyQuickPickItems extends IPickOpenEntry { handle: number; } export interface MainThreadQuickOpenShape extends IDisposable { - $show(options: IPickOptions): TPromise<number>; + $show(options: IPickOptions): TPromise<number | number[]>; $setItems(items: MyQuickPickItems[]): TPromise<any>; $setError(error: Error): TPromise<any>; $input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>; @@ -342,21 +352,35 @@ export interface MainThreadTelemetryShape extends IDisposable { $publicLog(eventName: string, data?: any): void; } -export type WebviewHandle = number; +export type WebviewPanelHandle = string; export interface MainThreadWebviewsShape extends IDisposable { - $createWebview(handle: WebviewHandle, uri: URI, title: string, column: EditorPosition, options: vscode.WebviewOptions): void; - $disposeWebview(handle: WebviewHandle): void; - $show(handle: WebviewHandle, column: EditorPosition): void; - $setTitle(handle: WebviewHandle, value: string): void; - $setHtml(handle: WebviewHandle, value: string): void; - $sendMessage(handle: WebviewHandle, value: any): Thenable<boolean>; + $createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionFolderPath: string): void; + $disposeWebview(handle: WebviewPanelHandle): void; + $reveal(handle: WebviewPanelHandle, column: EditorPosition | undefined): void; + $setTitle(handle: WebviewPanelHandle, value: string): void; + $setHtml(handle: WebviewPanelHandle, value: string): void; + $postMessage(handle: WebviewPanelHandle, value: any): Thenable<boolean>; + + $registerSerializer(viewType: string): void; + $unregisterSerializer(viewType: string): void; } + export interface ExtHostWebviewsShape { - $onMessage(handle: WebviewHandle, message: any): void; - $onDidChangeActiveWeview(handle: WebviewHandle | undefined): void; - $onDidDisposeWeview(handle: WebviewHandle): Thenable<void>; - $onDidChangePosition(handle: WebviewHandle, newPosition: EditorPosition): void; + $onMessage(handle: WebviewPanelHandle, message: any): void; + $onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, active: boolean, position: EditorPosition): void; + $onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void>; + $deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>; + $serializeWebviewPanel(webviewHandle: WebviewPanelHandle): Thenable<any>; +} + +export interface MainThreadUrlsShape extends IDisposable { + $registerProtocolHandler(handle: number, extensionId: string): TPromise<void>; + $unregisterProtocolHandler(handle: number): TPromise<void>; +} + +export interface ExtHostUrlsShape { + $handleExternalUri(handle: number, uri: UriComponents): TPromise<void>; } export interface MainThreadWorkspaceShape extends IDisposable { @@ -372,18 +396,22 @@ export interface IFileChangeDto { } export interface MainThreadFileSystemShape extends IDisposable { - $registerFileSystemProvider(handle: number, scheme: string): void; - $unregisterFileSystemProvider(handle: number): void; - - $onDidAddFileSystemRoot(root: UriComponents): void; + $registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void; + $unregisterProvider(handle: number): void; $onFileSystemChange(handle: number, resource: IFileChangeDto[]): void; - $reportFileChunk(handle: number, session: number, chunk: number[] | null): void; +} +export interface MainThreadSearchShape extends IDisposable { + $registerSearchProvider(handle: number, scheme: string): void; + $unregisterProvider(handle: number): void; $handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void; } export interface MainThreadTaskShape extends IDisposable { $registerTaskProvider(handle: number): TPromise<void>; + $fetchTasks(filter?: TaskFilterDTO): TPromise<TaskDTO[]>; + $executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>; + $terminateTask(id: string): TPromise<void>; $unregisterTaskProvider(handle: number): TPromise<void>; } @@ -454,6 +482,10 @@ export interface MainThreadSCMShape extends IDisposable { export type DebugSessionUUID = string; export interface MainThreadDebugServiceShape extends IDisposable { + $registerDebugTypes(debugTypes: string[]); + $acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage); + $acceptDAError(handle: number, name: string, message: string, stack: string); + $acceptDAExit(handle: number, code: number, signal: string); $registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasDebugAdapterExecutable: boolean, handle: number): TPromise<any>; $unregisterDebugConfigurationProvider(handle: number): TPromise<any>; $startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>; @@ -555,16 +587,20 @@ export interface ExtHostWorkspaceShape { } export interface ExtHostFileSystemShape { - $utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat>; $stat(handle: number, resource: UriComponents): TPromise<IStat>; - $read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number>; - $write(handle: number, resource: UriComponents, content: number[]): TPromise<void>; - $unlink(handle: number, resource: UriComponents): TPromise<void>; - $move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat>; - $mkdir(handle: number, resource: UriComponents): TPromise<IStat>; - $readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][]>; - $rmdir(handle: number, resource: UriComponents): TPromise<void>; - $findFiles(handle: number, session: number, query: string): TPromise<void>; + $readdir(handle: number, resource: UriComponents): TPromise<[string, FileType][]>; + $readFile(handle: number, resource: UriComponents): TPromise<string>; + $writeFile(handle: number, resource: UriComponents, base64Encoded: string, opts: FileWriteOptions): TPromise<void>; + $rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): TPromise<void>; + $copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): TPromise<void>; + $mkdir(handle: number, resource: UriComponents): TPromise<void>; + $delete(handle: number, resource: UriComponents): TPromise<void>; + $watch(handle: number, session: number, resource: UriComponents, opts: IWatchOptions): void; + $unwatch(handle: number, session: number): void; +} + +export interface ExtHostSearchShape { + $provideFileSearchResults(handle: number, session: number, query: string): TPromise<void>; $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void>; } @@ -697,7 +733,7 @@ export interface ExtHostLanguageFeaturesShape { $resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto>; $releaseWorkspaceSymbols(handle: number, id: number): void; $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<WorkspaceEditDto>; - $resolveInitialRenameValue(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameInitialValue>; + $resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameLocation>; $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto>; $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>; $releaseCompletionItems(handle: number, id: number): void; @@ -706,7 +742,7 @@ export interface ExtHostLanguageFeaturesShape { $resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>; $provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]>; $provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]>; - $provideFoldingRanges(handle: number, resource: UriComponents): TPromise<modes.IFoldingRangeList>; + $provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.FoldingRange[]>; } export interface ExtHostQuickOpenShape { @@ -714,9 +750,23 @@ export interface ExtHostQuickOpenShape { $validateInput(input: string): TPromise<string>; } +export interface ShellLaunchConfigDto { + name?: string; + executable?: string; + args?: string[] | string; + cwd?: string; + env?: { [key: string]: string }; +} + export interface ExtHostTerminalServiceShape { $acceptTerminalClosed(id: number): void; + $acceptTerminalOpened(id: number, name: string): void; $acceptTerminalProcessId(id: number, processId: number): void; + $acceptTerminalProcessData(id: number, data: string); + $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void; + $acceptProcessInput(id: number, data: string): void; + $acceptProcessResize(id: number, cols: number, rows: number): void; + $acceptProcessShutdown(id: number): void; } export interface ExtHostSCMShape { @@ -728,23 +778,26 @@ export interface ExtHostSCMShape { export interface ExtHostTaskShape { $provideTasks(handle: number): TPromise<TaskSet>; + $taskStarted(execution: TaskExecutionDTO): void; + $taskEnded(execution: TaskExecutionDTO): void; } -export interface IFunctionBreakpointDto { - type: 'function'; +export interface IBreakpointDto { + type: string; id?: string; enabled: boolean; condition?: string; hitCondition?: string; + logMessage?: string; +} + +export interface IFunctionBreakpointDto extends IBreakpointDto { + type: 'function'; functionName: string; } -export interface ISourceBreakpointDto { +export interface ISourceBreakpointDto extends IBreakpointDto { type: 'source'; - id?: string; - enabled: boolean; - condition?: string; - hitCondition?: string; uri: UriComponents; line: number; character: number; @@ -764,6 +817,7 @@ export interface ISourceMultiBreakpointDto { enabled: boolean; condition?: string; hitCondition?: string; + logMessage?: string; line: number; character: number; }[]; @@ -772,6 +826,11 @@ export interface ISourceMultiBreakpointDto { // {{SQL CARBON EDIT}} /* export interface ExtHostDebugServiceShape { + $substituteVariables(folder: UriComponents | undefined, config: IConfig): TPromise<IConfig>; + $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void>; + $startDASession(handle: number, debugType: string, adapterExecutableInfo: IAdapterExecutable | null): TPromise<void>; + $stopDASession(handle: number): TPromise<void>; + $sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void>; $resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): TPromise<IConfig>; $provideDebugConfigurations(handle: number, folder: UriComponents | undefined): TPromise<IConfig[]>; $debugAdapterExecutable(handle: number, folder: UriComponents | undefined): TPromise<IAdapterExecutable>; @@ -805,6 +864,10 @@ export interface ExtHostLogServiceShape { $setLevel(level: LogLevel); } +export interface ExtHostProgressShape { + $acceptProgressCanceled(handle: number): void; +} + // --- proxy identifiers export const MainContext = { @@ -831,10 +894,12 @@ export const MainContext = { MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'), MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'), MainThreadWebviews: createMainId<MainThreadWebviewsShape>('MainThreadWebviews'), + MainThreadUrls: createMainId<MainThreadUrlsShape>('MainThreadUrls'), MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'), MainThreadFileSystem: createMainId<MainThreadFileSystemShape>('MainThreadFileSystem'), MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'), MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM'), + MainThreadSearch: createMainId<MainThreadSearchShape>('MainThreadSearch'), MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'), MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'), }; @@ -861,8 +926,11 @@ export const ExtHostContext = { ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'), ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'), ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'), + ExtHostSearch: createExtId<ExtHostSearchShape>('ExtHostSearch'), ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'), ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'), ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'), - ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews') + ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'), + ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'), + ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress') }; diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index 0d5989207c..553d365629 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -10,25 +10,30 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import * as vscode from 'vscode'; import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters'; import * as types from 'vs/workbench/api/node/extHostTypes'; +import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol'; + import { ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search'; -import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures'; +import { ExtHostTask } from './extHostTask'; +import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand } from './apiCommands'; export class ExtHostApiCommands { - static register(commands: ExtHostCommands) { - return new ExtHostApiCommands(commands).registerCommands(); + static register(commands: ExtHostCommands, workspace: ExtHostTask) { + return new ExtHostApiCommands(commands, workspace).registerCommands(); } private _commands: ExtHostCommands; + private _tasks: ExtHostTask; private _disposables: IDisposable[] = []; - private constructor(commands: ExtHostCommands) { + private constructor(commands: ExtHostCommands, task: ExtHostTask) { this._commands = commands; + this._tasks = task; } registerCommands() { @@ -46,6 +51,14 @@ export class ExtHostApiCommands { ], returns: 'A promise that resolves to an array of Location-instances.' }); + this._register('vscode.executeTypeDefinitionProvider', this._executeTypeDefinitionProvider, { + description: 'Execute all type definition providers.', + args: [ + { name: 'uri', description: 'Uri of a text document', constraint: URI }, + { name: 'position', description: 'Position of a symbol', constraint: types.Position } + ], + returns: 'A promise that resolves to an array of Location-instances.' + }); this._register('vscode.executeImplementationProvider', this._executeImplementationProvider, { description: 'Execute all implementation providers.', args: [ @@ -108,7 +121,8 @@ export class ExtHostApiCommands { args: [ { name: 'uri', description: 'Uri of a text document', constraint: URI }, { name: 'position', description: 'Position in a text document', constraint: types.Position }, - { name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: value => value === void 0 || typeof value === 'string' } + { name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: value => value === void 0 || typeof value === 'string' }, + { name: 'itemResolveCount', description: '(optional) Number of completions to resolve (too large numbers slow down completions)', constraint: value => value === void 0 || typeof value === 'number' } ], returns: 'A promise that resolves to a CompletionList-instance.' }); @@ -123,7 +137,8 @@ export class ExtHostApiCommands { this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider, { description: 'Execute CodeLens provider.', args: [ - { name: 'uri', description: 'Uri of a text document', constraint: URI } + { name: 'uri', description: 'Uri of a text document', constraint: URI }, + { name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only retrun resolved lenses, will impact performance)', constraint: value => value === void 0 || typeof value === 'number' } ], returns: 'A promise that resolves to an array of CodeLens-instances.' }); @@ -161,99 +176,94 @@ export class ExtHostApiCommands { ], returns: 'A promise that resolves to an array of DocumentLink-instances.' }); + this._register('vscode.executeTaskProvider', this._executeTaskProvider, { + description: 'Execute task provider', + args: [], + returns: 'An array of task handles' + }); + this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, { + description: 'Execute document color provider.', + args: [ + { name: 'uri', description: 'Uri of a text document', constraint: URI }, + ], + returns: 'A promise that resolves to an array of ColorInformation objects.' + }); + this._register('vscode.executeColorPresentationProvider', this._executeColorPresentationProvider, { + description: 'Execute color presentation provider.', + args: [ + { name: 'color', description: 'The color to show and insert', constraint: types.Color }, + { name: 'context', description: 'Context object with uri and range' } + ], + returns: 'A promise that resolves to an array of ColorPresentation objects.' + }); - this._register('vscode.previewHtml', (uri: URI, position?: vscode.ViewColumn, label?: string, options?: any) => { - return this._commands.executeCommand('_workbench.previewHtml', - uri, - typeof position === 'number' && typeConverters.fromViewColumn(position), - label, - options); - }, { - description: ` - Render the html of the resource in an editor view. - See [working with the html preview](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands#working-with-the-html-preview) for more information about the html preview's intergration with the editor and for best practices for extension authors. + // ----------------------------------------------------------------- + // The following commands are registered on both sides separately. + // + // We are trying to maintain backwards compatibility for cases where + // API commands are encoded as markdown links, for example. + // ----------------------------------------------------------------- + + type ICommandHandler = (...args: any[]) => any; + const adjustHandler = (handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler => { + return (...args: any[]) => { + return handler(this._commands, ...args); + }; + }; + + this._register(PreviewHTMLAPICommand.ID, adjustHandler(PreviewHTMLAPICommand.execute), { + description: ` + Render the HTML of the resource in an editor view. + + See [working with the HTML preview](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands#working-with-the-html-preview) for more information about the HTML preview's integration with the editor and for best practices for extension authors. `, - args: [ - { name: 'uri', description: 'Uri of the resource to preview.', constraint: value => value instanceof URI || typeof value === 'string' }, - { name: 'column', description: '(optional) Column in which to preview.', constraint: value => typeof value === 'undefined' || (typeof value === 'number' && typeof types.ViewColumn[value] === 'string') }, - { name: 'label', description: '(optional) An human readable string that is used as title for the preview.', constraint: v => typeof v === 'string' || typeof v === 'undefined' }, - { name: 'options', description: '(optional) Options for controlling webview environment.', constraint: v => typeof v === 'object' || typeof v === 'undefined' } - ] - }); + args: [ + { name: 'uri', description: 'Uri of the resource to preview.', constraint: value => value instanceof URI || typeof value === 'string' }, + { name: 'column', description: '(optional) Column in which to preview.', constraint: value => typeof value === 'undefined' || (typeof value === 'number' && typeof types.ViewColumn[value] === 'string') }, + { name: 'label', description: '(optional) An human readable string that is used as title for the preview.', constraint: v => typeof v === 'string' || typeof v === 'undefined' }, + { name: 'options', description: '(optional) Options for controlling webview environment.', constraint: v => typeof v === 'object' || typeof v === 'undefined' } + ] + }); - this._register('vscode.openFolder', (uri?: URI, forceNewWindow?: boolean) => { - if (!uri) { - return this._commands.executeCommand('_files.pickFolderAndOpen', forceNewWindow); - } + this._register(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute), { + description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.', + args: [ + { name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: value => value === void 0 || value instanceof URI }, + { name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' } + ] + }); - return this._commands.executeCommand('_files.windowOpen', [uri.fsPath], forceNewWindow); - }, { - description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.', - args: [ - { name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: value => value === void 0 || value instanceof URI }, - { name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' } - ] - }); + this._register(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute), { + description: 'Opens the provided resources in the diff editor to compare their contents.', + args: [ + { name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI }, + { name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI }, + { name: 'title', description: '(optional) Human readable title for the diff editor', constraint: v => v === void 0 || typeof v === 'string' }, + { name: 'options', description: '(optional) Editor options, see vscode.TextDocumentShowOptions' } + ] + }); - this._register('vscode.diff', (left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions) => { - return this._commands.executeCommand('_workbench.diff', [ - left, right, - label, - undefined, - typeConverters.toTextEditorOptions(options), - options ? typeConverters.fromViewColumn(options.viewColumn) : undefined - ]); - }, { - description: 'Opens the provided resources in the diff editor to compare their contents.', - args: [ - { name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI }, - { name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI }, - { name: 'title', description: '(optional) Human readable title for the diff editor', constraint: v => v === void 0 || typeof v === 'string' }, - { name: 'options', description: '(optional) Editor options, see vscode.TextDocumentShowOptions' } - ] - }); + this._register(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute), { + description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.', + args: [ + { name: 'resource', description: 'Resource to open', constraint: URI }, + { name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: v => v === void 0 || typeof v === 'number' || typeof v === 'object' } + ] + }); - this._register('vscode.open', (resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions) => { - let options: ITextEditorOptions; - let column: EditorPosition; - - if (columnOrOptions) { - if (typeof columnOrOptions === 'number') { - column = typeConverters.fromViewColumn(columnOrOptions); - } else { - options = typeConverters.toTextEditorOptions(columnOrOptions); - column = typeConverters.fromViewColumn(columnOrOptions.viewColumn); - } - } - - return this._commands.executeCommand('_workbench.open', [ - resource, - options, - column - ]); - }, { - description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.', - args: [ - { name: 'resource', description: 'Resource to open', constraint: URI }, - { name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: v => v === void 0 || typeof v === 'number' || typeof v === 'object' } - ] - }); - - this._register('vscode.removeFromRecentlyOpened', (path: string) => { - return this._commands.executeCommand('_workbench.removeFromRecentlyOpened', path); - }, { - description: 'Removes an entry with the given path from the recently opened list.', - args: [ - { name: 'path', description: 'Path to remove from recently opened.', constraint: value => typeof value === 'string' } - ] - }); + this._register(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute), { + description: 'Removes an entry with the given path from the recently opened list.', + args: [ + { name: 'path', description: 'Path to remove from recently opened.', constraint: value => typeof value === 'string' } + ] + }); } // --- command impl private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void { - let disposable = this._commands.registerCommand(id, handler, this, description); + let disposable = this._commands.registerCommand(false, id, handler, this, description); this._disposables.push(disposable); } @@ -280,12 +290,17 @@ export class ExtHostApiCommands { resource, position: position && typeConverters.fromPosition(position) }; - return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.location.to); - } - return undefined; - }); + return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args) + .then(tryMapWith(typeConverters.location.to)); + } + + private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand<modes.Location[]>('_executeTypeDefinitionProvider', args) + .then(tryMapWith(typeConverters.location.to)); } private _executeImplementationProvider(resource: URI, position: types.Position): Thenable<types.Location[]> { @@ -293,12 +308,8 @@ export class ExtHostApiCommands { resource, position: position && typeConverters.fromPosition(position) }; - return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.location.to); - } - return undefined; - }); + return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args) + .then(tryMapWith(typeConverters.location.to)); } private _executeHoverProvider(resource: URI, position: types.Position): Thenable<types.Hover[]> { @@ -306,12 +317,8 @@ export class ExtHostApiCommands { resource, position: position && typeConverters.fromPosition(position) }; - return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.toHover); - } - return undefined; - }); + return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args) + .then(tryMapWith(typeConverters.toHover)); } private _executeDocumentHighlights(resource: URI, position: types.Position): Thenable<types.DocumentHighlight[]> { @@ -319,12 +326,8 @@ export class ExtHostApiCommands { resource, position: position && typeConverters.fromPosition(position) }; - return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.toDocumentHighlight); - } - return undefined; - }); + return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args) + .then(tryMapWith(typeConverters.toDocumentHighlight)); } private _executeReferenceProvider(resource: URI, position: types.Position): Thenable<types.Location[]> { @@ -332,12 +335,8 @@ export class ExtHostApiCommands { resource, position: position && typeConverters.fromPosition(position) }; - return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.location.to); - } - return undefined; - }); + return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args) + .then(tryMapWith(typeConverters.location.to)); } private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Thenable<types.WorkspaceEdit> { @@ -371,11 +370,12 @@ export class ExtHostApiCommands { }); } - private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable<types.CompletionList> { + private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string, maxItemsToResolve: number): Thenable<types.CompletionList> { const args = { resource, position: position && typeConverters.fromPosition(position), - triggerCharacter + triggerCharacter, + maxItemsToResolve }; return this._commands.executeCommand<modes.ISuggestResult>('_executeCompletionItemProvider', args).then(result => { if (result) { @@ -387,6 +387,32 @@ export class ExtHostApiCommands { }); } + private _executeDocumentColorProvider(resource: URI): Thenable<types.ColorInformation[]> { + const args = { + resource + }; + return this._commands.executeCommand<IRawColorInfo[]>('_executeDocumentColorProvider', args).then(result => { + if (result) { + return result.map(ci => ({ range: typeConverters.toRange(ci.range), color: typeConverters.Color.to(ci.color) })); + } + return []; + }); + } + + private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable<types.ColorPresentation[]> { + const args = { + resource: context.uri, + color: typeConverters.Color.from(color), + range: typeConverters.fromRange(context.range), + }; + return this._commands.executeCommand<modes.IColorPresentation[]>('_executeColorPresentationProvider', args).then(result => { + if (result) { + return result.map(typeConverters.ColorPresentation.to); + } + return []; + }); + } + private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> { const args = { resource @@ -404,11 +430,8 @@ export class ExtHostApiCommands { resource, range: typeConverters.fromRange(range) }; - return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args).then(value => { - if (!Array.isArray(value)) { - return undefined; - } - return value.map(codeAction => { + return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args) + .then(tryMapWith(codeAction => { if (codeAction._isSynthetic) { return this._commands.converter.fromInternal(codeAction.command); } else { @@ -424,22 +447,18 @@ export class ExtHostApiCommands { } return ret; } - }); - }); + })); } - private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]> { - const args = { resource }; - return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(item => { - return new types.CodeLens( - typeConverters.toRange(item.range), - this._commands.converter.fromInternal(item.command)); - }); - } - return undefined; - }); + private _executeCodeLensProvider(resource: URI, itemResolveCount: number): Thenable<vscode.CodeLens[]> { + const args = { resource, itemResolveCount }; + return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args) + .then(tryMapWith(item => { + return new types.CodeLens( + typeConverters.toRange(item.range), + this._commands.converter.fromInternal(item.command)); + })); + } private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> { @@ -447,12 +466,8 @@ export class ExtHostApiCommands { resource, options }; - return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)); - } - return undefined; - }); + return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args) + .then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text))); } private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> { @@ -461,12 +476,8 @@ export class ExtHostApiCommands { range: typeConverters.fromRange(range), options }; - return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)); - } - return undefined; - }); + return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args) + .then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text))); } private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> { @@ -476,20 +487,25 @@ export class ExtHostApiCommands { ch, options }; - return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args).then(value => { - if (Array.isArray(value)) { - return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)); - } - return undefined; - }); + return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args) + .then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text))); } private _executeDocumentLinkProvider(resource: URI): Thenable<vscode.DocumentLink[]> { - return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource).then(value => { - if (Array.isArray(value)) { - return value.map(typeConverters.DocumentLink.to); - } - return undefined; - }); + return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource) + .then(tryMapWith(typeConverters.DocumentLink.to)); + } + + private _executeTaskProvider(): Thenable<vscode.Task[]> { + return this._tasks.fetchTasks(); } } + +function tryMapWith<T, R>(f: (x: T) => R) { + return (value: T[]) => { + if (Array.isArray(value)) { + return value.map(f); + } + return undefined; + }; +} diff --git a/src/vs/workbench/api/node/extHostCommands.ts b/src/vs/workbench/api/node/extHostCommands.ts index f5922efac6..e84ff92ac1 100644 --- a/src/vs/workbench/api/node/extHostCommands.ts +++ b/src/vs/workbench/api/node/extHostCommands.ts @@ -54,7 +54,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { this._argumentProcessors.push(processor); } - registerCommand(id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable { + registerCommand(global: boolean, id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable { this._logService.trace('ExtHostCommands#registerCommand', id); if (!id.trim().length) { @@ -66,11 +66,15 @@ export class ExtHostCommands implements ExtHostCommandsShape { } this._commands.set(id, { callback, thisArg, description }); - this._proxy.$registerCommand(id); + if (global) { + this._proxy.$registerCommand(id); + } return new extHostTypes.Disposable(() => { if (this._commands.delete(id)) { - this._proxy.$unregisterCommand(id); + if (global) { + this._proxy.$unregisterCommand(id); + } } }); } @@ -112,6 +116,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { try { validateConstraint(args[i], description.args[i].constraint); } catch (err) { + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break return <any>Promise.reject(new Error(`Running the contributed command:'${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`)); } } @@ -122,12 +127,14 @@ export class ExtHostCommands implements ExtHostCommandsShape { return Promise.resolve(result); } catch (err) { this._logService.error(err, id); + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break return <any>Promise.reject(new Error(`Running the contributed command:'${id}' failed.`)); } } $executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> { if (!this._commands.has(id)) { + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break return <any>Promise.reject(new Error(`Contributed command '${id}' does not exist.`)); } else { args = args.map(arg => this._argumentProcessors.reduce((r, p) => p.processArgument(r), arg)); @@ -161,15 +168,16 @@ export class ExtHostCommands implements ExtHostCommandsShape { export class CommandsConverter { + private readonly _delegatingCommandId: string; private _commands: ExtHostCommands; private _heap: ExtHostHeapService; // --- conversion between internal and api commands constructor(commands: ExtHostCommands, heap: ExtHostHeapService) { - + this._delegatingCommandId = `_internal_command_delegation_${Date.now()}`; this._commands = commands; this._heap = heap; - this._commands.registerCommand('_internal_command_delegation', this._executeConvertedCommand, this); + this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this); } toInternal(command: vscode.Command): modes.Command { @@ -190,7 +198,7 @@ export class CommandsConverter { const id = this._heap.keep(command); ObjectIdentifier.mixin(result, id); - result.id = '_internal_command_delegation'; + result.id = this._delegatingCommandId; result.arguments = [id]; } diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 1c0942a92f..7aaa5931a2 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -6,16 +6,19 @@ import { mixin, deepClone } from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as vscode from 'vscode'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol'; import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes'; -import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; -import { StrictResourceMap } from 'vs/base/common/map'; +import { ResourceMap } from 'vs/base/common/map'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { isObject } from 'vs/base/common/types'; + +declare var Proxy: any; // TODO@TypeScript function lookUp(tree: any, key: string) { if (key) { @@ -47,7 +50,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) { this._proxy = proxy; this._extHostWorkspace = extHostWorkspace; - this._configuration = Configuration.parse(data); + this._configuration = ExtHostConfiguration.parse(data); this._configurationScopes = data.configurationScopes; } @@ -56,12 +59,12 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { } $acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) { - this._configuration = Configuration.parse(data); + this._configuration = ExtHostConfiguration.parse(data); this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData)); } getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration { - const config = deepClone(section + const config = this._toReadonlyValue(section ? lookUp(this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace), section) : this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace)); @@ -93,6 +96,49 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { let result = lookUp(config, key); if (typeof result === 'undefined') { result = defaultValue; + } else { + let clonedConfig = void 0; + const cloneOnWriteProxy = (target: any, accessor: string): any => { + let clonedTarget = void 0; + const cloneTarget = () => { + clonedConfig = clonedConfig ? clonedConfig : deepClone(config); + clonedTarget = clonedTarget ? clonedTarget : lookUp(clonedConfig, accessor); + }; + return isObject(target) ? + new Proxy(target, { + get: (target: any, property: string) => { + if (typeof property === 'string' && property.toLowerCase() === 'tojson') { + cloneTarget(); + return () => clonedTarget; + } + if (clonedConfig) { + clonedTarget = clonedTarget ? clonedTarget : lookUp(clonedConfig, accessor); + return clonedTarget[property]; + } + const result = target[property]; + if (typeof property === 'string') { + return cloneOnWriteProxy(result, `${accessor}.${property}`); + } + return result; + }, + set: (target: any, property: string, value: any) => { + cloneTarget(); + clonedTarget[property] = value; + return true; + }, + deleteProperty: (target: any, property: string) => { + cloneTarget(); + delete clonedTarget[property]; + return true; + }, + defineProperty: (target: any, property: string, descriptor: any) => { + cloneTarget(); + Object.defineProperty(clonedTarget, property, descriptor); + return true; + } + }) : target; + }; + result = cloneOnWriteProxy(result, key); } return result; }, @@ -128,6 +174,22 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return <vscode.WorkspaceConfiguration>Object.freeze(result); } + private _toReadonlyValue(result: any): any { + const readonlyProxy = (target) => { + return isObject(target) ? + new Proxy(target, { + get: (target: any, property: string) => readonlyProxy(target[property]), + set: (target: any, property: string, value: any) => { throw new Error(`TypeError: Cannot assign to read only property '${property}' of object`); }, + deleteProperty: (target: any, property: string) => { throw new Error(`TypeError: Cannot delete read only property '${property}' of object`); }, + defineProperty: (target: any, property: string) => { throw new Error(`TypeError: Cannot define property '${property}' for a readonly object`); }, + setPrototypeOf: (target: any) => { throw new Error(`TypeError: Cannot set prototype for a readonly object`); }, + isExtensible: () => false, + preventExtensions: () => true + }) : target; + }; + return readonlyProxy(result); + } + private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void { const scope = this._configurationScopes[key]; const extensionIdText = extensionId ? `[${extensionId}] ` : ''; @@ -147,7 +209,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent { const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides); - const changedConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>(); + const changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(); for (const key of Object.keys(data.changedConfigurationByResource)) { const resource = URI.parse(key); const model = data.changedConfigurationByResource[key]; @@ -158,4 +220,19 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource) }); } + + private static parse(data: IConfigurationData): Configuration { + const defaultConfiguration = ExtHostConfiguration.parseConfigurationModel(data.defaults); + const userConfiguration = ExtHostConfiguration.parseConfigurationModel(data.user); + const workspaceConfiguration = ExtHostConfiguration.parseConfigurationModel(data.workspace); + const folders: ResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => { + result.set(URI.parse(key), ExtHostConfiguration.parseConfigurationModel(data.folders[key])); + return result; + }, new ResourceMap<ConfigurationModel>()); + return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false); + } + + private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel { + return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze(); + } } diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index d8d171e002..32a228bfcb 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -7,43 +7,49 @@ // {{SQL CARBON EDIT}} /* import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { asWinJsPromise } from 'vs/base/common/async'; import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto } from 'vs/workbench/api/node/extHost.protocol'; -import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; - import * as vscode from 'vscode'; -import URI, { UriComponents } from 'vs/base/common/uri'; import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint } from 'vs/workbench/api/node/extHostTypes'; import { generateUuid } from 'vs/base/common/uuid'; +import { DebugAdapter, convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/node/debugAdapter'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; +import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; +import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; +import { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig } from 'vs/workbench/parts/debug/common/debug'; +import { getTerminalLauncher } from 'vs/workbench/parts/debug/node/terminals'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver'; +import { IConfigurationResolverService } from '../../services/configurationResolver/common/configurationResolver'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { ExtHostConfiguration } from './extHostConfiguration'; export class ExtHostDebugService implements ExtHostDebugServiceShape { - private _workspace: ExtHostWorkspace; - private _handleCounter: number; private _handlers: Map<number, vscode.DebugConfigurationProvider>; private _debugServiceProxy: MainThreadDebugServiceShape; private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>(); - private _onDidStartDebugSession: Emitter<vscode.DebugSession>; + private readonly _onDidStartDebugSession: Emitter<vscode.DebugSession>; get onDidStartDebugSession(): Event<vscode.DebugSession> { return this._onDidStartDebugSession.event; } - private _onDidTerminateDebugSession: Emitter<vscode.DebugSession>; + private readonly _onDidTerminateDebugSession: Emitter<vscode.DebugSession>; get onDidTerminateDebugSession(): Event<vscode.DebugSession> { return this._onDidTerminateDebugSession.event; } - private _onDidChangeActiveDebugSession: Emitter<vscode.DebugSession | undefined>; + private readonly _onDidChangeActiveDebugSession: Emitter<vscode.DebugSession | undefined>; get onDidChangeActiveDebugSession(): Event<vscode.DebugSession | undefined> { return this._onDidChangeActiveDebugSession.event; } private _activeDebugSession: ExtHostDebugSession | undefined; get activeDebugSession(): ExtHostDebugSession | undefined { return this._activeDebugSession; } - private _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>; + private readonly _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>; get onDidReceiveDebugSessionCustomEvent(): Event<vscode.DebugSessionCustomEvent> { return this._onDidReceiveDebugSessionCustomEvent.event; } private _activeDebugConsole: ExtHostDebugConsole; @@ -52,12 +58,19 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { private _breakpoints: Map<string, vscode.Breakpoint>; private _breakpointEventsActive: boolean; - private _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>; + private readonly _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>; + + private _debugAdapters: Map<number, DebugAdapter>; + + private _variableResolver: IConfigurationResolverService; - constructor(mainContext: IMainContext, workspace: ExtHostWorkspace) { - - this._workspace = workspace; + constructor(mainContext: IMainContext, + private _workspace: ExtHostWorkspace, + private _extensionService: ExtHostExtensionService, + private _editorsService: ExtHostDocumentsAndEditors, + private _configurationService: ExtHostConfiguration + ) { this._handleCounter = 0; this._handlers = new Map<number, vscode.DebugConfigurationProvider>(); @@ -79,6 +92,86 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { this._breakpoints = new Map<string, vscode.Breakpoint>(); this._breakpointEventsActive = false; + + this._debugAdapters = new Map<number, DebugAdapter>(); + + // register all debug extensions + const debugTypes: string[] = []; + for (const ed of this._extensionService.getAllExtensionDescriptions()) { + if (ed.contributes) { + const debuggers = <IDebuggerContribution[]>ed.contributes['debuggers']; + if (debuggers && debuggers.length > 0) { + for (const dbg of debuggers) { + // only debugger contributions with a "label" are considered a "main" debugger contribution + if (dbg.type && dbg.label) { + debugTypes.push(dbg.type); + } + } + } + } + } + if (debugTypes.length > 0) { + this._debugServiceProxy.$registerDebugTypes(debugTypes); + } + } + + public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> { + const terminalLauncher = getTerminalLauncher(); + if (terminalLauncher) { + return terminalLauncher.runInTerminal(args, config); + } + return void 0; + } + + public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): TPromise<IConfig> { + if (!this._variableResolver) { + this._variableResolver = new ExtHostVariableResolverService(this._workspace, this._editorsService, this._configurationService); + } + const folder = <IWorkspaceFolder>this.getFolder(folderUri); + return asWinJsPromise(token => DebugAdapter.substituteVariables(folder, config, this._variableResolver)); + } + + public $startDASession(handle: number, debugType: string, adpaterExecutable: IAdapterExecutable | null): TPromise<void> { + const mythis = this; + + const da = new class extends DebugAdapter { + + // DA -> VS Code + public acceptMessage(message: DebugProtocol.ProtocolMessage) { + convertToVSCPaths(message, source => { + if (paths.isAbsolute(source.path)) { + (<any>source).path = URI.file(source.path); + } + }); + mythis._debugServiceProxy.$acceptDAMessage(handle, message); + } + + }(debugType, adpaterExecutable, this._extensionService.getAllExtensionDescriptions()); + + this._debugAdapters.set(handle, da); + da.onError(err => this._debugServiceProxy.$acceptDAError(handle, err.name, err.message, err.stack)); + da.onExit(code => this._debugServiceProxy.$acceptDAExit(handle, code, null)); + return da.startSession(); + } + + public $sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void> { + // VS Code -> DA + convertToDAPaths(message, source => { + if (typeof source.path === 'object') { + source.path = URI.revive(source.path).fsPath; + } + }); + const da = this._debugAdapters.get(handle); + if (da) { + da.sendMessage(message); + } + return void 0; + } + + public $stopDASession(handle: number): TPromise<void> { + const da = this._debugAdapters.get(handle); + this._debugAdapters.delete(handle); + return da ? da.stopSession() : void 0; } private startBreakpoints() { @@ -113,18 +206,15 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { if (!this._breakpoints.has(bpd.id)) { let bp: vscode.Breakpoint; if (bpd.type === 'function') { - bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition); + bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage); } else { const uri = URI.revive(bpd.uri); - bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition); + bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage); } bp['_id'] = bpd.id; this._breakpoints.set(bpd.id, bp); a.push(bp); - } - - } } @@ -142,17 +232,20 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { for (const bpd of delta.changed) { let bp = this._breakpoints.get(bpd.id); if (bp) { - if (bpd.type === 'function') { + if (bp instanceof FunctionBreakpoint && bpd.type === 'function') { const fbp = <any>bp; fbp.enabled = bpd.enabled; fbp.condition = bpd.condition; fbp.hitCondition = bpd.hitCondition; + fbp.logMessage = bpd.logMessage; fbp.functionName = bpd.functionName; - } else { + } else if (bp instanceof SourceBreakpoint && bpd.type === 'source') { const sbp = <any>bp; sbp.enabled = bpd.enabled; sbp.condition = bpd.condition; sbp.hitCondition = bpd.hitCondition; + sbp.logMessage = bpd.logMessage; + sbp.location = new Location(URI.revive(bpd.uri), new Position(bpd.line, bpd.character)); } c.push(bp); } @@ -207,6 +300,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { enabled: bp.enabled, condition: bp.condition, hitCondition: bp.hitCondition, + logMessage: bp.logMessage, line: bp.location.range.start.line, character: bp.location.range.start.character }); @@ -215,9 +309,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { type: 'function', id: bp['_id'], enabled: bp.enabled, - functionName: bp.functionName, hitCondition: bp.hitCondition, - condition: bp.condition + logMessage: bp.logMessage, + condition: bp.condition, + functionName: bp.functionName }); } } diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts index 553af9a72c..caae72eb6c 100644 --- a/src/vs/workbench/api/node/extHostDecorations.ts +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -43,6 +43,10 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { return TPromise.join(requests.map(request => { const { handle, uri, id } = request; const provider = this._provider.get(handle); + if (!provider) { + // might have been unregistered in the meantime + return void 0; + } return asWinJsPromise(token => provider.provideDecoration(URI.revive(uri), token)).then(data => { result[id] = data && <DecorationData>[data.priority, data.bubble, data.title, data.abbreviation, data.color, data.source]; }, err => { diff --git a/src/vs/workbench/api/node/extHostDiagnostics.ts b/src/vs/workbench/api/node/extHostDiagnostics.ts index 4e6a4e3066..70a98cc692 100644 --- a/src/vs/workbench/api/node/extHostDiagnostics.ts +++ b/src/vs/workbench/api/node/extHostDiagnostics.ts @@ -5,31 +5,36 @@ 'use strict'; import { localize } from 'vs/nls'; -import { IMarkerData } from 'vs/platform/markers/common/markers'; +import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; import * as vscode from 'vscode'; import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape, IMainContext } from './extHost.protocol'; import { DiagnosticSeverity } from './extHostTypes'; +import * as converter from './extHostTypeConverters'; import { mergeSort } from 'vs/base/common/arrays'; +import { Event, Emitter, debounceEvent, mapEvent } from 'vs/base/common/event'; +import { keys } from 'vs/base/common/map'; export class DiagnosticCollection implements vscode.DiagnosticCollection { private static readonly _maxDiagnosticsPerFile: number = 250; private readonly _name: string; + private readonly _onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>; private _proxy: MainThreadDiagnosticsShape; private _isDisposed = false; private _data = new Map<string, vscode.Diagnostic[]>(); - constructor(name: string, proxy: MainThreadDiagnosticsShape) { + constructor(name: string, proxy: MainThreadDiagnosticsShape, onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>) { this._name = name; this._proxy = proxy; + this._onDidChangeDiagnostics = onDidChangeDiagnostics; } dispose(): void { if (!this._isDisposed) { + this._onDidChangeDiagnostics.fire(keys(this._data)); this._proxy.$clear(this.name); this._proxy = undefined; this._data = undefined; @@ -111,7 +116,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { orderLoop: for (let i = 0; i < 4; i++) { for (let diagnostic of diagnostics) { if (diagnostic.severity === order[i]) { - const len = marker.push(DiagnosticCollection.toMarkerData(diagnostic)); + const len = marker.push(converter.fromDiagnostic(diagnostic)); if (len === DiagnosticCollection._maxDiagnosticsPerFile) { break orderLoop; } @@ -121,7 +126,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { // add 'signal' marker for showing omitted errors/warnings marker.push({ - severity: Severity.Error, + severity: MarkerSeverity.Error, message: localize({ key: 'limitHit', comment: ['amount of errors/warning skipped due to limits'] }, "Not showing {0} further errors and warnings.", diagnostics.length - DiagnosticCollection._maxDiagnosticsPerFile), startLineNumber: marker[marker.length - 1].startLineNumber, startColumn: marker[marker.length - 1].startColumn, @@ -129,13 +134,14 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { endColumn: marker[marker.length - 1].endColumn }); } else { - marker = diagnostics.map(DiagnosticCollection.toMarkerData); + marker = diagnostics.map(converter.fromDiagnostic); } } entries.push([uri, marker]); } + this._onDidChangeDiagnostics.fire(toSync); this._proxy.$changeMany(this.name, entries); } @@ -147,6 +153,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { clear(): void { this._checkDisposed(); + this._onDidChangeDiagnostics.fire(keys(this._data)); this._data.clear(); this._proxy.$clear(this.name); } @@ -179,32 +186,6 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { } } - public static toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData { - - let range = diagnostic.range; - - return <IMarkerData>{ - startLineNumber: range.start.line + 1, - startColumn: range.start.character + 1, - endLineNumber: range.end.line + 1, - endColumn: range.end.character + 1, - message: diagnostic.message, - source: diagnostic.source, - severity: DiagnosticCollection._convertDiagnosticsSeverity(diagnostic.severity), - code: String(diagnostic.code) - }; - } - - private static _convertDiagnosticsSeverity(severity: number): Severity { - switch (severity) { - case 0: return Severity.Error; - case 1: return Severity.Warning; - case 2: return Severity.Info; - case 3: return Severity.Ignore; - default: return Severity.Error; - } - } - private static _compareIndexedTuplesByUri(a: [vscode.Uri, vscode.Diagnostic[]], b: [vscode.Uri, vscode.Diagnostic[]]): number { if (a[0].toString() < b[0].toString()) { return -1; @@ -220,12 +201,42 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape { private static _idPool: number = 0; - private _proxy: MainThreadDiagnosticsShape; - private _collections: DiagnosticCollection[]; + private readonly _proxy: MainThreadDiagnosticsShape; + private readonly _collections: DiagnosticCollection[] = []; + private readonly _onDidChangeDiagnostics = new Emitter<(vscode.Uri | string)[]>(); + + static _debouncer(last: (vscode.Uri | string)[], current: (vscode.Uri | string)[]): (vscode.Uri | string)[] { + if (!last) { + return current; + } else { + return last.concat(current); + } + } + + static _mapper(last: (vscode.Uri | string)[]): { uris: vscode.Uri[] } { + let uris: vscode.Uri[] = []; + let map = new Set<string>(); + for (const uri of last) { + if (typeof uri === 'string') { + if (!map.has(uri)) { + map.add(uri); + uris.push(URI.parse(uri)); + } + } else { + if (!map.has(uri.toString())) { + map.add(uri.toString()); + uris.push(uri); + } + } + } + Object.freeze(uris); + return { uris }; + } + + readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = mapEvent(debounceEvent(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper); constructor(mainContext: IMainContext) { this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics); - this._collections = []; } createDiagnosticCollection(name: string): vscode.DiagnosticCollection { @@ -233,10 +244,10 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape { name = '_generated_diagnostic_collection_name_#' + ExtHostDiagnostics._idPool++; } - const { _collections, _proxy } = this; + const { _collections, _proxy, _onDidChangeDiagnostics } = this; const result = new class extends DiagnosticCollection { constructor() { - super(name, _proxy); + super(name, _proxy, _onDidChangeDiagnostics); _collections.push(this); } dispose() { @@ -251,7 +262,36 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape { return result; } - forEach(callback: (collection: DiagnosticCollection) => any): void { - this._collections.forEach(callback); + getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[]; + getDiagnostics(): [vscode.Uri, vscode.Diagnostic[]][]; + getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][] { + if (resource) { + return this._getDiagnostics(resource); + } else { + let index = new Map<string, number>(); + let res: [vscode.Uri, vscode.Diagnostic[]][] = []; + for (const collection of this._collections) { + collection.forEach((uri, diagnostics) => { + let idx = index.get(uri.toString()); + if (typeof idx === 'undefined') { + idx = res.length; + index.set(uri.toString(), idx); + res.push([uri, []]); + } + res[idx][1] = res[idx][1].concat(...diagnostics); + }); + } + return res; + } + } + + private _getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[] { + let res: vscode.Diagnostic[] = []; + for (const collection of this._collections) { + if (collection.has(resource)) { + res = res.concat(collection.get(resource)); + } + } + return res; } } diff --git a/src/vs/workbench/api/node/extHostDocumentContentProviders.ts b/src/vs/workbench/api/node/extHostDocumentContentProviders.ts index eab66d8807..33cd1c6ec9 100644 --- a/src/vs/workbench/api/node/extHostDocumentContentProviders.ts +++ b/src/vs/workbench/api/node/extHostDocumentContentProviders.ts @@ -14,6 +14,7 @@ import { asWinJsPromise } from 'vs/base/common/async'; import { MainContext, ExtHostDocumentContentProvidersShape, MainThreadDocumentContentProvidersShape, IMainContext } from './extHost.protocol'; import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors'; import { Schemas } from 'vs/base/common/network'; +import { ILogService } from 'vs/platform/log/common/log'; export class ExtHostDocumentContentProvider implements ExtHostDocumentContentProvidersShape { @@ -21,11 +22,13 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro private readonly _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>(); private readonly _proxy: MainThreadDocumentContentProvidersShape; - private readonly _documentsAndEditors: ExtHostDocumentsAndEditors; - constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) { + constructor( + mainContext: IMainContext, + private readonly _documentsAndEditors: ExtHostDocumentsAndEditors, + private readonly _logService: ILogService, + ) { this._proxy = mainContext.getProxy(MainContext.MainThreadDocumentContentProviders); - this._documentsAndEditors = documentsAndEditors; } dispose(): void { @@ -47,6 +50,10 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro let subscription: IDisposable; if (typeof provider.onDidChange === 'function') { subscription = provider.onDidChange(uri => { + if (uri.scheme !== scheme) { + this._logService.warn(`Provider for scheme '${scheme}' is firing event for schema '${uri.scheme}' which will be IGNORED`); + return; + } if (this._documentsAndEditors.getDocument(uri.toString())) { this.$provideTextDocumentContent(handle, uri).then(value => { diff --git a/src/vs/workbench/api/node/extHostDocumentData.ts b/src/vs/workbench/api/node/extHostDocumentData.ts index 28a205d11f..2f8994f452 100644 --- a/src/vs/workbench/api/node/extHostDocumentData.ts +++ b/src/vs/workbench/api/node/extHostDocumentData.ts @@ -13,6 +13,7 @@ import * as vscode from 'vscode'; import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { MainThreadDocumentsShape } from './extHost.protocol'; import { TPromise } from 'vs/base/common/winjs.base'; +import { Schemas } from 'vs/base/common/network'; const _modeId2WordDefinition = new Map<string, RegExp>(); export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void { @@ -68,9 +69,7 @@ export class ExtHostDocumentData extends MirrorTextModel { this._document = { get uri() { return data._uri; }, get fileName() { return data._uri.fsPath; }, - // todo@remote - // documents from other fs-provider must not be untitled - get isUntitled() { return data._uri.scheme !== 'file'; }, + get isUntitled() { return data._uri.scheme === Schemas.untitled; }, get languageId() { return data._languageId; }, get version() { return data._versionId; }, get isClosed() { return data._isDisposed; }, diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index ac7ab57a2e..4410ec9034 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import URI, { UriComponents } from 'vs/base/common/uri'; import { sequence, always } from 'vs/base/common/async'; import { illegalState } from 'vs/base/common/errors'; diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index 928b40f42b..617a4fe6c1 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import URI, { UriComponents } from 'vs/base/common/uri'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as TypeConverters from './extHostTypeConverters'; @@ -137,6 +137,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape { contentChanges: events.changes.map((change) => { return { range: TypeConverters.toRange(change.range), + rangeOffset: change.rangeOffset, rangeLength: change.rangeLength, text: change.text }; diff --git a/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts b/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts index d5543de862..91e499c162 100644 --- a/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts +++ b/src/vs/workbench/api/node/extHostDocumentsAndEditors.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { dispose } from 'vs/base/common/lifecycle'; import { MainContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IMainContext } from './extHost.protocol'; import { ExtHostDocumentData } from './extHostDocumentData'; @@ -12,7 +12,6 @@ import { ExtHostTextEditor } from './extHostTextEditor'; import * as assert from 'assert'; import * as typeConverters from './extHostTypeConverters'; import URI from 'vs/base/common/uri'; -import { ExtHostWebview, ExtHostWebviews } from './extHostWebview'; import { Disposable } from './extHostTypes'; export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape { @@ -20,7 +19,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha private _disposables: Disposable[] = []; private _activeEditorId: string; - private _activeWebview: ExtHostWebview; private readonly _editors = new Map<string, ExtHostTextEditor>(); private readonly _documents = new Map<string, ExtHostDocumentData>(); @@ -29,31 +27,15 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha private readonly _onDidRemoveDocuments = new Emitter<ExtHostDocumentData[]>(); private readonly _onDidChangeVisibleTextEditors = new Emitter<ExtHostTextEditor[]>(); private readonly _onDidChangeActiveTextEditor = new Emitter<ExtHostTextEditor>(); - private readonly _onDidChangeActiveEditor = new Emitter<ExtHostTextEditor | ExtHostWebview>(); readonly onDidAddDocuments: Event<ExtHostDocumentData[]> = this._onDidAddDocuments.event; readonly onDidRemoveDocuments: Event<ExtHostDocumentData[]> = this._onDidRemoveDocuments.event; readonly onDidChangeVisibleTextEditors: Event<ExtHostTextEditor[]> = this._onDidChangeVisibleTextEditors.event; readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor> = this._onDidChangeActiveTextEditor.event; - readonly onDidChangeActiveEditor: Event<ExtHostTextEditor | ExtHostWebview> = this._onDidChangeActiveEditor.event; constructor( private readonly _mainContext: IMainContext, - _extHostWebviews?: ExtHostWebviews - ) { - if (_extHostWebviews) { - _extHostWebviews.onDidChangeActiveWebview(webview => { - if (webview) { - if (webview !== this._activeWebview) { - this._onDidChangeActiveEditor.fire(webview); - this._activeWebview = webview; - } - } else { - this._activeWebview = webview; - } - }, this, this._disposables); - } - } + ) { } dispose() { this._disposables = dispose(this._disposables); @@ -143,9 +125,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha } if (delta.newActiveEditor !== undefined) { this._onDidChangeActiveTextEditor.fire(this.activeEditor()); - - const activeEditor = this.activeEditor(); - this._onDidChangeActiveEditor.fire(activeEditor || this._activeWebview); } } diff --git a/src/vs/workbench/api/node/extHostExtensionActivator.ts b/src/vs/workbench/api/node/extHostExtensionActivator.ts index b19cdb3301..f75de4afc2 100644 --- a/src/vs/workbench/api/node/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/node/extHostExtensionActivator.ts @@ -28,6 +28,7 @@ export interface IExtensionContext { storagePath: string; asAbsolutePath(relativePath: string): string; logger: ExtHostLogger; + readonly logDirectory: string; } /** @@ -126,6 +127,7 @@ export class ExtensionActivationTimesBuilder { export class ActivatedExtension { public readonly activationFailed: boolean; + public readonly activationFailedError: Error; public readonly activationTimes: ExtensionActivationTimes; public readonly module: IExtensionModule; public readonly exports: IExtensionAPI; @@ -133,12 +135,14 @@ export class ActivatedExtension { constructor( activationFailed: boolean, + activationFailedError: Error, activationTimes: ExtensionActivationTimes, module: IExtensionModule, exports: IExtensionAPI, subscriptions: IDisposable[] ) { this.activationFailed = activationFailed; + this.activationFailedError = activationFailedError; this.activationTimes = activationTimes; this.module = module; this.exports = exports; @@ -148,13 +152,13 @@ export class ActivatedExtension { export class EmptyExtension extends ActivatedExtension { constructor(activationTimes: ExtensionActivationTimes) { - super(false, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []); + super(false, null, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []); } } export class FailedExtension extends ActivatedExtension { - constructor(activationTimes: ExtensionActivationTimes) { - super(true, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []); + constructor(activationError: Error) { + super(true, activationError, ExtensionActivationTimes.NONE, { activate: undefined, deactivate: undefined }, undefined, []); } } @@ -243,7 +247,8 @@ export class ExtensionsActivator { if (!depDesc) { // Error condition 1: unknown dependency this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Extension '{1}' failed to activate. Reason: unknown dependency '{0}'.", depId, currentExtension.id)); - this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE); + const error = new Error(`Unknown dependency '${depId}'`); + this._activatedExtensions[currentExtension.id] = new FailedExtension(error); return; } @@ -252,7 +257,9 @@ export class ExtensionsActivator { if (dep.activationFailed) { // Error condition 2: a dependency has already failed activation this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Extension '{1}' failed to activate. Reason: dependency '{0}' failed to activate.", depId, currentExtension.id)); - this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE); + const error = new Error(`Dependency ${depId} failed to activate`); + (<any>error).detail = dep.activationFailedError; + this._activatedExtensions[currentExtension.id] = new FailedExtension(error); return; } } else { @@ -285,7 +292,8 @@ export class ExtensionsActivator { for (let i = 0, len = extensionDescriptions.length; i < len; i++) { // Error condition 3: dependency loop this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension '{0}' failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id)); - this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(ExtensionActivationTimes.NONE); + const error = new Error('More than 10 levels of dependencies (most likely a dependency loop)'); + this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(error); } return TPromise.as(void 0); } @@ -333,7 +341,7 @@ export class ExtensionsActivator { console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message); console.log('Here is the error stack: ', err.stack); // Treat the extension as being empty - return new FailedExtension(ExtensionActivationTimes.NONE); + return new FailedExtension(err); }).then((x: ActivatedExtension) => { this._activatedExtensions[extensionDescription.id] = x; delete this._activatingExtensions[extensionDescription.id]; diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index e82ce418ab..5c9cf88b76 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -22,7 +22,6 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { TernarySearchTree } from 'vs/base/common/map'; import { Barrier } from 'vs/base/common/async'; import { ILogService } from 'vs/platform/log/common/log'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; import URI from 'vs/base/common/uri'; @@ -142,8 +141,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { extHostContext: IExtHostContext, extHostWorkspace: ExtHostWorkspace, extHostConfiguration: ExtHostConfiguration, - extHostLogService: ExtHostLogService, - environmentService: IEnvironmentService + extHostLogService: ExtHostLogService ) { this._barrier = new Barrier(); this._registry = new ExtensionDescriptionRegistry(initData.extensions); @@ -212,6 +210,17 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } } + public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): TPromise<void> { + return this.activateById(extensionId, reason).then(() => { + const extension = this._activator.getActivatedExtension(extensionId); + if (extension.activationFailed) { + // activation failed => bubble up the error as the promise result + return TPromise.wrapError(extension.activationFailedError); + } + return void 0; + }); + } + public getAllExtensionDescriptions(): IExtensionDescription[] { return this._registry.getAllExtensionDescriptions(); } @@ -358,6 +367,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { get logger() { checkProposedApiEnabled(extensionDescription); return that._extHostLogService.getExtLogger(extensionDescription.id); + }, + get logDirectory() { + checkProposedApiEnabled(extensionDescription); + return that._extHostLogService.getLogDirectory(extensionDescription.id); } }); }); @@ -371,7 +384,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { }; return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => { - return new ActivatedExtension(false, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions); + return new ActivatedExtension(false, null, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions); }); } @@ -423,7 +436,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription "TelemetryActivationEvent" : { "id": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, "name": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "publisherDisplayName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "publisherDisplayName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "activationEvents": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } diff --git a/src/vs/workbench/api/node/extHostFileSystem.ts b/src/vs/workbench/api/node/extHostFileSystem.ts index 52ae211f6a..fd0f58dd31 100644 --- a/src/vs/workbench/api/node/extHostFileSystem.ts +++ b/src/vs/workbench/api/node/extHostFileSystem.ts @@ -6,15 +6,17 @@ import URI, { UriComponents } from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape } from './extHost.protocol'; +import { Event, mapEvent } from 'vs/base/common/event'; +import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape, IFileChangeDto } from './extHost.protocol'; import * as vscode from 'vscode'; -import { IStat } from 'vs/platform/files/common/files'; +import * as files from 'vs/platform/files/common/files'; +import * as path from 'path'; import { IDisposable } from 'vs/base/common/lifecycle'; import { asWinJsPromise } from 'vs/base/common/async'; -import { IPatternInfo } from 'vs/platform/search/common/search'; import { values } from 'vs/base/common/map'; -import { Range } from 'vs/workbench/api/node/extHostTypes'; +import { Range, DeprecatedFileType, DeprecatedFileChangeType, FileChangeType } from 'vs/workbench/api/node/extHostTypes'; import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures'; +import { Schemas } from 'vs/base/common/network'; class FsLinkProvider implements vscode.DocumentLinkProvider { @@ -55,102 +57,245 @@ class FsLinkProvider implements vscode.DocumentLinkProvider { } } +class FileSystemProviderShim implements vscode.FileSystemProvider { + + onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>; + + constructor(private readonly _delegate: vscode.DeprecatedFileSystemProvider) { + if (!this._delegate.onDidChange) { + this.onDidChangeFile = Event.None; + } else { + this.onDidChangeFile = mapEvent(this._delegate.onDidChange, old => old.map(FileSystemProviderShim._modernizeFileChange)); + } + } + + watch(uri: vscode.Uri, options: {}): vscode.Disposable { + // does nothing because in the old API there was no notion of + // watch and provider decide what file events to generate... + return { dispose() { } }; + } + + stat(resource: vscode.Uri): Thenable<vscode.FileStat> { + return this._delegate.stat(resource).then(stat => FileSystemProviderShim._modernizeFileStat(stat)); + } + rename(oldUri: vscode.Uri, newUri: vscode.Uri): Thenable<void> { + return this._delegate.move(oldUri, newUri).then(stat => void 0); + } + readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileType][]> { + return this._delegate.readdir(resource).then(tuples => { + return tuples.map(tuple => <[string, vscode.FileType]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1]).type]); + }); + } + + private static _modernizeFileStat(stat: vscode.DeprecatedFileStat): vscode.FileStat { + let { mtime, size, type } = stat; + let newType: files.FileType; + + // no support for bitmask, effectively no support for symlinks + switch (type) { + case DeprecatedFileType.Dir: + newType = files.FileType.Directory; + break; + case DeprecatedFileType.File: + newType = files.FileType.File; + break; + case DeprecatedFileType.Symlink: + newType = files.FileType.File & files.FileType.SymbolicLink; + break; + } + return { type: newType, ctime: 0, mtime, size }; + } + + private static _modernizeFileChange(e: vscode.DeprecatedFileChange): vscode.FileChangeEvent { + let { resource, type } = e; + let newType: vscode.FileChangeType; + switch (type) { + case DeprecatedFileChangeType.Updated: + newType = FileChangeType.Changed; + break; + case DeprecatedFileChangeType.Added: + newType = FileChangeType.Created; + break; + case DeprecatedFileChangeType.Deleted: + newType = FileChangeType.Deleted; + break; + + } + return { uri: resource, type: newType }; + } + + // --- delete/create file or folder + + delete(resource: vscode.Uri): Thenable<void> { + return this._delegate.stat(resource).then(stat => { + if (stat.type === DeprecatedFileType.Dir) { + return this._delegate.rmdir(resource); + } else { + return this._delegate.unlink(resource); + } + }); + } + createDirectory(resource: vscode.Uri): Thenable<void> { + return this._delegate.mkdir(resource).then(stat => void 0); + } + + // --- read/write + + readFile(resource: vscode.Uri): Thenable<Uint8Array> { + let chunks: Buffer[] = []; + return this._delegate.read(resource, 0, -1, { + report(data) { + chunks.push(Buffer.from(data)); + } + }).then(() => { + return Buffer.concat(chunks); + }); + } + + writeFile(resource: vscode.Uri, content: Uint8Array, options: files.FileWriteOptions): Thenable<void> { + return this._delegate.write(resource, content); + } +} + export class ExtHostFileSystem implements ExtHostFileSystemShape { private readonly _proxy: MainThreadFileSystemShape; - private readonly _provider = new Map<number, vscode.FileSystemProvider>(); private readonly _linkProvider = new FsLinkProvider(); + private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>(); + private readonly _usedSchemes = new Set<string>(); + private readonly _watches = new Map<number, IDisposable>(); private _handlePool: number = 0; constructor(mainContext: IMainContext, extHostLanguageFeatures: ExtHostLanguageFeatures) { this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem); + this._usedSchemes.add(Schemas.file); + this._usedSchemes.add(Schemas.untitled); + this._usedSchemes.add(Schemas.vscode); + this._usedSchemes.add(Schemas.inMemory); + this._usedSchemes.add(Schemas.internal); + this._usedSchemes.add(Schemas.http); + this._usedSchemes.add(Schemas.https); + this._usedSchemes.add(Schemas.mailto); + this._usedSchemes.add(Schemas.data); + extHostLanguageFeatures.registerDocumentLinkProvider('*', this._linkProvider); } - registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider) { + registerDeprecatedFileSystemProvider(scheme: string, provider: vscode.DeprecatedFileSystemProvider) { + return this.registerFileSystemProvider(scheme, new FileSystemProviderShim(provider), { isCaseSensitive: false }); + } + + registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean }) { + + if (this._usedSchemes.has(scheme)) { + throw new Error(`a provider for the scheme '${scheme}' is already registered`); + } + const handle = this._handlePool++; this._linkProvider.add(scheme); - this._provider.set(handle, provider); - this._proxy.$registerFileSystemProvider(handle, scheme); - if (provider.root) { - // todo@remote - this._proxy.$onDidAddFileSystemRoot(provider.root); + this._usedSchemes.add(scheme); + this._fsProvider.set(handle, provider); + + let capabilites = files.FileSystemProviderCapabilities.FileReadWrite; + if (options.isCaseSensitive) { + capabilites += files.FileSystemProviderCapabilities.PathCaseSensitive; } - let reg: IDisposable; - if (provider.onDidChange) { - reg = provider.onDidChange(event => this._proxy.$onFileSystemChange(handle, <any>event)); + if (typeof provider.copy === 'function') { + capabilites += files.FileSystemProviderCapabilities.FileFolderCopy; } + + this._proxy.$registerFileSystemProvider(handle, scheme, capabilites); + + const subscription = provider.onDidChangeFile(event => { + let mapped: IFileChangeDto[] = []; + for (const e of event) { + let { uri: resource, type } = e; + if (resource.scheme !== scheme) { + // dropping events for wrong scheme + continue; + } + let newType: files.FileChangeType; + switch (type) { + case FileChangeType.Changed: + newType = files.FileChangeType.UPDATED; + break; + case FileChangeType.Created: + newType = files.FileChangeType.ADDED; + break; + case FileChangeType.Deleted: + newType = files.FileChangeType.DELETED; + break; + } + mapped.push({ resource, type: newType }); + } + this._proxy.$onFileSystemChange(handle, mapped); + }); + return { dispose: () => { - if (reg) { - reg.dispose(); - } + subscription.dispose(); this._linkProvider.delete(scheme); - this._provider.delete(handle); - this._proxy.$unregisterFileSystemProvider(handle); + this._usedSchemes.delete(scheme); + this._fsProvider.delete(handle); + this._proxy.$unregisterProvider(handle); } }; } - $utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat, any> { - return asWinJsPromise(token => this._provider.get(handle).utimes(URI.revive(resource), mtime, atime)); + private static _asIStat(stat: vscode.FileStat): files.IStat { + const { type, ctime, mtime, size } = stat; + return { type, ctime, mtime, size }; } - $stat(handle: number, resource: UriComponents): TPromise<IStat, any> { - return asWinJsPromise(token => this._provider.get(handle).stat(URI.revive(resource))); + + $stat(handle: number, resource: UriComponents): TPromise<files.IStat, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat); } - $read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number> { - const progress = { - report: chunk => { - this._proxy.$reportFileChunk(handle, session, [].slice.call(chunk)); - } - }; - return asWinJsPromise(token => this._provider.get(handle).read(URI.revive(resource), offset, count, progress)); + + $readdir(handle: number, resource: UriComponents): TPromise<[string, files.FileType][], any> { + return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource))); } - $write(handle: number, resource: UriComponents, content: number[]): TPromise<void, any> { - return asWinJsPromise(token => this._provider.get(handle).write(URI.revive(resource), Buffer.from(content))); + + $readFile(handle: number, resource: UriComponents): TPromise<string> { + return asWinJsPromise(token => { + return this._fsProvider.get(handle).readFile(URI.revive(resource)); + }).then(data => { + return Buffer.isBuffer(data) ? data.toString('base64') : Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('base64'); + }); } - $unlink(handle: number, resource: UriComponents): TPromise<void, any> { - return asWinJsPromise(token => this._provider.get(handle).unlink(URI.revive(resource))); + + $writeFile(handle: number, resource: UriComponents, base64Content: string, opts: files.FileWriteOptions): TPromise<void, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), opts)); } - $move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat, any> { - return asWinJsPromise(token => this._provider.get(handle).move(URI.revive(resource), URI.revive(target))); + + $delete(handle: number, resource: UriComponents): TPromise<void, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).delete(URI.revive(resource), { recursive: true })); } - $mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> { - return asWinJsPromise(token => this._provider.get(handle).mkdir(URI.revive(resource))); + + $rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts)); } - $readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> { - return asWinJsPromise(token => this._provider.get(handle).readdir(URI.revive(resource))); + + $copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts)); } - $rmdir(handle: number, resource: UriComponents): TPromise<void, any> { - return asWinJsPromise(token => this._provider.get(handle).rmdir(URI.revive(resource))); + + $mkdir(handle: number, resource: UriComponents): TPromise<void, any> { + return asWinJsPromise(token => this._fsProvider.get(handle).createDirectory(URI.revive(resource))); } - $findFiles(handle: number, session: number, query: string): TPromise<void> { - const provider = this._provider.get(handle); - if (!provider.findFiles) { - return TPromise.as(undefined); + + $watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void { + asWinJsPromise(token => { + let subscription = this._fsProvider.get(handle).watch(URI.revive(resource), opts); + this._watches.set(session, subscription); + }); + } + + $unwatch(handle: number, session: number): void { + let subscription = this._watches.get(session); + if (subscription) { + subscription.dispose(); + this._watches.delete(session); } - const progress = { - report: (uri) => { - this._proxy.$handleFindMatch(handle, session, uri); - } - }; - return asWinJsPromise(token => provider.findFiles(query, progress, token)); - } - $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> { - const provider = this._provider.get(handle); - if (!provider.provideTextSearchResults) { - return TPromise.as(undefined); - } - const progress = { - report: (data: vscode.TextSearchResult) => { - this._proxy.$handleFindMatch(handle, session, [data.uri, { - lineNumber: 1 + data.range.start.line, - preview: data.preview.leading + data.preview.matching + data.preview.trailing, - offsetAndLengths: [[data.preview.leading.length, data.preview.matching.length]] - }]); - } - }; - return asWinJsPromise(token => provider.provideTextSearchResults(pattern, options, progress, token)); } } diff --git a/src/vs/workbench/api/node/extHostFileSystemEventService.ts b/src/vs/workbench/api/node/extHostFileSystemEventService.ts index 1178918923..acab75515c 100644 --- a/src/vs/workbench/api/node/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/node/extHostFileSystemEventService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from './extHostTypes'; import { parse, IRelativePattern } from 'vs/base/common/glob'; import { Uri, FileSystemWatcher as _FileSystemWatcher } from 'vscode'; diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index bfb7eb5c1b..48c9db6ce2 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -9,19 +9,20 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { mixin } from 'vs/base/common/objects'; import * as vscode from 'vscode'; import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters'; -import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } from 'vs/workbench/api/node/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, HierarchicalSymbolInformation } from 'vs/workbench/api/node/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService'; import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands'; -import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics'; +import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics'; import { asWinJsPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } from './extHost.protocol'; +import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } from './extHost.protocol'; import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange } from 'vs/editor/common/core/range'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { isObject } from 'vs/base/common/types'; // --- adapter @@ -38,6 +39,9 @@ class OutlineAdapter { provideDocumentSymbols(resource: URI): TPromise<SymbolInformationDto[]> { let doc = this._documents.getDocumentData(resource).document; return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => { + if (value instanceof HierarchicalSymbolInformation) { + value = HierarchicalSymbolInformation.toFlatSymbolInformation(value); + } if (Array.isArray(value)) { return value.map(symbol => IdObject.mixin(TypeConverters.fromSymbolInformation(symbol))); } @@ -280,15 +284,11 @@ class CodeActionAdapter { const ran = <vscode.Range>TypeConverters.toRange(range); const allDiagnostics: vscode.Diagnostic[] = []; - this._diagnostics.forEach(collection => { - if (collection.has(resource)) { - for (let diagnostic of collection.get(resource)) { - if (ran.contains(diagnostic.range)) { - allDiagnostics.push(diagnostic); - } - } + for (const diagnostic of this._diagnostics.getDiagnostics(resource)) { + if (ran.contains(diagnostic.range)) { + allDiagnostics.push(diagnostic); } - }); + } const codeActionContext: vscode.CodeActionContext = { diagnostics: allDiagnostics, @@ -317,7 +317,7 @@ class CodeActionAdapter { result.push({ title: candidate.title, command: candidate.command && this._commands.toInternal(candidate.command), - diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData), + diagnostics: candidate.diagnostics && candidate.diagnostics.map(TypeConverters.fromDiagnostic), edit: candidate.edit && TypeConverters.WorkspaceEdit.from(candidate.edit), kind: candidate.kind && candidate.kind.value }); @@ -468,20 +468,16 @@ class NavigateTypeAdapter { } } -interface RenameProvider2 extends vscode.RenameProvider { - resolveInitialRenameValue?(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<any>; -} - class RenameAdapter { - static supportsResolving(provider: RenameProvider2): boolean { - return typeof provider.resolveInitialRenameValue === 'function'; + static supportsResolving(provider: vscode.RenameProvider): boolean { + return typeof provider.prepareRename === 'function'; } private _documents: ExtHostDocuments; - private _provider: RenameProvider2; + private _provider: vscode.RenameProvider; - constructor(documents: ExtHostDocuments, provider: RenameProvider2) { + constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) { this._documents = documents; this._provider = provider; } @@ -514,24 +510,40 @@ class RenameAdapter { }); } - resolveInitialRenameValue(resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> { - if (typeof this._provider.resolveInitialRenameValue !== 'function') { + resolveRenameLocation(resource: URI, position: IPosition): TPromise<modes.RenameLocation> { + if (typeof this._provider.prepareRename !== 'function') { return TPromise.as(undefined); } let doc = this._documents.getDocumentData(resource).document; let pos = TypeConverters.toPosition(position); - return asWinJsPromise(token => this._provider.resolveInitialRenameValue(doc, pos, token)).then((value) => { - return <modes.RenameInitialValue>{ - range: TypeConverters.fromRange(value.range), - text: value.text - }; + return asWinJsPromise(token => this._provider.prepareRename(doc, pos, token)).then(rangeOrLocation => { + + let range: vscode.Range; + let text: string; + if (Range.isRange(rangeOrLocation)) { + range = rangeOrLocation; + text = doc.getText(rangeOrLocation); + + } else if (isObject(rangeOrLocation)) { + range = rangeOrLocation.range; + text = rangeOrLocation.placeholder; + } + + if (!range) { + return undefined; + } + + if (!range.contains(pos)) { + console.warn('INVALID rename location: range must contain position'); + return undefined; + } + return { range: TypeConverters.fromRange(range), text }; }); } } - class SuggestAdapter { static supportsResolving(provider: vscode.CompletionItemProvider): boolean { @@ -785,7 +797,7 @@ class ColorProviderAdapter { const colorInfos: IRawColorInfo[] = colors.map(ci => { return { - color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number], + color: TypeConverters.Color.from(ci.color), range: TypeConverters.fromRange(ci.range) }; }); @@ -797,7 +809,7 @@ class ColorProviderAdapter { provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise<modes.IColorPresentation[]> { const document = this._documents.getDocumentData(resource).document; const range = TypeConverters.toRange(raw.range); - const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]); + const color = TypeConverters.Color.to(raw.color); return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => { return value.map(TypeConverters.ColorPresentation.from); }); @@ -808,16 +820,16 @@ class FoldingProviderAdapter { constructor( private _documents: ExtHostDocuments, - private _provider: vscode.FoldingProvider + private _provider: vscode.FoldingRangeProvider ) { } - provideFoldingRanges(resource: URI): TPromise<modes.IFoldingRangeList> { + provideFoldingRanges(resource: URI, context: modes.FoldingContext): TPromise<modes.FoldingRange[]> { const doc = this._documents.getDocumentData(resource).document; - return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, token)).then(list => { - if (!Array.isArray(list.ranges)) { + return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => { + if (!Array.isArray(ranges)) { return void 0; } - return TypeConverters.FoldingRangeList.from(list); + return ranges.map(TypeConverters.FoldingRange.from); }); } } @@ -828,10 +840,15 @@ type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapt | SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter; +export interface ISchemeTransformer { + transformOutgoing(scheme: string): string; +} + export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { private static _handlePool: number = 0; + private readonly _schemeTransformer: ISchemeTransformer; private _proxy: MainThreadLanguageFeaturesShape; private _documents: ExtHostDocuments; private _commands: ExtHostCommands; @@ -841,11 +858,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { constructor( mainContext: IMainContext, + schemeTransformer: ISchemeTransformer, documents: ExtHostDocuments, commands: ExtHostCommands, heapMonitor: ExtHostHeapService, diagnostics: ExtHostDiagnostics ) { + this._schemeTransformer = schemeTransformer; this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures); this._documents = documents; this._commands = commands; @@ -853,6 +872,42 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { this._diagnostics = diagnostics; } + private _transformDocumentSelector(selector: vscode.DocumentSelector): ISerializedDocumentFilter[] { + if (Array.isArray(selector)) { + return selector.map(sel => this._doTransformDocumentSelector(sel)); + } + + return [this._doTransformDocumentSelector(selector)]; + } + + private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter { + if (typeof selector === 'string') { + return { + $serialized: true, + language: selector + }; + } + + if (selector) { + return { + $serialized: true, + language: selector.language, + scheme: this._transformScheme(selector.scheme), + pattern: selector.pattern, + exclusive: selector.exclusive + }; + } + + return undefined; + } + + private _transformScheme(scheme: string): string { + if (this._schemeTransformer && typeof scheme === 'string') { + return this._schemeTransformer.transformOutgoing(scheme); + } + return scheme; + } + private _createDisposable(handle: number): Disposable { return new Disposable(() => { this._adapter.delete(handle); @@ -882,7 +937,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider)); - this._proxy.$registerOutlineSupport(handle, selector); + this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -897,7 +952,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined; this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider)); - this._proxy.$registerCodeLensSupport(handle, selector, eventHandle); + this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector), eventHandle); let result = this._createDisposable(handle); if (eventHandle !== undefined) { @@ -920,7 +975,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider)); - this._proxy.$registerDeclaractionSupport(handle, selector); + this._proxy.$registerDeclaractionSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -930,7 +985,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable { const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider)); - this._proxy.$registerImplementationSupport(handle, selector); + this._proxy.$registerImplementationSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -940,7 +995,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable { const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider)); - this._proxy.$registerTypeDefinitionSupport(handle, selector); + this._proxy.$registerTypeDefinitionSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -952,7 +1007,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable { const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider)); - this._proxy.$registerHoverProvider(handle, selector); + this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -964,7 +1019,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider)); - this._proxy.$registerDocumentHighlightProvider(handle, selector); + this._proxy.$registerDocumentHighlightProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -976,7 +1031,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider)); - this._proxy.$registerReferenceSupport(handle, selector); + this._proxy.$registerReferenceSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -986,9 +1041,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { // --- quick fix - registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable { + registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable { const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider)); - this._proxy.$registerQuickFixSupport(handle, selector); + this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), metadata && metadata.providedCodeActionKinds ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined); return this._createDisposable(handle); } @@ -1001,7 +1056,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider)); - this._proxy.$registerDocumentFormattingSupport(handle, selector); + this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -1011,7 +1066,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider)); - this._proxy.$registerRangeFormattingSupport(handle, selector); + this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -1021,7 +1076,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable { const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider)); - this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters); + this._proxy.$registerOnTypeFormattingSupport(handle, this._transformDocumentSelector(selector), triggerCharacters); return this._createDisposable(handle); } @@ -1051,9 +1106,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { // --- rename - registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider, canUseProposedApi = false): vscode.Disposable { + registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider)); - this._proxy.$registerRenameSupport(handle, selector, canUseProposedApi && RenameAdapter.supportsResolving(provider)); + this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), RenameAdapter.supportsResolving(provider)); return this._createDisposable(handle); } @@ -1061,15 +1116,15 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName)); } - $resolveInitialRenameValue(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> { - return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveInitialRenameValue(resource, position)); + $resolveRenameLocation(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameLocation> { + return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position)); } // --- suggestion registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable { const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider)); - this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider)); + this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider)); return this._createDisposable(handle); } @@ -1089,7 +1144,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable { const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider)); - this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters); + this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector), triggerCharacters); return this._createDisposable(handle); } @@ -1101,7 +1156,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider)); - this._proxy.$registerDocumentLinkProvider(handle, selector); + this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -1115,7 +1170,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable { const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider)); - this._proxy.$registerDocumentColorProvider(handle, selector); + this._proxy.$registerDocumentColorProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } @@ -1127,14 +1182,14 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo)); } - registerFoldingProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable { + registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable { const handle = this._addNewAdapter(new FoldingProviderAdapter(this._documents, provider)); - this._proxy.$registerFoldingProvider(handle, selector); + this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector)); return this._createDisposable(handle); } - $provideFoldingRanges(handle: number, resource: UriComponents): TPromise<modes.IFoldingRangeList> { - return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource))); + $provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.FoldingRange[]> { + return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context)); } // --- configuration diff --git a/src/vs/workbench/api/node/extHostLogService.ts b/src/vs/workbench/api/node/extHostLogService.ts index 5fd777f894..8dc3dc9216 100644 --- a/src/vs/workbench/api/node/extHostLogService.ts +++ b/src/vs/workbench/api/node/extHostLogService.ts @@ -5,15 +5,10 @@ 'use strict'; import * as vscode from 'vscode'; -import { TPromise } from 'vs/base/common/winjs.base'; import { join } from 'vs/base/common/paths'; -import { mkdirp, dirExists } from 'vs/base/node/pfs'; -import Event from 'vs/base/common/event'; import { LogLevel } from 'vs/workbench/api/node/extHostTypes'; import { ILogService, DelegatedLogService } from 'vs/platform/log/common/log'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { memoize } from 'vs/base/common/decorators'; import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol'; @@ -24,9 +19,9 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic constructor( private _windowId: number, logLevel: LogLevel, - private _environmentService: IEnvironmentService + private _logsPath: string ) { - super(createSpdLogService(`exthost${_windowId}`, logLevel, _environmentService.logsPath)); + super(createSpdLogService(`exthost${_windowId}`, logLevel, _logsPath)); } $setLevel(level: LogLevel): void { @@ -42,40 +37,23 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic return logger; } + getLogDirectory(extensionID: string): string { + return join(this._logsPath, `${extensionID}_${this._windowId}`); + } + private createLogger(extensionID: string): ExtHostLogger { - const logsDirPath = join(this._environmentService.logsPath, `${extensionID}_${this._windowId}`); + const logsDirPath = this.getLogDirectory(extensionID); const logService = createSpdLogService(extensionID, this.getLevel(), logsDirPath); this._register(this.onDidChangeLogLevel(level => logService.setLevel(level))); - return new ExtHostLogger(logService, logsDirPath); + return new ExtHostLogger(logService); } } export class ExtHostLogger implements vscode.Logger { constructor( - private readonly _logService: ILogService, - private readonly _logDirectory: string - ) { - } - - get onDidChangeLogLevel(): Event<LogLevel> { - return this._logService.onDidChangeLogLevel; - } - - get currentLevel(): LogLevel { return this._logService.getLevel(); } - - @memoize - get logDirectory(): TPromise<string> { - return dirExists(this._logDirectory).then(exists => { - if (exists) { - return TPromise.wrap(null); - } else { - return mkdirp(this._logDirectory); - } - }).then(() => { - return this._logDirectory; - }); - } + private readonly _logService: ILogService + ) { } trace(message: string, ...args: any[]): void { return this._logService.trace(message, ...args); diff --git a/src/vs/workbench/api/node/extHostMessageService.ts b/src/vs/workbench/api/node/extHostMessageService.ts index 4862bfb164..4c3289ba05 100644 --- a/src/vs/workbench/api/node/extHostMessageService.ts +++ b/src/vs/workbench/api/node/extHostMessageService.ts @@ -5,7 +5,7 @@ 'use strict'; import Severity from 'vs/base/common/severity'; -import vscode = require('vscode'); +import * as vscode from 'vscode'; import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; diff --git a/src/vs/workbench/api/node/extHostProgress.ts b/src/vs/workbench/api/node/extHostProgress.ts index 4f8c80e073..361de33200 100644 --- a/src/vs/workbench/api/node/extHostProgress.ts +++ b/src/vs/workbench/api/node/extHostProgress.ts @@ -4,16 +4,20 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { Progress, ProgressOptions, CancellationToken } from 'vscode'; -import { MainThreadProgressShape } from './extHost.protocol'; +import { ProgressOptions } from 'vscode'; +import { MainThreadProgressShape, ExtHostProgressShape } from './extHost.protocol'; import { ProgressLocation } from './extHostTypeConverters'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { IProgressStep } from 'vs/platform/progress/common/progress'; +import { IProgressStep, Progress } from 'vs/platform/progress/common/progress'; +import { localize } from 'vs/nls'; +import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; +import { debounce } from 'vs/base/common/decorators'; -export class ExtHostProgress { +export class ExtHostProgress implements ExtHostProgressShape { private _proxy: MainThreadProgressShape; private _handles: number = 0; + private _mapHandleToCancellationSource: Map<number, CancellationTokenSource> = new Map(); constructor(proxy: MainThreadProgressShape) { this._proxy = proxy; @@ -21,30 +25,66 @@ export class ExtHostProgress { withProgress<R>(extension: IExtensionDescription, options: ProgressOptions, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> { const handle = this._handles++; - const { title, location } = options; - this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, tooltip: extension.name }); - return this._withProgress(handle, task); + const { title, location, cancellable } = options; + const source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name); + this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, source, cancellable }); + return this._withProgress(handle, task, cancellable); } - private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> { + private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>, cancellable: boolean): Thenable<R> { + let source: CancellationTokenSource; + if (cancellable) { + source = new CancellationTokenSource(); + this._mapHandleToCancellationSource.set(handle, source); + } - const progress = { - report: (p: IProgressStep) => { - this._proxy.$progressReport(handle, p); + const progressEnd = (handle: number): void => { + this._proxy.$progressEnd(handle); + this._mapHandleToCancellationSource.delete(handle); + if (source) { + source.dispose(); } }; let p: Thenable<R>; try { - p = task(progress, null); + p = task(new ProgressCallback(this._proxy, handle), cancellable ? source.token : CancellationToken.None); } catch (err) { - this._proxy.$progressEnd(handle); + progressEnd(handle); throw err; } - p.then(result => this._proxy.$progressEnd(handle), err => this._proxy.$progressEnd(handle)); + p.then(result => progressEnd(handle), err => progressEnd(handle)); return p; } + + public $acceptProgressCanceled(handle: number): void { + const source = this._mapHandleToCancellationSource.get(handle); + if (source) { + source.cancel(); + this._mapHandleToCancellationSource.delete(handle); + } + } } +function mergeProgress(result: IProgressStep, currentValue: IProgressStep): IProgressStep { + result.message = currentValue.message; + if (typeof currentValue.increment === 'number' && typeof result.message === 'number') { + result.increment += currentValue.increment; + } else if (typeof currentValue.increment === 'number') { + result.increment = currentValue.increment; + } + return result; +} + +class ProgressCallback extends Progress<IProgressStep> { + constructor(private _proxy: MainThreadProgressShape, private _handle: number) { + super(p => this.throttledReport(p)); + } + + @debounce(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null)) + throttledReport(p: IProgressStep): void { + this._proxy.$progressReport(this._handle, p); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/node/extHostQuickOpen.ts b/src/vs/workbench/api/node/extHostQuickOpen.ts index fe1420feb0..2e9c841826 100644 --- a/src/vs/workbench/api/node/extHostQuickOpen.ts +++ b/src/vs/workbench/api/node/extHostQuickOpen.ts @@ -29,9 +29,10 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { this._commands = commands; } + showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options: QuickPickOptions & { canSelectMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>; showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>; showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>; - showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | undefined> { + showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> { // clear state from last invocation this._onDidSelectItem = undefined; @@ -43,7 +44,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { placeHolder: options && options.placeHolder, matchOnDescription: options && options.matchOnDescription, matchOnDetail: options && options.matchOnDetail, - ignoreFocusLost: options && options.ignoreFocusOut + ignoreFocusLost: options && options.ignoreFocusOut, + canSelectMany: options && options.canPickMany }); const promise = TPromise.any(<TPromise<number | Item[]>[]>[quickPickWidget, itemsPromise]).then(values => { @@ -60,6 +62,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { let label: string; let description: string; let detail: string; + let picked: boolean; if (typeof item === 'string') { label = item; @@ -67,12 +70,14 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { label = item.label; description = item.description; detail = item.detail; + picked = item.picked; } pickItems.push({ label, description, handle, - detail + detail, + picked }); } @@ -89,6 +94,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { return quickPickWidget.then(handle => { if (typeof handle === 'number') { return items[handle]; + } else if (Array.isArray(handle)) { + return handle.map(h => items[h]); } return undefined; }); @@ -98,7 +105,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { return TPromise.wrapError(err); }); }); - return wireCancellationToken<Item>(token, promise, true); + return wireCancellationToken<Item | Item[]>(token, promise, true); } $onItemSelected(handle: number): void { diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 41d4b48b87..e3f72e9862 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -6,7 +6,7 @@ import URI, { UriComponents } from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { debounce } from 'vs/base/common/decorators'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { asWinJsPromise } from 'vs/base/common/async'; diff --git a/src/vs/workbench/api/node/extHostSearch.ts b/src/vs/workbench/api/node/extHostSearch.ts new file mode 100644 index 0000000000..cd78823a82 --- /dev/null +++ b/src/vs/workbench/api/node/extHostSearch.ts @@ -0,0 +1,64 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { asWinJsPromise } from 'vs/base/common/async'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IPatternInfo } from 'vs/platform/search/common/search'; +import * as vscode from 'vscode'; +import { ExtHostSearchShape, IMainContext, MainContext, MainThreadSearchShape } from './extHost.protocol'; + +export class ExtHostSearch implements ExtHostSearchShape { + + private readonly _proxy: MainThreadSearchShape; + private readonly _searchProvider = new Map<number, vscode.SearchProvider>(); + private _handlePool: number = 0; + + constructor(mainContext: IMainContext) { + this._proxy = mainContext.getProxy(MainContext.MainThreadSearch); + } + + registerSearchProvider(scheme: string, provider: vscode.SearchProvider) { + const handle = this._handlePool++; + this._searchProvider.set(handle, provider); + this._proxy.$registerSearchProvider(handle, scheme); + return { + dispose: () => { + this._searchProvider.delete(handle); + this._proxy.$unregisterProvider(handle); + } + }; + } + + $provideFileSearchResults(handle: number, session: number, query: string): TPromise<void> { + const provider = this._searchProvider.get(handle); + if (!provider.provideFileSearchResults) { + return TPromise.as(undefined); + } + const progress = { + report: (uri) => { + this._proxy.$handleFindMatch(handle, session, uri); + } + }; + return asWinJsPromise(token => provider.provideFileSearchResults(query, progress, token)); + } + + $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> { + const provider = this._searchProvider.get(handle); + if (!provider.provideTextSearchResults) { + return TPromise.as(undefined); + } + const progress = { + report: (data: vscode.TextSearchResult) => { + this._proxy.$handleFindMatch(handle, session, [data.uri, { + lineNumber: data.range.start.line, + preview: data.preview.leading + data.preview.matching + data.preview.trailing, + offsetAndLengths: [[data.preview.leading.length, data.preview.matching.length]] + }]); + } + }; + return asWinJsPromise(token => provider.provideTextSearchResults(pattern, options, progress, token)); + } +} diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 2a5c540957..2dee742675 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; +import URI, { UriComponents } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import * as Objects from 'vs/base/common/objects'; import { asWinJsPromise } from 'vs/base/common/async'; +import { Event, Emitter } from 'vs/base/common/event'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks'; @@ -18,7 +19,12 @@ import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from import * as types from 'vs/workbench/api/node/extHostTypes'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import * as vscode from 'vscode'; +import { + TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO, + ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO +} from '../shared/tasks'; +export { TaskExecutionDTO }; /* namespace ProblemPattern { @@ -278,20 +284,43 @@ namespace CommandOptions { } } +namespace ShellQuoteOptions { + export function from(value: vscode.ShellQuotingOptions): TaskSystem.ShellQuotingOptions { + if (value === void 0 || value === null) { + return undefined; + } + return { + escape: value.escape, + strong: value.strong, + weak: value.strong + }; + } +} + namespace ShellConfiguration { - export function from(value: { executable?: string, shellArgs?: string[] }): TaskSystem.ShellConfiguration { + export function from(value: { executable?: string, shellArgs?: string[], quotes?: vscode.ShellQuotingOptions }): TaskSystem.ShellConfiguration { if (value === void 0 || value === null || !value.executable) { return undefined; } let result: TaskSystem.ShellConfiguration = { executable: value.executable, - args: Strings.from(value.shellArgs) + args: Strings.from(value.shellArgs), + quoting: ShellQuoteOptions.from(value.quotes) }; return result; } } +namespace ShellString { + export function from(value: (string | vscode.ShellQuotedString)[]): TaskSystem.CommandString[] { + if (value === void 0 || value === null) { + return undefined; + } + return value.slice(0); + } +} + namespace Tasks { export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask[] { @@ -396,19 +425,292 @@ namespace Tasks { } function getShellCommand(value: vscode.ShellExecution): TaskSystem.CommandConfiguration { - if (typeof value.commandLine !== 'string') { + if (value.args) { + if (typeof value.command !== 'string' && typeof value.command.value !== 'string') { + return undefined; + } + let result: TaskSystem.CommandConfiguration = { + name: value.command, + args: ShellString.from(value.args), + runtime: TaskSystem.RuntimeType.Shell, + presentation: undefined + }; + if (value.options) { + result.options = CommandOptions.from(value.options); + } + return result; + } else { + if (typeof value.commandLine !== 'string') { + return undefined; + } + let result: TaskSystem.CommandConfiguration = { + name: value.commandLine, + runtime: TaskSystem.RuntimeType.Shell, + presentation: undefined + }; + if (value.options) { + result.options = CommandOptions.from(value.options); + } + return result; + } + } +} + +namespace TaskDefinitionDTO { + export function from(value: vscode.TaskDefinition): TaskDefinitionDTO { + if (value === void 0 || value === null) { return undefined; } - let result: TaskSystem.CommandConfiguration = { - name: value.commandLine, - runtime: TaskSystem.RuntimeType.Shell, - presentation: undefined + return value; + } + export function to(value: TaskDefinitionDTO): vscode.TaskDefinition { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } +} + +namespace TaskPresentationOptionsDTO { + export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } + export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } +} + +namespace ProcessExecutionOptionsDTO { + export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } + export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } +} + +namespace ProcessExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO { + let candidate = value as ProcessExecutionDTO; + return candidate && !!candidate.process; + } + export function from(value: vscode.ProcessExecution): ProcessExecutionDTO { + if (value === void 0 || value === null) { + return undefined; + } + let result: ProcessExecutionDTO = { + process: value.process, + args: value.args }; if (value.options) { - result.options = CommandOptions.from(value.options); + result.options = ProcessExecutionOptionsDTO.from(value.options); } return result; } + export function to(value: ProcessExecutionDTO): types.ProcessExecution { + if (value === void 0 || value === null) { + return undefined; + } + return new types.ProcessExecution(value.process, value.args, value.options); + } +} + +namespace ShellExecutionOptionsDTO { + export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } + export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions { + if (value === void 0 || value === null) { + return undefined; + } + return value; + } +} + +namespace ShellExecutionDTO { + export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO { + let candidate = value as ShellExecutionDTO; + return candidate && (!!candidate.commandLine || !!candidate.command); + } + export function from(value: vscode.ShellExecution): ShellExecutionDTO { + if (value === void 0 || value === null) { + return undefined; + } + let result: ShellExecutionDTO = { + }; + if (value.commandLine !== void 0) { + result.commandLine = value.commandLine; + } else { + result.command = value.command; + result.args = value.args; + } + if (value.options) { + result.options = ShellExecutionOptionsDTO.from(value.options); + } + return result; + } + export function to(value: ShellExecutionDTO): types.ShellExecution { + if (value === void 0 || value === null) { + return undefined; + } + if (value.commandLine) { + return new types.ShellExecution(value.commandLine, value.options); + } else { + return new types.ShellExecution(value.command, value.args ? value.args : [], value.options); + } + } +} + +namespace TaskHandleDTO { + export function from(value: types.Task): TaskHandleDTO { + let folder: UriComponents; + if (value.scope !== void 0 && typeof value.scope !== 'number') { + folder = value.scope.uri; + } + return { + id: value._id, + workspaceFolder: folder + }; + } +} + +namespace TaskDTO { + + export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO { + if (value === void 0 || value === null) { + return undefined; + } + let execution: ShellExecutionDTO | ProcessExecutionDTO; + if (value.execution instanceof types.ProcessExecution) { + execution = ProcessExecutionDTO.from(value.execution); + } else if (value.execution instanceof types.ShellExecution) { + execution = ShellExecutionDTO.from(value.execution); + } + let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition); + let scope: number | UriComponents; + if (value.scope) { + if (typeof value.scope === 'number') { + scope = value.scope; + } else { + scope = value.scope.uri.toJSON(); + } + } + if (!definition || !scope) { + return undefined; + } + let group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined; + let result: TaskDTO = { + _id: (value as types.Task)._id, + definition, + name: value.name, + source: { + extensionId: extension.id, + label: value.source, + scope: scope + }, + execution, + isBackground: value.isBackground, + group: group, + presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions), + problemMatchers: value.problemMatchers, + hasDefinedMatchers: (value as types.Task).hasDefinedMatchers + }; + return result; + } + export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task { + if (value === void 0 || value === null) { + return undefined; + } + let execution: types.ShellExecution | types.ProcessExecution; + if (ProcessExecutionDTO.is(value.execution)) { + execution = ProcessExecutionDTO.to(value.execution); + } else if (ShellExecutionDTO.is(value.execution)) { + execution = ShellExecutionDTO.to(value.execution); + } + let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition); + let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder; + if (value.source) { + if (value.source.scope !== void 0) { + if (typeof value.source.scope === 'number') { + scope = value.source.scope; + } else { + scope = workspace.resolveWorkspaceFolder(URI.revive(value.source.scope)); + } + } else { + scope = types.TaskScope.Workspace; + } + } + if (!definition || !scope) { + return undefined; + } + let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers); + if (value.isBackground !== void 0) { + result.isBackground = value.isBackground; + } + if (value.group !== void 0) { + result.group = types.TaskGroup.from(value.group); + } + if (value.presentationOptions) { + result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions); + } + if (value._id) { + result._id = value._id; + } + return result; + } +} + +namespace TaskFilterDTO { + export function from(value: vscode.TaskFilter): TaskFilterDTO { + return value; + } + + export function to(value: TaskFilterDTO): vscode.TaskFilter { + if (!value) { + return undefined; + } + return Objects.assign(Object.create(null), value); + } +} + +class TaskExecutionImpl implements vscode.TaskExecution { + constructor(readonly _id: string, private readonly _task: vscode.Task, private readonly _tasks: ExtHostTask) { + } + + get task(): vscode.Task { + return this._task; + } + + public terminate(): void { + this._tasks.terminateTask(this); + } +} + +namespace TaskExecutionDTO { + export function to(value: TaskExecutionDTO, tasks: ExtHostTask): vscode.TaskExecution { + return new TaskExecutionImpl(value.id, TaskDTO.to(value.task, tasks.extHostWorkspace), tasks); + } + export function from(value: vscode.TaskExecution): TaskExecutionDTO { + return { + id: (value as TaskExecutionImpl)._id, + task: undefined + }; + } } interface HandlerData { @@ -422,12 +724,21 @@ export class ExtHostTask implements ExtHostTaskShape { private _extHostWorkspace: ExtHostWorkspace; private _handleCounter: number; private _handlers: Map<number, HandlerData>; + private _taskExecutions: Map<string, TaskExecutionImpl>; + + private readonly _onDidExecuteTask: Emitter<vscode.TaskStartEvent> = new Emitter<vscode.TaskStartEvent>(); + private readonly _onDidTerminateTask: Emitter<vscode.TaskEndEvent> = new Emitter<vscode.TaskEndEvent>(); constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) { this._proxy = mainContext.getProxy(MainContext.MainThreadTask); this._extHostWorkspace = extHostWorkspace; this._handleCounter = 0; this._handlers = new Map<number, HandlerData>(); + this._taskExecutions = new Map<string, TaskExecutionImpl>(); + } + + public get extHostWorkspace(): ExtHostWorkspace { + return this._extHostWorkspace; } public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable { @@ -443,6 +754,69 @@ export class ExtHostTask implements ExtHostTaskShape { }); } + public fetchTasks(filter?: vscode.TaskFilter): Thenable<vscode.Task[]> { + return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then((values) => { + let result: vscode.Task[] = []; + for (let value of values) { + let task = TaskDTO.to(value, this._extHostWorkspace); + if (task) { + result.push(task); + } + } + return result; + }); + } + + public executeTask(extension: IExtensionDescription, task: vscode.Task): Thenable<vscode.TaskExecution> { + let tTask = (task as types.Task); + // We have a preserved ID. So the task didn't change. + if (tTask._id !== void 0) { + return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task)); + } else { + let dto = TaskDTO.from(task, extension); + if (dto === void 0) { + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break + return Promise.reject<vscode.TaskExecution>(new Error('Task is not valid')); + } + return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task)); + } + } + + public $taskStarted(execution: TaskExecutionDTO): void { + this._onDidExecuteTask.fire({ + execution: this.getTaskExecution(execution) + }); + } + + get taskExecutions(): vscode.TaskExecution[] { + let result: vscode.TaskExecution[] = []; + this._taskExecutions.forEach(value => result.push(value)); + return result; + } + + get onDidStartTask(): Event<vscode.TaskStartEvent> { + return this._onDidExecuteTask.event; + } + + public terminateTask(execution: vscode.TaskExecution): TPromise<void> { + if (!(execution instanceof TaskExecutionImpl)) { + throw new Error('No valid task execution provided'); + } + return this._proxy.$terminateTask((execution as TaskExecutionImpl)._id); + } + + public $taskEnded(execution: TaskExecutionDTO): void { + const _execution = this.getTaskExecution(execution); + this._taskExecutions.delete(execution.id); + this._onDidTerminateTask.fire({ + execution: _execution + }); + } + + get onDidEndTask(): Event<vscode.TaskEndEvent> { + return this._onDidTerminateTask.event; + } + public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> { let handler = this._handlers.get(handle); if (!handler) { @@ -460,4 +834,14 @@ export class ExtHostTask implements ExtHostTaskShape { private nextHandle(): number { return this._handleCounter++; } + + private getTaskExecution(execution: TaskExecutionDTO, task?: vscode.Task): TaskExecutionImpl { + let result: TaskExecutionImpl = this._taskExecutions.get(execution.id); + if (result) { + return result; + } + result = new TaskExecutionImpl(execution.id, task ? task : TaskDTO.to(execution.task, this._extHostWorkspace), this); + this._taskExecutions.set(execution.id, result); + return result; + } } diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index a2d916cfe3..ce694dfaa0 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -4,12 +4,19 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import vscode = require('vscode'); -import Event, { Emitter } from 'vs/base/common/event'; -import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext } from './extHost.protocol'; +import * as vscode from 'vscode'; +import * as cp from 'child_process'; +import * as os from 'os'; +import * as platform from 'vs/base/common/platform'; +import * as terminalEnvironment from 'vs/workbench/parts/terminal/node/terminalEnvironment'; +import Uri from 'vs/base/common/uri'; +import { Event, Emitter } from 'vs/base/common/event'; +import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/node/extHost.protocol'; +import { IMessageFromTerminalProcess } from 'vs/workbench/parts/terminal/node/terminal'; +import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; +import { ILogService } from 'vs/platform/log/common/log'; export class ExtHostTerminal implements vscode.Terminal { - private _name: string; private _id: number; private _proxy: MainThreadTerminalServiceShape; @@ -18,23 +25,37 @@ export class ExtHostTerminal implements vscode.Terminal { private _pidPromise: Promise<number>; private _pidPromiseComplete: (value: number) => any; + private readonly _onData: Emitter<string> = new Emitter<string>(); + public get onData(): Event<string> { + // Tell the main side to start sending data if it's not already + this._proxy.$registerOnDataListener(this._id); + return this._onData && this._onData.event; + } + constructor( proxy: MainThreadTerminalServiceShape, - name?: string, + name: string = '', + id?: number + ) { + this._proxy = proxy; + this._name = name; + if (id) { + this._id = id; + } + this._queuedRequests = []; + this._pidPromise = new Promise<number>(c => { + this._pidPromiseComplete = c; + }); + } + + public create( shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean - ) { - this._name = name; - this._queuedRequests = []; - this._proxy = proxy; - this._pidPromise = new Promise<number>(c => { - this._pidPromiseComplete = c; - }); - - this._proxy.$createTerminal(name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => { + ): void { + this._proxy.$createTerminal(this._name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => { this._id = id; this._queuedRequests.forEach((r) => { r.run(this._proxy, this._id); @@ -44,12 +65,10 @@ export class ExtHostTerminal implements vscode.Terminal { } public get name(): string { - this._checkDisposed(); return this._name; } public get processId(): Thenable<number> { - this._checkDisposed(); return this._pidPromise; } @@ -76,8 +95,15 @@ export class ExtHostTerminal implements vscode.Terminal { } public _setProcessId(processId: number): void { - this._pidPromiseComplete(processId); - this._pidPromiseComplete = null; + // The event may fire 2 times when the panel is restored + if (this._pidPromiseComplete) { + this._pidPromiseComplete(processId); + this._pidPromiseComplete = null; + } + } + + public _fireOnData(data: string): void { + this._onData.fire(data); } private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) { @@ -97,43 +123,69 @@ export class ExtHostTerminal implements vscode.Terminal { } export class ExtHostTerminalService implements ExtHostTerminalServiceShape { - - private _onDidCloseTerminal: Emitter<vscode.Terminal>; private _proxy: MainThreadTerminalServiceShape; - private _terminals: ExtHostTerminal[]; + private _terminals: ExtHostTerminal[] = []; + private _terminalProcesses: { [id: number]: cp.ChildProcess } = {}; - constructor(mainContext: IMainContext) { - this._onDidCloseTerminal = new Emitter<vscode.Terminal>(); + public get terminals(): ExtHostTerminal[] { return this._terminals; } + + private readonly _onDidCloseTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>(); + public get onDidCloseTerminal(): Event<vscode.Terminal> { return this._onDidCloseTerminal && this._onDidCloseTerminal.event; } + private readonly _onDidOpenTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>(); + public get onDidOpenTerminal(): Event<vscode.Terminal> { return this._onDidOpenTerminal && this._onDidOpenTerminal.event; } + + constructor( + mainContext: IMainContext, + private _extHostConfiguration: ExtHostConfiguration, + private _logService: ILogService + ) { this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService); - this._terminals = []; } public createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { - let terminal = new ExtHostTerminal(this._proxy, name, shellPath, shellArgs); + let terminal = new ExtHostTerminal(this._proxy, name); + terminal.create(shellPath, shellArgs); this._terminals.push(terminal); return terminal; } public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal { - let terminal = new ExtHostTerminal(this._proxy, options.name, options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/); + let terminal = new ExtHostTerminal(this._proxy, options.name); + terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/); this._terminals.push(terminal); return terminal; } - public get onDidCloseTerminal(): Event<vscode.Terminal> { - return this._onDidCloseTerminal && this._onDidCloseTerminal.event; + public $acceptTerminalProcessData(id: number, data: string): void { + let index = this._getTerminalIndexById(id); + if (index === null) { + return; + } + const terminal = this._terminals[index]; + terminal._fireOnData(data); } public $acceptTerminalClosed(id: number): void { let index = this._getTerminalIndexById(id); if (index === null) { - // The terminal was not created by the terminal API, ignore it return; } let terminal = this._terminals.splice(index, 1)[0]; this._onDidCloseTerminal.fire(terminal); } + public $acceptTerminalOpened(id: number, name: string): void { + let index = this._getTerminalIndexById(id); + if (index !== null) { + // The terminal has already been created (via createTerminal*), only fire the event + this._onDidOpenTerminal.fire(this.terminals[index]); + return; + } + let terminal = new ExtHostTerminal(this._proxy, name, id); + this._terminals.push(terminal); + this._onDidOpenTerminal.fire(terminal); + } + public $acceptTerminalProcessId(id: number, processId: number): void { let terminal = this._getTerminalById(id); if (terminal) { @@ -141,6 +193,99 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { } } + public $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void { + // TODO: This function duplicates a lot of TerminalProcessManager.createProcess, ideally + // they would be merged into a single implementation. + + const terminalConfig = this._extHostConfiguration.getConfiguration('terminal.integrated'); + + const locale = terminalConfig.get('setLocaleVariables') ? platform.locale : undefined; + if (!shellLaunchConfig.executable) { + // TODO: This duplicates some of TerminalConfigHelper.mergeDefaultShellPathAndArgs and should be merged + // this._configHelper.mergeDefaultShellPathAndArgs(shellLaunchConfig); + + const platformKey = platform.isWindows ? 'windows' : platform.isMacintosh ? 'osx' : 'linux'; + const shellConfigValue: string = terminalConfig.get(`shell.${platformKey}`); + const shellArgsConfigValue: string = terminalConfig.get(`shellArgs.${platformKey}`); + + shellLaunchConfig.executable = shellConfigValue; + shellLaunchConfig.args = shellArgsConfigValue; + } + + // TODO: Base the cwd on the last active workspace root + // const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file'); + // this.initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, lastActiveWorkspaceRootUri, this._configHelper); + const initialCwd = os.homedir(); + + // TODO: Pull in and resolve config settings + // // Resolve env vars from config and shell + // const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); + // const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); + // const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot); + // const envFromShell = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...shellLaunchConfig.env }, lastActiveWorkspaceRoot); + // shellLaunchConfig.env = envFromShell; + + // Merge process env with the env from config + const parentEnv = { ...process.env }; + // terminalEnvironment.mergeEnvironments(parentEnv, envFromConfig); + + // Continue env initialization, merging in the env from the launch + // config and adding keys that are needed to create the process + const env = terminalEnvironment.createTerminalEnv(parentEnv, shellLaunchConfig, initialCwd, locale, cols, rows); + let cwd = Uri.parse(require.toUrl('../../parts/terminal/node')).fsPath; + const options = { env, cwd, execArgv: [] }; + + // Fork the process and listen for messages + this._logService.debug(`Terminal process launching on ext host`, options); + this._terminalProcesses[id] = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], options); + this._terminalProcesses[id].on('message', (message: IMessageFromTerminalProcess) => { + switch (message.type) { + case 'pid': this._proxy.$sendProcessPid(id, <number>message.content); break; + case 'title': this._proxy.$sendProcessTitle(id, <string>message.content); break; + case 'data': this._proxy.$sendProcessData(id, <string>message.content); break; + } + }); + this._terminalProcesses[id].on('exit', (exitCode) => this._onProcessExit(id, exitCode)); + } + + public $acceptProcessInput(id: number, data: string): void { + if (this._terminalProcesses[id].connected) { + this._terminalProcesses[id].send({ event: 'input', data }); + } + } + + public $acceptProcessResize(id: number, cols: number, rows: number): void { + if (this._terminalProcesses[id].connected) { + try { + this._terminalProcesses[id].send({ event: 'resize', cols, rows }); + } catch (error) { + // We tried to write to a closed pipe / channel. + if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') { + throw (error); + } + } + } + } + + public $acceptProcessShutdown(id: number): void { + if (this._terminalProcesses[id].connected) { + this._terminalProcesses[id].send({ event: 'shutdown' }); + } + } + + private _onProcessExit(id: number, exitCode: number): void { + // Remove listeners + const process = this._terminalProcesses[id]; + process.removeAllListeners('message'); + process.removeAllListeners('exit'); + + // Remove process reference + delete this._terminalProcesses[id]; + + // Send exit event to main side + this._proxy.$sendProcessExit(id, exitCode); + } + private _getTerminalById(id: number): ExtHostTerminal { let index = this._getTerminalIndexById(id); return index !== null ? this._terminals[index] : null; @@ -149,6 +294,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { private _getTerminalIndexById(id: number): number { let index: number = null; this._terminals.some((terminal, i) => { + // TODO: This shouldn't be cas let thisId = (<any>terminal)._id; if (thisId === id) { index = i; @@ -161,7 +307,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { } class ApiRequest { - private _callback: (...args: any[]) => void; private _args: any[]; diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index 4f36bd5fb5..5b59869f3d 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -313,8 +313,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { export class ExtHostTextEditor implements vscode.TextEditor { - public readonly editorType = 'texteditor'; - private readonly _proxy: MainThreadTextEditorsShape; private readonly _id: string; private readonly _documentData: ExtHostDocumentData; diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index 08a2f55ee1..05383c784c 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { toThenable } from 'vs/base/common/async'; import { TPromise } from 'vs/base/common/winjs.base'; import { TextEditorSelectionChangeKind } from './extHostTypes'; diff --git a/src/vs/workbench/api/node/extHostTreeViews.ts b/src/vs/workbench/api/node/extHostTreeViews.ts index 2a7a487d06..41fafaa578 100644 --- a/src/vs/workbench/api/node/extHostTreeViews.ts +++ b/src/vs/workbench/api/node/extHostTreeViews.ts @@ -38,14 +38,22 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape { }); } - registerTreeDataProvider<T>(id: string, dataProvider: vscode.TreeDataProvider<T>, proposedApiFunction: <U>(fn: U) => U): vscode.TreeView<T> { - const treeView = this.createExtHostTreeViewer(id, dataProvider); + registerTreeDataProvider<T>(id: string, treeDataProvider: vscode.TreeDataProvider<T>): vscode.Disposable { + const treeView = this.createTreeView(id, { treeDataProvider }); + return { dispose: () => treeView.dispose() }; + } + + createTreeView<T>(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<T> }): vscode.TreeView<T> { + if (!options || !options.treeDataProvider) { + throw new Error('Options with treeDataProvider is mandatory'); + } + const treeView = this.createExtHostTreeViewer(viewId, options.treeDataProvider); return { - reveal: proposedApiFunction((element: T, options?: { select?: boolean }): Thenable<void> => { + reveal: (element: T, options?: { select?: boolean }): Thenable<void> => { return treeView.reveal(element, options); - }), + }, dispose: () => { - this.treeViews.delete(id); + this.treeViews.delete(viewId); treeView.dispose(); } }; @@ -144,7 +152,7 @@ class ExtHostTreeView<T> extends Disposable { private resolveTreeNode(element: T, parent?: TreeNode): TPromise<TreeNode> { return asWinJsPromise(() => this.dataProvider.getTreeItem(element)) - .then(extTreeItem => this.createHandle(element, extTreeItem, parent)) + .then(extTreeItem => this.createHandle(element, extTreeItem, parent, true)) .then(handle => this.getChildren(parent ? parent.item.handle : null) .then(() => { const cachedElement = this.getExtensionElement(handle); @@ -295,7 +303,7 @@ class ExtHostTreeView<T> extends Disposable { return item; } - private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent?: TreeNode): TreeItemHandle { + private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode, first?: boolean): TreeItemHandle { if (id) { return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`; } @@ -308,7 +316,7 @@ class ExtHostTreeView<T> extends Disposable { for (let counter = 0; counter <= childrenNodes.length; counter++) { const handle = `${prefix}/${counter}:${elementId}`; - if (!this.elements.has(handle) || existingHandle === handle) { + if (first || !this.elements.has(handle) || existingHandle === handle) { return handle; } } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index e921be2ddf..35f779d735 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Severity from 'vs/base/common/severity'; import * as modes from 'vs/editor/common/modes'; import * as types from './extHostTypes'; import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor'; @@ -21,6 +20,7 @@ import * as htmlContent from 'vs/base/common/htmlContent'; import { IRelativePattern } from 'vs/base/common/glob'; import { LanguageSelector, LanguageFilter } from 'vs/editor/common/modes/languageSelector'; import { WorkspaceEditDto, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol'; +import { MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers'; export interface PositionLike { line: number; @@ -83,34 +83,58 @@ export function fromPosition(position: types.Position): IPosition { return { lineNumber: position.line + 1, column: position.character + 1 }; } -export function fromDiagnosticSeverity(value: number): Severity { - switch (value) { - case types.DiagnosticSeverity.Error: - return Severity.Error; - case types.DiagnosticSeverity.Warning: - return Severity.Warning; - case types.DiagnosticSeverity.Information: - return Severity.Info; - case types.DiagnosticSeverity.Hint: - return Severity.Ignore; - } - return Severity.Error; +export function fromDiagnostic(value: vscode.Diagnostic): IMarkerData { + return { + ...fromRange(value.range), + message: value.message, + source: value.source, + code: String(value.code), + severity: fromDiagnosticSeverity(value.severity), + relatedInformation: value.relatedInformation && value.relatedInformation.map(fromDiagnosticRelatedInformation) + }; } -export function toDiagnosticSeverty(value: Severity): types.DiagnosticSeverity { +export function fromDiagnosticRelatedInformation(value: types.DiagnosticRelatedInformation): IRelatedInformation { + return { + ...fromRange(value.location.range), + message: value.message, + resource: value.location.uri + }; +} + +export function toDiagnosticRelatedInformation(value: IRelatedInformation): types.DiagnosticRelatedInformation { + return new types.DiagnosticRelatedInformation(new types.Location(value.resource, toRange(value)), value.message); +} + +export function fromDiagnosticSeverity(value: number): MarkerSeverity { switch (value) { - case Severity.Info: + case types.DiagnosticSeverity.Error: + return MarkerSeverity.Error; + case types.DiagnosticSeverity.Warning: + return MarkerSeverity.Warning; + case types.DiagnosticSeverity.Information: + return MarkerSeverity.Info; + case types.DiagnosticSeverity.Hint: + return MarkerSeverity.Hint; + } + return MarkerSeverity.Error; +} + +export function toDiagnosticSeverty(value: MarkerSeverity): types.DiagnosticSeverity { + switch (value) { + case MarkerSeverity.Info: return types.DiagnosticSeverity.Information; - case Severity.Warning: + case MarkerSeverity.Warning: return types.DiagnosticSeverity.Warning; - case Severity.Error: + case MarkerSeverity.Error: return types.DiagnosticSeverity.Error; - case Severity.Ignore: + case MarkerSeverity.Hint: return types.DiagnosticSeverity.Hint; } return types.DiagnosticSeverity.Error; } + export function fromViewColumn(column?: vscode.ViewColumn): EditorPosition { let editorColumn = EditorPosition.ONE; if (typeof column !== 'number') { @@ -220,7 +244,7 @@ export const TextEdit = { range: fromRange(edit.range) }; }, - to(edit: modes.TextEdit): vscode.TextEdit { + to(edit: modes.TextEdit): types.TextEdit { let result = new types.TextEdit(toRange(edit.range), edit.text); result.newEol = EndOfLine.to(edit.eol); return result; @@ -522,12 +546,15 @@ export namespace DocumentLink { } export namespace ColorPresentation { - export function to(colorPresentation: modes.IColorPresentation): vscode.ColorPresentation { - return { - label: colorPresentation.label, - textEdit: colorPresentation.textEdit ? TextEdit.to(colorPresentation.textEdit) : undefined, - additionalTextEdits: colorPresentation.additionalTextEdits ? colorPresentation.additionalTextEdits.map(value => TextEdit.to(value)) : undefined - }; + export function to(colorPresentation: modes.IColorPresentation): types.ColorPresentation { + let cp = new types.ColorPresentation(colorPresentation.label); + if (colorPresentation.textEdit) { + cp.textEdit = TextEdit.to(colorPresentation.textEdit); + } + if (colorPresentation.additionalTextEdits) { + cp.additionalTextEdits = colorPresentation.additionalTextEdits.map(value => TextEdit.to(value)); + } + return cp; } export function from(colorPresentation: vscode.ColorPresentation): modes.IColorPresentation { @@ -539,6 +566,15 @@ export namespace ColorPresentation { } } +export namespace Color { + export function to(c: [number, number, number, number]): types.Color { + return new types.Color(c[0], c[1], c[2], c[3]); + } + export function from(color: types.Color): [number, number, number, number] { + return [color.red, color.green, color.blue, color.alpha]; + } +} + export namespace TextDocumentSaveReason { export function to(reason: SaveReason): vscode.TextDocumentSaveReason { @@ -581,16 +617,35 @@ export namespace ProgressLocation { switch (loc) { case types.ProgressLocation.SourceControl: return MainProgressLocation.Scm; case types.ProgressLocation.Window: return MainProgressLocation.Window; + case types.ProgressLocation.Notification: return MainProgressLocation.Notification; } return undefined; } } -export namespace FoldingRangeList { - export function from(rangeList: vscode.FoldingRangeList): modes.IFoldingRangeList { - return { - ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1, type: r.type })) - }; +export namespace FoldingRange { + export function from(r: vscode.FoldingRange): modes.FoldingRange { + let range: modes.FoldingRange = { start: r.start + 1, end: r.end + 1 }; + if (r.kind) { + range.kind = FoldingRangeKind.from(r.kind); + } + return range; + } +} + +export namespace FoldingRangeKind { + export function from(kind: vscode.FoldingRangeKind | undefined): modes.FoldingRangeKind | undefined { + if (kind) { + switch (kind) { + case types.FoldingRangeKind.Comment: + return modes.FoldingRangeKind.Comment; + case types.FoldingRangeKind.Imports: + return modes.FoldingRangeKind.Imports; + case types.FoldingRangeKind.Region: + return modes.FoldingRangeKind.Region; + } + } + return void 0; } } @@ -641,7 +696,8 @@ function doToLanguageSelector(selector: string | vscode.DocumentFilter): string return { language: selector.language, scheme: selector.scheme, - pattern: toGlobPattern(selector.pattern) + pattern: toGlobPattern(selector.pattern), + exclusive: selector.exclusive }; } diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 3a9033931b..448ffb4c3a 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -208,7 +208,7 @@ export class Position { export class Range { - static isRange(thing: any): thing is Range { + static isRange(thing: any): thing is vscode.Range { if (thing instanceof Range) { return true; } @@ -718,6 +718,27 @@ export class Location { } } +export class DiagnosticRelatedInformation { + + static is(thing: any): thing is DiagnosticRelatedInformation { + if (!thing) { + return false; + } + return typeof (<DiagnosticRelatedInformation>thing).message === 'string' + && (<DiagnosticRelatedInformation>thing).location + && Range.isRange((<DiagnosticRelatedInformation>thing).location.range) + && URI.isUri((<DiagnosticRelatedInformation>thing).location.uri); + } + + location: Location; + message: string; + + constructor(location: Location, message: string) { + this.location = location; + this.message = message; + } +} + export class Diagnostic { range: Range; @@ -725,6 +746,7 @@ export class Diagnostic { source: string; code: string | number; severity: DiagnosticSeverity; + relatedInformation: DiagnosticRelatedInformation[]; constructor(range: Range, message: string, severity: DiagnosticSeverity = DiagnosticSeverity.Error) { this.range = range; @@ -854,6 +876,38 @@ export class SymbolInformation { } } +export class HierarchicalSymbolInformation { + name: string; + location: Location; + kind: SymbolKind; + range: Range; + children: HierarchicalSymbolInformation[]; + + constructor(name: string, kind: SymbolKind, location: Location, range: Range) { + this.name = name; + this.kind = kind; + this.location = location; + this.range = range; + this.children = []; + } + + static toFlatSymbolInformation(info: HierarchicalSymbolInformation): SymbolInformation[] { + let result: SymbolInformation[] = []; + HierarchicalSymbolInformation._toFlatSymbolInformation(info, undefined, result); + return result; + } + + private static _toFlatSymbolInformation(info: HierarchicalSymbolInformation, containerName: string, bucket: SymbolInformation[]): void { + bucket.push(new SymbolInformation(info.name, info.kind, containerName, new Location(info.location.uri, info.range))); + if (Array.isArray(info.children)) { + for (const child of info.children) { + HierarchicalSymbolInformation._toFlatSymbolInformation(child, info.name, bucket); + } + } + } + +} + export class CodeAction { title: string; @@ -881,6 +935,8 @@ export class CodeActionKind { public static readonly RefactorExtract = CodeActionKind.Refactor.append('extract'); public static readonly RefactorInline = CodeActionKind.Refactor.append('inline'); public static readonly RefactorRewrite = CodeActionKind.Refactor.append('rewrite'); + public static readonly Source = CodeActionKind.Empty.append('source'); + public static readonly SourceOrganizeImports = CodeActionKind.Source.append('organizeImports'); constructor( public readonly value: string @@ -1235,6 +1291,21 @@ export class TaskGroup implements vscode.TaskGroup { public static Test: TaskGroup = new TaskGroup('test', 'Test'); + public static from(value: string) { + switch (value) { + case 'clean': + return TaskGroup.Clean; + case 'build': + return TaskGroup.Build; + case 'rebuild': + return TaskGroup.Rebuild; + case 'test': + return TaskGroup.Test; + default: + return undefined; + } + } + constructor(id: string, _label: string) { if (typeof id !== 'string') { throw illegalArgument('name'); @@ -1306,19 +1377,49 @@ export class ProcessExecution implements vscode.ProcessExecution { set options(value: vscode.ProcessExecutionOptions) { this._options = value; } + + public computeId(): string { + const hash = crypto.createHash('md5'); + hash.update('process'); + if (this._process !== void 0) { + hash.update(this._process); + } + if (this._args && this._args.length > 0) { + for (let arg of this._args) { + hash.update(arg); + } + } + return hash.digest('hex'); + } } export class ShellExecution implements vscode.ShellExecution { private _commandLine: string; + private _command: string | vscode.ShellQuotedString; + private _args: (string | vscode.ShellQuotedString)[]; private _options: vscode.ShellExecutionOptions; - constructor(commandLine: string, options?: vscode.ShellExecutionOptions) { - if (typeof commandLine !== 'string') { - throw illegalArgument('commandLine'); + constructor(commandLine: string, options?: vscode.ShellExecutionOptions); + constructor(command: string | vscode.ShellQuotedString, args: (string | vscode.ShellQuotedString)[], options?: vscode.ShellExecutionOptions); + constructor(arg0: string | vscode.ShellQuotedString, arg1?: vscode.ShellExecutionOptions | (string | vscode.ShellQuotedString)[], arg2?: vscode.ShellExecutionOptions) { + if (Array.isArray(arg1)) { + if (!arg0) { + throw illegalArgument('command can\'t be undefined or null'); + } + if (typeof arg0 !== 'string' && typeof arg0.value !== 'string') { + throw illegalArgument('command'); + } + this._command = arg0; + this._args = arg1 as (string | vscode.ShellQuotedString)[]; + this._options = arg2; + } else { + if (typeof arg0 !== 'string') { + throw illegalArgument('commandLine'); + } + this._commandLine = arg0; + this._options = arg1; } - this._commandLine = commandLine; - this._options = options; } get commandLine(): string { @@ -1332,6 +1433,25 @@ export class ShellExecution implements vscode.ShellExecution { this._commandLine = value; } + get command(): string | vscode.ShellQuotedString { + return this._command; + } + + set command(value: string | vscode.ShellQuotedString) { + if (typeof value !== 'string' && typeof value.value !== 'string') { + throw illegalArgument('command'); + } + this._command = value; + } + + get args(): (string | vscode.ShellQuotedString)[] { + return this._args; + } + + set args(value: (string | vscode.ShellQuotedString)[]) { + this._args = value || []; + } + get options(): vscode.ShellExecutionOptions { return this._options; } @@ -1339,6 +1459,29 @@ export class ShellExecution implements vscode.ShellExecution { set options(value: vscode.ShellExecutionOptions) { this._options = value; } + + public computeId(): string { + const hash = crypto.createHash('md5'); + hash.update('shell'); + if (this._commandLine !== void 0) { + hash.update(this._commandLine); + } + if (this._command !== void 0) { + hash.update(typeof this._command === 'string' ? this._command : this._command.value); + } + if (this._args && this._args.length > 0) { + for (let arg of this._args) { + hash.update(typeof arg === 'string' ? arg : arg.value); + } + } + return hash.digest('hex'); + } +} + +export enum ShellQuoting { + Escape = 1, + Strong = 2, + Weak = 3 } export enum TaskScope { @@ -1348,6 +1491,8 @@ export enum TaskScope { export class Task implements vscode.Task { + private __id: string; + private _definition: vscode.TaskDefinition; private _definitionKey: string; private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder; @@ -1396,6 +1541,35 @@ export class Task implements vscode.Task { this._isBackground = false; } + get _id(): string { + return this.__id; + } + + set _id(value: string) { + this.__id = value; + } + + private clear(): void { + if (this.__id === void 0) { + return; + } + this.__id = undefined; + this._scope = undefined; + this._definitionKey = undefined; + this._definition = undefined; + if (this._execution instanceof ProcessExecution) { + this._definition = { + type: 'process', + id: this._execution.computeId() + }; + } else if (this._execution instanceof ShellExecution) { + this._definition = { + type: 'shell', + id: this._execution.computeId() + }; + } + } + get definition(): vscode.TaskDefinition { return this._definition; } @@ -1404,6 +1578,7 @@ export class Task implements vscode.Task { if (value === void 0 || value === null) { throw illegalArgument('Kind can\'t be undefined or null'); } + this.clear(); this._definitionKey = undefined; this._definition = value; } @@ -1422,6 +1597,7 @@ export class Task implements vscode.Task { } set target(value: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder) { + this.clear(); this._scope = value; } @@ -1433,6 +1609,7 @@ export class Task implements vscode.Task { if (typeof value !== 'string') { throw illegalArgument('name'); } + this.clear(); this._name = value; } @@ -1444,6 +1621,7 @@ export class Task implements vscode.Task { if (value === null) { value = undefined; } + this.clear(); this._execution = value; } @@ -1457,6 +1635,7 @@ export class Task implements vscode.Task { this._hasDefinedMatchers = false; return; } + this.clear(); this._problemMatchers = value; this._hasDefinedMatchers = true; } @@ -1473,6 +1652,7 @@ export class Task implements vscode.Task { if (value !== true && value !== false) { value = false; } + this.clear(); this._isBackground = value; } @@ -1484,6 +1664,7 @@ export class Task implements vscode.Task { if (typeof value !== 'string' || value.length === 0) { throw illegalArgument('source must be a string of length > 0'); } + this.clear(); this._source = value; } @@ -1496,6 +1677,7 @@ export class Task implements vscode.Task { this._group = undefined; return; } + this.clear(); this._group = value; } @@ -1507,6 +1689,7 @@ export class Task implements vscode.Task { if (value === null) { value = undefined; } + this.clear(); this._presentationOptions = value; } } @@ -1515,6 +1698,7 @@ export class Task implements vscode.Task { export enum ProgressLocation { SourceControl = 1, Window = 10, + Notification = 15 } export class TreeItem { @@ -1600,8 +1784,9 @@ export class Breakpoint { readonly enabled: boolean; readonly condition?: string; readonly hitCondition?: string; + readonly logMessage?: string; - protected constructor(enabled?: boolean, condition?: string, hitCondition?: string) { + protected constructor(enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) { this.enabled = typeof enabled === 'boolean' ? enabled : true; if (typeof condition === 'string') { this.condition = condition; @@ -1609,14 +1794,17 @@ export class Breakpoint { if (typeof hitCondition === 'string') { this.hitCondition = hitCondition; } + if (typeof logMessage === 'string') { + this.logMessage = logMessage; + } } } export class SourceBreakpoint extends Breakpoint { readonly location: Location; - constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string) { - super(enabled, condition, hitCondition); + constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) { + super(enabled, condition, hitCondition, logMessage); if (location === null) { throw illegalArgument('location'); } @@ -1627,8 +1815,8 @@ export class SourceBreakpoint extends Breakpoint { export class FunctionBreakpoint extends Breakpoint { readonly functionName: string; - constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string) { - super(enabled, condition, hitCondition); + constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) { + super(enabled, condition, hitCondition, logMessage); if (!functionName) { throw illegalArgument('functionName'); } @@ -1661,59 +1849,85 @@ export enum LogLevel { //#region file api // todo@remote -export enum FileChangeType { +export enum DeprecatedFileChangeType { Updated = 0, Added = 1, Deleted = 2 } -export enum FileType { +export enum FileChangeType { + Changed = 1, + Created = 2, + Deleted = 3, +} + +export enum DeprecatedFileType { File = 0, Dir = 1, Symlink = 2 } +export class FileSystemError extends Error { + + static FileExists(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'EntryExists', FileSystemError.FileExists); + } + static FileNotFound(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'EntryNotFound', FileSystemError.FileNotFound); + } + static FileNotADirectory(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'EntryNotADirectory', FileSystemError.FileNotADirectory); + } + static FileIsADirectory(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'EntryIsADirectory', FileSystemError.FileIsADirectory); + } + static NoPermissions(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'NoPermissions', FileSystemError.NoPermissions); + } + static Unavailable(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, 'Unavailable', FileSystemError.Unavailable); + } + + constructor(uriOrMessage?: string | URI, code?: string, terminator?: Function) { + super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage); + this.name = code ? `${code} (FileSystemError)` : `FileSystemError`; + + // workaround when extending builtin objects and when compiling to ES5, see: + // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work + if (typeof (<any>Object).setPrototypeOf === 'function') { + (<any>Object).setPrototypeOf(this, FileSystemError.prototype); + } + + if (typeof Error.captureStackTrace === 'function' && typeof terminator === 'function') { + // nice stack traces + Error.captureStackTrace(this, terminator); + } + } +} + //#endregion //#region folding api -export class FoldingRangeList { - - ranges: FoldingRange[]; - - constructor(ranges: FoldingRange[]) { - this.ranges = ranges; - } -} - export class FoldingRange { - startLine: number; + start: number; - endLine: number; + end: number; - type?: FoldingRangeType | string; + kind?: FoldingRangeKind; - constructor(startLine: number, endLine: number, type?: FoldingRangeType | string) { - this.startLine = startLine; - this.endLine = endLine; - this.type = type; + constructor(start: number, end: number, kind?: FoldingRangeKind) { + this.start = start; + this.end = end; + this.kind = kind; } } -export enum FoldingRangeType { - /** - * Folding range for a comment - */ - Comment = 'comment', - /** - * Folding range for a imports or includes - */ - Imports = 'imports', - /** - * Folding range for a region (e.g. `#region`) - */ - Region = 'region' +export enum FoldingRangeKind { + Comment = 1, + Imports = 2, + Region = 3 } -//#endregion \ No newline at end of file +//#endregion diff --git a/src/vs/workbench/api/node/extHostUrls.ts b/src/vs/workbench/api/node/extHostUrls.ts new file mode 100644 index 0000000000..c17ca7b403 --- /dev/null +++ b/src/vs/workbench/api/node/extHostUrls.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from './extHost.protocol'; +import URI, { UriComponents } from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { toDisposable } from 'vs/base/common/lifecycle'; + +export class ExtHostUrls implements ExtHostUrlsShape { + + private static HandlePool = 0; + private readonly _proxy: MainThreadUrlsShape; + + private handles = new Set<string>(); + private handlers = new Map<number, vscode.ProtocolHandler>(); + + constructor( + mainContext: IMainContext + ) { + this._proxy = mainContext.getProxy(MainContext.MainThreadUrls); + } + + registerProtocolHandler(extensionId: string, handler: vscode.ProtocolHandler): vscode.Disposable { + if (this.handles.has(extensionId)) { + throw new Error(`Protocol handler already registered for extension ${extensionId}`); + } + + const handle = ExtHostUrls.HandlePool++; + this.handles.add(extensionId); + this.handlers.set(handle, handler); + this._proxy.$registerProtocolHandler(handle, extensionId); + + return toDisposable(() => { + this.handles.delete(extensionId); + this.handlers.delete(handle); + this._proxy.$unregisterProtocolHandler(handle); + }); + } + + $handleExternalUri(handle: number, uri: UriComponents): TPromise<void> { + const handler = this.handlers.get(handle); + + if (!handler) { + return TPromise.as(null); + } + + handler.handleUri(URI.revive(uri)); + return TPromise.as(null); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/node/extHostWebview.ts b/src/vs/workbench/api/node/extHostWebview.ts index f7c16cb6fd..6b5286caa5 100644 --- a/src/vs/workbench/api/node/extHostWebview.ts +++ b/src/vs/workbench/api/node/extHostWebview.ts @@ -3,71 +3,36 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewHandle } from './extHost.protocol'; +import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewPanelHandle } from './extHost.protocol'; import * as vscode from 'vscode'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters'; import { Position } from 'vs/platform/editor/common/editor'; import { TPromise } from 'vs/base/common/winjs.base'; +import { Disposable } from './extHostTypes'; export class ExtHostWebview implements vscode.Webview { - public readonly editorType = 'webview'; - - private _title: string; + private readonly _handle: WebviewPanelHandle; + private readonly _proxy: MainThreadWebviewsShape; private _html: string; private _options: vscode.WebviewOptions; private _isDisposed: boolean = false; - private _viewColumn: vscode.ViewColumn; - public readonly onMessageEmitter = new Emitter<any>(); - public readonly onDidReceiveMessage: Event<any> = this.onMessageEmitter.event; - - public readonly onDisposeEmitter = new Emitter<void>(); - public readonly onDidDispose: Event<void> = this.onDisposeEmitter.event; - - public readonly onDidChangeViewColumnEmitter = new Emitter<vscode.ViewColumn>(); - public readonly onDidChangeViewColumn: Event<vscode.ViewColumn> = this.onDidChangeViewColumnEmitter.event; + readonly _onMessageEmitter = new Emitter<any>(); + public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event; constructor( - private readonly _handle: WebviewHandle, - private readonly _proxy: MainThreadWebviewsShape, - private readonly _uri: vscode.Uri, - viewColumn: vscode.ViewColumn, + handle: WebviewPanelHandle, + proxy: MainThreadWebviewsShape, options: vscode.WebviewOptions ) { - this._viewColumn = viewColumn; + this._handle = handle; + this._proxy = proxy; this._options = options; } - public dispose() { - if (this._isDisposed) { - return; - } - - this._isDisposed = true; - this._proxy.$disposeWebview(this._handle); - - this.onDisposeEmitter.dispose(); - this.onMessageEmitter.dispose(); - this.onDidChangeViewColumnEmitter.dispose(); - } - - get uri(): vscode.Uri { - this.assertNotDisposed(); - return this._uri; - } - - get title(): string { - this.assertNotDisposed(); - return this._title; - } - - set title(value: string) { - this.assertNotDisposed(); - if (this._title !== value) { - this._title = value; - this._proxy.$setTitle(this._handle, value); - } + dispose() { + this._onMessageEmitter.dispose(); } get html(): string { @@ -88,22 +53,127 @@ export class ExtHostWebview implements vscode.Webview { return this._options; } + public postMessage(message: any): Thenable<boolean> { + this.assertNotDisposed(); + return this._proxy.$postMessage(this._handle, message); + } + + private assertNotDisposed() { + if (this._isDisposed) { + throw new Error('Webview is disposed'); + } + } +} + +export class ExtHostWebviewPanel implements vscode.WebviewPanel { + + private readonly _handle: WebviewPanelHandle; + private readonly _proxy: MainThreadWebviewsShape; + private readonly _viewType: string; + private _title: string; + + private readonly _options: vscode.WebviewPanelOptions; + private readonly _webview: ExtHostWebview; + private _isDisposed: boolean = false; + private _viewColumn: vscode.ViewColumn; + private _visible: boolean = true; + + readonly _onDisposeEmitter = new Emitter<void>(); + public readonly onDidDispose: Event<void> = this._onDisposeEmitter.event; + + readonly _onDidChangeViewStateEmitter = new Emitter<vscode.WebviewPanelOnDidChangeViewStateEvent>(); + public readonly onDidChangeViewState: Event<vscode.WebviewPanelOnDidChangeViewStateEvent> = this._onDidChangeViewStateEmitter.event; + + + constructor( + handle: WebviewPanelHandle, + proxy: MainThreadWebviewsShape, + viewType: string, + title: string, + viewColumn: vscode.ViewColumn, + editorOptions: vscode.WebviewPanelOptions, + webview: ExtHostWebview + ) { + this._handle = handle; + this._proxy = proxy; + this._viewType = viewType; + this._options = editorOptions; + this._viewColumn = viewColumn; + this._title = title; + this._webview = webview; + } + + public dispose() { + if (this._isDisposed) { + return; + } + + this._isDisposed = true; + this._onDisposeEmitter.fire(); + + this._proxy.$disposeWebview(this._handle); + + this._webview.dispose(); + + this._onDisposeEmitter.dispose(); + this._onDidChangeViewStateEmitter.dispose(); + } + + get webview() { + this.assertNotDisposed(); + return this._webview; + } + + get viewType(): string { + this.assertNotDisposed(); + return this._viewType; + } + + get title(): string { + this.assertNotDisposed(); + return this._title; + } + + set title(value: string) { + this.assertNotDisposed(); + if (this._title !== value) { + this._title = value; + this._proxy.$setTitle(this._handle, value); + } + } + + get options() { + return this._options; + } + get viewColumn(): vscode.ViewColumn { this.assertNotDisposed(); return this._viewColumn; } - set viewColumn(value: vscode.ViewColumn) { + _setViewColumn(value: vscode.ViewColumn) { this.assertNotDisposed(); this._viewColumn = value; } - public postMessage(message: any): Thenable<boolean> { - return this._proxy.$sendMessage(this._handle, message); + get visible(): boolean { + this.assertNotDisposed(); + return this._visible; } - public show(viewColumn: vscode.ViewColumn): void { - this._proxy.$show(this._handle, typeConverters.fromViewColumn(viewColumn)); + _setVisible(value: boolean) { + this.assertNotDisposed(); + this._visible = value; + } + + public postMessage(message: any): Thenable<boolean> { + this.assertNotDisposed(); + return this._proxy.$postMessage(this._handle, message); + } + + public reveal(viewColumn?: vscode.ViewColumn): void { + this.assertNotDisposed(); + this._proxy.$reveal(this._handle, viewColumn ? typeConverters.fromViewColumn(viewColumn) : undefined); } private assertNotDisposed() { @@ -114,11 +184,12 @@ export class ExtHostWebview implements vscode.Webview { } export class ExtHostWebviews implements ExtHostWebviewsShape { - private static handlePool = 0; + private static webviewHandlePool = 1; private readonly _proxy: MainThreadWebviewsShape; - private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>(); + private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewPanel>(); + private readonly _serializers = new Map<string, vscode.WebviewPanelSerializer>(); constructor( mainContext: IMainContext @@ -127,54 +198,103 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } createWebview( - uri: vscode.Uri, + viewType: string, title: string, viewColumn: vscode.ViewColumn, - options: vscode.WebviewOptions - ): vscode.Webview { - const handle = ExtHostWebviews.handlePool++; - this._proxy.$createWebview(handle, uri, title, typeConverters.fromViewColumn(viewColumn), options); + options: (vscode.WebviewPanelOptions & vscode.WebviewOptions) | undefined, + extensionFolderPath: string + ): vscode.WebviewPanel { + options = options || {}; + const handle = ExtHostWebviews.webviewHandlePool++ + ''; + this._proxy.$createWebviewPanel(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath); - const webview = new ExtHostWebview(handle, this._proxy, uri, viewColumn, options); - this._webviews.set(handle, webview); - return webview; + const webview = new ExtHostWebview(handle, this._proxy, options); + const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview); + this._webviewPanels.set(handle, panel); + return panel; } - $onMessage(handle: WebviewHandle, message: any): void { - const webview = this.getWebview(handle); - if (webview) { - webview.onMessageEmitter.fire(message); + registerWebviewPanelSerializer( + viewType: string, + serializer: vscode.WebviewPanelSerializer + ): vscode.Disposable { + if (this._serializers.has(viewType)) { + throw new Error(`Serializer for '${viewType}' already registered`); + } + + this._serializers.set(viewType, serializer); + this._proxy.$registerSerializer(viewType); + + return new Disposable(() => { + this._serializers.delete(viewType); + this._proxy.$unregisterSerializer(viewType); + }); + } + + $onMessage(handle: WebviewPanelHandle, message: any): void { + const panel = this.getWebviewPanel(handle); + if (panel) { + panel.webview._onMessageEmitter.fire(message); } } - $onDidChangeActiveWeview(handle: WebviewHandle | undefined): void { - this._onDidChangeActiveWebview.fire(this.getWebview(handle)); - } - - $onDidDisposeWeview(handle: WebviewHandle): Thenable<void> { - const webview = this.getWebview(handle); - if (webview) { - webview.onDisposeEmitter.fire(); - this._webviews.delete(handle); - } - return TPromise.as(void 0); - } - - $onDidChangePosition(handle: WebviewHandle, newPosition: Position): void { - const webview = this.getWebview(handle); - if (webview) { - const newViewColumn = typeConverters.toViewColumn(newPosition); - if (webview.viewColumn !== newViewColumn) { - webview.viewColumn = newViewColumn; - webview.onDidChangeViewColumnEmitter.fire(newViewColumn); + $onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, visible: boolean, position: Position): void { + const panel = this.getWebviewPanel(handle); + if (panel) { + const viewColumn = typeConverters.toViewColumn(position); + if (panel.visible !== visible || panel.viewColumn !== viewColumn) { + panel._setVisible(visible); + panel._setViewColumn(viewColumn); + panel._onDidChangeViewStateEmitter.fire({ webviewPanel: panel }); } } } - private readonly _onDidChangeActiveWebview = new Emitter<ExtHostWebview | undefined>(); - public readonly onDidChangeActiveWebview = this._onDidChangeActiveWebview.event; + $onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void> { + const panel = this.getWebviewPanel(handle); + if (panel) { + panel.dispose(); + this._webviewPanels.delete(handle); + } + return TPromise.as(void 0); + } - private getWebview(handle: WebviewHandle) { - return this._webviews.get(handle); + $deserializeWebviewPanel( + webviewHandle: WebviewPanelHandle, + viewType: string, + title: string, + state: any, + position: Position, + options: vscode.WebviewOptions & vscode.WebviewPanelOptions + ): Thenable<void> { + const serializer = this._serializers.get(viewType); + if (!serializer) { + return TPromise.wrapError(new Error(`No serializer found for '${viewType}'`)); + } + + const webview = new ExtHostWebview(webviewHandle, this._proxy, options); + const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeConverters.toViewColumn(position), options, webview); + this._webviewPanels.set(webviewHandle, revivedPanel); + return serializer.deserializeWebviewPanel(revivedPanel, state); + } + + $serializeWebviewPanel( + webviewHandle: WebviewPanelHandle + ): Thenable<any> { + const panel = this.getWebviewPanel(webviewHandle); + if (!panel) { + return TPromise.as(undefined); + } + + const serialzer = this._serializers.get(panel.viewType); + if (!serialzer) { + return TPromise.as(undefined); + } + + return serialzer.serializeWebviewPanel(panel); + } + + private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewPanel | undefined { + return this._webviewPanels.get(handle); } } \ No newline at end of file diff --git a/src/vs/workbench/api/node/extHostWindow.ts b/src/vs/workbench/api/node/extHostWindow.ts index d49af6a7a9..27a0ea587c 100644 --- a/src/vs/workbench/api/node/extHostWindow.ts +++ b/src/vs/workbench/api/node/extHostWindow.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext } from './extHost.protocol'; import { WindowState } from 'vscode'; diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index 0f1ccde5b1..8cf5d3aeda 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -5,10 +5,10 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { normalize } from 'vs/base/common/paths'; import { delta as arrayDelta } from 'vs/base/common/arrays'; -import { relative, dirname } from 'path'; +import { relative, posix } from 'path'; import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext, MainThreadMessageServiceShape } from './extHost.protocol'; import * as vscode from 'vscode'; @@ -121,10 +121,14 @@ class ExtHostWorkspaceImpl extends Workspace { getWorkspaceFolder(uri: URI, resolveParent?: boolean): vscode.WorkspaceFolder { if (resolveParent && this._structure.get(uri.toString())) { // `uri` is a workspace folder so we check for its parent - uri = uri.with({ path: dirname(uri.path) }); + uri = uri.with({ path: posix.dirname(uri.path) }); } return this._structure.findSubstr(uri.toString()); } + + resolveWorkspaceFolder(uri: URI): vscode.WorkspaceFolder { + return this._structure.get(uri.toString()); + } } export class ExtHostWorkspace implements ExtHostWorkspaceShape { @@ -239,6 +243,13 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent); } + resolveWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder { + if (!this._actualWorkspace) { + return undefined; + } + return this._actualWorkspace.resolveWorkspaceFolder(uri); + } + getPath(): string { // this is legacy from the days before having @@ -352,7 +363,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { if (token) { token.onCancellationRequested(() => this._proxy.$cancelSearch(requestId)); } - return result.then(data => data.map(URI.revive)); + return result.then(data => Array.isArray(data) ? data.map(URI.revive) : []); } saveAll(includeUntitled?: boolean): Thenable<boolean> { diff --git a/src/vs/workbench/api/shared/tasks.ts b/src/vs/workbench/api/shared/tasks.ts new file mode 100644 index 0000000000..fa0bd1468f --- /dev/null +++ b/src/vs/workbench/api/shared/tasks.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { UriComponents } from 'vs/base/common/uri'; + +export interface TaskDefinitionDTO { + type: string; + [name: string]: any; +} + +export interface TaskPresentationOptionsDTO { + reveal?: number; + echo?: boolean; + focus?: boolean; + panel?: number; +} + +export interface ExecutionOptionsDTO { + cwd?: string; + env?: { [key: string]: string }; +} + +export interface ProcessExecutionOptionsDTO extends ExecutionOptionsDTO { +} + +export interface ProcessExecutionDTO { + process: string; + args: string[]; + options?: ProcessExecutionOptionsDTO; +} + +export interface ShellQuotingOptionsDTO { + escape?: string | { + escapeChar: string; + charsToEscape: string; + }; + strong?: string; + weak?: string; +} + +export interface ShellExecutionOptionsDTO extends ExecutionOptionsDTO { + executable?: string; + shellArgs?: string[]; + shellQuoting?: ShellQuotingOptionsDTO; +} + +export interface ShellQuotedStringDTO { + value: string; + quoting: number; +} + +export interface ShellExecutionDTO { + commandLine?: string; + command?: string | ShellQuotedStringDTO; + args?: (string | ShellQuotedStringDTO)[]; + options?: ShellExecutionOptionsDTO; +} + +export interface TaskSourceDTO { + label: string; + extensionId?: string; + scope?: number | UriComponents; +} + +export interface TaskHandleDTO { + id: string; + workspaceFolder: UriComponents; +} + +export interface TaskDTO { + _id: string; + name: string; + execution: ProcessExecutionDTO | ShellExecutionDTO; + definition: TaskDefinitionDTO; + isBackground: boolean; + source: TaskSourceDTO; + group?: string; + presentationOptions: TaskPresentationOptionsDTO; + problemMatchers: string[]; + hasDefinedMatchers: boolean; +} + +export interface TaskExecutionDTO { + id: string; + task: TaskDTO; +} + +export interface TaskFilterDTO { + version?: string; + type?: string; +} \ No newline at end of file diff --git a/src/vs/workbench/browser/actions.ts b/src/vs/workbench/browser/actions.ts index fb40e66877..354cc4dbc4 100644 --- a/src/vs/workbench/browser/actions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Registry } from 'vs/platform/registry/common/platform'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { Action, IAction } from 'vs/base/common/actions'; import { BaseActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; diff --git a/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts b/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts index e333a9eccf..d8dd371ca0 100644 --- a/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleActivityBarVisibility.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleCenteredLayout.ts b/src/vs/workbench/browser/actions/toggleCenteredLayout.ts index 80459fa4e5..8629e6ad6b 100644 --- a/src/vs/workbench/browser/actions/toggleCenteredLayout.ts +++ b/src/vs/workbench/browser/actions/toggleCenteredLayout.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -26,11 +26,11 @@ class ToggleCenteredLayout extends Action { } public run(): TPromise<any> { - this.partService.toggleCenteredEditorLayout(); + this.partService.centerEditorLayout(!this.partService.isEditorLayoutCentered()); return TPromise.as(null); } } const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions); -registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', nls.localize('view', "View")); \ No newline at end of file +registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', nls.localize('view', "View")); diff --git a/src/vs/workbench/browser/actions/toggleEditorLayout.ts b/src/vs/workbench/browser/actions/toggleEditorLayout.ts index 86717ae11b..82b007e434 100644 --- a/src/vs/workbench/browser/actions/toggleEditorLayout.ts +++ b/src/vs/workbench/browser/actions/toggleEditorLayout.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/actions'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts index 93a48217a6..258bc57dd9 100644 --- a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts +++ b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleSidebarVisibility.ts b/src/vs/workbench/browser/actions/toggleSidebarVisibility.ts index 36d443728b..69a1a5673c 100644 --- a/src/vs/workbench/browser/actions/toggleSidebarVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleSidebarVisibility.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts b/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts index 5f7a2b2a59..8d475bf2fb 100644 --- a/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleStatusbarVisibility.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleTabsVisibility.ts b/src/vs/workbench/browser/actions/toggleTabsVisibility.ts index cacf545cf7..a965e189f3 100644 --- a/src/vs/workbench/browser/actions/toggleTabsVisibility.ts +++ b/src/vs/workbench/browser/actions/toggleTabsVisibility.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/browser/actions/toggleZenMode.ts b/src/vs/workbench/browser/actions/toggleZenMode.ts index 6c3251a2ba..dd526a6665 100644 --- a/src/vs/workbench/browser/actions/toggleZenMode.ts +++ b/src/vs/workbench/browser/actions/toggleZenMode.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 3a40ac75f4..a7bf0d8804 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; diff --git a/src/vs/workbench/browser/actions/workspaceCommands.ts b/src/vs/workbench/browser/actions/workspaceCommands.ts index cf5c6bab54..5962c5e469 100644 --- a/src/vs/workbench/browser/actions/workspaceCommands.ts +++ b/src/vs/workbench/browser/actions/workspaceCommands.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index 33547e0ae4..19f677bf40 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -4,18 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions'; import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { Component } from 'vs/workbench/common/component'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IComposite } from 'vs/workbench/common/composite'; import { IEditorControl } from 'vs/platform/editor/common/editor'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import DOM = require('vs/base/browser/dom'); import { IDisposable } from 'vs/base/common/lifecycle'; +import { IFocusTracker, trackFocus, Dimension } from 'vs/base/browser/dom'; /** * Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite @@ -28,14 +27,14 @@ import { IDisposable } from 'vs/base/common/lifecycle'; * layout and focus call, but only one create and dispose call. */ export abstract class Composite extends Component implements IComposite { - private _onTitleAreaUpdate: Emitter<void>; - private _onDidFocus: Emitter<void>; + private readonly _onTitleAreaUpdate: Emitter<void>; + private readonly _onDidFocus: Emitter<void>; - private _focusTracker?: DOM.IFocusTracker; + private _focusTracker?: IFocusTracker; private _focusListenerDisposable?: IDisposable; private visible: boolean; - private parent: Builder; + private parent: HTMLElement; protected actionRunner: IActionRunner; @@ -75,7 +74,7 @@ export abstract class Composite extends Component implements IComposite { * Note that DOM-dependent calculations should be performed from the setVisible() * call. Only then the composite will be part of the DOM. */ - public create(parent: Builder): TPromise<void> { + public create(parent: HTMLElement): TPromise<void> { this.parent = parent; return TPromise.as(null); @@ -88,12 +87,12 @@ export abstract class Composite extends Component implements IComposite { /** * Returns the container this composite is being build in. */ - public getContainer(): Builder { + public getContainer(): HTMLElement { return this.parent; } public get onDidFocus(): Event<any> { - this._focusTracker = DOM.trackFocus(this.getContainer().getHTMLElement()); + this._focusTracker = trackFocus(this.getContainer()); this._focusListenerDisposable = this._focusTracker.onDidFocus(() => { this._onDidFocus.fire(); }); @@ -243,6 +242,10 @@ export abstract class CompositeDescriptor<T extends Composite> { } export abstract class CompositeRegistry<T extends Composite> { + + private readonly _onDidRegister: Emitter<CompositeDescriptor<T>> = new Emitter<CompositeDescriptor<T>>(); + readonly onDidRegister: Event<CompositeDescriptor<T>> = this._onDidRegister.event; + private composites: CompositeDescriptor<T>[]; constructor() { @@ -255,6 +258,7 @@ export abstract class CompositeRegistry<T extends Composite> { } this.composites.push(descriptor); + this._onDidRegister.fire(descriptor); } public getComposite(id: string): CompositeDescriptor<T> { diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index dbc1f799ff..56f79f2bbf 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -7,7 +7,7 @@ import { WORKSPACE_EXTENSION, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { extname, basename } from 'vs/base/common/paths'; -import { IFileService, IFileStat } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import URI from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -348,7 +348,7 @@ export class SimpleFileResourceDragAndDrop extends DefaultDragAndDrop { } } -export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | IFileStat)[], event: DragMouseEvent | DragEvent): void { +export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], event: DragMouseEvent | DragEvent): void { if (resources.length === 0) { return; } @@ -455,4 +455,4 @@ export class LocalSelectionTransfer<T> { this.proto = proto; } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index cda8a10e69..27daf18d92 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -6,7 +6,7 @@ 'use strict'; import uri from 'vs/base/common/uri'; -import resources = require('vs/base/common/resources'); +import * as resources from 'vs/base/common/resources'; import { IconLabel, IIconLabelValueOptions, IIconLabelCreationOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -25,6 +25,7 @@ import { Schemas } from 'vs/base/common/network'; import { FileKind, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { ITextModel } from 'vs/editor/common/model'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { Event, Emitter } from 'vs/base/common/event'; export interface IResourceLabel { name: string; @@ -38,11 +39,16 @@ export interface IResourceLabelOptions extends IIconLabelValueOptions { } export class ResourceLabel extends IconLabel { + private toDispose: IDisposable[]; private label: IResourceLabel; private options: IResourceLabelOptions; private computedIconClasses: string[]; private lastKnownConfiguredLangId: string; + private computedPathLabel: string; + + private _onDidRender = new Emitter<void>(); + readonly onDidRender: Event<void> = this._onDidRender.event; constructor( container: HTMLElement, @@ -121,6 +127,10 @@ export class ResourceLabel extends IconLabel { this.label = label; this.options = options; + if (hasResourceChanged) { + this.computedPathLabel = void 0; // reset path label due to resource change + } + this.render(hasResourceChanged); } @@ -151,6 +161,7 @@ export class ResourceLabel extends IconLabel { this.options = void 0; this.lastKnownConfiguredLangId = void 0; this.computedIconClasses = void 0; + this.computedPathLabel = void 0; this.setValue(); } @@ -184,7 +195,11 @@ export class ResourceLabel extends IconLabel { if (this.options && typeof this.options.title === 'string') { iconLabelOptions.title = this.options.title; } else if (resource && resource.scheme !== Schemas.data /* do not accidentally inline Data URIs */) { - iconLabelOptions.title = getPathLabel(resource, void 0, this.environmentService); + if (!this.computedPathLabel) { + this.computedPathLabel = getPathLabel(resource, void 0, this.environmentService); + } + + iconLabelOptions.title = this.computedPathLabel; } if (!this.computedIconClasses) { @@ -197,7 +212,7 @@ export class ResourceLabel extends IconLabel { } if (this.options && this.options.fileDecorations && resource) { - let deco = this.decorationsService.getDecoration( + const deco = this.decorationsService.getDecoration( resource, this.options.fileKind !== FileKind.FILE, this.options.fileDecorations.data @@ -207,9 +222,11 @@ export class ResourceLabel extends IconLabel { if (deco.tooltip) { iconLabelOptions.title = `${iconLabelOptions.title} • ${deco.tooltip}`; } + if (this.options.fileDecorations.colors) { iconLabelOptions.extraClasses.push(deco.labelClassName); } + if (this.options.fileDecorations.badges) { iconLabelOptions.extraClasses.push(deco.badgeClassName); } @@ -217,6 +234,8 @@ export class ResourceLabel extends IconLabel { } this.setValue(label, this.label.description, iconLabelOptions); + + this._onDidRender.fire(); } public dispose(): void { @@ -227,6 +246,7 @@ export class ResourceLabel extends IconLabel { this.options = void 0; this.lastKnownConfiguredLangId = void 0; this.computedIconClasses = void 0; + this.computedPathLabel = void 0; } } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index c939dee556..d49f5368a9 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { TPromise } from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import { Part } from 'vs/workbench/browser/part'; import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; +import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput'; import { Sash, ISashEvent, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation } from 'vs/base/browser/ui/sash/sash'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService, Position, ILayoutOptions, Parts } from 'vs/workbench/services/part/common/partService'; @@ -22,11 +22,14 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { memoize } from 'vs/base/common/decorators'; import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter'; import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts'; +import { Dimension, getClientArea, size, position, hide, show } from 'vs/base/browser/dom'; const MIN_SIDEBAR_PART_WIDTH = 170; +const DEFAULT_SIDEBAR_PART_WIDTH = 300; const MIN_EDITOR_PART_HEIGHT = 70; const MIN_EDITOR_PART_WIDTH = 220; const MIN_PANEL_PART_HEIGHT = 77; +const DEFAULT_PANEL_PART_SIZE = 350; const MIN_PANEL_PART_WIDTH = 300; const DEFAULT_PANEL_SIZE_COEFFICIENT = 0.4; const PANEL_SIZE_BEFORE_MAXIMIZED_BOUNDARY = 0.7; @@ -56,8 +59,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal private static readonly sashYHeightSettingsKey = 'workbench.panel.height'; private static readonly panelSizeBeforeMaximizedKey = 'workbench.panel.sizeBeforeMaximized'; - private parent: Builder; - private workbenchContainer: Builder; + private parent: HTMLElement; + private workbenchContainer: HTMLElement; private titlebar: Part; private activitybar: Part; private editor: Part; @@ -65,6 +68,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal private panel: Part; private statusbar: Part; private quickopen: QuickOpenController; + private quickInput: QuickInputService; private notificationsCenter: NotificationsCenter; private notificationsToasts: NotificationsToasts; private toUnbind: IDisposable[]; @@ -84,8 +88,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal // Take parts as an object bag since instatation service does not have typings for constructors with 9+ arguments constructor( - parent: Builder, - workbenchContainer: Builder, + parent: HTMLElement, + workbenchContainer: HTMLElement, parts: { titlebar: Part, activitybar: Part, @@ -95,6 +99,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal statusbar: Part }, quickopen: QuickOpenController, + quickInput: QuickInputService, notificationsCenter: NotificationsCenter, notificationsToasts: NotificationsToasts, @IStorageService private storageService: IStorageService, @@ -114,28 +119,29 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.panel = parts.panel; this.statusbar = parts.statusbar; this.quickopen = quickopen; + this.quickInput = quickInput; this.notificationsCenter = notificationsCenter; this.notificationsToasts = notificationsToasts; this.toUnbind = []; this.panelSizeBeforeMaximized = this.storageService.getInteger(WorkbenchLayout.panelSizeBeforeMaximizedKey, StorageScope.GLOBAL, 0); this.panelMaximized = false; - this.sashXOne = new Sash(this.workbenchContainer.getHTMLElement(), this, { + this.sashXOne = new Sash(this.workbenchContainer, this, { baseSize: 5 }); - this.sashXTwo = new Sash(this.workbenchContainer.getHTMLElement(), this, { + this.sashXTwo = new Sash(this.workbenchContainer, this, { baseSize: 5 }); - this.sashY = new Sash(this.workbenchContainer.getHTMLElement(), this, { + this.sashY = new Sash(this.workbenchContainer, this, { baseSize: 4, orientation: Orientation.HORIZONTAL }); - this._sidebarWidth = this.storageService.getInteger(WorkbenchLayout.sashXOneWidthSettingsKey, StorageScope.GLOBAL, -1); - this._panelHeight = this.storageService.getInteger(WorkbenchLayout.sashYHeightSettingsKey, StorageScope.GLOBAL, 0); - this._panelWidth = this.storageService.getInteger(WorkbenchLayout.sashXTwoWidthSettingsKey, StorageScope.GLOBAL, 0); + this._sidebarWidth = Math.max(this.partLayoutInfo.sidebar.minWidth, this.storageService.getInteger(WorkbenchLayout.sashXOneWidthSettingsKey, StorageScope.GLOBAL, DEFAULT_SIDEBAR_PART_WIDTH)); + this._panelHeight = Math.max(this.partLayoutInfo.panel.minHeight, this.storageService.getInteger(WorkbenchLayout.sashYHeightSettingsKey, StorageScope.GLOBAL, DEFAULT_PANEL_PART_SIZE)); + this._panelWidth = Math.max(this.partLayoutInfo.panel.minWidth, this.storageService.getInteger(WorkbenchLayout.sashXTwoWidthSettingsKey, StorageScope.GLOBAL, DEFAULT_PANEL_PART_SIZE)); this.layoutEditorGroupsVertically = (this.editorGroupService.getGroupOrientation() !== 'horizontal'); @@ -397,7 +403,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.toUnbind.push(this.sashXOne.onDidReset(() => { let activeViewlet = this.viewletService.getActiveViewlet(); let optimalWidth = activeViewlet && activeViewlet.getOptimalWidth(); - this.sidebarWidth = optimalWidth || 0; + this.sidebarWidth = Math.max(optimalWidth, DEFAULT_SIDEBAR_PART_WIDTH); this.storageService.store(WorkbenchLayout.sashXOneWidthSettingsKey, this.sidebarWidth, StorageScope.GLOBAL); this.partService.setSideBarHidden(false).done(() => this.layout(), errors.onUnexpectedError); })); @@ -441,7 +447,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal } public layout(options?: ILayoutOptions): void { - this.workbenchSize = this.parent.getClientArea(); + this.workbenchSize = getClientArea(this.parent); const isActivityBarHidden = !this.partService.isVisible(Parts.ACTIVITYBAR_PART); const isTitlebarHidden = !this.partService.isVisible(Parts.TITLEBAR_PART); @@ -572,12 +578,11 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal } // Workbench - this.workbenchContainer - .position(0, 0, 0, 0, 'relative') - .size(this.workbenchSize.width, this.workbenchSize.height); + position(this.workbenchContainer, 0, 0, 0, 0, 'relative'); + size(this.workbenchContainer, this.workbenchSize.width, this.workbenchSize.height); // Bug on Chrome: Sometimes Chrome wants to scroll the workbench container on layout changes. The fix is to reset scrolling in this case. - const workbenchContainer = this.workbenchContainer.getHTMLElement(); + const workbenchContainer = this.workbenchContainer; if (workbenchContainer.scrollTop > 0) { workbenchContainer.scrollTop = 0; } @@ -586,69 +591,78 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal } // Title Part + const titleContainer = this.titlebar.getContainer(); if (isTitlebarHidden) { - this.titlebar.getContainer().hide(); + hide(titleContainer); } else { - this.titlebar.getContainer().show(); + show(titleContainer); } // Editor Part and Panel part - this.editor.getContainer().size(editorSize.width, editorSize.height); - this.panel.getContainer().size(panelDimension.width, panelDimension.height); + const editorContainer = this.editor.getContainer(); + const panelContainer = this.panel.getContainer(); + size(editorContainer, editorSize.width, editorSize.height); + size(panelContainer, panelDimension.width, panelDimension.height); if (panelPosition === Position.BOTTOM) { if (sidebarPosition === Position.LEFT) { - this.editor.getContainer().position(this.titlebarHeight, 0, this.statusbarHeight + panelDimension.height, sidebarSize.width + activityBarSize.width); - this.panel.getContainer().position(editorSize.height + this.titlebarHeight, 0, this.statusbarHeight, sidebarSize.width + activityBarSize.width); + position(editorContainer, this.titlebarHeight, 0, this.statusbarHeight + panelDimension.height, sidebarSize.width + activityBarSize.width); + position(panelContainer, editorSize.height + this.titlebarHeight, 0, this.statusbarHeight, sidebarSize.width + activityBarSize.width); } else { - this.editor.getContainer().position(this.titlebarHeight, sidebarSize.width, this.statusbarHeight + panelDimension.height, 0); - this.panel.getContainer().position(editorSize.height + this.titlebarHeight, sidebarSize.width, this.statusbarHeight, 0); + position(editorContainer, this.titlebarHeight, sidebarSize.width, this.statusbarHeight + panelDimension.height, 0); + position(panelContainer, editorSize.height + this.titlebarHeight, sidebarSize.width, this.statusbarHeight, 0); } } else { if (sidebarPosition === Position.LEFT) { - this.editor.getContainer().position(this.titlebarHeight, panelDimension.width, this.statusbarHeight, sidebarSize.width + activityBarSize.width); - this.panel.getContainer().position(this.titlebarHeight, 0, this.statusbarHeight, sidebarSize.width + activityBarSize.width + editorSize.width); + position(editorContainer, this.titlebarHeight, panelDimension.width, this.statusbarHeight, sidebarSize.width + activityBarSize.width); + position(panelContainer, this.titlebarHeight, 0, this.statusbarHeight, sidebarSize.width + activityBarSize.width + editorSize.width); } else { - this.editor.getContainer().position(this.titlebarHeight, sidebarSize.width + activityBarSize.width + panelWidth, this.statusbarHeight, 0); - this.panel.getContainer().position(this.titlebarHeight, sidebarSize.width + activityBarSize.width, this.statusbarHeight, editorSize.width); + position(editorContainer, this.titlebarHeight, sidebarSize.width + activityBarSize.width + panelWidth, this.statusbarHeight, 0); + position(panelContainer, this.titlebarHeight, sidebarSize.width + activityBarSize.width, this.statusbarHeight, editorSize.width); } } // Activity Bar Part - this.activitybar.getContainer().size(null, activityBarSize.height); + const activitybarContainer = this.activitybar.getContainer(); + size(activitybarContainer, null, activityBarSize.height); if (sidebarPosition === Position.LEFT) { - this.activitybar.getContainer().getHTMLElement().style.right = ''; - this.activitybar.getContainer().position(this.titlebarHeight, null, 0, 0); + this.activitybar.getContainer().style.right = ''; + position(activitybarContainer, this.titlebarHeight, null, 0, 0); } else { - this.activitybar.getContainer().getHTMLElement().style.left = ''; - this.activitybar.getContainer().position(this.titlebarHeight, 0, 0, null); + this.activitybar.getContainer().style.left = ''; + position(activitybarContainer, this.titlebarHeight, 0, 0, null); } if (isActivityBarHidden) { - this.activitybar.getContainer().hide(); + hide(activitybarContainer); } else { - this.activitybar.getContainer().show(); + show(activitybarContainer); } // Sidebar Part - this.sidebar.getContainer().size(sidebarSize.width, sidebarSize.height); + const sidebarContainer = this.sidebar.getContainer(); + size(sidebarContainer, sidebarSize.width, sidebarSize.height); const editorAndPanelWidth = editorSize.width + (panelPosition === Position.RIGHT ? panelWidth : 0); if (sidebarPosition === Position.LEFT) { - this.sidebar.getContainer().position(this.titlebarHeight, editorAndPanelWidth, this.statusbarHeight, activityBarSize.width); + position(sidebarContainer, this.titlebarHeight, editorAndPanelWidth, this.statusbarHeight, activityBarSize.width); } else { - this.sidebar.getContainer().position(this.titlebarHeight, activityBarSize.width, this.statusbarHeight, editorAndPanelWidth); + position(sidebarContainer, this.titlebarHeight, activityBarSize.width, this.statusbarHeight, editorAndPanelWidth); } // Statusbar Part - this.statusbar.getContainer().position(this.workbenchSize.height - this.statusbarHeight); + const statusbarContainer = this.statusbar.getContainer(); + position(statusbarContainer, this.workbenchSize.height - this.statusbarHeight); if (isStatusbarHidden) { - this.statusbar.getContainer().hide(); + hide(statusbarContainer); } else { - this.statusbar.getContainer().show(); + show(statusbarContainer); } // Quick open this.quickopen.layout(this.workbenchSize); + // Quick input + this.quickInput.layout(this.workbenchSize); + // Notifications this.notificationsCenter.layout(this.workbenchSize); this.notificationsToasts.layout(this.workbenchSize); @@ -786,4 +800,4 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.toUnbind = null; } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/media/part.css b/src/vs/workbench/browser/media/part.css index 2160bdf44c..f432e49191 100644 --- a/src/vs/workbench/browser/media/part.css +++ b/src/vs/workbench/browser/media/part.css @@ -68,7 +68,7 @@ font-size: 13px; } -.monaco-workbench > .part > .content .progress-container { +.monaco-workbench > .part > .content .monaco-progress-container { position: absolute; left: 0; top: 33px; /* at the bottom of the 35px height title container */ @@ -76,6 +76,6 @@ height: 2px; } -.monaco-workbench > .part > .content .progress-container .progress-bit { +.monaco-workbench > .part > .content .monaco-progress-container .progress-bit { height: 2px; } \ No newline at end of file diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index ab83bd0299..060afa2050 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -95,7 +95,7 @@ export abstract class TogglePanelAction extends Action { const activePanel = this.panelService.getActivePanel(); const activeElement = document.activeElement; - return activePanel && activeElement && DOM.isAncestor(activeElement, (<Panel>activePanel).getContainer().getHTMLElement()); + return activePanel && activeElement && DOM.isAncestor(activeElement, (<Panel>activePanel).getContainer()); } } diff --git a/src/vs/workbench/browser/part.ts b/src/vs/workbench/browser/part.ts index 0894cca25a..94b8784d5b 100644 --- a/src/vs/workbench/browser/part.ts +++ b/src/vs/workbench/browser/part.ts @@ -6,9 +6,9 @@ 'use strict'; import 'vs/css!./media/part'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { Component } from 'vs/workbench/common/component'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; +import { Dimension, size } from 'vs/base/browser/dom'; export interface IPartOptions { hasTitle?: boolean; @@ -20,9 +20,9 @@ export interface IPartOptions { * and mandatory content area to show content. */ export abstract class Part extends Component { - private parent: Builder; - private titleArea: Builder; - private contentArea: Builder; + private parent: HTMLElement; + private titleArea: HTMLElement; + private contentArea: HTMLElement; private partLayout: PartLayout; constructor( @@ -47,7 +47,7 @@ export abstract class Part extends Component { * * Called to create title and content area of the part. */ - public create(parent: Builder): void { + public create(parent: HTMLElement): void { this.parent = parent; this.titleArea = this.createTitleArea(parent); this.contentArea = this.createContentArea(parent); @@ -60,35 +60,35 @@ export abstract class Part extends Component { /** * Returns the overall part container. */ - public getContainer(): Builder { + public getContainer(): HTMLElement { return this.parent; } /** * Subclasses override to provide a title area implementation. */ - protected createTitleArea(parent: Builder): Builder { + protected createTitleArea(parent: HTMLElement): HTMLElement { return null; } /** * Returns the title area container. */ - protected getTitleArea(): Builder { + protected getTitleArea(): HTMLElement { return this.titleArea; } /** * Subclasses override to provide a content area implementation. */ - protected createContentArea(parent: Builder): Builder { + protected createContentArea(parent: HTMLElement): HTMLElement { return null; } /** * Returns the content area container. */ - protected getContentArea(): Builder { + protected getContentArea(): HTMLElement { return this.contentArea; } @@ -104,8 +104,7 @@ const TITLE_HEIGHT = 35; export class PartLayout { - constructor(container: Builder, private options: IPartOptions, titleArea: Builder, private contentArea: Builder) { - } + constructor(container: HTMLElement, private options: IPartOptions, titleArea: HTMLElement, private contentArea: HTMLElement) { } public layout(dimension: Dimension): Dimension[] { const { width, height } = dimension; @@ -133,7 +132,7 @@ export class PartLayout { // Content if (this.contentArea) { - this.contentArea.size(contentSize.width, contentSize.height); + size(this.contentArea, contentSize.width, contentSize.height); } return sizes; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 836748d31b..3d7d933899 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -6,7 +6,7 @@ 'use strict'; import 'vs/css!./media/activityaction'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; @@ -22,6 +22,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ActivityAction, ActivityActionItem, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; export class ViewletActivityAction extends ActivityAction { @@ -32,7 +33,8 @@ export class ViewletActivityAction extends ActivityAction { constructor( activity: IActivity, @IViewletService private viewletService: IViewletService, - @IPartService private partService: IPartService + @IPartService private partService: IPartService, + @ITelemetryService private telemetryService: ITelemetryService ) { super(activity); } @@ -54,11 +56,23 @@ export class ViewletActivityAction extends ActivityAction { // Hide sidebar if selected viewlet already visible if (sideBarVisible && activeViewlet && activeViewlet.getId() === this.activity.id) { + this.logAction('hide'); return this.partService.setSideBarHidden(true); } + this.logAction('show'); return this.viewletService.openViewlet(this.activity.id, true).then(() => this.activate()); } + + private logAction(action: string) { + /* __GDPR__ + "activityBarAction" : { + "viewletId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "action": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('activityBarAction', { viewletId: this.activity.id, action }); + } } export class ToggleViewletAction extends Action { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 565ca0627a..bea73c3c18 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -6,10 +6,10 @@ 'use strict'; import 'vs/css!./media/activitybarpart'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { illegalArgument } from 'vs/base/common/errors'; -import { Builder, $, Dimension } from 'vs/base/browser/builder'; +import { $ } from 'vs/base/browser/builder'; import { Action } from 'vs/base/common/actions'; import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity'; @@ -30,8 +30,10 @@ import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; // {{SQL CARBON EDIT}} -import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { ViewLocation, ViewsRegistry } from 'vs/workbench/common/views'; +import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; +import { Dimension } from 'vs/base/browser/dom'; export class ActivitybarPart extends Part { @@ -66,6 +68,7 @@ export class ActivitybarPart extends Part { super(id, { hasTitle: false }, themeService); this.globalActivityIdToActions = Object.create(null); + this.compositeBar = this.instantiationService.createInstance(CompositeBar, { icon: true, storageId: ActivitybarPart.PINNED_VIEWLETS, @@ -80,7 +83,9 @@ export class ActivitybarPart extends Part { colors: ActivitybarPart.COLORS, overflowActionSize: ActivitybarPart.ACTION_HEIGHT }); + this.registerListeners(); + this.updateCompositebar(); } // {{SQL CARBON EDIT}} @@ -97,6 +102,10 @@ export class ActivitybarPart extends Part { private registerListeners(): void { + this.toUnbind.push(this.viewletService.onDidViewletRegister(() => this.updateCompositebar())); + this.toUnbind.push(ViewsRegistry.onViewsRegistered(() => this.updateCompositebar())); + this.toUnbind.push(ViewsRegistry.onViewsDeregistered(() => this.updateCompositebar())); + // Activate viewlet action on opening of a viewlet this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.compositeBar.activateComposite(viewlet.getId()))); @@ -105,7 +114,7 @@ export class ActivitybarPart extends Part { this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); this.toUnbind.push(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => { if (enabled) { - this.compositeBar.addComposite(this.viewletService.getViewlet(id)); + this.compositeBar.addComposite(this.viewletService.getViewlet(id), true); } else { this.compositeBar.removeComposite(id); } @@ -135,7 +144,7 @@ export class ActivitybarPart extends Part { return toDisposable(() => action.setBadge(undefined)); } - public createContentArea(parent: Builder): Builder { + public createContentArea(parent: HTMLElement): HTMLElement { const $el = $(parent); const $result = $('.content').appendTo($el); @@ -145,14 +154,14 @@ export class ActivitybarPart extends Part { // Top Actionbar with action items for each viewlet action this.createGlobalActivityActionBar($('.global-activity').appendTo($result).getHTMLElement()); - return $result; + return $result.getHTMLElement(); } public updateStyles(): void { super.updateStyles(); // Part container - const container = this.getContainer(); + const container = $(this.getContainer()); const background = this.getColor(ACTIVITY_BAR_BACKGROUND); container.style('background-color', background); @@ -170,7 +179,9 @@ export class ActivitybarPart extends Part { private showContextMenu(e: MouseEvent): void { const event = new StandardMouseEvent(e); - const actions: Action[] = this.viewletService.getViewlets().map(viewlet => this.instantiationService.createInstance(ToggleCompositePinnedAction, viewlet, this.compositeBar)); + const actions: Action[] = this.viewletService.getViewlets() + .filter(viewlet => this.canShow(viewlet)) + .map(viewlet => this.instantiationService.createInstance(ToggleCompositePinnedAction, viewlet, this.compositeBar)); actions.push(new Separator()); actions.push(this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))); @@ -202,6 +213,26 @@ export class ActivitybarPart extends Part { }); } + private updateCompositebar(): void { + const viewlets = this.viewletService.getViewlets(); + for (const viewlet of viewlets) { + const canShow = this.canShow(viewlet); + if (canShow) { + this.compositeBar.addComposite(viewlet, false); + } else { + this.compositeBar.removeComposite(viewlet.id); + } + } + } + + private canShow(viewlet: ViewletDescriptor): boolean { + const viewLocation = ViewLocation.get(viewlet.id); + if (viewLocation) { + return ViewsRegistry.getViews(viewLocation).length > 0; + } + return true; + } + public getPinned(): string[] { return this.viewletService.getViewlets().map(v => v.id).filter(id => this.compositeBar.isPinned(id)); } @@ -229,6 +260,11 @@ export class ActivitybarPart extends Part { return sizes; } + public shutdown(): void { + this.compositeBar.shutdown(); + super.shutdown(); + } + public dispose(): void { if (this.compositeBar) { this.compositeBar.dispose(); @@ -242,4 +278,4 @@ export class ActivitybarPart extends Part { super.dispose(); } -} +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index c2dce7efae..1a6c6128f9 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -19,7 +19,7 @@ background-color: inherit; } -.monaco-workbench > .activitybar [tabindex="0"]:focus { +.monaco-workbench > .activitybar .action-item:focus { outline: 0 !important; /* activity bar indicates focus custom */ } diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 72356f0f7d..0d42d449f9 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -6,22 +6,20 @@ 'use strict'; import 'vs/css!./media/compositepart'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import strings = require('vs/base/common/strings'); +import { Builder, $ } from 'vs/base/browser/builder'; +import * as strings from 'vs/base/common/strings'; import { Emitter } from 'vs/base/common/event'; -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); -import * as DOM from 'vs/base/browser/dom'; -import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { prepareActions } from 'vs/workbench/browser/actions'; -import { Action, IAction, IRunEvent } from 'vs/base/common/actions'; +import { Action, IAction } from 'vs/base/common/actions'; import { Part, IPartOptions } from 'vs/workbench/browser/part'; import { Composite, CompositeRegistry } from 'vs/workbench/browser/composite'; import { IComposite } from 'vs/workbench/common/composite'; @@ -37,6 +35,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension } from 'vs/base/browser/dom'; export interface ICompositeTitleLabel { @@ -74,10 +73,10 @@ export abstract class CompositePart<T extends Composite> extends Part { private telemetryService: ITelemetryService, protected contextMenuService: IContextMenuService, protected partService: IPartService, - private keybindingService: IKeybindingService, + protected keybindingService: IKeybindingService, protected instantiationService: IInstantiationService, themeService: IThemeService, - private registry: CompositeRegistry<T>, + protected readonly registry: CompositeRegistry<T>, private activeCompositeSettingsKey: string, private defaultCompositeId: string, private nameForTelemetry: string, @@ -223,8 +222,8 @@ export abstract class CompositePart<T extends Composite> extends Part { compositeContainer = $().div({ 'class': ['composite', this.compositeCSSClass], id: composite.getId() - }, (div: Builder) => { - createCompositePromise = composite.create(div).then(() => { + }, div => { + createCompositePromise = composite.create(div.getHTMLElement()).then(() => { composite.updateStyles(); }); }); @@ -279,7 +278,7 @@ export abstract class CompositePart<T extends Composite> extends Part { } // Action Run Handling - this.telemetryActionsListener = this.toolBar.actionRunner.onDidRun((e: IRunEvent) => { + this.telemetryActionsListener = this.toolBar.actionRunner.onDidRun(e => { // Check for Error if (e.error && !errors.isPromiseCanceledError(e.error)) { @@ -311,7 +310,7 @@ export abstract class CompositePart<T extends Composite> extends Part { composite.layout(this.contentAreaSize); } }); - }, (error: any) => this.onError(error)); + }, error => this.onError(error)); } protected onTitleAreaUpdate(compositeId: string): void { @@ -391,7 +390,7 @@ export abstract class CompositePart<T extends Composite> extends Part { compositeContainer.hide(); // Clear any running Progress - this.progressBar.stop().getContainer().hide(); + this.progressBar.stop().hide(); // Empty Actions this.toolBar.setActions([])(); @@ -401,39 +400,37 @@ export abstract class CompositePart<T extends Composite> extends Part { }); } - public createTitleArea(parent: Builder): Builder { + public createTitleArea(parent: HTMLElement): HTMLElement { // Title Area Container const titleArea = $(parent).div({ 'class': ['composite', 'title'] }); - $(titleArea).on(DOM.EventType.CONTEXT_MENU, (e: MouseEvent) => this.onTitleAreaContextMenu(new StandardMouseEvent(e))); - // Left Title Label - this.titleLabel = this.createTitleLabel(titleArea); + this.titleLabel = this.createTitleLabel(titleArea.getHTMLElement()); // Right Actions Container $(titleArea).div({ 'class': 'title-actions' - }, (div) => { + }, div => { // Toolbar this.toolBar = new ToolBar(div.getHTMLElement(), this.contextMenuService, { - actionItemProvider: (action: Action) => this.actionItemProvider(action), + actionItemProvider: action => this.actionItemProvider(action as Action), orientation: ActionsOrientation.HORIZONTAL, - getKeyBinding: (action) => this.keybindingService.lookupKeybinding(action.id) + getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id) }); }); - return titleArea; + return titleArea.getHTMLElement(); } - protected createTitleLabel(parent: Builder): ICompositeTitleLabel { + protected createTitleLabel(parent: HTMLElement): ICompositeTitleLabel { let titleLabel: Builder; $(parent).div({ 'class': 'title-label' - }, (div) => { + }, div => { titleLabel = div.span(); }); @@ -456,27 +453,8 @@ export abstract class CompositePart<T extends Composite> extends Part { this.titleLabel.updateStyles(); } - private onTitleAreaContextMenu(event: StandardMouseEvent): void { - if (this.activeComposite) { - const contextMenuActions = this.getTitleAreaContextMenuActions(); - if (contextMenuActions.length) { - const anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; - this.contextMenuService.showContextMenu({ - getAnchor: () => anchor, - getActions: () => TPromise.as(contextMenuActions), - getActionItem: (action: Action) => this.actionItemProvider(action), - actionRunner: this.activeComposite.getActionRunner(), - getKeyBinding: (action) => this.keybindingService.lookupKeybinding(action.id) - }); - } - } - } + protected actionItemProvider(action: Action): IActionItem { - protected getTitleAreaContextMenuActions(): IAction[] { - return this.activeComposite ? this.activeComposite.getContextMenuActions() : []; - } - - private actionItemProvider(action: Action): IActionItem { // Check Active Composite if (this.activeComposite) { return this.activeComposite.getActionItem(action); @@ -485,14 +463,14 @@ export abstract class CompositePart<T extends Composite> extends Part { return undefined; } - public createContentArea(parent: Builder): Builder { + public createContentArea(parent: HTMLElement): HTMLElement { return $(parent).div({ 'class': 'content' - }, (div: Builder) => { - this.progressBar = new ProgressBar(div); + }, div => { + this.progressBar = new ProgressBar(div.getHTMLElement()); this.toUnbind.push(attachProgressBarStyler(this.progressBar, this.themeService)); - this.progressBar.getContainer().hide(); - }); + this.progressBar.hide(); + }).getHTMLElement(); } private onError(error: any): void { diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index a444d7ee21..13a27c3c3f 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -5,26 +5,25 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; -import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; -import { Dimension } from 'vs/base/browser/builder'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { TPromise } from 'vs/base/common/winjs.base'; +import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom'; export interface ICompositeBarOptions { icon: boolean; storageId: string; orientation: ActionsOrientation; - composites: { id: string, name: string }[]; + composites: { id: string, name: string, order: number }[]; colors: ICompositeBarColors; overflowActionSize: number; getActivityAction: (compositeId: string) => ActivityAction; @@ -35,9 +34,14 @@ export interface ICompositeBarOptions { hidePart: () => TPromise<any>; } +interface CompositeState { + id: string; + pinned: boolean; +} + export class CompositeBar implements ICompositeBar { - private _onDidContextMenu: Emitter<MouseEvent>; + private readonly _onDidContextMenu: Emitter<MouseEvent>; private dimension: Dimension; private toDispose: IDisposable[]; @@ -51,6 +55,7 @@ export class CompositeBar implements ICompositeBar { private compositeIdToActivityStack: { [compositeId: string]: ICompositeActivity[]; }; private compositeSizeInBar: Map<string, number>; + private initialCompositesStates: CompositeState[]; private pinnedComposites: string[]; private activeCompositeId: string; private activeUnpinnedCompositeId: string; @@ -67,27 +72,36 @@ export class CompositeBar implements ICompositeBar { this.compositeSizeInBar = new Map<string, number>(); this._onDidContextMenu = new Emitter<MouseEvent>(); - - const pinnedComposites = JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, null)) as string[]; - if (pinnedComposites) { - const compositeIds = this.options.composites.map(c => c.id); - this.pinnedComposites = pinnedComposites.filter(pcid => compositeIds.indexOf(pcid) >= 0); - } else { - this.pinnedComposites = this.options.composites.map(c => c.id); - } + this.initialCompositesStates = this.loadCompositesStates(); + this.pinnedComposites = this.initialCompositesStates + .filter(c => c.pinned) + .map(c => c.id) + .filter(id => this.options.composites.some(c => c.id === id)); } public get onDidContextMenu(): Event<MouseEvent> { return this._onDidContextMenu.event; } - public addComposite(compositeData: { id: string; name: string }): void { + public addComposite(compositeData: { id: string; name: string, order: number }, activate: boolean): void { if (this.options.composites.filter(c => c.id === compositeData.id).length) { return; } - this.options.composites.push(compositeData); - this.pin(compositeData.id); + + const compositeState = this.initialCompositesStates.filter(c => c.id === compositeData.id)[0]; + if (!compositeState /* new composites are pinned by default */ || compositeState.pinned) { + let index; + if (compositeState) { + index = this.initialCompositesStates.indexOf(compositeState); + } else { + index = 0; + while (index < this.options.composites.length && this.options.composites[index].order < compositeData.order) { + index++; + } + } + this.pin(compositeData.id, true, index, activate); + } } public removeComposite(id: string): void { @@ -97,6 +111,9 @@ export class CompositeBar implements ICompositeBar { this.options.composites = this.options.composites.filter(c => c.id !== id); this.unpin(id); + this.pullComposite(id); + // Only at the end deactivate composite so the unpin and pull properly finish + this.deactivateComposite(id); } public activateComposite(id: string): void { @@ -119,6 +136,13 @@ export class CompositeBar implements ICompositeBar { if (this.compositeIdToActions[id]) { this.compositeIdToActions[id].deactivate(); } + if (this.activeCompositeId === id) { + this.activeCompositeId = undefined; + } + if (this.activeUnpinnedCompositeId === id) { + this.updateCompositeSwitcher(); + this.activeUnpinnedCompositeId = undefined; + } } public showActivity(compositeId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable { @@ -191,7 +215,7 @@ export class CompositeBar implements ICompositeBar { } public create(parent: HTMLElement): HTMLElement { - const actionBarDiv = parent.appendChild(dom.$('.composite-bar')); + const actionBarDiv = parent.appendChild($('.composite-bar')); this.compositeSwitcherBar = new ActionBar(actionBarDiv, { actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], orientation: this.options.orientation, @@ -201,16 +225,16 @@ export class CompositeBar implements ICompositeBar { this.toDispose.push(this.compositeSwitcherBar); // Contextmenu for composites - this.toDispose.push(dom.addDisposableListener(parent, dom.EventType.CONTEXT_MENU, (e: MouseEvent) => { - dom.EventHelper.stop(e, true); + this.toDispose.push(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => { + EventHelper.stop(e, true); this._onDidContextMenu.fire(e); })); // Allow to drop at the end to move composites to the end - this.toDispose.push(dom.addDisposableListener(parent, dom.EventType.DROP, (e: DragEvent) => { + this.toDispose.push(addDisposableListener(parent, EventType.DROP, (e: DragEvent) => { const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); if (draggedCompositeId) { - dom.EventHelper.stop(e, true); + EventHelper.stop(e, true); CompositeActionItem.clearDraggedComposite(); const targetId = this.pinnedComposites[this.pinnedComposites.length - 1]; @@ -424,20 +448,21 @@ export class CompositeBar implements ICompositeBar { }); // Persist - this.savePinnedComposites(); + this.saveCompositesStates(); } public isPinned(compositeId: string): boolean { return this.pinnedComposites.indexOf(compositeId) >= 0; } - public pin(compositeId: string, update = true): void { + public pin(compositeId: string, update = true, index = this.pinnedComposites.length, activate: boolean = true): void { if (this.isPinned(compositeId)) { return; } - this.options.openComposite(compositeId).then(() => { - this.pinnedComposites.push(compositeId); + const activatePromise = activate ? this.options.openComposite(compositeId) : TPromise.as(null); + activatePromise.then(() => { + this.pinnedComposites.splice(index, 0, compositeId); this.pinnedComposites = arrays.distinct(this.pinnedComposites); if (update) { @@ -445,7 +470,7 @@ export class CompositeBar implements ICompositeBar { } // Persist - this.savePinnedComposites(); + this.saveCompositesStates(); }); } @@ -477,7 +502,7 @@ export class CompositeBar implements ICompositeBar { }, 0); // Persist - this.savePinnedComposites(); + this.saveCompositesStates(); } public layout(dimension: Dimension): void { @@ -501,8 +526,33 @@ export class CompositeBar implements ICompositeBar { this.updateCompositeSwitcher(); } - private savePinnedComposites(): void { - this.storageService.store(this.options.storageId, JSON.stringify(this.pinnedComposites), StorageScope.GLOBAL); + private loadCompositesStates(): CompositeState[] { + const storedStates = <Array<string | CompositeState>>JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, '[]')); + const isOldData = storedStates && storedStates.length && typeof storedStates[0] === 'string'; + const compositeStates = <CompositeState[]>storedStates.map(c => + typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true } : c); + + if (!isOldData) { /* Add new composites only if it is new data */ + const newComposites = this.options.composites.filter(c => compositeStates.every(s => s.id !== c.id)); + newComposites.sort((c1, c2) => c1.order < c2.order ? -1 : 1); + newComposites.forEach(c => compositeStates.push({ id: c.id, pinned: true /* new composites are pinned by default */ })); + } + + return compositeStates; + } + + private saveCompositesStates(): void { + const toSave = this.pinnedComposites.map(id => (<CompositeState>{ id, pinned: true })); + for (const composite of this.options.composites) { + if (this.pinnedComposites.indexOf(composite.id) === -1) { // Unpinned composites + toSave.push({ id: composite.id, pinned: false }); + } + } + this.storageService.store(this.options.storageId, JSON.stringify(toSave), StorageScope.GLOBAL); + } + + public shutdown(): void { + this.saveCompositesStates(); } public dispose(): void { diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 30f914e0cd..6bb35038d7 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -5,7 +5,7 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { TPromise } from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; @@ -21,7 +21,7 @@ import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; export interface ICompositeActivity { badge: IBadge; @@ -193,7 +193,7 @@ export class ActivityActionItem extends BaseActionItem { this.$label.text(this.getAction().label); } - this.$badge = this.builder.clone().div({ 'class': 'badge' }, (badge: Builder) => { + this.$badge = this.builder.clone().div({ 'class': 'badge' }, badge => { this.$badgeContent = badge.div({ 'class': 'badge-content' }); }); @@ -207,6 +207,10 @@ export class ActivityActionItem extends BaseActionItem { } protected updateBadge(badge: IBadge, clazz?: string): void { + if (!this.$badge || !this.$badgeContent) { + return; + } + this.badgeDisposable.dispose(); this.badgeDisposable = empty; diff --git a/src/vs/workbench/browser/parts/editor/baseEditor.ts b/src/vs/workbench/browser/parts/editor/baseEditor.ts index 03335f7d93..3c068125e3 100644 --- a/src/vs/workbench/browser/parts/editor/baseEditor.ts +++ b/src/vs/workbench/browser/parts/editor/baseEditor.ts @@ -5,7 +5,6 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder } from 'vs/base/browser/builder'; import { Panel } from 'vs/workbench/browser/panel'; import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { IEditor, Position } from 'vs/platform/editor/common/editor'; @@ -64,9 +63,9 @@ export abstract class BaseEditor extends Panel implements IEditor { this._options = null; } - public create(parent: Builder): void; // create is sync for editors - public create(parent: Builder): TPromise<void>; - public create(parent: Builder): TPromise<void> { + public create(parent: HTMLElement): void; // create is sync for editors + public create(parent: HTMLElement): TPromise<void>; + public create(parent: HTMLElement): TPromise<void> { const res = super.create(parent); // Create Editor @@ -76,9 +75,16 @@ export abstract class BaseEditor extends Panel implements IEditor { } /** - * Called to create the editor in the parent builder. + * Called to create the editor in the parent HTMLElement. */ - protected abstract createEditor(parent: Builder): void; + protected abstract createEditor(parent: HTMLElement): void; + + /** + * Subclasses can set this to false if it does not make sense to center editor input. + */ + public supportsCenteredLayout(): boolean { + return true; + } /** * Overload this function to allow for passing in a position argument. @@ -119,4 +125,4 @@ export abstract class BaseEditor extends Panel implements IEditor { // Super Dispose super.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts index 1c589c067f..ad78d4aba0 100644 --- a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts @@ -5,7 +5,7 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { BINARY_DIFF_EDITOR_ID } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index e61f64bf3f..9ddbe9d706 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -5,41 +5,51 @@ 'use strict'; -import nls = require('vs/nls'); -import Event, { Emitter } from 'vs/base/common/event'; -import URI from 'vs/base/common/uri'; +import * as nls from 'vs/nls'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import { EditorModel, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { Builder, $ } from 'vs/base/browser/builder'; +import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IWindowsService } from 'vs/platform/windows/common/windows'; import { ResourceViewerContext, ResourceViewer } from 'vs/workbench/browser/parts/editor/resourceViewer'; +import URI from 'vs/base/common/uri'; +import { Dimension } from 'vs/base/browser/dom'; + +export interface IOpenCallbacks { + openInternal: (input: EditorInput, options: EditorOptions) => void; + openExternal: (uri: URI) => void; +} /* * This class is only intended to be subclassed and not instantiated. */ export abstract class BaseBinaryResourceEditor extends BaseEditor { - private _onMetadataChanged: Emitter<void>; - private metadata: string; + private readonly _onMetadataChanged: Emitter<void>; + + private callbacks: IOpenCallbacks; + private metadata: string; private binaryContainer: Builder; private scrollbar: DomScrollableElement; private resourceViewerContext: ResourceViewerContext; constructor( id: string, + callbacks: IOpenCallbacks, telemetryService: ITelemetryService, - themeService: IThemeService, - private windowsService: IWindowsService + themeService: IThemeService ) { super(id, telemetryService, themeService); this._onMetadataChanged = new Emitter<void>(); + this.toUnbind.push(this._onMetadataChanged); + + this.callbacks = callbacks; } public get onMetadataChanged(): Event<void> { @@ -50,7 +60,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { return this.input ? this.input.getName() : nls.localize('binaryEditor', "Binary Viewer"); } - protected createEditor(parent: Builder): void { + protected createEditor(parent: HTMLElement): void { // Container for Binary const binaryContainerElement = document.createElement('div'); @@ -61,7 +71,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { // Custom Scrollbars this.scrollbar = new DomScrollableElement(binaryContainerElement, { horizontal: ScrollbarVisibility.Auto, vertical: ScrollbarVisibility.Auto }); - parent.getHTMLElement().appendChild(this.scrollbar.getDomNode()); + parent.appendChild(this.scrollbar.getDomNode()); } public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> { @@ -74,10 +84,10 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { // Otherwise set input and resolve return super.setInput(input, options).then(() => { - return input.resolve(true).then((resolvedModel: EditorModel) => { + return input.resolve(true).then(model => { // Assert Model instance - if (!(resolvedModel instanceof BinaryEditorModel)) { + if (!(model instanceof BinaryEditorModel)) { return TPromise.wrapError<void>(new Error('Unable to open file as binary')); } @@ -87,21 +97,14 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { } // Render Input - const model = <BinaryEditorModel>resolvedModel; this.resourceViewerContext = ResourceViewer.show( { name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag(), mime: model.getMime() }, - this.binaryContainer, + this.binaryContainer.getHTMLElement(), this.scrollbar, - (resource: URI) => { - this.windowsService.openExternal(resource.toString()).then(didOpen => { - if (!didOpen) { - return this.windowsService.showItemInFolder(resource.fsPath); - } - - return void 0; - }); - }, - (meta) => this.handleMetadataChanged(meta)); + resource => this.callbacks.openInternal(input, options), + resource => this.callbacks.openExternal(resource), + meta => this.handleMetadataChanged(meta) + ); return TPromise.as<void>(null); }); @@ -117,6 +120,10 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { return this.metadata; } + public supportsCenteredLayout(): boolean { + return false; + } + public clearInput(): void { // Clear Meta diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index c312ee65f9..fbefc1c031 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -5,7 +5,7 @@ 'use strict'; import { Registry } from 'vs/platform/registry/common/platform'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; import { Action, IAction } from 'vs/base/common/actions'; import { IEditorQuickOpenEntry, IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; @@ -225,7 +225,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction, export class QuickOpenActionContributor extends ActionBarContributor { private openToSideActionInstance: OpenToSideAction; - constructor( @IInstantiationService private instantiationService: IInstantiationService) { + constructor(@IInstantiationService private instantiationService: IInstantiationService) { super(); } diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 3e47e5d693..34fb8e2117 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { mixin } from 'vs/base/common/objects'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; @@ -543,6 +543,50 @@ export class CloseEditorAction extends Action { } } +export class CloseOneEditorAction extends Action { + + public static readonly ID = 'workbench.action.closeActiveEditor'; + public static readonly LABEL = nls.localize('closeOneEditor', "Close"); + + constructor( + id: string, + label: string, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IEditorGroupService private editorGroupService: IEditorGroupService + ) { + super(id, label, 'close-editor-action'); + } + + public run(context?: IEditorCommandsContext): TPromise<any> { + const model = this.editorGroupService.getStacksModel(); + + const group = context ? model.getGroup(context.groupId) : null; + const position = group ? model.positionOfGroup(group) : null; + + // Close Active Editor + if (typeof position !== 'number') { + const activeEditor = this.editorService.getActiveEditor(); + if (activeEditor) { + return this.editorService.closeEditor(activeEditor.position, activeEditor.input); + } + } + + // Close Specific Editor + const editor = group && context && typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : null; + if (editor) { + return this.editorService.closeEditor(position, editor); + } + + // Close First Editor at Position + const visibleEditors = this.editorService.getVisibleEditors(); + if (visibleEditors[position]) { + return this.editorService.closeEditor(position, visibleEditors[position].input); + } + + return TPromise.as(false); + } +} + export class RevertAndCloseEditorAction extends Action { public static readonly ID = 'workbench.action.revertAndCloseActiveEditor'; diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 06e36db099..3a7f893470 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -70,7 +70,7 @@ function registerActiveEditorMoveCommand(): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ id: EditorCommands.MoveActiveEditor, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: EditorContextKeys.textFocus, + when: EditorContextKeys.editorTextFocus, primary: null, handler: (accessor, args: any) => moveActiveEditor(args, accessor), description: { @@ -269,7 +269,7 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U), - handler: (accessor, resource: URI, context: IEditorCommandsContext) => { + handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const model = editorGroupService.getStacksModel(); const editorService = accessor.get(IWorkbenchEditorService); @@ -299,7 +299,7 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W), - handler: (accessor, resource: URI, context: IEditorCommandsContext) => { + handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); const contexts = getMultiSelectedEditorContexts(context, accessor.get(IListService)); @@ -324,7 +324,7 @@ function registerEditorCommands() { when: void 0, primary: KeyMod.CtrlCmd | KeyCode.KEY_W, win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] }, - handler: (accessor, resource: URI, context: IEditorCommandsContext) => { + handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); @@ -373,7 +373,7 @@ function registerEditorCommands() { when: void 0, primary: void 0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T }, - handler: (accessor, resource: URI, context: IEditorCommandsContext) => { + handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); const contexts = getMultiSelectedEditorContexts(context, accessor.get(IListService)); diff --git a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts index 239a5ab166..f14a5b04c9 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts @@ -6,16 +6,16 @@ 'use strict'; import 'vs/css!./media/editorGroupsControl'; -import arrays = require('vs/base/common/arrays'); -import Event, { Emitter } from 'vs/base/common/event'; +import * as arrays from 'vs/base/common/arrays'; +import { Event, Emitter } from 'vs/base/common/event'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import types = require('vs/base/common/types'); -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; +import * as types from 'vs/base/common/types'; +import { Builder, $ } from 'vs/base/browser/builder'; import { Sash, ISashEvent, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation } from 'vs/base/browser/ui/sash/sash'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import DOM = require('vs/base/browser/dom'); -import errors = require('vs/base/common/errors'); +import * as DOM from 'vs/base/browser/dom'; +import * as errors from 'vs/base/common/errors'; import { RunOnceScheduler } from 'vs/base/common/async'; import { isMacintosh } from 'vs/base/common/platform'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -29,7 +29,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl'; import { ITitleAreaControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { NoTabsTitleControl } from 'vs/workbench/browser/parts/editor/noTabsTitleControl'; -import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup, EditorOptions, TextEditorOptions, IEditorIdentifier, EditorInput, PREFERENCES_EDITOR_ID, TEXT_DIFF_EDITOR_ID } from 'vs/workbench/common/editor'; +import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup, EditorOptions, TextEditorOptions, IEditorIdentifier, EditorInput } from 'vs/workbench/common/editor'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { editorBackground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -40,6 +40,7 @@ import { ResourcesDropHandler, LocalSelectionTransfer, DraggedEditorIdentifier } import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IPartService } from 'vs/workbench/services/part/common/partService'; + export enum Rochade { NONE, TWO_TO_ONE, @@ -74,7 +75,7 @@ export interface IEditorGroupsControl { updateProgress(position: Position, state: ProgressState): void; updateTitleAreas(refreshActive?: boolean): void; - layout(dimension: Dimension): void; + layout(dimension: DOM.Dimension): void; layout(position: Position): void; arrangeGroups(arrangement: GroupArrangement): void; @@ -121,8 +122,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro private stacks: IEditorStacksModel; - private parent: Builder; - private dimension: Dimension; + private parent: HTMLElement; + private dimension: DOM.Dimension; private dragging: boolean; private layoutVertically: boolean; @@ -151,7 +152,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro private centeredEditorActive: boolean; private centeredEditorSashLeft: Sash; private centeredEditorSashRight: Sash; - private centeredEditorPreferedSize: number; + private centeredEditorPreferredSize: number; private centeredEditorLeftMarginRatio: number; private centeredEditorDragStartPosition: number; private centeredEditorDragStartSize: number; @@ -163,7 +164,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro private visibleEditorFocusTrackerDisposable: IDisposable[]; - private _onGroupFocusChanged: Emitter<void>; + private readonly _onGroupFocusChanged: Emitter<void>; private onStacksChangeScheduler: RunOnceScheduler; private stacksChangedBuffer: IStacksModelChangeEvent[]; @@ -171,12 +172,12 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro private transfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>(); constructor( - parent: Builder, + parent: HTMLElement, groupOrientation: GroupOrientation, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IEditorGroupService private editorGroupService: IEditorGroupService, @IPartService private partService: IPartService, - @IStorageService private storageServise: IStorageService, + @IStorageService private storageService: IStorageService, @IContextKeyService private contextKeyService: IContextKeyService, @IExtensionService private extensionService: IExtensionService, @IInstantiationService private instantiationService: IInstantiationService, @@ -188,7 +189,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.stacks = editorGroupService.getStacksModel(); this.parent = parent; - this.dimension = new Dimension(0, 0); + this.dimension = new DOM.Dimension(0, 0); this.silos = []; this.silosSize = []; @@ -291,6 +292,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro titleControl.dispose(); titleContainer.empty(); this.createTitleControl(this.stacks.groupAt(position), this.silos[position], titleContainer, this.getInstantiationService(position)); + this.layoutTitleControl(position); } // Refresh title when layout options change @@ -369,8 +371,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.trackFocus(editor, position); // Find target container and build into - const target = this.silos[position].child(); - editor.getContainer().build(target); + const target = this.silos[position].child().getHTMLElement(); + target.appendChild(editor.getContainer()); // Adjust layout according to provided ratios (used when restoring multiple editors at once) if (ratio && (ratio.length === 2 || ratio.length === 3)) { @@ -442,7 +444,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } // Show editor container - editor.getContainer().show(); + DOM.show(editor.getContainer()); } private getVisibleEditorCount(): number { @@ -554,7 +556,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.clearPosition(position); // Take editor container offdom and hide - editor.getContainer().offDOM().hide(); + const editorContainer = editor.getContainer(); + if (editorContainer.parentNode) { + editorContainer.parentNode.removeChild(editorContainer); + } + DOM.hide(editorContainer); // Adjust layout and rochade if instructed to do so if (layoutAndRochade) { @@ -780,10 +786,10 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.layoutVertically = (orientation !== 'horizontal'); // Editor Layout - const verticalLayouting = this.parent.hasClass('vertical-layout'); + const verticalLayouting = DOM.hasClass(this.parent, 'vertical-layout'); if (verticalLayouting !== this.layoutVertically) { - this.parent.removeClass('vertical-layout', 'horizontal-layout'); - this.parent.addClass(this.layoutVertically ? 'vertical-layout' : 'horizontal-layout'); + DOM.removeClasses(this.parent, 'vertical-layout', 'horizontal-layout'); + DOM.addClass(this.parent, this.layoutVertically ? 'vertical-layout' : 'horizontal-layout'); this.sashOne.setOrientation(this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL); this.sashTwo.setOrientation(this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL); @@ -968,16 +974,16 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro private create(): void { // Store layout as class property - this.parent.addClass(this.layoutVertically ? 'vertical-layout' : 'horizontal-layout'); + DOM.addClass(this.parent, this.layoutVertically ? 'vertical-layout' : 'horizontal-layout'); // Allow to drop into container to open - this.enableDropTarget(this.parent.getHTMLElement()); + this.enableDropTarget(this.parent); // Silo One this.silos[Position.ONE] = $(this.parent).div({ class: 'one-editor-silo editor-one' }); // Sash One - this.sashOne = new Sash(this.parent.getHTMLElement(), this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL }); + this.sashOne = new Sash(this.parent, this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL }); this.toUnbind.push(this.sashOne.onDidStart(() => this.onSashOneDragStart())); this.toUnbind.push(this.sashOne.onDidChange((e: ISashEvent) => this.onSashOneDrag(e))); this.toUnbind.push(this.sashOne.onDidEnd(() => this.onSashOneDragEnd())); @@ -988,7 +994,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.silos[Position.TWO] = $(this.parent).div({ class: 'one-editor-silo editor-two' }); // Sash Two - this.sashTwo = new Sash(this.parent.getHTMLElement(), this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL }); + this.sashTwo = new Sash(this.parent, this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL }); this.toUnbind.push(this.sashTwo.onDidStart(() => this.onSashTwoDragStart())); this.toUnbind.push(this.sashTwo.onDidChange((e: ISashEvent) => this.onSashTwoDrag(e))); this.toUnbind.push(this.sashTwo.onDidEnd(() => this.onSashTwoDragEnd())); @@ -1033,9 +1039,9 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.createTitleControl(this.stacks.groupAt(position), silo, titleContainer, instantiationService); // Progress Bar - const progressBar = new ProgressBar($(container)); + const progressBar = new ProgressBar(container.getHTMLElement()); this.toUnbind.push(attachProgressBarStyler(progressBar, this.themeService)); - progressBar.getContainer().hide(); + progressBar.hide(); container.setProperty(EditorGroupsControl.PROGRESS_BAR_CONTROL_KEY, progressBar); // associate with container // Sash for first position to support centered editor layout @@ -1059,11 +1065,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.centeredEditorLeftMarginRatio = 0.5; // Restore centered layout position and size - const centeredLayoutDataString = this.storageServise.get(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL); + const centeredLayoutDataString = this.storageService.get(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL); if (centeredLayoutDataString) { const centeredLayout = <CenteredEditorLayoutData>JSON.parse(centeredLayoutDataString); this.centeredEditorLeftMarginRatio = centeredLayout.leftMarginRatio; - this.centeredEditorPreferedSize = centeredLayout.size; + this.centeredEditorPreferredSize = centeredLayout.size; } } } @@ -1284,7 +1290,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro if (!overlay) { const containers = $this.visibleEditors.filter(e => !!e).map(e => e.getContainer()); containers.forEach((container, index) => { - if (container && DOM.isAncestor(target, container.getHTMLElement())) { + if (container && DOM.isAncestor(target, container)) { const activeContrastBorderColor = $this.getColor(activeContrastBorder); overlay = $('div').style({ top: $this.tabOptions.showTabs ? `${EditorGroupsControl.EDITOR_TITLE_HEIGHT}px` : 0, @@ -1596,8 +1602,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro // TODO@Ben remove me after a while /* __GDPR__ "editorGroupMoved" : { - "source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "to": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "to": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('editorGroupMoved', { source: position, to: moveTo }); @@ -1627,11 +1633,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro let borderColor = null; if (isDragging) { - this.parent.addClass('dragging'); + DOM.addClass(this.parent, 'dragging'); silo.addClass('dragging'); borderColor = this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder); } else { - this.parent.removeClass('dragging'); + DOM.removeClass(this.parent, 'dragging'); silo.removeClass('dragging'); } @@ -1930,11 +1936,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } private get centeredEditorAvailableSize(): number { - return this.silosSize[Position.ONE] - EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN * 2; + return this.dimension.width - EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN * 2; } private get centeredEditorSize(): number { - return Math.min(this.centeredEditorAvailableSize, this.centeredEditorPreferedSize); + return Math.min(this.centeredEditorAvailableSize, this.centeredEditorPreferredSize); } private get centeredEditorPosition(): number { @@ -1956,7 +1962,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } if (size > 3 * this.minSize && size < this.centeredEditorAvailableSize) { - this.centeredEditorPreferedSize = size; + this.centeredEditorPreferredSize = size; position -= EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN; position = Math.min(position, this.centeredEditorAvailableSize - this.centeredEditorSize); position = Math.max(0, position); @@ -1971,7 +1977,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro leftMarginRatio: this.centeredEditorLeftMarginRatio, size: this.centeredEditorSize }; - this.storageServise.store(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, JSON.stringify(data), StorageScope.GLOBAL); + this.storageService.store(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, JSON.stringify(data), StorageScope.GLOBAL); } public getVerticalSashTop(sash: Sash): number { @@ -2013,17 +2019,17 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro return this.dragging; } - public layout(dimension: Dimension): void; + public layout(dimension: DOM.Dimension): void; public layout(position: Position): void; public layout(arg: any): void { - if (arg instanceof Dimension) { - this.layoutControl(<Dimension>arg); + if (arg instanceof DOM.Dimension) { + this.layoutControl(<DOM.Dimension>arg); } else { this.layoutEditor(<Position>arg); } } - private layoutControl(dimension: Dimension): void { + private layoutControl(dimension: DOM.Dimension): void { let oldDimension = this.dimension; this.dimension = dimension; @@ -2141,14 +2147,14 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro }); // Layout centered Editor (only in vertical layout when one group is opened) - const id = this.visibleEditors[Position.ONE] ? this.visibleEditors[Position.ONE].getId() : undefined; - const doCentering = this.layoutVertically && this.stacks.groups.length === 1 && this.partService.isEditorLayoutCentered() && id !== PREFERENCES_EDITOR_ID && id !== TEXT_DIFF_EDITOR_ID; + const doCentering = this.partService.isEditorLayoutCentered() && this.stacks.groups.length === 1 && + this.visibleEditors[Position.ONE] && this.visibleEditors[Position.ONE].supportsCenteredLayout(); if (doCentering && !this.centeredEditorActive) { this.centeredEditorSashLeft.show(); this.centeredEditorSashRight.show(); // no size set yet. Calculate a default value - if (!this.centeredEditorPreferedSize) { + if (!this.centeredEditorPreferredSize) { this.resetCenteredEditor(false); } } else if (!doCentering && this.centeredEditorActive) { @@ -2169,16 +2175,18 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro }); // Layout title controls - POSITIONS.forEach(position => { - const siloWidth = this.layoutVertically ? this.silosSize[position] : this.dimension.width; - - this.getTitleAreaControl(position).layout(new Dimension(siloWidth, EditorGroupsControl.EDITOR_TITLE_HEIGHT)); - }); + POSITIONS.forEach(position => this.layoutTitleControl(position)); // Update minimized state this.updateMinimizedState(); } + private layoutTitleControl(position: Position): void { + const siloWidth = this.layoutVertically ? this.silosSize[position] : this.dimension.width; + + this.getTitleAreaControl(position).layout(new DOM.Dimension(siloWidth, EditorGroupsControl.EDITOR_TITLE_HEIGHT)); + } + private layoutEditor(position: Position): void { const editorSize = this.silosSize[position]; const editor = this.visibleEditors[position]; @@ -2201,20 +2209,20 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } const editorContainer = editor.getContainer(); - editorContainer.style('margin-left', this.centeredEditorActive ? `${editorPosition}px` : null); - editorContainer.style('width', this.centeredEditorActive ? `${editorWidth}px` : null); - editorContainer.style('border-color', this.centeredEditorActive ? this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder) : null); - editor.layout(new Dimension(editorWidth, editorHeight)); + editorContainer.style.marginLeft = this.centeredEditorActive ? `${editorPosition}px` : null; + editorContainer.style.width = this.centeredEditorActive ? `${editorWidth}px` : null; + editorContainer.style.borderColor = this.centeredEditorActive ? this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder) : null; + editor.layout(new DOM.Dimension(editorWidth, editorHeight)); } } private resetCenteredEditor(layout: boolean = true) { this.centeredEditorLeftMarginRatio = 0.5; - this.centeredEditorPreferedSize = Math.floor(this.dimension.width * EditorGroupsControl.GOLDEN_RATIO); + this.centeredEditorPreferredSize = Math.floor(this.dimension.width * EditorGroupsControl.GOLDEN_RATIO); if (layout) { this.layoutContainers(); } - this.storageServise.remove(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL); + this.storageService.remove(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL); } public getInstantiationService(position: Position): IInstantiationService { @@ -2269,13 +2277,13 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro switch (state) { case ProgressState.INFINITE: - progressbar.infinite().getContainer().show(); + progressbar.infinite().show(); break; case ProgressState.DONE: - progressbar.done().getContainer().hide(); + progressbar.done().hide(); break; case ProgressState.STOP: - progressbar.stop().getContainer().hide(); + progressbar.stop().hide(); break; } } diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 5268384a98..80fda9778c 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -9,12 +9,11 @@ import 'vs/css!./media/editorpart'; import 'vs/workbench/browser/parts/editor/editor.contribution'; import { TPromise } from 'vs/base/common/winjs.base'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import nls = require('vs/nls'); -import strings = require('vs/base/common/strings'); -import arrays = require('vs/base/common/arrays'); -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); +import * as nls from 'vs/nls'; +import * as strings from 'vs/base/common/strings'; +import * as arrays from 'vs/base/common/arrays'; +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; import * as objects from 'vs/base/common/objects'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; import { toErrorMessage } from 'vs/base/common/errorMessage'; @@ -35,20 +34,19 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { EditorStacksModel, EditorGroup, EditorIdentifier, EditorCloseEvent } from 'vs/workbench/common/editor/editorStacksModel'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { EDITOR_GROUP_BACKGROUND } from 'vs/workbench/common/theme'; -import { createCSSRule } from 'vs/base/browser/dom'; +import { createCSSRule, Dimension, addClass, removeClass } from 'vs/base/browser/dom'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { join } from 'vs/base/common/paths'; import { IEditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { ThrottledEmitter } from 'vs/base/common/async'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import { isUndefinedOrNull } from 'vs/base/common/types'; import { INotificationService, Severity, INotificationActions } from 'vs/platform/notification/common/notification'; -import { isErrorWithActions } from 'vs/base/common/errors'; +import { dispose } from 'vs/base/common/lifecycle'; // {{SQL CARBON EDIT}} import { convertEditorInput } from 'sql/parts/common/customInputConverter'; @@ -107,16 +105,17 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService private forceHideTabs: boolean; private doNotFireTabOptionsChanged: boolean; private revealIfOpen: boolean; - - private _onEditorsChanged: ThrottledEmitter<void>; - private _onEditorOpening: Emitter<IEditorOpeningEvent>; - private _onEditorGroupMoved: Emitter<void>; - private _onEditorOpenFail: Emitter<EditorInput>; - private _onGroupOrientationChanged: Emitter<void>; - private _onTabOptionsChanged: Emitter<IEditorTabOptions>; - + private ignoreOpenEditorErrors: boolean; private textCompareEditorVisible: IContextKey<boolean>; + private readonly _onEditorsChanged: ThrottledEmitter<void>; + private readonly _onEditorOpening: Emitter<IEditorOpeningEvent>; + private readonly _onEditorGroupMoved: Emitter<void>; + private readonly _onEditorOpenFail: Emitter<EditorInput>; + private readonly _onGroupOrientationChanged: Emitter<void>; + private readonly _onTabOptionsChanged: Emitter<IEditorTabOptions>; + private readonly _onLayout: Emitter<Dimension>; + // The following data structures are partitioned into array of Position as provided by Services.POSITION array private visibleEditors: BaseEditor[]; private instantiatedEditors: BaseEditor[][]; @@ -124,9 +123,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService private pendingEditorInputsToClose: EditorIdentifier[]; private pendingEditorInputCloseTimeout: number; - private onLayoutEmitter = new Emitter<Dimension>(); - public onLayout = this.onLayoutEmitter.event; - constructor( id: string, restoreFromStorage: boolean, @@ -148,6 +144,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this._onEditorOpenFail = new Emitter<EditorInput>(); this._onGroupOrientationChanged = new Emitter<void>(); this._onTabOptionsChanged = new Emitter<IEditorTabOptions>(); + this._onLayout = new Emitter<Dimension>(); this.visibleEditors = []; @@ -298,6 +295,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.editorGroupsControl.resizeGroup(position, groupSizeChange); } + public get onLayout(): Event<Dimension> { + return this._onLayout.event; + } + public get onEditorsChanged(): Event<void> { return this._onEditorsChanged.event; } @@ -479,11 +480,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Create editor as needed if (!editor.getContainer()) { - editor.create($().div({ - 'class': 'editor-container', - 'role': 'tabpanel', - id: descriptor.getId() - })); + const editorContainer = document.createElement('div'); + editorContainer.id = descriptor.getId(); + addClass(editorContainer, 'editor-container'); + editorContainer.setAttribute('role', 'tabpanel'); + + editor.create(editorContainer); } return editor; @@ -555,18 +557,21 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Stop loading promise if any monitor.cancel(); - // Report error only if this was not us restoring previous error state - if (this.partService.isCreated() && !errors.isPromiseCanceledError(error)) { + // Report error only if this was not us restoring previous error state or + // we are told to ignore errors that occur from opening an editor + if (this.partService.isCreated() && !errors.isPromiseCanceledError(error) && !this.ignoreOpenEditorErrors) { const actions: INotificationActions = { primary: [] }; - if (isErrorWithActions(error)) { - actions.primary = error.actions; + if (errors.isErrorWithActions(error)) { + actions.primary = (error as errors.IErrorWithActions).actions; } - this.notificationService.notify({ + const handle = this.notificationService.notify({ severity: Severity.Error, message: nls.localize('editorOpenError', "Unable to open '{0}': {1}.", input.getName(), toErrorMessage(error)), actions }); + + once(handle.onDidClose)(() => dispose(actions.primary)); } this.editorGroupsControl.updateProgress(position, ProgressState.DONE); @@ -576,7 +581,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Recover by closing the active editor (if the input is still the active one) if (group.activeEditor === input) { - this.doCloseActiveEditor(group, !(options && options.preserveFocus) /* still preserve focus as needed */); + this.doCloseActiveEditor(group, !(options && options.preserveFocus) /* still preserve focus as needed */, true /* from error */); } } @@ -610,7 +615,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } } - private doCloseActiveEditor(group: EditorGroup, focusNext = true): void { + private doCloseActiveEditor(group: EditorGroup, focusNext = true, fromError?: boolean): void { const position = this.stacks.positionOfGroup(group); // Update stacks model @@ -623,7 +628,22 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Otherwise open next active else { - this.openEditor(group.activeEditor, !focusNext ? EditorOptions.create({ preserveFocus: true }) : null, position).done(null, errors.onUnexpectedError); + // When closing an editor due to an error we can end up in a loop where we continue closing + // editors that fail to open (e.g. when the file no longer exists). We do not want to show + // repeated errors in this case to the user. As such, if we open the next editor and we are + // in a scope of a previous editor failing, we silence the input errors until the editor is + // opened. + if (fromError) { + this.ignoreOpenEditorErrors = true; + } + + this.openEditor(group.activeEditor, !focusNext ? EditorOptions.create({ preserveFocus: true }) : null, position).done(() => { + this.ignoreOpenEditorErrors = false; + }, error => { + errors.onUnexpectedError(error); + + this.ignoreOpenEditorErrors = false; + }); } } @@ -710,7 +730,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } // Then check for array of positions to close - if (Array.isArray(positionsOrEditors) || isUndefinedOrNull(positionsOrEditors)) { + if (Array.isArray(positionsOrEditors) || types.isUndefinedOrNull(positionsOrEditors)) { return this.doCloseAllEditorsAtPositions(positionsOrEditors as Position[]); } @@ -833,16 +853,18 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Close: By Filter or all else { - editorsToClose = group.getEditors(true /* in MRU order */); filter = filterOrEditors || Object.create(null); + const hasDirection = !types.isUndefinedOrNull(filter.direction); + editorsToClose = group.getEditors(!hasDirection /* in MRU order only if direction is not specified */); + // Filter: saved only if (filter.savedOnly) { editorsToClose = editorsToClose.filter(e => !e.isDirty()); } // Filter: direction (left / right) - else if (!types.isUndefinedOrNull(filter.direction)) { + else if (hasDirection) { editorsToClose = (filter.direction === Direction.LEFT) ? editorsToClose.slice(0, group.indexOf(filter.except)) : editorsToClose.slice(group.indexOf(filter.except) + 1); } @@ -1141,12 +1163,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService return this.editorGroupsControl.getGroupOrientation(); } - public createContentArea(parent: Builder): Builder { + public createContentArea(parent: HTMLElement): HTMLElement { // Content Container - const contentArea = $(parent) - .div() - .addClass('content'); + const contentArea = document.createElement('div'); + addClass(contentArea, 'content'); + parent.appendChild(contentArea); // get settings this.memento = this.getMemento(this.storageService, MementoScope.WORKSPACE); @@ -1164,19 +1186,19 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService // Part container const container = this.getContainer(); - container.style('background-color', this.getColor(editorBackground)); + container.style.backgroundColor = this.getColor(editorBackground); // Content area const content = this.getContentArea(); const groupCount = this.stacks.groups.length; if (groupCount > 1) { - content.addClass('multiple-groups'); + addClass(content, 'multiple-groups'); } else { - content.removeClass('multiple-groups'); + removeClass(content, 'multiple-groups'); } - content.style('background-color', groupCount > 0 ? this.getColor(EDITOR_GROUP_BACKGROUND) : null); + content.style.backgroundColor = groupCount > 0 ? this.getColor(EDITOR_GROUP_BACKGROUND) : null; } private onGroupFocusChanged(): void { @@ -1474,7 +1496,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.dimension = sizes[1]; this.editorGroupsControl.layout(this.dimension); - this.onLayoutEmitter.fire(dimension); + this._onLayout.fire(dimension); return sizes; } @@ -1512,6 +1534,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this._onEditorOpening.dispose(); this._onEditorGroupMoved.dispose(); this._onEditorOpenFail.dispose(); + this._onGroupOrientationChanged.dispose(); + this._onTabOptionsChanged.dispose(); + this._onLayout.dispose(); // Reset Tokens this.editorOpenToken = []; diff --git a/src/vs/workbench/browser/parts/editor/editorPicker.ts b/src/vs/workbench/browser/parts/editor/editorPicker.ts index f4ac1aaf94..c03ea356ea 100644 --- a/src/vs/workbench/browser/parts/editor/editorPicker.ts +++ b/src/vs/workbench/browser/parts/editor/editorPicker.ts @@ -6,9 +6,9 @@ import 'vs/css!./media/editorpicker'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { IAutoFocus, Mode, IEntryRunContext, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenModel, QuickOpenEntry, QuickOpenEntryGroup, QuickOpenItemAccessor } from 'vs/base/parts/quickopen/browser/quickOpenModel'; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index d4a2fcb955..b7900ed49d 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -6,14 +6,14 @@ 'use strict'; import 'vs/css!./media/editorstatus'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import { $, append, runAtThisOrScheduleAtNextAnimationFrame, addDisposableListener } from 'vs/base/browser/dom'; -import strings = require('vs/base/common/strings'); -import paths = require('vs/base/common/paths'); -import types = require('vs/base/common/types'); +import { $, append, runAtThisOrScheduleAtNextAnimationFrame, addDisposableListener, getDomNodePagePosition } from 'vs/base/browser/dom'; +import * as strings from 'vs/base/common/strings'; +import * as paths from 'vs/base/common/paths'; +import * as types from 'vs/base/common/types'; import uri from 'vs/base/common/uri'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { Action } from 'vs/base/common/actions'; import { language, LANGUAGE_DEFAULT, AccessibilitySupport } from 'vs/base/common/platform'; @@ -50,35 +50,58 @@ import { IConfigurationChangedEvent, IEditorOptions } from 'vs/editor/common/con import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { attachStylerCallback, attachButtonStyler } from 'vs/platform/theme/common/styler'; -import { widgetShadow, editorWidgetBackground } from 'vs/platform/theme/common/colorRegistry'; +import { attachButtonStyler } from 'vs/platform/theme/common/styler'; +import { widgetShadow, editorWidgetBackground, foreground, darken, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { deepClone } from 'vs/base/common/objects'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Button } from 'vs/base/browser/ui/button/button'; import { Schemas } from 'vs/base/common/network'; +import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; +import { Themable } from 'vs/workbench/common/theme'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; -// TODO@Sandeep layer breaker -// tslint:disable-next-line:import-patterns -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; +class SideBySideEditorEncodingSupport implements IEncodingSupport { + constructor(private master: IEncodingSupport, private details: IEncodingSupport) { } + + public getEncoding(): string { + return this.master.getEncoding(); // always report from modified (right hand) side + } + + public setEncoding(encoding: string, mode: EncodingMode): void { + [this.master, this.details].forEach(s => s.setEncoding(encoding, mode)); + } +} // {{SQL CARBON EDIT}} import { QueryEditorService } from 'sql/parts/query/services/queryEditorService'; function toEditorWithEncodingSupport(input: IEditorInput): IEncodingSupport { - if (input instanceof SideBySideEditorInput) { - input = input.master; - } + // Untitled Editor if (input instanceof UntitledEditorInput) { return input; } + // Side by Side (diff) Editor + if (input instanceof SideBySideEditorInput) { + const masterEncodingSupport = toEditorWithEncodingSupport(input.master); + const detailsEncodingSupport = toEditorWithEncodingSupport(input.details); + + if (masterEncodingSupport && detailsEncodingSupport) { + return new SideBySideEditorEncodingSupport(masterEncodingSupport, detailsEncodingSupport); + } + + return masterEncodingSupport; + } + + // File or Resource Editor let encodingSupport = input as IFileEditorInput; if (types.areFunctions(encodingSupport.setEncoding, encodingSupport.getEncoding)) { return encodingSupport; } + // Unsupported for any other editor return null; } @@ -246,16 +269,16 @@ const nlsTabFocusMode = nls.localize('tabFocusModeEnabled', "Tab Moves Focus"); const nlsScreenReaderDetected = nls.localize('screenReaderDetected', "Screen Reader Optimized"); const nlsScreenReaderDetectedTitle = nls.localize('screenReaderDetectedExtra', "If you are not using a Screen Reader, please change the setting `editor.accessibilitySupport` to \"off\"."); -function _setDisplay(el: HTMLElement, desiredValue: string): void { +function setDisplay(el: HTMLElement, desiredValue: string): void { if (el.style.display !== desiredValue) { el.style.display = desiredValue; } } function show(el: HTMLElement): void { - _setDisplay(el, ''); + setDisplay(el, ''); } function hide(el: HTMLElement): void { - _setDisplay(el, 'none'); + setDisplay(el, 'none'); } export class EditorStatus implements IStatusbarItem { @@ -274,7 +297,7 @@ export class EditorStatus implements IStatusbarItem { private activeEditorListeners: IDisposable[]; private delayedRender: IDisposable; private toRender: StateChange; - private lastScreenReaderExplanation: ScreenReaderDetectedExplanation; + private screenReaderExplanation: ScreenReaderDetectedExplanation; constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @@ -289,7 +312,6 @@ export class EditorStatus implements IStatusbarItem { this.toDispose = []; this.activeEditorListeners = []; this.state = new State(); - this.lastScreenReaderExplanation = null; } public render(container: HTMLElement): IDisposable { @@ -313,7 +335,7 @@ export class EditorStatus implements IStatusbarItem { hide(this.selectionElement); this.indentationElement = append(this.element, $('a.editor-status-indentation')); - this.indentationElement.title = nls.localize('indentation', "Indentation"); + this.indentationElement.title = nls.localize('selectIndentation', "Select Indentation"); this.indentationElement.onclick = () => this.onIndentationClick(); hide(this.indentationElement); @@ -487,7 +509,18 @@ export class EditorStatus implements IStatusbarItem { } private onScreenReaderModeClick(): void { - this.lastScreenReaderExplanation = this.instantiationService.createInstance(ScreenReaderDetectedExplanation, this.screenRedearModeElement); + const showExplanation = !this.screenReaderExplanation || !this.screenReaderExplanation.visible; + + if (!this.screenReaderExplanation) { + this.screenReaderExplanation = this.instantiationService.createInstance(ScreenReaderDetectedExplanation); + this.toDispose.push(this.screenReaderExplanation); + } + + if (showExplanation) { + this.screenReaderExplanation.show(this.screenRedearModeElement); + } else { + this.screenReaderExplanation.hide(); + } } private onSelectionClick(): void { @@ -652,9 +685,8 @@ export class EditorStatus implements IStatusbarItem { screenReaderMode = (editorWidget.getConfiguration().accessibilitySupport === AccessibilitySupport.Enabled); } - if (screenReaderMode === false && this.lastScreenReaderExplanation) { - this.lastScreenReaderExplanation.hide(); - this.lastScreenReaderExplanation = null; + if (screenReaderMode === false && this.screenReaderExplanation && this.screenReaderExplanation.visible) { + this.screenReaderExplanation.hide(); } this.updateState({ screenReaderMode: screenReaderMode }); @@ -1229,113 +1261,148 @@ export class ChangeEncodingAction extends Action { } } -class ScreenReaderDetectedExplanation { - - private _isDisposed: boolean; - private _toDispose: IDisposable[]; +class ScreenReaderDetectedExplanation extends Themable { + private container: HTMLElement; + private hrElement: HTMLHRElement; + private _visible: boolean; constructor( - anchorElement: HTMLElement, - @IThemeService private readonly themeService: IThemeService, + @IThemeService themeService: IThemeService, @IContextViewService private readonly contextViewService: IContextViewService, @IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService, ) { - this._isDisposed = false; - this._toDispose = []; + super(themeService); + } + + public get visible(): boolean { + return this._visible; + } + + protected updateStyles(): void { + if (this.container) { + const background = this.getColor(editorWidgetBackground); + this.container.style.backgroundColor = background ? background.toString() : null; + + const widgetShadowColor = this.getColor(widgetShadow); + this.container.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : null; + + const contrastBorderColor = this.getColor(contrastBorder); + this.container.style.border = contrastBorderColor ? `1px solid ${contrastBorderColor}` : null; + + const foregroundColor = this.getColor(foreground); + this.hrElement.style.backgroundColor = foregroundColor ? foregroundColor.toString() : null; + } + } + + public show(anchorElement: HTMLElement): void { + this._visible = true; this.contextViewService.showContextView({ - getAnchor: () => anchorElement, + getAnchor: () => { + const res = getDomNodePagePosition(anchorElement); + return { + x: res.left, + y: res.top - 9, /* above the status bar */ + width: res.width, + height: res.height + } as IAnchor; + }, render: (container) => { return this.renderContents(container); }, - - onDOMEvent: (e, activeElement) => { - }, - + onDOMEvent: (e, activeElement) => { }, onHide: () => { - this.dispose(); + this._visible = false; } }); } - public dispose(): void { - this._isDisposed = true; - this._toDispose = dispose(this._toDispose); - } - public hide(): void { - if (this._isDisposed) { - return; - } this.contextViewService.hideContextView(); } - protected renderContents(container: HTMLElement): IDisposable { - const domNode = $('div.screen-reader-detected-explanation', { + protected renderContents(parent: HTMLElement): IDisposable { + const toDispose: IDisposable[] = []; + + this.container = $('div.screen-reader-detected-explanation', { 'aria-hidden': 'true' }); const title = $('h2.title', {}, nls.localize('screenReaderDetectedExplanation.title', "Screen Reader Optimized")); - domNode.appendChild(title); + this.container.appendChild(title); const closeBtn = $('div.cancel'); - this._toDispose.push(addDisposableListener(closeBtn, 'click', () => { + toDispose.push(addDisposableListener(closeBtn, 'click', () => { this.contextViewService.hideContextView(); })); - domNode.appendChild(closeBtn); + toDispose.push(addDisposableListener(closeBtn, 'mouseover', () => { + const theme = this.themeService.getTheme(); + let darkenFactor: number; + switch (theme.type) { + case 'light': + darkenFactor = 0.1; + break; + case 'dark': + darkenFactor = 0.2; + break; + } + + if (darkenFactor) { + closeBtn.style.backgroundColor = this.getColor(editorWidgetBackground, (color, theme) => darken(color, darkenFactor)(theme)); + } + })); + toDispose.push(addDisposableListener(closeBtn, 'mouseout', () => { + closeBtn.style.backgroundColor = null; + })); + this.container.appendChild(closeBtn); // {{SQL CARBON EDIT}} const question = $('p.question', {}, nls.localize('screenReaderDetectedExplanation.question', "Are you using a screen reader to operate SQL Operations Studio?")); - domNode.appendChild(question); + this.container.appendChild(question); const buttonContainer = $('div.buttons'); - domNode.appendChild(buttonContainer); + this.container.appendChild(buttonContainer); const yesBtn = new Button(buttonContainer); yesBtn.label = nls.localize('screenReaderDetectedExplanation.answerYes', "Yes"); - this._toDispose.push(attachButtonStyler(yesBtn, this.themeService)); - this._toDispose.push(yesBtn.onDidClick(e => { + toDispose.push(attachButtonStyler(yesBtn, this.themeService)); + toDispose.push(yesBtn.onDidClick(e => { this.configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER); this.contextViewService.hideContextView(); })); const noBtn = new Button(buttonContainer); noBtn.label = nls.localize('screenReaderDetectedExplanation.answerNo', "No"); - this._toDispose.push(attachButtonStyler(noBtn, this.themeService)); - this._toDispose.push(noBtn.onDidClick(e => { + toDispose.push(attachButtonStyler(noBtn, this.themeService)); + toDispose.push(noBtn.onDidClick(e => { this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER); this.contextViewService.hideContextView(); })); const clear = $('div'); clear.style.clear = 'both'; - domNode.appendChild(clear); + this.container.appendChild(clear); const br = $('br'); - domNode.appendChild(br); + this.container.appendChild(br); - const hr = $('hr'); - domNode.appendChild(hr); + this.hrElement = $('hr'); + this.container.appendChild(this.hrElement); // {{SQL CARBON EDIT}} const explanation1 = $('p.body1', {}, nls.localize('screenReaderDetectedExplanation.body1', "SQL Operations Studio is now optimized for usage with a screen reader.")); - domNode.appendChild(explanation1); + this.container.appendChild(explanation1); const explanation2 = $('p.body2', {}, nls.localize('screenReaderDetectedExplanation.body2', "Some editor features will have different behaviour: e.g. word wrapping, folding, etc.")); - domNode.appendChild(explanation2); + this.container.appendChild(explanation2); - container.appendChild(domNode); + parent.appendChild(this.container); - this._toDispose.push(attachStylerCallback(this.themeService, { widgetShadow, editorWidgetBackground }, colors => { - domNode.style.backgroundColor = colors.editorWidgetBackground; - if (colors.widgetShadow) { - domNode.style.boxShadow = `0 5px 8px ${colors.widgetShadow}`; - } - })); + this.updateStyles(); return { - dispose: () => { this.dispose(); } + dispose: () => dispose(toDispose) }; } } diff --git a/src/vs/workbench/browser/parts/editor/media/editorpicker.css b/src/vs/workbench/browser/parts/editor/media/editorpicker.css index c02d6e8c0a..6e3cb19a7a 100644 --- a/src/vs/workbench/browser/parts/editor/media/editorpicker.css +++ b/src/vs/workbench/browser/parts/editor/media/editorpicker.css @@ -3,6 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry.editor-preview { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry.editor-preview { font-style: italic; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/media/editorstatus.css b/src/vs/workbench/browser/parts/editor/media/editorstatus.css index 99f23afade..3327f91060 100644 --- a/src/vs/workbench/browser/parts/editor/media/editorstatus.css +++ b/src/vs/workbench/browser/parts/editor/media/editorstatus.css @@ -22,7 +22,6 @@ cursor: default !important; } - .monaco-shell .screen-reader-detected-explanation { width: 420px; top: 30px; @@ -53,8 +52,9 @@ font-size: 1.2em; } -.monaco-shell .screen-reader-detected-explanation p.question { - font-size: 1.4em; +.monaco-shell .screen-reader-detected-explanation hr { + border: 0; + height: 2px; } .monaco-shell .screen-reader-detected-explanation .buttons { @@ -72,21 +72,8 @@ .monaco-shell.vs .screen-reader-detected-explanation .cancel { background: url('close-big.svg') center center no-repeat; } -.monaco-shell.vs .screen-reader-detected-explanation .cancel:hover { - background-color: #eaeaea; -} .monaco-shell.vs-dark .screen-reader-detected-explanation .cancel, .monaco-shell.hc-black .screen-reader-detected-explanation .cancel { background: url('close-big-dark.svg') center center no-repeat; -} -.monaco-shell.vs-dark .screen-reader-detected-explanation .cancel:hover { - background-color: rgba(30,30,30,0.8); -} - -.monaco-shell.hc-black .screen-reader-detected-explanation .cancel { - opacity: 0.6; -} -.monaco-shell.hc-black .screen-reader-detected-explanation .cancel:hover { - opacity: 1; -} +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/media/resourceviewer.css b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css index 40fbffdc95..54be06f243 100644 --- a/src/vs/workbench/browser/parts/editor/media/resourceviewer.css +++ b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css @@ -54,8 +54,9 @@ cursor: zoom-out; } -.monaco-resource-viewer .open-external, -.monaco-resource-viewer .open-external:hover { +.monaco-resource-viewer .embedded-link, +.monaco-resource-viewer .embedded-link:hover { cursor: pointer; text-decoration: underline; + margin-left: 5px; } diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitle.css b/src/vs/workbench/browser/parts/editor/media/tabstitle.css index f781a26101..b1e586fa2f 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitle.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitle.css @@ -62,15 +62,24 @@ max-width: fit-content; } +.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after, +.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after { + content: ""; + display: flex; + flex: 0; + width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */ +} + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-left { min-width: 80px; /* make more room for close button when it shows to the left */ + padding-right: 5px; /* we need less room when sizing is shrink */ } .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged { will-change: transform; /* forces tab to be drawn on a separate layer (fixes https://github.com/Microsoft/vscode/issues/18733) */ } -.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged-over * { +.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged-over div { pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */ } @@ -190,6 +199,10 @@ padding-right: 10px; /* give a little bit more room if close button is off */ } +.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-off { + padding-right: 5px; /* we need less room when sizing is shrink */ +} + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.close-button-off.dirty { background-repeat: no-repeat; background-position-y: center; diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 3f21fe11de..9b5264c070 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -6,9 +6,9 @@ 'use strict'; import 'vs/css!./media/notabstitle'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { toResource } from 'vs/workbench/common/editor'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import { Verbosity } from 'vs/platform/editor/common/editor'; @@ -81,14 +81,14 @@ export class NoTabsTitleControl extends TitleControl { // Close editor on middle mouse click if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) { - this.closeEditorAction.run({ groupId: group.id, editorIndex: group.indexOf(group.activeEditor) }).done(null, errors.onUnexpectedError); + this.closeOneEditorAction.run({ groupId: group.id, editorIndex: group.indexOf(group.activeEditor) }).done(null, errors.onUnexpectedError); } // Focus editor group unless: // - click on toolbar: should trigger actions within // - mouse click: do not focus group if there are more than one as it otherwise makes group DND funky // - touch: always focus - else if ((this.stacks.groups.length === 1 || !(e instanceof MouseEvent)) && !DOM.isAncestor(((e as GestureEvent).initialTarget || e.target || e.srcElement) as HTMLElement, this.editorActionsToolbar.getContainer().getHTMLElement())) { + else if ((this.stacks.groups.length === 1 || !(e instanceof MouseEvent)) && !DOM.isAncestor(((e as GestureEvent).initialTarget || e.target || e.srcElement) as HTMLElement, this.editorActionsToolbar.getContainer())) { this.editorGroupService.focusGroup(group); } } diff --git a/src/vs/workbench/browser/parts/editor/rangeDecorations.ts b/src/vs/workbench/browser/parts/editor/rangeDecorations.ts index 187c62b560..d68731ef3c 100644 --- a/src/vs/workbench/browser/parts/editor/rangeDecorations.ts +++ b/src/vs/workbench/browser/parts/editor/rangeDecorations.ts @@ -5,7 +5,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IRange } from 'vs/editor/common/core/range'; import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; @@ -25,10 +25,10 @@ export class RangeHighlightDecorations implements IDisposable { private editor: ICodeEditor = null; private editorDisposables: IDisposable[] = []; - private _onHighlightRemoved: Emitter<void> = new Emitter<void>(); + private readonly _onHighlightRemoved: Emitter<void> = new Emitter<void>(); public readonly onHighlghtRemoved: Event<void> = this._onHighlightRemoved.event; - constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService) { + constructor(@IWorkbenchEditorService private editorService: IWorkbenchEditorService) { } public removeHighlightRange() { diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts index 63f692f934..43d4b3b7df 100644 --- a/src/vs/workbench/browser/parts/editor/resourceViewer.ts +++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts @@ -6,12 +6,12 @@ 'use strict'; import 'vs/css!./media/resourceviewer'; -import nls = require('vs/nls'); -import mimes = require('vs/base/common/mime'); +import * as nls from 'vs/nls'; +import * as mimes from 'vs/base/common/mime'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import { Builder, $, Dimension } from 'vs/base/browser/builder'; -import DOM = require('vs/base/browser/dom'); +import * as paths from 'vs/base/common/paths'; +import { Builder, $ } from 'vs/base/browser/builder'; +import * as DOM from 'vs/base/browser/dom'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { LRUCache } from 'vs/base/common/map'; import { Schemas } from 'vs/base/common/network'; @@ -19,7 +19,6 @@ import { clamp } from 'vs/base/common/numbers'; import { Themable } from 'vs/workbench/common/theme'; import { IStatusbarItem, StatusbarItemDescriptor, IStatusbarRegistry, Extensions, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { } from 'vs/platform/workspace/common/workspace'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -119,7 +118,7 @@ class BinarySize { } export interface ResourceViewerContext { - layout(dimension: Dimension): void; + layout(dimension: DOM.Dimension): void; } /** @@ -127,26 +126,42 @@ export interface ResourceViewerContext { * progress of the binary resource. */ export class ResourceViewer { + + private static readonly MAX_OPEN_INTERNAL_SIZE = BinarySize.MB * 200; // max size until we offer an action to open internally + public static show( descriptor: IResourceDescriptor, - container: Builder, + container: HTMLElement, scrollbar: DomScrollableElement, - openExternal: (uri: URI) => void, + openInternalClb: (uri: URI) => void, + openExternalClb: (uri: URI) => void, metadataClb: (meta: string) => void - ): ResourceViewerContext { + ): ResourceViewerContext | null { + // Ensure CSS class $(container).setClass('monaco-resource-viewer'); + // Images if (ResourceViewer.isImageResource(descriptor)) { - return ImageView.create(container, descriptor, scrollbar, openExternal, metadataClb); + return ImageView.create(container, descriptor, scrollbar, openExternalClb, metadataClb); + } + + // Large Files + if (descriptor.size > ResourceViewer.MAX_OPEN_INTERNAL_SIZE) { + FileTooLargeFileView.create(container, descriptor, scrollbar, metadataClb); + } + + // Seemingly Binary Files + else { + FileSeemsBinaryFileView.create(container, descriptor, scrollbar, openInternalClb, metadataClb); } - GenericBinaryFileView.create(container, metadataClb, descriptor, scrollbar); return null; } private static isImageResource(descriptor: IResourceDescriptor) { const mime = ResourceViewer.getMime(descriptor); + return mime.indexOf('image/') >= 0; } @@ -158,6 +173,7 @@ export class ResourceViewer { mime = mapExtToMediaMimes[ext.toLowerCase()]; } } + return mime || mimes.MIME_BINARY; } } @@ -167,17 +183,18 @@ class ImageView { private static readonly BASE64_MARKER = 'base64,'; public static create( - container: Builder, + container: HTMLElement, descriptor: IResourceDescriptor, scrollbar: DomScrollableElement, - openExternal: (uri: URI) => void, + openExternalClb: (uri: URI) => void, metadataClb: (meta: string) => void ): ResourceViewerContext | null { if (ImageView.shouldShowImageInline(descriptor)) { return InlineImageView.create(container, descriptor, scrollbar, metadataClb); } - LargeImageView.create(container, descriptor, openExternal); + LargeImageView.create(container, descriptor, openExternalClb); + return null; } @@ -203,43 +220,81 @@ class ImageView { class LargeImageView { public static create( - container: Builder, + container: HTMLElement, descriptor: IResourceDescriptor, - openExternal: (uri: URI) => void + openExternalClb: (uri: URI) => void ) { + const size = BinarySize.formatSize(descriptor.size); + const imageContainer = $(container) .empty() .p({ - text: nls.localize('largeImageError', "The file size of the image is too large (>1MB) to display in the editor. ") + text: nls.localize('largeImageError', "The image is not displayed in the editor because it is too large ({0}).", size) }); if (descriptor.resource.scheme !== Schemas.data) { imageContainer.append($('a', { role: 'button', - class: 'open-external', + class: 'embedded-link', text: nls.localize('resourceOpenExternalButton', "Open image using external program?") }).on(DOM.EventType.CLICK, (e) => { - openExternal(descriptor.resource); + openExternalClb(descriptor.resource); })); } } } -class GenericBinaryFileView { +class FileTooLargeFileView { public static create( - container: Builder, - metadataClb: (meta: string) => void, + container: HTMLElement, descriptor: IResourceDescriptor, - scrollbar: DomScrollableElement + scrollbar: DomScrollableElement, + metadataClb: (meta: string) => void ) { + const size = BinarySize.formatSize(descriptor.size); + $(container) .empty() .span({ - text: nls.localize('nativeBinaryError', "The file will not be displayed in the editor because it is either binary, very large or uses an unsupported text encoding.") + text: nls.localize('nativeFileTooLargeError', "The file is not displayed in the editor because it is too large ({0}).", size) }); + + if (metadataClb) { + metadataClb(size); + } + + scrollbar.scanDomNode(); + } +} + +class FileSeemsBinaryFileView { + public static create( + container: HTMLElement, + descriptor: IResourceDescriptor, + scrollbar: DomScrollableElement, + openInternalClb: (uri: URI) => void, + metadataClb: (meta: string) => void + ) { + const binaryContainer = $(container) + .empty() + .p({ + text: nls.localize('nativeBinaryError', "The file is not displayed in the editor because it is either binary or uses an unsupported text encoding.") + }); + + if (descriptor.resource.scheme !== Schemas.data) { + binaryContainer.append($('a', { + role: 'button', + class: 'embedded-link', + text: nls.localize('openAsText', "Do you want to open it anyway?") + }).on(DOM.EventType.CLICK, (e) => { + openInternalClb(descriptor.resource); + })); + } + if (metadataClb) { metadataClb(BinarySize.formatSize(descriptor.size)); } + scrollbar.scanDomNode(); } } @@ -266,7 +321,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem { private onEditorsChanged(): void { this.hide(); - this.onSelectScale = undefined; + this.onSelectScale = void 0; } public show(scale: Scale, onSelectScale: (scale: number) => void) { @@ -295,6 +350,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem { .getHTMLElement(); this.statusBarItem.style.display = 'none'; } + return this; } @@ -306,10 +362,11 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem { private get zoomActions(): Action[] { const scales: Scale[] = [10, 5, 2, 1, 0.5, 0.2, 'fit']; return scales.map(scale => - new Action('zoom.' + scale, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => { + new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), void 0, void 0, () => { if (this.onSelectScale) { this.onSelectScale(scale); } + return null; })); } @@ -376,13 +433,13 @@ class InlineImageView { private static readonly imageStateCache = new LRUCache<string, ImageState>(100); public static create( - container: Builder, + container: HTMLElement, descriptor: IResourceDescriptor, scrollbar: DomScrollableElement, metadataClb: (meta: string) => void ) { const context = { - layout(dimension: Dimension) { } + layout(dimension: DOM.Dimension) { } }; const cacheKey = descriptor.resource.toString(); @@ -585,6 +642,4 @@ class InlineImageView { return cached.src; } -} - - +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index 05f0cb493d..323766e752 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -5,14 +5,11 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as DOM from 'vs/base/browser/dom'; -import { Dimension, Builder } from 'vs/base/browser/builder'; - import { Registry } from 'vs/platform/registry/common/platform'; import { EditorInput, EditorOptions, SideBySideEditorInput } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { IEditorControl, Position, IEditor } from 'vs/platform/editor/common/editor'; import { VSash } from 'vs/base/browser/ui/sash/sash'; - import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -23,7 +20,7 @@ export class SideBySideEditor extends BaseEditor { public static readonly ID: string = 'workbench.editor.sidebysideEditor'; - private dimension: Dimension; + private dimension: DOM.Dimension; protected masterEditor: BaseEditor; private masterEditorContainer: HTMLElement; @@ -41,10 +38,9 @@ export class SideBySideEditor extends BaseEditor { super(SideBySideEditor.ID, telemetryService, themeService); } - protected createEditor(parent: Builder): void { - const parentElement = parent.getHTMLElement(); - DOM.addClass(parentElement, 'side-by-side-editor'); - this.createSash(parentElement); + protected createEditor(parent: HTMLElement): void { + DOM.addClass(parent, 'side-by-side-editor'); + this.createSash(parent); } public setInput(newInput: SideBySideEditorInput, options?: EditorOptions): TPromise<void> { @@ -90,7 +86,7 @@ export class SideBySideEditor extends BaseEditor { } } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this.dimension = dimension; this.sash.setDimenesion(this.dimension); } @@ -110,6 +106,10 @@ export class SideBySideEditor extends BaseEditor { return this.detailsEditor; } + public supportsCenteredLayout(): boolean { + return false; + } + private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options?: EditorOptions): void { if (!newInput.matches(oldInput)) { if (oldInput) { @@ -137,7 +137,7 @@ export class SideBySideEditor extends BaseEditor { const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput); const editor = descriptor.instantiate(this.instantiationService); - editor.create(new Builder(container)); + editor.create(container); editor.setVisible(this.isVisible(), this.position); return editor; @@ -151,7 +151,7 @@ export class SideBySideEditor extends BaseEditor { } private createEditorContainers(): void { - const parentElement = this.getContainer().getHTMLElement(); + const parentElement = this.getContainer(); this.detailsEditorContainer = DOM.append(parentElement, DOM.$('.details-editor-container')); this.detailsEditorContainer.style.position = 'absolute'; this.masterEditorContainer = DOM.append(parentElement, DOM.$('.master-editor-container')); @@ -188,12 +188,12 @@ export class SideBySideEditor extends BaseEditor { this.masterEditorContainer.style.height = `${this.dimension.height}px`; this.masterEditorContainer.style.left = `${splitPoint}px`; - this.detailsEditor.layout(new Dimension(detailsEditorWidth, this.dimension.height)); - this.masterEditor.layout(new Dimension(masterEditorWidth, this.dimension.height)); + this.detailsEditor.layout(new DOM.Dimension(detailsEditorWidth, this.dimension.height)); + this.masterEditor.layout(new DOM.Dimension(masterEditorWidth, this.dimension.height)); } private disposeEditors(): void { - const parentContainer = this.getContainer().getHTMLElement(); + const parentContainer = this.getContainer(); if (this.detailsEditor) { this.detailsEditor.dispose(); this.detailsEditor = null; @@ -216,4 +216,4 @@ export class SideBySideEditor extends BaseEditor { this.disposeEditors(); super.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 2a5ecc7ff9..8bdead0c70 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -6,10 +6,10 @@ 'use strict'; import 'vs/css!./media/tabstitle'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import errors = require('vs/base/common/errors'); -import DOM = require('vs/base/browser/dom'); +import * as errors from 'vs/base/common/errors'; +import * as DOM from 'vs/base/browser/dom'; import { isMacintosh } from 'vs/base/common/platform'; import { shorten } from 'vs/base/common/labels'; import { ActionRunner, IAction } from 'vs/base/common/actions'; @@ -38,8 +38,6 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_BACKGROUND, WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { activeContrastBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry'; -import { Dimension } from 'vs/base/browser/builder'; -import { scheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; import { ResourcesDropHandler, fillResourceDataTransfers, LocalSelectionTransfer, DraggedEditorIdentifier } from 'vs/workbench/browser/dnd'; import { Color } from 'vs/base/common/color'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -72,7 +70,7 @@ export class TabsTitleControl extends TitleControl { private scrollbar: ScrollableElement; private tabDisposeables: IDisposable[]; private blockRevealActiveTab: boolean; - private dimension: Dimension; + private dimension: DOM.Dimension; private layoutScheduled: IDisposable; private transfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>(); @@ -576,7 +574,7 @@ export class TabsTitleControl extends TitleControl { this.tabDisposeables.push(actionRunner); const bar = new ActionBar(tabCloseContainer, { ariaLabel: nls.localize('araLabelTabActions', "Tab actions"), actionRunner }); - bar.push(this.closeEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeEditorAction) }); + bar.push(this.closeOneEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeOneEditorAction) }); // Eventing const disposable = this.hookTabListeners(tabContainer, index); @@ -586,7 +584,7 @@ export class TabsTitleControl extends TitleControl { return tabContainer; } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { if (!this.activeTab || !dimension) { return; } @@ -597,14 +595,14 @@ export class TabsTitleControl extends TitleControl { // that can result in the browser doing a full page layout to validate them. To buffer // this a little bit we try at least to schedule this work on the next animation frame. if (!this.layoutScheduled) { - this.layoutScheduled = scheduleAtNextAnimationFrame(() => { + this.layoutScheduled = DOM.scheduleAtNextAnimationFrame(() => { this.doLayout(this.dimension); this.layoutScheduled = void 0; }); } } - private doLayout(dimension: Dimension): void { + private doLayout(dimension: DOM.Dimension): void { const visibleContainerWidth = this.tabsContainer.offsetWidth; const totalContainerWidth = this.tabsContainer.scrollWidth; @@ -695,7 +693,7 @@ export class TabsTitleControl extends TitleControl { tab.blur(); if (e.button === 1 /* Middle Button*/ && !this.isTabActionBar((e.target || e.srcElement) as HTMLElement)) { - this.closeEditorAction.run({ groupId: this.context.id, editorIndex: index }).done(null, errors.onUnexpectedError); + this.closeOneEditorAction.run({ groupId: this.context.id, editorIndex: index }).done(null, errors.onUnexpectedError); } })); @@ -789,7 +787,7 @@ export class TabsTitleControl extends TitleControl { // Fixes https://github.com/Microsoft/vscode/issues/18733 DOM.addClass(tab, 'dragged'); - scheduleAtNextAnimationFrame(() => DOM.removeClass(tab, 'dragged')); + DOM.scheduleAtNextAnimationFrame(() => DOM.removeClass(tab, 'dragged')); })); // We need to keep track of DRAG_ENTER and DRAG_LEAVE events because a tab is not just a div without children, @@ -977,7 +975,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (tabHoverBackground) { collector.addRule(` .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title.active .tabs-container > .tab:hover { - background: ${tabHoverBackground} !important; + background-color: ${tabHoverBackground} !important; } `); } @@ -986,7 +984,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (tabUnfocusedHoverBackground) { collector.addRule(` .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title.inactive .tabs-container > .tab:hover { - background: ${tabUnfocusedHoverBackground} !important; + background-color: ${tabUnfocusedHoverBackground} !important; } `); } diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 3639de73fd..867b95886a 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -7,12 +7,11 @@ import 'vs/css!./media/textdiffeditor'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import objects = require('vs/base/common/objects'); -import { Builder } from 'vs/base/browser/builder'; +import * as nls from 'vs/nls'; +import * as objects from 'vs/base/common/objects'; import { Action, IAction } from 'vs/base/common/actions'; import { onUnexpectedError } from 'vs/base/common/errors'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -32,10 +31,13 @@ import { IWorkbenchEditorService, DelegatingWorkbenchEditorService } from 'vs/wo import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ScrollType } from 'vs/editor/common/editorCommon'; +import { ScrollType, IDiffEditorViewState, IDiffEditorModel } from 'vs/editor/common/editorCommon'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; +import URI from 'vs/base/common/uri'; +import { getCodeOrDiffEditor } from 'vs/editor/browser/services/codeEditorService'; +import { once } from 'vs/base/common/event'; /** * The text editor that leverages the diff text editor for the editing experience. @@ -45,10 +47,10 @@ export class TextDiffEditor extends BaseTextEditor { public static readonly ID = TEXT_DIFF_EDITOR_ID; private diffNavigator: DiffNavigator; + private diffNavigatorDisposables: IDisposable[]; private nextDiffAction: NavigateAction; private previousDiffAction: NavigateAction; private toggleIgnoreTrimWhitespaceAction: ToggleIgnoreTrimWhitespaceAction; - private _configurationListener: IDisposable; constructor( @ITelemetryService telemetryService: ITelemetryService, @@ -63,11 +65,12 @@ export class TextDiffEditor extends BaseTextEditor { ) { super(TextDiffEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorGroupService); - this._configurationListener = this._actualConfigurationService.onDidChangeConfiguration((e) => { + this.diffNavigatorDisposables = []; + this.toUnbind.push(this._actualConfigurationService.onDidChangeConfiguration((e) => { if (e.affectsConfiguration('diffEditor.ignoreTrimWhitespace')) { this.updateIgnoreTrimWhitespaceAction(); } - }); + })); } public getTitle(): string { @@ -78,7 +81,7 @@ export class TextDiffEditor extends BaseTextEditor { return nls.localize('textDiffEditor', "Text Diff Editor"); } - public createEditorControl(parent: Builder, configuration: IEditorOptions): IDiffEditor { + public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IDiffEditor { // Actions this.nextDiffAction = new NavigateAction(this, true); @@ -118,7 +121,7 @@ export class TextDiffEditor extends BaseTextEditor { // Create a special child of instantiator that will delegate all calls to openEditor() to the same diff editor if the input matches with the modified one const diffEditorInstantiator = this.instantiationService.createChild(new ServiceCollection([IWorkbenchEditorService, delegatingEditorService])); - return diffEditorInstantiator.createInstance(DiffEditorWidget, parent.getHTMLElement(), configuration); + return diffEditorInstantiator.createInstance(DiffEditorWidget, parent, configuration); } public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> { @@ -137,9 +140,10 @@ export class TextDiffEditor extends BaseTextEditor { } // Dispose previous diff navigator - if (this.diffNavigator) { - this.diffNavigator.dispose(); - } + this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables); + + // Remember view settings if input changes + this.saveTextDiffEditorViewState(this.input); // Set input and resolve return super.setInput(input, options).then(() => { @@ -155,27 +159,32 @@ export class TextDiffEditor extends BaseTextEditor { return null; } - // Editor + // Set Editor Model const diffEditor = <IDiffEditor>this.getControl(); diffEditor.setModel((<TextDiffEditorModel>resolvedModel).textDiffEditorModel); - // Handle TextOptions - let alwaysRevealFirst = true; + // Apply Options from TextOptions + let optionsGotApplied = false; if (options && types.isFunction((<TextEditorOptions>options).apply)) { - const hadOptions = (<TextEditorOptions>options).apply(<IDiffEditor>diffEditor, ScrollType.Immediate); - if (hadOptions) { - alwaysRevealFirst = false; // Do not reveal if we are instructed to open specific line/col - } + optionsGotApplied = (<TextEditorOptions>options).apply(<IDiffEditor>diffEditor, ScrollType.Immediate); + } + + // Otherwise restore View State + let hasPreviousViewState = false; + if (!optionsGotApplied) { + hasPreviousViewState = this.restoreTextDiffEditorViewState(input); } - // Listen on diff updated changes to reveal the first change this.diffNavigator = new DiffNavigator(diffEditor, { - alwaysRevealFirst + alwaysRevealFirst: !optionsGotApplied && !hasPreviousViewState // only reveal first change if we had no options or viewstate }); - this.diffNavigator.onDidUpdate(() => { + this.diffNavigatorDisposables.push(this.diffNavigator); + + this.diffNavigatorDisposables.push(this.diffNavigator.onDidUpdate(() => { this.nextDiffAction.updateEnablement(); this.previousDiffAction.updateEnablement(); - }); + })); + this.updateIgnoreTrimWhitespaceAction(); }, error => { @@ -190,6 +199,26 @@ export class TextDiffEditor extends BaseTextEditor { }); } + public supportsCenteredLayout(): boolean { + return false; + } + + private restoreTextDiffEditorViewState(input: EditorInput): boolean { + if (input instanceof DiffEditorInput) { + const resource = this.toDiffEditorViewStateResource(input); + if (resource) { + const viewState = this.loadTextEditorViewState(resource); + if (viewState) { + this.getControl().restoreViewState(viewState); + + return true; + } + } + } + + return false; + } + private updateIgnoreTrimWhitespaceAction(): void { const ignoreTrimWhitespace = this.configurationService.getValue<boolean>(this.getResource(), 'diffEditor.ignoreTrimWhitespace'); if (this.toggleIgnoreTrimWhitespaceAction) { @@ -278,9 +307,10 @@ export class TextDiffEditor extends BaseTextEditor { public clearInput(): void { // Dispose previous diff navigator - if (this.diffNavigator) { - this.diffNavigator.dispose(); - } + this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables); + + // Keep editor view state in settings to restore when coming back + this.saveTextDiffEditorViewState(this.input); // Clear Model this.getControl().setModel(null); @@ -305,14 +335,85 @@ export class TextDiffEditor extends BaseTextEditor { return super.getControl() as IDiffEditor; } - public dispose(): void { + protected loadTextEditorViewState(resource: URI): IDiffEditorViewState { + return super.loadTextEditorViewState(resource) as IDiffEditorViewState; // overridden for text diff editor support + } - // Dispose previous diff navigator - if (this.diffNavigator) { - this.diffNavigator.dispose(); + private saveTextDiffEditorViewState(input: EditorInput): void { + if (!(input instanceof DiffEditorInput)) { + return; // only supported for diff editor inputs } - this._configurationListener.dispose(); + const resource = this.toDiffEditorViewStateResource(input); + if (!resource) { + return; // unable to retrieve input resource + } + + // Clear view state if input is disposed + if (input.isDisposed()) { + super.clearTextEditorViewState([resource]); + } + + // Otherwise save it + else { + super.saveTextEditorViewState(resource); + + // Make sure to clean up when the input gets disposed + once(input.onDispose)(() => { + super.clearTextEditorViewState([resource]); + }); + } + } + + protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState { + return this.retrieveTextDiffEditorViewState(resource); // overridden for text diff editor support + } + + private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState { + const editor = getCodeOrDiffEditor(this).diffEditor; + if (!editor) { + return null; // not supported for non-diff editors + } + + const model = editor.getModel(); + if (!model || !model.modified || !model.original) { + return null; // view state always needs a model + } + + const modelUri = this.toDiffEditorViewStateResource(model); + if (!modelUri) { + return null; // model URI is needed to make sure we save the view state correctly + } + + if (modelUri.toString() !== resource.toString()) { + return null; // prevent saving view state for a model that is not the expected one + } + + return editor.saveViewState(); + } + + private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI { + let original: URI; + let modified: URI; + + if (modelOrInput instanceof DiffEditorInput) { + original = modelOrInput.originalInput.getResource(); + modified = modelOrInput.modifiedInput.getResource(); + } else { + original = modelOrInput.original.uri; + modified = modelOrInput.modified.uri; + } + + if (!original || !modified) { + return null; + } + + // create a URI that is the Base64 concatenation of original + modified resource + return URI.from({ scheme: 'diff', path: `${btoa(original.toString())}${btoa(modified.toString())}` }); + } + + public dispose(): void { + this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables); super.dispose(); } @@ -372,4 +473,4 @@ class ToggleIgnoreTrimWhitespaceAction extends Action { this._configurationService.updateValue(`diffEditor.ignoreTrimWhitespace`, !this._isChecked); return null; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index d15f1b2940..2711ea79ed 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -5,16 +5,15 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; -import { Dimension, Builder } from 'vs/base/browser/builder'; -import objects = require('vs/base/common/objects'); -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); -import DOM = require('vs/base/browser/dom'); +import * as objects from 'vs/base/common/objects'; +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; +import * as DOM from 'vs/base/browser/dom'; import { CodeEditor } from 'vs/editor/browser/codeEditor'; -import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, EditorViewStateMemento } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { IEditorViewState, IEditor } from 'vs/editor/common/editorCommon'; import { Position } from 'vs/platform/editor/common/editor'; @@ -43,15 +42,16 @@ export interface IEditorConfiguration { */ export abstract class BaseTextEditor extends BaseEditor { private editorControl: IEditor; - private _editorContainer: Builder; + private _editorContainer: HTMLElement; private hasPendingConfigurationChange: boolean; private lastAppliedEditorOptions: IEditorOptions; + private editorViewStateMemento: EditorViewStateMemento<IEditorViewState>; constructor( id: string, @ITelemetryService telemetryService: ITelemetryService, @IInstantiationService private readonly _instantiationService: IInstantiationService, - @IStorageService private storageService: IStorageService, + @IStorageService storageService: IStorageService, @ITextResourceConfigurationService private readonly _configurationService: ITextResourceConfigurationService, @IThemeService protected themeService: IThemeService, @ITextFileService private readonly _textFileService: ITextFileService, @@ -59,6 +59,8 @@ export abstract class BaseTextEditor extends BaseEditor { ) { super(id, telemetryService, themeService); + this.editorViewStateMemento = new EditorViewStateMemento<IEditorViewState>(this.getMemento(storageService, Scope.WORKSPACE), TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100); + this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getValue<IEditorConfiguration>(this.getResource())))); } @@ -123,7 +125,7 @@ export abstract class BaseTextEditor extends BaseEditor { return overrides; } - protected createEditor(parent: Builder): void { + protected createEditor(parent: HTMLElement): void { // Editor for Text this._editorContainer = parent; @@ -177,10 +179,10 @@ export abstract class BaseTextEditor extends BaseEditor { * * The passed in configuration object should be passed to the editor control when creating it. */ - protected createEditorControl(parent: Builder, configuration: IEditorOptions): IEditor { + protected createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IEditor { // Use a getter for the instantiation service since some subclasses might use scoped instantiation services - return this.instantiationService.createInstance(CodeEditor, parent.getHTMLElement(), configuration); + return this.instantiationService.createInstance(CodeEditor, parent, configuration); } public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> { @@ -189,7 +191,7 @@ export abstract class BaseTextEditor extends BaseEditor { // Update editor options after having set the input. We do this because there can be // editor input specific options (e.g. an ARIA label depending on the input showing) this.updateEditorConfiguration(); - this._editorContainer.getHTMLElement().setAttribute('aria-label', this.computeAriaLabel()); + this._editorContainer.setAttribute('aria-label', this.computeAriaLabel()); }); } @@ -219,7 +221,7 @@ export abstract class BaseTextEditor extends BaseEditor { this.editorControl.focus(); } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { // Pass on to Editor this.editorControl.layout(dimension); @@ -233,69 +235,51 @@ export abstract class BaseTextEditor extends BaseEditor { * Saves the text editor view state for the given resource. */ protected saveTextEditorViewState(resource: URI): void { + const editorViewState = this.retrieveTextEditorViewState(resource); + if (!editorViewState) { + return; + } + + this.editorViewStateMemento.saveState(resource, this.position, editorViewState); + } + + protected retrieveTextEditorViewState(resource: URI): IEditorViewState { const editor = getCodeOrDiffEditor(this).codeEditor; if (!editor) { - return; // not supported for diff editors + return null; // not supported for diff editors } const model = editor.getModel(); if (!model) { - return; // view state always needs a model + return null; // view state always needs a model } const modelUri = model.uri; if (!modelUri) { - return; // model URI is needed to make sure we save the view state correctly + return null; // model URI is needed to make sure we save the view state correctly } if (modelUri.toString() !== resource.toString()) { - return; // prevent saving view state for a model that is not the expected one + return null; // prevent saving view state for a model that is not the expected one } - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - - let textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY]; - if (!textEditorViewStateMemento) { - textEditorViewStateMemento = Object.create(null); - memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY] = textEditorViewStateMemento; - } - - let lastKnownViewState = textEditorViewStateMemento[resource.toString()]; - if (!lastKnownViewState) { - lastKnownViewState = Object.create(null); - textEditorViewStateMemento[resource.toString()] = lastKnownViewState; - } - - if (typeof this.position === 'number') { - lastKnownViewState[this.position] = editor.saveViewState(); - } + return editor.saveViewState(); } /** * Clears the text editor view state for the given resources. */ protected clearTextEditorViewState(resources: URI[]): void { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - const textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY]; - if (textEditorViewStateMemento) { - resources.forEach(resource => delete textEditorViewStateMemento[resource.toString()]); - } + resources.forEach(resource => { + this.editorViewStateMemento.clearState(resource); + }); } /** * Loads the text editor view state for the given resource and returns it. */ protected loadTextEditorViewState(resource: URI): IEditorViewState { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - const textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY]; - if (textEditorViewStateMemento) { - const viewState = textEditorViewStateMemento[resource.toString()]; - if (viewState) { - return viewState[this.position]; - } - } - - return null; + return this.editorViewStateMemento.loadState(resource, this.position); } private updateEditorConfiguration(configuration = this.configurationService.getValue<IEditorConfiguration>(this.getResource())): void { @@ -337,6 +321,14 @@ export abstract class BaseTextEditor extends BaseEditor { protected abstract getAriaLabel(): string; + protected saveMemento(): void { + + // ensure to first save our view state memento + this.editorViewStateMemento.save(); + + super.saveMemento(); + } + public dispose(): void { this.lastAppliedEditorOptions = void 0; this.editorControl.dispose(); diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index f8354629ff..86d2522f85 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -5,8 +5,8 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import types = require('vs/base/common/types'); +import * as nls from 'vs/nls'; +import * as types from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { TextEditorOptions, EditorModel, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; @@ -67,7 +67,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { } // Remember view settings if input changes - this.saveTextEditorViewStateForInput(this.input); + this.saveTextResourceEditorViewState(this.input); // Set input and resolve return super.setInput(input, options).then(() => { @@ -97,7 +97,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { // Otherwise restore View State if (!optionsGotApplied) { - this.restoreViewState(input); + this.restoreTextResourceEditorViewState(input); } return void 0; @@ -105,7 +105,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { }); } - protected restoreViewState(input: EditorInput) { + private restoreTextResourceEditorViewState(input: EditorInput) { if (input instanceof UntitledEditorInput || input instanceof ResourceEditorInput) { const viewState = this.loadTextEditorViewState(input.getResource()); if (viewState) { @@ -153,7 +153,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { public clearInput(): void { // Keep editor view state in settings to restore when coming back - this.saveTextEditorViewStateForInput(this.input); + this.saveTextResourceEditorViewState(this.input); // Clear Model this.getControl().setModel(null); @@ -165,14 +165,14 @@ export class AbstractTextResourceEditor extends BaseTextEditor { // Save View State (only for untitled) if (this.input instanceof UntitledEditorInput) { - this.saveTextEditorViewStateForInput(this.input); + this.saveTextResourceEditorViewState(this.input); } // Call Super super.shutdown(); } - protected saveTextEditorViewStateForInput(input: EditorInput): void { + private saveTextResourceEditorViewState(input: EditorInput): void { if (!(input instanceof UntitledEditorInput) && !(input instanceof ResourceEditorInput)) { return; // only enabled for untitled and resource inputs } diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 85f2c14681..0581da865a 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -6,15 +6,14 @@ 'use strict'; import 'vs/css!./media/titlecontrol'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { prepareActions } from 'vs/workbench/browser/actions'; import { IAction, Action, IRunEvent } from 'vs/base/common/actions'; -import errors = require('vs/base/common/errors'); -import DOM = require('vs/base/browser/dom'); +import * as errors from 'vs/base/common/errors'; import { TPromise } from 'vs/base/common/winjs.base'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { RunOnceScheduler } from 'vs/base/common/async'; -import arrays = require('vs/base/common/arrays'); +import * as arrays from 'vs/base/common/arrays'; import { IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IStacksModelChangeEvent, toResource, IEditorCommandsContext } from 'vs/workbench/common/editor'; import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; @@ -28,7 +27,7 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { SplitEditorAction, CloseEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; +import { SplitEditorAction, CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createActionItem, fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; import { IMenuService, MenuId, IMenu, ExecuteCommandAction } from 'vs/platform/actions/common/actions'; @@ -36,8 +35,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Themable } from 'vs/workbench/common/theme'; import { isDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import { Dimension } from 'vs/base/browser/builder'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension, findParentWithClass } from 'vs/base/browser/dom'; export interface IToolbarActions { primary: IAction[]; @@ -65,7 +64,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl protected dragged: boolean; - protected closeEditorAction: CloseEditorAction; + protected closeOneEditorAction: CloseOneEditorAction; protected splitEditorAction: SplitEditorAction; private parent: HTMLElement; @@ -75,7 +74,8 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl protected editorActionsToolbar: ToolBar; private mapActionsToEditors: { [editorId: string]: IToolbarActions; }; - private scheduler: RunOnceScheduler; + private titleAreaUpdateScheduler: RunOnceScheduler; + private titleAreaToolbarUpdateScheduler: RunOnceScheduler; private refreshScheduled: boolean; private resourceContext: ResourceContextKey; @@ -101,8 +101,11 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl this.stacks = editorGroupService.getStacksModel(); this.mapActionsToEditors = Object.create(null); - this.scheduler = new RunOnceScheduler(() => this.onSchedule(), 0); - this.toUnbind.push(this.scheduler); + this.titleAreaUpdateScheduler = new RunOnceScheduler(() => this.onSchedule(), 0); + this.toUnbind.push(this.titleAreaUpdateScheduler); + + this.titleAreaToolbarUpdateScheduler = new RunOnceScheduler(() => this.updateEditorActionsToolbar(), 0); + this.toUnbind.push(this.titleAreaToolbarUpdateScheduler); this.resourceContext = instantiationService.createInstance(ResourceContextKey); @@ -166,22 +169,26 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl public update(instant?: boolean): void { if (instant) { - this.scheduler.cancel(); + this.titleAreaUpdateScheduler.cancel(); this.onSchedule(); } else { - this.scheduler.schedule(); + this.titleAreaUpdateScheduler.schedule(); } + + this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too } public refresh(instant?: boolean) { this.refreshScheduled = true; if (instant) { - this.scheduler.cancel(); + this.titleAreaUpdateScheduler.cancel(); this.onSchedule(); } else { - this.scheduler.schedule(); + this.titleAreaUpdateScheduler.schedule(); } + + this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too } public create(parent: HTMLElement): void { @@ -203,11 +210,11 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl } public allowDragging(element: HTMLElement): boolean { - return !DOM.findParentWithClass(element, 'monaco-action-bar', 'one-editor-silo'); + return !findParentWithClass(element, 'monaco-action-bar', 'one-editor-silo'); } protected initActions(services: IInstantiationService): void { - this.closeEditorAction = services.createInstance(CloseEditorAction, CloseEditorAction.ID, nls.localize('close', "Close")); + this.closeOneEditorAction = services.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL); this.splitEditorAction = services.createInstance(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL); } @@ -296,7 +303,14 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl const codeEditor = isCodeEditor(widget) && widget || isDiffEditor(widget) && widget.getModifiedEditor(); const scopedContextKeyService = codeEditor && codeEditor.invokeWithinContext(accessor => accessor.get(IContextKeyService)) || this.contextKeyService; const titleBarMenu = this.menuService.createMenu(MenuId.EditorTitle, scopedContextKeyService); - this.disposeOnEditorActions.push(titleBarMenu, titleBarMenu.onDidChange(_ => this.update())); + this.disposeOnEditorActions.push(titleBarMenu, titleBarMenu.onDidChange(_ => { + // schedule the update for the title area toolbar only if no other + // update to the title area is scheduled which will always also + // update the toolbar + if (!this.titleAreaUpdateScheduler.isScheduled()) { + this.titleAreaToolbarUpdateScheduler.schedule(); + } + })); fillInActions(titleBarMenu, { arg: this.resourceContext.get(), shouldForwardArgs: true }, { primary, secondary }, this.contextMenuService); } @@ -334,11 +348,10 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl const primaryEditorActionIds = primaryEditorActions.map(a => a.id); if (!tabOptions.showTabs) { - primaryEditorActionIds.push(this.closeEditorAction.id); // always show "Close" when tabs are disabled + primaryEditorActionIds.push(this.closeOneEditorAction.id); // always show "Close" when tabs are disabled } const secondaryEditorActionIds = secondaryEditorActions.map(a => a.id); - if ( !arrays.equals(primaryEditorActionIds, this.currentPrimaryEditorActionIds) || !arrays.equals(secondaryEditorActionIds, this.currentSecondaryEditorActionIds) || @@ -348,7 +361,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl this.editorActionsToolbar.setActions(primaryEditorActions, secondaryEditorActions)(); if (!tabOptions.showTabs) { - this.editorActionsToolbar.addPrimaryAction(this.closeEditorAction)(); + this.editorActionsToolbar.addPrimaryAction(this.closeOneEditorAction)(); } this.currentPrimaryEditorActionIds = primaryEditorActionIds; @@ -416,7 +429,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl // Actions [ this.splitEditorAction, - this.closeEditorAction + this.closeOneEditorAction ].forEach((action) => { action.dispose(); }); diff --git a/src/vs/workbench/browser/parts/editor/webviewEditor.ts b/src/vs/workbench/browser/parts/editor/webviewEditor.ts deleted file mode 100644 index 8fc5f1a711..0000000000 --- a/src/vs/workbench/browser/parts/editor/webviewEditor.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import URI from 'vs/base/common/uri'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { Scope } from 'vs/workbench/common/memento'; - -export interface HtmlPreviewEditorViewState { - scrollYPercentage: number; -} - - -/** - * This class is only intended to be subclassed and not instantiated. - */ -export abstract class BaseWebviewEditor extends BaseEditor { - - constructor( - id: string, - telemetryService: ITelemetryService, - themeService: IThemeService, - private storageService: IStorageService - ) { - super(id, telemetryService, themeService); - } - - private get viewStateStorageKey(): string { - return this.getId() + '.editorViewState'; - } - - protected saveViewState(resource: URI | string, editorViewState: HtmlPreviewEditorViewState): void { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - let editorViewStateMemento: { [key: string]: { [position: number]: HtmlPreviewEditorViewState } } = memento[this.viewStateStorageKey]; - if (!editorViewStateMemento) { - editorViewStateMemento = Object.create(null); - memento[this.viewStateStorageKey] = editorViewStateMemento; - } - - let fileViewState = editorViewStateMemento[resource.toString()]; - if (!fileViewState) { - fileViewState = Object.create(null); - editorViewStateMemento[resource.toString()] = fileViewState; - } - - if (typeof this.position === 'number') { - fileViewState[this.position] = editorViewState; - } - } - - protected loadViewState(resource: URI | string): HtmlPreviewEditorViewState | null { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - const editorViewStateMemento: { [key: string]: { [position: number]: HtmlPreviewEditorViewState } } = memento[this.viewStateStorageKey]; - if (editorViewStateMemento) { - const fileViewState = editorViewStateMemento[resource.toString()]; - if (fileViewState) { - return fileViewState[this.position]; - } - } - return null; - } -} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsActions.css b/src/vs/workbench/browser/parts/notifications/media/notificationsActions.css index 5fa878b63c..2a0fe21884 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsActions.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsActions.css @@ -24,21 +24,21 @@ } .vs .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .expand-notification-action { - background-image: url('down.svg'); + background-image: url('up.svg'); } .vs-dark .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .expand-notification-action, .hc-black .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .expand-notification-action { - background-image: url('down-inverse.svg'); + background-image: url('up-inverse.svg'); } .vs .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .collapse-notification-action { - background-image: url('up.svg'); + background-image: url('down.svg'); } .vs-dark .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .collapse-notification-action, .hc-black .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .collapse-notification-action { - background-image: url('up-inverse.svg'); + background-image: url('down-inverse.svg'); } .vs .monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-toolbar-container .configure-notification-action { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index ad35b912f0..e958e0a284 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -10,14 +10,13 @@ import 'vs/css!./media/notificationsActions'; import { Themable, NOTIFICATIONS_BORDER, NOTIFICATIONS_CENTER_HEADER_FOREGROUND, NOTIFICATIONS_CENTER_HEADER_BACKGROUND, NOTIFICATIONS_CENTER_BORDER } from 'vs/workbench/common/theme'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { INotificationsModel, INotificationChangeEvent, NotificationChangeType } from 'vs/workbench/common/notifications'; -import { Dimension } from 'vs/base/browser/builder'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { NotificationsCenterVisibleContext } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { addClass, removeClass, isAncestor } from 'vs/base/browser/dom'; +import { addClass, removeClass, isAncestor, Dimension } from 'vs/base/browser/dom'; import { widgetShadow } from 'vs/platform/theme/common/colorRegistry'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { localize } from 'vs/nls'; @@ -32,10 +31,11 @@ export class NotificationsCenter extends Themable { private notificationsCenterContainer: HTMLElement; private notificationsCenterHeader: HTMLElement; + private notificationsCenterTitle: HTMLSpanElement; private notificationsList: NotificationsList; private _isVisible: boolean; private workbenchDimensions: Dimension; - private _onDidChangeVisibility: Emitter<void>; + private readonly _onDidChangeVisibility: Emitter<void>; private notificationsCenterVisibleContextKey: IContextKey<boolean>; constructor( @@ -71,10 +71,6 @@ export class NotificationsCenter extends Themable { } public show(): void { - if (this.model.notifications.length === 0) { - return; // currently not supporting to show empty (https://github.com/Microsoft/vscode/issues/44509) - } - if (this._isVisible) { this.notificationsList.show(true /* focus */); @@ -86,6 +82,9 @@ export class NotificationsCenter extends Themable { this.create(); } + // Title + this.updateTitle(); + // Make visible this._isVisible = true; addClass(this.notificationsCenterContainer, 'visible'); @@ -110,6 +109,14 @@ export class NotificationsCenter extends Themable { this._onDidChangeVisibility.fire(); } + private updateTitle(): void { + if (this.model.notifications.length === 0) { + this.notificationsCenterTitle.innerText = localize('notificationsEmpty', "No new notifications"); + } else { + this.notificationsCenterTitle.innerText = localize('notifications', "Notifications"); + } + } + private create(): void { // Container @@ -122,10 +129,9 @@ export class NotificationsCenter extends Themable { this.notificationsCenterContainer.appendChild(this.notificationsCenterHeader); // Header Title - const title = document.createElement('span'); - addClass(title, 'notifications-center-header-title'); - title.innerText = localize('notifications', "Notifications"); - this.notificationsCenterHeader.appendChild(title); + this.notificationsCenterTitle = document.createElement('span'); + addClass(this.notificationsCenterTitle, 'notifications-center-header-title'); + this.notificationsCenterHeader.appendChild(this.notificationsCenterTitle); // Header Toolbar const toolbarContainer = document.createElement('div'); @@ -184,6 +190,9 @@ export class NotificationsCenter extends Themable { break; } + // Update title + this.updateTitle(); + // Hide if no more notifications to show if (this.model.notifications.length === 0) { this.hide(); @@ -280,7 +289,7 @@ export class NotificationsCenter extends Themable { // Hide notifications center first this.hide(); - // Dispose all + // Close all while (this.model.notifications.length) { this.model.notifications[0].close(); } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index 6ad56eebc9..48558806a9 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -74,7 +74,7 @@ export class NotificationsList extends Themable { const renderer = this.instantiationService.createInstance(NotificationRenderer, actionRunner); // List - this.list = this.instantiationService.createInstance( + this.list = <WorkbenchList<INotificationViewItem>>this.instantiationService.createInstance( WorkbenchList, this.listContainer, new NotificationsListDelegate(this.listContainer), diff --git a/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts b/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts index 24a4022ebc..b2f2a77a29 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts @@ -75,7 +75,7 @@ export class NotificationsStatus { // Create new this.statusItem = this.statusbarService.addEntry({ text: this.count === 0 ? '$(bell)' : `$(bell) ${this.count}`, - command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : this.model.notifications.length > 0 ? SHOW_NOTIFICATIONS_CENTER : void 0, + command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : SHOW_NOTIFICATIONS_CENTER, tooltip: this.getTooltip(), showBeak: this.isNotificationsCenterVisible }, StatusbarAlignment.RIGHT, -1000 /* towards the far end of the right hand side */); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index a48d66c1c4..bc76d0029c 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -8,10 +8,9 @@ import 'vs/css!./media/notificationsToasts'; import { INotificationsModel, NotificationChangeType, INotificationChangeEvent, INotificationViewItem, NotificationViewItemLabelKind } from 'vs/workbench/common/notifications'; import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import { addClass, removeClass, isAncestor, addDisposableListener, EventType } from 'vs/base/browser/dom'; +import { addClass, removeClass, isAncestor, addDisposableListener, EventType, Dimension } from 'vs/base/browser/dom'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList'; -import { Dimension } from 'vs/base/browser/builder'; import { once } from 'vs/base/common/event'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { Themable, NOTIFICATIONS_TOAST_BORDER } from 'vs/workbench/common/theme'; @@ -122,8 +121,6 @@ export class NotificationsToasts extends Themable { this.notificationsToastsContainer.appendChild(notificationToastContainer); } - itemDisposeables.push(toDisposable(() => this.notificationsToastsContainer.removeChild(notificationToastContainer))); - // Toast const notificationToast = document.createElement('div'); addClass(notificationToast, 'notification-toast'); @@ -135,7 +132,15 @@ export class NotificationsToasts extends Themable { verticalScrollMode: ScrollbarVisibility.Hidden }); itemDisposeables.push(notificationList); - this.mapNotificationToToast.set(item, { item, list: notificationList, container: notificationToastContainer, toast: notificationToast, disposeables: itemDisposeables }); + + const toast: INotificationToast = { item, list: notificationList, container: notificationToastContainer, toast: notificationToast, disposeables: itemDisposeables }; + this.mapNotificationToToast.set(item, toast); + + itemDisposeables.push(toDisposable(() => { + if (this.isVisible(toast)) { + this.notificationsToastsContainer.removeChild(toast.container); + } + })); // Make visible notificationList.show(); @@ -163,7 +168,7 @@ export class NotificationsToasts extends Themable { } })); - // Remove when item gets disposed + // Remove when item gets closed once(item.onDidClose)(() => { this.removeToast(item); }); @@ -431,6 +436,8 @@ export class NotificationsToasts extends Themable { availableHeight -= (2 * 12); // adjust for paddings top and bottom } + availableHeight = Math.round(availableHeight * 0.618); // try to not cover the full height for stacked toasts + return new Dimension(Math.min(maxWidth, availableWidth), availableHeight); } @@ -466,10 +473,18 @@ export class NotificationsToasts extends Themable { } private setVisibility(toast: INotificationToast, visible: boolean): void { - toast.container.style.display = visible ? 'block' : 'none'; + if (this.isVisible(toast) === visible) { + return; + } + + if (visible) { + this.notificationsToastsContainer.appendChild(toast.container); + } else { + this.notificationsToastsContainer.removeChild(toast.container); + } } private isVisible(toast: INotificationToast): boolean { - return toast.container.style.display === 'block'; + return !!toast.container.parentElement; } } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts index 87587fa091..7acf0139f0 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsViewer.ts @@ -434,7 +434,9 @@ export class NotificationTemplateRenderer { const action = notification.actions.primary[index]; button.label = action.label; - this.inputDisposeables.push(button.onDidClick(() => { + this.inputDisposeables.push(button.onDidClick(e => { + e.preventDefault(); + e.stopPropagation(); // Run action this.actionRunner.run(action, notification); @@ -454,7 +456,7 @@ export class NotificationTemplateRenderer { // Return early if the item has no progress if (!notification.hasProgress()) { - this.template.progress.stop().getContainer().hide(); + this.template.progress.stop().hide(); return; } @@ -462,23 +464,23 @@ export class NotificationTemplateRenderer { // Infinite const state = notification.progress.state; if (state.infinite) { - this.template.progress.infinite().getContainer().show(); + this.template.progress.infinite().show(); } // Total / Worked - else if (state.total || state.worked) { - if (state.total) { + else if (typeof state.total === 'number' || typeof state.worked === 'number') { + if (typeof state.total === 'number' && !this.template.progress.hasTotal()) { this.template.progress.total(state.total); } - if (state.worked) { - this.template.progress.worked(state.worked).getContainer().show(); + if (typeof state.worked === 'number') { + this.template.progress.worked(state.worked).show(); } } // Done else { - this.template.progress.done().getContainer().hide(); + this.template.progress.done().hide(); } } diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index 545d045cb7..388ef46e58 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -30,10 +30,6 @@ border-left-style: solid; } -.monaco-workbench > .part.panel > .composite.title > .title-actions { - flex-grow: 0; -} - .monaco-workbench > .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label { outline-offset: -2px; } @@ -90,7 +86,7 @@ cursor: default; } -.monaco-workbench .panel .monaco-action-bar .action-item .select-box { +.monaco-workbench .panel .monaco-action-bar .action-item .monaco-select-box { cursor: pointer; min-width: 110px; } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 1e2a5b983b..827d940153 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/panelpart'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 0dddb029fb..54e54dcef8 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -6,13 +6,13 @@ import 'vs/css!./media/panelpart'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, Action } from 'vs/base/common/actions'; -import Event from 'vs/base/common/event'; -import { Builder, Dimension } from 'vs/base/browser/builder'; +import { Event } from 'vs/base/common/event'; +import { $ } from 'vs/base/browser/builder'; import { Registry } from 'vs/platform/registry/common/platform'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { IPanel } from 'vs/workbench/common/panel'; import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/compositePart'; -import { Panel, PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; +import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService'; import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -30,6 +30,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension } from 'vs/base/browser/dom'; export class PanelPart extends CompositePart<Panel> implements IPanelService { @@ -42,7 +43,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { private blockOpeningPanel: boolean; private compositeBar: CompositeBar; private dimension: Dimension; - private toolbarWidth = new Map<string, number>(); constructor( id: string, @@ -100,6 +100,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { private registerListeners(): void { + this.toUnbind.push(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor, false))); + // Activate panel action on opening of a panel this.toUnbind.push(this.onDidPanelOpen(panel => { this.compositeBar.activateComposite(panel.getId()); @@ -123,11 +125,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { public updateStyles(): void { super.updateStyles(); - const container = this.getContainer(); + const container = $(this.getContainer()); container.style('background-color', this.getColor(PANEL_BACKGROUND)); container.style('border-left-color', this.getColor(PANEL_BORDER) || this.getColor(contrastBorder)); - const title = this.getTitleArea(); + const title = $(this.getTitleArea()); title.style('border-top-color', this.getColor(PANEL_BORDER) || this.getColor(contrastBorder)); } @@ -169,7 +171,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { }); } - public getPanels(): IPanelIdentifier[] { + public getPanels(): PanelDescriptor[] { return Registry.as<PanelRegistry>(PanelExtensions.Panels).getPanels() .filter(p => p.enabled) .sort((v1, v2) => v1.order - v2.order); @@ -180,7 +182,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { if (descriptor && descriptor.enabled !== enabled) { descriptor.enabled = enabled; if (enabled) { - this.compositeBar.addComposite(descriptor); + this.compositeBar.addComposite(descriptor, true); } else { this.compositeBar.removeComposite(id); } @@ -207,8 +209,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { return this.hideActiveComposite().then(composite => void 0); } - protected createTitleLabel(parent: Builder): ICompositeTitleLabel { - const titleArea = this.compositeBar.create(parent.getHTMLElement()); + protected createTitleLabel(parent: HTMLElement): ICompositeTitleLabel { + const titleArea = this.compositeBar.create(parent); titleArea.classList.add('panel-switcher-container'); return { @@ -241,6 +243,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { return sizes; } + public shutdown(): void { + this.compositeBar.shutdown(); + super.shutdown(); + } + private layoutCompositeBar(): void { if (this.dimension) { let availableWidth = this.dimension.width - 40; // take padding into account @@ -257,11 +264,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService { if (!activePanel) { return 0; } - if (!this.toolbarWidth.has(activePanel.getId())) { - this.toolbarWidth.set(activePanel.getId(), this.toolBar.getContainer().getHTMLElement().offsetWidth); - } - - return this.toolbarWidth.get(activePanel.getId()); + return this.toolBar.getItemsWidth(); } } diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.css b/src/vs/workbench/browser/parts/quickinput/quickInput.css new file mode 100644 index 0000000000..bc631bd066 --- /dev/null +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.css @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.quick-input-widget { + position: absolute; + width: 600px; + z-index: 2000; + padding-bottom: 6px; + left: 50%; + margin-left: -300px; +} + +.quick-input-header { + display: flex; + padding: 6px 6px 4px 6px; +} + +.quick-input-check-all { + align-self: center; + margin: 0; +} + +.quick-input-filter { + flex-grow: 1; + display: flex; + position: relative; +} + +.quick-input-box { + flex-grow: 1; +} + +.quick-input-widget[data-type=selectMany] .quick-input-box { + margin-left: 5px; +} + +.quick-input-count { + align-self: center; + position: absolute; + right: 4px; +} + +.quick-input-count .monaco-count-badge { + vertical-align: middle; +} + +.quick-input-action { + margin-left: 6px; +} + +.quick-input-action .monaco-text-button { + font-size: 85%; + padding: 7px 6px 6px 6px; + line-height: initial; +} + +.quick-input-message { + margin: 0px 11px; +} + +.quick-input-progress.monaco-progress-container, +.quick-input-progress.monaco-progress-container .progress-bit { + height: 2px; +} + +.quick-input-checkbox-list { + line-height: 22px; +} + +.quick-input-checkbox-list .monaco-list { + overflow: hidden; + max-height: calc(20 * 22px); +} + +.quick-input-checkbox-list .quick-input-checkbox-list-entry { + overflow: hidden; + display: flex; + height: 100%; + padding: 0 6px; +} + +.quick-input-checkbox-list .quick-input-checkbox-list-label { + overflow: hidden; + display: flex; + height: 100%; + flex: 1; +} + +.quick-input-checkbox-list .quick-input-checkbox-list-checkbox { + align-self: center; + margin: 0; + /* TODO */ + /* margin-top: 5px; */ +} + +.quick-input-checkbox-list .quick-input-checkbox-list-rows { + overflow: hidden; + text-overflow: ellipsis; + display: flex; + flex-direction: column; + height: 100%; + flex: 1; + margin-left: 10px; +} + +.quick-input-checkbox-list .quick-input-checkbox-list-rows > .quick-input-checkbox-list-row { + display: flex; + align-items: center; +} + +.quick-input-checkbox-list .quick-input-checkbox-list-rows .monaco-highlighted-label span { + opacity: 1; +} + +.quick-input-checkbox-list .quick-input-checkbox-list-label-meta { + opacity: 0.7; + line-height: normal; +} diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.ts b/src/vs/workbench/browser/parts/quickinput/quickInput.ts new file mode 100644 index 0000000000..248ea46b37 --- /dev/null +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.ts @@ -0,0 +1,526 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'vs/css!./quickInput'; +import { Component } from 'vs/workbench/common/component'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; +import * as dom from 'vs/base/browser/dom'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; +import { SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND } from 'vs/workbench/common/theme'; +import { IQuickOpenService, IPickOpenEntry, IPickOptions, IInputOptions } from 'vs/platform/quickOpen/common/quickOpen'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { QuickInputCheckboxList } from './quickInputCheckboxList'; +import { QuickInputBox } from './quickInputBox'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { localize } from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { CLOSE_ON_FOCUS_LOST_CONFIG } from 'vs/workbench/browser/quickopen'; +import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; +import { attachBadgeStyler, attachProgressBarStyler, attachButtonStyler } from 'vs/platform/theme/common/styler'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; +import { chain, debounceEvent } from 'vs/base/common/event'; +import { Button } from 'vs/base/browser/ui/button/button'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { onUnexpectedError, canceled } from 'vs/base/common/errors'; +import Severity from 'vs/base/common/severity'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; + +const $ = dom.$; + +type InputParameters = SelectManyParameters | TextInputParameters; + +export interface BaseInputParameters { + readonly type: 'selectMany' | 'textInput'; + readonly ignoreFocusLost?: boolean; +} + +export interface SelectManyParameters<T extends IPickOpenEntry = IPickOpenEntry> extends BaseInputParameters { + readonly type: 'selectMany'; + readonly picks: TPromise<T[]>; + readonly matchOnDescription?: boolean; + readonly matchOnDetail?: boolean; + readonly placeHolder?: string; +} + +export interface TextInputParameters extends BaseInputParameters { + readonly type: 'textInput'; + readonly value?: string; + readonly valueSelection?: [number, number]; + readonly prompt?: string; + readonly placeHolder?: string; + readonly password?: boolean; + readonly validateInput?: (input: string) => TPromise<string>; +} + +interface QuickInputUI { + checkAll: HTMLInputElement; + inputBox: QuickInputBox; + count: CountBadge; + message: HTMLElement; + checkboxList: QuickInputCheckboxList; +} + +interface InputController<R> { + readonly showUI: { [k in keyof QuickInputUI]?: boolean; } & { ok?: boolean; }; + readonly result: TPromise<R>; + readonly ready: TPromise<void>; + readonly resolve: (ok?: true | Thenable<never>) => void | TPromise<void>; +} + +class SelectManyController<T extends IPickOpenEntry> implements InputController<T[]> { + public showUI = { checkAll: true, inputBox: true, count: true, ok: true, checkboxList: true }; + public result: TPromise<T[]>; + public ready: TPromise<void>; + public resolve: (ok?: true | Thenable<never>) => void; + public progress: (value: T) => void; + private closed = false; + + constructor(ui: QuickInputUI, parameters: SelectManyParameters<T>) { + this.result = new TPromise<T[]>((resolve, reject, progress) => { + this.resolve = ok => resolve(ok === true ? <T[]>ui.checkboxList.getCheckedElements() : ok); + this.progress = progress; + }); + this.result.then(() => this.closed = true, () => this.closed = true); + + ui.inputBox.value = ''; + ui.inputBox.setPlaceholder(parameters.placeHolder || ''); + ui.checkboxList.matchOnDescription = parameters.matchOnDescription; + ui.checkboxList.matchOnDetail = parameters.matchOnDetail; + ui.checkboxList.setElements([]); + ui.checkAll.checked = ui.checkboxList.getAllVisibleChecked(); + ui.count.setCount(ui.checkboxList.getCheckedCount()); + + this.ready = parameters.picks.then(elements => { + if (this.closed) { + return; + } + + ui.checkboxList.setElements(elements); + ui.checkboxList.filter(ui.inputBox.value); + ui.checkAll.checked = ui.checkboxList.getAllVisibleChecked(); + ui.count.setCount(ui.checkboxList.getCheckedCount()); + }); + } +} + +class TextInputController implements InputController<string> { + public showUI = { inputBox: true, message: true }; + public result: TPromise<string>; + public ready = TPromise.as(null); + public resolveResult: (string) => void; + private validationValue: string; + private validation: TPromise<string>; + private defaultMessage: string; + private disposables: IDisposable[] = []; + + constructor(private ui: QuickInputUI, private parameters: TextInputParameters) { + this.result = new TPromise<string>((resolve, reject, progress) => { + this.resolveResult = resolve; + }); + this.result.then(() => this.dispose()); + + ui.inputBox.value = parameters.value || ''; + const selection = parameters.valueSelection; + ui.inputBox.select(selection && { start: selection[0], end: selection[1] }); + ui.inputBox.setPlaceholder(parameters.placeHolder || ''); + this.defaultMessage = parameters.prompt + ? localize('inputModeEntryDescription', "{0} (Press 'Enter' to confirm or 'Escape' to cancel)", parameters.prompt) + : localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel"); + ui.message.textContent = this.defaultMessage; + ui.inputBox.setPassword(parameters.password); + + if (parameters.validateInput) { + const onDidChange = debounceEvent(ui.inputBox.onDidChange, (last, cur) => cur, 100); + this.disposables.push(onDidChange(() => this.didChange())); + if (ui.inputBox.value) { + // Replicating old behavior: only fire if value is not empty. + this.didChange(); + } + } + } + + didChange() { + this.updatedValidation() + .then(validationError => { + this.ui.message.textContent = validationError || this.defaultMessage; + this.ui.inputBox.showDecoration(validationError ? Severity.Error : Severity.Ignore); + }) + .then(null, onUnexpectedError); + } + + resolve(ok?: true | Thenable<never>) { + if (ok === true) { + return this.updatedValidation() + .then(validationError => { + if (validationError) { + throw canceled(); + } + this.resolveResult(this.ui.inputBox.value); + }); + } else { + this.resolveResult(ok); + } + return null; + } + + private updatedValidation() { + if (this.parameters.validateInput) { + const value = this.ui.inputBox.value; + if (value !== this.validationValue) { + this.validationValue = value; + this.validation = this.parameters.validateInput(value) + .then(validationError => { + if (this.validationValue !== value) { + throw canceled(); + } + return validationError; + }); + } + } else if (!this.validation) { + this.validation = TPromise.as(null); + } + return this.validation; + } + + private dispose() { + this.disposables = dispose(this.disposables); + } +} + +export class QuickInputService extends Component implements IQuickInputService { + + public _serviceBrand: any; + + private static readonly ID = 'workbench.component.quickinput'; + private static readonly MAX_WIDTH = 600; // Max total width of quick open widget + + private layoutDimensions: dom.Dimension; + private container: HTMLElement; + private filterContainer: HTMLElement; + private countContainer: HTMLElement; + private okContainer: HTMLElement; + private ui: QuickInputUI; + private ready = false; + private progressBar: ProgressBar; + private ignoreFocusLost = false; + + private controller: InputController<any>; + + constructor( + @IEnvironmentService private environmentService: IEnvironmentService, + @IConfigurationService private configurationService: IConfigurationService, + @IInstantiationService private instantiationService: IInstantiationService, + @IPartService private partService: IPartService, + @IQuickOpenService private quickOpenService: IQuickOpenService, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IThemeService themeService: IThemeService + ) { + super(QuickInputService.ID, themeService); + } + + private create() { + if (this.container) { + return; + } + + const workbench = document.getElementById(this.partService.getWorkbenchElementId()); + this.container = dom.append(workbench, $('.quick-input-widget')); + this.container.tabIndex = -1; + this.container.style.display = 'none'; + + const headerContainer = dom.append(this.container, $('.quick-input-header')); + + const checkAll = <HTMLInputElement>dom.append(headerContainer, $('input.quick-input-check-all')); + checkAll.type = 'checkbox'; + this.toUnbind.push(dom.addStandardDisposableListener(checkAll, dom.EventType.CHANGE, e => { + const checked = checkAll.checked; + checkboxList.setAllVisibleChecked(checked); + })); + this.toUnbind.push(dom.addDisposableListener(checkAll, dom.EventType.CLICK, e => { + if (e.x || e.y) { // Avoid 'click' triggered by 'space'... + inputBox.setFocus(); + } + })); + + this.filterContainer = dom.append(headerContainer, $('.quick-input-filter')); + + const inputBox = new QuickInputBox(this.filterContainer); + this.toUnbind.push(inputBox); + inputBox.onDidChange(value => { + checkboxList.filter(value); + }); + this.toUnbind.push(inputBox.onKeyDown(event => { + if (!checkboxList.isDisplayed()) { + return; + } + switch (event.keyCode) { + case KeyCode.DownArrow: + checkboxList.focus('First'); + checkboxList.domFocus(); + break; + case KeyCode.UpArrow: + checkboxList.focus('Last'); + checkboxList.domFocus(); + break; + } + })); + + this.countContainer = dom.append(this.filterContainer, $('.quick-input-count')); + const count = new CountBadge(this.countContainer, { countFormat: localize('quickInput.countSelected', "{0} Selected") }); + this.toUnbind.push(attachBadgeStyler(count, this.themeService)); + + this.okContainer = dom.append(headerContainer, $('.quick-input-action')); + const ok = new Button(this.okContainer); + attachButtonStyler(ok, this.themeService); + ok.label = localize('ok', "OK"); + this.toUnbind.push(ok.onDidClick(e => { + if (this.ready) { + this.close(true); + } + })); + + const message = dom.append(this.container, $('.quick-input-message')); + + this.progressBar = new ProgressBar(this.container); + dom.addClass(this.progressBar.getContainer(), 'quick-input-progress'); + this.toUnbind.push(attachProgressBarStyler(this.progressBar, this.themeService)); + + const checkboxList = this.instantiationService.createInstance(QuickInputCheckboxList, this.container); + this.toUnbind.push(checkboxList); + this.toUnbind.push(checkboxList.onAllVisibleCheckedChanged(checked => { + checkAll.checked = checked; + })); + this.toUnbind.push(checkboxList.onCheckedCountChanged(c => { + count.setCount(c); + })); + this.toUnbind.push(checkboxList.onLeave(() => { + // Defer to avoid the input field reacting to the triggering key. + setTimeout(() => { + inputBox.setFocus(); + checkboxList.clearFocus(); + }, 0); + })); + this.toUnbind.push( + chain(checkboxList.onFocusChange) + .map(e => e[0]) + .filter(e => !!e) + .latch() + .on(e => this.controller instanceof SelectManyController && this.controller.progress(e)) // TODO + ); + + this.toUnbind.push(dom.addDisposableListener(this.container, 'focusout', (e: FocusEvent) => { + if (e.relatedTarget === this.container) { + (<HTMLElement>e.target).focus(); + return; + } + for (let element = <Element>e.relatedTarget; element; element = element.parentElement) { + if (element === this.container) { + return; + } + } + if (!this.ignoreFocusLost && !this.environmentService.args['sticky-quickopen'] && this.configurationService.getValue(CLOSE_ON_FOCUS_LOST_CONFIG)) { + this.close(undefined, true); + } + })); + this.toUnbind.push(dom.addDisposableListener(this.container, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { + const event = new StandardKeyboardEvent(e); + switch (event.keyCode) { + case KeyCode.Enter: + if (this.ready) { + dom.EventHelper.stop(e, true); + this.close(true); + } + break; + case KeyCode.Escape: + dom.EventHelper.stop(e, true); + this.close(); + break; + case KeyCode.Tab: + if (!event.altKey && !event.ctrlKey && !event.metaKey) { + const inputs = this.container.querySelectorAll('input'); + if (event.shiftKey && event.target === inputs[0]) { + dom.EventHelper.stop(e, true); + inputs[inputs.length - 1].focus(); + } else if (!event.shiftKey && event.target === inputs[inputs.length - 1]) { + dom.EventHelper.stop(e, true); + inputs[0].focus(); + } + } + break; + } + })); + + this.toUnbind.push(this.quickOpenService.onShow(() => this.close())); + + this.ui = { checkAll, inputBox, count, message, checkboxList }; + this.updateStyles(); + } + + private close(ok?: true | Thenable<never>, focusLost?: boolean) { + if (!this.container || this.container.style.display === 'none') { + return TPromise.as(undefined); + } + if (this.controller) { + const resolved = this.controller.resolve(ok); + if (resolved) { + const result = resolved + .then(() => { + this.container.style.display = 'none'; + if (!focusLost) { + this.restoreFocus(); + } + }); + result.then(null, onUnexpectedError); + return result; + } + } + this.container.style.display = 'none'; + if (!focusLost) { + this.restoreFocus(); + } + return TPromise.as(undefined); + } + + private restoreFocus(): void { + const editor = this.editorService.getActiveEditor(); + if (editor) { + editor.focus(); + } + } + + pick<T extends IPickOpenEntry>(picks: TPromise<T[]>, options: IPickOptions = {}, token?: CancellationToken): TPromise<T[]> { + return this.show({ + type: 'selectMany', + picks, + placeHolder: options.placeHolder, + matchOnDescription: options.matchOnDescription, + matchOnDetail: options.matchOnDetail, + ignoreFocusLost: options.ignoreFocusLost + }, token); + } + + input(options: IInputOptions = {}, token?: CancellationToken): TPromise<string> { + return this.show({ + type: 'textInput', + value: options.value, + valueSelection: options.valueSelection, + prompt: options.prompt, + placeHolder: options.placeHolder, + password: options.password, + ignoreFocusLost: options.ignoreFocusLost, + validateInput: options.validateInput, + }, token); + } + + show<T extends IPickOpenEntry>(parameters: SelectManyParameters<T>, token?: CancellationToken): TPromise<T[]>; + show(parameters: TextInputParameters, token?: CancellationToken): TPromise<string>; + show<R>(parameters: InputParameters, token: CancellationToken = CancellationToken.None): TPromise<R> { + this.create(); + this.quickOpenService.close(); + if (this.controller) { + this.controller.resolve(); + } + + this.container.setAttribute('data-type', parameters.type); + + this.ignoreFocusLost = parameters.ignoreFocusLost; + + this.progressBar.stop(); + this.ready = false; + + this.controller = parameters.type === 'selectMany' ? new SelectManyController(this.ui, parameters) : new TextInputController(this.ui, parameters); + this.ui.checkAll.style.display = this.controller.showUI.checkAll ? null : 'none'; + this.filterContainer.style.display = this.controller.showUI.inputBox ? null : 'none'; + this.ui.inputBox.showDecoration(Severity.Ignore); + this.countContainer.style.display = this.controller.showUI.count ? null : 'none'; + this.okContainer.style.display = this.controller.showUI.ok ? null : 'none'; + this.ui.message.style.display = this.controller.showUI.message ? null : 'none'; + this.ui.checkboxList.display(this.controller.showUI.checkboxList); + + this.container.style.display = null; + this.updateLayout(); + this.ui.inputBox.setFocus(); + + const d = token.onCancellationRequested(() => this.close()); + this.controller.result.then(() => d.dispose(), () => d.dispose()); + + const delay = TPromise.timeout(800); + delay.then(() => this.progressBar.infinite(), () => { /* ignore */ }); + + const wasController = this.controller; + this.controller.ready.then(() => { + delay.cancel(); + if (this.controller !== wasController) { + return; + } + + this.progressBar.stop(); + this.ready = true; + + this.updateLayout(); + }).then(null, reason => this.close(TPromise.wrapError(reason))); + + return this.controller.result; + } + + focus() { + if (this.ui) { + this.ui.inputBox.setFocus(); + } + } + + accept() { + return this.close(true); + } + + cancel() { + return this.close(); + } + + layout(dimension: dom.Dimension): void { + this.layoutDimensions = dimension; + this.updateLayout(); + } + + private updateLayout() { + if (this.layoutDimensions && this.container) { + const titlebarOffset = this.partService.getTitleBarOffset(); + this.container.style.top = `${titlebarOffset}px`; + + const style = this.container.style; + const width = Math.min(this.layoutDimensions.width * 0.62 /* golden cut */, QuickInputService.MAX_WIDTH); + style.width = width + 'px'; + style.marginLeft = '-' + (width / 2) + 'px'; + + this.ui.inputBox.layout(); + this.ui.checkboxList.layout(); + } + } + + protected updateStyles() { + const theme = this.themeService.getTheme(); + if (this.ui) { + this.ui.inputBox.style(theme); + } + if (this.container) { + const sideBarBackground = theme.getColor(SIDE_BAR_BACKGROUND); + this.container.style.backgroundColor = sideBarBackground ? sideBarBackground.toString() : undefined; + const sideBarForeground = theme.getColor(SIDE_BAR_FOREGROUND); + this.container.style.color = sideBarForeground ? sideBarForeground.toString() : undefined; + const contrastBorderColor = theme.getColor(contrastBorder); + this.container.style.border = contrastBorderColor ? `1px solid ${contrastBorderColor}` : undefined; + const widgetShadowColor = theme.getColor(widgetShadow); + this.container.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : undefined; + } + } +} diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts b/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts new file mode 100644 index 0000000000..18a4ba59fc --- /dev/null +++ b/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'vs/css!./quickInput'; +import * as dom from 'vs/base/browser/dom'; +import { InputBox, IRange, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; +import { localize } from 'vs/nls'; +import { inputBackground, inputForeground, inputBorder, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationErrorBackground, inputValidationErrorBorder } from 'vs/platform/theme/common/colorRegistry'; +import { ITheme } from 'vs/platform/theme/common/themeService'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import Severity from 'vs/base/common/severity'; + +const $ = dom.$; + +const DEFAULT_INPUT_ARIA_LABEL = localize('quickInputBox.ariaLabel', "Type to narrow down results."); + +export class QuickInputBox { + + private container: HTMLElement; + private inputBox: InputBox; + private disposables: IDisposable[] = []; + + constructor( + private parent: HTMLElement + ) { + this.container = dom.append(this.parent, $('.quick-input-box')); + this.inputBox = new InputBox(this.container, null, { + ariaLabel: DEFAULT_INPUT_ARIA_LABEL + }); + this.disposables.push(this.inputBox); + + // ARIA + const inputElement = this.inputBox.inputElement; + inputElement.setAttribute('role', 'combobox'); + inputElement.setAttribute('aria-haspopup', 'false'); + inputElement.setAttribute('aria-autocomplete', 'list'); + } + + onKeyDown = (handler: (event: StandardKeyboardEvent) => void): IDisposable => { + return dom.addDisposableListener(this.inputBox.inputElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { + handler(new StandardKeyboardEvent(e)); + }); + } + + onDidChange = (handler: (event: string) => void): IDisposable => { + return this.inputBox.onDidChange(handler); + } + + get value() { + return this.inputBox.value; + } + + set value(value: string) { + this.inputBox.value = value; + } + + select(range: IRange = null): void { + this.inputBox.select(range); + } + + setPlaceholder(placeholder: string) { + this.inputBox.setPlaceHolder(placeholder); + } + + setPassword(isPassword: boolean): void { + this.inputBox.inputElement.type = isPassword ? 'password' : 'text'; + } + + showDecoration(decoration: Severity): void { + if (decoration === Severity.Ignore) { + this.inputBox.hideMessage(); + } else { + this.inputBox.showMessage({ type: decoration === Severity.Info ? MessageType.INFO : decoration === Severity.Warning ? MessageType.WARNING : MessageType.ERROR, content: '' }); + } + } + + setFocus(): void { + this.inputBox.focus(); + } + + layout(): void { + this.inputBox.layout(); + } + + style(theme: ITheme) { + this.inputBox.style({ + inputForeground: theme.getColor(inputForeground), + inputBackground: theme.getColor(inputBackground), + inputBorder: theme.getColor(inputBorder), + inputValidationInfoBackground: theme.getColor(inputValidationInfoBackground), + inputValidationInfoBorder: theme.getColor(inputValidationInfoBorder), + inputValidationWarningBackground: theme.getColor(inputValidationWarningBackground), + inputValidationWarningBorder: theme.getColor(inputValidationWarningBorder), + inputValidationErrorBackground: theme.getColor(inputValidationErrorBackground), + inputValidationErrorBorder: theme.getColor(inputValidationErrorBorder), + }); + } + + dispose() { + this.disposables = dispose(this.disposables); + } +} diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts b/src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts new file mode 100644 index 0000000000..f82d713e6f --- /dev/null +++ b/src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts @@ -0,0 +1,389 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'vs/css!./quickInput'; +import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; +import * as dom from 'vs/base/browser/dom'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { WorkbenchList } from 'vs/platform/list/browser/listService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; +import { IMatch } from 'vs/base/common/filters'; +import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon'; +import { compareAnything } from 'vs/base/common/comparers'; +import { Emitter, Event, mapEvent } from 'vs/base/common/event'; +import { assign } from 'vs/base/common/objects'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; +import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; +import { memoize } from 'vs/base/common/decorators'; +import { range } from 'vs/base/common/arrays'; +import * as platform from 'vs/base/common/platform'; + +const $ = dom.$; + +interface ICheckableElement { + index: number; + item: IPickOpenEntry; + checked: boolean; +} + +class CheckableElement implements ICheckableElement { + index: number; + item: IPickOpenEntry; + shouldAlwaysShow = false; + hidden = false; + private _onChecked = new Emitter<boolean>(); + onChecked = this._onChecked.event; + _checked: boolean; + get checked() { + return this._checked; + } + set checked(value: boolean) { + if (value !== this._checked) { + this._checked = value; + this._onChecked.fire(value); + } + } + labelHighlights?: IMatch[]; + descriptionHighlights?: IMatch[]; + detailHighlights?: IMatch[]; + + constructor(init: ICheckableElement) { + assign(this, init); + } +} + +interface ICheckableElementTemplateData { + checkbox: HTMLInputElement; + label: IconLabel; + detail: HighlightedLabel; + element: CheckableElement; + toDisposeElement: IDisposable[]; + toDisposeTemplate: IDisposable[]; +} + +class CheckableElementRenderer implements IRenderer<CheckableElement, ICheckableElementTemplateData> { + + static readonly ID = 'checkableelement'; + + get templateId() { + return CheckableElementRenderer.ID; + } + + renderTemplate(container: HTMLElement): ICheckableElementTemplateData { + const data: ICheckableElementTemplateData = Object.create(null); + + const entry = dom.append(container, $('.quick-input-checkbox-list-entry')); + const label = dom.append(entry, $('label.quick-input-checkbox-list-label')); + + // Entry + data.checkbox = <HTMLInputElement>dom.append(label, $('input.quick-input-checkbox-list-checkbox')); + data.checkbox.type = 'checkbox'; + data.toDisposeElement = []; + data.toDisposeTemplate = []; + data.toDisposeTemplate.push(dom.addStandardDisposableListener(data.checkbox, dom.EventType.CHANGE, e => { + data.element.checked = data.checkbox.checked; + })); + + const rows = dom.append(label, $('.quick-input-checkbox-list-rows')); + const row1 = dom.append(rows, $('.quick-input-checkbox-list-row')); + const row2 = dom.append(rows, $('.quick-input-checkbox-list-row')); + + // Label + data.label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true }); + + // Detail + const detailContainer = dom.append(row2, $('.quick-input-checkbox-list-label-meta')); + data.detail = new HighlightedLabel(detailContainer); + + return data; + } + + renderElement(element: CheckableElement, index: number, data: ICheckableElementTemplateData): void { + data.toDisposeElement = dispose(data.toDisposeElement); + data.element = element; + data.checkbox.checked = element.checked; + data.toDisposeElement.push(element.onChecked(checked => data.checkbox.checked = checked)); + + const { labelHighlights, descriptionHighlights, detailHighlights } = element; + + // Label + const options: IIconLabelValueOptions = Object.create(null); + options.matches = labelHighlights || []; + options.descriptionTitle = element.item.description; + options.descriptionMatches = descriptionHighlights || []; + data.label.setValue(element.item.label, element.item.description, options); + + // Meta + data.detail.set(element.item.detail, detailHighlights); + } + + disposeTemplate(data: ICheckableElementTemplateData): void { + data.toDisposeElement = dispose(data.toDisposeElement); + data.toDisposeTemplate = dispose(data.toDisposeTemplate); + } +} + +class CheckableElementDelegate implements IDelegate<CheckableElement> { + + getHeight(element: CheckableElement): number { + return element.item.detail ? 44 : 22; + } + + getTemplateId(element: CheckableElement): string { + return CheckableElementRenderer.ID; + } +} + +export class QuickInputCheckboxList { + + private container: HTMLElement; + private list: WorkbenchList<CheckableElement>; + private elements: CheckableElement[] = []; + matchOnDescription = false; + matchOnDetail = false; + private _onAllVisibleCheckedChanged = new Emitter<boolean>(); // TODO: Debounce + onAllVisibleCheckedChanged: Event<boolean> = this._onAllVisibleCheckedChanged.event; + private _onCheckedCountChanged = new Emitter<number>(); // TODO: Debounce + onCheckedCountChanged: Event<number> = this._onCheckedCountChanged.event; + private _onLeave = new Emitter<void>(); + onLeave: Event<void> = this._onLeave.event; + private _fireCheckedEvents = true; + private elementDisposables: IDisposable[] = []; + private disposables: IDisposable[] = []; + + constructor( + private parent: HTMLElement, + @IInstantiationService private instantiationService: IInstantiationService + ) { + this.container = dom.append(this.parent, $('.quick-input-checkbox-list')); + const delegate = new CheckableElementDelegate(); + this.list = this.instantiationService.createInstance(WorkbenchList, this.container, delegate, [new CheckableElementRenderer()], { + identityProvider: element => element.label, + multipleSelectionSupport: false + }) as WorkbenchList<CheckableElement>; + this.disposables.push(this.list); + this.disposables.push(this.list.onKeyDown(e => { + const event = new StandardKeyboardEvent(e); + switch (event.keyCode) { + case KeyCode.Space: + this.toggleCheckbox(); + break; + case KeyCode.KEY_A: + if (platform.isMacintosh ? e.metaKey : e.ctrlKey) { + this.list.setFocus(range(this.list.length)); + } + break; + case KeyCode.UpArrow: + const focus1 = this.list.getFocus(); + if (focus1.length === 1 && focus1[0] === 0) { + this._onLeave.fire(); + } + break; + case KeyCode.DownArrow: + const focus2 = this.list.getFocus(); + if (focus2.length === 1 && focus2[0] === this.list.length - 1) { + this._onLeave.fire(); + } + break; + } + })); + this.disposables.push(dom.addDisposableListener(this.container, dom.EventType.CLICK, e => { + if (e.x || e.y) { // Avoid 'click' triggered by 'space' on checkbox. + this._onLeave.fire(); + } + })); + this.disposables.push(this.list.onSelectionChange(e => { + if (e.elements.length) { + this.list.setSelection([]); + } + })); + } + + @memoize + get onFocusChange() { + return mapEvent(this.list.onFocusChange, e => e.elements.map(e => e.item)); + } + + getAllVisibleChecked() { + return this.allVisibleChecked(this.elements, false); + } + + private allVisibleChecked(elements: CheckableElement[], whenNoneVisible = true) { + for (let i = 0, n = elements.length; i < n; i++) { + const element = elements[i]; + if (!element.hidden) { + if (!element.checked) { + return false; + } else { + whenNoneVisible = true; + } + } + } + return whenNoneVisible; + } + + getCheckedCount() { + let count = 0; + const elements = this.elements; + for (let i = 0, n = elements.length; i < n; i++) { + if (elements[i].checked) { + count++; + } + } + return count; + } + + setAllVisibleChecked(checked: boolean) { + try { + this._fireCheckedEvents = false; + this.elements.forEach(element => { + if (!element.hidden) { + element.checked = checked; + } + }); + } finally { + this._fireCheckedEvents = true; + this.fireCheckedEvents(); + } + } + + setElements(elements: IPickOpenEntry[]): void { + this.elementDisposables = dispose(this.elementDisposables); + this.elements = elements.map((item, index) => new CheckableElement({ + index, + item, + checked: !!item.picked + })); + this.elementDisposables.push(...this.elements.map(element => element.onChecked(() => this.fireCheckedEvents()))); + this.list.splice(0, this.list.length, this.elements); + this.list.setFocus([]); + } + + getCheckedElements() { + return this.elements.filter(e => e.checked) + .map(e => e.item); + } + + focus(what: 'First' | 'Last' | 'Next' | 'Previous' | 'NextPage' | 'PreviousPage'): void { + this.list['focus' + what](); + this.list.reveal(this.list.getFocus()[0]); + } + + clearFocus() { + this.list.setFocus([]); + } + + domFocus() { + this.list.domFocus(); + } + + layout(): void { + this.list.layout(); + } + + filter(query: string) { + query = query.trim(); + + // Reset filtering + if (!query) { + this.elements.forEach(element => { + element.labelHighlights = undefined; + element.descriptionHighlights = undefined; + element.detailHighlights = undefined; + element.hidden = false; + }); + } + + // Filter by value (since we support octicons, use octicon aware fuzzy matching) + else { + this.elements.forEach(element => { + const labelHighlights = matchesFuzzyOcticonAware(query, parseOcticons(element.item.label)); + const descriptionHighlights = this.matchOnDescription ? matchesFuzzyOcticonAware(query, parseOcticons(element.item.description || '')) : undefined; + const detailHighlights = this.matchOnDetail ? matchesFuzzyOcticonAware(query, parseOcticons(element.item.detail || '')) : undefined; + + if (element.shouldAlwaysShow || labelHighlights || descriptionHighlights || detailHighlights) { + element.labelHighlights = labelHighlights; + element.descriptionHighlights = descriptionHighlights; + element.detailHighlights = detailHighlights; + element.hidden = false; + } else { + element.labelHighlights = undefined; + element.descriptionHighlights = undefined; + element.detailHighlights = undefined; + element.hidden = true; + } + }); + } + + // Sort by value + const normalizedSearchValue = query.toLowerCase(); + this.elements.sort((a, b) => { + if (!query) { + return a.index - b.index; // restore natural order + } + return compareEntries(a, b, normalizedSearchValue); + }); + + this.list.splice(0, this.list.length, this.elements.filter(element => !element.hidden)); + this.list.setFocus([]); + this.list.layout(); + + this._onAllVisibleCheckedChanged.fire(this.getAllVisibleChecked()); + } + + toggleCheckbox() { + try { + this._fireCheckedEvents = false; + const elements = this.list.getFocusedElements(); + const allChecked = this.allVisibleChecked(elements); + for (const element of elements) { + element.checked = !allChecked; + } + } finally { + this._fireCheckedEvents = true; + this.fireCheckedEvents(); + } + } + + display(display: boolean) { + this.container.style.display = display ? null : 'none'; + } + + isDisplayed() { + return this.container.style.display !== 'none'; + } + + dispose() { + this.elementDisposables = dispose(this.elementDisposables); + this.disposables = dispose(this.disposables); + } + + private fireCheckedEvents() { + if (this._fireCheckedEvents) { + this._onAllVisibleCheckedChanged.fire(this.getAllVisibleChecked()); + this._onCheckedCountChanged.fire(this.getCheckedCount()); + } + } +} + +function compareEntries(elementA: CheckableElement, elementB: CheckableElement, lookFor: string): number { + + const labelHighlightsA = elementA.labelHighlights || []; + const labelHighlightsB = elementB.labelHighlights || []; + if (labelHighlightsA.length && !labelHighlightsB.length) { + return -1; + } + + if (!labelHighlightsA.length && labelHighlightsB.length) { + return 1; + } + + return compareAnything(elementA.item.label, elementB.item.label, lookFor); +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/quickopen/media/quickopen.css b/src/vs/workbench/browser/parts/quickopen/media/quickopen.css index ffe36dd8ed..48c9e2f3c5 100644 --- a/src/vs/workbench/browser/parts/quickopen/media/quickopen.css +++ b/src/vs/workbench/browser/parts/quickopen/media/quickopen.css @@ -3,22 +3,22 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none { +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.none { width: 16px; background: none; } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { width: 14px; height: 18px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { background-image: url('dirty.svg'); } -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.dirty { background-image: url('dirty-inverse.svg'); } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 00c7934964..50893cf20a 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -7,15 +7,13 @@ import 'vs/css!./media/quickopen'; import { TPromise, ValueCallback } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as browser from 'vs/base/browser/browser'; -import { Dimension, withElementById } from 'vs/base/browser/builder'; -import strings = require('vs/base/common/strings'); -import DOM = require('vs/base/browser/dom'); +import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; import * as resources from 'vs/base/common/resources'; import { defaultGenerator } from 'vs/base/common/idGenerator'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { Action, IAction } from 'vs/base/common/actions'; import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -23,7 +21,7 @@ import { Mode, IEntryRunContext, IAutoFocus, IQuickNavigateConfiguration, IModel import { QuickOpenEntry, QuickOpenModel, QuickOpenEntryGroup, compareEntries, QuickOpenItemAccessorClass } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenWidget, HideReason } from 'vs/base/parts/quickopen/browser/quickOpenWidget'; import { ContributableActionProvider } from 'vs/workbench/browser/actions'; -import labels = require('vs/base/common/labels'); +import * as labels from 'vs/base/common/labels'; import { ITextFileService, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles'; import { Registry } from 'vs/platform/registry/common/platform'; import { IResourceInput, IEditorInput } from 'vs/platform/editor/common/editor'; @@ -32,10 +30,10 @@ import { getIconClasses } from 'vs/workbench/browser/labels'; import { IModelService } from 'vs/editor/common/services/modelService'; import { EditorInput, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { Component } from 'vs/workbench/common/component'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { QuickOpenHandler, QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions, EditorQuickOpenEntry, CLOSE_ON_FOCUS_LOST_CONFIG } from 'vs/workbench/browser/quickopen'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPickOpenEntry, IFilePickOpenEntry, IInputOptions, IQuickOpenService, IPickOptions, IShowOptions, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -51,13 +49,13 @@ import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { FileKind, IFileService } from 'vs/platform/files/common/files'; import { scoreItem, ScorerCache, compareItemsByScore, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; -import { getBaseLabel } from 'vs/base/common/labels'; import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { matchesFuzzyOcticonAware, parseOcticons, IParsedOcticons } from 'vs/base/common/octicon'; import { IMatch } from 'vs/base/common/filters'; import { Schemas } from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension, addClass } from 'vs/base/browser/dom'; const HELP_PREFIX = '?'; @@ -84,8 +82,8 @@ export class QuickOpenController extends Component implements IQuickOpenService private static readonly ID = 'workbench.component.quickopen'; - private _onShow: Emitter<void>; - private _onHide: Emitter<void>; + private readonly _onShow: Emitter<void>; + private readonly _onHide: Emitter<void>; private quickOpenWidget: QuickOpenWidget; private pickOpenWidget: QuickOpenWidget; @@ -206,7 +204,7 @@ export class QuickOpenController extends Component implements IQuickOpenService currentDecoration = !!message ? Severity.Error : void 0; const newPick = message || defaultMessage; if (newPick !== currentPick) { - options.valueSelection = [lastValue.length, lastValue.length]; + options.valueSelection = null; currentPick = newPick; resolve(new TPromise<any>(init)); } @@ -303,7 +301,7 @@ export class QuickOpenController extends Component implements IQuickOpenService // Create upon first open if (!this.pickOpenWidget) { this.pickOpenWidget = new QuickOpenWidget( - withElementById(this.partService.getWorkbenchElementId()).getHTMLElement(), + document.getElementById(this.partService.getWorkbenchElementId()), { onOk: () => { /* ignore, handle later */ }, onCancel: () => { /* ignore, handle later */ }, @@ -319,7 +317,7 @@ export class QuickOpenController extends Component implements IQuickOpenService this.toUnbind.push(attachQuickOpenStyler(this.pickOpenWidget, this.themeService, { background: SIDE_BAR_BACKGROUND, foreground: SIDE_BAR_FOREGROUND })); const pickOpenContainer = this.pickOpenWidget.create(); - DOM.addClass(pickOpenContainer, 'show-file-icons'); + addClass(pickOpenContainer, 'show-file-icons'); this.positionQuickOpenWidget(); } @@ -375,7 +373,7 @@ export class QuickOpenController extends Component implements IQuickOpenService picksPromiseDone = true; // Reset Progress - this.pickOpenWidget.getProgressBar().stop().getContainer().hide(); + this.pickOpenWidget.getProgressBar().stop().hide(); // Model const model = new QuickOpenModel([], new PickOpenActionProvider()); @@ -488,7 +486,7 @@ export class QuickOpenController extends Component implements IQuickOpenService // Progress if task takes a long time TPromise.timeout(800).then(() => { if (!picksPromiseDone && this.currentPickerToken === currentPickerToken) { - this.pickOpenWidget.getProgressBar().infinite().getContainer().show(); + this.pickOpenWidget.getProgressBar().infinite().show(); } }); @@ -558,7 +556,7 @@ export class QuickOpenController extends Component implements IQuickOpenService // Create upon first open if (!this.quickOpenWidget) { this.quickOpenWidget = new QuickOpenWidget( - withElementById(this.partService.getWorkbenchElementId()).getHTMLElement(), + document.getElementById(this.partService.getWorkbenchElementId()), { onOk: () => { /* ignore */ }, onCancel: () => { /* ignore */ }, @@ -575,7 +573,7 @@ export class QuickOpenController extends Component implements IQuickOpenService this.toUnbind.push(attachQuickOpenStyler(this.quickOpenWidget, this.themeService, { background: SIDE_BAR_BACKGROUND, foreground: SIDE_BAR_FOREGROUND })); const quickOpenContainer = this.quickOpenWidget.create(); - DOM.addClass(quickOpenContainer, 'show-file-icons'); + addClass(quickOpenContainer, 'show-file-icons'); this.positionQuickOpenWidget(); } @@ -624,11 +622,11 @@ export class QuickOpenController extends Component implements IQuickOpenService const titlebarOffset = this.partService.getTitleBarOffset(); if (this.quickOpenWidget) { - this.quickOpenWidget.getElement().style('top', `${titlebarOffset}px`); + this.quickOpenWidget.getElement().style.top = `${titlebarOffset}px`; } if (this.pickOpenWidget) { - this.pickOpenWidget.getElement().style('top', `${titlebarOffset}px`); + this.pickOpenWidget.getElement().style.top = `${titlebarOffset}px`; } } @@ -743,7 +741,7 @@ export class QuickOpenController extends Component implements IQuickOpenService // Reset Progress if (!instantProgress) { - this.quickOpenWidget.getProgressBar().stop().getContainer().hide(); + this.quickOpenWidget.getProgressBar().stop().hide(); } // Reset Extra Class @@ -785,7 +783,7 @@ export class QuickOpenController extends Component implements IQuickOpenService // Progress if task takes a long time TPromise.timeout(instantProgress ? 0 : 800).then(() => { if (!resultPromiseDone && currentResultToken === this.currentResultToken) { - this.quickOpenWidget.getProgressBar().infinite().getContainer().show(); + this.quickOpenWidget.getProgressBar().infinite().show(); } }); @@ -794,7 +792,7 @@ export class QuickOpenController extends Component implements IQuickOpenService resultPromiseDone = true; if (currentResultToken === this.currentResultToken) { - this.quickOpenWidget.getProgressBar().getContainer().hide(); + this.quickOpenWidget.getProgressBar().hide(); } }, (error: any) => { resultPromiseDone = true; @@ -1292,7 +1290,7 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry { } else { const resourceInput = input as IResourceInput; this.resource = resourceInput.resource; - this.label = getBaseLabel(resourceInput.resource); + this.label = labels.getBaseLabel(resourceInput.resource); this.description = labels.getPathLabel(resources.dirname(this.resource), contextService, environmentService); this.dirty = this.resource && this.textFileService.isDirty(this.resource); diff --git a/src/vs/workbench/browser/parts/quickopen/quickopen.contribution.ts b/src/vs/workbench/browser/parts/quickopen/quickopen.contribution.ts index bda6dcd994..f9cf3887bb 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickopen.contribution.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickopen.contribution.ts @@ -12,6 +12,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { RemoveFromEditorHistoryAction } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; import { QuickOpenSelectNextAction, QuickOpenSelectPreviousAction, inQuickOpenContext, getQuickNavigateHandler, QuickOpenNavigateNextAction, QuickOpenNavigatePreviousAction, defaultQuickOpenContext, QUICKOPEN_ACTION_ID, QUICKOPEN_ACION_LABEL } from 'vs/workbench/browser/parts/quickopen/quickopen'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'workbench.action.closeQuickOpen', @@ -21,6 +22,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: accessor => { const quickOpenService = accessor.get(IQuickOpenService); quickOpenService.close(); + const quickInputService = accessor.get(IQuickInputService); + return quickInputService.cancel(); } }); @@ -32,6 +35,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: accessor => { const quickOpenService = accessor.get(IQuickOpenService); quickOpenService.accept(); + const quickInputService = accessor.get(IQuickInputService); + return quickInputService.accept(); } }); @@ -43,10 +48,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: accessor => { const quickOpenService = accessor.get(IQuickOpenService); quickOpenService.focus(); + const quickInputService = accessor.get(IQuickInputService); + quickInputService.focus(); } }); -const registry = <IWorkbenchActionRegistry>Registry.as(ActionExtensions.WorkbenchActions); +const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions); const globalQuickOpenKeybinding = { primary: KeyMod.CtrlCmd | KeyCode.KEY_P, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E], mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_P, secondary: null } }; diff --git a/src/vs/workbench/browser/parts/quickopen/quickopen.ts b/src/vs/workbench/browser/parts/quickopen/quickopen.ts index 033b19222b..2cd9ba69b9 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickopen.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickopen.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index 1818c226f0..1396c906a6 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/sidebarpart'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { CompositePart } from 'vs/workbench/browser/parts/compositePart'; @@ -21,12 +21,14 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER } from 'vs/workbench/common/theme'; -import { Dimension } from 'vs/base/browser/builder'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension, EventType } from 'vs/base/browser/dom'; +import { $ } from 'vs/base/browser/builder'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; export class SidebarPart extends CompositePart<Viewlet> { @@ -75,11 +77,18 @@ export class SidebarPart extends CompositePart<Viewlet> { return this._onDidCompositeClose.event as Event<IViewlet>; } + public createTitleArea(parent: HTMLElement): HTMLElement { + const titleArea = super.createTitleArea(parent); + $(titleArea).on(EventType.CONTEXT_MENU, (e: MouseEvent) => this.onTitleAreaContextMenu(new StandardMouseEvent(e))); + + return titleArea; + } + public updateStyles(): void { super.updateStyles(); // Part container - const container = this.getContainer(); + const container = $(this.getContainer()); container.style('background-color', this.getColor(SIDE_BAR_BACKGROUND)); container.style('color', this.getColor(SIDE_BAR_FOREGROUND)); @@ -132,6 +141,23 @@ export class SidebarPart extends CompositePart<Viewlet> { return super.layout(dimension); } + + private onTitleAreaContextMenu(event: StandardMouseEvent): void { + const activeViewlet = this.getActiveViewlet() as Viewlet; + if (activeViewlet) { + const contextMenuActions = activeViewlet ? activeViewlet.getContextMenuActions() : []; + if (contextMenuActions.length) { + const anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + getActions: () => TPromise.as(contextMenuActions), + getActionItem: action => this.actionItemProvider(action as Action), + actionRunner: activeViewlet.getActionRunner(), + getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id) + }); + } + } + } } class FocusSideBarAction extends Action { diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css index d63db6f3a0..6658726079 100644 --- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css +++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css @@ -45,7 +45,7 @@ margin-left: 5px; } -.monaco-workbench > .part.statusbar > .statusbar-item a:not([disabled]):not(.disabled) { +.monaco-workbench > .part.statusbar > .statusbar-item a { cursor: pointer; display: inline-block; height: 100%; @@ -57,7 +57,7 @@ } .monaco-workbench > .part.statusbar > .statusbar-entry > span, -.monaco-workbench > .part.statusbar > .statusbar-entry > a:not([disabled]) { +.monaco-workbench > .part.statusbar > .statusbar-entry > a { padding: 0 5px 0 5px; white-space: pre; /* gives some degree of styling */ } @@ -67,6 +67,6 @@ font-size: 14px; } -.monaco-workbench > .part.statusbar > .statusbar-item a:hover:not([disabled]):not(.disabled) { +.monaco-workbench > .part.statusbar > .statusbar-item a:hover { text-decoration: none; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 5e7e54d3ba..3f0f15365f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -6,11 +6,11 @@ 'use strict'; import 'vs/css!./media/statusbarpart'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { TPromise } from 'vs/base/common/winjs.base'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { Builder, $ } from 'vs/base/browser/builder'; +import { $ } from 'vs/base/browser/builder'; import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import { Registry } from 'vs/platform/registry/common/platform'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -39,7 +39,7 @@ export class StatusbarPart extends Part implements IStatusbarService { private static readonly PRIORITY_PROP = 'priority'; private static readonly ALIGNMENT_PROP = 'alignment'; - private statusItemsContainer: Builder; + private statusItemsContainer: HTMLElement; private statusMsgDispose: IDisposable; private styleElement: HTMLStyleElement; @@ -67,7 +67,7 @@ export class StatusbarPart extends Part implements IStatusbarService { const toDispose = item.render(el); // Insert according to priority - const container = this.statusItemsContainer.getHTMLElement(); + const container = this.statusItemsContainer; const neighbours = this.getEntries(alignment); let inserted = false; for (let i = 0; i < neighbours.length; i++) { @@ -101,7 +101,7 @@ export class StatusbarPart extends Part implements IStatusbarService { private getEntries(alignment: StatusbarAlignment): HTMLElement[] { const entries: HTMLElement[] = []; - const container = this.statusItemsContainer.getHTMLElement(); + const container = this.statusItemsContainer; const children = container.children; for (let i = 0; i < children.length; i++) { const childElement = <HTMLElement>children.item(i); @@ -113,8 +113,8 @@ export class StatusbarPart extends Part implements IStatusbarService { return entries; } - public createContentArea(parent: Builder): Builder { - this.statusItemsContainer = $(parent); + public createContentArea(parent: HTMLElement): HTMLElement { + this.statusItemsContainer = parent; // Fill in initial items that were contributed from the registry const registry = Registry.as<IStatusbarRegistry>(Extensions.Statusbar); @@ -129,7 +129,7 @@ export class StatusbarPart extends Part implements IStatusbarService { const el = this.doCreateStatusItem(descriptor.alignment, descriptor.priority); const dispose = item.render(el); - this.statusItemsContainer.append(el); + this.statusItemsContainer.appendChild(el); return dispose; })); @@ -140,7 +140,7 @@ export class StatusbarPart extends Part implements IStatusbarService { protected updateStyles(): void { super.updateStyles(); - const container = this.getContainer(); + const container = $(this.getContainer()); // Background colors const backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND); @@ -334,12 +334,12 @@ class ManageExtensionAction extends Action { registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND); if (statusBarItemHoverBackground) { - collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:hover:not([disabled]):not(.disabled) { background-color: ${statusBarItemHoverBackground}; }`); + collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`); } const statusBarItemActiveBackground = theme.getColor(STATUS_BAR_ITEM_ACTIVE_BACKGROUND); if (statusBarItemActiveBackground) { - collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:active:not([disabled]):not(.disabled) { background-color: ${statusBarItemActiveBackground}; }`); + collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:active { background-color: ${statusBarItemActiveBackground}; }`); } const statusBarProminentItemBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_BACKGROUND); @@ -349,6 +349,6 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const statusBarProminentItemHoverBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND); if (statusBarProminentItemHoverBackground) { - collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a.status-bar-info:hover:not([disabled]):not(.disabled) { background-color: ${statusBarProminentItemHoverBackground}; }`); + collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a.status-bar-info:hover { background-color: ${statusBarProminentItemHoverBackground}; }`); } }); diff --git a/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css b/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css index 4c18f883d1..6e85bfd43d 100644 --- a/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css +++ b/src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css @@ -12,7 +12,7 @@ flex-shrink: 0; align-items: center; justify-content: center; - -webkit-user-select: none; + user-select: none; -webkit-app-region: drag; zoom: 1; /* prevent zooming */ line-height: 22px; diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index dc7f42e826..bc204f5ef9 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -7,8 +7,7 @@ import 'vs/css!./media/titlebarpart'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, $, Dimension } from 'vs/base/browser/builder'; -import * as DOM from 'vs/base/browser/dom'; +import { Builder, $ } from 'vs/base/browser/builder'; import * as paths from 'vs/base/common/paths'; import { Part } from 'vs/workbench/browser/part'; import { ITitleService, ITitleProperties } from 'vs/workbench/services/title/common/titleService'; @@ -22,7 +21,7 @@ import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/co import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as labels from 'vs/base/common/labels'; import { EditorInput, toResource } from 'vs/workbench/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -34,6 +33,7 @@ import { isMacintosh, isWindows } from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { trim } from 'vs/base/common/strings'; +import { addDisposableListener, EventType, EventHelper, Dimension } from 'vs/base/browser/dom'; export class TitlebarPart extends Part implements ITitleService { @@ -86,8 +86,8 @@ export class TitlebarPart extends Part implements ITitleService { } private registerListeners(): void { - this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onBlur())); - this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus())); + this.toUnbind.push(addDisposableListener(window, EventType.BLUR, () => this.onBlur())); + this.toUnbind.push(addDisposableListener(window, EventType.FOCUS, () => this.onFocus())); this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChanged(e))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.setTitle(this.getWindowTitle()))); @@ -226,7 +226,7 @@ export class TitlebarPart extends Part implements ITitleService { }); } - public createContentArea(parent: Builder): Builder { + public createContentArea(parent: HTMLElement): HTMLElement { this.titleContainer = $(parent); // Title @@ -236,16 +236,16 @@ export class TitlebarPart extends Part implements ITitleService { } // Maximize/Restore on doubleclick - this.titleContainer.on(DOM.EventType.DBLCLICK, (e) => { - DOM.EventHelper.stop(e); + this.titleContainer.on(EventType.DBLCLICK, (e) => { + EventHelper.stop(e); this.onTitleDoubleclick(); }); // Context menu on title - this.title.on([DOM.EventType.CONTEXT_MENU, DOM.EventType.MOUSE_DOWN], (e: MouseEvent) => { - if (e.type === DOM.EventType.CONTEXT_MENU || e.metaKey) { - DOM.EventHelper.stop(e); + this.title.on([EventType.CONTEXT_MENU, EventType.MOUSE_DOWN], (e: MouseEvent) => { + if (e.type === EventType.CONTEXT_MENU || e.metaKey) { + EventHelper.stop(e); this.onContextMenu(e); } @@ -253,7 +253,7 @@ export class TitlebarPart extends Part implements ITitleService { // Since the title area is used to drag the window, we do not want to steal focus from the // currently active element. So we restore focus after a timeout back to where it was. - this.titleContainer.on([DOM.EventType.MOUSE_DOWN], () => { + this.titleContainer.on([EventType.MOUSE_DOWN], () => { const active = document.activeElement; setTimeout(() => { if (active instanceof HTMLElement) { @@ -262,20 +262,19 @@ export class TitlebarPart extends Part implements ITitleService { }, 0 /* need a timeout because we are in capture phase */); }, void 0, true /* use capture to know the currently active element properly */); - return this.titleContainer; + return this.titleContainer.getHTMLElement(); } protected updateStyles(): void { super.updateStyles(); // Part container - const container = this.getContainer(); - if (container) { - container.style('color', this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_FOREGROUND : TITLE_BAR_ACTIVE_FOREGROUND)); - container.style('background-color', this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND)); + if (this.titleContainer) { + this.titleContainer.style('color', this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_FOREGROUND : TITLE_BAR_ACTIVE_FOREGROUND)); + this.titleContainer.style('background-color', this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND)); const titleBorder = this.getColor(TITLE_BAR_BORDER); - container.style('border-bottom', titleBorder ? `1px solid ${titleBorder}` : null); + this.titleContainer.style('border-bottom', titleBorder ? `1px solid ${titleBorder}` : null); } } diff --git a/src/vs/workbench/browser/parts/views/contributableViews.ts b/src/vs/workbench/browser/parts/views/contributableViews.ts new file mode 100644 index 0000000000..d6eea10e93 --- /dev/null +++ b/src/vs/workbench/browser/parts/views/contributableViews.ts @@ -0,0 +1,446 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { ViewsRegistry, IViewDescriptor, ViewLocation } from 'vs/workbench/common/views'; +import { IContextKeyService, IContextKeyChangeEvent, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; +import { Event, chain, filterEvent, Emitter } from 'vs/base/common/event'; +import { sortedDiff, firstIndex, move } from 'vs/base/common/arrays'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; + +function filterViewEvent(location: ViewLocation, event: Event<IViewDescriptor[]>): Event<IViewDescriptor[]> { + return chain(event) + .map(views => views.filter(view => view.location === location)) + .filter(views => views.length > 0) + .event; +} + +class CounterSet<T> implements IReadableSet<T> { + + private map = new Map<T, number>(); + + add(value: T): CounterSet<T> { + this.map.set(value, (this.map.get(value) || 0) + 1); + return this; + } + + delete(value: T): boolean { + let counter = this.map.get(value) || 0; + + if (counter === 0) { + return false; + } + + counter--; + + if (counter === 0) { + this.map.delete(value); + } else { + this.map.set(value, counter); + } + + return true; + } + + has(value: T): boolean { + return this.map.has(value); + } +} + +export interface IViewItem { + viewDescriptor: IViewDescriptor; + active: boolean; +} + +class ViewDescriptorCollection { + + private contextKeys = new CounterSet<string>(); + private items: IViewItem[] = []; + private disposables: IDisposable[] = []; + + private _onDidChange = new Emitter<void>(); + readonly onDidChange: Event<void> = this._onDidChange.event; + + get viewDescriptors(): IViewDescriptor[] { + return this.items + .filter(i => i.active) + .map(i => i.viewDescriptor); + } + + constructor( + location: ViewLocation, + @IContextKeyService private contextKeyService: IContextKeyService + ) { + const onRelevantViewsRegistered = filterViewEvent(location, ViewsRegistry.onViewsRegistered); + onRelevantViewsRegistered(this.onViewsRegistered, this, this.disposables); + + const onRelevantViewsDeregistered = filterViewEvent(location, ViewsRegistry.onViewsDeregistered); + onRelevantViewsDeregistered(this.onViewsDeregistered, this, this.disposables); + + const onRelevantContextChange = filterEvent(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys)); + onRelevantContextChange(this.onContextChanged, this); + + this.onViewsRegistered(ViewsRegistry.getViews(location)); + } + + private onViewsRegistered(viewDescriptors: IViewDescriptor[]): any { + let fireChangeEvent = false; + + for (const viewDescriptor of viewDescriptors) { + const item = { + viewDescriptor, + active: this.isViewDescriptorActive(viewDescriptor) // TODO: should read from some state? + }; + + this.items.push(item); + + if (viewDescriptor.when) { + for (const key of viewDescriptor.when.keys()) { + this.contextKeys.add(key); + } + } + + if (item.active) { + fireChangeEvent = true; + } + } + + if (fireChangeEvent) { + this._onDidChange.fire(); + } + } + + private onViewsDeregistered(viewDescriptors: IViewDescriptor[]): any { + let fireChangeEvent = false; + + for (const viewDescriptor of viewDescriptors) { + const index = firstIndex(this.items, i => i.viewDescriptor.id === viewDescriptor.id); + + if (index === -1) { + continue; + } + + const item = this.items[index]; + this.items.splice(index, 1); + + if (viewDescriptor.when) { + for (const key of viewDescriptor.when.keys()) { + this.contextKeys.delete(key); + } + } + + if (item.active) { + fireChangeEvent = true; + } + } + + if (fireChangeEvent) { + this._onDidChange.fire(); + } + } + + private onContextChanged(event: IContextKeyChangeEvent): any { + let fireChangeEvent = false; + + for (const item of this.items) { + const active = this.isViewDescriptorActive(item.viewDescriptor); + + if (item.active !== active) { + fireChangeEvent = true; + } + + item.active = active; + } + + if (fireChangeEvent) { + this._onDidChange.fire(); + } + } + + private isViewDescriptorActive(viewDescriptor: IViewDescriptor): boolean { + return !viewDescriptor.when || this.contextKeyService.contextMatchesRules(viewDescriptor.when); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + +export interface IView { + viewDescriptor: IViewDescriptor; + visible: boolean; +} + +export interface IViewState { + visible: boolean; + collapsed: boolean; + order?: number; + size?: number; +} + +export interface IViewDescriptorRef { + viewDescriptor: IViewDescriptor; + index: number; +} + +export interface IAddedViewDescriptorRef extends IViewDescriptorRef { + collapsed: boolean; + size?: number; +} + +export class ContributableViewsModel { + + readonly viewDescriptors: IViewDescriptor[] = []; + get visibleViewDescriptors(): IViewDescriptor[] { + return this.viewDescriptors.filter(v => this.viewStates.get(v.id).visible); + } + + private _onDidAdd = new Emitter<IAddedViewDescriptorRef>(); + readonly onDidAdd: Event<IAddedViewDescriptorRef> = this._onDidAdd.event; + + private _onDidRemove = new Emitter<IViewDescriptorRef>(); + readonly onDidRemove: Event<IViewDescriptorRef> = this._onDidRemove.event; + + private _onDidMove = new Emitter<{ from: IViewDescriptorRef; to: IViewDescriptorRef; }>(); + readonly onDidMove: Event<{ from: IViewDescriptorRef; to: IViewDescriptorRef; }> = this._onDidMove.event; + + private disposables: IDisposable[] = []; + + constructor( + location: ViewLocation, + @IContextKeyService contextKeyService: IContextKeyService, + protected viewStates = new Map<string, IViewState>() + ) { + const viewDescriptorCollection = new ViewDescriptorCollection(location, contextKeyService); + this.disposables.push(viewDescriptorCollection); + + viewDescriptorCollection.onDidChange(() => this.onDidChangeViewDescriptors(viewDescriptorCollection.viewDescriptors), this, this.disposables); + this.onDidChangeViewDescriptors(viewDescriptorCollection.viewDescriptors); + } + + isVisible(id: string): boolean { + const state = this.viewStates.get(id); + + if (!state) { + throw new Error(`Unknown view ${id}`); + } + + return state.visible; + } + + setVisible(id: string, visible: boolean): void { + const { visibleIndex, viewDescriptor, state } = this.find(id); + + if (!viewDescriptor.canToggleVisibility) { + throw new Error(`Can't toggle this view's visibility`); + } + + if (state.visible === visible) { + return; + } + + state.visible = visible; + + if (visible) { + this._onDidAdd.fire({ index: visibleIndex, viewDescriptor, size: state.size, collapsed: state.collapsed }); + } else { + this._onDidRemove.fire({ index: visibleIndex, viewDescriptor }); + } + } + + isCollapsed(id: string): boolean { + const state = this.viewStates.get(id); + + if (!state) { + throw new Error(`Unknown view ${id}`); + } + + return state.collapsed; + } + + setCollapsed(id: string, collapsed: boolean): void { + const { state } = this.find(id); + state.collapsed = collapsed; + } + + getSize(id: string): number | undefined { + const state = this.viewStates.get(id); + + if (!state) { + throw new Error(`Unknown view ${id}`); + } + + return state.size; + } + + setSize(id: string, size: number): void { + const { state } = this.find(id); + state.size = size; + } + + move(from: string, to: string): void { + const fromIndex = firstIndex(this.viewDescriptors, v => v.id === from); + const toIndex = firstIndex(this.viewDescriptors, v => v.id === to); + + const fromViewDescriptor = this.viewDescriptors[fromIndex]; + const toViewDescriptor = this.viewDescriptors[toIndex]; + + move(this.viewDescriptors, fromIndex, toIndex); + + for (let index = 0; index < this.viewDescriptors.length; index++) { + const state = this.viewStates.get(this.viewDescriptors[index].id); + state.order = index; + } + + this._onDidMove.fire({ + from: { index: fromIndex, viewDescriptor: fromViewDescriptor }, + to: { index: toIndex, viewDescriptor: toViewDescriptor } + }); + } + + private find(id: string): { index: number, visibleIndex: number, viewDescriptor: IViewDescriptor, state: IViewState } { + for (let i = 0, visibleIndex = 0; i < this.viewDescriptors.length; i++) { + const viewDescriptor = this.viewDescriptors[i]; + const state = this.viewStates.get(viewDescriptor.id); + + if (viewDescriptor.id === id) { + return { index: i, visibleIndex, viewDescriptor, state }; + } + + if (state.visible) { + visibleIndex++; + } + } + + throw new Error(`view descriptor ${id} not found`); + } + + private compareViewDescriptors(a: IViewDescriptor, b: IViewDescriptor): number { + const viewStateA = this.viewStates.get(a.id); + const viewStateB = this.viewStates.get(b.id); + + let orderA = viewStateA && viewStateA.order; + orderA = typeof orderA === 'number' ? orderA : a.order; + orderA = typeof orderA === 'number' ? orderA : Number.POSITIVE_INFINITY; + + let orderB = viewStateB && viewStateB.order; + orderB = typeof orderB === 'number' ? orderB : b.order; + orderB = typeof orderB === 'number' ? orderB : Number.POSITIVE_INFINITY; + + if (orderA !== orderB) { + return orderA - orderB; + } + + if (a.id === b.id) { + return 0; + } + + return a.id < b.id ? -1 : 1; + } + + private onDidChangeViewDescriptors(viewDescriptors: IViewDescriptor[]): void { + const ids = new Set<string>(); + + for (const viewDescriptor of this.viewDescriptors) { + ids.add(viewDescriptor.id); + } + + viewDescriptors = viewDescriptors.sort(this.compareViewDescriptors.bind(this)); + + for (const viewDescriptor of viewDescriptors) { + if (!this.viewStates.has(viewDescriptor.id)) { + this.viewStates.set(viewDescriptor.id, { + visible: true, + collapsed: false + }); + } + } + + const splices = sortedDiff<IViewDescriptor>( + this.viewDescriptors, + viewDescriptors, + this.compareViewDescriptors.bind(this) + ).reverse(); + + for (const splice of splices) { + const startViewDescriptor = this.viewDescriptors[splice.start]; + let startIndex = startViewDescriptor ? this.find(startViewDescriptor.id).visibleIndex : this.viewDescriptors.length; + + for (let i = 0; i < splice.deleteCount; i++) { + const viewDescriptor = this.viewDescriptors[splice.start + i]; + const { state } = this.find(viewDescriptor.id); + + if (state.visible) { + this._onDidRemove.fire({ index: startIndex, viewDescriptor }); + } + } + + for (let i = 0; i < splice.toInsert.length; i++) { + const viewDescriptor = splice.toInsert[i]; + const state = this.viewStates.get(viewDescriptor.id); + + if (state.visible) { + this._onDidAdd.fire({ index: startIndex++, viewDescriptor, size: state.size, collapsed: state.collapsed }); + } + } + } + + this.viewDescriptors.splice(0, this.viewDescriptors.length, ...viewDescriptors); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + +interface ISerializedViewState { + id: string; + state: IViewState; +} + +export class PersistentContributableViewsModel extends ContributableViewsModel { + + private viewletStateStorageId: string; + private storageService: IStorageService; + private contextService: IWorkspaceContextService; + + constructor( + location: ViewLocation, + viewletStateStorageId: string, + @IContextKeyService contextKeyService: IContextKeyService, + @IStorageService storageService: IStorageService, + @IWorkspaceContextService contextService: IWorkspaceContextService + ) { + const scope = contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL; + const raw = storageService.get(viewletStateStorageId, scope, '[]'); + const serializedViewsStates = JSON.parse(raw) as ISerializedViewState[]; + const viewStates = new Map<string, IViewState>(); + + for (const { id, state } of serializedViewsStates) { + viewStates.set(id, state); + } + + super(location, contextKeyService, viewStates); + + this.viewletStateStorageId = viewletStateStorageId; + this.storageService = storageService; + this.contextService = contextService; + } + + saveViewsStates(): void { + const serializedViewStates: ISerializedViewState[] = []; + this.viewStates.forEach((state, id) => serializedViewStates.push({ id, state })); + const raw = JSON.stringify(serializedViewStates); + + const scope = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL; + this.storageService.store(this.viewletStateStorageId, raw, scope); + } + + dispose(): void { + this.saveViewsStates(); + super.dispose(); + } +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index 3b9c5f6e24..98d8b08f1f 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -9,10 +9,9 @@ import { IDisposable, Disposable, dispose } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; import * as DOM from 'vs/base/browser/dom'; -import { $ } from 'vs/base/browser/builder'; import { LIGHT, FileThemeIcon, FolderThemeIcon } from 'vs/platform/theme/common/themeService'; import { ITree, IDataSource, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree'; -import { TreeItemCollapsibleState, ITreeItem, ITreeViewer, ICustomViewsService, ITreeViewDataProvider, ViewsRegistry, IViewDescriptor, TreeViewItemHandleArg, ICustomViewDescriptor, IViewsViewlet } from 'vs/workbench/common/views'; +import { TreeItemCollapsibleState, ITreeItem, ITreeViewer, IViewsService, ITreeViewDataProvider, ViewsRegistry, IViewDescriptor, TreeViewItemHandleArg, ICustomViewDescriptor, IViewsViewlet, ViewLocation } from 'vs/workbench/common/views'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; @@ -34,7 +33,7 @@ import { FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { isUndefinedOrNull } from 'vs/base/common/types'; -export class CustomViewsService extends Disposable implements ICustomViewsService { +export class CustomViewsService extends Disposable implements IViewsService { _serviceBrand: any; @@ -57,12 +56,16 @@ export class CustomViewsService extends Disposable implements ICustomViewsServic openView(id: string, focus: boolean): TPromise<void> { const viewDescriptor = ViewsRegistry.getView(id); if (viewDescriptor) { - return this.viewletService.openViewlet(viewDescriptor.id) - .then((viewlet: IViewsViewlet) => { - if (viewlet && viewlet.openView) { - viewlet.openView(id, focus); - } - }); + const viewletId = viewDescriptor.location === ViewLocation.SCM ? 'workbench.view.scm' : viewDescriptor.location.id; + const viewletDescriptor = this.viewletService.getViewlet(viewletId); + if (viewletDescriptor) { + return this.viewletService.openViewlet(viewletDescriptor.id) + .then((viewlet: IViewsViewlet) => { + if (viewlet && viewlet.openView) { + viewlet.openView(id, focus); + } + }); + } } return TPromise.as(null); } @@ -70,7 +73,7 @@ export class CustomViewsService extends Disposable implements ICustomViewsServic private createViewers(viewDescriptors: IViewDescriptor[]): void { for (const viewDescriptor of viewDescriptors) { if ((<ICustomViewDescriptor>viewDescriptor).treeView) { - this.viewers.set(viewDescriptor.id, this.instantiationService.createInstance(CustomTreeViewer, viewDescriptor.id)); + this.viewers.set(viewDescriptor.id, this.instantiationService.createInstance(CustomTreeViewer, viewDescriptor.id, viewDescriptor.location)); } } } @@ -111,6 +114,7 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { constructor( private id: string, + private location: ViewLocation, @IExtensionService private extensionService: IExtensionService, @IWorkbenchThemeService private themeService: IWorkbenchThemeService, @IInstantiationService private instantiationService: IInstantiationService, @@ -133,7 +137,7 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { onDidChange = dataProvider.onDidChange; onDispose = dataProvider.onDispose; getChildren(node?: ITreeItem): TPromise<ITreeItem[]> { - if (node.children) { + if (node && node.children) { return TPromise.as(node.children); } const promise = node instanceof Root ? dataProvider.getChildren() : dataProvider.getChildren(node); @@ -171,9 +175,9 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { if (this.tree) { if (this.isVisible) { - $(this.tree.getHTMLElement()).show(); + DOM.show(this.tree.getHTMLElement()); } else { - $(this.tree.getHTMLElement()).hide(); // make sure the tree goes out of the tabindex world by hiding it + DOM.hide(this.tree.getHTMLElement()); // make sure the tree goes out of the tabindex world by hiding it } if (this.isVisible) { @@ -198,7 +202,7 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { } // Pass Focus to Viewer - this.tree.DOMFocus(); + this.tree.domFocus(); } } @@ -213,7 +217,7 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { this.treeContainer = DOM.$('.tree-explorer-viewlet-tree-view'); const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : undefined; const menus = this.instantiationService.createInstance(Menus, this.id); - const dataSource = this.instantiationService.createInstance(TreeDataSource, this); + const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.getProgressLocation()); const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, actionItemProvider); const controller = this.instantiationService.createInstance(TreeController, this.id, menus); this.tree = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {}); @@ -223,6 +227,18 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { this.tree.setInput(this.root); } + private getProgressLocation(): ProgressLocation { + switch (this.location.id) { + case ViewLocation.Explorer.id: + return ProgressLocation.Explorer; + case ViewLocation.SCM.id: + return ProgressLocation.Scm; + case ViewLocation.Debug.id: + return null /* No debug progress location yet */; + } + return null; + } + layout(size: number) { if (this.tree) { this.treeContainer.style.height = size + 'px'; @@ -265,7 +281,7 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { return result.then(() => this.tree.reveal(item)) .then(() => { if (select) { - this.tree.setSelection([item]); + this.tree.setSelection([item], { source: 'api' }); } }); } @@ -287,6 +303,9 @@ class CustomTreeViewer extends Disposable implements ITreeViewer { } private onSelection({ payload }: any): void { + if (payload && payload.source === 'api') { + return; + } const selection: ITreeItem = this.tree.getSelection()[0]; if (selection) { if (selection.command) { @@ -306,6 +325,7 @@ class TreeDataSource implements IDataSource { constructor( private treeView: ITreeViewer, + private location: ProgressLocation, @IProgressService2 private progressService: IProgressService2 ) { } @@ -320,7 +340,7 @@ class TreeDataSource implements IDataSource { public getChildren(tree: ITree, node: ITreeItem): TPromise<any[]> { if (this.treeView.dataProvider) { - return this.progressService.withProgress({ location: ProgressLocation.Explorer }, () => this.treeView.dataProvider.getChildren(node)); + return this.location ? this.progressService.withProgress({ location: this.location }, () => this.treeView.dataProvider.getChildren(node)) : this.treeView.dataProvider.getChildren(node); } return TPromise.as([]); } @@ -406,7 +426,7 @@ class TreeRenderer implements IRenderer { templateData.actionBar.context = (<TreeViewItemHandleArg>{ $treeViewId: this.treeViewId, $treeItemHandle: node.handle }); templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false }); - templateData.aligner.align(node); + templateData.aligner.treeItem = node; } private getFileKind(node: ITreeItem): FileKind { @@ -430,7 +450,7 @@ class TreeRenderer implements IRenderer { class Aligner extends Disposable { - private node: ITreeItem; + private _treeItem: ITreeItem; constructor( private container: HTMLElement, @@ -438,65 +458,47 @@ class Aligner extends Disposable { private themeService: IWorkbenchThemeService ) { super(); - this._register(this.themeService.onDidFileIconThemeChange(() => this.alignByTheme())); + this._register(this.themeService.onDidFileIconThemeChange(() => this.render())); } - align(treeItem: ITreeItem): void { - this.node = treeItem; - this.alignByTheme(); + set treeItem(treeItem: ITreeItem) { + this._treeItem = treeItem; + this.render(); } - private alignByTheme(): void { - if (this.node) { - DOM.toggleClass(this.container, 'align-with-twisty', this.hasToAlignWithTwisty()); + private render(): void { + if (this._treeItem) { + DOM.toggleClass(this.container, 'align-icon-with-twisty', this.hasToAlignIconWithTwisty()); } } - private hasToAlignWithTwisty(): boolean { - if (this.hasParentHasIcon()) { + private hasToAlignIconWithTwisty(): boolean { + if (this._treeItem.collapsibleState !== TreeItemCollapsibleState.None) { return false; } + if (!this.hasIcon(this._treeItem)) { + return false; - const fileIconTheme = this.themeService.getFileIconTheme(); - if (!(fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons)) { + } + const parent: ITreeItem = this.tree.getNavigator(this._treeItem).parent() || this.tree.getInput(); + if (this.hasIcon(parent)) { return false; } - if (this.node.collapsibleState !== TreeItemCollapsibleState.None) { - return false; - } - const icon = this.themeService.getTheme().type === LIGHT ? this.node.icon : this.node.iconDark; - const hasIcon = !!icon || !!this.node.resourceUri; - if (!hasIcon) { - return false; - } - - const siblingsWithChildren = this.getSiblings().filter(s => s.collapsibleState !== TreeItemCollapsibleState.None); - for (const s of siblingsWithChildren) { - const icon = this.themeService.getTheme().type === LIGHT ? s.icon : s.iconDark; - if (icon) { - return false; - } - } - - return true; + return parent.children && parent.children.every(c => c.collapsibleState === TreeItemCollapsibleState.None || !this.hasIcon(c)); } - private getSiblings(): ITreeItem[] { - const parent: ITreeItem = this.tree.getNavigator(this.node).parent() || this.tree.getInput(); - return parent.children; - } - - private hasParentHasIcon(): boolean { - const parent = this.tree.getNavigator(this.node).parent() || this.tree.getInput(); - const icon = this.themeService.getTheme().type === LIGHT ? parent.icon : parent.iconDark; + private hasIcon(node: ITreeItem): boolean { + const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark; if (icon) { return true; } - if (parent.resourceUri) { + if (node.resourceUri || node.themeIcon) { const fileIconTheme = this.themeService.getFileIconTheme(); - if (fileIconTheme.hasFileIcons && fileIconTheme.hasFolderIcons) { - return true; + const isFolder = node.themeIcon ? node.themeIcon.id === FolderThemeIcon.id : node.collapsibleState !== TreeItemCollapsibleState.None; + if (isFolder) { + return fileIconTheme.hasFileIcons && fileIconTheme.hasFolderIcons; } + return fileIconTheme.hasFileIcons; } return false; } @@ -541,7 +543,7 @@ class TreeController extends WorkbenchTreeController { onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, diff --git a/src/vs/workbench/browser/parts/views/customViewPanel.ts b/src/vs/workbench/browser/parts/views/customViewPanel.ts index 982a171955..4c8720d8c7 100644 --- a/src/vs/workbench/browser/parts/views/customViewPanel.ts +++ b/src/vs/workbench/browser/parts/views/customViewPanel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/views'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose, empty as EmptyDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -14,7 +14,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; import { fillInActions, ContextAwareMenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { ICustomViewsService, ITreeViewer } from 'vs/workbench/common/views'; +import { IViewsService, ITreeViewer } from 'vs/workbench/common/views'; import { IViewletViewOptions, IViewOptions, ViewsViewletPanel } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -31,10 +31,10 @@ export class CustomTreeViewPanel extends ViewsViewletPanel { @IContextMenuService contextMenuService: IContextMenuService, @IInstantiationService private instantiationService: IInstantiationService, @IConfigurationService configurationService: IConfigurationService, - @ICustomViewsService customViewsService: ICustomViewsService, + @IViewsService viewsService: IViewsService, ) { super({ ...(options as IViewOptions), ariaHeaderLabel: options.name }, keybindingService, contextMenuService, configurationService); - this.treeViewer = customViewsService.getTreeViewer(this.id); + this.treeViewer = viewsService.getTreeViewer(this.id); this.disposables.push(toDisposable(() => this.treeViewer.setVisibility(false))); this.menus = this.instantiationService.createInstance(Menus, this.id); this.menus.onDidChangeTitle(() => this.updateActions(), this, this.disposables); diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index faef97aaad..9d2591d553 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -50,8 +50,11 @@ display: none; } -.tree-explorer-viewlet-tree-view.file-icon-themable-tree.align-icons-and-twisties .monaco-tree-row:not(.has-children) .content:not(.align-with-twisty)::before, -.tree-explorer-viewlet-tree-view.file-icon-themable-tree.hide-arrows .monaco-tree-row .content::before { +.tree-explorer-viewlet-tree-view.file-icon-themable-tree .monaco-tree-row .content.align-icon-with-twisty::before { + display: none; +} + +.tree-explorer-viewlet-tree-view.file-icon-themable-tree .monaco-tree-row .content:not(.align-icon-with-twisty)::before { display: inline-block; } diff --git a/src/vs/workbench/browser/parts/views/panelViewlet.ts b/src/vs/workbench/browser/parts/views/panelViewlet.ts index 960cfd2a29..71d49859c7 100644 --- a/src/vs/workbench/browser/parts/views/panelViewlet.ts +++ b/src/vs/workbench/browser/parts/views/panelViewlet.ts @@ -6,12 +6,11 @@ import 'vs/css!./media/panelviewlet'; import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, filterEvent } from 'vs/base/common/event'; +import { Event, Emitter, filterEvent } from 'vs/base/common/event'; import { ColorIdentifier, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { attachStyler, IColorMapping, IThemable } from 'vs/platform/theme/common/styler'; +import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler'; import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND } from 'vs/workbench/common/theme'; -import { Dimension, Builder } from 'vs/base/browser/builder'; -import { append, $, trackFocus, toggleClass, EventType, isAncestor } from 'vs/base/browser/dom'; +import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener } from 'vs/base/browser/dom'; import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; import { firstIndex } from 'vs/base/common/arrays'; import { IAction, IActionRunner } from 'vs/base/common/actions'; @@ -36,15 +35,6 @@ export interface IPanelColors extends IColorMapping { headerHighContrastBorder?: ColorIdentifier; } -export function attachPanelStyler(widget: IThemable, themeService: IThemeService) { - return attachStyler<IPanelColors>(themeService, { - headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND, - headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND, - headerHighContrastBorder: contrastBorder, - dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND - }, widget); -} - export interface IViewletPanelOptions extends IPanelOptions { actionRunner?: IActionRunner; } @@ -56,6 +46,9 @@ export abstract class ViewletPanel extends Panel { private _onDidFocus = new Emitter<void>(); readonly onDidFocus: Event<void> = this._onDidFocus.event; + private _onDidChangeTitleArea = new Emitter<void>(); + readonly onDidChangeTitleArea: Event<void> = this._onDidChangeTitleArea.event; + protected actionRunner: IActionRunner; protected toolbar: ToolBar; private headerContainer: HTMLElement; @@ -95,7 +88,7 @@ export abstract class ViewletPanel extends Panel { }); this.disposables.push(this.toolbar); - this.updateActions(); + this.setActions(); const onDidRelevantConfigurationChange = filterEvent(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewletPanel.AlwaysShowActionsConfig)); onDidRelevantConfigurationChange(this.updateActionsVisibility, this, this.disposables); @@ -110,16 +103,21 @@ export abstract class ViewletPanel extends Panel { this._onDidFocus.fire(); } - protected updateActions(): void { + private setActions(): void { this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions()))(); this.toolbar.context = this.getActionsContext(); } - protected updateActionsVisibility(): void { + private updateActionsVisibility(): void { const shouldAlwaysShowActions = this.configurationService.getValue<boolean>('workbench.view.alwaysShowHeaderActions'); toggleClass(this.headerContainer, 'actions-always-visible', shouldAlwaysShowActions); } + protected updateActions(): void { + this.setActions(); + this._onDidChangeTitleArea.fire(); + } + getActions(): IAction[] { return []; } @@ -160,6 +158,10 @@ export class PanelViewlet extends Viewlet { return this.panelview.onDidSashChange; } + protected get panels(): ViewletPanel[] { + return this.panelItems.map(i => i.panel); + } + protected get length(): number { return this.panelItems.length; } @@ -175,13 +177,12 @@ export class PanelViewlet extends Viewlet { super(id, partService, telemetryService, themeService); } - async create(parent: Builder): TPromise<void> { + async create(parent: HTMLElement): TPromise<void> { super.create(parent); - const container = parent.getHTMLElement(); - this.panelview = this._register(new PanelView(container, this.options)); + this.panelview = this._register(new PanelView(parent, this.options)); this._register(this.panelview.onDidDrop(({ from, to }) => this.movePanel(from as ViewletPanel, to as ViewletPanel))); - this._register(parent.on(EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e)))); + this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e)))); } private showContextMenu(event: StandardMouseEvent): void { @@ -228,6 +229,14 @@ export class PanelViewlet extends Viewlet { return []; } + getActionItem(action: IAction): IActionItem { + if (this.isSingleView()) { + return this.panelItems[0].panel.getActionItem(action); + } + + return super.getActionItem(action); + } + focus(): void { super.focus(); @@ -254,26 +263,58 @@ export class PanelViewlet extends Viewlet { return Math.max(...sizes); } - addPanel(panel: ViewletPanel, size: number, index = this.panelItems.length - 1): void { + addPanels(panels: { panel: ViewletPanel, size: number, index?: number }[]): void { + const wasSingleView = this.isSingleView(); + + for (const { panel, size, index } of panels) { + this.addPanel(panel, size, index); + } + + this.updateViewHeaders(); + if (this.isSingleView() !== wasSingleView) { + this.updateTitleArea(); + } + } + + private addPanel(panel: ViewletPanel, size: number, index = this.panelItems.length - 1): void { const disposables: IDisposable[] = []; const onDidFocus = panel.onDidFocus(() => this.lastFocusedPanel = panel, null, disposables); + const onDidChangeTitleArea = panel.onDidChangeTitleArea(() => { + if (this.isSingleView()) { + this.updateTitleArea(); + } + }, null, disposables); const onDidChange = panel.onDidChange(() => { if (panel === this.lastFocusedPanel && !panel.isExpanded()) { this.lastFocusedPanel = undefined; } }, null, disposables); - const styler = attachPanelStyler(panel, this.themeService); - const disposable = combinedDisposable([onDidFocus, styler, onDidChange]); + + const panelStyler = attachStyler<IPanelColors>(this.themeService, { + headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND, + headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND, + headerHighContrastBorder: index === 0 ? null : contrastBorder, + dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND + }, panel); + const disposable = combinedDisposable([onDidFocus, onDidChangeTitleArea, panelStyler, onDidChange]); const panelItem: IViewletPanelItem = { panel, disposable }; this.panelItems.splice(index, 0, panelItem); this.panelview.addPanel(panel, size, index); - - this.updateViewHeaders(); - this.updateTitleArea(); } - removePanel(panel: ViewletPanel): void { + removePanels(panels: ViewletPanel[]): void { + const wasSingleView = this.isSingleView(); + + panels.forEach(panel => this.removePanel(panel)); + + this.updateViewHeaders(); + if (wasSingleView !== this.isSingleView()) { + this.updateTitleArea(); + } + } + + private removePanel(panel: ViewletPanel): void { const index = firstIndex(this.panelItems, i => i.panel === panel); if (index === -1) { @@ -288,8 +329,6 @@ export class PanelViewlet extends Viewlet { const [panelItem] = this.panelItems.splice(index, 1); panelItem.disposable.dispose(); - this.updateViewHeaders(); - this.updateTitleArea(); } movePanel(from: ViewletPanel, to: ViewletPanel): void { @@ -336,4 +375,4 @@ export class PanelViewlet extends Viewlet { this.panelItems.forEach(i => i.disposable.dispose()); this.panelview.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 52a4cb2b00..2da57f1af7 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -6,7 +6,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import * as DOM from 'vs/base/browser/dom'; -import { $, Dimension, Builder } from 'vs/base/browser/builder'; import { Scope } from 'vs/workbench/common/memento'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IAction, IActionRunner } from 'vs/base/common/actions'; @@ -24,11 +23,11 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { IContextKeyService, IContextKeyChangeEvent } from 'vs/platform/contextkey/common/contextkey'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { PanelViewlet, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet'; -import { IPanelOptions } from 'vs/base/browser/ui/splitview/panelview'; +import { IPanelOptions, DefaultPanelDndController } from 'vs/base/browser/ui/splitview/panelview'; import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { localize } from 'vs/nls'; @@ -137,9 +136,9 @@ export abstract class TreeViewsViewletPanel extends ViewsViewletPanel { } if (isVisible) { - $(tree.getHTMLElement()).show(); + DOM.show(tree.getHTMLElement()); } else { - $(tree.getHTMLElement()).hide(); // make sure the tree goes out of the tabindex world by hiding it + DOM.hide(tree.getHTMLElement()); // make sure the tree goes out of the tabindex world by hiding it } if (isVisible) { @@ -161,7 +160,7 @@ export abstract class TreeViewsViewletPanel extends ViewsViewletPanel { } // Pass Focus to Viewer - this.tree.DOMFocus(); + this.tree.domFocus(); } dispose(): void { @@ -190,11 +189,11 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { private readonly viewsContextKeys: Set<string> = new Set<string>(); private viewsViewletPanels: ViewsViewletPanel[] = []; private didLayout = false; - private dimension: Dimension; + private dimension: DOM.Dimension; protected viewsStates: Map<string, IViewState> = new Map<string, IViewState>(); private areExtensionsReady: boolean = false; - private _onDidChangeViewVisibilityState: Emitter<string> = new Emitter<string>(); + private readonly _onDidChangeViewVisibilityState: Emitter<string> = new Emitter<string>(); readonly onDidChangeViewVisibilityState: Event<string> = this._onDidChangeViewVisibilityState.event; constructor( @@ -210,12 +209,12 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { @IContextMenuService protected contextMenuService: IContextMenuService, @IExtensionService protected extensionService: IExtensionService ) { - super(id, { showHeaderInTitleWhenSingleView, dnd: true }, partService, contextMenuService, telemetryService, themeService); + super(id, { showHeaderInTitleWhenSingleView, dnd: new DefaultPanelDndController() }, partService, contextMenuService, telemetryService, themeService); this.viewletSettings = this.getMemento(storageService, Scope.WORKSPACE); } - async create(parent: Builder): TPromise<void> { + async create(parent: HTMLElement): TPromise<void> { await super.create(parent); this._register(this.onDidSashChange(() => this.snapshotViewsStates())); @@ -276,7 +275,7 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { } } - layout(dimension: Dimension): void { + layout(dimension: DOM.Dimension): void { super.layout(dimension); this.dimension = dimension; if (this.didLayout) { @@ -371,14 +370,15 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { this.snapshotViewsStates(); if (toRemove.length) { - for (const viewDescriptor of toRemove) { - let view = this.getView(viewDescriptor.id); - this.removePanel(view); - this.viewsViewletPanels.splice(this.viewsViewletPanels.indexOf(view), 1); - view.dispose(); + const panelsToRemove: ViewsViewletPanel[] = toRemove.map(viewDescriptor => this.getView(viewDescriptor.id)); + this.removePanels(panelsToRemove); + for (const panel of panelsToRemove) { + this.viewsViewletPanels.splice(this.viewsViewletPanels.indexOf(panel), 1); + panel.dispose(); } } + const panelsToAdd: { panel: ViewsViewletPanel, size: number, index: number }[] = []; for (const viewDescriptor of toAdd) { let viewState = this.viewsStates.get(viewDescriptor.id); let index = visible.indexOf(viewDescriptor); @@ -393,8 +393,13 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { toCreate.push(view); const size = (viewState && viewState.size) || 200; - this.addPanel(view, size, index); - this.viewsViewletPanels.splice(index, 0, view); + panelsToAdd.push({ panel: view, size, index }); + } + + this.addPanels(panelsToAdd); + + for (const { panel, index } of panelsToAdd) { + this.viewsViewletPanels.splice(index, 0, panel); } return TPromise.join(toCreate.map(view => view.create())) @@ -545,19 +550,17 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { return false; } - if (ViewLocation.getContributedViewLocation(this.location.id)) { - let visibleViewsCount = 0; - if (this.areExtensionsReady) { - visibleViewsCount = this.getViewDescriptorsFromRegistry().reduce((visibleViewsCount, v) => visibleViewsCount + (this.canBeVisible(v) ? 1 : 0), 0); - } else { + if (ViewLocation.get(this.location.id)) { + if (!this.areExtensionsReady) { + let visibleViewsCount = 0; // Check in cache so that view do not jump. See #29609 this.viewsStates.forEach((viewState, id) => { if (!viewState.isHidden) { visibleViewsCount++; } }); + return visibleViewsCount === 1; } - return visibleViewsCount === 1; } return super.isSingleView(); @@ -603,18 +606,17 @@ export class ViewsViewlet extends PanelViewlet implements IViewsViewlet { } const collapsed = !view.isExpanded(); - const order = this.viewsViewletPanels.indexOf(view); const panelSize = this.getPanelSize(view); + // Do not save order because views can come late. if (currentState) { currentState.collapsed = collapsed; currentState.size = collapsed ? currentState.size : panelSize; - currentState.order = order; } else { this.viewsStates.set(view.id, { collapsed, size: this.didLayout ? panelSize : void 0, isHidden: false, - order, + order: void 0 }); } } @@ -645,7 +647,7 @@ export class PersistentViewsViewlet extends ViewsViewlet { this._register(this.onDidChangeViewVisibilityState(id => this.onViewVisibilityChanged(id))); } - create(parent: Builder): TPromise<void> { + create(parent: HTMLElement): TPromise<void> { this.loadViewsStates(); return super.create(parent); } diff --git a/src/vs/workbench/browser/quickopen.ts b/src/vs/workbench/browser/quickopen.ts index 31aab6b2ac..2734503093 100644 --- a/src/vs/workbench/browser/quickopen.ts +++ b/src/vs/workbench/browser/quickopen.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import * as objects from 'vs/base/common/objects'; -import arrays = require('vs/base/common/arrays'); -import strings = require('vs/base/common/strings'); -import types = require('vs/base/common/types'); -import errors = require('vs/base/common/errors'); +import * as arrays from 'vs/base/common/arrays'; +import * as strings from 'vs/base/common/strings'; +import * as types from 'vs/base/common/types'; +import * as errors from 'vs/base/common/errors'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action } from 'vs/base/common/actions'; import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen'; diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 4c4f1111e3..5cd1a7e128 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -3,9 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import DOM = require('vs/base/browser/dom'); +import * as DOM from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; import { Action, IAction } from 'vs/base/common/actions'; import { ITree } from 'vs/base/parts/tree/browser/tree'; @@ -154,7 +154,7 @@ export class ToggleViewletAction extends Action { const activeViewlet = this.viewletService.getActiveViewlet(); const activeElement = document.activeElement; - return activeViewlet && activeElement && DOM.isAncestor(activeElement, (<Viewlet>activeViewlet).getContainer().getHTMLElement()); + return activeViewlet && activeElement && DOM.isAncestor(activeElement, (<Viewlet>activeViewlet).getContainer()); } } @@ -170,7 +170,7 @@ export class CollapseAction extends Action { viewer.collapseAll(); viewer.clearSelection(); viewer.clearFocus(); - viewer.DOMFocus(); + viewer.domFocus(); viewer.focusFirst(); return TPromise.as(null); diff --git a/src/vs/workbench/common/actions.ts b/src/vs/workbench/common/actions.ts index 81407239ba..0329064b3f 100644 --- a/src/vs/workbench/common/actions.ts +++ b/src/vs/workbench/common/actions.ts @@ -96,21 +96,21 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR } private _triggerAndDisposeAction(instantitationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Thenable<void> { - const actionInstance = instantitationService.createInstance(descriptor.syncDescriptor); - actionInstance.label = descriptor.label || actionInstance.label; - - // don't run the action when not enabled - if (!actionInstance.enabled) { - actionInstance.dispose(); - - return void 0; - } - - const from = args && args.from || 'keybinding'; - // run action when workbench is created return lifecycleService.when(LifecyclePhase.Running).then(() => { + const actionInstance = instantitationService.createInstance(descriptor.syncDescriptor); try { + actionInstance.label = descriptor.label || actionInstance.label; + + // don't run the action when not enabled + if (!actionInstance.enabled) { + actionInstance.dispose(); + + return void 0; + } + + const from = args && args.from || 'keybinding'; + return TPromise.as(actionInstance.run(undefined, { from })).then(() => { actionInstance.dispose(); }, (err) => { @@ -124,4 +124,3 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR }); } }); - diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index d89939fe4c..e6c373f925 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -5,9 +5,9 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import * as objects from 'vs/base/common/objects'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; @@ -17,6 +17,7 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITextModel } from 'vs/editor/common/model'; import { Schemas } from 'vs/base/common/network'; +import { LRUCache } from 'vs/base/common/map'; export const TextCompareEditorVisible = new RawContextKey<boolean>('textCompareEditorVisible', false); @@ -31,8 +32,6 @@ export enum ConfirmResult { */ export const TEXT_DIFF_EDITOR_ID = 'workbench.editors.textDiffEditor'; -export const PREFERENCES_EDITOR_ID = 'workbench.editor.preferencesEditor'; - /** * Binary diff editor id. */ @@ -96,7 +95,7 @@ export interface IEditorInputFactory { * Each editor input is mapped to an editor that is capable of opening it through the Platform facade. */ export abstract class EditorInput implements IEditorInput { - private _onDispose: Emitter<void>; + private readonly _onDispose: Emitter<void>; protected _onDidChangeDirty: Emitter<void>; protected _onDidChangeLabel: Emitter<void>; @@ -486,7 +485,7 @@ export interface ITextEditorModel extends IEditorModel { * are typically cached for some while because they are expensive to construct. */ export class EditorModel extends Disposable implements IEditorModel { - private _onDispose: Emitter<void>; + private readonly _onDispose: Emitter<void>; constructor() { super(); @@ -919,6 +918,114 @@ export function toResource(editor: IEditorInput, options?: IResourceOptions): UR return null; } +export interface IEditorViewStates<T> { + [Position.ONE]?: T; + [Position.TWO]?: T; + [Position.THREE]?: T; +} + +export class EditorViewStateMemento<T> { + private cache: LRUCache<string, IEditorViewStates<T>>; + + constructor(private memento: object, private key: string, private limit: number = 10) { } + + public saveState(resource: URI, position: Position, state: T): void; + public saveState(editor: EditorInput, position: Position, state: T): void; + public saveState(resourceOrEditor: URI | EditorInput, position: Position, state: T): void { + if (typeof position !== 'number') { + return; // we need a position at least + } + + const resource = this.doGetResource(resourceOrEditor); + if (resource) { + const cache = this.doLoad(); + + let viewStates = cache.get(resource.toString()); + if (!viewStates) { + viewStates = Object.create(null) as IEditorViewStates<T>; + cache.set(resource.toString(), viewStates); + } + + viewStates[position] = state; + + // Automatically clear when editor input gets disposed if any + if (resourceOrEditor instanceof EditorInput) { + once(resourceOrEditor.onDispose)(() => { + this.clearState(resource); + }); + } + } + } + + public loadState(resource: URI, position: Position): T; + public loadState(editor: EditorInput, position: Position): T; + public loadState(resourceOrEditor: URI | EditorInput, position: Position): T { + if (typeof position !== 'number') { + return void 0; // we need a position at least + } + + const resource = this.doGetResource(resourceOrEditor); + if (resource) { + const cache = this.doLoad(); + + const viewStates = cache.get(resource.toString()); + if (viewStates) { + return viewStates[position]; + } + } + + return void 0; + } + + public clearState(resource: URI): void; + public clearState(editor: EditorInput): void; + public clearState(resourceOrEditor: URI | EditorInput): void { + const resource = this.doGetResource(resourceOrEditor); + if (resource) { + const cache = this.doLoad(); + cache.delete(resource.toString()); + } + } + + private doGetResource(resourceOrEditor: URI | EditorInput): URI { + if (resourceOrEditor instanceof EditorInput) { + return resourceOrEditor.getResource(); + } + + return resourceOrEditor; + } + + private doLoad(): LRUCache<string, IEditorViewStates<T>> { + if (!this.cache) { + this.cache = new LRUCache<string, T>(this.limit); + + // Restore from serialized map state + const rawViewState = this.memento[this.key]; + if (Array.isArray(rawViewState)) { + this.cache.fromJSON(rawViewState); + } + + // Migration from old object state + else if (rawViewState) { + const keys = Object.keys(rawViewState); + keys.forEach((key, index) => { + if (index < this.limit) { + this.cache.set(key, rawViewState[key]); + } + }); + } + } + + return this.cache; + } + + public save(): void { + const cache = this.doLoad(); + + this.memento[this.key] = cache.toJSON(); + } +} + class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { private instantiationService: IInstantiationService; private fileInputFactory: IFileInputFactory; diff --git a/src/vs/workbench/common/editor/editorStacksModel.ts b/src/vs/workbench/common/editor/editorStacksModel.ts index 576dbc3266..37b9fe0e8f 100644 --- a/src/vs/workbench/common/editor/editorStacksModel.ts +++ b/src/vs/workbench/common/editor/editorStacksModel.ts @@ -5,7 +5,7 @@ 'use strict'; -import Event, { Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorStacksModel, IEditorGroup, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IStacksModelChangeEvent, EditorOpenPositioning, SideBySideEditorInput, OPEN_POSITIONING_CONFIG } from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -65,17 +65,17 @@ export class EditorGroup implements IEditorGroup { private toDispose: IDisposable[]; private editorOpenPositioning: 'left' | 'right' | 'first' | 'last'; - private _onEditorActivated: Emitter<EditorInput>; - private _onEditorOpened: Emitter<EditorInput>; - private _onEditorClosed: Emitter<EditorCloseEvent>; - private _onEditorDisposed: Emitter<EditorInput>; - private _onEditorDirty: Emitter<EditorInput>; - private _onEditorLabelChange: Emitter<EditorInput>; - private _onEditorMoved: Emitter<EditorInput>; - private _onEditorPinned: Emitter<EditorInput>; - private _onEditorUnpinned: Emitter<EditorInput>; - private _onEditorStateChanged: Emitter<EditorInput>; - private _onEditorsStructureChanged: Emitter<EditorInput>; + private readonly _onEditorActivated: Emitter<EditorInput>; + private readonly _onEditorOpened: Emitter<EditorInput>; + private readonly _onEditorClosed: Emitter<EditorCloseEvent>; + private readonly _onEditorDisposed: Emitter<EditorInput>; + private readonly _onEditorDirty: Emitter<EditorInput>; + private readonly _onEditorLabelChange: Emitter<EditorInput>; + private readonly _onEditorMoved: Emitter<EditorInput>; + private readonly _onEditorPinned: Emitter<EditorInput>; + private readonly _onEditorUnpinned: Emitter<EditorInput>; + private readonly _onEditorStateChanged: Emitter<EditorInput>; + private readonly _onEditorsStructureChanged: Emitter<EditorInput>; constructor( arg1: string | ISerializedEditorGroup, @@ -732,22 +732,22 @@ export class EditorStacksModel implements IEditorStacksModel { private _activeGroup: EditorGroup; private groupToIdentifier: { [id: number]: EditorGroup }; - private _onGroupOpened: Emitter<EditorGroup>; - private _onGroupClosed: Emitter<EditorGroup>; - private _onGroupMoved: Emitter<EditorGroup>; - private _onGroupActivated: Emitter<EditorGroup>; - private _onGroupDeactivated: Emitter<EditorGroup>; - private _onGroupRenamed: Emitter<EditorGroup>; + private readonly _onGroupOpened: Emitter<EditorGroup>; + private readonly _onGroupClosed: Emitter<EditorGroup>; + private readonly _onGroupMoved: Emitter<EditorGroup>; + private readonly _onGroupActivated: Emitter<EditorGroup>; + private readonly _onGroupDeactivated: Emitter<EditorGroup>; + private readonly _onGroupRenamed: Emitter<EditorGroup>; - private _onEditorDisposed: Emitter<EditorIdentifier>; - private _onEditorDirty: Emitter<EditorIdentifier>; - private _onEditorLabelChange: Emitter<EditorIdentifier>; - private _onEditorOpened: Emitter<EditorIdentifier>; + private readonly _onEditorDisposed: Emitter<EditorIdentifier>; + private readonly _onEditorDirty: Emitter<EditorIdentifier>; + private readonly _onEditorLabelChange: Emitter<EditorIdentifier>; + private readonly _onEditorOpened: Emitter<EditorIdentifier>; - private _onWillCloseEditor: Emitter<EditorCloseEvent>; - private _onEditorClosed: Emitter<EditorCloseEvent>; + private readonly _onWillCloseEditor: Emitter<EditorCloseEvent>; + private readonly _onEditorClosed: Emitter<EditorCloseEvent>; - private _onModelChanged: Emitter<IStacksModelChangeEvent>; + private readonly _onModelChanged: Emitter<IStacksModelChangeEvent>; constructor( private restoreFromStorage: boolean, diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 1c02449e25..38ce13e38b 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -8,16 +8,16 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { suggestFilename } from 'vs/base/common/mime'; import { memoize } from 'vs/base/common/decorators'; -import labels = require('vs/base/common/labels'); +import * as labels from 'vs/base/common/labels'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; import { EditorInput, IEncodingSupport, EncodingMode, ConfirmResult } from 'vs/workbench/common/editor'; import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetryUtils'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -35,8 +35,8 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport private cachedModel: UntitledEditorModel; private modelResolve: TPromise<UntitledEditorModel>; - private _onDidModelChangeContent: Emitter<void>; - private _onDidModelChangeEncoding: Emitter<void>; + private readonly _onDidModelChangeContent: Emitter<void>; + private readonly _onDidModelChangeEncoding: Emitter<void>; private toUnbind: IDisposable[]; diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 6241181946..df2f748c27 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -14,7 +14,7 @@ import { CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/file import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IMode } from 'vs/editor/common/modes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; @@ -28,9 +28,9 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private toDispose: IDisposable[]; private dirty: boolean; - private _onDidChangeContent: Emitter<void>; - private _onDidChangeDirty: Emitter<void>; - private _onDidChangeEncoding: Emitter<void>; + private readonly _onDidChangeContent: Emitter<void>; + private readonly _onDidChangeDirty: Emitter<void>; + private readonly _onDidChangeEncoding: Emitter<void>; private versionId: number; diff --git a/src/vs/workbench/common/memento.ts b/src/vs/workbench/common/memento.ts index 4110a2a778..1a82cd2fb5 100644 --- a/src/vs/workbench/common/memento.ts +++ b/src/vs/workbench/common/memento.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; /** diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index 9c1ac7426a..d4c88347b0 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -7,7 +7,7 @@ import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import Event, {Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { isPromiseCanceledError, isErrorWithActions } from 'vs/base/common/errors'; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 2d4ed86803..ee86974149 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -6,8 +6,7 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import { basename } from 'vs/base/common/paths'; +import * as paths from 'vs/base/common/paths'; import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IFileService } from 'vs/platform/files/common/files'; @@ -47,7 +46,7 @@ export class ResourceContextKey implements IContextKey<URI> { set(value: URI) { this._resourceKey.set(value); this._schemeKey.set(value && value.scheme); - this._filenameKey.set(value && basename(value.fsPath)); + this._filenameKey.set(value && paths.basename(value.fsPath)); this._langIdKey.set(value && this._modeService.getModeIdByFilenameOrFirstLine(value.fsPath)); this._extensionKey.set(value && paths.extname(value.fsPath)); this._hasResource.set(!!value); diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 199223e26e..39d1c875c7 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable, Disposable, dispose } from 'vs/base/common/lifecycle'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; @@ -361,7 +361,7 @@ export const TITLE_BAR_INACTIVE_BACKGROUND = registerColor('titleBar.inactiveBac export const TITLE_BAR_BORDER = registerColor('titleBar.border', { dark: null, light: null, - hc: null + hc: contrastBorder }, nls.localize('titleBarBorder', "Title bar border color. Note that this color is currently only supported on macOS.")); // < --- Notifications --- > diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 5b641a3d7e..5f28d6853f 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Command } from 'vs/editor/common/modes'; import { UriComponents } from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ITreeViewDataProvider } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; @@ -17,24 +17,24 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export class ViewLocation { - static readonly Explorer = new ViewLocation('workbench.view.explorer'); - static readonly Debug = new ViewLocation('workbench.view.debug'); - static readonly Extensions = new ViewLocation('workbench.view.extensions'); - - constructor(private _id: string) { + private static locations: Map<string, ViewLocation> = new Map<string, ViewLocation>(); + static register(id: string): ViewLocation { + const viewLocation = new ViewLocation(id); + ViewLocation.locations.set(id, viewLocation); + return viewLocation; + } + static get(value: string): ViewLocation { + return ViewLocation.locations.get(value); } - get id(): string { - return this._id; - } + static readonly Explorer: ViewLocation = ViewLocation.register('workbench.view.explorer'); + static readonly Debug: ViewLocation = ViewLocation.register('workbench.view.debug'); + static readonly Extensions: ViewLocation = ViewLocation.register('workbench.view.extensions'); + static readonly SCM: ViewLocation = ViewLocation.register('workbench.view.scm.views.contributed'); + + private constructor(private _id: string) { } + get id(): string { return this._id; } - static getContributedViewLocation(value: string): ViewLocation { - switch (value) { - case 'explorer': return ViewLocation.Explorer; - case 'debug': return ViewLocation.Debug; - } - return void 0; - } } export interface IViewDescriptor { @@ -79,10 +79,10 @@ export interface IViewsRegistry { export const ViewsRegistry: IViewsRegistry = new class implements IViewsRegistry { - private _onViewsRegistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>(); + private readonly _onViewsRegistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>(); readonly onViewsRegistered: Event<IViewDescriptor[]> = this._onViewsRegistered.event; - private _onViewsDeregistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>(); + private readonly _onViewsDeregistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>(); readonly onViewsDeregistered: Event<IViewDescriptor[]> = this._onViewsDeregistered.event; private _viewLocations: ViewLocation[] = []; @@ -182,9 +182,9 @@ export interface ICustomViewDescriptor extends IViewDescriptor { } -export const ICustomViewsService = createDecorator<ICustomViewsService>('customViewsService'); +export const IViewsService = createDecorator<IViewsService>('viewsService'); -export interface ICustomViewsService { +export interface IViewsService { _serviceBrand: any; getTreeViewer(id: string): ITreeViewer; diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 11920a8664..561023c2c4 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -11,15 +11,15 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import { IWindowService, IWindowsService, MenuBarVisibility } from 'vs/platform/windows/common/windows'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import { isMacintosh, isLinux } from 'vs/base/common/platform'; import { IQuickOpenService, IFilePickOpenEntry, ISeparator, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen'; import * as browser from 'vs/base/browser/browser'; @@ -871,6 +871,24 @@ export class OpenIssueReporterAction extends Action { } } +export class OpenProcessExplorer extends Action { + public static readonly ID = 'workbench.action.openProcessExplorer'; + public static readonly LABEL = nls.localize('openProcessExplorer', "Open Process Explorer"); + + constructor( + id: string, + label: string, + @IWorkbenchIssueService private issueService: IWorkbenchIssueService + ) { + super(id, label); + } + + public run(): TPromise<boolean> { + return this.issueService.openProcessExplorer() + .then(() => true); + } +} + export class ReportPerformanceIssueUsingReporterAction extends Action { public static readonly ID = 'workbench.action.reportPerformanceIssueUsingReporter'; public static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue"); diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index 7aa5f27d6b..ddb862c704 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -28,9 +28,11 @@ process.lazyEnv = new Promise(function (resolve) { assign(process.env, shellEnv); resolve(process.env); }); - ipc.send('vscode:fetchShellEnv', remote.getCurrentWindow().id); + ipc.send('vscode:fetchShellEnv'); }); +Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) + function onError(error, enableDeveloperTools) { if (enableDeveloperTools) { remote.getCurrentWebContents().openDevTools(); @@ -160,10 +162,10 @@ function main() { const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; const originalResolveLookupPaths = Module._resolveLookupPaths; - Module._resolveLookupPaths = function (request, parent) { - const result = originalResolveLookupPaths(request, parent); + Module._resolveLookupPaths = function (request, parent, newReturn) { + const result = originalResolveLookupPaths(request, parent, newReturn); - const paths = result[1]; + const paths = newReturn ? result : result[1]; for (let i = 0, len = paths.length; i < len; i++) { if (paths[i] === NODE_MODULES_PATH) { paths.splice(i, 0, NODE_MODULES_ASAR_PATH); @@ -204,7 +206,7 @@ function main() { bundles[bundle] = json; cb(undefined, json); }) - .catch(cb); + .catch(cb); }; } diff --git a/src/vs/workbench/electron-browser/commands.ts b/src/vs/workbench/electron-browser/commands.ts index b06c026aef..cb91bb4c78 100644 --- a/src/vs/workbench/electron-browser/commands.ts +++ b/src/vs/workbench/electron-browser/commands.ts @@ -5,7 +5,7 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -13,12 +13,12 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { NoEditorsVisibleContext, InZenModeContext } from 'vs/workbench/electron-browser/workbench'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import { List } from 'vs/base/browser/ui/list/listWidget'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import URI from 'vs/base/common/uri'; import { IEditorOptions, Position as EditorPosition } from 'vs/platform/editor/common/editor'; -import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey } from 'vs/platform/list/browser/listService'; +import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget } from 'vs/platform/list/browser/listService'; import { PagedList } from 'vs/base/browser/ui/list/listPaging'; import { range } from 'vs/base/common/arrays'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -26,12 +26,25 @@ import { ITree } from 'vs/base/parts/tree/browser/tree'; // --- List Commands +function ensureDOMFocus(widget: ListWidget): void { + // it can happen that one of the commands is executed while + // DOM focus is within another focusable control within the + // list/tree item. therefor we should ensure that the + // list/tree has DOM focus again after the command ran. + if (widget && !widget.isDOMFocused()) { + widget.domFocus(); + } +} + export function registerCommands(): void { function focusDown(accessor: ServicesAccessor, arg2?: number): void { const focused = accessor.get(IListService).lastFocusedList; const count = typeof arg2 === 'number' ? arg2 : 1; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; @@ -131,6 +144,9 @@ export function registerCommands(): void { const focused = accessor.get(IListService).lastFocusedList; const count = typeof arg2 === 'number' ? arg2 : 1; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; @@ -261,6 +277,9 @@ export function registerCommands(): void { handler: (accessor) => { const focused = accessor.get(IListService).lastFocusedList; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; @@ -287,6 +306,9 @@ export function registerCommands(): void { handler: (accessor) => { const focused = accessor.get(IListService).lastFocusedList; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; @@ -324,6 +346,9 @@ export function registerCommands(): void { function listFocusFirst(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void { const focused = accessor.get(IListService).lastFocusedList; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; @@ -360,6 +385,9 @@ export function registerCommands(): void { function listFocusLast(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void { const focused = accessor.get(IListService).lastFocusedList; + // Ensure DOM Focus + ensureDOMFocus(focused); + // List if (focused instanceof List || focused instanceof PagedList) { const list = focused; diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index 19ece67ae4..adb2930c60 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -6,20 +6,22 @@ 'use strict'; import { Registry } from 'vs/platform/registry/common/platform'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import product from 'vs/platform/node/product'; import * as os from 'os'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; -import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction } from 'vs/workbench/electron-browser/actions'; +import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction, OpenProcessExplorer } from 'vs/workbench/electron-browser/actions'; import { registerCommands } from 'vs/workbench/electron-browser/commands'; import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, OpenFolderAsWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; // Contribute Commands registerCommands(); @@ -103,14 +105,25 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(AddRoo workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory); -workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceConfigFileAction, OpenWorkspaceConfigFileAction.ID, OpenWorkspaceConfigFileAction.LABEL), 'Workspaces: Open Workspace Configuration File', workspacesCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFolderAsWorkspaceInNewWindowAction, OpenFolderAsWorkspaceInNewWindowAction.ID, OpenFolderAsWorkspaceInNewWindowAction.LABEL), 'Workspaces: Open Folder as Workspace in New Window', workspacesCategory); +CommandsRegistry.registerCommand(OpenWorkspaceConfigFileAction.ID, serviceAccessor => { + serviceAccessor.get(IInstantiationService).createInstance(OpenWorkspaceConfigFileAction, OpenWorkspaceConfigFileAction.ID, OpenWorkspaceConfigFileAction.LABEL).run(); +}); +MenuRegistry.appendMenuItem(MenuId.CommandPalette, { + command: { + id: OpenWorkspaceConfigFileAction.ID, + title: `${workspacesCategory}: ${OpenWorkspaceConfigFileAction.LABEL}`, + }, + when: new RawContextKey<string>('workbenchState', '').isEqualTo('workspace') +}); + // Developer related actions const developerCategory = nls.localize('developer', "Developer"); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowStartupPerformance, ShowStartupPerformance.ID, ShowStartupPerformance.LABEL), 'Developer: Startup Performance', developerCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSharedProcessAction, ToggleSharedProcessAction.ID, ToggleSharedProcessAction.LABEL), 'Developer: Toggle Shared Process', developerCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(InspectContextKeysAction, InspectContextKeysAction.ID, InspectContextKeysAction.LABEL), 'Developer: Inspect Context Keys', developerCategory); +workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenProcessExplorer, OpenProcessExplorer.ID, OpenProcessExplorer.LABEL), 'Developer: Open Process Explorer', developerCategory); const recentFilesPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inRecentFilesPickerContextKey)); @@ -293,11 +306,16 @@ configurationRegistry.registerConfiguration({ 'enumDescriptions': [ nls.localize('window.openFilesInNewWindow.on', "Files will open in a new window"), nls.localize('window.openFilesInNewWindow.off', "Files will open in the window with the files' folder open or the last active window"), - nls.localize('window.openFilesInNewWindow.default', "Files will open in the window with the files' folder open or the last active window unless opened via the dock or from finder (macOS only)") + isMacintosh ? + nls.localize('window.openFilesInNewWindow.defaultMac', "Files will open in the window with the files' folder open or the last active window unless opened via the Dock or from Finder") : + nls.localize('window.openFilesInNewWindow.default', "Files will open in a new window unless picked from within the application (e.g. via the File menu)") ], 'default': 'off', + 'scope': ConfigurationScope.APPLICATION, 'description': - nls.localize('openFilesInNewWindow', "Controls if files should open in a new window.\n- default: files will open in the window with the files' folder open or the last active window unless opened via the dock or from finder (macOS only)\n- on: files will open in a new window\n- off: files will open in the window with the files' folder open or the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).") + isMacintosh ? + nls.localize('openFilesInNewWindowMac', "Controls if files should open in a new window.\n- default: files will open in the window with the files' folder open or the last active window unless opened via the Dock or from Finder\n- on: files will open in a new window\n- off: files will open in the window with the files' folder open or the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).") : + nls.localize('openFilesInNewWindow', "Controls if files should open in a new window.\n- default: files will open in a new window unless picked from within the application (e.g. via the File menu)\n- on: files will open in a new window\n- off: files will open in the window with the files' folder open or the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).") }, 'window.openFoldersInNewWindow': { 'type': 'string', @@ -308,8 +326,20 @@ configurationRegistry.registerConfiguration({ nls.localize('window.openFoldersInNewWindow.default', "Folders will open in a new window unless a folder is picked from within the application (e.g. via the File menu)") ], 'default': 'default', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('openFoldersInNewWindow', "Controls if folders should open in a new window or replace the last active window.\n- default: folders will open in a new window unless a folder is picked from within the application (e.g. via the File menu)\n- on: folders will open in a new window\n- off: folders will replace the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).") }, + 'window.openWithoutArgumentsInNewWindow': { + 'type': 'string', + 'enum': ['on', 'off'], + 'enumDescriptions': [ + nls.localize('window.openWithoutArgumentsInNewWindow.on', "Open a new empty window"), + nls.localize('window.openWithoutArgumentsInNewWindow.off', "Focus the last active running instance") + ], + 'default': isMacintosh ? 'off' : 'on', + 'scope': ConfigurationScope.APPLICATION, + 'description': nls.localize('openWithoutArgumentsInNewWindow', "Controls if a new empty window should open when starting a second instance without arguments or if the last running instance should get focus.\n- on: open a new empty window\n- off: the last active running instance will get focus\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).") + }, 'window.restoreWindows': { 'type': 'string', 'enum': ['all', 'folders', 'one', 'none'], @@ -320,11 +350,13 @@ configurationRegistry.registerConfiguration({ nls.localize('window.reopenFolders.none', "Never reopen a window. Always start with an empty one.") ], 'default': 'one', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('restoreWindows', "Controls how windows are being reopened after a restart. Select 'none' to always start with an empty workspace, 'one' to reopen the last window you worked on, 'folders' to reopen all windows that had folders opened or 'all' to reopen all windows of your last session.") }, 'window.restoreFullscreen': { 'type': 'boolean', 'default': false, + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('restoreFullscreen', "Controls if a window should restore to full screen mode if it was exited in full screen mode.") }, 'window.zoomLevel': { @@ -336,7 +368,7 @@ configurationRegistry.registerConfiguration({ 'type': 'string', 'default': isMacintosh ? '${activeEditorShort}${separator}${rootName}' : '${dirty}${activeEditorShort}${separator}${rootName}${separator}${appName}', 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'title' }, - "Controls the window title based on the active editor. Variables are substituted based on the context:\n\${activeEditorShort}: the file name (e.g. myFile.txt)\n\${activeEditorMedium}: the path of the file relative to the workspace folder (e.g. myFolder/myFile.txt)\n\${activeEditorLong}: the full path of the file (e.g. /Users/Development/myProject/myFolder/myFile.txt)\n\${folderName}: name of the workspace folder the file is contained in (e.g. myFolder)\n\${folderPath}: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder)\n\${rootName}: name of the workspace (e.g. myFolder or myWorkspace)\n\${rootPath}: file path of the workspace (e.g. /Users/Development/myWorkspace)\n\${appName}: e.g. VS Code\n\${dirty}: a dirty indicator if the active editor is dirty\n\${separator}: a conditional separator (\" - \") that only shows when surrounded by variables with values") + "Controls the window title based on the active editor. Variables are substituted based on the context:\n\${activeEditorShort}: the file name (e.g. myFile.txt)\n\${activeEditorMedium}: the path of the file relative to the workspace folder (e.g. myFolder/myFile.txt)\n\${activeEditorLong}: the full path of the file (e.g. /Users/Development/myProject/myFolder/myFile.txt)\n\${folderName}: name of the workspace folder the file is contained in (e.g. myFolder)\n\${folderPath}: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder)\n\${rootName}: name of the workspace (e.g. myFolder or myWorkspace)\n\${rootPath}: file path of the workspace (e.g. /Users/Development/myWorkspace)\n\${appName}: e.g. VS Code\n\${dirty}: a dirty indicator if the active editor is dirty\n\${separator}: a conditional separator (\" - \") that only shows when surrounded by variables with values or static text") }, 'window.newWindowDimensions': { 'type': 'string', @@ -348,6 +380,7 @@ configurationRegistry.registerConfiguration({ nls.localize('window.newWindowDimensions.fullscreen', "Open new windows in full screen mode.") ], 'default': 'default', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('newWindowDimensions', "Controls the dimensions of opening a new window when at least one window is already opened. By default, a new window will open in the center of the screen with small dimensions. When set to 'inherit', the window will get the same dimensions as the last window that was active. When set to 'maximized', the window will open maximized and fullscreen if configured to 'fullscreen'. Note that this setting does not have an impact on the first window that is opened. The first window will always restore the size and location as you left it before closing.") }, 'window.closeWhenEmpty': { @@ -365,12 +398,14 @@ configurationRegistry.registerConfiguration({ nls.localize('window.menuBarVisibility.hidden', "Menu is always hidden.") ], 'default': 'default', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('menuBarVisibility', "Control the visibility of the menu bar. A setting of 'toggle' means that the menu bar is hidden and a single press of the Alt key will show it. By default, the menu bar will be visible, unless the window is full screen."), 'included': isWindows || isLinux }, 'window.enableMenuBarMnemonics': { 'type': 'boolean', 'default': true, + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('enableMenuBarMnemonics', "If enabled, the main menus can be opened via Alt-key shortcuts. Disabling mnemonics allows to bind these Alt-key shortcuts to editor commands instead."), 'included': isWindows || isLinux }, @@ -384,14 +419,30 @@ configurationRegistry.registerConfiguration({ 'type': 'string', 'enum': ['native', 'custom'], 'default': 'custom', + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('titleBarStyle', "Adjust the appearance of the window title bar. Changes require a full restart to apply."), 'included': isMacintosh }, 'window.nativeTabs': { 'type': 'boolean', 'default': false, + 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."), 'included': isMacintosh && parseFloat(os.release()) >= 16 // Minimum: macOS Sierra (10.12.x = darwin 16.x) + }, + 'window.smoothScrollingWorkaround': { + 'type': 'boolean', + 'default': false, + 'scope': ConfigurationScope.APPLICATION, + 'description': nls.localize('window.smoothScrollingWorkaround', "Enable this workaround if scrolling is no longer smooth after restoring a minimized VS Code window. This is a workaround for an issue (https://github.com/Microsoft/vscode/issues/13612) where scrolling starts to lag on devices with precision trackpads like the Surface devices from Microsoft. Enabling this workaround can result in a little bit of layout flickering after restoring the window from minimized state but is otherwise harmless."), + 'included': isWindows + }, + 'window.clickThroughInactive': { + 'type': 'boolean', + 'default': true, + 'scope': ConfigurationScope.APPLICATION, + 'description': nls.localize('window.clickThroughInactive', "If enabled, clicking on an inactive window will both activate the window and trigger the element under the mouse if it is clickable. If disabled, clicking anywhere on an inactive window will activate it only and a second click is required on the element."), + 'included': isMacintosh } } }); diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index cb2e5ae2bb..85c907f1af 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -5,25 +5,25 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as perf from 'vs/base/common/performance'; import { TPromise } from 'vs/base/common/winjs.base'; import { WorkbenchShell } from 'vs/workbench/electron-browser/shell'; import * as browser from 'vs/base/browser/browser'; import { domContentLoaded } from 'vs/base/browser/dom'; -import errors = require('vs/base/common/errors'); -import comparer = require('vs/base/common/comparers'); -import platform = require('vs/base/common/platform'); -import paths = require('vs/base/common/paths'); +import * as errors from 'vs/base/common/errors'; +import * as comparer from 'vs/base/common/comparers'; +import * as platform from 'vs/base/common/platform'; +import * as paths from 'vs/base/common/paths'; import uri from 'vs/base/common/uri'; -import strings = require('vs/base/common/strings'); +import * as strings from 'vs/base/common/strings'; import { IWorkspaceContextService, Workspace, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { realpath } from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import gracefulFs = require('graceful-fs'); +import * as gracefulFs from 'graceful-fs'; import { IInitData } from 'vs/workbench/services/timer/common/timerService'; import { TimerService } from 'vs/workbench/services/timer/node/timerService'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; @@ -36,17 +36,18 @@ import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ import { webFrame } from 'electron'; import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc'; import { IUpdateService } from 'vs/platform/update/common/update'; -import { URLChannelClient } from 'vs/platform/url/common/urlIpc'; +import { URLHandlerChannel, URLServiceChannelClient } from 'vs/platform/url/common/urlIpc'; import { IURLService } from 'vs/platform/url/common/url'; import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspacesIpc'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; - -import fs = require('fs'); +import * as fs from 'fs'; import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log'; import { IssueChannelClient } from 'vs/platform/issue/common/issueIpc'; import { IIssueService } from 'vs/platform/issue/common/issue'; import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; +import { RelayURLService } from 'vs/platform/url/common/urlService'; + gracefulFs.gracefulify(fs); // enable gracefulFs export function startup(configuration: IWindowConfiguration): TPromise<void> { @@ -72,7 +73,7 @@ export function startup(configuration: IWindowConfiguration): TPromise<void> { } function openWorkbench(configuration: IWindowConfiguration): TPromise<void> { - const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`)); + const mainProcessClient = new ElectronIPCClient(`window:${configuration.windowId}`); const mainServices = createMainProcessServices(mainProcessClient, configuration); const environmentService = new EnvironmentService(configuration, configuration.execPath); @@ -96,7 +97,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise<void> { logService, timerService, storageService - }, mainServices, configuration); + }, mainServices, mainProcessClient, configuration); shell.open(); // Inform user about loading issues from the loader @@ -216,7 +217,12 @@ function createMainProcessServices(mainProcessClient: ElectronIPCClient, configu serviceCollection.set(IUpdateService, new SyncDescriptor(UpdateChannelClient, updateChannel)); const urlChannel = mainProcessClient.getChannel('url'); - serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, configuration.windowId)); + const mainUrlService = new URLServiceChannelClient(urlChannel); + const urlService = new RelayURLService(mainUrlService); + serviceCollection.set(IURLService, urlService); + + const urlHandlerChannel = new URLHandlerChannel(urlService); + mainProcessClient.registerChannel('urlHandler', urlHandlerChannel); const issueChannel = mainProcessClient.getChannel('issue'); serviceCollection.set(IIssueService, new SyncDescriptor(IssueChannelClient, issueChannel)); diff --git a/src/vs/workbench/electron-browser/media/shell.css b/src/vs/workbench/electron-browser/media/shell.css index 5fc74c8458..46e66ba111 100644 --- a/src/vs/workbench/electron-browser/media/shell.css +++ b/src/vs/workbench/electron-browser/media/shell.css @@ -10,7 +10,7 @@ padding: 0; overflow: hidden; font-size: 11px; - -webkit-user-select: none; + user-select: none; } /* Font Families (with CJK support) */ @@ -21,7 +21,6 @@ .monaco-shell:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Meiryo", "Hiragino Kaku Gothic Pro", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", "Sazanami Gothic", "IPA Gothic", sans-serif; } .monaco-shell:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Malgun Gothic", "Nanum Gothic", "Dotom", "Apple SD Gothic Neo", "AppleGothic", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } -@-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .monaco-shell img { @@ -66,29 +65,12 @@ cursor: pointer; } -.monaco-shell input[type="search"]::-webkit-search-decoration, -.monaco-shell input[type="search"]::-webkit-search-results-button, -.monaco-shell input[type="search"]::-webkit-search-results-decoration { - display: none; -} - -.monaco-shell input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; - height: 18px; - width: 18px; - background-image: url('clear.svg'); - background-repeat: no-repeat; - background-position: center center; -} - /* START Keyboard Focus Indication Styles */ .monaco-shell [tabindex="0"]:focus, .monaco-shell .synthetic-focus, .monaco-shell select:focus, .monaco-shell input[type="button"]:focus, -.monaco-shell input[type="submit"]:focus, -.monaco-shell input[type="search"]:focus, .monaco-shell input[type="text"]:focus, .monaco-shell textarea:focus, .monaco-shell input[type="checkbox"]:focus { @@ -98,28 +80,23 @@ opacity: 1 !important; } +.monaco-shell [tabindex="0"]:active, +.monaco-shell select:active, +.monaco-shell input[type="button"]:active, +.monaco-shell input[type="checkbox"]:active, +.monaco-shell .monaco-tree .monaco-tree-row +.monaco-action-bar .action-item [tabindex="0"]:hover, +.monaco-shell .monaco-tree.focused.no-focused-item:active:before { + outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ +} + .monaco-shell .mac select:focus { border: none; /* outline is a square, but border has a radius, so we avoid this glitch when focused (https://github.com/Microsoft/vscode/issues/26045) */ } -.monaco-shell.hc-black [tabindex="0"]:focus, -.monaco-shell.hc-black .synthetic-focus, -.monaco-shell.hc-black select:focus, -.monaco-shell.hc-black input[type="button"]:focus, -.monaco-shell.hc-black input[type="text"]:focus, -.monaco-shell.hc-black textarea:focus, -.monaco-shell.hc-black input[type="search"]:focus, -.monaco-shell.hc-black input[type="checkbox"]:focus { - outline-style: solid; - outline-width: 1px; -} -.monaco-shell.hc-black .synthetic-focus input { - background: transparent; /* Search input focus fix when in high contrast */ -} -.monaco-shell.vs .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus, -.monaco-shell.vs-dark .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { +.monaco-shell .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { outline-width: 1px; /* higher contrast color for focusable elements in a row that shows focus feedback */ outline-style: solid; } @@ -140,11 +117,6 @@ outline-offset: -1px; } -.monaco-shell.hc-black .monaco-tree.focused.no-focused-item:focus:before { - outline-width: 1px; - outline-offset: -2px; -} - .monaco-shell .synthetic-focus :focus { outline: 0 !important; /* elements within widgets that draw synthetic-focus should never show focus */ } @@ -161,15 +133,4 @@ .monaco-shell .monaco-tree.focused:focus, .monaco-shell .monaco-list:focus { outline: 0 !important; /* tree indicates focus not via outline but through the focused item */ -} - -.monaco-shell [tabindex="0"]:active, -.monaco-shell select:active, -.monaco-shell input[type="button"]:active, -.monaco-shell input[type="submit"]:active, -.monaco-shell input[type="checkbox"]:active, -.monaco-shell .monaco-tree .monaco-tree-row -.monaco-action-bar .action-item [tabindex="0"]:hover, -.monaco-shell .monaco-tree.focused.no-focused-item:active:before { - outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ } \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/media/workbench.css b/src/vs/workbench/electron-browser/media/workbench.css index f0ab30188e..d80b400531 100644 --- a/src/vs/workbench/electron-browser/media/workbench.css +++ b/src/vs/workbench/electron-browser/media/workbench.css @@ -20,12 +20,12 @@ box-sizing: border-box; } -.monaco-workbench .monaco-action-bar .select-box { - margin-top: 8px; /* Center the select box */ +.monaco-workbench .monaco-action-bar .monaco-select-box { + margin-top: 10px; /* Center the select box */ } -.monaco-workbench.windows .monaco-action-bar .select-box { - margin-top: 7px; /* Center the select box */ +.monaco-workbench.windows .monaco-action-bar .monaco-select-box { + margin-top: 8px; /* Center the select box */ } .monaco-font-aliasing-antialiased { @@ -40,4 +40,4 @@ .monaco-font-aliasing-auto { -webkit-font-smoothing: antialiased; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/electron-browser/resources.ts b/src/vs/workbench/electron-browser/resources.ts index edfb51923a..a335ecfc2e 100644 --- a/src/vs/workbench/electron-browser/resources.ts +++ b/src/vs/workbench/electron-browser/resources.ts @@ -6,10 +6,10 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import objects = require('vs/base/common/objects'); +import * as objects from 'vs/base/common/objects'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob'; import { relative } from 'path'; @@ -19,7 +19,7 @@ export class ResourceGlobMatcher { private static readonly NO_ROOT: string = null; - private _onExpressionChange: Emitter<void>; + private readonly _onExpressionChange: Emitter<void>; private toUnbind: IDisposable[]; private mapRootToParsedExpression: Map<string, ParsedExpression>; private mapRootToExpressionConfig: Map<string, IExpression>; diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 33706df32b..69e6080356 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -9,11 +9,9 @@ import 'vs/css!./media/shell'; import * as platform from 'vs/base/common/platform'; import * as perf from 'vs/base/common/performance'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import dom = require('vs/base/browser/dom'); -import aria = require('vs/base/browser/ui/aria/aria'); +import * as aria from 'vs/base/browser/ui/aria/aria'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import product from 'vs/platform/node/product'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -62,7 +60,7 @@ import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/work import { IModeService } from 'vs/editor/common/services/modeService'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { ICrashReporterService, NullCrashReporterService, CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService'; -import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; +import { getDelayedChannel, IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc'; import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -76,7 +74,7 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl'; -import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, ITheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry'; import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax'; import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService'; @@ -93,9 +91,10 @@ import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue import { WorkbenchIssueService } from 'vs/workbench/services/issue/electron-browser/workbenchIssueService'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { NotificationService } from 'vs/workbench/services/notification/common/notificationService'; -import { ChoiceChannel } from 'vs/platform/dialogs/common/choiceIpc'; -import { IChoiceService, IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; -import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService'; +import { DialogChannel } from 'vs/platform/dialogs/common/dialogIpc'; +import { EventType, addDisposableListener, addClass, getClientArea } from 'vs/base/browser/dom'; // {{SQL CARBON EDIT}} import { FileTelemetryService } from 'sql/platform/telemetry/fileTelemetryService'; @@ -138,12 +137,12 @@ export class WorkbenchShell { private previousErrorValue: string; private previousErrorTime: number; private content: HTMLElement; - private contentsContainer: Builder; + private contentsContainer: HTMLElement; private configuration: IWindowConfiguration; private workbench: Workbench; - constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, configuration: IWindowConfiguration) { + constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, private mainProcessClient: IPCClient, configuration: IWindowConfiguration) { this.container = container; this.configuration = configuration; @@ -161,19 +160,20 @@ export class WorkbenchShell { this.previousErrorTime = 0; } - private createContents(parent: Builder): Builder { + private createContents(parent: HTMLElement): HTMLElement { // ARIA aria.setARIAContainer(document.body); // Workbench Container - const workbenchContainer = $(parent).div(); + const workbenchContainer = document.createElement('div'); + parent.appendChild(workbenchContainer); // Instantiation service with services - const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement()); + const [instantiationService, serviceCollection] = this.initServiceCollection(parent); // Workbench - this.workbench = this.createWorkbench(instantiationService, serviceCollection, parent.getHTMLElement(), workbenchContainer.getHTMLElement()); + this.workbench = this.createWorkbench(instantiationService, serviceCollection, parent, workbenchContainer); // Window this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container); @@ -192,7 +192,7 @@ export class WorkbenchShell { private createWorkbench(instantiationService: IInstantiationService, serviceCollection: ServiceCollection, parent: HTMLElement, workbenchContainer: HTMLElement): Workbench { try { - const workbench = instantiationService.createInstance(Workbench, parent, workbenchContainer, this.configuration, serviceCollection, this.lifecycleService); + const workbench = instantiationService.createInstance(Workbench, parent, workbenchContainer, this.configuration, serviceCollection, this.lifecycleService, this.mainProcessClient); // Set lifecycle phase to `Restoring` this.lifecycleService.phase = LifecyclePhase.Restoring; @@ -241,23 +241,23 @@ export class WorkbenchShell { /* __GDPR__ "workspaceLoad" : { "userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" }, "experiments": { "${inline}": [ "${IExperiments}" ] }, "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('workspaceLoad', { @@ -315,14 +315,14 @@ export class WorkbenchShell { perf.mark('didStatLocalStorage'); /* __GDPR__ - "localStorageTimers" : { - "statTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "accessTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "firstReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "subsequentReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "writeTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "keys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "size": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "localStorageTimers<NUMBER>" : { + "statTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "accessTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "firstReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "subsequentReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "writeTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "keys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "size": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('localStorageTimers2', { @@ -366,7 +366,7 @@ export class WorkbenchShell { .then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.configuration.windowId}`)); sharedProcess - .done(client => client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel))); + .done(client => client.registerChannel('dialog', instantiationService.createInstance(DialogChannel))); // Warm up font cache information before building up too many dom elements restoreFontInfo(this.storageService); @@ -413,9 +413,7 @@ export class WorkbenchShell { } serviceCollection.set(ICrashReporterService, crashReporterService); - const dialog = instantiationService.createInstance(DialogService); - serviceCollection.set(IChoiceService, dialog); - serviceCollection.set(IConfirmationService, dialog); + serviceCollection.set(IDialogService, instantiationService.createInstance(DialogService)); const lifecycleService = instantiationService.createInstance(LifecycleService); this.toUnbind.push(lifecycleService.onShutdown(reason => this.dispose(reason))); @@ -429,6 +427,8 @@ export class WorkbenchShell { serviceCollection.set(IExtensionEnablementService, extensionEnablementService); this.toUnbind.push(extensionEnablementService); + serviceCollection.set(IRequestService, new SyncDescriptor(RequestService)); + this.extensionService = instantiationService.createInstance(ExtensionService); serviceCollection.set(IExtensionService, this.extensionService); @@ -445,8 +445,6 @@ export class WorkbenchShell { this.contextViewService = instantiationService.createInstance(ContextViewService, this.container); serviceCollection.set(IContextViewService, this.contextViewService); - serviceCollection.set(IRequestService, new SyncDescriptor(RequestService)); - serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService)); serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl)); @@ -483,13 +481,15 @@ export class WorkbenchShell { }); // Shell Class for CSS Scoping - $(this.container).addClass('monaco-shell'); + addClass(this.container, 'monaco-shell'); // Controls - this.content = $('.monaco-shell-content').appendTo(this.container).getHTMLElement(); + this.content = document.createElement('div'); + addClass(this.content, 'monaco-shell-content'); + this.container.appendChild(this.content); // Create Contents - this.contentsContainer = this.createContents($(this.content)); + this.contentsContainer = this.createContents(this.content); // Layout this.layout(); @@ -501,7 +501,7 @@ export class WorkbenchShell { private registerListeners(): void { // Resize - $(window).on(dom.EventType.RESIZE, () => this.layout(), this.toUnbind); + this.toUnbind.push(addDisposableListener(window, EventType.RESIZE, () => this.layout())); } public onUnexpectedError(error: any): void { @@ -528,10 +528,10 @@ export class WorkbenchShell { } private layout(): void { - const clArea = $(this.container).getClientArea(); + const clientArea = getClientArea(this.container); - const contentsSize = new Dimension(clArea.width, clArea.height); - this.contentsContainer.size(contentsSize.width, contentsSize.height); + this.contentsContainer.style.width = `${clientArea.width}px`; + this.contentsContainer.style.height = `${clientArea.height}px`; this.contextViewService.layout(); this.workbench.layout(); @@ -652,4 +652,29 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { } `); } + + // High Contrast theme overwrites for outline + if (theme.type === HIGH_CONTRAST) { + collector.addRule(` + .monaco-shell.hc-black [tabindex="0"]:focus, + .monaco-shell.hc-black .synthetic-focus, + .monaco-shell.hc-black select:focus, + .monaco-shell.hc-black input[type="button"]:focus, + .monaco-shell.hc-black input[type="text"]:focus, + .monaco-shell.hc-black textarea:focus, + .monaco-shell.hc-black input[type="checkbox"]:focus { + outline-style: solid; + outline-width: 1px; + } + + .monaco-shell.hc-black .monaco-tree.focused.no-focused-item:focus:before { + outline-width: 1px; + outline-offset: -2px; + } + + .monaco-shell.hc-black .synthetic-focus input { + background: transparent; /* Search input focus fix when in high contrast */ + } + `); + } }); diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 6e439f00a1..dddffc308e 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -5,14 +5,14 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; -import errors = require('vs/base/common/errors'); -import types = require('vs/base/common/types'); +import * as errors from 'vs/base/common/errors'; +import * as types from 'vs/base/common/types'; import { TPromise } from 'vs/base/common/winjs.base'; -import arrays = require('vs/base/common/arrays'); -import objects = require('vs/base/common/objects'); -import DOM = require('vs/base/browser/dom'); +import * as arrays from 'vs/base/common/arrays'; +import * as objects from 'vs/base/common/objects'; +import * as DOM from 'vs/base/browser/dom'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IAction, Action } from 'vs/base/common/actions'; import { AutoSaveConfiguration, IFileService } from 'vs/platform/files/common/files'; @@ -131,7 +131,7 @@ export class ElectronWindow extends Themable { }); // Support runAction event - ipc.on('vscode:runAction', (_event: any, request: IRunActionInWindowRequest) => { + ipc.on('vscode:runAction', (event: any, request: IRunActionInWindowRequest) => { const args: any[] = []; // If we run an action from the touchbar, we fill in the currently active resource @@ -162,7 +162,7 @@ export class ElectronWindow extends Themable { }); // Support resolve keybindings event - ipc.on('vscode:resolveKeybindings', (_event: any, rawActionIds: string) => { + ipc.on('vscode:resolveKeybindings', (event: any, rawActionIds: string) => { let actionIds: string[] = []; try { actionIds = JSON.parse(rawActionIds); @@ -178,7 +178,7 @@ export class ElectronWindow extends Themable { }, () => errors.onUnexpectedError); }); - ipc.on('vscode:reportError', (_event: any, error: string) => { + ipc.on('vscode:reportError', (event: any, error: string) => { if (error) { const errorParsed = JSON.parse(error); errorParsed.mainProcess = true; @@ -187,13 +187,13 @@ export class ElectronWindow extends Themable { }); // Support openFiles event for existing and new files - ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => this.onOpenFiles(request)); + ipc.on('vscode:openFiles', (event: any, request: IOpenFileRequest) => this.onOpenFiles(request)); // Support addFolders event if we have a workspace opened - ipc.on('vscode:addFolders', (_event: any, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); + ipc.on('vscode:addFolders', (event: any, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); // Message support - ipc.on('vscode:showInfoMessage', (_event: any, message: string) => { + ipc.on('vscode:showInfoMessage', (event: any, message: string) => { this.notificationService.info(message); }); @@ -240,7 +240,7 @@ export class ElectronWindow extends Themable { }); // keyboard layout changed event - ipc.on('vscode:accessibilitySupportChanged', (_event: any, accessibilitySupportEnabled: boolean) => { + ipc.on('vscode:accessibilitySupportChanged', (event: any, accessibilitySupportEnabled: boolean) => { browser.setAccessibilitySupport(accessibilitySupportEnabled ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled); }); diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 8e0163cdec..38fbecc21c 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -10,13 +10,13 @@ import 'vs/css!./media/workbench'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; -import DOM = require('vs/base/browser/dom'); +import { Event, Emitter } from 'vs/base/common/event'; +import * as DOM from 'vs/base/browser/dom'; import { Builder, $ } from 'vs/base/browser/builder'; import { Delayer, RunOnceScheduler } from 'vs/base/common/async'; import * as browser from 'vs/base/browser/browser'; import * as perf from 'vs/base/common/performance'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -35,8 +35,10 @@ import { WorkbenchLayout } from 'vs/workbench/browser/layout'; import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions'; import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput'; import { getServices } from 'vs/platform/instantiation/common/extensions'; -import { Position, Parts, IPartService, ILayoutOptions, Dimension } from 'vs/workbench/services/part/common/partService'; +import { Position, Parts, IPartService, ILayoutOptions, IDimension } from 'vs/workbench/services/part/common/partService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService'; @@ -95,7 +97,7 @@ import URI from 'vs/base/common/uri'; import { IListService, ListService } from 'vs/platform/list/browser/listService'; import { domEvent } from 'vs/base/browser/event'; import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys'; -import { ICustomViewsService } from 'vs/workbench/common/views'; +import { IViewsService } from 'vs/workbench/common/views'; import { CustomViewsService } from 'vs/workbench/browser/parts/views/customView'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { NotificationService } from 'vs/workbench/services/notification/common/notificationService'; @@ -104,6 +106,11 @@ import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/no import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus'; import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts'; +import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; +import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService'; +import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; // {{SQL CARBON EDIT}} @@ -187,6 +194,8 @@ export interface IWorkbenchStartedInfo { type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto'; +const fontAliasingValues: FontAliasingOption[] = ['antialiased', 'none', 'auto']; + const Identifiers = { WORKBENCH_CONTAINER: 'workbench.main.container', TITLEBAR_PART: 'workbench.parts.titlebar', @@ -226,7 +235,7 @@ export class Workbench implements IPartService { private static readonly fontAliasingConfigurationKey = 'workbench.fontAliasing'; - private _onTitleBarVisibilityChange: Emitter<void>; + private readonly _onTitleBarVisibilityChange: Emitter<void>; public _serviceBrand: any; @@ -251,6 +260,7 @@ export class Workbench implements IPartService { private editorPart: EditorPart; private statusbarPart: StatusbarPart; private quickOpen: QuickOpenController; + private quickInput: QuickInputService; private notificationsCenter: NotificationsCenter; private notificationsToasts: NotificationsToasts; private workbenchLayout: WorkbenchLayout; @@ -280,9 +290,10 @@ export class Workbench implements IPartService { constructor( parent: HTMLElement, container: HTMLElement, - configuration: IWindowConfiguration, + private configuration: IWindowConfiguration, serviceCollection: ServiceCollection, private lifecycleService: LifecycleService, + private mainProcessClient: IPCClient, @IInstantiationService private instantiationService: IInstantiationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IStorageService private storageService: IStorageService, @@ -316,7 +327,7 @@ export class Workbench implements IPartService { return this._onTitleBarVisibilityChange.event; } - public get onEditorLayout(): Event<Dimension> { + public get onEditorLayout(): Event<IDimension> { return this.editorPart.onLayout; } @@ -367,6 +378,12 @@ export class Workbench implements IPartService { // Workbench Layout this.createWorkbenchLayout(); + // Driver + if (this.environmentService.driverHandle) { + registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService) + .then(disposable => this.toUnbind.push(disposable)); + } + // Restore Parts return this.restoreParts(); } @@ -473,6 +490,7 @@ export class Workbench implements IPartService { workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I } } : void 0), 'Developer: Toggle Developer Tools', localize('developer', "Developer")); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: isDeveloping ? null : KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', localize('file', "File")); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Reload Window Without Extensions'); + // Actions for macOS native tabs management (only when enabled) const windowConfig = this.configurationService.getValue<IWindowConfiguration>(); if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) { @@ -612,7 +630,7 @@ export class Workbench implements IPartService { // Custom views service const customViewsService = this.instantiationService.createInstance(CustomViewsService); - serviceCollection.set(ICustomViewsService, customViewsService); + serviceCollection.set(IViewsService, customViewsService); // Activity service (activitybar part) this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART); @@ -623,7 +641,7 @@ export class Workbench implements IPartService { // File Service this.fileService = this.instantiationService.createInstance(RemoteFileService); serviceCollection.set(IFileService, this.fileService); - this.toUnbind.push(this.fileService.onFileChanges(e => this.configurationService.handleWorkspaceFileEvents(e))); + this.configurationService.acquireFileService(this.fileService); // Editor service (editor part) this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, !this.hasFilesToCreateOpenOrDiff); @@ -653,6 +671,9 @@ export class Workbench implements IPartService { // SCM Service serviceCollection.set(ISCMService, new SyncDescriptor(SCMService)); + // Inactive extension URL handler + serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler)); + // Text Model Resolver Service serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService)); @@ -718,6 +739,13 @@ export class Workbench implements IPartService { this.toUnbind.push({ dispose: () => connectionManagementService.shutdown() }); this.toUnbind.push({ dispose: () => accountManagementService.shutdown() }); this.toUnbind.push({ dispose: () => capabilitiesService.shutdown() }); + // Quick input service + this.quickInput = this.instantiationService.createInstance(QuickInputService); + this.toUnbind.push({ dispose: () => this.quickInput.shutdown() }); + serviceCollection.set(IQuickInputService, this.quickInput); + + // PreferencesService + serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService)); // Contributed services const contributedServices = getServices(); @@ -732,7 +760,7 @@ export class Workbench implements IPartService { this.instantiationService.createInstance(DefaultConfigurationExportHelper); - this.configurationService.setInstantiationService(this.getInstantiationService()); + this.configurationService.acquireInstantiationService(this.getInstantiationService()); } private initSettings(): void { @@ -809,7 +837,7 @@ export class Workbench implements IPartService { } public getContainer(part: Parts): HTMLElement { - let container: Builder = null; + let container: HTMLElement = null; switch (part) { case Parts.TITLEBAR_PART: container = this.titlebarPart.getContainer(); @@ -830,7 +858,8 @@ export class Workbench implements IPartService { container = this.statusbarPart.getContainer(); break; } - return container && container.getHTMLElement(); + + return container; } public isVisible(part: Parts): boolean { @@ -1034,10 +1063,10 @@ export class Workbench implements IPartService { this.sideBarPosition = position; // Adjust CSS - this.activitybarPart.getContainer().removeClass(oldPositionValue); - this.sidebarPart.getContainer().removeClass(oldPositionValue); - this.activitybarPart.getContainer().addClass(newPositionValue); - this.sidebarPart.getContainer().addClass(newPositionValue); + DOM.removeClass(this.activitybarPart.getContainer(), oldPositionValue); + DOM.removeClass(this.sidebarPart.getContainer(), oldPositionValue); + DOM.addClass(this.activitybarPart.getContainer(), newPositionValue); + DOM.addClass(this.sidebarPart.getContainer(), newPositionValue); // Update Styles this.activitybarPart.updateStyles(); @@ -1059,8 +1088,8 @@ export class Workbench implements IPartService { this.storageService.store(Workbench.panelPositionStorageKey, Position[this.panelPosition].toLowerCase(), StorageScope.WORKSPACE); // Adjust CSS - this.panelPart.getContainer().removeClass(oldPositionValue); - this.panelPart.getContainer().addClass(newPositionValue); + DOM.removeClass(this.panelPart.getContainer(), oldPositionValue); + DOM.addClass(this.panelPart.getContainer(), newPositionValue); // Update Styles this.panelPart.updateStyles(); @@ -1072,13 +1101,12 @@ export class Workbench implements IPartService { private setFontAliasing(aliasing: FontAliasingOption) { this.fontAliasing = aliasing; - const fontAliasingClassNames = [ - 'monaco-font-aliasing-antialiased', - 'monaco-font-aliasing-none', - 'monaco-font-aliasing-auto' - ]; - document.body.classList.remove(...fontAliasingClassNames); - if (aliasing !== 'default') { + + // Remove all + document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`)); + + // Add specific + if (fontAliasingValues.some(option => option === aliasing)) { document.body.classList.add(`monaco-font-aliasing-${aliasing}`); } } @@ -1092,10 +1120,13 @@ export class Workbench implements IPartService { // Preserve zen mode only on reload. Real quit gets out of zen mode so novice users do not get stuck in zen mode. const zenConfig = this.configurationService.getValue<IZenModeSettings>('zenMode'); - const zenModeActive = (zenConfig.restore || reason === ShutdownReason.RELOAD) && this.zenMode.active; - if (zenModeActive) { + const restoreZenMode = this.zenMode.active && (zenConfig.restore || reason === ShutdownReason.RELOAD); + if (restoreZenMode) { this.storageService.store(Workbench.zenModeActiveStorageKey, true, StorageScope.WORKSPACE); } else { + if (this.zenMode.active) { + this.toggleZenMode(true); + } this.storageService.remove(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE); } @@ -1198,10 +1229,10 @@ export class Workbench implements IPartService { const editorContainer = this.editorPart.getContainer(); if (visibleEditors === 0) { this.editorsVisibleContext.reset(); - this.editorBackgroundDelayer.trigger(() => editorContainer.addClass('empty')); + this.editorBackgroundDelayer.trigger(() => DOM.addClass(editorContainer, 'empty')); } else { this.editorsVisibleContext.set(true); - this.editorBackgroundDelayer.trigger(() => editorContainer.removeClass('empty')); + this.editorBackgroundDelayer.trigger(() => DOM.removeClass(editorContainer, 'empty')); } } @@ -1242,8 +1273,8 @@ export class Workbench implements IPartService { private createWorkbenchLayout(): void { this.workbenchLayout = this.instantiationService.createInstance( WorkbenchLayout, - $(this.container), // Parent - this.workbench, // Workbench Container + this.container, // Parent + this.workbench.getHTMLElement(), // Workbench Container { titlebar: this.titlebarPart, // Title Bar activitybar: this.activitybarPart, // Activity Bar @@ -1253,6 +1284,7 @@ export class Workbench implements IPartService { statusbar: this.statusbarPart, // Statusbar }, this.quickOpen, // Quickopen + this.quickInput, // QuickInput this.notificationsCenter, // Notifications Center this.notificationsToasts // Notifications Toasts ); @@ -1307,7 +1339,7 @@ export class Workbench implements IPartService { role: 'contentinfo' }); - this.titlebarPart.create(titlebarContainer); + this.titlebarPart.create(titlebarContainer.getHTMLElement()); } private createActivityBarPart(): void { @@ -1318,7 +1350,7 @@ export class Workbench implements IPartService { role: 'navigation' }); - this.activitybarPart.create(activitybarPartContainer); + this.activitybarPart.create(activitybarPartContainer.getHTMLElement()); } private createSidebarPart(): void { @@ -1329,7 +1361,7 @@ export class Workbench implements IPartService { role: 'complementary' }); - this.sidebarPart.create(sidebarPartContainer); + this.sidebarPart.create(sidebarPartContainer.getHTMLElement()); } private createPanelPart(): void { @@ -1340,7 +1372,7 @@ export class Workbench implements IPartService { role: 'complementary' }); - this.panelPart.create(panelPartContainer); + this.panelPart.create(panelPartContainer.getHTMLElement()); } private createEditorPart(): void { @@ -1351,7 +1383,7 @@ export class Workbench implements IPartService { role: 'main' }); - this.editorPart.create(editorContainer); + this.editorPart.create(editorContainer.getHTMLElement()); } private createStatusbarPart(): void { @@ -1361,7 +1393,7 @@ export class Workbench implements IPartService { role: 'contentinfo' }); - this.statusbarPart.create(statusbarContainer); + this.statusbarPart.create(statusbarContainer.getHTMLElement()); } private createNotificationsHandlers(): void { @@ -1380,7 +1412,6 @@ export class Workbench implements IPartService { // Notifications Status const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, this.notificationService.model); - this.toUnbind.push(notificationsStatus); // Eventing this.toUnbind.push(this.notificationsCenter.onDidChangeVisibility(() => { @@ -1422,13 +1453,11 @@ export class Workbench implements IPartService { // Check if zen mode transitioned to full screen and if now we are out of zen mode -> we need to go out of full screen let toggleFullScreen = false; // Same goes for the centered editor layout - let toggleCenteredEditorLayout = false; if (this.zenMode.active) { const config = this.configurationService.getValue<IZenModeSettings>('zenMode'); toggleFullScreen = !browser.isFullscreen() && config.fullScreen; this.zenMode.transitionedToFullScreen = toggleFullScreen; - toggleCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout; - this.zenMode.transitionedToCenteredEditorLayout = toggleCenteredEditorLayout; + this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout; this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART); this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART); this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError); @@ -1445,14 +1474,20 @@ export class Workbench implements IPartService { if (config.hideTabs) { this.editorPart.hideTabs(true); } + + if (config.centerLayout) { + this.centerEditorLayout(true, true); + } } else { if (this.zenMode.wasPanelVisible) { this.setPanelHidden(false, true).done(void 0, errors.onUnexpectedError); } - if (this.zenMode.wasSideBarVisible) { this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError); } + if (this.zenMode.transitionedToCenteredEditorLayout) { + this.centerEditorLayout(false, true); + } // Status bar and activity bar visibility come from settings -> update their visibility. this.onDidUpdateConfiguration(true); @@ -1463,15 +1498,10 @@ export class Workbench implements IPartService { } toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen(); - toggleCenteredEditorLayout = this.zenMode.transitionedToCenteredEditorLayout && this.isEditorLayoutCentered(); } this.inZenMode.set(this.zenMode.active); - if (toggleCenteredEditorLayout) { - this.toggleCenteredEditorLayout(true); - } - if (!skipLayout) { this.layout(); } @@ -1485,8 +1515,8 @@ export class Workbench implements IPartService { return this.centeredEditorLayoutActive; } - public toggleCenteredEditorLayout(skipLayout?: boolean): void { - this.centeredEditorLayoutActive = !this.centeredEditorLayoutActive; + public centerEditorLayout(active: boolean, skipLayout?: boolean): void { + this.centeredEditorLayoutActive = active; this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, this.centeredEditorLayoutActive, StorageScope.GLOBAL); if (!skipLayout) { diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index 17246f4334..ed9f872e80 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -5,8 +5,8 @@ 'use strict'; -import nls = require('vs/nls'); -import pfs = require('vs/base/node/pfs'); +import * as nls from 'vs/nls'; +import * as pfs from 'vs/base/node/pfs'; import { TPromise } from 'vs/base/common/winjs.base'; import { join } from 'path'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; @@ -17,26 +17,24 @@ import { QueryType, ISearchQuery } from 'vs/platform/search/common/search'; import { DiskSearch } from 'vs/workbench/services/search/node/searchService'; import { IInitData, IEnvironment, IWorkspaceData, MainContext } from 'vs/workbench/api/node/extHost.protocol'; import * as errors from 'vs/base/common/errors'; -import * as watchdog from 'native-watchdog'; import * as glob from 'vs/base/common/glob'; import { ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator'; -import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; import URI from 'vs/base/common/uri'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; -// const nativeExit = process.exit.bind(process); +const nativeExit = process.exit.bind(process); function patchProcess(allowExit: boolean) { - process.exit = function (code) { + process.exit = function (code?: number) { if (allowExit) { exit(code); } else { const err = new Error('An extension called process.exit() and this was prevented.'); console.warn(err.stack); } - }; + } as (code?: number) => never; process.crash = function () { const err = new Error('An extension called process.crash() and this was prevented.'); @@ -44,14 +42,20 @@ function patchProcess(allowExit: boolean) { }; } export function exit(code?: number) { - //nativeExit(code); - // TODO@electron // See https://github.com/Microsoft/vscode/issues/32990 // calling process.exit() does not exit the process when the process is being debugged // It waits for the debugger to disconnect, but in our version, the debugger does not // receive an event that the process desires to exit such that it can disconnect. + let watchdog: { exit: (exitCode: number) => void; } = null; + try { + watchdog = require.__$__nodeRequire('native-watchdog'); + } catch (err) { + nativeExit(code); + return; + } + // Do exactly what node.js would have done, minus the wait for the debugger part if (code || code === 0) { @@ -89,8 +93,7 @@ export class ExtensionHostMain { // services const rpcProtocol = new RPCProtocol(protocol); - const environmentService = new EnvironmentService(initData.args, initData.execPath); - this._extHostLogService = new ExtHostLogService(initData.windowId, initData.logLevel, environmentService); + this._extHostLogService = new ExtHostLogService(initData.windowId, initData.logLevel, initData.logsPath); this.disposables.push(this._extHostLogService); const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, initData.workspace, this._extHostLogService); @@ -98,9 +101,10 @@ export class ExtensionHostMain { this._extHostLogService.trace('initData', initData); this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration); - this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._extHostLogService, environmentService); + this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._extHostLogService); // error forwarding and stack trace scanning + Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) const extensionErrors = new WeakMap<Error, IExtensionDescription>(); this._extensionService.getExtensionPathIndex().then(map => { (<any>Error).prepareStackTrace = (error: Error, stackTrace: errors.V8CallSite[]) => { diff --git a/src/vs/workbench/node/extensionHostProcess.ts b/src/vs/workbench/node/extensionHostProcess.ts index bb90ea3406..cf818443e7 100644 --- a/src/vs/workbench/node/extensionHostProcess.ts +++ b/src/vs/workbench/node/extensionHostProcess.ts @@ -11,7 +11,7 @@ import { IInitData } from 'vs/workbench/api/node/extHost.protocol'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { Protocol } from 'vs/base/parts/ipc/node/ipc.net'; import { createConnection } from 'net'; -import Event, { filterEvent } from 'vs/base/common/event'; +import { Event, filterEvent } from 'vs/base/common/event'; interface IRendererConnection { protocol: IMessagePassingProtocol; diff --git a/src/vs/workbench/parts/backup/common/backupModelTracker.ts b/src/vs/workbench/parts/backup/common/backupModelTracker.ts index b1aae8b2dc..7e4a57fcb2 100644 --- a/src/vs/workbench/parts/backup/common/backupModelTracker.ts +++ b/src/vs/workbench/parts/backup/common/backupModelTracker.ts @@ -6,7 +6,7 @@ 'use strict'; import Uri from 'vs/base/common/uri'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ITextFileService, TextFileModelChangeEvent, StateChange } from 'vs/workbench/services/textfile/common/textfiles'; diff --git a/src/vs/workbench/parts/backup/common/backupRestorer.ts b/src/vs/workbench/parts/backup/common/backupRestorer.ts index 7ad9daa77a..a44d482dac 100644 --- a/src/vs/workbench/parts/backup/common/backupRestorer.ts +++ b/src/vs/workbench/parts/backup/common/backupRestorer.ts @@ -9,7 +9,7 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/parts/cache/node/nodeCachedDataManager.ts b/src/vs/workbench/parts/cache/node/nodeCachedDataManager.ts index dccfb0524d..41038d042c 100644 --- a/src/vs/workbench/parts/cache/node/nodeCachedDataManager.ts +++ b/src/vs/workbench/parts/cache/node/nodeCachedDataManager.ts @@ -36,7 +36,7 @@ export class NodeCachedDataManager implements IWorkbenchContribution { /* __GDPR__ "cachedDataError" : { "errorCode" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "path": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" } + "path": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } } */ this._telemetryService.publicLog('cachedDataError', { @@ -49,18 +49,18 @@ export class NodeCachedDataManager implements IWorkbenchContribution { // log summary /* __GDPR__ "cachedDataInfo" : { - "didRequestCachedData" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "didRejectCachedData": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "didProduceCachedData": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "didRequestCachedData" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "didRejectCachedData": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "didProduceCachedData": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ this._telemetryService.publicLog('cachedDataInfo', { - didRequestCachedData: Boolean(global.require.getConfig().nodeCachedDataDir), + didRequestCachedData: Boolean((<any>global).require.getConfig().nodeCachedDataDir), didRejectCachedData, didProduceCachedData }); - global.require.config({ onNodeCachedData: undefined }); + (<any>global).require.config({ onNodeCachedData: undefined }); delete MonacoEnvironment.onNodeCachedData; } } diff --git a/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts b/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts index 848d51decb..d1755b9c8b 100644 --- a/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts +++ b/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts @@ -17,9 +17,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import product from 'vs/platform/node/product'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; -import { ILogService } from '../../../../platform/log/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; function ignore<T>(code: string, value: T = null): (err: any) => TPromise<T> { return err => err.code === code ? TPromise.as<T>(value) : TPromise.wrapError<T>(err); @@ -47,7 +47,7 @@ class InstallAction extends Action { id: string, label: string, @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService, + @IDialogService private dialogService: IDialogService, @ILogService private logService: ILogService ) { super(id, label); @@ -103,9 +103,9 @@ class InstallAction extends Action { private createBinFolder(): TPromise<void> { return new TPromise<void>((c, e) => { - const choices: Choice[] = [nls.localize('ok', "OK"), nls.localize('cancel2', "Cancel")]; + const buttons = [nls.localize('ok', "OK"), nls.localize('cancel2', "Cancel")]; - this.choiceService.choose(Severity.Info, nls.localize('warnEscalation', "Code will now prompt with 'osascript' for Administrator privileges to install the shell command."), choices, 1, true).then(choice => { + this.dialogService.show(Severity.Info, nls.localize('warnEscalation', "Code will now prompt with 'osascript' for Administrator privileges to install the shell command."), buttons, { cancelId: 1 }).then(choice => { switch (choice) { case 0 /* OK */: const command = 'osascript -e "do shell script \\"mkdir -p /usr/local/bin && chown \\" & (do shell script (\\"whoami\\")) & \\" /usr/local/bin\\" with administrator privileges"'; diff --git a/src/vs/workbench/parts/codeEditor/codeEditor.contribution.ts b/src/vs/workbench/parts/codeEditor/codeEditor.contribution.ts index a8cfc8ce93..122133bbca 100644 --- a/src/vs/workbench/parts/codeEditor/codeEditor.contribution.ts +++ b/src/vs/workbench/parts/codeEditor/codeEditor.contribution.ts @@ -13,10 +13,4 @@ import './electron-browser/toggleMultiCursorModifier'; import './electron-browser/toggleRenderControlCharacter'; import './electron-browser/toggleRenderWhitespace'; import './electron-browser/toggleWordWrap'; -import { OPTIONS, TextBufferType } from 'vs/editor/common/model/textModel'; - -// Configure text buffer implementation -if (process.env['VSCODE_PIECE_TREE']) { - console.log(`Using TextBufferType.PieceTree (env variable VSCODE_PIECE_TREE)`); - OPTIONS.TEXT_BUFFER_IMPLEMENTATION = TextBufferType.PieceTree; -} +import './electron-browser/workbenchReferenceSearch'; \ No newline at end of file diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts index 5e44f0419c..c91cba711c 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts @@ -581,5 +581,5 @@ const schema: IJSONSchema = { } }; -let schemaRegistry = <IJSONContributionRegistry>Registry.as(Extensions.JSONContribution); +let schemaRegistry = Registry.as<IJSONContributionRegistry>(Extensions.JSONContribution); schemaRegistry.registerSchema(schemaId, schema); diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.css b/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.css index f8fbc89cc7..6bdbc8f26d 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.css +++ b/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.css @@ -5,11 +5,6 @@ .tm-inspect-widget { z-index: 50; - -webkit-user-select: text; - -ms-user-select: text; - -khtml-user-select: text; - -moz-user-select: text; - -o-user-select: text; user-select: text; padding: 10px; } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/workbenchReferenceSearch.ts b/src/vs/workbench/parts/codeEditor/electron-browser/workbenchReferenceSearch.ts new file mode 100644 index 0000000000..c491985cea --- /dev/null +++ b/src/vs/workbench/parts/codeEditor/electron-browser/workbenchReferenceSearch.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IEditorService } from 'vs/platform/editor/common/editor'; +import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ReferencesController } from 'vs/editor/contrib/referenceSearch/referencesController'; + +export class WorkbenchReferencesController extends ReferencesController { + + public constructor( + editor: ICodeEditor, + @IContextKeyService contextKeyService: IContextKeyService, + @IEditorService editorService: IEditorService, + @ITextModelService textModelResolverService: ITextModelService, + @INotificationService notificationService: INotificationService, + @IInstantiationService instantiationService: IInstantiationService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, + @optional(IEnvironmentService) environmentService: IEnvironmentService + ) { + super( + false, + editor, + contextKeyService, + editorService, + textModelResolverService, + notificationService, + instantiationService, + contextService, + storageService, + themeService, + configurationService, + environmentService + ); + } +} + +registerEditorContribution(WorkbenchReferencesController); diff --git a/src/vs/workbench/parts/debug/browser/baseDebugView.ts b/src/vs/workbench/parts/debug/browser/baseDebugView.ts index cbca5cfb09..95df398ba3 100644 --- a/src/vs/workbench/parts/debug/browser/baseDebugView.ts +++ b/src/vs/workbench/parts/debug/browser/baseDebugView.ts @@ -146,12 +146,11 @@ export function renderRenameBox(debugService: IDebugService, contextViewService: const wrapUp = once((renamed: boolean) => { if (!disposed) { disposed = true; + debugService.getViewModel().setSelectedExpression(undefined); if (element instanceof Expression && renamed && inputBox.value) { debugService.renameWatchExpression(element.getId(), inputBox.value); - debugService.getViewModel().setSelectedExpression(undefined); } else if (element instanceof Expression && !element.name) { debugService.removeWatchExpressions(element.getId()); - debugService.getViewModel().setSelectedExpression(undefined); } else if (element instanceof Variable) { element.errorMessage = null; if (renamed && element.value !== inputBox.value) { @@ -165,7 +164,7 @@ export function renderRenameBox(debugService: IDebugService, contextViewService: } } - tree.DOMFocus(); + tree.domFocus(); tree.setFocus(element); // need to remove the input box since this template will be reused. @@ -229,7 +228,7 @@ export class BaseDebugController extends WorkbenchTreeController { }), onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, getActionsContext: () => element diff --git a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts b/src/vs/workbench/parts/debug/browser/breakpointWidget.ts deleted file mode 100644 index 995298359b..0000000000 --- a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts +++ /dev/null @@ -1,165 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import 'vs/css!../browser/media/breakpointWidget'; -import * as nls from 'vs/nls'; -import * as errors from 'vs/base/common/errors'; -import { KeyCode } from 'vs/base/common/keyCodes'; -import { isWindows, isMacintosh } from 'vs/base/common/platform'; -import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox'; -import * as lifecycle from 'vs/base/common/lifecycle'; -import * as dom from 'vs/base/browser/dom'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IDebugService, IBreakpoint } from 'vs/workbench/parts/debug/common/debug'; -import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { once } from 'vs/base/common/functional'; -import { attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; - -const $ = dom.$; -const EXPRESSION_PLACEHOLDER = nls.localize('breakpointWidgetExpressionPlaceholder', "Break when expression evaluates to true. 'Enter' to accept, 'esc' to cancel."); -const EXPRESSION_ARIA_LABEL = nls.localize('breakpointWidgetAriaLabel', "The program will only stop here if this condition is true. Press Enter to accept or Escape to cancel."); -const HIT_COUNT_PLACEHOLDER = nls.localize('breakpointWidgetHitCountPlaceholder', "Break when hit count condition is met. 'Enter' to accept, 'esc' to cancel."); -const HIT_COUNT_ARIA_LABEL = nls.localize('breakpointWidgetHitCountAriaLabel', "The program will only stop here if the hit count is met. Press Enter to accept or Escape to cancel."); - -export class BreakpointWidget extends ZoneWidget { - - private inputBox: InputBox; - private toDispose: lifecycle.IDisposable[]; - private hitCountContext: boolean; - private hitCountInput: string; - private conditionInput: string; - - constructor(editor: ICodeEditor, private lineNumber: number, private column: number, - @IContextViewService private contextViewService: IContextViewService, - @IDebugService private debugService: IDebugService, - @IThemeService private themeService: IThemeService - ) { - super(editor, { showFrame: true, showArrow: false, frameWidth: 1 }); - - this.toDispose = []; - this.hitCountInput = ''; - this.conditionInput = ''; - this.create(); - } - - private get placeholder(): string { - return this.hitCountContext ? HIT_COUNT_PLACEHOLDER : EXPRESSION_PLACEHOLDER; - } - - private get ariaLabel(): string { - return this.hitCountContext ? HIT_COUNT_ARIA_LABEL : EXPRESSION_ARIA_LABEL; - } - - private getInputBoxValue(breakpoint: IBreakpoint): string { - if (this.hitCountContext) { - return breakpoint && breakpoint.hitCondition ? breakpoint.hitCondition : this.hitCountInput; - } - - return breakpoint && breakpoint.condition ? breakpoint.condition : this.conditionInput; - } - - protected _fillContainer(container: HTMLElement): void { - this.setCssClass('breakpoint-widget'); - const uri = this.editor.getModel().uri; - const breakpoint = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === this.lineNumber && bp.column === this.column && bp.uri.toString() === uri.toString()).pop(); - - this.hitCountContext = breakpoint && breakpoint.hitCondition && !breakpoint.condition; - const selected = this.hitCountContext ? 1 : 0; - const selectBox = new SelectBox([nls.localize('expression', "Expression"), nls.localize('hitCount', "Hit Count")], selected, this.contextViewService); - this.toDispose.push(attachSelectBoxStyler(selectBox, this.themeService)); - selectBox.render(dom.append(container, $('.breakpoint-select-container'))); - selectBox.onDidSelect(e => { - this.hitCountContext = e.selected === 'Hit Count'; - if (this.hitCountContext) { - this.conditionInput = this.inputBox.value; - } else { - this.hitCountInput = this.inputBox.value; - } - - this.inputBox.setAriaLabel(this.ariaLabel); - this.inputBox.setPlaceHolder(this.placeholder); - this.inputBox.value = this.getInputBoxValue(breakpoint); - }); - - const inputBoxContainer = dom.append(container, $('.inputBoxContainer')); - this.inputBox = new InputBox(inputBoxContainer, this.contextViewService, { - placeholder: this.placeholder, - ariaLabel: this.ariaLabel - }); - this.toDispose.push(attachInputBoxStyler(this.inputBox, this.themeService)); - this.toDispose.push(this.inputBox); - - dom.addClass(this.inputBox.inputElement, isWindows ? 'windows' : isMacintosh ? 'mac' : 'linux'); - this.inputBox.value = this.getInputBoxValue(breakpoint); - // Due to an electron bug we have to do the timeout, otherwise we do not get focus - setTimeout(() => this.inputBox.focus(), 0); - - let disposed = false; - const wrapUp = once((success: boolean) => { - if (!disposed) { - disposed = true; - if (success) { - // if there is already a breakpoint on this location - remove it. - const oldBreakpoint = this.debugService.getModel().getBreakpoints() - .filter(bp => bp.lineNumber === this.lineNumber && bp.column === this.column && bp.uri.toString() === uri.toString()).pop(); - - let condition = oldBreakpoint && oldBreakpoint.condition; - let hitCondition = oldBreakpoint && oldBreakpoint.hitCondition; - - if (this.hitCountContext) { - hitCondition = this.inputBox.value; - if (this.conditionInput) { - condition = this.conditionInput; - } - } else { - condition = this.inputBox.value; - if (this.hitCountInput) { - hitCondition = this.hitCountInput; - } - } - - if (oldBreakpoint) { - this.debugService.updateBreakpoints(oldBreakpoint.uri, { - [oldBreakpoint.getId()]: { - condition, - hitCondition, - verified: oldBreakpoint.verified - } - }, false); - } else { - this.debugService.addBreakpoints(uri, [{ - lineNumber: this.lineNumber, - column: oldBreakpoint ? oldBreakpoint.column : undefined, - enabled: true, - condition, - hitCondition - }]).done(null, errors.onUnexpectedError); - } - } - - this.dispose(); - } - }); - - this.toDispose.push(dom.addStandardDisposableListener(this.inputBox.inputElement, 'keydown', (e: IKeyboardEvent) => { - const isEscape = e.equals(KeyCode.Escape); - const isEnter = e.equals(KeyCode.Enter); - if (isEscape || isEnter) { - e.stopPropagation(); - wrapUp(isEnter); - } - })); - } - - public dispose(): void { - super.dispose(); - lifecycle.dispose(this.toDispose); - setTimeout(() => this.editor.focus(), 0); - } -} diff --git a/src/vs/workbench/parts/debug/browser/breakpointsView.ts b/src/vs/workbench/parts/debug/browser/breakpointsView.ts index 6a8e8ac068..87255e7097 100644 --- a/src/vs/workbench/parts/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/parts/debug/browser/breakpointsView.ts @@ -107,6 +107,13 @@ export class BreakpointsView extends ViewsViewletPanel { this.list.splice(0, this.list.length, this.elements); } + public focus(): void { + if (this.list) { + this.list.domFocus(); + } + super.focus(); + } + protected layoutBody(size: number): void { if (this.list) { this.list.layout(size); @@ -117,8 +124,9 @@ export class BreakpointsView extends ViewsViewletPanel { const actions: IAction[] = []; const element = e.element; + const breakpointType = element instanceof Breakpoint && element.logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint"); if (element instanceof Breakpoint || element instanceof FunctionBreakpoint) { - actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', nls.localize('editConditionalBreakpoint', "Edit Breakpoint..."), undefined, true, () => { + actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', nls.localize('editBreakpoint', "Edit {0}...", breakpointType), undefined, true, () => { if (element instanceof Breakpoint) { return openBreakpointSource(element, false, false, this.debugService, this.editorService).then(editor => { const codeEditor = editor.getControl(); @@ -135,8 +143,7 @@ export class BreakpointsView extends ViewsViewletPanel { actions.push(new Separator()); } - actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL, this.debugService, this.keybindingService)); - + actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService, this.keybindingService)); if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length > 1) { actions.push(new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService)); @@ -196,7 +203,7 @@ export class BreakpointsView extends ViewsViewletPanel { private get elements(): IEnablement[] { const model = this.debugService.getModel(); - const elements = (<IEnablement[]>model.getExceptionBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints()); + const elements = (<ReadonlyArray<IEnablement>>model.getExceptionBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints()); return elements; } @@ -547,7 +554,7 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, te if (!breakpoint.enabled || !debugService.getModel().areBreakpointsActivated()) { return { - className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-disabled' : 'debug-breakpoint-disabled', + className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-disabled' : breakpoint.logMessage ? 'debug-breakpoint-log-disabled' : 'debug-breakpoint-disabled', message: nls.localize('breakpointDisabledHover', "Disabled breakpoint"), }; } @@ -557,7 +564,7 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, te }; if (debugActive && !breakpoint.verified) { return { - className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-unverified' : 'debug-breakpoint-unverified', + className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-unverified' : breakpoint.logMessage ? 'debug-breakpoint-log-unverified' : 'debug-breakpoint-unverified', message: appendMessage(nls.localize('breakpointUnverifieddHover', "Unverified breakpoint")), }; } @@ -583,6 +590,20 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, te }; } + if (breakpoint.logMessage) { + if (process && breakpoint.condition && !process.session.capabilities.supportsLogPoints) { + return { + className: 'debug-breakpoint-unsupported', + message: nls.localize('logBreakpointUnsupported', "Logpoints not supported by this debug type"), + }; + } + + return { + className: 'debug-breakpoint-log', + message: appendMessage(breakpoint.logMessage) + }; + } + if (breakpoint.condition || breakpoint.hitCondition) { if (process && breakpoint.condition && !process.session.capabilities.supportsConditionalBreakpoints) { return { diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index d51de1ff22..df2cd21b46 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as lifecycle from 'vs/base/common/lifecycle'; import * as errors from 'vs/base/common/errors'; import { IAction, IActionRunner } from 'vs/base/common/actions'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -21,6 +20,7 @@ import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { selectBorder } from 'vs/platform/theme/common/colorRegistry'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; const $ = dom.$; @@ -33,7 +33,7 @@ export class StartDebugActionItem implements IActionItem { private start: HTMLElement; private selectBox: SelectBox; private options: { label: string, handler: (() => boolean) }[]; - private toDispose: lifecycle.IDisposable[]; + private toDispose: IDisposable[]; private selected: number; constructor( @@ -48,6 +48,7 @@ export class StartDebugActionItem implements IActionItem { ) { this.toDispose = []; this.selectBox = new SelectBox([], -1, contextViewService); + this.toDispose.push(this.selectBox); this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService, { selectBackground: SIDE_BAR_BACKGROUND })); @@ -61,14 +62,6 @@ export class StartDebugActionItem implements IActionItem { this.updateOptions(); } })); - this.toDispose.push(this.selectBox.onDidSelect(e => { - if (this.options[e.index].handler()) { - this.selected = e.index; - } else { - // Some select options should not remain selected https://github.com/Microsoft/vscode/issues/31526 - this.selectBox.select(this.selected); - } - })); this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => { this.updateOptions(); })); @@ -108,6 +101,15 @@ export class StartDebugActionItem implements IActionItem { event.stopPropagation(); } })); + this.toDispose.push(this.selectBox.onDidSelect(e => { + const shouldBeSelected = this.options[e.index].handler(); + if (shouldBeSelected) { + this.selected = e.index; + } else { + // Some select options should not remain selected https://github.com/Microsoft/vscode/issues/31526 + this.selectBox.select(this.selected); + } + })); const selectBoxContainer = $('.configuration'); this.selectBox.render(dom.append(container, selectBoxContainer)); @@ -147,7 +149,7 @@ export class StartDebugActionItem implements IActionItem { } public dispose(): void { - this.toDispose = lifecycle.dispose(this.toDispose); + this.toDispose = dispose(this.toDispose); } private updateOptions(): void { diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index a51a862582..d53522649e 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -7,12 +7,11 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import * as lifecycle from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IFileService } from 'vs/platform/files/common/files'; -import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState } +import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID, ProcessState } from 'vs/workbench/parts/debug/common/debug'; import { Variable, Expression, Thread, Breakpoint, Process } from 'vs/workbench/parts/debug/common/debugModel'; import { IPartService } from 'vs/workbench/services/part/common/partService'; @@ -23,6 +22,8 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { ITree } from 'vs/base/parts/tree/browser/tree'; +import { first } from 'vs/base/common/arrays'; +import { IHistoryService } from 'vs/workbench/services/history/common/history'; export abstract class AbstractDebugAction extends Action { @@ -105,7 +106,12 @@ export class ConfigureAction extends AbstractDebugAction { } const sideBySide = !!(event && (event.ctrlKey || event.metaKey)); - return this.debugService.getConfigurationManager().selectedConfiguration.launch.openConfigFile(sideBySide); + const configurationManager = this.debugService.getConfigurationManager(); + if (!configurationManager.selectedConfiguration.launch) { + configurationManager.selectConfiguration(configurationManager.getLaunches()[0]); + } + + return configurationManager.selectedConfiguration.launch.openConfigFile(sideBySide); } } @@ -116,7 +122,8 @@ export class StartAction extends AbstractDebugAction { constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService, - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IHistoryService private historyService: IHistoryService ) { super(id, label, 'debug-action start', debugService, keybindingService); @@ -126,7 +133,19 @@ export class StartAction extends AbstractDebugAction { } public run(): TPromise<any> { - const launch = this.debugService.getConfigurationManager().selectedConfiguration.launch; + const configurationManager = this.debugService.getConfigurationManager(); + let launch = configurationManager.selectedConfiguration.launch; + if (!launch) { + const rootUri = this.historyService.getLastActiveWorkspaceRoot(); + launch = configurationManager.getLaunch(rootUri); + if (!launch || launch.getConfigurationNames().length === 0) { + const launches = configurationManager.getLaunches(); + launch = first(launches, l => !!l.getConfigurationNames().length, launches.length ? launches[0] : launch); + } + + configurationManager.selectConfiguration(launch); + } + return this.debugService.startDebugging(launch, undefined, this.isNoDebug()); } @@ -196,10 +215,21 @@ export class RestartAction extends AbstractDebugAction { static LABEL = nls.localize('restartDebug', "Restart"); static RECONNECT_LABEL = nls.localize('reconnectDebug', "Reconnect"); - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { + private startAction: StartAction; + + constructor(id: string, label: string, + @IDebugService debugService: IDebugService, + @IKeybindingService keybindingService: IKeybindingService, + @IWorkspaceContextService private contextService?: IWorkspaceContextService, + @IHistoryService historyService?: IHistoryService + ) { super(id, label, 'debug-action restart', debugService, keybindingService, 70); this.setLabel(this.debugService.getViewModel().focusedProcess); this.toDispose.push(this.debugService.getViewModel().onDidFocusStackFrame(() => this.setLabel(this.debugService.getViewModel().focusedProcess))); + + if (contextService !== undefined && historyService !== undefined) { + this.startAction = new StartAction(id, label, debugService, keybindingService, contextService, historyService); + } } private setLabel(process: IProcess): void { @@ -210,8 +240,9 @@ export class RestartAction extends AbstractDebugAction { if (!(process instanceof Process)) { process = this.debugService.getViewModel().focusedProcess; } + if (!process) { - return TPromise.as(null); + return this.startAction.run(); } if (this.debugService.getModel().getProcesses().length <= 1) { @@ -221,7 +252,11 @@ export class RestartAction extends AbstractDebugAction { } protected isEnabled(state: State): boolean { - return super.isEnabled(state) && (state === State.Running || state === State.Stopped); + return super.isEnabled(state) && ( + state === State.Running || + state === State.Stopped || + StartAction.isEnabled(this.debugService, this.contextService, this.debugService.getConfigurationManager().selectedConfiguration.name) + ); } } @@ -369,6 +404,27 @@ export class PauseAction extends AbstractDebugAction { } } +export class TerminateThreadAction extends AbstractDebugAction { + static readonly ID = 'workbench.action.debug.terminateThread'; + static LABEL = nls.localize('terminateThread', "Terminate Thread"); + + constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { + super(id, label, undefined, debugService, keybindingService); + } + + public run(thread: IThread): TPromise<any> { + if (!(thread instanceof Thread)) { + thread = this.debugService.getViewModel().focusedThread; + } + + return thread ? thread.terminate() : TPromise.as(null); + } + + protected isEnabled(state: State): boolean { + return super.isEnabled(state) && (state === State.Running || state === State.Stopped); + } +} + export class RestartFrameAction extends AbstractDebugAction { static readonly ID = 'workbench.action.debug.restartFrame'; static LABEL = nls.localize('restartFrame', "Restart Frame"); @@ -419,32 +475,6 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { } } -export class EnableBreakpointAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.enableBreakpoint'; - static LABEL = nls.localize('enableBreakpoint', "Enable Breakpoint"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, undefined, debugService, keybindingService); - } - - public run(element: IEnablement): TPromise<any> { - return this.debugService.enableOrDisableBreakpoints(true, element); - } -} - -export class DisableBreakpointAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.disableBreakpoint'; - static LABEL = nls.localize('disableBreakpoint', "Disable Breakpoint"); - - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, undefined, debugService, keybindingService); - } - - public run(element: IEnablement): TPromise<any> { - return this.debugService.enableOrDisableBreakpoints(false, element); - } -} - export class EnableAllBreakpointsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.enableAllBreakpoints'; static LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints"); @@ -460,7 +490,7 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction { protected isEnabled(state: State): boolean { const model = this.debugService.getModel(); - return super.isEnabled(state) && (<IEnablement[]>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled); + return super.isEnabled(state) && (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled); } } @@ -479,7 +509,7 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction { protected isEnabled(state: State): boolean { const model = this.debugService.getModel(); - return super.isEnabled(state) && (<IEnablement[]>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled); + return super.isEnabled(state) && (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled); } } @@ -547,44 +577,6 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction { } } -export class AddConditionalBreakpointAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.addConditionalBreakpointAction'; - static LABEL = nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint..."); - - constructor(id: string, label: string, - private editor: ICodeEditor, - private lineNumber: number, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - ) { - super(id, label, null, debugService, keybindingService); - } - - public run(): TPromise<any> { - this.editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(this.lineNumber, undefined); - return TPromise.as(null); - } -} - -export class EditConditionalBreakpointAction extends AbstractDebugAction { - static readonly ID = 'workbench.debug.viewlet.action.editConditionalBreakpointAction'; - static LABEL = nls.localize('editConditionalBreakpoint', "Edit Breakpoint..."); - - constructor(id: string, label: string, - private editor: ICodeEditor, - @IDebugService debugService: IDebugService, - @IKeybindingService keybindingService: IKeybindingService, - ) { - super(id, label, null, debugService, keybindingService); - } - - public run(breakpoint: IBreakpoint): TPromise<any> { - this.editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(breakpoint.lineNumber, breakpoint.column); - return TPromise.as(null); - } -} - - export class SetValueAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.setValue'; static LABEL = nls.localize('setValue', "Set Value"); @@ -645,15 +637,18 @@ export class AddToWatchExpressionsAction extends AbstractDebugAction { static readonly ID = 'workbench.debug.viewlet.action.addToWatchExpressions'; static LABEL = nls.localize('addToWatchExpressions', "Add to Watch"); - constructor(id: string, label: string, private expression: IExpression, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { + constructor(id: string, label: string, private variable: Variable, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { super(id, label, 'debug-action add-to-watch', debugService, keybindingService); + this.updateEnablement(); } public run(): TPromise<any> { - const name = this.expression instanceof Variable ? this.expression.evaluateName : this.expression.name; - this.debugService.addWatchExpression(name); + this.debugService.addWatchExpression(this.variable.evaluateName); return TPromise.as(undefined); + } + protected isEnabled(state: State): boolean { + return super.isEnabled(state) && this.variable && !!this.variable.evaluateName; } } diff --git a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts index 0de52acbc1..92764d9b72 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/debugActionsWidget'; import * as errors from 'vs/base/common/errors'; import * as strings from 'vs/base/common/strings'; import * as browser from 'vs/base/browser/browser'; -import * as builder from 'vs/base/browser/builder'; +import { $, Builder } from 'vs/base/browser/builder'; import * as dom from 'vs/base/browser/dom'; import * as arrays from 'vs/base/common/arrays'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; @@ -29,8 +29,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { RunOnceScheduler } from 'vs/base/common/async'; -const $ = builder.$; const DEBUG_ACTIONS_WIDGET_POSITION_KEY = 'debug.actionswidgetposition'; export const debugToolBarBackground = registerColor('debugToolBar.background', { @@ -46,11 +46,12 @@ export const debugToolBarBorder = registerColor('debugToolBar.border', { export class DebugActionsWidget extends Themable implements IWorkbenchContribution { - private $el: builder.Builder; - private dragArea: builder.Builder; + private $el: Builder; + private dragArea: Builder; private actionBar: ActionBar; private allActions: AbstractDebugAction[]; private activeActions: AbstractDebugAction[]; + private updateScheduler: RunOnceScheduler; private isVisible: boolean; private isBuilt: boolean; @@ -77,7 +78,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi this.$el.append(actionBarContainter); this.activeActions = []; - this.actionBar = new ActionBar(actionBarContainter, { + this.actionBar = new ActionBar(actionBarContainter.getHTMLElement(), { orientation: ActionsOrientation.HORIZONTAL, actionItemProvider: (action: IAction) => { if (action.id === FocusProcessAction.ID) { @@ -88,6 +89,21 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi } }); + this.updateScheduler = new RunOnceScheduler(() => { + const state = this.debugService.state; + if (state === State.Inactive || state === State.Initializing || this.configurationService.getValue<IDebugConfiguration>('debug').hideActionBar) { + return this.hide(); + } + + const actions = this.getActions(); + if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id)) { + this.actionBar.clear(); + this.actionBar.push(actions, { icon: true, label: false }); + this.activeActions = actions; + } + this.show(); + }, 20); + this.updateStyles(); this.toUnbind.push(this.actionBar); @@ -98,7 +114,8 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi } private registerListeners(): void { - this.toUnbind.push(this.debugService.onDidChangeState(state => this.update(state))); + this.toUnbind.push(this.debugService.onDidChangeState(() => this.updateScheduler.schedule())); + this.toUnbind.push(this.debugService.getViewModel().onDidFocusProcess(() => this.updateScheduler.schedule())); this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e))); this.toUnbind.push(this.actionBar.actionRunner.onDidRun((e: IRunEvent) => { // check for error @@ -200,31 +217,17 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi private onDidConfigurationChange(event: IConfigurationChangeEvent): void { if (event.affectsConfiguration('debug.hideActionBar')) { - this.update(this.debugService.state); + this.updateScheduler.schedule(); } } - private update(state: State): void { - if (state === State.Inactive || state === State.Initializing || this.configurationService.getValue<IDebugConfiguration>('debug').hideActionBar) { - return this.hide(); - } - - const actions = this.getActions(); - if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id)) { - this.actionBar.clear(); - this.actionBar.push(actions, { icon: true, label: false }); - this.activeActions = actions; - } - this.show(); - } - private show(): void { if (this.isVisible) { return; } if (!this.isBuilt) { this.isBuilt = true; - this.$el.build(builder.withElementById(this.partService.getWorkbenchElementId()).getHTMLElement()); + this.$el.build(document.getElementById(this.partService.getWorkbenchElementId())); } this.isVisible = true; diff --git a/src/vs/workbench/parts/debug/browser/debugCommands.ts b/src/vs/workbench/parts/debug/browser/debugCommands.ts index c35e01831f..ff1159b1a1 100644 --- a/src/vs/workbench/parts/debug/browser/debugCommands.ts +++ b/src/vs/workbench/parts/debug/browser/debugCommands.ts @@ -34,13 +34,12 @@ export function registerCommands(): void { handler: (accessor) => { const listService = accessor.get(IListService); const debugService = accessor.get(IDebugService); - const focused = listService.lastFocusedList; - - // Tree only - if (!(focused instanceof List)) { - const tree = focused; - const element = <IEnablement>tree.getFocus(); - debugService.enableOrDisableBreakpoints(!element.enabled, element).done(null, errors.onUnexpectedError); + const list = listService.lastFocusedList; + if (list instanceof List) { + const focused = <IEnablement[]>list.getFocusedElements(); + if (focused && focused.length) { + debugService.enableOrDisableBreakpoints(!focused[0].enabled, focused[0]).done(null, errors.onUnexpectedError); + } } } }); @@ -111,17 +110,18 @@ export function registerCommands(): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'debug.removeBreakpoint', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ContextKeyExpr.and(CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_BREAKPOINT_SELECTED.toNegated()), + when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_BREAKPOINT_SELECTED.toNegated()), primary: KeyCode.Delete, mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace }, handler: (accessor) => { const listService = accessor.get(IListService); const debugService = accessor.get(IDebugService); - const focused = listService.lastFocusedList; + const list = listService.lastFocusedList; // Tree only - if (!(focused instanceof List)) { - const element = focused.getFocus(); + if (list instanceof List) { + const focused = list.getFocusedElements(); + const element = focused.length ? focused[0] : undefined; if (element instanceof Breakpoint) { debugService.removeBreakpoints(element.getId()).done(null, errors.onUnexpectedError); } else if (element instanceof FunctionBreakpoint) { @@ -177,7 +177,7 @@ export function registerCommands(): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyMod.Shift | KeyCode.F9, - when: EditorContextKeys.textFocus, + when: EditorContextKeys.editorTextFocus, id: COLUMN_BREAKPOINT_COMMAND_ID, handler: (accessor) => { const debugService = accessor.get(IDebugService); @@ -188,13 +188,13 @@ export function registerCommands(): void { const position = control.getPosition(); const modelUri = control.getModel().uri; const bp = debugService.getModel().getBreakpoints() - .filter(bp => bp.lineNumber === position.lineNumber && bp.column === position.column && bp.uri.toString() === modelUri.toString()).pop(); + .filter(bp => bp.lineNumber === position.lineNumber && (bp.column === position.column || !bp.column && position.column <= 1) && bp.uri.toString() === modelUri.toString()).pop(); if (bp) { return TPromise.as(null); } if (debugService.getConfigurationManager().canSetBreakpointsIn(control.getModel())) { - return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column }]); + return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column > 1 ? position.column : undefined }]); } } diff --git a/src/vs/workbench/parts/debug/browser/debugContentProvider.ts b/src/vs/workbench/parts/debug/browser/debugContentProvider.ts index ead0b8b239..06e67d30de 100644 --- a/src/vs/workbench/parts/debug/browser/debugContentProvider.ts +++ b/src/vs/workbench/parts/debug/browser/debugContentProvider.ts @@ -23,7 +23,7 @@ import { Source } from 'vs/workbench/parts/debug/common/debugSource'; * debug:arbitrary_path?session=123e4567-e89b-12d3-a456-426655440000&ref=1016 * \___/ \____________/ \__________________________________________/ \______/ * | | | | - * scheme source.path session id source.referencequery + * scheme source.path session id source.reference * * the arbitrary_path and the session id are encoded with 'encodeURIComponent' * @@ -58,7 +58,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC if (!process) { return TPromise.wrapError<ITextModel>(new Error(localize('unable', "Unable to resolve the resource without a debug session"))); } - const source = process.sources.get(resource.toString()); + const source = process.getSourceForUri(resource); let rawSource: DebugProtocol.Source; if (source) { rawSource = source.raw; diff --git a/src/vs/workbench/parts/debug/browser/debugEditorActions.ts b/src/vs/workbench/parts/debug/browser/debugEditorActions.ts index 4c2aa1a3fb..711d3ad96e 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorActions.ts @@ -8,12 +8,11 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { Range } from 'vs/editor/common/core/range'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { ServicesAccessor, registerEditorAction, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; +import { ServicesAccessor, registerEditorAction, EditorAction } from 'vs/editor/browser/editorExtensions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, CONTEXT_DEBUG_STATE, State, REPL_ID, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, CONTEXT_DEBUG_STATE, State, REPL_ID, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint } from 'vs/workbench/parts/debug/common/debug'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; class ToggleBreakpointAction extends EditorAction { @@ -24,7 +23,7 @@ class ToggleBreakpointAction extends EditorAction { alias: 'Debug: Toggle Breakpoint', precondition: null, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyCode.F9 } }); @@ -70,6 +69,26 @@ class ConditionalBreakpointAction extends EditorAction { } } +class LogPointAction extends EditorAction { + + constructor() { + super({ + id: 'editor.debug.action.toggleLogPoint', + label: nls.localize('logPointEditorAction', "Debug: Add Logpoint..."), + alias: 'Debug: Add Logpoint...', + precondition: null + }); + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + const debugService = accessor.get(IDebugService); + + const { lineNumber, column } = editor.getPosition(); + if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) { + editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, column, BreakpointWidgetContext.LOG_MESSAGE); + } + } +} class RunToCursorAction extends EditorAction { @@ -88,26 +107,27 @@ class RunToCursorAction extends EditorAction { public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> { const debugService = accessor.get(IDebugService); - if (debugService.state !== State.Stopped) { return TPromise.as(null); } - const position = editor.getPosition(); - const uri = editor.getModel().uri; + let breakpointToRemove: IBreakpoint; const oneTimeListener = debugService.getViewModel().focusedProcess.session.onDidEvent(event => { if (event.event === 'stopped' || event.event === 'exit') { - const toRemove = debugService.getModel().getBreakpoints() - .filter(bp => bp.lineNumber === position.lineNumber && bp.uri.toString() === uri.toString()).pop(); - if (toRemove) { - debugService.removeBreakpoints(toRemove.getId()); + if (breakpointToRemove) { + debugService.removeBreakpoints(breakpointToRemove.getId()); } oneTimeListener.dispose(); } }); + const position = editor.getPosition(); + const uri = editor.getModel().uri; const bpExists = !!(debugService.getModel().getBreakpoints().filter(bp => bp.column === position.column && bp.lineNumber === position.lineNumber && bp.uri.toString() === uri.toString()).pop()); - return (bpExists ? TPromise.as(null) : debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }])).then(() => { + return (bpExists ? TPromise.as(null) : debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }])).then((breakpoints) => { + if (breakpoints && breakpoints.length) { + breakpointToRemove = breakpoints[0]; + } debugService.getViewModel().focusedThread.continue(); }); } @@ -172,7 +192,7 @@ class ShowDebugHoverAction extends EditorAction { alias: 'Debug: Show Hover', precondition: CONTEXT_IN_DEBUG_MODE, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_I) } }); @@ -190,30 +210,10 @@ class ShowDebugHoverAction extends EditorAction { } } -class CloseBreakpointWidgetCommand extends EditorCommand { - - constructor() { - super({ - id: 'closeBreakpointWidget', - precondition: CONTEXT_BREAKPOINT_WIDGET_VISIBLE, - kbOpts: { - weight: KeybindingsRegistry.WEIGHT.editorContrib(8), - kbExpr: EditorContextKeys.focus, - primary: KeyCode.Escape, - secondary: [KeyMod.Shift | KeyCode.Escape] - } - }); - } - - public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { - return editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).closeBreakpointWidget(); - } -} - registerEditorAction(ToggleBreakpointAction); registerEditorAction(ConditionalBreakpointAction); +registerEditorAction(LogPointAction); registerEditorAction(RunToCursorAction); registerEditorAction(SelectionToReplAction); registerEditorAction(SelectionToWatchExpressionsAction); registerEditorAction(ShowDebugHoverAction); -registerEditorCommand(new CloseBreakpointWidgetCommand()); diff --git a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts index 4c2f060596..9f6e57b02d 100644 --- a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts +++ b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts @@ -3,16 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); -import Filters = require('vs/base/common/filters'); +import * as nls from 'vs/nls'; +import * as Filters from 'vs/base/common/filters'; import { TPromise } from 'vs/base/common/winjs.base'; -import Quickopen = require('vs/workbench/browser/quickopen'); -import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen'); -import Model = require('vs/base/parts/quickopen/browser/quickOpenModel'); +import * as Quickopen from 'vs/workbench/browser/quickopen'; +import * as QuickOpen from 'vs/base/parts/quickopen/common/quickOpen'; +import * as Model from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IDebugService, ILaunch } from 'vs/workbench/parts/debug/common/debug'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import * as errors from 'vs/base/common/errors'; -import { QuickOpenEntry, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { StartAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -94,7 +93,7 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler { } public getResults(input: string): TPromise<Model.QuickOpenModel> { - const configurations: QuickOpenEntry[] = []; + const configurations: Model.QuickOpenEntry[] = []; const configManager = this.debugService.getConfigurationManager(); const launches = configManager.getLaunches(); @@ -113,7 +112,7 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler { const label = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration..."); const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, Filters.matchesContiguousSubString(input, label)); if (index === 0) { - configurations.push(new QuickOpenEntryGroup(entry, undefined, true)); + configurations.push(new Model.QuickOpenEntryGroup(entry, undefined, true)); } else { configurations.push(entry); } diff --git a/src/vs/workbench/parts/debug/browser/debugStatus.ts b/src/vs/workbench/parts/debug/browser/debugStatus.ts index abe174e416..cff16a0e72 100644 --- a/src/vs/workbench/parts/debug/browser/debugStatus.ts +++ b/src/vs/workbench/parts/debug/browser/debugStatus.ts @@ -13,6 +13,7 @@ import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IDebugService, State, IDebugConfiguration } from 'vs/workbench/parts/debug/common/debug'; import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { STATUS_BAR_DEBUGGING_FOREGROUND, isStatusbarInDebugMode } from 'vs/workbench/parts/debug/browser/statusbarColorProvider'; const $ = dom.$; @@ -61,7 +62,11 @@ export class DebugStatus extends Themable implements IStatusbarItem { protected updateStyles(): void { super.updateStyles(); if (this.icon) { - this.icon.style.backgroundColor = this.getColor(STATUS_BAR_FOREGROUND); + if (isStatusbarInDebugMode(this.debugService)) { + this.icon.style.backgroundColor = this.getColor(STATUS_BAR_DEBUGGING_FOREGROUND); + } else { + this.icon.style.backgroundColor = this.getColor(STATUS_BAR_FOREGROUND); + } } } @@ -85,15 +90,16 @@ export class DebugStatus extends Themable implements IStatusbarItem { this.icon = dom.append(a, $('.icon')); this.label = dom.append(a, $('span.label')); this.setLabel(); - this.updateStyles(); } + + this.updateStyles(); } private setLabel(): void { if (this.label && this.statusBarItem) { const manager = this.debugService.getConfigurationManager(); const name = manager.selectedConfiguration.name; - if (name) { + if (name && manager.selectedConfiguration.launch) { this.statusBarItem.style.display = 'block'; this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedConfiguration.launch.name})` : name; } else { diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index a370de710f..9da5b2c0eb 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -5,7 +5,6 @@ import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; -import { Builder } from 'vs/base/browser/builder'; import { Action, IAction } from 'vs/base/common/actions'; import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -27,6 +26,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { memoize } from 'vs/base/common/decorators'; export class DebugViewlet extends PersistentViewsViewlet { @@ -56,11 +56,10 @@ export class DebugViewlet extends PersistentViewsViewlet { this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateTitleArea())); } - async create(parent: Builder): TPromise<void> { + async create(parent: HTMLElement): TPromise<void> { await super.create(parent); - const el = parent.getHTMLElement(); - DOM.addClass(el, 'debug-viewlet'); + DOM.addClass(parent, 'debug-viewlet'); } public focus(): void { @@ -71,12 +70,17 @@ export class DebugViewlet extends PersistentViewsViewlet { } } + @memoize + private get actions(): IAction[] { + return [ + this._register(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL)), + this._register(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL)), + this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL)) + ]; + } + public getActions(): IAction[] { - const actions = []; - actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL)); - actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL)); - actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL))); - return actions; + return this.actions; } public getSecondaryActions(): IAction[] { @@ -111,22 +115,26 @@ export class DebugViewlet extends PersistentViewsViewlet { } } - addPanel(panel: ViewsViewletPanel, size: number, index?: number): void { - super.addPanel(panel, size, index); + addPanels(panels: { panel: ViewsViewletPanel, size: number, index?: number }[]): void { + super.addPanels(panels); - // attach event listener to - if (panel.id === BREAKPOINTS_VIEW_ID) { - this.breakpointView = panel; - this.updateBreakpointsMaxSize(); - } else { - this.panelListeners.set(panel.id, panel.onDidChange(() => this.updateBreakpointsMaxSize())); + for (const { panel } of panels) { + // attach event listener to + if (panel.id === BREAKPOINTS_VIEW_ID) { + this.breakpointView = panel; + this.updateBreakpointsMaxSize(); + } else { + this.panelListeners.set(panel.id, panel.onDidChange(() => this.updateBreakpointsMaxSize())); + } } } - removePanel(panel: ViewsViewletPanel): void { - super.removePanel(panel); - dispose(this.panelListeners.get(panel.id)); - this.panelListeners.delete(panel.id); + removePanels(panels: ViewsViewletPanel[]): void { + super.removePanels(panels); + for (const panel of panels) { + dispose(this.panelListeners.get(panel.id)); + this.panelListeners.delete(panel.id); + } } private updateBreakpointsMaxSize(): void { diff --git a/src/vs/workbench/parts/debug/browser/media/add-focus.svg b/src/vs/workbench/parts/debug/browser/media/add-focus.svg index 5e9f5851e8..769bd3b12b 100644 --- a/src/vs/workbench/parts/debug/browser/media/add-focus.svg +++ b/src/vs/workbench/parts/debug/browser/media/add-focus.svg @@ -1 +1 @@ -<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1 \ No newline at end of file +add-focus \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/add-inverse.svg b/src/vs/workbench/parts/debug/browser/media/add-inverse.svg index 3475c1e196..7d3fd77ffd 100644 --- a/src/vs/workbench/parts/debug/browser/media/add-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/add-inverse.svg @@ -1 +1 @@ -Layer 1 \ No newline at end of file +add \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/add.svg b/src/vs/workbench/parts/debug/browser/media/add.svg index bdecdb0e45..2b679663e8 100644 --- a/src/vs/workbench/parts/debug/browser/media/add.svg +++ b/src/vs/workbench/parts/debug/browser/media/add.svg @@ -1 +1 @@ -Layer 1 \ No newline at end of file +add \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-dark.svg deleted file mode 100644 index 720679e07e..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-disabled.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-disabled.svg new file mode 100644 index 0000000000..61eb04a081 --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-disabled.svg @@ -0,0 +1 @@ +breakpoint-conditional-disabled \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-unverified.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-unverified.svg new file mode 100644 index 0000000000..b3d735c414 --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional-unverified.svg @@ -0,0 +1 @@ +breakpoint-conditional-unverified \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional.svg index 77dd991c2b..db2c251350 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-conditional.svg @@ -1,10 +1 @@ - - - - - - +breakpoint-conditional \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-dark.svg deleted file mode 100644 index 5ccf397efa..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled-dark.svg deleted file mode 100644 index bf58a18178..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled.svg index 9780270357..a06c2bea57 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-disabled.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoint-disabled \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-dark.svg deleted file mode 100644 index 6b2651a9a3..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-dark.svg +++ /dev/null @@ -1 +0,0 @@ -BreakpointFunction_16xMD diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled-dark.svg deleted file mode 100644 index fe6aaa60d7..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled-dark.svg +++ /dev/null @@ -1 +0,0 @@ -BreakpointFunction_disabled_16xMD diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled.svg index e45fd9cb12..f25dc4ed16 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-disabled.svg @@ -1 +1 @@ -BreakpointFunction_disabled_16xMD +breakpoint-function-disabled \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified-dark.svg deleted file mode 100644 index 13903346b2..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified-dark.svg +++ /dev/null @@ -1 +0,0 @@ -BreakpointFunctionUnverified_16xMD diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified.svg index 0af1324d78..b97b5cf9d9 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-function-unverified.svg @@ -1 +1 @@ -BreakpointFunctionUnverified_16xMD +breakpoint-function-unverified \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-function.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-function.svg index 6bc70465fa..add61599b7 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-function.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-function.svg @@ -1 +1 @@ -BreakpointFunction_16xMD \ No newline at end of file +breakpoint-function \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-hint.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-hint.svg index 24f2006952..39f954b0a1 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-hint.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-hint.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoint-hint \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-log-disabled.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-log-disabled.svg new file mode 100644 index 0000000000..d1dc5cd656 --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-log-disabled.svg @@ -0,0 +1 @@ +breakpoint-log-disabled \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-log-unverified.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-log-unverified.svg new file mode 100644 index 0000000000..534c1f762f --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-log-unverified.svg @@ -0,0 +1 @@ +breakpoint-log-unverified \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-log.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-log.svg new file mode 100644 index 0000000000..51e2e70edb --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-log.svg @@ -0,0 +1 @@ +breakpoint-log \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported-dark.svg deleted file mode 100644 index fffcfb8cb4..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported-dark.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported.svg index cc0c89e1b7..49a195c47c 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-unsupported.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - +breakpoint-unsupported \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified-dark.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified-dark.svg deleted file mode 100644 index 4a2575a305..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified.svg index 617e7ede7b..a625db104b 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint-unverified.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoint-unverified \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoint.svg b/src/vs/workbench/parts/debug/browser/media/breakpoint.svg index 7629294bcc..5cb33572fb 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoint.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoint.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoint \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/breakpointWidget.css b/src/vs/workbench/parts/debug/browser/media/breakpointWidget.css index 9359b4de9e..75a0b6ab90 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpointWidget.css +++ b/src/vs/workbench/parts/debug/browser/media/breakpointWidget.css @@ -14,28 +14,11 @@ justify-content: center; flex-direction: column; padding: 0 10px; + flex-shrink: 0; } -.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .inputBoxContainer { +.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .inputContainer { flex: 1; -} - -.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .monaco-inputbox { - border: none; -} - -.monaco-editor .breakpoint-widget .input { - font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback"; - line-height: 22px; - background-color: transparent; - padding: 8px; -} - -.monaco-workbench.mac .monaco-editor .breakpoint-widget .input { - font-size: 11px; -} - -.monaco-workbench.windows .monaco-editor .breakpoint-widget .input, -.monaco-workbench.linux .monaco-editor .breakpoint-widget .input { - font-size: 13px; + margin-top: 6px; + margin-bottom: 6px; } diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoints-activate-inverse.svg b/src/vs/workbench/parts/debug/browser/media/breakpoints-activate-inverse.svg index 07344800a2..b919b3c4f2 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoints-activate-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoints-activate-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoints-activate diff --git a/src/vs/workbench/parts/debug/browser/media/breakpoints-activate.svg b/src/vs/workbench/parts/debug/browser/media/breakpoints-activate.svg index b32b1cd6de..34809f9b1b 100644 --- a/src/vs/workbench/parts/debug/browser/media/breakpoints-activate.svg +++ b/src/vs/workbench/parts/debug/browser/media/breakpoints-activate.svg @@ -1 +1 @@ - \ No newline at end of file +breakpoints-activate \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/clear-repl-inverse.svg b/src/vs/workbench/parts/debug/browser/media/clear-repl-inverse.svg index 7df4455d7c..f6d7128f4b 100644 --- a/src/vs/workbench/parts/debug/browser/media/clear-repl-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/clear-repl-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +clear-repl \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/clear-repl.svg b/src/vs/workbench/parts/debug/browser/media/clear-repl.svg index 6e4d3a1d48..7867d13d75 100644 --- a/src/vs/workbench/parts/debug/browser/media/clear-repl.svg +++ b/src/vs/workbench/parts/debug/browser/media/clear-repl.svg @@ -1 +1 @@ - \ No newline at end of file +clear-repl \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/configure-inverse.svg b/src/vs/workbench/parts/debug/browser/media/configure-inverse.svg index 61baaea2b8..bbfbd366eb 100644 --- a/src/vs/workbench/parts/debug/browser/media/configure-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/configure-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +configure \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/configure.svg b/src/vs/workbench/parts/debug/browser/media/configure.svg index 3dec2ba50f..c97bb48bdc 100644 --- a/src/vs/workbench/parts/debug/browser/media/configure.svg +++ b/src/vs/workbench/parts/debug/browser/media/configure.svg @@ -1 +1 @@ - \ No newline at end of file +configure \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/continue-inverse.svg b/src/vs/workbench/parts/debug/browser/media/continue-inverse.svg index f82c45c110..3be0c24f6f 100644 --- a/src/vs/workbench/parts/debug/browser/media/continue-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/continue-inverse.svg @@ -1,3 +1 @@ - -]> \ No newline at end of file +continue \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/continue.svg b/src/vs/workbench/parts/debug/browser/media/continue.svg index 33affa1a51..f1db6d9e47 100644 --- a/src/vs/workbench/parts/debug/browser/media/continue.svg +++ b/src/vs/workbench/parts/debug/browser/media/continue.svg @@ -1,3 +1,3 @@ -]> \ No newline at end of file +]> diff --git a/src/vs/workbench/parts/debug/browser/media/current-and-breakpoint.svg b/src/vs/workbench/parts/debug/browser/media/current-and-breakpoint.svg index 7a3e6f2635..7dbc3fdedd 100644 --- a/src/vs/workbench/parts/debug/browser/media/current-and-breakpoint.svg +++ b/src/vs/workbench/parts/debug/browser/media/current-and-breakpoint.svg @@ -1 +1 @@ - \ No newline at end of file +current-and-breakpoint \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/current-arrow.svg b/src/vs/workbench/parts/debug/browser/media/current-arrow.svg index bd1ca579f1..6a73340306 100644 --- a/src/vs/workbench/parts/debug/browser/media/current-arrow.svg +++ b/src/vs/workbench/parts/debug/browser/media/current-arrow.svg @@ -1 +1 @@ - \ No newline at end of file +current-arrow \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/debug-dark.svg b/src/vs/workbench/parts/debug/browser/media/debug-dark.svg index 9a969fb358..cedddacf03 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug-dark.svg +++ b/src/vs/workbench/parts/debug/browser/media/debug-dark.svg @@ -1 +1 @@ - \ No newline at end of file +debug-dark \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css index 8e3928acf8..5e19ded322 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css @@ -6,6 +6,7 @@ /* Activity Bar */ .monaco-workbench > .activitybar .monaco-action-bar .action-label.debug { -webkit-mask: url('debug-dark.svg') no-repeat 50% 50%; + -webkit-mask-size: 28px; } .monaco-editor .debug-top-stack-frame-line, @@ -59,13 +60,12 @@ .monaco-editor .debug-breakpoint-column::before, .monaco-editor .debug-top-stack-frame-column::before { content: " "; - width: 0.9em; - height: 0.8em; + width: 1.3em; + height: 1.3em; display: inline-block; + vertical-align: text-bottom; margin-right: 2px; margin-left: 2px; - background-size: 110% !important; - background-position: initial !important; } .debug-function-breakpoint { @@ -74,7 +74,6 @@ .debug-function-breakpoint-unverified { background: url('breakpoint-function-unverified.svg') center center no-repeat; - } .debug-function-breakpoint-disabled { @@ -86,6 +85,19 @@ background: url('breakpoint-conditional.svg') center center no-repeat; } +.debug-breakpoint-log, +.monaco-editor .debug-breakpoint-column.debug-breakpoint-log-column::before { + background: url('breakpoint-log.svg') center center no-repeat; +} + +.debug-breakpoint-log-disabled { + background: url('breakpoint-log-disabled.svg') center center no-repeat; +} + +.debug-breakpoint-log-unverified { + background: url('breakpoint-log-unverified.svg') center center no-repeat; +} + .debug-breakpoint-unsupported, .monaco-editor .debug-breakpoint-column.debug-breakpoint-unsupported-column::before { background: url('breakpoint-unsupported.svg') center center no-repeat; @@ -93,15 +105,14 @@ .monaco-editor .debug-top-stack-frame.debug-breakpoint, .monaco-editor .debug-top-stack-frame.debug-breakpoint-conditional, -.monaco-editor .debug-breakpoint-column.debug-breakpoint-column.debug-top-stack-frame-column::before, -.monaco-editor.vs-dark .debug-top-stack-frame.debug-breakpoint, -.monaco-editor.vs-dark .debug-top-stack-frame.debug-breakpoint-conditional, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-column.debug-top-stack-frame-column::before { +.monaco-editor .debug-top-stack-frame.debug-breakpoint-log, +.monaco-editor .debug-breakpoint-column.debug-breakpoint-column.debug-top-stack-frame-column::before { background: url('current-and-breakpoint.svg') center center no-repeat; } .monaco-editor .debug-focused-stack-frame.debug-breakpoint, -.monaco-editor .debug-focused-stack-frame.debug-breakpoint-conditional { +.monaco-editor .debug-focused-stack-frame.debug-breakpoint-conditional, +.monaco-editor .debug-focused-stack-frame.debug-breakpoint-log { background: url('stackframe-and-breakpoint.svg') center center no-repeat; } @@ -117,7 +128,7 @@ /* Debug status */ /* A very precise css rule to overwrite the display set in statusbar.css */ -.monaco-workbench > .part.statusbar > .statusbar-item > .debug-statusbar-item > a:not([disabled]):not(.disabled) { +.monaco-workbench > .part.statusbar > .statusbar-item > .debug-statusbar-item > a { display: flex; padding: 0 5px 0 5px; } @@ -246,61 +257,6 @@ background-color: rgba(255, 255, 0, 0.3) } -.vs-dark .debug-breakpoint, -.hc-black .debug-breakpoint, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-column::before { - background: url('breakpoint-dark.svg') center center no-repeat; -} - -.vs-dark .debug-breakpoint-conditional, -.hc-black .debug-breakpoint-conditional, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-conditional-column::before { - background: url('breakpoint-conditional-dark.svg') center center no-repeat; -} - -.vs-dark .debug-breakpoint-unsupported, -.hc-black .debug-breakpoint-unsupported, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unsupported-column::before { - background: url('breakpoint-unsupported-dark.svg') center center no-repeat; -} - -.vs-dark .debug-breakpoint-disabled, -.hc-black .debug-breakpoint-disabled, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-disabled-column::before { - background: url('breakpoint-disabled-dark.svg') center center no-repeat; -} - -.vs-dark .debug-breakpoint-unverified, -.hc-black .debug-breakpoint-unverified, -.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unverified-column::before { - background: url('breakpoint-unverified-dark.svg') center center no-repeat; -} - -.monaco-editor.vs-dark .debug-focused-stack-frame { - background: url('stackframe-arrow-dark.svg') center center no-repeat; -} - -.monaco-editor.vs-dark .debug-focused-stack-frame.debug-breakpoint, -.monaco-editor.vs-dark .debug-focused-stack-frame.debug-breakpoint-conditional { - background: url('stackframe-and-breakpoint-dark.svg') center center no-repeat; -} - -.vs-dark .debug-function-breakpoint, -.hc-black .debug-function-breakpoint { - background: url('breakpoint-function-dark.svg') center center no-repeat; -} - -.vs-dark .debug-function-breakpoint-unverified, -.hc-black .debug-function-breakpoint-unverified { - background: url('breakpoint-function-unverified.svg') center center no-repeat; - -} - -.vs-dark .debug-function-breakpoint-disabled, -.hc-black .debug-function-breakpoint-disabled { - background: url('breakpoint-function-disabled.svg') center center no-repeat; -} - /* High Contrast Theming */ .monaco-editor.hc-black .debug-focused-stack-frame-line { diff --git a/src/vs/workbench/parts/debug/browser/media/debugActionsWidget.css b/src/vs/workbench/parts/debug/browser/media/debugActionsWidget.css index 3d473236e0..b8ae3dfd39 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugActionsWidget.css +++ b/src/vs/workbench/parts/debug/browser/media/debugActionsWidget.css @@ -17,15 +17,16 @@ margin-right: 7px; } -.monaco-workbench .debug-actions-widget .monaco-action-bar .action-item .select-box { +.monaco-workbench .debug-actions-widget .monaco-action-bar .action-item .monaco-select-box { margin-top: 6px; } .monaco-workbench .debug-actions-widget .drag-area { cursor: -webkit-grab; height: 32px; - width: 10px; + width: 16px; background: url('drag.svg') center center no-repeat; + background-size: 16px 16px; } .monaco-workbench .debug-actions-widget .drag-area.dragged { diff --git a/src/vs/workbench/parts/debug/browser/media/debugHover.css b/src/vs/workbench/parts/debug/browser/media/debugHover.css index 461ac769fa..9ddb5c8fb9 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugHover.css +++ b/src/vs/workbench/parts/debug/browser/media/debugHover.css @@ -10,7 +10,7 @@ z-index: 50; animation-duration: 0.15s; animation-name: fadeIn; - -webkit-user-select: text; + user-select: text; word-break: break-all; padding: 4px 5px; } @@ -35,7 +35,7 @@ } .monaco-editor .debug-hover-widget .debug-hover-tree .monaco-tree .monaco-tree-row > .content { - -webkit-user-select: text; + user-select: text; white-space: pre; } diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 6d526f93d2..c60a9b8518 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -67,7 +67,9 @@ .monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon { height: 20px; width: 20px; - background: url('continue.svg') center center no-repeat; + background: url('continue.svg') no-repeat; + background-size: 16px 16px; + background-position: center center; flex-shrink: 0; transition: transform 50ms ease; -webkit-transition: -webkit-transform 50ms ease; @@ -75,16 +77,16 @@ .vs-dark .monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon, .hc-black .monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon { - background: url('continue-inverse.svg') center center no-repeat; + background-image: url('continue-inverse.svg'); } -.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration .select-box { +.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration .monaco-select-box { border: none; margin-top: 0px; cursor: pointer; } -.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration.disabled .select-box { +.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration.disabled .monaco-select-box { opacity: 0.7; font-style: italic; cursor: initial; @@ -368,8 +370,8 @@ } .debug-viewlet .debug-breakpoints .breakpoint > .icon { - width: 18px; - height: 18px; + width: 19px; + height: 19px; } .debug-viewlet .debug-breakpoints .breakpoint > .file-path { diff --git a/src/vs/workbench/parts/debug/browser/media/disconnect-inverse.svg b/src/vs/workbench/parts/debug/browser/media/disconnect-inverse.svg index e00fd4062d..2d1e78b5b6 100644 --- a/src/vs/workbench/parts/debug/browser/media/disconnect-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/disconnect-inverse.svg @@ -1 +1 @@ -Plan de travail 1 \ No newline at end of file +disconnect \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/disconnect.svg b/src/vs/workbench/parts/debug/browser/media/disconnect.svg index 2a87ce11ef..b2deb2b91d 100644 --- a/src/vs/workbench/parts/debug/browser/media/disconnect.svg +++ b/src/vs/workbench/parts/debug/browser/media/disconnect.svg @@ -1 +1 @@ -Plan de travail 1 \ No newline at end of file +disconnect \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/drag.svg b/src/vs/workbench/parts/debug/browser/media/drag.svg index 7f4145d742..522bf98284 100644 --- a/src/vs/workbench/parts/debug/browser/media/drag.svg +++ b/src/vs/workbench/parts/debug/browser/media/drag.svg @@ -1,8 +1 @@ - - - - - - - - \ No newline at end of file +drag \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/exceptionWidget.css b/src/vs/workbench/parts/debug/browser/media/exceptionWidget.css index d1297ade08..15e65a0d2e 100644 --- a/src/vs/workbench/parts/debug/browser/media/exceptionWidget.css +++ b/src/vs/workbench/parts/debug/browser/media/exceptionWidget.css @@ -10,11 +10,6 @@ .monaco-editor .zone-widget .zone-widget-container.exception-widget { padding: 6px 10px; white-space: pre-wrap; - -webkit-user-select: text; - -ms-user-select: text; - -khtml-user-select: text; - -moz-user-select: text; - -o-user-select: text; user-select: text; } diff --git a/src/vs/workbench/parts/debug/browser/media/pause-inverse.svg b/src/vs/workbench/parts/debug/browser/media/pause-inverse.svg index 7418a23615..5072d2f8cd 100644 --- a/src/vs/workbench/parts/debug/browser/media/pause-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/pause-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +pause \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/pause.svg b/src/vs/workbench/parts/debug/browser/media/pause.svg index f8e3b859b1..0875d60cb8 100644 --- a/src/vs/workbench/parts/debug/browser/media/pause.svg +++ b/src/vs/workbench/parts/debug/browser/media/pause.svg @@ -1 +1 @@ - \ No newline at end of file +pause \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/remove-all-inverse.svg b/src/vs/workbench/parts/debug/browser/media/remove-all-inverse.svg index 74e8dd8a02..99369626bf 100644 --- a/src/vs/workbench/parts/debug/browser/media/remove-all-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/remove-all-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +remove-all \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/remove-all.svg b/src/vs/workbench/parts/debug/browser/media/remove-all.svg index 7250ff6b54..a71c2feeed 100644 --- a/src/vs/workbench/parts/debug/browser/media/remove-all.svg +++ b/src/vs/workbench/parts/debug/browser/media/remove-all.svg @@ -1 +1 @@ - \ No newline at end of file +remove-all_16x \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/remove-focus.svg b/src/vs/workbench/parts/debug/browser/media/remove-focus.svg index 865c5aaea5..e1af90b805 100644 --- a/src/vs/workbench/parts/debug/browser/media/remove-focus.svg +++ b/src/vs/workbench/parts/debug/browser/media/remove-focus.svg @@ -1 +1 @@ - \ No newline at end of file +remove-focus \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/remove-inverse.svg b/src/vs/workbench/parts/debug/browser/media/remove-inverse.svg index 751e89b3b0..e78bb99873 100644 --- a/src/vs/workbench/parts/debug/browser/media/remove-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/remove-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +remove \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/remove.svg b/src/vs/workbench/parts/debug/browser/media/remove.svg index fde34404d4..31d6abd6ba 100644 --- a/src/vs/workbench/parts/debug/browser/media/remove.svg +++ b/src/vs/workbench/parts/debug/browser/media/remove.svg @@ -1 +1 @@ - \ No newline at end of file +remove \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/repl-inverse.svg b/src/vs/workbench/parts/debug/browser/media/repl-inverse.svg index f9fcfba75e..a8939860d0 100644 --- a/src/vs/workbench/parts/debug/browser/media/repl-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/repl-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +repl \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/repl.css b/src/vs/workbench/parts/debug/browser/media/repl.css index 098057be48..a0b7bd3681 100644 --- a/src/vs/workbench/parts/debug/browser/media/repl.css +++ b/src/vs/workbench/parts/debug/browser/media/repl.css @@ -23,7 +23,7 @@ .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content { line-height: 18px; - -webkit-user-select: text; + user-select: text; /* Wrap words but also do not trim whitespace #6275 */ word-wrap: break-word; white-space: pre-wrap; @@ -163,6 +163,7 @@ /* ANSI Codes */ .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-bold { font-weight: bold; } +.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-underline { text-decoration: underline; } .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: gray; } .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #BE1717; } diff --git a/src/vs/workbench/parts/debug/browser/media/repl.svg b/src/vs/workbench/parts/debug/browser/media/repl.svg index 93558e96b4..8175eb32f9 100644 --- a/src/vs/workbench/parts/debug/browser/media/repl.svg +++ b/src/vs/workbench/parts/debug/browser/media/repl.svg @@ -1 +1 @@ - \ No newline at end of file +repl \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/restart-inverse.svg b/src/vs/workbench/parts/debug/browser/media/restart-inverse.svg index 1443bb3158..5cda703e42 100644 --- a/src/vs/workbench/parts/debug/browser/media/restart-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/restart-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +restart \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/restart.svg b/src/vs/workbench/parts/debug/browser/media/restart.svg index 3d7a499db2..1f6f664acf 100644 --- a/src/vs/workbench/parts/debug/browser/media/restart.svg +++ b/src/vs/workbench/parts/debug/browser/media/restart.svg @@ -1 +1 @@ - \ No newline at end of file +restart \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint-dark.svg b/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint-dark.svg deleted file mode 100644 index 1d6a7c3ec3..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint.svg b/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint.svg index 2d5823561e..41bf68010d 100644 --- a/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint.svg +++ b/src/vs/workbench/parts/debug/browser/media/stackframe-and-breakpoint.svg @@ -1 +1 @@ - \ No newline at end of file +stackframe-and-breakpoint \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stackframe-arrow-dark.svg b/src/vs/workbench/parts/debug/browser/media/stackframe-arrow-dark.svg deleted file mode 100644 index f965fddd63..0000000000 --- a/src/vs/workbench/parts/debug/browser/media/stackframe-arrow-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stackframe-arrow.svg b/src/vs/workbench/parts/debug/browser/media/stackframe-arrow.svg index e39215f9a7..e576510612 100644 --- a/src/vs/workbench/parts/debug/browser/media/stackframe-arrow.svg +++ b/src/vs/workbench/parts/debug/browser/media/stackframe-arrow.svg @@ -1 +1 @@ - \ No newline at end of file +stackframe-arrow \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-into-inverse.svg b/src/vs/workbench/parts/debug/browser/media/step-into-inverse.svg index b7de8c5fd1..8cfab5c40b 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-into-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-into-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +step-into \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-into.svg b/src/vs/workbench/parts/debug/browser/media/step-into.svg index b92fb4ef80..a4beee5441 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-into.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-into.svg @@ -1 +1 @@ - \ No newline at end of file +step-into \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-out-inverse.svg b/src/vs/workbench/parts/debug/browser/media/step-out-inverse.svg index fc66ca1b80..045a84ff03 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-out-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-out-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +step-out \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-out.svg b/src/vs/workbench/parts/debug/browser/media/step-out.svg index 0fdc63f6ef..850aed93c2 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-out.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-out.svg @@ -1 +1 @@ - \ No newline at end of file +step-out \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-over-inverse.svg b/src/vs/workbench/parts/debug/browser/media/step-over-inverse.svg index 98c1026db4..f3a1aa36f2 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-over-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-over-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +step-over \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/step-over.svg b/src/vs/workbench/parts/debug/browser/media/step-over.svg index a716cbcf55..3343de71d8 100644 --- a/src/vs/workbench/parts/debug/browser/media/step-over.svg +++ b/src/vs/workbench/parts/debug/browser/media/step-over.svg @@ -1 +1 @@ - \ No newline at end of file +step-over \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stop-inverse.svg b/src/vs/workbench/parts/debug/browser/media/stop-inverse.svg index a0e6bcb42d..c8e3720287 100644 --- a/src/vs/workbench/parts/debug/browser/media/stop-inverse.svg +++ b/src/vs/workbench/parts/debug/browser/media/stop-inverse.svg @@ -1 +1 @@ - \ No newline at end of file +stop \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/stop.svg b/src/vs/workbench/parts/debug/browser/media/stop.svg index 333812dcda..57c29044b1 100644 --- a/src/vs/workbench/parts/debug/browser/media/stop.svg +++ b/src/vs/workbench/parts/debug/browser/media/stop.svg @@ -1 +1 @@ - \ No newline at end of file +stop \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/statusbarColorProvider.ts b/src/vs/workbench/parts/debug/browser/statusbarColorProvider.ts index cfdbaac303..8779dc502e 100644 --- a/src/vs/workbench/parts/debug/browser/statusbarColorProvider.ts +++ b/src/vs/workbench/parts/debug/browser/statusbarColorProvider.ts @@ -56,7 +56,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri super.updateStyles(); const container = this.partService.getContainer(Parts.STATUSBAR_PART); - if (this.isDebugging()) { + if (isStatusbarInDebugMode(this.debugService)) { addClass(container, 'debugging'); } else { removeClass(container, 'debugging'); @@ -84,7 +84,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri private getColorKey(noFolderColor: string, debuggingColor: string, normalColor: string): string { // Not debugging - if (!this.isDebugging()) { + if (!isStatusbarInDebugMode(this.debugService)) { if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { return normalColor; } @@ -95,24 +95,20 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri // Debugging return debuggingColor; } +} - private isDebugging(): boolean { - if (this.debugService.state === State.Inactive || this.debugService.state === State.Initializing) { - return false; - } - - if (this.isRunningWithoutDebug()) { - return false; - } - - return true; +export function isStatusbarInDebugMode(debugService: IDebugService): boolean { + if (debugService.state === State.Inactive || debugService.state === State.Initializing) { + return false; } - private isRunningWithoutDebug(): boolean { - const process = this.debugService.getViewModel().focusedProcess; - - return process && process.configuration && process.configuration.noDebug; + const process = debugService.getViewModel().focusedProcess; + const isRunningWithoutDebug = process && process.configuration && process.configuration.noDebug; + if (isRunningWithoutDebug) { + return false; } + + return true; } registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { @@ -120,4 +116,4 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (statusBarItemDebuggingForeground) { collector.addRule(`.monaco-workbench > .part.statusbar.debugging > .statusbar-item .mask-icon { background-color: ${statusBarItemDebuggingForeground} !important; }`); } -}); \ No newline at end of file +}); diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index ea10b06de9..b207499132 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import uri from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import severity from 'vs/base/common/severity'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IJSONSchemaSnippet } from 'vs/base/common/jsonSchema'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -20,6 +20,7 @@ import { Range, IRange } from 'vs/editor/common/core/range'; import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IDisposable } from 'vs/base/common/lifecycle'; export const VIEWLET_ID = 'workbench.view.debug'; export const VARIABLES_VIEW_ID = 'workbench.debug.variablesView'; @@ -34,9 +35,10 @@ export const CONTEXT_IN_DEBUG_MODE = new RawContextKey('inDebugMode', f export const CONTEXT_NOT_IN_DEBUG_MODE: ContextKeyExpr = CONTEXT_IN_DEBUG_MODE.toNegated(); export const CONTEXT_IN_DEBUG_REPL = new RawContextKey('inDebugRepl', false); export const CONTEXT_NOT_IN_DEBUG_REPL: ContextKeyExpr = CONTEXT_IN_DEBUG_REPL.toNegated(); -export const CONTEXT_ON_FIRST_DEBUG_REPL_LINE = new RawContextKey('onFirsteDebugReplLine', false); +export const CONTEXT_ON_FIRST_DEBUG_REPL_LINE = new RawContextKey('onFirstDebugReplLine', false); export const CONTEXT_ON_LAST_DEBUG_REPL_LINE = new RawContextKey('onLastDebugReplLine', false); export const CONTEXT_BREAKPOINT_WIDGET_VISIBLE = new RawContextKey('breakpointWidgetVisible', false); +export const CONTEXT_IN_BREAKPOINT_WIDGET = new RawContextKey('inBreakpointWidget', false); export const CONTEXT_BREAKPOINTS_FOCUSED = new RawContextKey('breakpointsFocused', true); export const CONTEXT_WATCH_EXPRESSIONS_FOCUSED = new RawContextKey('watchExpressionsFocused', true); export const CONTEXT_VARIABLES_FOCUSED = new RawContextKey('variablesFocused', true); @@ -121,6 +123,7 @@ export interface ISession { stepOut(args: DebugProtocol.StepOutArguments): TPromise; continue(args: DebugProtocol.ContinueArguments): TPromise; pause(args: DebugProtocol.PauseArguments): TPromise; + terminateThreads(args: DebugProtocol.TerminateThreadsArguments): TPromise; stepBack(args: DebugProtocol.StepBackArguments): TPromise; reverseContinue(args: DebugProtocol.ReverseContinueArguments): TPromise; @@ -139,8 +142,8 @@ export interface IProcess extends ITreeElement { getName(includeRoot: boolean): string; configuration: IConfig; session: ISession; - sources: Map; state: ProcessState; + getSourceForUri(modelUri: uri): Source; getThread(threadId: number): IThread; getAllThreads(): IThread[]; getSource(raw: DebugProtocol.Source): Source; @@ -197,6 +200,7 @@ export interface IThread extends ITreeElement { stepBack(): TPromise; continue(): TPromise; pause(): TPromise; + terminate(): TPromise; reverseContinue(): TPromise; } @@ -230,32 +234,36 @@ export interface IBreakpointData { column?: number; enabled?: boolean; condition?: string; + logMessage?: string; hitCondition?: string; } export interface IBreakpointUpdateData extends DebugProtocol.Breakpoint { condition?: string; hitCondition?: string; + logMessage?: string; } -export interface IBreakpoint extends IEnablement { +export interface IBaseBreakpoint extends IEnablement { + condition: string; + hitCondition: string; + logMessage: string; + verified: boolean; + idFromAdapter: number; +} + +export interface IBreakpoint extends IBaseBreakpoint { uri: uri; lineNumber: number; endLineNumber?: number; column: number; endColumn?: number; - condition: string; - hitCondition: string; - verified: boolean; - idFromAdapter: number; message: string; + adapterData: any; } -export interface IFunctionBreakpoint extends IEnablement { +export interface IFunctionBreakpoint extends IBaseBreakpoint { name: string; - verified: boolean; - idFromAdapter: number; - hitCondition: string; } export interface IExceptionBreakpoint extends IEnablement { @@ -300,13 +308,13 @@ export interface IViewModel extends ITreeElement { } export interface IModel extends ITreeElement { - getProcesses(): IProcess[]; - getBreakpoints(): IBreakpoint[]; + getProcesses(): ReadonlyArray; + getBreakpoints(): ReadonlyArray; areBreakpointsActivated(): boolean; - getFunctionBreakpoints(): IFunctionBreakpoint[]; - getExceptionBreakpoints(): IExceptionBreakpoint[]; - getWatchExpressions(): IExpression[]; - getReplElements(): IReplElement[]; + getFunctionBreakpoints(): ReadonlyArray; + getExceptionBreakpoints(): ReadonlyArray; + getWatchExpressions(): ReadonlyArray; + getReplElements(): ReadonlyArray; onDidChangeBreakpoints: Event; onDidChangeCallStack: Event; @@ -342,6 +350,8 @@ export interface IDebugConfiguration { hideActionBar: boolean; showInStatusBar: 'never' | 'always' | 'onFirstSessionStart'; internalConsoleOptions: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'; + extensionHostDebugAdapter: boolean; + enableAllHovers: boolean; } export interface IGlobalConfig { @@ -351,22 +361,29 @@ export interface IGlobalConfig { } export interface IEnvConfig { - name?: string; - type: string; - request: string; internalConsoleOptions?: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'; preLaunchTask?: string; - __restart?: any; - __sessionId?: string; + postDebugTask?: string; debugServer?: number; noDebug?: boolean; - port?: number; } export interface IConfig extends IEnvConfig { + + // fundamental attributes + type: string; + request: string; + name?: string; + + // platform specifics windows?: IEnvConfig; osx?: IEnvConfig; linux?: IEnvConfig; + + // internals + __sessionId?: string; + __restart?: any; + port?: number; // TODO } export interface ICompound { @@ -374,34 +391,58 @@ export interface ICompound { configurations: (string | { name: string, folder: string })[]; } +export interface IDebugAdapter extends IDisposable { + readonly onError: Event; + readonly onExit: Event; + onRequest(callback: (request: DebugProtocol.Request) => void); + onEvent(callback: (event: DebugProtocol.Event) => void); + startSession(): TPromise; + sendMessage(message: DebugProtocol.ProtocolMessage): void; + sendResponse(response: DebugProtocol.Response): void; + sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void): void; + stopSession(): TPromise; +} + +export interface IDebugAdapterProvider extends ITerminalLauncher { + createDebugAdapter(debugType: string, adapterInfo: IAdapterExecutable | null): IDebugAdapter; + substituteVariables(folder: IWorkspaceFolder, config: IConfig): TPromise; +} + export interface IAdapterExecutable { command?: string; args?: string[]; } -export interface IRawEnvAdapter { - type?: string; - label?: string; +export interface IPlatformSpecificAdapterContribution { program?: string; args?: string[]; runtime?: string; runtimeArgs?: string[]; } -export interface IRawAdapter extends IRawEnvAdapter { +export interface IDebuggerContribution extends IPlatformSpecificAdapterContribution { + type?: string; + label?: string; + // debug adapter executable adapterExecutableCommand?: string; - enableBreakpointsFor?: { languageIds: string[] }; - configurationAttributes?: any; - configurationSnippets?: IJSONSchemaSnippet[]; - initialConfigurations?: any[]; - languages?: string[]; - variables?: { [key: string]: string }; + win?: IPlatformSpecificAdapterContribution; + winx86?: IPlatformSpecificAdapterContribution; + windows?: IPlatformSpecificAdapterContribution; + osx?: IPlatformSpecificAdapterContribution; + linux?: IPlatformSpecificAdapterContribution; + + // internal aiKey?: string; - win?: IRawEnvAdapter; - winx86?: IRawEnvAdapter; - windows?: IRawEnvAdapter; - osx?: IRawEnvAdapter; - linux?: IRawEnvAdapter; + + // supported languages + languages?: string[]; + enableBreakpointsFor?: { languageIds: string[] }; + + // debug configuration support + configurationAttributes?: any; + initialConfigurations?: any[]; + configurationSnippets?: IJSONSchemaSnippet[]; + variables?: { [key: string]: string }; } export interface IDebugConfigurationProvider { @@ -412,6 +453,25 @@ export interface IDebugConfigurationProvider { debugAdapterExecutable(folderUri: uri | undefined): TPromise; } +export interface ITerminalLauncher { + runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise; +} + +export interface ITerminalSettings { + external: { + windowsExec: string, + osxExec: string, + linuxExec: string + }; + integrated: { + shell: { + osx: string, + windows: string, + linux: string + } + }; +} + export interface IConfigurationManager { /** * Returns true if breakpoints can be set for a given editor model. Depends on mode. @@ -442,6 +502,11 @@ export interface IConfigurationManager { resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any): TPromise; debugAdapterExecutable(folderUri: uri | undefined, type: string): TPromise; + + registerDebugAdapterProvider(debugTypes: string[], debugAdapterLauncher: IDebugAdapterProvider): IDisposable; + createDebugAdapter(debugType: string, adapterExecutable: IAdapterExecutable | null): IDebugAdapter | undefined; + substituteVariables(debugType: string, folder: IWorkspaceFolder, config: IConfig): TPromise; + runInTerminal(debugType: string, args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise; } export interface ILaunch { @@ -484,12 +549,6 @@ export interface ILaunch { */ getConfigurationNames(includeCompounds?: boolean): string[]; - /** - * Returns the resolved configuration. - * Replaces os specific values, system variables, interactive variables. - */ - resolveConfiguration(config: IConfig): TPromise; - /** * Opens the launch.json file. Creates if it does not exist. */ @@ -545,7 +604,7 @@ export interface IDebugService { /** * Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes. */ - addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise; + addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise; /** * Updates the breakpoints. @@ -627,7 +686,7 @@ export interface IDebugService { * Also saves all files, manages if compounds are present in the configuration * and resolveds configurations via DebugConfigurationProviders. */ - startDebugging(launch: ILaunch, configOrName?: IConfig | string, noDebug?: boolean): TPromise; + startDebugging(launch: ILaunch, configOrName?: IConfig | string, noDebug?: boolean): TPromise; /** * Restarts a process or creates a new one if there is no active session. @@ -656,9 +715,14 @@ export interface IDebugService { } // Editor interfaces +export enum BreakpointWidgetContext { + CONDITION = 0, + HIT_COUNT = 1, + LOG_MESSAGE = 2 +} export interface IDebugEditorContribution extends IEditorContribution { showHover(range: Range, focus: boolean): TPromise; - showBreakpointWidget(lineNumber: number, column: number): void; + showBreakpointWidget(lineNumber: number, column: number, context?: BreakpointWidgetContext): void; closeBreakpointWidget(): void; addLaunchConfiguration(): TPromise; } diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 097dd0aaf2..91ead692ba 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -8,19 +8,19 @@ import uri from 'vs/base/common/uri'; import * as resources from 'vs/base/common/resources'; import { TPromise } from 'vs/base/common/winjs.base'; import * as lifecycle from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { generateUuid } from 'vs/base/common/uuid'; import * as errors from 'vs/base/common/errors'; import { RunOnceScheduler } from 'vs/base/common/async'; import severity from 'vs/base/common/severity'; -import { isObject, isString } from 'vs/base/common/types'; +import { isObject, isString, isUndefinedOrNull } from 'vs/base/common/types'; import { distinct } from 'vs/base/common/arrays'; import { Range, IRange } from 'vs/editor/common/core/range'; import { ISuggestion } from 'vs/editor/common/modes'; import { Position } from 'vs/editor/common/core/position'; import { ITreeElement, IExpression, IExpressionContainer, IProcess, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel, IReplElementSource, - IConfig, ISession, IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, ProcessState, IBreakpointsChangeEvent, IBreakpointUpdateData + IConfig, ISession, IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, ProcessState, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint } from 'vs/workbench/parts/debug/common/debug'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -39,6 +39,7 @@ export abstract class AbstractReplElement implements IReplElement { return `replelement:${this.id}`; } + // Used by the copy all action in repl abstract toString(): string; } @@ -97,7 +98,7 @@ export class RawObjectReplElement extends AbstractReplElement implements IExpres } public toString(): string { - return this.name ? `${this.name}: ${this.value}` : this.value; + return `${this.name}\n${this.value}`; } } @@ -524,6 +525,10 @@ export class Thread implements IThread { return this.process.session.pause({ threadId: this.threadId }); } + public terminate(): TPromise { + return this.process.session.terminateThreads({ threadIds: [this.threadId] }); + } + public reverseContinue(): TPromise { return this.process.session.reverseContinue({ threadId: this.threadId }); } @@ -531,8 +536,9 @@ export class Thread implements IThread { export class Process implements IProcess { - public sources: Map; + private sources: Map; private threads: Map; + public inactive = true; constructor(public configuration: IConfig, private _session: ISession & ITreeElement) { @@ -557,6 +563,10 @@ export class Process implements IProcess { return this.configuration.type === 'attach' ? ProcessState.ATTACH : ProcessState.LAUNCH; } + public getSourceForUri(modelUri: uri): Source { + return this.sources.get(modelUri.toString()); + } + public getSource(raw: DebugProtocol.Source): Source { let source = new Source(raw, this.getId()); if (this.sources.has(source.uri.toString())) { @@ -671,12 +681,48 @@ export class Process implements IProcess { return result; }, err => []); } + + setNotAvailable(modelUri: uri) { + const source = this.sources.get(modelUri.toString()); + if (source) { + source.available = false; + } + } } -export class Breakpoint implements IBreakpoint { +export class Enablement implements IEnablement { + constructor( + public enabled: boolean, + private id: string + ) { } + + public getId(): string { + return this.id; + } +} + +export class BaseBreakpoint extends Enablement implements IBaseBreakpoint { public verified: boolean; public idFromAdapter: number; + + constructor( + enabled: boolean, + public hitCondition: string, + public condition: string, + public logMessage: string, + id: string + ) { + super(enabled, id); + if (enabled === undefined) { + this.enabled = true; + } + this.verified = false; + } +} + +export class Breakpoint extends BaseBreakpoint implements IBreakpoint { + public message: string; public endLineNumber: number; public endColumn: number; @@ -685,47 +731,34 @@ export class Breakpoint implements IBreakpoint { public uri: uri, public lineNumber: number, public column: number, - public enabled: boolean, - public condition: string, - public hitCondition: string, + enabled: boolean, + condition: string, + hitCondition: string, + logMessage: string, public adapterData: any, - private id = generateUuid() + id = generateUuid() ) { - if (enabled === undefined) { - this.enabled = true; - } - this.verified = false; - } - - public getId(): string { - return this.id; + super(enabled, hitCondition, condition, logMessage, id); } } -export class FunctionBreakpoint implements IFunctionBreakpoint { +export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreakpoint { - public verified: boolean; - public idFromAdapter: number; - - constructor(public name: string, public enabled: boolean, public hitCondition: string, private id = generateUuid()) { - this.verified = false; - } - - public getId(): string { - return this.id; + constructor( + public name: string, + enabled: boolean, + hitCondition: string, + condition: string, + logMessage: string, + id = generateUuid()) { + super(enabled, hitCondition, condition, logMessage, id); } } -export class ExceptionBreakpoint implements IExceptionBreakpoint { +export class ExceptionBreakpoint extends Enablement implements IExceptionBreakpoint { - private id: string; - - constructor(public filter: string, public label: string, public enabled: boolean) { - this.id = generateUuid(); - } - - public getId(): string { - return this.id; + constructor(public filter: string, public label: string, enabled: boolean) { + super(enabled, generateUuid()); } } @@ -743,10 +776,10 @@ export class Model implements IModel { private toDispose: lifecycle.IDisposable[]; private replElements: IReplElement[]; private schedulers = new Map(); - private _onDidChangeBreakpoints: Emitter; - private _onDidChangeCallStack: Emitter; - private _onDidChangeWatchExpressions: Emitter; - private _onDidChangeREPLElements: Emitter; + private readonly _onDidChangeBreakpoints: Emitter; + private readonly _onDidChangeCallStack: Emitter; + private readonly _onDidChangeWatchExpressions: Emitter; + private readonly _onDidChangeREPLElements: Emitter; constructor( private breakpoints: Breakpoint[], @@ -837,10 +870,23 @@ export class Model implements IModel { return thread.fetchCallStack(); } - public getBreakpoints(): Breakpoint[] { + public getBreakpoints(): IBreakpoint[] { return this.breakpoints; } + public getBreakpointsForResource(resource: uri): IBreakpoint[] { + const uriString = resource.toString(); + return this.breakpoints.filter(bp => bp.uri.toString() === uriString); + } + + public getEnabledBreakpointsForResource(resource: uri): IBreakpoint[] { + if (this.breakpointsActivated) { + const uriString = resource.toString(); + return this.breakpoints.filter(bp => bp.uri.toString() === uriString && bp.enabled); + } + return []; + } + public getFunctionBreakpoints(): IFunctionBreakpoint[] { return this.functionBreakpoints; } @@ -868,8 +914,8 @@ export class Model implements IModel { this._onDidChangeBreakpoints.fire(); } - public addBreakpoints(uri: uri, rawData: IBreakpointData[], fireEvent = true): Breakpoint[] { - const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled, rawBp.condition, rawBp.hitCondition, undefined, rawBp.id)); + public addBreakpoints(uri: uri, rawData: IBreakpointData[], fireEvent = true): IBreakpoint[] { + const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled, rawBp.condition, rawBp.hitCondition, rawBp.logMessage, undefined, rawBp.id)); this.breakpoints = this.breakpoints.concat(newBreakpoints); this.breakpointsActivated = true; this.sortAndDeDup(); @@ -891,16 +937,28 @@ export class Model implements IModel { this.breakpoints.forEach(bp => { const bpData = data[bp.getId()]; if (bpData) { - bp.lineNumber = bpData.line ? bpData.line : bp.lineNumber; + if (!isUndefinedOrNull(bpData.line)) { + bp.lineNumber = bpData.line; + } bp.endLineNumber = bpData.endLine; bp.column = bpData.column; bp.endColumn = bpData.endColumn; - bp.verified = bp.verified || bpData.verified; + if (!isUndefinedOrNull(bpData.verified)) { + bp.verified = bpData.verified; + } bp.idFromAdapter = bpData.id; bp.message = bpData.message; bp.adapterData = bpData.source ? bpData.source.adapterData : bp.adapterData; - bp.condition = bpData.condition || bp.condition; - bp.hitCondition = bpData.hitCondition || bp.hitCondition; + + if (!isUndefinedOrNull(bpData.condition)) { + bp.condition = bpData.condition; + } + if (!isUndefinedOrNull(bpData.hitCondition)) { + bp.hitCondition = bpData.hitCondition; + } + if (!isUndefinedOrNull(bpData.logMessage)) { + bp.logMessage = bpData.logMessage; + } updated.push(bp); } }); @@ -961,8 +1019,8 @@ export class Model implements IModel { this._onDidChangeBreakpoints.fire({ changed: changed }); } - public addFunctionBreakpoint(functionName: string, id: string): FunctionBreakpoint { - const newFunctionBreakpoint = new FunctionBreakpoint(functionName, true, null, id); + public addFunctionBreakpoint(functionName: string, id: string): IFunctionBreakpoint { + const newFunctionBreakpoint = new FunctionBreakpoint(functionName, true, undefined, undefined, undefined, id); this.functionBreakpoints.push(newFunctionBreakpoint); this._onDidChangeBreakpoints.fire({ added: [newFunctionBreakpoint] }); @@ -1082,11 +1140,7 @@ export class Model implements IModel { } public sourceIsNotAvailable(uri: uri): void { - this.processes.forEach(p => { - if (p.sources.has(uri.toString())) { - p.sources.get(uri.toString()).available = false; - } - }); + this.processes.forEach(p => p.setNotAvailable(uri)); this._onDidChangeCallStack.fire(); } diff --git a/src/vs/workbench/parts/debug/common/debugProtocol.d.ts b/src/vs/workbench/parts/debug/common/debugProtocol.d.ts index db67afaf91..49f682b623 100644 --- a/src/vs/workbench/parts/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/parts/debug/common/debugProtocol.d.ts @@ -82,6 +82,8 @@ declare module DebugProtocol { description?: string; /** The thread which was stopped. */ threadId?: number; + /** A value of true hints to the frontend that this event should not change the focus. */ + preserveFocusHint?: boolean; /** Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI. */ text?: string; /** If allThreadsStopped is true, a debug adapter can announce that all threads have stopped. @@ -125,7 +127,7 @@ declare module DebugProtocol { // event: 'terminated'; body?: { /** A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session. - The value is not interpreted by the client and passed unmodified as an attribute '__restart' to the launchRequest. + The value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests. */ restart?: any; }; @@ -295,6 +297,8 @@ declare module DebugProtocol { export interface InitializeRequestArguments { /** The ID of the (frontend) client using this adapter. */ clientID?: string; + /** The human readable name of the (frontend) client using this adapter. */ + clientName?: string; /** The ID of the debug adapter. */ adapterID: string; /** The ISO-639 locale of the (frontend) client using this adapter, e.g. en-US or de-CH. */ @@ -345,10 +349,15 @@ declare module DebugProtocol { arguments: LaunchRequestArguments; } - /** Arguments for 'launch' request. */ + /** Arguments for 'launch' request. Additional attributes are implementation specific. */ export interface LaunchRequestArguments { /** If noDebug is true the launch request should launch the program without enabling debugging. */ noDebug?: boolean; + /** Optional data from the previous, restarted session. + The data is sent as the 'restart' attribute of the 'terminated' event. + The client should leave the data intact. + */ + __restart?: any; } /** Response to 'launch' request. This is just an acknowledgement, so no body field is required. */ @@ -361,10 +370,13 @@ declare module DebugProtocol { arguments: AttachRequestArguments; } - /** Arguments for 'attach' request. - The attach request has no standardized attributes. - */ + /** Arguments for 'attach' request. Additional attributes are implementation specific. */ export interface AttachRequestArguments { + /** Optional data from the previous, restarted session. + The data is sent as the 'restart' attribute of the 'terminated' event. + The client should leave the data intact. + */ + __restart?: any; } /** Response to 'attach' request. This is just an acknowledgement, so no body field is required. */ @@ -588,7 +600,7 @@ declare module DebugProtocol { /** Arguments for 'stepBack' request. */ export interface StepBackArguments { - /** Exceute 'stepBack' for this thread. */ + /** Execute 'stepBack' for this thread. */ threadId: number; } @@ -606,7 +618,7 @@ declare module DebugProtocol { /** Arguments for 'reverseContinue' request. */ export interface ReverseContinueArguments { - /** Exceute 'reverseContinue' for this thread. */ + /** Execute 'reverseContinue' for this thread. */ threadId: number; } @@ -839,6 +851,24 @@ declare module DebugProtocol { }; } + /** Terminate thread request; value of command field is 'terminateThreads'. + The request terminates the threads with the given ids. + */ + export interface TerminateThreadsRequest extends Request { + // command: 'terminateThreads'; + arguments: TerminateThreadsArguments; + } + + /** Arguments for 'terminateThreads' request. */ + export interface TerminateThreadsArguments { + /** Ids of threads to be terminated. */ + threadIds?: number[]; + } + + /** Response to 'terminateThreads' request. This is just an acknowledgement, so no body field is required. */ + export interface TerminateThreadsResponse extends Response { + } + /** Modules can be retrieved from the debug adapter with the ModulesRequest which can either return all modules or a range of modules to support paging. */ export interface ModulesRequest extends Request { // command: 'modules'; @@ -932,6 +962,49 @@ declare module DebugProtocol { }; } + /** SetExpression request; value of command field is 'setExpression'. + Evaluates the given 'value' expression and assigns it to the 'expression' which must be a modifiable l-value. + The expressions have access to any variables and arguments that are in scope of the specified frame. + */ + export interface SetExpressionRequest extends Request { + // command: 'setExpression'; + arguments: SetExpressionArguments; + } + + /** Arguments for 'setExpression' request. */ + export interface SetExpressionArguments { + /** The l-value expression to assign to. */ + expression: string; + /** The value expression to assign to the l-value expression. */ + value: string; + /** Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope. */ + frameId?: number; + /** Specifies how the resulting value should be formatted. */ + format?: ValueFormat; + } + + /** Response to 'setExpression' request. */ + export interface SetExpressionResponse extends Response { + body: { + /** The new value of the expression. */ + value: string; + /** The optional type of the value. */ + type?: string; + /** Properties of a value that can be used to determine how to render the result in the UI. */ + presentationHint?: VariablePresentationHint; + /** If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. */ + variablesReference?: number; + /** The number of named child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + */ + namedVariables?: number; + /** The number of indexed child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + */ + indexedVariables?: number; + }; + } + /** StepInTargets request; value of command field is 'stepInTargets'. This request retrieves the possible stepIn targets for the specified stack frame. These targets can be used in the 'stepIn' request. @@ -1043,7 +1116,7 @@ declare module DebugProtocol { /** Information about the capabilities of a debug adapter. */ export interface Capabilities { - /** The debug adapter supports the configurationDoneRequest. */ + /** The debug adapter supports the 'configurationDone' request. */ supportsConfigurationDoneRequest?: boolean; /** The debug adapter supports function breakpoints. */ supportsFunctionBreakpoints?: boolean; @@ -1055,31 +1128,31 @@ declare module DebugProtocol { supportsEvaluateForHovers?: boolean; /** Available filters or options for the setExceptionBreakpoints request. */ exceptionBreakpointFilters?: ExceptionBreakpointsFilter[]; - /** The debug adapter supports stepping back via the stepBack and reverseContinue requests. */ + /** The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests. */ supportsStepBack?: boolean; /** The debug adapter supports setting a variable to a value. */ supportsSetVariable?: boolean; /** The debug adapter supports restarting a frame. */ supportsRestartFrame?: boolean; - /** The debug adapter supports the gotoTargetsRequest. */ + /** The debug adapter supports the 'gotoTargets' request. */ supportsGotoTargetsRequest?: boolean; - /** The debug adapter supports the stepInTargetsRequest. */ + /** The debug adapter supports the 'stepInTargets' request. */ supportsStepInTargetsRequest?: boolean; - /** The debug adapter supports the completionsRequest. */ + /** The debug adapter supports the 'completions' request. */ supportsCompletionsRequest?: boolean; - /** The debug adapter supports the modules request. */ + /** The debug adapter supports the 'modules' request. */ supportsModulesRequest?: boolean; /** The set of additional module information exposed by the debug adapter. */ additionalModuleColumns?: ColumnDescriptor[]; /** Checksum algorithms supported by the debug adapter. */ supportedChecksumAlgorithms?: ChecksumAlgorithm[]; - /** The debug adapter supports the RestartRequest. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the RestartRequest. */ + /** The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the RestartRequest. */ supportsRestartRequest?: boolean; /** The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request. */ supportsExceptionOptions?: boolean; /** The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest. */ supportsValueFormattingOptions?: boolean; - /** The debug adapter supports the exceptionInfo request. */ + /** The debug adapter supports the 'exceptionInfo' request. */ supportsExceptionInfoRequest?: boolean; /** The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request. */ supportTerminateDebuggee?: boolean; @@ -1089,6 +1162,10 @@ declare module DebugProtocol { supportsLoadedSourcesRequest?: boolean; /** The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint. */ supportsLogPoints?: boolean; + /** The debug adapter supports the 'terminateThreads' request. */ + supportsTerminateThreadsRequest?: boolean; + /** The debug adapter supports the 'setExpression' request. */ + supportsSetExpression?: boolean; } /** An ExceptionBreakpointsFilter is shown in the UI as an option for configuring how exceptions are dealt with. */ diff --git a/src/vs/workbench/parts/debug/common/debugSource.ts b/src/vs/workbench/parts/debug/common/debugSource.ts index c71c1b7dcb..a4be13e56b 100644 --- a/src/vs/workbench/parts/debug/common/debugSource.ts +++ b/src/vs/workbench/parts/debug/common/debugSource.ts @@ -15,6 +15,20 @@ import { Schemas } from 'vs/base/common/network'; const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Source"); +/** + * Debug URI format + * + * a debug URI represents a Source object and the debug session where the Source comes from. + * + * debug:arbitrary_path?session=123e4567-e89b-12d3-a456-426655440000&ref=1016 + * \___/ \____________/ \__________________________________________/ \______/ + * | | | | + * scheme source.path session id source.reference + * + * the arbitrary_path and the session id are encoded with 'encodeURIComponent' + * + */ + export class Source { public readonly uri: uri; @@ -30,8 +44,9 @@ export class Source { this.uri = uri.parse(`${DEBUG_SCHEME}:${encodeURIComponent(path)}?session=${encodeURIComponent(sessionId)}&ref=${this.raw.sourceReference}`); } else { if (paths.isAbsolute(path)) { - this.uri = uri.file(path); // path should better be absolute! + this.uri = uri.file(path); } else { + // assume that path is a URI this.uri = uri.parse(path); } } diff --git a/src/vs/workbench/parts/debug/common/debugViewModel.ts b/src/vs/workbench/parts/debug/common/debugViewModel.ts index 91f06ca52f..0ad16ece1e 100644 --- a/src/vs/workbench/parts/debug/common/debugViewModel.ts +++ b/src/vs/workbench/parts/debug/common/debugViewModel.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IProcess, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED } from 'vs/workbench/parts/debug/common/debug'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -14,9 +14,9 @@ export class ViewModel implements IViewModel { private _focusedThread: IThread; private selectedExpression: IExpression; private selectedFunctionBreakpoint: IFunctionBreakpoint; - private _onDidFocusProcess: Emitter; - private _onDidFocusStackFrame: Emitter<{ stackFrame: IStackFrame, explicit: boolean }>; - private _onDidSelectExpression: Emitter; + private readonly _onDidFocusProcess: Emitter; + private readonly _onDidFocusStackFrame: Emitter<{ stackFrame: IStackFrame, explicit: boolean }>; + private readonly _onDidSelectExpression: Emitter; private multiProcessView: boolean; private expressionSelectedContextKey: IContextKey; private breakpointSelectedContextKey: IContextKey; diff --git a/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.ts b/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.ts new file mode 100644 index 0000000000..d75d77a8a1 --- /dev/null +++ b/src/vs/workbench/parts/debug/electron-browser/breakpointWidget.ts @@ -0,0 +1,336 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!../browser/media/breakpointWidget'; +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox'; +import * as lifecycle from 'vs/base/common/lifecycle'; +import * as dom from 'vs/base/browser/dom'; +import { Position } from 'vs/editor/common/core/position'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IDebugService, IBreakpoint, BreakpointWidgetContext as Context, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, DEBUG_SCHEME, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, CONTEXT_IN_BREAKPOINT_WIDGET } from 'vs/workbench/parts/debug/common/debug'; +import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { SimpleDebugEditor } from 'vs/workbench/parts/debug/electron-browser/simpleDebugEditor'; +import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ServicesAccessor, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { IModelService } from 'vs/editor/common/services/modelService'; +import uri from 'vs/base/common/uri'; +import { SuggestRegistry, ISuggestResult, SuggestContext } from 'vs/editor/common/modes'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { ITextModel } from 'vs/editor/common/model'; +import { wireCancellationToken } from 'vs/base/common/async'; +import { provideSuggestionItems } from 'vs/editor/contrib/suggest/suggest'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { transparent, editorForeground } from 'vs/platform/theme/common/colorRegistry'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { IDecorationOptions } from 'vs/editor/common/editorCommon'; + +const $ = dom.$; +const IPrivateBreakopintWidgetService = createDecorator('privateBreakopintWidgetService'); +export interface IPrivateBreakopintWidgetService { + _serviceBrand: any; + close(success: boolean): void; +} +const DECORATION_KEY = 'breakpointwidgetdecoration'; + +export class BreakpointWidget extends ZoneWidget implements IPrivateBreakopintWidgetService { + public _serviceBrand: any; + + private selectContainer: HTMLElement; + private input: SimpleDebugEditor; + private toDispose: lifecycle.IDisposable[]; + private conditionInput = ''; + private hitCountInput = ''; + private logMessageInput = ''; + private breakpoint: IBreakpoint; + + constructor(editor: ICodeEditor, private lineNumber: number, private context: Context, + @IContextViewService private contextViewService: IContextViewService, + @IDebugService private debugService: IDebugService, + @IThemeService private themeService: IThemeService, + @IContextKeyService private contextKeyService: IContextKeyService, + @IInstantiationService private instantiationService: IInstantiationService, + @IModelService private modelService: IModelService, + @ICodeEditorService private codeEditorService: ICodeEditorService, + ) { + super(editor, { showFrame: true, showArrow: false, frameWidth: 1 }); + + this.toDispose = []; + const uri = this.editor.getModel().uri; + this.breakpoint = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === this.lineNumber && bp.uri.toString() === uri.toString()).pop(); + + if (this.context === undefined) { + if (this.breakpoint && !this.breakpoint.condition && !this.breakpoint.hitCondition && this.breakpoint.logMessage) { + this.context = Context.LOG_MESSAGE; + } else if (this.breakpoint && !this.breakpoint.condition && this.breakpoint.hitCondition) { + this.context = Context.HIT_COUNT; + } else { + this.context = Context.CONDITION; + } + } + + this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(e => { + if (this.breakpoint && e && e.removed && e.removed.indexOf(this.breakpoint) >= 0) { + this.dispose(); + } + })); + this.codeEditorService.registerDecorationType(DECORATION_KEY, {}); + + this.create(); + } + + private get placeholder(): string { + switch (this.context) { + case Context.LOG_MESSAGE: + return nls.localize('breakpointWidgetLogMessagePlaceholder', "Message to log when breakpoint is hit. Expressions within {} are interpolated. 'Enter' to accept, 'esc' to cancel."); + case Context.HIT_COUNT: + return nls.localize('breakpointWidgetHitCountPlaceholder', "Break when hit count condition is met. 'Enter' to accept, 'esc' to cancel."); + default: + return nls.localize('breakpointWidgetExpressionPlaceholder', "Break when expression evaluates to true. 'Enter' to accept, 'esc' to cancel."); + } + } + + private getInputValue(breakpoint: IBreakpoint): string { + switch (this.context) { + case Context.LOG_MESSAGE: + return breakpoint && breakpoint.logMessage ? breakpoint.logMessage : this.logMessageInput; + case Context.HIT_COUNT: + return breakpoint && breakpoint.hitCondition ? breakpoint.hitCondition : this.hitCountInput; + default: + return breakpoint && breakpoint.condition ? breakpoint.condition : this.conditionInput; + } + } + + private rememberInput(): void { + const value = this.input.getModel().getValue(); + switch (this.context) { + case Context.LOG_MESSAGE: + this.logMessageInput = value; + break; + case Context.HIT_COUNT: + this.hitCountInput = value; + break; + default: + this.conditionInput = value; + } + } + + protected _fillContainer(container: HTMLElement): void { + this.setCssClass('breakpoint-widget'); + const selectBox = new SelectBox([nls.localize('expression', "Expression"), nls.localize('hitCount', "Hit Count"), nls.localize('logMessage', "Log Message")], this.context, this.contextViewService); + this.toDispose.push(attachSelectBoxStyler(selectBox, this.themeService)); + this.selectContainer = $('.breakpoint-select-container'); + selectBox.render(dom.append(container, this.selectContainer)); + selectBox.onDidSelect(e => { + this.rememberInput(); + this.context = e.index; + + const value = this.getInputValue(this.breakpoint); + this.input.getModel().setValue(value); + }); + + this.createBreakpointInput(dom.append(container, $('.inputContainer'))); + + this.input.getModel().setValue(this.getInputValue(this.breakpoint)); + this.input.setPosition({ lineNumber: 1, column: this.input.getModel().getLineMaxColumn(1) }); + // Due to an electron bug we have to do the timeout, otherwise we do not get focus + setTimeout(() => this.input.focus(), 100); + } + + public close(success: boolean): void { + if (success) { + // if there is already a breakpoint on this location - remove it. + + let condition = this.breakpoint && this.breakpoint.condition; + let hitCondition = this.breakpoint && this.breakpoint.hitCondition; + let logMessage = this.breakpoint && this.breakpoint.logMessage; + this.rememberInput(); + + if (this.conditionInput || this.context === Context.CONDITION) { + condition = this.conditionInput; + } + if (this.hitCountInput || this.context === Context.HIT_COUNT) { + hitCondition = this.hitCountInput; + } + if (this.logMessageInput || this.context === Context.LOG_MESSAGE) { + logMessage = this.logMessageInput; + } + + if (this.breakpoint) { + this.debugService.updateBreakpoints(this.breakpoint.uri, { + [this.breakpoint.getId()]: { + condition, + hitCondition, + verified: this.breakpoint.verified, + column: this.breakpoint.column, + logMessage + } + }, false); + } else { + this.debugService.addBreakpoints(this.editor.getModel().uri, [{ + lineNumber: this.lineNumber, + enabled: true, + condition, + hitCondition, + logMessage + }]).done(null, errors.onUnexpectedError); + } + } + + this.dispose(); + } + + protected _doLayout(heightInPixel: number, widthInPixel: number): void { + this.input.layout({ height: 18, width: widthInPixel - 113 }); + } + + private createBreakpointInput(container: HTMLElement): void { + const scopedContextKeyService = this.contextKeyService.createScoped(container); + this.toDispose.push(scopedContextKeyService); + + const scopedInstatiationService = this.instantiationService.createChild(new ServiceCollection( + [IContextKeyService, scopedContextKeyService], [IPrivateBreakopintWidgetService, this])); + + const options = SimpleDebugEditor.getEditorOptions(); + this.input = scopedInstatiationService.createInstance(SimpleDebugEditor, container, options); + CONTEXT_IN_BREAKPOINT_WIDGET.bindTo(scopedContextKeyService).set(true); + const model = this.modelService.createModel('', null, uri.parse(`${DEBUG_SCHEME}:breakpointinput`), true); + this.input.setModel(model); + this.toDispose.push(model); + const setDecorations = () => { + const value = this.input.getModel().getValue(); + const decorations = !!value ? [] : this.createDecorations(); + this.input.setDecorations(DECORATION_KEY, decorations); + }; + this.input.getModel().onDidChangeContent(() => setDecorations()); + this.themeService.onThemeChange(() => setDecorations()); + + this.toDispose.push(SuggestRegistry.register({ scheme: DEBUG_SCHEME, hasAccessToAllModels: true }, { + provideCompletionItems: (model: ITextModel, position: Position, _context: SuggestContext, token: CancellationToken): Thenable => { + let suggestionsPromise: TPromise; + if (this.context === Context.CONDITION || this.context === Context.LOG_MESSAGE && this.isCurlyBracketOpen()) { + suggestionsPromise = provideSuggestionItems(this.editor.getModel(), new Position(this.lineNumber, 1), 'none', undefined, _context).then(suggestions => { + + let overwriteBefore = 0; + if (this.context === Context.CONDITION) { + overwriteBefore = position.column - 1; + } else { + // Inside the currly brackets, need to count how many useful characters are behind the position so they would all be taken into account + const value = this.input.getModel().getValue(); + while ((position.column - 2 - overwriteBefore >= 0) && value[position.column - 2 - overwriteBefore] !== '{' && value[position.column - 2 - overwriteBefore] !== ' ') { + overwriteBefore++; + } + } + + return { + suggestions: suggestions.map(s => { + s.suggestion.overwriteAfter = 0; + s.suggestion.overwriteBefore = overwriteBefore; + return s.suggestion; + }) + }; + }); + } else { + suggestionsPromise = TPromise.as({ suggestions: [] }); + } + + return wireCancellationToken(token, suggestionsPromise); + } + })); + } + + private createDecorations(): IDecorationOptions[] { + return [{ + range: { + startLineNumber: 0, + endLineNumber: 0, + startColumn: 0, + endColumn: 1 + }, + renderOptions: { + after: { + contentText: this.placeholder, + color: transparent(editorForeground, 0.4)(this.themeService.getTheme()).toString() + } + } + }]; + } + + private isCurlyBracketOpen(): boolean { + const value = this.input.getModel().getValue(); + for (let i = this.input.getPosition().column - 2; i >= 0; i--) { + if (value[i] === '{') { + return true; + } + + if (value[i] === '}') { + return false; + } + } + + return false; + } + + public dispose(): void { + super.dispose(); + this.input.dispose(); + lifecycle.dispose(this.toDispose); + setTimeout(() => this.editor.focus(), 0); + } +} + +class AcceptBreakpointWidgetInputAction extends EditorCommand { + + constructor() { + super({ + id: 'breakpointWidget.action.acceptInput', + precondition: CONTEXT_BREAKPOINT_WIDGET_VISIBLE, + kbOpts: { + kbExpr: CONTEXT_IN_BREAKPOINT_WIDGET, + primary: KeyCode.Enter + } + }); + } + + public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void { + accessor.get(IPrivateBreakopintWidgetService).close(true); + } +} + +class CloseBreakpointWidgetCommand extends EditorCommand { + + constructor() { + super({ + id: 'closeBreakpointWidget', + precondition: CONTEXT_BREAKPOINT_WIDGET_VISIBLE, + kbOpts: { + kbExpr: EditorContextKeys.textInputFocus, + primary: KeyCode.Escape, + secondary: [KeyMod.Shift | KeyCode.Escape] + } + }); + } + + public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { + const debugContribution = editor.getContribution(EDITOR_CONTRIBUTION_ID); + if (debugContribution) { + // if focus is in outer editor we need to use the debug contribution to close + return debugContribution.closeBreakpointWidget(); + } + + accessor.get(IPrivateBreakopintWidgetService).close(false); + } +} + +registerEditorCommand(new AcceptBreakpointWidgetInputAction()); +registerEditorCommand(new CloseBreakpointWidgetCommand()); diff --git a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts index 11c06885cb..47c8d908dd 100644 --- a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts @@ -18,7 +18,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { BaseDebugController, twistiePixels, renderViewTree } from 'vs/workbench/parts/debug/browser/baseDebugView'; import { ITree, IActionProvider, IDataSource, IRenderer, IAccessibilityProvider } from 'vs/base/parts/tree/browser/tree'; import { IAction, IActionItem } from 'vs/base/common/actions'; -import { RestartAction, StopAction, ContinueAction, StepOverAction, StepIntoAction, StepOutAction, PauseAction, RestartFrameAction } from 'vs/workbench/parts/debug/browser/debugActions'; +import { RestartAction, StopAction, ContinueAction, StepOverAction, StepIntoAction, StepOutAction, PauseAction, RestartFrameAction, TerminateThreadAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { CopyStackTraceAction } from 'vs/workbench/parts/debug/electron-browser/electronDebugActions'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -27,6 +27,7 @@ import { basenameOrAuthority } from 'vs/base/common/resources'; import { TreeResourceNavigator, WorkbenchTree } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; const $ = dom.$; @@ -268,6 +269,9 @@ class CallStackActionProvider implements IActionProvider { } else { actions.push(new PauseAction(PauseAction.ID, PauseAction.LABEL, this.debugService, this.keybindingService)); } + + actions.push(new Separator()); + actions.push(new TerminateThreadAction(TerminateThreadAction.ID, TerminateThreadAction.LABEL, this.debugService, this.keybindingService)); } else if (element instanceof StackFrame) { if (element.thread.process.session.capabilities.supportsRestartFrame) { actions.push(new RestartFrameAction(RestartFrameAction.ID, RestartFrameAction.LABEL, this.debugService, this.keybindingService)); @@ -523,7 +527,7 @@ class CallStackRenderer implements IRenderer { class CallstackAccessibilityProvider implements IAccessibilityProvider { - constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { // noop } diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 8acc0cecb0..88c5e53d9f 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -30,7 +30,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { DebugEditorModelManager } from 'vs/workbench/parts/debug/browser/debugEditorModelManager'; import { StepOverAction, ClearReplAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction, - ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction + ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction, TerminateThreadAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { DebugActionsWidget } from 'vs/workbench/parts/debug/browser/debugActionsWidget'; import * as service from 'vs/workbench/parts/debug/electron-browser/debugService'; @@ -86,7 +86,7 @@ Registry.as(ViewletExtensions.Viewlets).registerViewlet(new Vie VIEWLET_ID, nls.localize('debug', "Debug"), 'debug', - 40 + 3 )); const openViewletKb: IKeybindings = { @@ -134,6 +134,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(StopAction, StopAction registry.registerWorkbenchAction(new SyncActionDescriptor(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL), 'Debug: Disconnect', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ContinueAction, ContinueAction.ID, ContinueAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Continue', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseAction.ID, PauseAction.LABEL, { primary: KeyCode.F6 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Pause', debugCategory); +registry.registerWorkbenchAction(new SyncActionDescriptor(TerminateThreadAction, TerminateThreadAction.ID, TerminateThreadAction.LABEL, undefined, CONTEXT_IN_DEBUG_MODE), 'Debug: Terminate Thread', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory); @@ -151,7 +152,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(FocusBreakpointsViewAc // Register Quick Open -(Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler( +(Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler( new QuickOpenHandlerDescriptor( DebugQuickOpenHandler, DebugQuickOpenHandler.ID, @@ -204,6 +205,11 @@ configurationRegistry.registerConfiguration({ default: 'openOnFirstSessionStart', description: nls.localize('openDebug', "Controls whether debug view should be open on debugging session start.") }, + 'debug.enableAllHovers': { + type: 'boolean', + description: nls.localize({ comment: ['This is the description for a setting'], key: 'enableAllHovers' }, "Controls if the non debug hovers should be enabled while debugging. If true the hover providers will be called to provide a hover. Regular hovers will not be shown even if this setting is true."), + default: false + }, 'launch': { type: 'object', description: nls.localize({ comment: ['This is the description for a setting'], key: 'launch' }, "Global debug launch configuration. Should be used as an alternative to 'launch.json' that is shared across workspaces"), diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 1252b60d23..72347479b7 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -5,11 +5,9 @@ import * as nls from 'vs/nls'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import * as strings from 'vs/base/common/strings'; -import { first } from 'vs/base/common/arrays'; -import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import * as objects from 'vs/base/common/objects'; import uri from 'vs/base/common/uri'; import * as paths from 'vs/base/common/paths'; @@ -27,17 +25,18 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch, IAdapterExecutable } from 'vs/workbench/parts/debug/common/debug'; -import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; +import { IDebugConfigurationProvider, IDebuggerContribution, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IAdapterExecutable, IDebugAdapterProvider, IDebugAdapter, ITerminalSettings, ITerminalLauncher } from 'vs/workbench/parts/debug/common/debug'; +import { Debugger } from 'vs/workbench/parts/debug/node/debugger'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { TerminalLauncher } from 'vs/workbench/parts/debug/electron-browser/terminalSupport'; // debuggers extension point -export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint('debuggers', [], { +export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint('debuggers', [], { description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'), type: 'array', defaultSnippets: [{ body: [{ type: '', extensions: [] }] }], @@ -216,13 +215,13 @@ const schema: IJSONSchema = { } }; -const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); +const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); jsonRegistry.registerSchema(launchSchemaId, schema); const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; const DEBUG_SELECTED_ROOT = 'debug.selectedroot'; export class ConfigurationManager implements IConfigurationManager { - private adapters: Adapter[]; + private debuggers: Debugger[]; private breakpointModeIdsSet = new Set(); private launches: ILaunch[]; private selectedName: string; @@ -230,6 +229,9 @@ export class ConfigurationManager implements IConfigurationManager { private toDispose: IDisposable[]; private _onDidSelectConfigurationName = new Emitter(); private providers: IDebugConfigurationProvider[]; + private debugAdapterProviders: Map; + private terminalLauncher: ITerminalLauncher; + constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService, @@ -240,16 +242,20 @@ export class ConfigurationManager implements IConfigurationManager { @ICommandService private commandService: ICommandService, @IStorageService private storageService: IStorageService, @ILifecycleService lifecycleService: ILifecycleService, - @IExtensionService private extensionService: IExtensionService + @IExtensionService private extensionService: IExtensionService, + @IConfigurationResolverService private configurationResolverService: IConfigurationResolverService ) { this.providers = []; - this.adapters = []; + this.debuggers = []; this.toDispose = []; this.registerListeners(lifecycleService); this.initLaunches(); const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE); - const filtered = this.launches.filter(l => l.uri.toString() === previousSelectedRoot); - this.selectConfiguration(filtered.length ? filtered[0] : undefined, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE)); + const previousSelectedLaunch = this.launches.filter(l => l.uri.toString() === previousSelectedRoot).pop(); + if (previousSelectedLaunch) { + this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE)); + } + this.debugAdapterProviders = new Map(); } public registerDebugConfigurationProvider(handle: number, debugConfigurationProvider: IDebugConfigurationProvider): void { @@ -260,10 +266,10 @@ export class ConfigurationManager implements IConfigurationManager { debugConfigurationProvider.handle = handle; this.providers = this.providers.filter(p => p.handle !== handle); this.providers.push(debugConfigurationProvider); - const adapter = this.getAdapter(debugConfigurationProvider.type); + const dbg = this.getDebugger(debugConfigurationProvider.type); // Check if the provider contributes provideDebugConfigurations method - if (adapter && debugConfigurationProvider.provideDebugConfigurations) { - adapter.hasConfigurationProvider = true; + if (dbg && debugConfigurationProvider.provideDebugConfigurations) { + dbg.hasConfigurationProvider = true; } } @@ -272,19 +278,21 @@ export class ConfigurationManager implements IConfigurationManager { } public resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: IConfig): TPromise { - // pipe the config through the promises sequentially. append at the end the '*' types - const providers = this.providers.filter(p => p.type === type && p.resolveDebugConfiguration) - .concat(this.providers.filter(p => p.type === '*' && p.resolveDebugConfiguration)); + return this.extensionService.activateByEvent(`onDebugResolve:${type}`).then(() => { + // pipe the config through the promises sequentially. append at the end the '*' types + const providers = this.providers.filter(p => p.type === type && p.resolveDebugConfiguration) + .concat(this.providers.filter(p => p.type === '*' && p.resolveDebugConfiguration)); - return providers.reduce((promise, provider) => { - return promise.then(config => { - if (config) { - return provider.resolveDebugConfiguration(folderUri, config); - } else { - return Promise.resolve(config); - } - }); - }, TPromise.as(debugConfiguration)); + return providers.reduce((promise, provider) => { + return promise.then(config => { + if (config) { + return provider.resolveDebugConfiguration(folderUri, config); + } else { + return Promise.resolve(config); + } + }); + }, TPromise.as(debugConfiguration)); + }); } public provideDebugConfigurations(folderUri: uri | undefined, type: string): TPromise { @@ -300,12 +308,53 @@ export class ConfigurationManager implements IConfigurationManager { return TPromise.as(undefined); } + public registerDebugAdapterProvider(debugTypes: string[], debugAdapterLauncher: IDebugAdapterProvider): IDisposable { + debugTypes.forEach(debugType => this.debugAdapterProviders.set(debugType, debugAdapterLauncher)); + return { + dispose: () => { + debugTypes.forEach(debugType => this.debugAdapterProviders.delete(debugType)); + } + }; + } + + private getDebugAdapterProvider(type: string): IDebugAdapterProvider | undefined { + return this.debugAdapterProviders.get(type); + } + + public createDebugAdapter(debugType: string, adapterExecutable: IAdapterExecutable): IDebugAdapter | undefined { + let dap = this.getDebugAdapterProvider(debugType); + if (dap) { + return dap.createDebugAdapter(debugType, adapterExecutable); + } + return undefined; + } + + public substituteVariables(debugType: string, folder: IWorkspaceFolder, config: IConfig): TPromise { + let dap = this.getDebugAdapterProvider(debugType); + if (dap) { + return dap.substituteVariables(folder, config); + } + return TPromise.as(config); + } + + public runInTerminal(debugType: string, args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise { + + let tl: ITerminalLauncher = this.getDebugAdapterProvider(debugType); + if (!tl) { + if (!this.terminalLauncher) { + this.terminalLauncher = this.instantiationService.createInstance(TerminalLauncher); + } + tl = this.terminalLauncher; + } + return tl.runInTerminal(args, config); + } + private registerListeners(lifecycleService: ILifecycleService): void { debuggersExtPoint.setHandler((extensions) => { extensions.forEach(extension => { extension.value.forEach(rawAdapter => { if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { - extension.collector.error(nls.localize('debugNoType', "Debug adapter 'type' can not be omitted and must be of type 'string'.")); + extension.collector.error(nls.localize('debugNoType', "Debugger 'type' can not be omitted and must be of type 'string'.")); } if (rawAdapter.enableBreakpointsFor) { rawAdapter.enableBreakpointsFor.languageIds.forEach(modeId => { @@ -313,17 +362,17 @@ export class ConfigurationManager implements IConfigurationManager { }); } - const duplicate = this.adapters.filter(a => a.type === rawAdapter.type).pop(); + const duplicate = this.getDebugger(rawAdapter.type); if (duplicate) { duplicate.merge(rawAdapter, extension.description); } else { - this.adapters.push(new Adapter(this, rawAdapter, extension.description, this.configurationService, this.commandService)); + this.debuggers.push(new Debugger(this, rawAdapter, extension.description, this.configurationService, this.commandService, this.configurationResolverService)); } }); }); // update the schema to include all attributes, snippets and types from extensions. - this.adapters.forEach(adapter => { + this.debuggers.forEach(adapter => { const items = (schema.properties['configurations'].items); const schemaAttributes = adapter.getSchemaAttributes(); if (schemaAttributes) { @@ -348,12 +397,12 @@ export class ConfigurationManager implements IConfigurationManager { this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => { this.initLaunches(); - this.selectConfiguration(); + this.selectConfiguration(this.selectedLaunch); this.setCompoundSchemaValues(); })); this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('launch')) { - this.selectConfiguration(); + this.selectConfiguration(this.selectedLaunch); this.setCompoundSchemaValues(); } })); @@ -417,14 +466,10 @@ export class ConfigurationManager implements IConfigurationManager { return undefined; } - public selectConfiguration(launch?: ILaunch, name?: string, debugStarted?: boolean): void { + public selectConfiguration(launch: ILaunch, name?: string): void { const previousLaunch = this.selectedLaunch; const previousName = this.selectedName; - if (!launch) { - launch = this.selectedLaunch && this.selectedLaunch.getConfigurationNames().length ? this.selectedLaunch : first(this.launches, l => !!l.getConfigurationNames().length, this.launches.length ? this.launches[0] : undefined); - } - this.selectedLaunch = launch; const names = launch ? launch.getConfigurationNames() : []; if (name && names.indexOf(name) >= 0) { @@ -452,25 +497,26 @@ export class ConfigurationManager implements IConfigurationManager { return this.breakpointModeIdsSet.has(modeId); } - public getAdapter(type: string): Adapter { - return this.adapters.filter(adapter => strings.equalsIgnoreCase(adapter.type, type)).pop(); + public getDebugger(type: string): Debugger { + return this.debuggers.filter(dbg => strings.equalsIgnoreCase(dbg.type, type)).pop(); } - public guessAdapter(type?: string): TPromise { - return this.extensionService.activateByEvent('onDebugInitialConfigurations').then(() => this.extensionService.activateByEvent('onDebug').then(() => { + public guessDebugger(type?: string): TPromise { + return this.activateDebuggers().then(() => { + if (type) { - const adapter = this.getAdapter(type); + const adapter = this.getDebugger(type); return TPromise.as(adapter); } const editor = this.editorService.getActiveEditor(); - let candidates: Adapter[]; + let candidates: Debugger[]; if (editor) { const codeEditor = editor.getControl(); if (isCodeEditor(codeEditor)) { const model = codeEditor.getModel(); const language = model ? model.getLanguageIdentifier().language : undefined; - const adapters = this.adapters.filter(a => a.languages && a.languages.indexOf(language) >= 0); + const adapters = this.debuggers.filter(a => a.languages && a.languages.indexOf(language) >= 0); if (adapters.length === 1) { return TPromise.as(adapters[0]); } @@ -481,11 +527,11 @@ export class ConfigurationManager implements IConfigurationManager { } if (!candidates) { - candidates = this.adapters.filter(a => a.hasInitialConfiguration() || a.hasConfigurationProvider); + candidates = this.debuggers.filter(a => a.hasInitialConfiguration() || a.hasConfigurationProvider); } return this.quickOpenService.pick([...candidates, { label: 'More...', separator: { border: true } }], { placeHolder: nls.localize('selectDebug', "Select Environment") }) .then(picked => { - if (picked instanceof Adapter) { + if (picked instanceof Debugger) { return picked; } if (picked) { @@ -493,7 +539,11 @@ export class ConfigurationManager implements IConfigurationManager { } return undefined; }); - })); + }); + } + + public activateDebuggers(): TPromise { + return this.extensionService.activateByEvent('onDebugInitialConfigurations').then(() => this.extensionService.activateByEvent('onDebug')); } private store(): void { @@ -516,8 +566,7 @@ class Launch implements ILaunch { @IFileService private fileService: IFileService, @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IConfigurationService protected configurationService: IConfigurationService, - @IConfigurationResolverService private configurationResolverService: IConfigurationResolverService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService + @IWorkspaceContextService protected contextService: IWorkspaceContextService, ) { // noop } @@ -574,93 +623,60 @@ class Launch implements ILaunch { return config.configurations.filter(config => config && config.name === name).shift(); } - protected getWorkspaceForResolving(): IWorkspaceFolder { - if (this.workspace) { - return this.workspace; - } - - if (this.contextService.getWorkspace().folders.length === 1) { - return this.contextService.getWorkspace().folders[0]; - } - - return undefined; - } - - public resolveConfiguration(config: IConfig): TPromise { - const result = objects.deepClone(config) as IConfig; - // Set operating system specific properties #1873 - const setOSProperties = (flag: boolean, osConfig: IEnvConfig) => { - if (flag && osConfig) { - Object.keys(osConfig).forEach(key => { - result[key] = osConfig[key]; - }); - } - }; - setOSProperties(isWindows, result.windows); - setOSProperties(isMacintosh, result.osx); - setOSProperties(isLinux, result.linux); - - // massage configuration attributes - append workspace path to relatvie paths, substitute variables in paths. - Object.keys(result).forEach(key => { - result[key] = this.configurationResolverService.resolveAny(this.getWorkspaceForResolving(), result[key]); - }); - - const adapter = this.configurationManager.getAdapter(result.type); - return this.configurationResolverService.resolveInteractiveVariables(result, adapter ? adapter.variables : null); - } - public openConfigFile(sideBySide: boolean, type?: string): TPromise { - const resource = this.uri; - let pinned = false; + return this.configurationManager.activateDebuggers().then(() => { + const resource = this.uri; + let pinned = false; - return this.fileService.resolveContent(resource).then(content => content.value, err => { + return this.fileService.resolveContent(resource).then(content => content.value, err => { - // launch.json not found: create one by collecting launch configs from debugConfigProviders + // launch.json not found: create one by collecting launch configs from debugConfigProviders - return this.configurationManager.guessAdapter(type).then(adapter => { - if (adapter) { - return this.configurationManager.provideDebugConfigurations(this.workspace.uri, adapter.type).then(initialConfigs => { - return adapter.getInitialConfigurationContent(initialConfigs); + return this.configurationManager.guessDebugger(type).then(adapter => { + if (adapter) { + return this.configurationManager.provideDebugConfigurations(this.workspace.uri, adapter.type).then(initialConfigs => { + return adapter.getInitialConfigurationContent(initialConfigs); + }); + } else { + return undefined; + } + }).then(content => { + + if (!content) { + return undefined; + } + + pinned = true; // pin only if config file is created #8727 + return this.fileService.updateContent(resource, content).then(() => { + // convert string into IContent; see #32135 + return content; }); - } else { - return undefined; - } + }); }).then(content => { - if (!content) { return undefined; } - - pinned = true; // pin only if config file is created #8727 - return this.fileService.updateContent(resource, content).then(() => { - // convert string into IContent; see #32135 - return content; - }); - }); - }).then(content => { - if (!content) { - return undefined; - } - const index = content.indexOf(`"${this.configurationManager.selectedConfiguration.name}"`); - let startLineNumber = 1; - for (let i = 0; i < index; i++) { - if (content.charAt(i) === '\n') { - startLineNumber++; + const index = content.indexOf(`"${this.configurationManager.selectedConfiguration.name}"`); + let startLineNumber = 1; + for (let i = 0; i < index; i++) { + if (content.charAt(i) === '\n') { + startLineNumber++; + } } - } - const selection = startLineNumber > 1 ? { startLineNumber, startColumn: 4 } : undefined; + const selection = startLineNumber > 1 ? { startLineNumber, startColumn: 4 } : undefined; - return this.editorService.openEditor({ - resource: resource, - options: { - forceOpen: true, - selection, - pinned, - revealIfVisible: true - }, - }, sideBySide); - }, (error) => { - throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); + return this.editorService.openEditor({ + resource: resource, + options: { + forceOpen: true, + selection, + pinned, + revealIfVisible: true + }, + }, sideBySide); + }, (error) => { + throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); + }); }); } } @@ -673,9 +689,9 @@ class WorkspaceLaunch extends Launch implements ILaunch { @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IConfigurationService configurationService: IConfigurationService, @IConfigurationResolverService configurationResolverService: IConfigurationResolverService, - @IWorkspaceContextService contextService: IWorkspaceContextService + @IWorkspaceContextService contextService: IWorkspaceContextService, ) { - super(configurationManager, undefined, fileService, editorService, configurationService, configurationResolverService, contextService); + super(configurationManager, undefined, fileService, editorService, configurationService, contextService); } get uri(): uri { @@ -706,7 +722,7 @@ class UserLaunch extends Launch implements ILaunch { @IPreferencesService private preferencesService: IPreferencesService, @IWorkspaceContextService contextService: IWorkspaceContextService ) { - super(configurationManager, undefined, fileService, editorService, configurationService, configurationResolverService, contextService); + super(configurationManager, undefined, fileService, editorService, configurationService, contextService); } get uri(): uri { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts index 95421d10ef..544fdaeb6d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts @@ -11,6 +11,7 @@ import * as lifecycle from 'vs/base/common/lifecycle'; import * as env from 'vs/base/common/platform'; import uri from 'vs/base/common/uri'; import { visit } from 'vs/base/common/json'; +import severity from 'vs/base/common/severity'; import { Constants } from 'vs/editor/common/core/uint'; import { IAction, Action } from 'vs/base/common/actions'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -30,9 +31,9 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { DebugHoverWidget } from 'vs/workbench/parts/debug/electron-browser/debugHover'; -import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpointAction, DisableBreakpointAction, AddConditionalBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions'; -import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug'; -import { BreakpointWidget } from 'vs/workbench/parts/debug/browser/breakpointWidget'; +import { RemoveBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions'; +import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo, BreakpointWidgetContext } from 'vs/workbench/parts/debug/common/debug'; +import { BreakpointWidget } from 'vs/workbench/parts/debug/electron-browser/breakpointWidget'; import { ExceptionWidget } from 'vs/workbench/parts/debug/browser/exceptionWidget'; import { FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -42,10 +43,12 @@ import { first } from 'vs/base/common/arrays'; import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ContextSubMenu } from 'vs/base/browser/contextmenu'; +import { memoize } from 'vs/base/common/decorators'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { getHover } from 'vs/editor/contrib/hover/getHover'; const HOVER_DELAY = 300; const LAUNCH_JSON_REGEX = /launch\.json$/; -const REMOVE_INLINE_VALUES_DELAY = 100; const INLINE_VALUE_DECORATION_KEY = 'inlinevaluedecoration'; const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added @@ -55,9 +58,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { private toDispose: lifecycle.IDisposable[]; private hoverWidget: DebugHoverWidget; - private showHoverScheduler: RunOnceScheduler; - private hideHoverScheduler: RunOnceScheduler; - private removeInlineValuesScheduler: RunOnceScheduler; + private nonDebugHoverPosition: Position; private hoverRange: Range; private breakpointHintDecoration: string[]; @@ -80,14 +81,12 @@ export class DebugEditorContribution implements IDebugEditorContribution { @ITelemetryService private telemetryService: ITelemetryService, @IConfigurationService private configurationService: IConfigurationService, @IThemeService themeService: IThemeService, - @IKeybindingService private keybindingService: IKeybindingService + @IKeybindingService private keybindingService: IKeybindingService, + @IDialogService private dialogService: IDialogService, ) { this.breakpointHintDecoration = []; this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService, this.instantiationService, themeService); this.toDispose = []; - this.showHoverScheduler = new RunOnceScheduler(() => this.showHover(this.hoverRange, false), HOVER_DELAY); - this.hideHoverScheduler = new RunOnceScheduler(() => this.hoverWidget.hide(), HOVER_DELAY); - this.removeInlineValuesScheduler = new RunOnceScheduler(() => this.editor.removeDecorations(INLINE_VALUE_DECORATION_KEY), REMOVE_INLINE_VALUES_DELAY); this.registerListeners(); this.breakpointWidgetVisible = CONTEXT_BREAKPOINT_WIDGET_VISIBLE.bindTo(contextKeyService); this.updateConfigurationWidgetVisibility(); @@ -98,13 +97,23 @@ export class DebugEditorContribution implements IDebugEditorContribution { private getContextMenuActions(breakpoints: IBreakpoint[], uri: uri, lineNumber: number): TPromise<(IAction | ContextSubMenu)[]> { const actions: (IAction | ContextSubMenu)[] = []; if (breakpoints.length === 1) { - actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL, this.debugService, this.keybindingService)); - actions.push(new EditConditionalBreakpointAction(EditConditionalBreakpointAction.ID, EditConditionalBreakpointAction.LABEL, this.editor, this.debugService, this.keybindingService)); - if (breakpoints[0].enabled) { - actions.push(new DisableBreakpointAction(DisableBreakpointAction.ID, DisableBreakpointAction.LABEL, this.debugService, this.keybindingService)); - } else { - actions.push(new EnableBreakpointAction(EnableBreakpointAction.ID, EnableBreakpointAction.LABEL, this.debugService, this.keybindingService)); - } + const breakpointType = breakpoints[0].logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint"); + actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService, this.keybindingService)); + actions.push(new Action( + 'workbench.debug.action.editBreakpointAction', + nls.localize('editBreakpoint', "Edit {0}...", breakpointType), + undefined, + true, + () => TPromise.as(this.editor.getContribution(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(breakpoints[0].lineNumber, breakpoints[0].column)) + )); + + actions.push(new Action( + `workbench.debug.viewlet.action.toggleBreakpoint`, + breakpoints[0].enabled ? nls.localize('disableBreakpoint', "Disable {0}", breakpointType) : nls.localize('enableBreakpoint', "Enable {0}", breakpointType), + undefined, + true, + () => this.debugService.enableOrDisableBreakpoints(!breakpoints[0].enabled, breakpoints[0]) + )); } else if (breakpoints.length > 1) { const sorted = breakpoints.sort((first, second) => first.column - second.column); actions.push(new ContextSubMenu(nls.localize('removeBreakpoints', "Remove Breakpoints"), sorted.map(bp => new Action( @@ -140,7 +149,20 @@ export class DebugEditorContribution implements IDebugEditorContribution { true, () => this.debugService.addBreakpoints(uri, [{ lineNumber }]) )); - actions.push(new AddConditionalBreakpointAction(AddConditionalBreakpointAction.ID, AddConditionalBreakpointAction.LABEL, this.editor, lineNumber, this.debugService, this.keybindingService)); + actions.push(new Action( + 'addConditionalBreakpoint', + nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint..."), + null, + true, + () => TPromise.as(this.editor.getContribution(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, undefined)) + )); + actions.push(new Action( + 'addLogPoint', + nls.localize('addLogPoint', "Add Logpoint..."), + null, + true, + () => TPromise.as(this.editor.getContribution(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, undefined, BreakpointWidgetContext.LOG_MESSAGE)) + )); } return TPromise.as(actions); @@ -174,7 +196,25 @@ export class DebugEditorContribution implements IDebugEditorContribution { .filter(bp => bp.uri.toString() === uri.toString() && bp.lineNumber === lineNumber); if (breakpoints.length) { - breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId())); + if (breakpoints.some(bp => !!bp.condition || !!bp.logMessage || !!bp.hitCondition)) { + const logPoint = breakpoints.every(bp => !!bp.logMessage); + const breakpointType = logPoint ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint"); + this.dialogService.show(severity.Info, nls.localize('breakpointHasCondition', "This {0} has a {1} that will get lost on remove. Consider disabling the {0} instead.", + breakpointType.toLowerCase(), logPoint ? nls.localize('message', "message") : nls.localize('condition', "condition")), [ + nls.localize('removeLogPoint', "Remove {0}", breakpointType), + nls.localize('disableLogPoint', "Disable {0}", breakpointType), + nls.localize('cancel', "Cancel") + ], { cancelId: 2 }).then(choice => { + if (choice === 0) { + breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId())); + } + if (choice === 1) { + breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(false, bp)); + } + }); + } else { + breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId())); + } } else if (canSetBreakpoints) { this.debugService.addBreakpoints(uri, [{ lineNumber }]); } @@ -201,6 +241,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.toDispose.push(this.editor.onMouseDown((e: IEditorMouseEvent) => this.onEditorMouseDown(e))); this.toDispose.push(this.editor.onMouseMove((e: IEditorMouseEvent) => this.onEditorMouseMove(e))); this.toDispose.push(this.editor.onMouseLeave((e: IEditorMouseEvent) => { + this.provideNonDebugHoverScheduler.cancel(); const hoverDomNode = this.hoverWidget.getDomNode(); if (!hoverDomNode) { return; @@ -215,17 +256,18 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.toDispose.push(this.editor.onKeyDown((e: IKeyboardEvent) => this.onKeyDown(e))); this.toDispose.push(this.editor.onDidChangeModelContent(() => { this.wordToLineNumbersMap = null; + this.updateInlineValuesScheduler.schedule(); })); this.toDispose.push(this.editor.onDidChangeModel(() => { - const sf = this.debugService.getViewModel().focusedStackFrame; + const stackFrame = this.debugService.getViewModel().focusedStackFrame; const model = this.editor.getModel(); - this.editor.updateOptions({ hover: !sf || !model || model.uri.toString() !== sf.source.uri.toString() }); + this.editor.updateOptions({ hover: !stackFrame || !model || model.uri.toString() !== stackFrame.source.uri.toString() }); this.closeBreakpointWidget(); this.toggleExceptionWidget(); this.hideHoverWidget(); this.updateConfigurationWidgetVisibility(); this.wordToLineNumbersMap = null; - this.updateInlineDecorations(sf); + this.updateInlineValueDecorations(stackFrame); })); this.toDispose.push(this.editor.onDidScrollChange(() => this.hideHoverWidget)); this.toDispose.push(this.debugService.onDidChangeState((state: State) => { @@ -288,7 +330,33 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.hideHoverWidget(); } - this.updateInlineDecorations(sf); + this.updateInlineValueDecorations(sf); + } + + @memoize + private get showHoverScheduler(): RunOnceScheduler { + const scheduler = new RunOnceScheduler(() => this.showHover(this.hoverRange, false), HOVER_DELAY); + this.toDispose.push(scheduler); + + return scheduler; + } + + @memoize + private get hideHoverScheduler(): RunOnceScheduler { + const scheduler = new RunOnceScheduler(() => this.hoverWidget.hide(), HOVER_DELAY); + this.toDispose.push(scheduler); + + return scheduler; + } + + @memoize + private get provideNonDebugHoverScheduler(): RunOnceScheduler { + const scheduler = new RunOnceScheduler(() => { + getHover(this.editor.getModel(), this.nonDebugHoverPosition); + }, HOVER_DELAY); + this.toDispose.push(scheduler); + + return scheduler; } private hideHoverWidget(): void { @@ -296,6 +364,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.hideHoverScheduler.schedule(); } this.showHoverScheduler.cancel(); + this.provideNonDebugHoverScheduler.cancel(); } // hover business @@ -313,6 +382,10 @@ export class DebugEditorContribution implements IDebugEditorContribution { return; } + if (!this.configurationService.getValue('debug').enableAllHovers) { + this.nonDebugHoverPosition = mouseEvent.target.position; + this.provideNonDebugHoverScheduler.schedule(); + } const targetType = mouseEvent.target.type; const stopKey = env.isMacintosh ? 'metaKey' : 'ctrlKey'; @@ -341,12 +414,12 @@ export class DebugEditorContribution implements IDebugEditorContribution { // end hover business // breakpoint widget - public showBreakpointWidget(lineNumber: number, column: number): void { + public showBreakpointWidget(lineNumber: number, column: number, context?: BreakpointWidgetContext): void { if (this.breakpointWidget) { this.breakpointWidget.dispose(); } - this.breakpointWidget = this.instantiationService.createInstance(BreakpointWidget, this.editor, lineNumber, column); + this.breakpointWidget = this.instantiationService.createInstance(BreakpointWidget, this.editor, lineNumber, context); this.breakpointWidget.show({ lineNumber, column: 1 }, 2); this.breakpointWidgetVisible.set(true); } @@ -474,7 +547,24 @@ export class DebugEditorContribution implements IDebugEditorContribution { }; // Inline Decorations - private updateInlineDecorations(stackFrame: IStackFrame): void { + + @memoize + private get removeInlineValuesScheduler(): RunOnceScheduler { + return new RunOnceScheduler( + () => this.editor.removeDecorations(INLINE_VALUE_DECORATION_KEY), + 100 + ); + } + + @memoize + private get updateInlineValuesScheduler(): RunOnceScheduler { + return new RunOnceScheduler( + () => this.updateInlineValueDecorations(this.debugService.getViewModel().focusedStackFrame), + 200 + ); + } + + private updateInlineValueDecorations(stackFrame: IStackFrame): void { const model = this.editor.getModel(); if (!this.configurationService.getValue('debug').inlineValues || !model || !stackFrame || model.uri.toString() !== stackFrame.source.uri.toString()) { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts index 8ff594c1df..0aab00de7c 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts @@ -27,6 +27,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry'; import { WorkbenchTree, WorkbenchTreeController } from 'vs/platform/list/browser/listService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; const $ = dom.$; const MAX_ELEMENTS_SHOWN = 18; @@ -89,7 +90,11 @@ export class DebugHoverWidget implements IContentWidget { this.editor.applyFontInfo(this.domNode); this.toDispose.push(attachStylerCallback(this.themeService, { editorHoverBackground, editorHoverBorder }, colors => { - this.domNode.style.backgroundColor = colors.editorHoverBackground; + if (colors.editorHoverBackground) { + this.domNode.style.backgroundColor = colors.editorHoverBackground.toString(); + } else { + this.domNode.style.backgroundColor = null; + } if (colors.editorHoverBorder) { this.domNode.style.border = `1px solid ${colors.editorHoverBorder}`; } else { @@ -204,15 +209,17 @@ export class DebugHoverWidget implements IContentWidget { this.highlightDecorations = this.editor.deltaDecorations(this.highlightDecorations, [{ range: new Range(pos.lineNumber, expressionRange.startColumn, pos.lineNumber, expressionRange.startColumn + matchingExpression.length), - options: { - className: 'hoverHighlight' - } + options: DebugHoverWidget._HOVER_HIGHLIGHT_DECORATION_OPTIONS }]); return this.doShow(pos, expression, focus); }); } + private static _HOVER_HIGHLIGHT_DECORATION_OPTIONS = ModelDecorationOptions.register({ + className: 'hoverHighlight' + }); + private doFindExpression(container: IExpressionContainer, namesToFind: string[]): TPromise { if (!container) { return TPromise.as(null); @@ -281,7 +288,7 @@ export class DebugHoverWidget implements IContentWidget { this.scrollbar.scanDomNode(); if (focus) { this.editor.render(); - this.tree.DOMFocus(); + this.tree.domFocus(); } }); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 99539ed21f..791b47122a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import * as lifecycle from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import * as resources from 'vs/base/common/resources'; import * as strings from 'vs/base/common/strings'; import { generateUuid } from 'vs/base/common/uuid'; @@ -35,7 +35,7 @@ import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import * as debugactions from 'vs/workbench/parts/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/parts/debug/electron-browser/debugConfigurationManager'; -import Constants from 'vs/workbench/parts/markers/common/constants'; +import Constants from 'vs/workbench/parts/markers/electron-browser/constants'; import { ITaskService, ITaskSummary } from 'vs/workbench/parts/tasks/common/taskService'; import { TaskError } from 'vs/workbench/parts/tasks/common/taskSystem'; import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; @@ -51,10 +51,12 @@ import { IBroadcastService, IBroadcast } from 'vs/platform/broadcast/electron-br import { IRemoteConsoleLog, parse, getFirstFrame } from 'vs/base/node/console'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { TaskEvent, TaskEventKind } from 'vs/workbench/parts/tasks/common/tasks'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IAction, Action } from 'vs/base/common/actions'; import { normalizeDriveLetter } from 'vs/base/common/labels'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import product from 'vs/platform/node/product'; const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; @@ -66,10 +68,10 @@ export class DebugService implements debug.IDebugService { public _serviceBrand: any; private sessionStates: Map; - private _onDidChangeState: Emitter; - private _onDidNewProcess: Emitter; - private _onDidEndProcess: Emitter; - private _onDidCustomEvent: Emitter; + private readonly _onDidChangeState: Emitter; + private readonly _onDidNewProcess: Emitter; + private readonly _onDidEndProcess: Emitter; + private readonly _onDidCustomEvent: Emitter; private model: Model; private viewModel: ViewModel; private allProcesses: Map; @@ -82,7 +84,9 @@ export class DebugService implements debug.IDebugService { private breakpointsToSendOnResourceSaved: Set; private launchJsonChanged: boolean; private firstSessionStart: boolean; + private skipRunningTask: boolean; private previousState: debug.State; + private fetchThreadsSchedulers: Map; constructor( @IStorageService private storageService: IStorageService, @@ -91,7 +95,7 @@ export class DebugService implements debug.IDebugService { @IViewletService private viewletService: IViewletService, @IPanelService private panelService: IPanelService, @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService, + @IDialogService private dialogService: IDialogService, @IPartService private partService: IPartService, @IWindowService private windowService: IWindowService, @IBroadcastService private broadcastService: IBroadcastService, @@ -115,6 +119,7 @@ export class DebugService implements debug.IDebugService { this._onDidCustomEvent = new Emitter(); this.sessionStates = new Map(); this.allProcesses = new Map(); + this.fetchThreadsSchedulers = new Map(); this.configurationManager = this.instantiationService.createInstance(ConfigurationManager); this.toDispose.push(this.configurationManager); @@ -294,7 +299,7 @@ export class DebugService implements debug.IDebugService { // Call fetch call stack twice, the first only return the top stack frame. // Second retrieves the rest of the call stack. For performance reasons #25605 this.model.fetchCallStack(thread).then(() => { - return this.tryToAutoFocusStackFrame(thread); + return !event.body.preserveFocusHint ? this.tryToAutoFocusStackFrame(thread) : undefined; }); } }, errors.onUnexpectedError); @@ -302,7 +307,18 @@ export class DebugService implements debug.IDebugService { this.toDisposeOnSessionEnd.get(session.getId()).push(session.onDidThread(event => { if (event.body.reason === 'started') { - this.fetchThreads(session).done(undefined, errors.onUnexpectedError); + // debounce to reduce threadsRequest frequency and improve performance + let scheduler = this.fetchThreadsSchedulers.get(session.getId()); + if (!scheduler) { + scheduler = new RunOnceScheduler(() => { + this.fetchThreads(session).done(undefined, errors.onUnexpectedError); + }, 100); + this.fetchThreadsSchedulers.set(session.getId(), scheduler); + this.toDisposeOnSessionEnd.get(session.getId()).push(scheduler); + } + if (!scheduler.isScheduled()) { + scheduler.schedule(); + } } else if (event.body.reason === 'exited') { this.model.clearThreads(session.getId(), true, event.body.threadId); } @@ -336,10 +352,10 @@ export class DebugService implements debug.IDebugService { const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info; if (event.body.category === 'telemetry') { - // only log telemetry events from debug adapter if the adapter provided the telemetry key + // only log telemetry events from debug adapter if the debug extension provided the telemetry key // and the user opted in telemetry if (session.customTelemetryService && this.telemetryService.isOptedIn) { - // __GDPR__TODO__ We're sending events in the name of the debug adapter and we can not ensure that those are declared correctly. + // __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly. session.customTelemetryService.publicLog(event.body.output, event.body.data); } @@ -350,7 +366,7 @@ export class DebugService implements debug.IDebugService { const waitFor = outputPromises.slice(); const source = event.body.source ? { lineNumber: event.body.line, - column: event.body.column, + column: event.body.column ? event.body.column : 1, source: process.getSource(event.body.source) } : undefined; if (event.body.variablesReference) { @@ -445,7 +461,7 @@ export class DebugService implements debug.IDebugService { let result: Breakpoint[]; try { result = JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => { - return new Breakpoint(uri.parse(breakpoint.uri.external || breakpoint.source.uri.external), breakpoint.lineNumber, breakpoint.column, breakpoint.enabled, breakpoint.condition, breakpoint.hitCondition, breakpoint.adapterData); + return new Breakpoint(uri.parse(breakpoint.uri.external || breakpoint.source.uri.external), breakpoint.lineNumber, breakpoint.column, breakpoint.enabled, breakpoint.condition, breakpoint.hitCondition, breakpoint.logMessage, breakpoint.adapterData); }); } catch (e) { } @@ -456,7 +472,7 @@ export class DebugService implements debug.IDebugService { let result: FunctionBreakpoint[]; try { result = JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => { - return new FunctionBreakpoint(fb.name, fb.enabled, fb.hitCondition); + return new FunctionBreakpoint(fb.name, fb.enabled, fb.hitCondition, fb.condition, fb.logMessage); }); } catch (e) { } @@ -583,11 +599,11 @@ export class DebugService implements debug.IDebugService { return this.sendAllBreakpoints(); } - public addBreakpoints(uri: uri, rawBreakpoints: debug.IBreakpointData[]): TPromise { - this.model.addBreakpoints(uri, rawBreakpoints); + public addBreakpoints(uri: uri, rawBreakpoints: debug.IBreakpointData[]): TPromise { + const breakpoints = this.model.addBreakpoints(uri, rawBreakpoints); rawBreakpoints.forEach(rbp => aria.status(nls.localize('breakpointAdded', "Added breakpoint, line {0}, file {1}", rbp.lineNumber, uri.fsPath))); - return this.sendBreakpoints(uri); + return this.sendBreakpoints(uri).then(() => breakpoints); } public updateBreakpoints(uri: uri, data: { [id: string]: DebugProtocol.Breakpoint }, sendOnResourceSaved: boolean): void { @@ -665,7 +681,14 @@ export class DebugService implements debug.IDebugService { this.model.removeWatchExpressions(id); } - public startDebugging(launch: debug.ILaunch, configOrName?: debug.IConfig | string, noDebug = false): TPromise { + public startDebugging(launch: debug.ILaunch, configOrName?: debug.IConfig | string, noDebug = false): TPromise { + const sessionId = generateUuid(); + this.updateStateAndEmit(sessionId, debug.State.Initializing); + const wrapUpState = () => { + if (this.sessionStates.get(sessionId) === debug.State.Initializing) { + this.updateStateAndEmit(sessionId, debug.State.Inactive); + } + }; // make sure to save all files and that the configuration is up to date return this.extensionService.activateByEvent('onDebug').then(() => this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined).then(() => @@ -743,43 +766,57 @@ export class DebugService implements debug.IDebugService { config.noDebug = true; } - const sessionId = generateUuid(); - this.updateStateAndEmit(sessionId, debug.State.Initializing); - const wrapUpState = () => { - if (this.sessionStates.get(sessionId) === debug.State.Initializing) { - this.updateStateAndEmit(sessionId, debug.State.Inactive); - } - }; + return (type ? TPromise.as(null) : this.configurationManager.guessDebugger().then(a => type = a && a.type)).then(() => + this.configurationManager.resolveConfigurationByProviders(launch && launch.workspace ? launch.workspace.uri : undefined, type, config).then(config => { + // a falsy config indicates an aborted launch + if (config && config.type) { + return this.createProcess(launch, config, sessionId); + } - return (type ? TPromise.as(null) : this.configurationManager.guessAdapter().then(a => type = a && a.type)).then(() => - (type ? this.extensionService.activateByEvent(`onDebugResolve:${type}`) : TPromise.as(null)).then(() => - this.configurationManager.resolveConfigurationByProviders(launch && launch.workspace ? launch.workspace.uri : undefined, type, config).then(config => { - // a falsy config indicates an aborted launch - if (config && config.type) { - return this.createProcess(launch, config, sessionId); - } - - if (launch) { - return launch.openConfigFile(false, type).done(undefined, errors.onUnexpectedError); - } - }) - ).then(() => wrapUpState(), err => { - wrapUpState(); - return TPromise.wrapError(err); - })); + if (launch && type) { + return launch.openConfigFile(false, type).done(undefined, errors.onUnexpectedError); + } + }) + ).then(() => undefined); }) - ))); + ))).then(() => wrapUpState(), err => { + wrapUpState(); + return TPromise.wrapError(err); + }); + } + + private substituteVariables(launch: debug.ILaunch | undefined, config: debug.IConfig): TPromise { + const dbg = this.configurationManager.getDebugger(config.type); + if (dbg) { + let folder: IWorkspaceFolder = undefined; + if (launch && launch.workspace) { + folder = launch.workspace; + } else { + const folders = this.contextService.getWorkspace().folders; + if (folders.length === 1) { + folder = folders[0]; + } + } + return dbg.substituteVariables(folder, config).then(config => { + return config; + }, (err: Error) => { + this.showError(err.message); + return undefined; // bail out + }); + } + return TPromise.as(config); } private createProcess(launch: debug.ILaunch, config: debug.IConfig, sessionId: string): TPromise { return this.textFileService.saveAll().then(() => - (launch ? launch.resolveConfiguration(config) : TPromise.as(config)).then(resolvedConfig => { + this.substituteVariables(launch, config).then(resolvedConfig => { + if (!resolvedConfig) { // User canceled resolving of interactive variables, silently return return undefined; } - if (!this.configurationManager.getAdapter(resolvedConfig.type) || (config.request !== 'attach' && config.request !== 'launch')) { + if (!this.configurationManager.getDebugger(resolvedConfig.type) || (config.request !== 'attach' && config.request !== 'launch')) { let message: string; if (config.request !== 'attach' && config.request !== 'launch') { message = config.request ? nls.localize('debugRequestNotSupported', "Attribute '{0}' has an unsupported value '{1}' in the chosen debug configuration.", 'request', config.request) @@ -800,7 +837,7 @@ export class DebugService implements debug.IDebugService { return this.doCreateProcess(workspace, resolvedConfig, sessionId); }); - return this.runPreLaunchTask(sessionId, workspace, resolvedConfig.preLaunchTask).then((taskSummary: ITaskSummary) => { + return this.runTask(sessionId, workspace, resolvedConfig.preLaunchTask).then((taskSummary: ITaskSummary) => { const errorCount = resolvedConfig.preLaunchTask ? this.markerService.getStatistics().errors : 0; const successExitCode = taskSummary && taskSummary.exitCode === 0; const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; @@ -840,9 +877,9 @@ export class DebugService implements debug.IDebugService { telemetryInfo['common.vscodesessionid'] = info.sessionId; return telemetryInfo; }).then(data => { - const adapter = this.configurationManager.getAdapter(configuration.type); - const { aiKey, type } = adapter; - const publisher = adapter.extensionDescription.publisher; + const dbg = this.configurationManager.getDebugger(configuration.type); + const { aiKey, type } = dbg; + const publisher = dbg.extensionDescription.publisher; let client: TelemetryClient; let customTelemetryService: TelemetryService; @@ -867,7 +904,7 @@ export class DebugService implements debug.IDebugService { customTelemetryService = new TelemetryService({ appender }, this.configurationService); } - const session = this.instantiationService.createInstance(RawDebugSession, sessionId, configuration.debugServer, adapter, customTelemetryService, root); + const session = this.instantiationService.createInstance(RawDebugSession, sessionId, configuration.debugServer, dbg, customTelemetryService, root); const process = this.model.addProcess(configuration, session); this.allProcesses.set(process.getId(), process); @@ -878,6 +915,7 @@ export class DebugService implements debug.IDebugService { return session.initialize({ clientID: 'vscode', + clientName: product.nameLong, adapterID: configuration.type, pathFormat: 'path', linesStartAt1: true, @@ -917,12 +955,12 @@ export class DebugService implements debug.IDebugService { /* __GDPR__ "debugSessionStart" : { "type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "exceptionBreakpoints": { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionName": { "classification": "PublicPersonalData", "purpose": "FeatureInsight" }, - "isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "launchJsonExists": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "exceptionBreakpoints": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "extensionName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true}, + "launchJsonExists": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ return this.telemetryService.publicLog('debugSessionStart', { @@ -930,8 +968,8 @@ export class DebugService implements debug.IDebugService { breakpointCount: this.model.getBreakpoints().length, exceptionBreakpoints: this.model.getExceptionBreakpoints(), watchExpressionsCount: this.model.getWatchExpressions().length, - extensionName: `${adapter.extensionDescription.publisher}.${adapter.extensionDescription.name}`, - isBuiltin: adapter.extensionDescription.isBuiltin, + extensionName: dbg.extensionDescription.id, + isBuiltin: dbg.extensionDescription.isBuiltin, launchJsonExists: root && !!this.configurationService.getValue('launch', { resource: root.uri }) }); }).then(() => process, (error: Error | string) => { @@ -951,10 +989,10 @@ export class DebugService implements debug.IDebugService { this.updateStateAndEmit(session.getId(), debug.State.Inactive); if (!session.disconnected) { session.disconnect().done(null, errors.onUnexpectedError); - } - if (process) { + } else if (process) { this.model.removeProcess(process.getId()); } + // Show the repl if some error got logged there #5870 if (this.model.getReplElements().length > 0) { this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); @@ -972,7 +1010,7 @@ export class DebugService implements debug.IDebugService { private showError(message: string, actions: IAction[] = []): TPromise { const configureAction = this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL); actions.push(configureAction); - return this.choiceService.choose(severity.Error, message, actions.map(a => a.label).concat(nls.localize('cancel', "Cancel")), actions.length, true).then(choice => { + return this.dialogService.show(severity.Error, message, actions.map(a => a.label).concat(nls.localize('cancel', "Cancel")), { cancelId: actions.length }).then(choice => { if (choice < actions.length) { return actions[choice].run(); } @@ -981,15 +1019,16 @@ export class DebugService implements debug.IDebugService { }); } - private runPreLaunchTask(sessionId: string, root: IWorkspaceFolder, taskName: string): TPromise { - if (!taskName) { + private runTask(sessionId: string, root: IWorkspaceFolder, taskName: string): TPromise { + if (!taskName || this.skipRunningTask) { + this.skipRunningTask = false; return TPromise.as(null); } // run a task before starting a debug session return this.taskService.getTask(root, taskName).then(task => { if (!task) { - return TPromise.wrapError(errors.create(nls.localize('DebugTaskNotFound', "Could not find the preLaunchTask \'{0}\'.", taskName))); + return TPromise.wrapError(errors.create(nls.localize('DebugTaskNotFound', "Could not find the task \'{0}\'.", taskName))); } function once(kind: TaskEventKind, event: Event): Event { @@ -1033,7 +1072,7 @@ export class DebugService implements debug.IDebugService { setTimeout(() => { if (!taskStarted) { - e({ severity: severity.Error, message: nls.localize('taskNotTracked', "The preLaunchTask '{0}' cannot be tracked.", taskName) }); + e({ severity: severity.Error, message: nls.localize('taskNotTracked', "The task '{0}' cannot be tracked.", taskName) }); } }, 10000); }); @@ -1051,6 +1090,8 @@ export class DebugService implements debug.IDebugService { } const focusedProcess = this.viewModel.focusedProcess; const preserveFocus = focusedProcess && process.getId() === focusedProcess.getId(); + // Do not run preLaunch and postDebug tasks for automatic restarts + this.skipRunningTask = !!restartData; return process.session.disconnect(true).then(() => { if (strings.equalsIgnoreCase(process.configuration.type, 'extensionHost') && process.session.root) { @@ -1074,6 +1115,7 @@ export class DebugService implements debug.IDebugService { config.noDebug = process.configuration.noDebug; } config.__restart = restartData; + this.skipRunningTask = !!restartData; this.startDebugging(launch, config).then(() => c(null), err => e(err)); }, 300); }); @@ -1110,10 +1152,10 @@ export class DebugService implements debug.IDebugService { /* __GDPR__ "debugSessionStop" : { "type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "sessionLengthInSeconds": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "sessionLengthInSeconds": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('debugSessionStop', { @@ -1128,6 +1170,11 @@ export class DebugService implements debug.IDebugService { if (process) { process.inactive = true; this._onDidEndProcess.fire(process); + if (process.configuration.postDebugTask) { + this.runTask(process.getId(), process.session.root, process.configuration.postDebugTask).done(undefined, err => + this.notificationService.error(err) + ); + } } this.toDisposeOnSessionEnd.set(session.getId(), lifecycle.dispose(this.toDisposeOnSessionEnd.get(session.getId()))); @@ -1182,9 +1229,9 @@ export class DebugService implements debug.IDebugService { return TPromise.as(null); } - const breakpointsToSend = this.model.getBreakpoints().filter(bp => this.model.areBreakpointsActivated() && bp.enabled && bp.uri.toString() === modelUri.toString()); + const breakpointsToSend = this.model.getEnabledBreakpointsForResource(modelUri); - const source = process.sources.get(modelUri.toString()); + const source = process.getSourceForUri(modelUri); let rawSource: DebugProtocol.Source; if (source) { rawSource = source.raw; @@ -1202,7 +1249,7 @@ export class DebugService implements debug.IDebugService { return session.setBreakpoints({ source: rawSource, lines: breakpointsToSend.map(bp => bp.lineNumber), - breakpoints: breakpointsToSend.map(bp => ({ line: bp.lineNumber, column: bp.column, condition: bp.condition, hitCondition: bp.hitCondition })), + breakpoints: breakpointsToSend.map(bp => ({ line: bp.lineNumber, column: bp.column, condition: bp.condition, hitCondition: bp.hitCondition, logMessage: bp.logMessage })), sourceModified }).then(response => { if (!response || !response.body) { @@ -1280,11 +1327,11 @@ export class DebugService implements debug.IDebugService { } fileChangesEvent.getUpdated().forEach(event => { - if (this.breakpointsToSendOnResourceSaved.has(event.resource.toString())) { - this.breakpointsToSendOnResourceSaved.delete(event.resource.toString()); + + if (this.breakpointsToSendOnResourceSaved.delete(event.resource.toString())) { this.sendBreakpoints(event.resource, true).done(null, errors.onUnexpectedError); } - if (event.resource.toString().indexOf('.vscode/launch.json') >= 0) { + if (strings.endsWith(event.resource.toString(), '.vscode/launch.json')) { this.launchJsonChanged = true; } }); diff --git a/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.ts b/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.ts index c4487ee964..9cef6a3bf5 100644 --- a/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.ts +++ b/src/vs/workbench/parts/debug/electron-browser/electronDebugActions.ts @@ -9,8 +9,9 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ITree } from 'vs/base/parts/tree/browser/tree'; import { removeAnsiEscapeCodes } from 'vs/base/common/strings'; import { Variable } from 'vs/workbench/parts/debug/common/debugModel'; -import { IDebugService, IStackFrame } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, IStackFrame, IReplElement } from 'vs/workbench/parts/debug/common/debug'; import { clipboard } from 'electron'; +import { isWindows } from 'vs/base/common/platform'; export class CopyValueAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.copyValue'; @@ -18,6 +19,7 @@ export class CopyValueAction extends Action { constructor(id: string, label: string, private value: any, @IDebugService private debugService: IDebugService) { super(id, label, 'debug-action copy-value'); + this._enabled = typeof this.value === 'string' || (this.value instanceof Variable && !!this.value.evaluateName); } public run(): TPromise { @@ -38,15 +40,13 @@ export class CopyEvaluatePathAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.copyEvaluatePath'; static LABEL = nls.localize('copyAsExpression', "Copy as Expression"); - constructor(id: string, label: string, private value: any) { + constructor(id: string, label: string, private value: Variable) { super(id, label); + this._enabled = this.value && !!this.value.evaluateName; } public run(): TPromise { - if (this.value instanceof Variable) { - clipboard.writeText(this.value.evaluateName); - } - + clipboard.writeText(this.value.evaluateName); return TPromise.as(null); } } @@ -61,6 +61,7 @@ export class CopyAction extends Action { } } +const lineDelimiter = isWindows ? '\r\n' : '\n'; export class CopyAllAction extends Action { static readonly ID = 'workbench.debug.action.copyAll'; static LABEL = nls.localize('copyAll', "Copy All"); @@ -75,9 +76,9 @@ export class CopyAllAction extends Action { // skip first navigator element - the root node while (navigator.next()) { if (text) { - text += `\n`; + text += lineDelimiter; } - text += navigator.current().toString(); + text += (navigator.current()).toString(); } clipboard.writeText(removeAnsiEscapeCodes(text)); @@ -90,7 +91,7 @@ export class CopyStackTraceAction extends Action { static LABEL = nls.localize('copyStackTrace', "Copy Call Stack"); public run(frame: IStackFrame): TPromise { - clipboard.writeText(frame.thread.getCallStack().map(sf => sf.toString()).join('\n')); + clipboard.writeText(frame.thread.getCallStack().map(sf => sf.toString()).join(lineDelimiter)); return TPromise.as(null); } } diff --git a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts index c91a01c069..7713c6927a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts @@ -3,28 +3,21 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); -import cp = require('child_process'); -import net = require('net'); -import Event, { Emitter } from 'vs/base/common/event'; -import platform = require('vs/base/common/platform'); -import objects = require('vs/base/common/objects'); +import * as nls from 'vs/nls'; +import * as net from 'net'; +import { Event, Emitter } from 'vs/base/common/event'; +import * as objects from 'vs/base/common/objects'; import { Action } from 'vs/base/common/actions'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { TPromise } from 'vs/base/common/winjs.base'; -import stdfork = require('vs/base/node/stdFork'); import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; -import { ITerminalService as IExternalTerminalService } from 'vs/workbench/parts/execution/common/execution'; -import debug = require('vs/workbench/parts/debug/common/debug'); -import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; -import { V8Protocol } from 'vs/workbench/parts/debug/node/v8Protocol'; +import * as debug from 'vs/workbench/parts/debug/common/debug'; +import { Debugger } from 'vs/workbench/parts/debug/node/debugger'; import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { TerminalSupport } from 'vs/workbench/parts/debug/electron-browser/terminalSupport'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { StreamDebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter'; + export interface SessionExitedEvent extends debug.DebugEvent { body: { @@ -40,45 +33,73 @@ export interface SessionTerminatedEvent extends debug.DebugEvent { }; } -export class RawDebugSession extends V8Protocol implements debug.ISession { +export class SocketDebugAdapter extends StreamDebugAdapter { + + private socket: net.Socket; + + constructor(private host: string, private port: number) { + super(); + } + + startSession(): TPromise { + return new TPromise((c, e) => { + this.socket = net.createConnection(this.port, this.host, () => { + this.connect(this.socket, this.socket); + c(null); + }); + this.socket.on('error', (err: any) => { + e(err); + }); + this.socket.on('close', () => this._onExit.fire(0)); + }); + } + + stopSession(): TPromise { + if (this.socket !== null) { + this.socket.end(); + this.socket = undefined; + } + return void 0; + } +} + +export class RawDebugSession implements debug.ISession { + + private debugAdapter: debug.IDebugAdapter; public emittedStopped: boolean; public readyForBreakpoints: boolean; - private serverProcess: cp.ChildProcess; - private socket: net.Socket = null; - private cachedInitServer: TPromise; + //private serverProcess: cp.ChildProcess; + //private socket: net.Socket = null; + private cachedInitServerP: TPromise; private startTime: number; public disconnected: boolean; private sentPromises: TPromise[]; private _capabilities: DebugProtocol.Capabilities; private allThreadsContinued: boolean; - private _onDidInitialize: Emitter; - private _onDidStop: Emitter; - private _onDidContinued: Emitter; - private _onDidTerminateDebugee: Emitter; - private _onDidExitAdapter: Emitter; - private _onDidThread: Emitter; - private _onDidOutput: Emitter; - private _onDidBreakpoint: Emitter; - private _onDidCustomEvent: Emitter; - private _onDidEvent: Emitter; + private readonly _onDidInitialize: Emitter; + private readonly _onDidStop: Emitter; + private readonly _onDidContinued: Emitter; + private readonly _onDidTerminateDebugee: Emitter; + private readonly _onDidExitAdapter: Emitter; + private readonly _onDidThread: Emitter; + private readonly _onDidOutput: Emitter; + private readonly _onDidBreakpoint: Emitter; + private readonly _onDidCustomEvent: Emitter; + private readonly _onDidEvent: Emitter; constructor( - id: string, + private id: string, private debugServerPort: number, - private adapter: Adapter, + private _debugger: Debugger, public customTelemetryService: ITelemetryService, public root: IWorkspaceFolder, @INotificationService private notificationService: INotificationService, @ITelemetryService private telemetryService: ITelemetryService, - @IOutputService private outputService: IOutputService, - @ITerminalService private terminalService: ITerminalService, - @IExternalTerminalService private nativeTerminalService: IExternalTerminalService, - @IConfigurationService private configurationService: IConfigurationService + @IOutputService private outputService: IOutputService ) { - super(id); this.emittedStopped = false; this.readyForBreakpoints = false; this.allThreadsContinued = true; @@ -96,6 +117,10 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { this._onDidEvent = new Emitter(); } + public getId(): string { + return this.id; + } + public get onDidInitialize(): Event { return this._onDidInitialize.event; } @@ -137,28 +162,49 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { } private initServer(): TPromise { - if (this.cachedInitServer) { - return this.cachedInitServer; + + if (this.cachedInitServerP) { + return this.cachedInitServerP; } - const serverPromise = this.debugServerPort ? this.connectServer(this.debugServerPort) : this.startServer(); - this.cachedInitServer = serverPromise.then(() => { + const startSessionP = this.startSession(); + + this.cachedInitServerP = startSessionP.then(() => { this.startTime = new Date().getTime(); }, err => { - this.cachedInitServer = null; + this.cachedInitServerP = null; return TPromise.wrapError(err); }); - return this.cachedInitServer; + return this.cachedInitServerP; + } + + private startSession(): TPromise { + + const debugAdapterP = this.debugServerPort + ? TPromise.as(new SocketDebugAdapter('127.0.0.1', this.debugServerPort)) + : this._debugger.createDebugAdapter(this.root, this.outputService); + + return debugAdapterP.then(debugAdapter => { + + this.debugAdapter = debugAdapter; + + this.debugAdapter.onError(err => this.onDapServerError(err)); + this.debugAdapter.onEvent(event => this.onDapEvent(event)); + this.debugAdapter.onRequest(request => this.dispatchRequest(request)); + this.debugAdapter.onExit(code => this.onServerExit()); + + return this.debugAdapter.startSession(); + }); } public custom(request: string, args: any): TPromise { return this.send(request, args); } - protected send(command: string, args: any, cancelOnDisconnect = true): TPromise { + private send(command: string, args: any, cancelOnDisconnect = true): TPromise { return this.initServer().then(() => { - const promise = super.send(command, args).then(response => response, (errorResponse: DebugProtocol.ErrorResponse) => { + const promise = this.internalSend(command, args).then(response => response, (errorResponse: DebugProtocol.ErrorResponse) => { const error = errorResponse && errorResponse.body ? errorResponse.body.error : null; const errorMessage = errorResponse ? errorResponse.message : ''; const telemetryMessage = error ? debug.formatPII(error.format, true, error.variables) : errorMessage; @@ -199,8 +245,22 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { }); } - protected onEvent(event: debug.DebugEvent): void { - event.sessionId = this.getId(); + private internalSend(command: string, args: any): TPromise { + let errorCallback: (error: Error) => void; + return new TPromise((completeDispatch, errorDispatch) => { + errorCallback = errorDispatch; + this.debugAdapter.sendRequest(command, args, (result: R) => { + if (result.success) { + completeDispatch(result); + } else { + errorDispatch(result); + } + }); + }, () => errorCallback(errors.canceled())); + } + + private onDapEvent(event: debug.DebugEvent): void { + event.sessionId = this.id; if (event.event === 'initialized') { this.readyForBreakpoints = true; @@ -290,6 +350,10 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { return this.send('pause', args); } + public terminateThreads(args: DebugProtocol.TerminateThreadsArguments): TPromise { + return this.send('terminateThreads', args); + } + public setVariable(args: DebugProtocol.SetVariableArguments): TPromise { return this.send('setVariable', args); } @@ -317,7 +381,7 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { this.sentPromises = []; }, 1000); - if ((this.serverProcess || this.socket) && !this.disconnected) { + if (this.debugAdapter && !this.disconnected) { // point of no return: from now on don't report any errors this.disconnected = true; return this.send('disconnect', { restart: restart }, false).then(() => this.stopServer(), () => this.stopServer()); @@ -372,14 +436,18 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { public stepBack(args: DebugProtocol.StepBackArguments): TPromise { return this.send('stepBack', args).then(response => { - this.fireFakeContinued(args.threadId); + if (response.body === undefined) { + this.fireFakeContinued(args.threadId); + } return response; }); } public reverseContinue(args: DebugProtocol.ReverseContinueArguments): TPromise { return this.send('reverseContinue', args).then(response => { - this.fireFakeContinued(args.threadId); + if (response.body === undefined) { + this.fireFakeContinued(args.threadId); + } return response; }); } @@ -388,17 +456,27 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { return (new Date().getTime() - this.startTime) / 1000; } - protected dispatchRequest(request: DebugProtocol.Request, response: DebugProtocol.Response): void { + private dispatchRequest(request: DebugProtocol.Request): void { + + const response: DebugProtocol.Response = { + type: 'response', + seq: 0, + command: request.command, + request_seq: request.seq, + success: true + }; if (request.command === 'runInTerminal') { - TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, this.configurationService, request.arguments, response).then(() => { - this.sendResponse(response); - }, e => { + this._debugger.runInTerminal(request.arguments).then(_ => { + response.body = {}; + this.debugAdapter.sendResponse(response); + }, err => { response.success = false; - response.message = e.message; - this.sendResponse(response); + response.message = err.message; + this.debugAdapter.sendResponse(response); }); + } else if (request.command === 'handshake') { try { const vsda = require.__$__nodeRequire('vsda'); @@ -407,16 +485,16 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { response.body = { signature: sig }; - this.sendResponse(response); + this.debugAdapter.sendResponse(response); } catch (e) { response.success = false; response.message = e.message; - this.sendResponse(response); + this.debugAdapter.sendResponse(response); } } else { response.success = false; response.message = `unknown request '${request.command}'`; - this.sendResponse(response); + this.debugAdapter.sendResponse(response); } } @@ -432,111 +510,36 @@ export class RawDebugSession extends V8Protocol implements debug.ISession { }); } - private connectServer(port: number): TPromise { - return new TPromise((c, e) => { - this.socket = net.createConnection(port, '127.0.0.1', () => { - this.connect(this.socket, this.socket); - c(null); - }); - this.socket.on('error', (err: any) => { - e(err); - }); - this.socket.on('close', () => this.onServerExit()); - }); - } - - private startServer(): TPromise { - return this.adapter.getAdapterExecutable(this.root).then(ae => this.launchServer(ae).then(() => { - this.serverProcess.on('error', (err: Error) => this.onServerError(err)); - this.serverProcess.on('exit', (code: number, signal: string) => this.onServerExit()); - - const sanitize = (s: string) => s.toString().replace(/\r?\n$/mg, ''); - // this.serverProcess.stdout.on('data', (data: string) => { - // console.log('%c' + sanitize(data), 'background: #ddd; font-style: italic;'); - // }); - this.serverProcess.stderr.on('data', (data: string) => { - this.outputService.getChannel(ExtensionsChannelId).append(sanitize(data)); - }); - - this.connect(this.serverProcess.stdout, this.serverProcess.stdin); - })); - } - - private launchServer(launch: debug.IAdapterExecutable): TPromise { - return new TPromise((c, e) => { - if (launch.command === 'node') { - if (Array.isArray(launch.args) && launch.args.length > 0) { - stdfork.fork(launch.args[0], launch.args.slice(1), {}, (err, child) => { - if (err) { - e(new Error(nls.localize('unableToLaunchDebugAdapter', "Unable to launch debug adapter from '{0}'.", launch.args[0]))); - } - this.serverProcess = child; - c(null); - }); - } else { - e(new Error(nls.localize('unableToLaunchDebugAdapterNoArgs', "Unable to launch debug adapter."))); - } - } else { - this.serverProcess = cp.spawn(launch.command, launch.args, { - stdio: [ - 'pipe', // stdin - 'pipe', // stdout - 'pipe' // stderr - ], - }); - c(null); - } - }); - } - private stopServer(): TPromise { - if (this.socket !== null) { - this.socket.end(); - this.cachedInitServer = null; + if (/* this.socket !== null */ this.debugAdapter instanceof SocketDebugAdapter) { + this.debugAdapter.stopSession(); + this.cachedInitServerP = null; } - this.onEvent({ event: 'exit', type: 'event', seq: 0 }); - if (!this.serverProcess) { + this.onDapEvent({ event: 'exit', type: 'event', seq: 0 }); + if (/* !this.serverProcess */ this.debugAdapter instanceof SocketDebugAdapter) { return TPromise.as(null); } this.disconnected = true; - let ret: TPromise; - // when killing a process in windows its child - // processes are *not* killed but become root - // processes. Therefore we use TASKKILL.EXE - if (platform.isWindows) { - ret = new TPromise((c, e) => { - const killer = cp.exec(`taskkill /F /T /PID ${this.serverProcess.pid}`, function (err, stdout, stderr) { - if (err) { - return e(err); - } - }); - killer.on('exit', c); - killer.on('error', e); - }); - } else { - this.serverProcess.kill('SIGTERM'); - ret = TPromise.as(null); - } - - return ret; + return this.debugAdapter.stopSession(); } - protected onServerError(err: Error): void { - this.notificationService.error(nls.localize('stoppingDebugAdapter', "{0}. Stopping the debug adapter.", err.message)); + private onDapServerError(err: Error): void { + this.notificationService.error(err.message || err.toString()); this.stopServer().done(null, errors.onUnexpectedError); } private onServerExit(): void { - this.serverProcess = null; - this.cachedInitServer = null; + //this.serverProcess = null; + this.debugAdapter = null; + this.cachedInitServerP = null; if (!this.disconnected) { this.notificationService.error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly")); } - this.onEvent({ event: 'exit', type: 'event', seq: 0 }); + this.onDapEvent({ event: 'exit', type: 'event', seq: 0 }); } public dispose(): void { diff --git a/src/vs/workbench/parts/debug/electron-browser/repl.ts b/src/vs/workbench/parts/debug/electron-browser/repl.ts index 6dc381d7dc..086d1441f3 100644 --- a/src/vs/workbench/parts/debug/electron-browser/repl.ts +++ b/src/vs/workbench/parts/debug/electron-browser/repl.ts @@ -10,7 +10,6 @@ import { wireCancellationToken } from 'vs/base/common/async'; import { TPromise } from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import { IAction } from 'vs/base/common/actions'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import * as dom from 'vs/base/browser/dom'; import { isMacintosh } from 'vs/base/common/platform'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -19,7 +18,6 @@ import { ITree, ITreeOptions } from 'vs/base/parts/tree/browser/tree'; import { Context as SuggestContext } from 'vs/editor/contrib/suggest/suggest'; import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { ITextModel } from 'vs/editor/common/model'; -import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { Position } from 'vs/editor/common/core/position'; import * as modes from 'vs/editor/common/modes'; import { registerEditorAction, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; @@ -31,13 +29,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ReplExpressionsRenderer, ReplExpressionsController, ReplExpressionsDataSource, ReplExpressionsActionProvider, ReplExpressionsAccessibilityProvider } from 'vs/workbench/parts/debug/electron-browser/replViewer'; -import { ReplInputEditor } from 'vs/workbench/parts/debug/electron-browser/replEditor'; +import { SimpleDebugEditor } from 'vs/workbench/parts/debug/electron-browser/simpleDebugEditor'; import * as debug from 'vs/workbench/parts/debug/common/debug'; import { ClearReplAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { ReplHistory } from 'vs/workbench/parts/debug/common/replHistory'; import { Panel } from 'vs/workbench/browser/panel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { clipboard } from 'electron'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -45,6 +42,7 @@ import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { memoize } from 'vs/base/common/decorators'; import { dispose } from 'vs/base/common/lifecycle'; import { OpenMode, ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; const $ = dom.$; @@ -77,11 +75,11 @@ export class Repl extends Panel implements IPrivateReplService { private renderer: ReplExpressionsRenderer; private container: HTMLElement; private treeContainer: HTMLElement; - private replInput: ReplInputEditor; + private replInput: SimpleDebugEditor; private replInputContainer: HTMLElement; private refreshTimeoutHandle: number; private actions: IAction[]; - private dimension: Dimension; + private dimension: dom.Dimension; private replInputHeight: number; private model: ITextModel; @@ -128,9 +126,9 @@ export class Repl extends Panel implements IPrivateReplService { } } - public create(parent: Builder): TPromise { + public create(parent: HTMLElement): TPromise { super.create(parent); - this.container = dom.append(parent.getHTMLElement(), $('.repl')); + this.container = dom.append(parent, $('.repl')); this.treeContainer = dom.append(this.container, $('.repl-tree')); this.createReplInput(this.container); @@ -156,7 +154,7 @@ export class Repl extends Panel implements IPrivateReplService { if (!visible) { dispose(this.model); } else { - this.model = this.modelService.createModel('', null, uri.parse(`${debug.DEBUG_SCHEME}:input`)); + this.model = this.modelService.createModel('', null, uri.parse(`${debug.DEBUG_SCHEME}:input`), true); this.replInput.setModel(this.model); } @@ -176,9 +174,9 @@ export class Repl extends Panel implements IPrivateReplService { const scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection( [IContextKeyService, scopedContextKeyService], [IPrivateReplService, this])); - this.replInput = scopedInstantiationService.createInstance(ReplInputEditor, this.replInputContainer, this.getReplInputOptions()); + this.replInput = scopedInstantiationService.createInstance(SimpleDebugEditor, this.replInputContainer, SimpleDebugEditor.getEditorOptions()); - modes.SuggestRegistry.register({ scheme: debug.DEBUG_SCHEME }, { + modes.SuggestRegistry.register({ scheme: debug.DEBUG_SCHEME, hasAccessToAllModels: true }, { triggerCharacters: ['.'], provideCompletionItems: (model: ITextModel, position: Position, _context: modes.SuggestContext, token: CancellationToken): Thenable => { const word = this.replInput.getModel().getWordAtPosition(position); @@ -243,7 +241,7 @@ export class Repl extends Panel implements IPrivateReplService { return text; } - public layout(dimension: Dimension): void { + public layout(dimension: dom.Dimension): void { this.dimension = dimension; if (this.tree) { this.renderer.setWidth(dimension.width - 25, this.characterWidth); @@ -295,29 +293,6 @@ export class Repl extends Panel implements IPrivateReplService { } } - private getReplInputOptions(): IEditorOptions { - return { - wordWrap: 'on', - overviewRulerLanes: 0, - glyphMargin: false, - lineNumbers: 'off', - folding: false, - selectOnLineNumbers: false, - selectionHighlight: false, - scrollbar: { - horizontal: 'hidden' - }, - lineDecorationsWidth: 0, - scrollBeyondLastLine: false, - renderLineHighlight: 'none', - fixedOverflowWidgets: true, - acceptSuggestionOnEnter: 'smart', - minimap: { - enabled: false - } - }; - } - public dispose(): void { this.replInput.dispose(); super.dispose(); @@ -333,7 +308,7 @@ class ReplHistoryPreviousAction extends EditorAction { alias: 'History Previous', precondition: debug.CONTEXT_IN_DEBUG_REPL, kbOpts: { - kbExpr: ContextKeyExpr.and(EditorContextKeys.textFocus, debug.CONTEXT_ON_FIRST_DEBUG_REPL_LINE), + kbExpr: debug.CONTEXT_ON_FIRST_DEBUG_REPL_LINE, primary: KeyCode.UpArrow, weight: 50 }, @@ -357,7 +332,7 @@ class ReplHistoryNextAction extends EditorAction { alias: 'History Next', precondition: debug.CONTEXT_IN_DEBUG_REPL, kbOpts: { - kbExpr: ContextKeyExpr.and(EditorContextKeys.textFocus, debug.CONTEXT_ON_LAST_DEBUG_REPL_LINE), + kbExpr: debug.CONTEXT_ON_LAST_DEBUG_REPL_LINE, primary: KeyCode.DownArrow, weight: 50 }, @@ -381,7 +356,7 @@ class AcceptReplInputAction extends EditorAction { alias: 'REPL Accept Input', precondition: debug.CONTEXT_IN_DEBUG_REPL, kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.Enter } }); @@ -421,7 +396,7 @@ registerEditorCommand(new SuggestCommand({ handler: x => x.acceptSelectedSuggestion(), kbOpts: { weight: 50, - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.textInputFocus, primary: KeyCode.RightArrow } })); diff --git a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts index 9612c0f70a..9b8fc0a5ce 100644 --- a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts @@ -107,11 +107,16 @@ export class ReplExpressionsRenderer implements IRenderer { return 2 * ReplExpressionsRenderer.LINE_HEIGHT_PX; } - return this.getHeightForString(element.value) + (element instanceof Expression ? this.getHeightForString(element.name) : 0); + let availableWidth = this.width; + if (element instanceof SimpleReplElement && element.sourceData) { + availableWidth -= `${element.sourceData.source.name}:${element.sourceData.lineNumber}`.length * this.characterWidth; + } + + return this.getHeightForString(element.value, availableWidth) + (element instanceof Expression ? this.getHeightForString(element.name, availableWidth) : 0); } - private getHeightForString(s: string): number { - if (!s || !s.length || !this.width || this.width <= 0 || !this.characterWidth || this.characterWidth <= 0) { + private getHeightForString(s: string, availableWidth: number): number { + if (!s || !s.length || !availableWidth || availableWidth <= 0 || !this.characterWidth || this.characterWidth <= 0) { return ReplExpressionsRenderer.LINE_HEIGHT_PX; } @@ -126,7 +131,7 @@ export class ReplExpressionsRenderer implements IRenderer { lineLength += isFullWidthCharacter(line.charCodeAt(i)) ? 2 : 1; } - return lineCount + Math.floor(lineLength * this.characterWidth / this.width); + return lineCount + Math.floor(lineLength * this.characterWidth / availableWidth); }, lines.length); return ReplExpressionsRenderer.LINE_HEIGHT_PX * numLines; @@ -337,6 +342,8 @@ export class ReplExpressionsRenderer implements IRenderer { token.className += 'code' + parsedMode; } else if (parsedMode === 1) { token.className += 'code-bold'; + } else if (parsedMode === 4) { + token.className += 'code-underline'; } } @@ -352,7 +359,13 @@ export class ReplExpressionsRenderer implements IRenderer { } currentToken = token; - tokensContainer.appendChild(token); + + // get child until deepest nested node is found + let childPointer: Node = tokensContainer; + while (childPointer.hasChildNodes() && childPointer.firstChild.nodeName !== '#text') { + childPointer = childPointer.firstChild; + } + childPointer.appendChild(token); i = index; } diff --git a/src/vs/workbench/parts/debug/electron-browser/replEditor.ts b/src/vs/workbench/parts/debug/electron-browser/simpleDebugEditor.ts similarity index 70% rename from src/vs/workbench/parts/debug/electron-browser/replEditor.ts rename to src/vs/workbench/parts/debug/electron-browser/simpleDebugEditor.ts index 3c01c7dc20..917cee33ad 100644 --- a/src/vs/workbench/parts/debug/electron-browser/replEditor.ts +++ b/src/vs/workbench/parts/debug/electron-browser/simpleDebugEditor.ts @@ -19,8 +19,9 @@ import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; import { TabCompletionController } from 'vs/workbench/parts/snippets/electron-browser/tabCompletion'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { INotificationService } from 'vs/platform/notification/common/notification'; -export class ReplInputEditor extends CodeEditorWidget { +export class SimpleDebugEditor extends CodeEditorWidget { constructor( domElement: HTMLElement, options: IEditorOptions, @@ -28,9 +29,10 @@ export class ReplInputEditor extends CodeEditorWidget { @ICodeEditorService codeEditorService: ICodeEditorService, @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService, ) { - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService); + super(domElement, options, true, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService); } protected _getContributions(): IEditorContributionCtor[] { @@ -47,4 +49,29 @@ export class ReplInputEditor extends CodeEditorWidget { protected _getActions(): EditorAction[] { return EditorExtensionsRegistry.getEditorActions(); } + + public static getEditorOptions(): IEditorOptions { + return { + wordWrap: 'on', + overviewRulerLanes: 0, + glyphMargin: false, + lineNumbers: 'off', + folding: false, + selectOnLineNumbers: false, + hideCursorInOverviewRuler: true, + selectionHighlight: false, + scrollbar: { + horizontal: 'hidden' + }, + lineDecorationsWidth: 0, + overviewRulerBorder: false, + scrollBeyondLastLine: false, + renderLineHighlight: 'none', + fixedOverflowWidgets: true, + acceptSuggestionOnEnter: 'smart', + minimap: { + enabled: false + } + }; + } } diff --git a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts index 53134ab86b..8d8ca40d8a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts +++ b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts @@ -5,50 +5,60 @@ import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; -import cp = require('child_process'); +import * as cp from 'child_process'; import { IDisposable } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import { ITerminalService, ITerminalInstance, ITerminalConfiguration } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalService, ITerminalInstance } from 'vs/workbench/parts/terminal/common/terminal'; import { ITerminalService as IExternalTerminalService } from 'vs/workbench/parts/execution/common/execution'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ITerminalLauncher, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug'; const enum ShellType { cmd, powershell, bash } -export class TerminalSupport { +export class TerminalLauncher implements ITerminalLauncher { - private static integratedTerminalInstance: ITerminalInstance; - private static terminalDisposedListener: IDisposable; + private integratedTerminalInstance: ITerminalInstance; + private terminalDisposedListener: IDisposable; - public static runInTerminal(terminalService: ITerminalService, nativeTerminalService: IExternalTerminalService, configurationService: IConfigurationService, args: DebugProtocol.RunInTerminalRequestArguments, response: DebugProtocol.RunInTerminalResponse): TPromise { + constructor( + @ITerminalService private terminalService: ITerminalService, + @IExternalTerminalService private nativeTerminalService: IExternalTerminalService + ) { + } + + runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise { if (args.kind === 'external') { - return nativeTerminalService.runInTerminal(args.title, args.cwd, args.args, args.env || {}); + return this.nativeTerminalService.runInTerminal(args.title, args.cwd, args.args, args.env || {}); } - if (!TerminalSupport.terminalDisposedListener) { + if (!this.terminalDisposedListener) { // React on terminal disposed and check if that is the debug terminal #12956 - TerminalSupport.terminalDisposedListener = terminalService.onInstanceDisposed(terminal => { - if (TerminalSupport.integratedTerminalInstance && TerminalSupport.integratedTerminalInstance.id === terminal.id) { - TerminalSupport.integratedTerminalInstance = null; + this.terminalDisposedListener = this.terminalService.onInstanceDisposed(terminal => { + if (this.integratedTerminalInstance && this.integratedTerminalInstance.id === terminal.id) { + this.integratedTerminalInstance = null; } }); } - let t = TerminalSupport.integratedTerminalInstance; + let t = this.integratedTerminalInstance; if ((t && this.isBusy(t)) || !t) { - t = terminalService.createInstance({ name: args.title || nls.localize('debug.terminal.title', "debuggee") }); - TerminalSupport.integratedTerminalInstance = t; + t = this.terminalService.createTerminal({ name: args.title || nls.localize('debug.terminal.title', "debuggee") }); + this.integratedTerminalInstance = t; } - terminalService.setActiveInstance(t); - terminalService.showPanel(true); + this.terminalService.setActiveInstance(t); + this.terminalService.showPanel(true); - const command = this.prepareCommand(args, configurationService); - t.sendText(command, true); + const command = this.prepareCommand(args, config); - return TPromise.as(void 0); + return new TPromise((resolve, error) => { + setTimeout(_ => { + t.sendText(command, true); + resolve(void 0); + }, 500); + }); } - private static isBusy(t: ITerminalInstance): boolean { + private isBusy(t: ITerminalInstance): boolean { if (t.processId) { try { // if shell has at least one child process, assume that shell is busy @@ -78,13 +88,13 @@ export class TerminalSupport { return true; } - private static prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments, configurationService: IConfigurationService): string { + private prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): string { let shellType: ShellType; // get the shell configuration for the current platform let shell: string; - const shell_config = (configurationService.getValue().terminal.integrated).shell; + const shell_config = config.integrated.shell; if (platform.isWindows) { shell = shell_config.windows; shellType = ShellType.cmd; @@ -202,4 +212,4 @@ export class TerminalSupport { return command; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/debug/electron-browser/variablesView.ts b/src/vs/workbench/parts/debug/electron-browser/variablesView.ts index 8d218bdfe6..846b7774ab 100644 --- a/src/vs/workbench/parts/debug/electron-browser/variablesView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/variablesView.ts @@ -27,7 +27,7 @@ import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { WorkbenchTree } from 'vs/platform/list/browser/listService'; -import { OpenMode } from 'vs/base/parts/tree/browser/treeDefaults'; +import { OpenMode, ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; const $ = dom.$; @@ -88,7 +88,7 @@ export class VariablesView extends TreeViewsViewletPanel { dataSource: new VariablesDataSource(), renderer: this.instantiationService.createInstance(VariablesRenderer), accessibilityProvider: new VariablesAccessibilityProvider(), - controller: this.instantiationService.createInstance(VariablesController, new VariablesActionProvider(this.debugService, this.keybindingService), MenuId.DebugVariablesContext, { openMode: OpenMode.SINGLE_CLICK }) + controller: this.instantiationService.createInstance(VariablesController, new VariablesActionProvider(this.debugService, this.keybindingService), MenuId.DebugVariablesContext, { openMode: OpenMode.SINGLE_CLICK, clickBehavior: ClickBehavior.ON_MOUSE_UP }) }, { ariaLabel: nls.localize('variablesAriaTreeLabel', "Debug Variables"), twistiePixels diff --git a/src/vs/workbench/parts/debug/node/debugAdapter.ts b/src/vs/workbench/parts/debug/node/debugAdapter.ts index 3d08732bdc..7053a07076 100644 --- a/src/vs/workbench/parts/debug/node/debugAdapter.ts +++ b/src/vs/workbench/parts/debug/node/debugAdapter.ts @@ -3,259 +3,514 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import fs = require('fs'); -import path = require('path'); +import * as fs from 'fs'; +import * as cp from 'child_process'; +import * as stream from 'stream'; import * as nls from 'vs/nls'; -import { TPromise } from 'vs/base/common/winjs.base'; +import * as paths from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import * as objects from 'vs/base/common/objects'; -import * as paths from 'vs/base/common/paths'; import * as platform from 'vs/base/common/platform'; -import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema'; -import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { IConfig, IRawAdapter, IAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager } from 'vs/workbench/parts/debug/common/debug'; +import * as stdfork from 'vs/base/node/stdFork'; +import { Emitter, Event } from 'vs/base/common/event'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IOutputService } from 'vs/workbench/parts/output/common/output'; +import { IDebugAdapter, IAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IConfig } from 'vs/workbench/parts/debug/common/debug'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IStringDictionary } from 'vs/base/common/collections'; -export class Adapter { +/** + * Abstract implementation of the low level API for a debug adapter. + * Missing is how this API communicates with the debug adapter. + */ +export abstract class AbstractDebugAdapter implements IDebugAdapter { - constructor(private configurationManager: IConfigurationManager, private rawAdapter: IRawAdapter, public extensionDescription: IExtensionDescription, - @IConfigurationService private configurationService: IConfigurationService, - @ICommandService private commandService: ICommandService - ) { - if (rawAdapter.windows) { - rawAdapter.win = rawAdapter.windows; + private sequence: number; + private pendingRequests: Map void>; + private requestCallback: (request: DebugProtocol.Request) => void; + private eventCallback: (request: DebugProtocol.Event) => void; + + protected readonly _onError: Emitter; + protected readonly _onExit: Emitter; + + constructor() { + this.sequence = 1; + this.pendingRequests = new Map void>(); + + this._onError = new Emitter(); + this._onExit = new Emitter(); + } + + abstract startSession(): TPromise; + abstract stopSession(): TPromise; + + public dispose(): void { + } + + abstract sendMessage(message: DebugProtocol.ProtocolMessage): void; + + public get onError(): Event { + return this._onError.event; + } + + public get onExit(): Event { + return this._onExit.event; + } + + public onEvent(callback: (event: DebugProtocol.Event) => void): void { + if (this.eventCallback) { + this._onError.fire(new Error(`attempt to set more than one 'Event' callback`)); + } + this.eventCallback = callback; + } + + public onRequest(callback: (request: DebugProtocol.Request) => void): void { + if (this.requestCallback) { + this._onError.fire(new Error(`attempt to set more than one 'Request' callback`)); + } + this.requestCallback = callback; + } + + public sendResponse(response: DebugProtocol.Response): void { + if (response.seq > 0) { + this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`)); + } else { + this.internalSend('response', response); } } - public hasConfigurationProvider = false; + public sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void): void { - public getAdapterExecutable(root: IWorkspaceFolder, verifyAgainstFS = true): TPromise { + const request: any = { + command: command + }; + if (args && Object.keys(args).length > 0) { + request.arguments = args; + } - return this.configurationManager.debugAdapterExecutable(root ? root.uri : undefined, this.rawAdapter.type).then(adapterExecutable => { + this.internalSend('request', request); - if (adapterExecutable) { - return this.verifyAdapterDetails(adapterExecutable, verifyAgainstFS); - } - - // try deprecated command based extension API - if (this.rawAdapter.adapterExecutableCommand && root) { - return this.commandService.executeCommand(this.rawAdapter.adapterExecutableCommand, root.uri.toString()).then(ad => { - return this.verifyAdapterDetails(ad, verifyAgainstFS); - }); - } - - // fallback: executable contribution specified in package.json - adapterExecutable = { - command: this.getProgram(), - args: this.getAttributeBasedOnPlatform('args') - }; - const runtime = this.getRuntime(); - if (runtime) { - const runtimeArgs = this.getAttributeBasedOnPlatform('runtimeArgs'); - adapterExecutable.args = (runtimeArgs || []).concat([adapterExecutable.command]).concat(adapterExecutable.args || []); - adapterExecutable.command = runtime; - } - return this.verifyAdapterDetails(adapterExecutable, verifyAgainstFS); - }); + if (clb) { + // store callback for this request + this.pendingRequests.set(request.seq, clb); + } } - private verifyAdapterDetails(details: IAdapterExecutable, verifyAgainstFS: boolean): TPromise { + public acceptMessage(message: DebugProtocol.ProtocolMessage): void { + switch (message.type) { + case 'event': + if (this.eventCallback) { + this.eventCallback(message); + } + break; + case 'request': + if (this.requestCallback) { + this.requestCallback(message); + } + break; + case 'response': + const response = message; + const clb = this.pendingRequests.get(response.request_seq); + if (clb) { + this.pendingRequests.delete(response.request_seq); + clb(response); + } + break; + } + } - if (details.command) { - if (verifyAgainstFS) { - if (path.isAbsolute(details.command)) { - return new TPromise((c, e) => { - fs.exists(details.command, exists => { - if (exists) { - c(details); - } else { - e(new Error(nls.localize('debugAdapterBinNotFound', "Debug adapter executable '{0}' does not exist.", details.command))); - } - }); - }); + private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void { + + message.type = typ; + message.seq = this.sequence++; + + this.sendMessage(message); + } +} + +/** + * An implementation that communicates via two streams with the debug adapter. + */ +export abstract class StreamDebugAdapter extends AbstractDebugAdapter { + + private static readonly TWO_CRLF = '\r\n\r\n'; + private static readonly HEADER_LINESEPARATOR = /\r?\n/; // allow for non-RFC 2822 conforming line separators + private static readonly HEADER_FIELDSEPARATOR = /: */; + + private outputStream: stream.Writable; + private rawData: Buffer; + private contentLength: number; + + constructor() { + super(); + } + + public connect(readable: stream.Readable, writable: stream.Writable): void { + + this.outputStream = writable; + this.rawData = Buffer.allocUnsafe(0); + this.contentLength = -1; + + readable.on('data', (data: Buffer) => this.handleData(data)); + + // readable.on('close', () => { + // this._emitEvent(new Event('close')); + // }); + // readable.on('error', (error) => { + // this._emitEvent(new Event('error', 'readable error: ' + (error && error.message))); + // }); + + // writable.on('error', (error) => { + // this._emitEvent(new Event('error', 'writable error: ' + (error && error.message))); + // }); + } + + public sendMessage(message: DebugProtocol.ProtocolMessage): void { + + if (this.outputStream) { + const json = JSON.stringify(message); + this.outputStream.write(`Content-Length: ${Buffer.byteLength(json, 'utf8')}${StreamDebugAdapter.TWO_CRLF}${json}`, 'utf8'); + } + } + + private handleData(data: Buffer): void { + + this.rawData = Buffer.concat([this.rawData, data]); + + while (true) { + if (this.contentLength >= 0) { + if (this.rawData.length >= this.contentLength) { + const message = this.rawData.toString('utf8', 0, this.contentLength); + this.rawData = this.rawData.slice(this.contentLength); + this.contentLength = -1; + if (message.length > 0) { + try { + this.acceptMessage(JSON.parse(message)); + } catch (e) { + this._onError.fire(new Error((e.message || e) + '\n' + message)); + } + } + continue; // there may be more complete messages to process + } + } else { + const idx = this.rawData.indexOf(StreamDebugAdapter.TWO_CRLF); + if (idx !== -1) { + const header = this.rawData.toString('utf8', 0, idx); + const lines = header.split(StreamDebugAdapter.HEADER_LINESEPARATOR); + for (const h of lines) { + const kvPair = h.split(StreamDebugAdapter.HEADER_FIELDSEPARATOR); + if (kvPair[0] === 'Content-Length') { + this.contentLength = Number(kvPair[1]); + } + } + this.rawData = this.rawData.slice(idx + StreamDebugAdapter.TWO_CRLF.length); + continue; + } + } + break; + } + } +} + +/** + * An implementation that launches the debug adapter as a separate process and communicates via stdin/stdout. +*/ +export class DebugAdapter extends StreamDebugAdapter { + + private _serverProcess: cp.ChildProcess; + + constructor(private _debugType: string, private _adapterExecutable: IAdapterExecutable | null, extensionDescriptions: IExtensionDescription[], private _outputService?: IOutputService) { + super(); + + if (!this._adapterExecutable) { + this._adapterExecutable = DebugAdapter.platformAdapterExecutable(extensionDescriptions, this._debugType); + } + } + + startSession(): TPromise { + + return new TPromise((c, e) => { + + // verify executables + if (this._adapterExecutable.command) { + if (paths.isAbsolute(this._adapterExecutable.command)) { + if (!fs.existsSync(this._adapterExecutable.command)) { + e(new Error(nls.localize('debugAdapterBinNotFound', "Debug adapter executable '{0}' does not exist.", this._adapterExecutable.command))); + } } else { // relative path - if (details.command.indexOf('/') < 0 && details.command.indexOf('\\') < 0) { + if (this._adapterExecutable.command.indexOf('/') < 0 && this._adapterExecutable.command.indexOf('\\') < 0) { // no separators: command looks like a runtime name like 'node' or 'mono' - return TPromise.as(details); // TODO: check that the runtime is available on PATH + // TODO: check that the runtime is available on PATH } } } else { - return TPromise.as(details); + e(new Error(nls.localize({ key: 'debugAdapterCannotDetermineExecutable', comment: ['Adapter executable file not found'] }, + "Cannot determine executable for debug adapter '{0}'.", this._debugType))); } - } - return TPromise.wrapError(new Error(nls.localize({ key: 'debugAdapterCannotDetermineExecutable', comment: ['Adapter executable file not found'] }, - "Cannot determine executable for debug adapter '{0}'.", this.type))); - } - - private getRuntime(): string { - let runtime = this.getAttributeBasedOnPlatform('runtime'); - if (runtime && runtime.indexOf('./') === 0) { - runtime = paths.join(this.extensionDescription.extensionFolderPath, runtime); - } - return runtime; - } - - private getProgram(): string { - let program = this.getAttributeBasedOnPlatform('program'); - if (program) { - program = paths.join(this.extensionDescription.extensionFolderPath, program); - } - return program; - } - - public get aiKey(): string { - return this.rawAdapter.aiKey; - } - - public get label(): string { - return this.rawAdapter.label || this.rawAdapter.type; - } - - public get type(): string { - return this.rawAdapter.type; - } - - public get variables(): { [key: string]: string } { - return this.rawAdapter.variables; - } - - public get configurationSnippets(): IJSONSchemaSnippet[] { - return this.rawAdapter.configurationSnippets; - } - - public get languages(): string[] { - return this.rawAdapter.languages; - } - - public merge(secondRawAdapter: IRawAdapter, extensionDescription: IExtensionDescription): void { - // Give priority to built in debug adapters - if (extensionDescription.isBuiltin) { - this.extensionDescription = extensionDescription; - } - objects.mixin(this.rawAdapter, secondRawAdapter, extensionDescription.isBuiltin); - } - - public hasInitialConfiguration(): boolean { - return !!this.rawAdapter.initialConfigurations; - } - - public getInitialConfigurationContent(initialConfigs?: IConfig[]): TPromise { - // at this point we got some configs from the package.json and/or from registered DebugConfigurationProviders - let initialConfigurations = this.rawAdapter.initialConfigurations || []; - if (initialConfigs) { - initialConfigurations = initialConfigurations.concat(initialConfigs); - } - - const configs = JSON.stringify(initialConfigurations, null, '\t').split('\n').map(line => '\t' + line).join('\n').trim(); - const comment1 = nls.localize('launch.config.comment1', "Use IntelliSense to learn about possible attributes."); - const comment2 = nls.localize('launch.config.comment2', "Hover to view descriptions of existing attributes."); - const comment3 = nls.localize('launch.config.comment3', "For more information, visit: {0}", 'https://go.microsoft.com/fwlink/?linkid=830387'); - - let content = [ - '{', - `\t// ${comment1}`, - `\t// ${comment2}`, - `\t// ${comment3}`, - `\t"version": "0.2.0",`, - `\t"configurations": ${configs}`, - '}' - ].join('\n'); - - // fix formatting - const editorConfig = this.configurationService.getValue(); - if (editorConfig.editor && editorConfig.editor.insertSpaces) { - content = content.replace(new RegExp('\t', 'g'), strings.repeat(' ', editorConfig.editor.tabSize)); - } - - return TPromise.as(content); - } - - public getSchemaAttributes(): IJSONSchema[] { - if (!this.rawAdapter.configurationAttributes) { - return null; - } - // fill in the default configuration attributes shared by all adapters. - return Object.keys(this.rawAdapter.configurationAttributes).map(request => { - const attributes: IJSONSchema = this.rawAdapter.configurationAttributes[request]; - const defaultRequired = ['name', 'type', 'request']; - attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired; - attributes.additionalProperties = false; - attributes.type = 'object'; - if (!attributes.properties) { - attributes.properties = {}; + if (this._adapterExecutable.command === 'node' && this._outputService) { + if (Array.isArray(this._adapterExecutable.args) && this._adapterExecutable.args.length > 0) { + stdfork.fork(this._adapterExecutable.args[0], this._adapterExecutable.args.slice(1), {}, (err, child) => { + if (err) { + e(new Error(nls.localize('unableToLaunchDebugAdapter', "Unable to launch debug adapter from '{0}'.", this._adapterExecutable.args[0]))); + } + this._serverProcess = child; + c(null); + }); + } else { + e(new Error(nls.localize('unableToLaunchDebugAdapterNoArgs', "Unable to launch debug adapter."))); + } + } else { + this._serverProcess = cp.spawn(this._adapterExecutable.command, this._adapterExecutable.args); + c(null); } - const properties = attributes.properties; - properties['type'] = { - enum: [this.type], - description: nls.localize('debugType', "Type of configuration."), - pattern: '^(?!node2)', - errorMessage: nls.localize('debugTypeNotRecognised', "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled."), - patternErrorMessage: nls.localize('node2NotSupported', "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".") - }; - properties['name'] = { - type: 'string', - description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."), - default: 'Launch' - }; - properties['request'] = { - enum: [request], - description: nls.localize('debugRequest', "Request type of configuration. Can be \"launch\" or \"attach\"."), - }; - properties['debugServer'] = { - type: 'number', - description: nls.localize('debugServer', "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode"), - default: 4711 - }; - properties['preLaunchTask'] = { - type: ['string', 'null'], - default: null, - description: nls.localize('debugPrelaunchTask', "Task to run before debug session starts.") - }; - properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA; + }).then(_ => { + this._serverProcess.on('error', (err: Error) => this._onError.fire(err)); + this._serverProcess.on('exit', (code: number, signal: string) => this._onExit.fire(code)); - const osProperties = objects.deepClone(properties); - properties['windows'] = { - type: 'object', - description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."), - properties: osProperties - }; - properties['osx'] = { - type: 'object', - description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."), - properties: osProperties - }; - properties['linux'] = { - type: 'object', - description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."), - properties: osProperties - }; - Object.keys(attributes.properties).forEach(name => { - // Use schema allOf property to get independent error reporting #21113 - attributes.properties[name].pattern = attributes.properties[name].pattern || '^(?!.*\\$\\{(env|config|command)\\.)'; - attributes.properties[name].patternErrorMessage = attributes.properties[name].patternErrorMessage || - nls.localize('deprecatedVariables', "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead."); - }); + if (this._outputService) { + const sanitize = (s: string) => s.toString().replace(/\r?\n$/mg, ''); + // this.serverProcess.stdout.on('data', (data: string) => { + // console.log('%c' + sanitize(data), 'background: #ddd; font-style: italic;'); + // }); + this._serverProcess.stderr.on('data', (data: string) => { + this._outputService.getChannel(ExtensionsChannelId).append(sanitize(data)); + }); + } - return attributes; + this.connect(this._serverProcess.stdout, this._serverProcess.stdin); + }, err => { + this._onError.fire(err); }); } - private getAttributeBasedOnPlatform(key: string): any { - let result: any; - if (platform.isWindows && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') && this.rawAdapter.winx86) { - result = this.rawAdapter.winx86[key]; - } else if (platform.isWindows && this.rawAdapter.win) { - result = this.rawAdapter.win[key]; - } else if (platform.isMacintosh && this.rawAdapter.osx) { - result = this.rawAdapter.osx[key]; - } else if (platform.isLinux && this.rawAdapter.linux) { - result = this.rawAdapter.linux[key]; + stopSession(): TPromise { + + // when killing a process in windows its child + // processes are *not* killed but become root + // processes. Therefore we use TASKKILL.EXE + if (platform.isWindows) { + return new TPromise((c, e) => { + const killer = cp.exec(`taskkill /F /T /PID ${this._serverProcess.pid}`, function (err, stdout, stderr) { + if (err) { + return e(err); + } + }); + killer.on('exit', c); + killer.on('error', e); + }); + } else { + this._serverProcess.kill('SIGTERM'); + return TPromise.as(null); + } + } + + private static extract(contribution: IDebuggerContribution, extensionFolderPath: string): IDebuggerContribution { + if (!contribution) { + return undefined; + } + let result: IDebuggerContribution = {}; + + if (contribution.runtime) { + if (contribution.runtime.indexOf('./') === 0) { // TODO + result.runtime = paths.join(extensionFolderPath, contribution.runtime); + } else { + result.runtime = contribution.runtime; + } + } + if (contribution.runtimeArgs) { + result.runtimeArgs = contribution.runtimeArgs; + } + if (contribution.program) { + if (!paths.isAbsolute(contribution.program)) { + result.program = paths.join(extensionFolderPath, contribution.program); + } else { + result.program = contribution.program; + } + } + if (contribution.args) { + result.args = contribution.args; } - return result || this.rawAdapter[key]; + if (contribution.win) { + result.win = DebugAdapter.extract(contribution.win, extensionFolderPath); + } + if (contribution.winx86) { + result.winx86 = DebugAdapter.extract(contribution.winx86, extensionFolderPath); + } + if (contribution.windows) { + result.windows = DebugAdapter.extract(contribution.windows, extensionFolderPath); + } + if (contribution.osx) { + result.osx = DebugAdapter.extract(contribution.osx, extensionFolderPath); + } + if (contribution.linux) { + result.linux = DebugAdapter.extract(contribution.linux, extensionFolderPath); + } + return result; + } + + static platformAdapterExecutable(extensionDescriptions: IExtensionDescription[], debugType: string): IAdapterExecutable { + + let result: IDebuggerContribution = {}; + + debugType = debugType.toLowerCase(); + + // merge all contributions into one + for (const ed of extensionDescriptions) { + if (ed.contributes) { + const debuggers = ed.contributes['debuggers']; + if (debuggers && debuggers.length > 0) { + const dbgs = debuggers.filter(d => strings.equalsIgnoreCase(d.type, debugType)); + for (const dbg of dbgs) { + + // extract relevant attributes and make then absolute where needed + const dbg1 = DebugAdapter.extract(dbg, ed.extensionFolderPath); + + // merge + objects.mixin(result, dbg1, ed.isBuiltin); + } + } + } + } + + // select the right platform + let platformInfo: IPlatformSpecificAdapterContribution; + if (platform.isWindows && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')) { + platformInfo = result.winx86 || result.win || result.windows; + } else if (platform.isWindows) { + platformInfo = result.win || result.windows; + } else if (platform.isMacintosh) { + platformInfo = result.osx; + } else if (platform.isLinux) { + platformInfo = result.linux; + } + platformInfo = platformInfo || result; + + // these are the relevant attributes + let program = platformInfo.program || result.program; + const args = platformInfo.args || result.args; + let runtime = platformInfo.runtime || result.runtime; + const runtimeArgs = platformInfo.runtimeArgs || result.runtimeArgs; + + if (runtime) { + return { + command: runtime, + args: (runtimeArgs || []).concat([program]).concat(args || []) + }; + } else { + return { + command: program, + args: args || [] + }; + } + } + + static substituteVariables(workspaceFolder: IWorkspaceFolder, config: IConfig, resolverService: IConfigurationResolverService, commandValueMapping?: IStringDictionary): IConfig { + + const result = objects.deepClone(config) as IConfig; + + // hoist platform specific attributes to top level + if (platform.isWindows && result.windows) { + Object.keys(result.windows).forEach(key => result[key] = result.windows[key]); + } else if (platform.isMacintosh && result.osx) { + Object.keys(result.osx).forEach(key => result[key] = result.osx[key]); + } else if (platform.isLinux && result.linux) { + Object.keys(result.linux).forEach(key => result[key] = result.linux[key]); + } + + // delete all platform specific sections + delete result.windows; + delete result.osx; + delete result.linux; + + // substitute all variables in string values + return resolverService.resolveAny(workspaceFolder, result, commandValueMapping); + } +} + +// path hooks helpers + +export function convertToDAPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePaths: (source: DebugProtocol.Source) => void): void { + convertPaths(msg, (toDA: boolean, source: DebugProtocol.Source | undefined) => { + if (toDA && source) { + fixSourcePaths(source); + } + }); +} + +export function convertToVSCPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePaths: (source: DebugProtocol.Source) => void): void { + convertPaths(msg, (toDA: boolean, source: DebugProtocol.Source | undefined) => { + if (!toDA && source) { + fixSourcePaths(source); + } + }); +} + +function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePaths: (toDA: boolean, source: DebugProtocol.Source | undefined) => void): void { + switch (msg.type) { + case 'event': + const event = msg; + switch (event.event) { + case 'output': + fixSourcePaths(false, (event).body.source); + break; + case 'loadedSource': + fixSourcePaths(false, (event).body.source); + break; + case 'breakpoint': + fixSourcePaths(false, (event).body.breakpoint.source); + break; + default: + break; + } + break; + case 'request': + const request = msg; + switch (request.command) { + case 'setBreakpoints': + fixSourcePaths(true, (request.arguments).source); + break; + case 'source': + fixSourcePaths(true, (request.arguments).source); + break; + case 'gotoTargets': + fixSourcePaths(true, (request.arguments).source); + break; + default: + break; + } + break; + case 'response': + const response = msg; + switch (response.command) { + case 'stackTrace': + const r1 = response; + r1.body.stackFrames.forEach(frame => fixSourcePaths(false, frame.source)); + break; + case 'loadedSources': + const r2 = response; + r2.body.sources.forEach(source => fixSourcePaths(false, source)); + break; + case 'scopes': + const r3 = response; + r3.body.scopes.forEach(scope => fixSourcePaths(false, scope.source)); + break; + case 'setFunctionBreakpoints': + const r4 = response; + r4.body.breakpoints.forEach(bp => fixSourcePaths(false, bp.source)); + break; + case 'setBreakpoints': + const r5 = response; + r5.body.breakpoints.forEach(bp => fixSourcePaths(false, bp.source)); + break; + default: + break; + } + break; } } diff --git a/src/vs/workbench/parts/debug/node/debugger.ts b/src/vs/workbench/parts/debug/node/debugger.ts new file mode 100644 index 0000000000..1f0581bc2d --- /dev/null +++ b/src/vs/workbench/parts/debug/node/debugger.ts @@ -0,0 +1,239 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { TPromise } from 'vs/base/common/winjs.base'; +import * as strings from 'vs/base/common/strings'; +import * as objects from 'vs/base/common/objects'; +import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IConfig, IDebuggerContribution, IAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, IDebugConfiguration, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug'; +import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IOutputService } from 'vs/workbench/parts/output/common/output'; +import { DebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; + +export class Debugger { + + private _mergedExtensionDescriptions: IExtensionDescription[]; + + constructor(private configurationManager: IConfigurationManager, private debuggerContribution: IDebuggerContribution, public extensionDescription: IExtensionDescription, + @IConfigurationService private configurationService: IConfigurationService, + @ICommandService private commandService: ICommandService, + @IConfigurationResolverService private configurationResolverService: IConfigurationResolverService, + ) { + this._mergedExtensionDescriptions = [extensionDescription]; + } + + public hasConfigurationProvider = false; + + public createDebugAdapter(root: IWorkspaceFolder, outputService: IOutputService): TPromise { + return this.getAdapterExecutable(root).then(adapterExecutable => { + const debugConfigs = this.configurationService.getValue('debug'); + if (debugConfigs.extensionHostDebugAdapter) { + return this.configurationManager.createDebugAdapter(this.type, adapterExecutable); + } else { + return new DebugAdapter(this.type, adapterExecutable, this._mergedExtensionDescriptions, outputService); + } + }); + } + + public getAdapterExecutable(root: IWorkspaceFolder): TPromise { + + // first try to get an executable from DebugConfigurationProvider + return this.configurationManager.debugAdapterExecutable(root ? root.uri : undefined, this.type).then(adapterExecutable => { + + if (adapterExecutable) { + return adapterExecutable; + } + + // try deprecated command based extension API to receive an executable + if (this.debuggerContribution.adapterExecutableCommand) { + return this.commandService.executeCommand(this.debuggerContribution.adapterExecutableCommand, root ? root.uri.toString() : undefined); + } + + // give up and let DebugAdapter determine executable based on package.json contribution + return TPromise.as(null); + }); + } + + public substituteVariables(folder: IWorkspaceFolder, config: IConfig): TPromise { + + // first resolve command variables (which might have a UI) + return this.configurationResolverService.executeCommandVariables(config, this.variables).then(commandValueMapping => { + + if (!commandValueMapping) { // cancelled by user + return null; + } + + // optionally substitute in EH + const inEh = this.configurationService.getValue('debug').extensionHostDebugAdapter; + + // now substitute all other variables + return (inEh ? this.configurationManager.substituteVariables(this.type, folder, config) : TPromise.as(config)).then(config => { + try { + return TPromise.as(DebugAdapter.substituteVariables(folder, config, this.configurationResolverService, commandValueMapping)); + } catch (e) { + return TPromise.wrapError(e); + } + }); + }); + } + + public runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): TPromise { + const debugConfigs = this.configurationService.getValue('debug'); + const config = this.configurationService.getValue('terminal'); + const type = debugConfigs.extensionHostDebugAdapter ? this.type : '*'; + return this.configurationManager.runInTerminal(type, args, config); + } + + public get aiKey(): string { + return this.debuggerContribution.aiKey; + } + + public get label(): string { + return this.debuggerContribution.label || this.debuggerContribution.type; + } + + public get type(): string { + return this.debuggerContribution.type; + } + + public get variables(): { [key: string]: string } { + return this.debuggerContribution.variables; + } + + public get configurationSnippets(): IJSONSchemaSnippet[] { + return this.debuggerContribution.configurationSnippets; + } + + public get languages(): string[] { + return this.debuggerContribution.languages; + } + + public merge(secondRawAdapter: IDebuggerContribution, extensionDescription: IExtensionDescription): void { + + // remember all ext descriptions that are the source of this debugger + this._mergedExtensionDescriptions.push(extensionDescription); + + // Give priority to built in debug adapters + if (extensionDescription.isBuiltin) { + this.extensionDescription = extensionDescription; + } + objects.mixin(this.debuggerContribution, secondRawAdapter, extensionDescription.isBuiltin); + } + + public hasInitialConfiguration(): boolean { + return !!this.debuggerContribution.initialConfigurations; + } + + public getInitialConfigurationContent(initialConfigs?: IConfig[]): TPromise { + // at this point we got some configs from the package.json and/or from registered DebugConfigurationProviders + let initialConfigurations = this.debuggerContribution.initialConfigurations || []; + if (initialConfigs) { + initialConfigurations = initialConfigurations.concat(initialConfigs); + } + + const configs = JSON.stringify(initialConfigurations, null, '\t').split('\n').map(line => '\t' + line).join('\n').trim(); + const comment1 = nls.localize('launch.config.comment1', "Use IntelliSense to learn about possible attributes."); + const comment2 = nls.localize('launch.config.comment2', "Hover to view descriptions of existing attributes."); + const comment3 = nls.localize('launch.config.comment3', "For more information, visit: {0}", 'https://go.microsoft.com/fwlink/?linkid=830387'); + + let content = [ + '{', + `\t// ${comment1}`, + `\t// ${comment2}`, + `\t// ${comment3}`, + `\t"version": "0.2.0",`, + `\t"configurations": ${configs}`, + '}' + ].join('\n'); + + // fix formatting + const editorConfig = this.configurationService.getValue(); + if (editorConfig.editor && editorConfig.editor.insertSpaces) { + content = content.replace(new RegExp('\t', 'g'), strings.repeat(' ', editorConfig.editor.tabSize)); + } + + return TPromise.as(content); + } + + public getSchemaAttributes(): IJSONSchema[] { + if (!this.debuggerContribution.configurationAttributes) { + return null; + } + // fill in the default configuration attributes shared by all adapters. + return Object.keys(this.debuggerContribution.configurationAttributes).map(request => { + const attributes: IJSONSchema = this.debuggerContribution.configurationAttributes[request]; + const defaultRequired = ['name', 'type', 'request']; + attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired; + attributes.additionalProperties = false; + attributes.type = 'object'; + if (!attributes.properties) { + attributes.properties = {}; + } + const properties = attributes.properties; + properties['type'] = { + enum: [this.type], + description: nls.localize('debugType', "Type of configuration."), + pattern: '^(?!node2)', + errorMessage: nls.localize('debugTypeNotRecognised', "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled."), + patternErrorMessage: nls.localize('node2NotSupported', "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".") + }; + properties['name'] = { + type: 'string', + description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."), + default: 'Launch' + }; + properties['request'] = { + enum: [request], + description: nls.localize('debugRequest', "Request type of configuration. Can be \"launch\" or \"attach\"."), + }; + properties['debugServer'] = { + type: 'number', + description: nls.localize('debugServer', "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode"), + default: 4711 + }; + properties['preLaunchTask'] = { + type: ['string', 'null'], + default: '', + description: nls.localize('debugPrelaunchTask', "Task to run before debug session starts.") + }; + properties['postDebugTask'] = { + type: ['string', 'null'], + default: '', + description: nls.localize('debugPostDebugTask', "Task to run after debug session ends.") + }; + properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA; + + const osProperties = objects.deepClone(properties); + properties['windows'] = { + type: 'object', + description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."), + properties: osProperties + }; + properties['osx'] = { + type: 'object', + description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."), + properties: osProperties + }; + properties['linux'] = { + type: 'object', + description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."), + properties: osProperties + }; + Object.keys(attributes.properties).forEach(name => { + // Use schema allOf property to get independent error reporting #21113 + attributes.properties[name].pattern = attributes.properties[name].pattern || '^(?!.*\\$\\{(env|config|command)\\.)'; + attributes.properties[name].patternErrorMessage = attributes.properties[name].patternErrorMessage || + nls.localize('deprecatedVariables', "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead."); + }); + + return attributes; + }); + } +} diff --git a/src/vs/workbench/parts/debug/node/terminals.ts b/src/vs/workbench/parts/debug/node/terminals.ts new file mode 100644 index 0000000000..bb97292b43 --- /dev/null +++ b/src/vs/workbench/parts/debug/node/terminals.ts @@ -0,0 +1,260 @@ +/*--------------------------------------------------------------------------------------------- + * 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 cp from 'child_process'; +import * as nls from 'vs/nls'; +import * as env from 'vs/base/common/platform'; +import * as pfs from 'vs/base/node/pfs'; +import { assign } from 'vs/base/common/objects'; +import { TPromise } from 'vs/base/common/winjs.base'; +import uri from 'vs/base/common/uri'; +import { ITerminalLauncher, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug'; + +const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console"); + +let terminalLauncher: ITerminalLauncher = undefined; + +export function getTerminalLauncher() { + if (!terminalLauncher) { + if (env.isWindows) { + terminalLauncher = new WinTerminalService(); + } else if (env.isMacintosh) { + terminalLauncher = new MacTerminalService(); + } else if (env.isLinux) { + terminalLauncher = new LinuxTerminalService(); + } + } + return terminalLauncher; +} + +let _DEFAULT_TERMINAL_LINUX_READY: TPromise = null; +export function getDefaultTerminalLinuxReady(): TPromise { + if (!_DEFAULT_TERMINAL_LINUX_READY) { + _DEFAULT_TERMINAL_LINUX_READY = new TPromise(c => { + if (env.isLinux) { + TPromise.join([pfs.exists('/etc/debian_version'), process.lazyEnv]).then(([isDebian]) => { + if (isDebian) { + c('x-terminal-emulator'); + } else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') { + c('gnome-terminal'); + } else if (process.env.DESKTOP_SESSION === 'kde-plasma') { + c('konsole'); + } else if (process.env.COLORTERM) { + c(process.env.COLORTERM); + } else if (process.env.TERM) { + c(process.env.TERM); + } else { + c('xterm'); + } + }); + return; + } + + c('xterm'); + }, () => { }); + } + return _DEFAULT_TERMINAL_LINUX_READY; +} + +let _DEFAULT_TERMINAL_WINDOWS: string = null; +export function getDefaultTerminalWindows(): string { + if (!_DEFAULT_TERMINAL_WINDOWS) { + const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + _DEFAULT_TERMINAL_WINDOWS = `${process.env.windir ? process.env.windir : 'C:\\Windows'}\\${isWoW64 ? 'Sysnative' : 'System32'}\\cmd.exe`; + } + return _DEFAULT_TERMINAL_WINDOWS; +} + +abstract class TerminalLauncher implements ITerminalLauncher { + public runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise { + return this.runInTerminal0(args.title, args.cwd, args.args, args.env || {}, config); + } + runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, config): TPromise { + return void 0; + } +} + +class WinTerminalService extends TerminalLauncher { + + private static readonly CMD = 'cmd.exe'; + + public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): TPromise { + + const exec = configuration.external.windowsExec || getDefaultTerminalWindows(); + + return new TPromise((c, e) => { + + const title = `"${dir} - ${TERMINAL_TITLE}"`; + const command = `""${args.join('" "')}" & pause"`; // use '|' to only pause on non-zero exit code + + const cmdArgs = [ + '/c', 'start', title, '/wait', exec, '/c', command + ]; + + // merge environment variables into a copy of the process.env + const env = assign({}, process.env, envVars); + + // delete environment variables that have a null value + Object.keys(env).filter(v => env[v] === null).forEach(key => delete env[key]); + + const options: any = { + cwd: dir, + env: env, + windowsVerbatimArguments: true + }; + + const cmd = cp.spawn(WinTerminalService.CMD, cmdArgs, options); + cmd.on('error', e); + + c(null); + }); + } +} + +class MacTerminalService extends TerminalLauncher { + + private static readonly DEFAULT_TERMINAL_OSX = 'Terminal.app'; + private static readonly OSASCRIPT = '/usr/bin/osascript'; // osascript is the AppleScript interpreter on OS X + + public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): TPromise { + + const terminalApp = configuration.external.osxExec || MacTerminalService.DEFAULT_TERMINAL_OSX; + + return new TPromise((c, e) => { + + if (terminalApp === MacTerminalService.DEFAULT_TERMINAL_OSX || terminalApp === 'iTerm.app') { + + // On OS X we launch an AppleScript that creates (or reuses) a Terminal window + // and then launches the program inside that window. + + const script = terminalApp === MacTerminalService.DEFAULT_TERMINAL_OSX ? 'TerminalHelper' : 'iTermHelper'; + const scriptpath = uri.parse(require.toUrl(`vs/workbench/parts/execution/electron-browser/${script}.scpt`)).fsPath; + + const osaArgs = [ + scriptpath, + '-t', title || TERMINAL_TITLE, + '-w', dir, + ]; + + for (let a of args) { + osaArgs.push('-a'); + osaArgs.push(a); + } + + if (envVars) { + for (let key in envVars) { + const value = envVars[key]; + if (value === null) { + osaArgs.push('-u'); + osaArgs.push(key); + } else { + osaArgs.push('-e'); + osaArgs.push(`${key}=${value}`); + } + } + } + + let stderr = ''; + const osa = cp.spawn(MacTerminalService.OSASCRIPT, osaArgs); + osa.on('error', e); + osa.stderr.on('data', (data) => { + stderr += data.toString(); + }); + osa.on('exit', (code: number) => { + if (code === 0) { // OK + c(null); + } else { + if (stderr) { + const lines = stderr.split('\n', 1); + e(new Error(lines[0])); + } else { + e(new Error(nls.localize('mac.terminal.script.failed', "Script '{0}' failed with exit code {1}", script, code))); + } + } + }); + } else { + e(new Error(nls.localize('mac.terminal.type.not.supported', "'{0}' not supported", terminalApp))); + } + }); + } +} + +class LinuxTerminalService extends TerminalLauncher { + + private static readonly WAIT_MESSAGE = nls.localize('press.any.key', "Press any key to continue..."); + + public runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): TPromise { + + const terminalConfig = configuration.external; + const execPromise = terminalConfig.linuxExec ? TPromise.as(terminalConfig.linuxExec) : getDefaultTerminalLinuxReady(); + + return new TPromise((c, e) => { + + let termArgs: string[] = []; + //termArgs.push('--title'); + //termArgs.push(`"${TERMINAL_TITLE}"`); + execPromise.then(exec => { + if (exec.indexOf('gnome-terminal') >= 0) { + termArgs.push('-x'); + } else { + termArgs.push('-e'); + } + termArgs.push('bash'); + termArgs.push('-c'); + + const bashCommand = `${quote(args)}; echo; read -p "${LinuxTerminalService.WAIT_MESSAGE}" -n1;`; + termArgs.push(`''${bashCommand}''`); // wrapping argument in two sets of ' because node is so "friendly" that it removes one set... + + // merge environment variables into a copy of the process.env + const env = assign({}, process.env, envVars); + + // delete environment variables that have a null value + Object.keys(env).filter(v => env[v] === null).forEach(key => delete env[key]); + + const options: any = { + cwd: dir, + env: env + }; + + let stderr = ''; + const cmd = cp.spawn(exec, termArgs, options); + cmd.on('error', e); + cmd.stderr.on('data', (data) => { + stderr += data.toString(); + }); + cmd.on('exit', (code: number) => { + if (code === 0) { // OK + c(null); + } else { + if (stderr) { + const lines = stderr.split('\n', 1); + e(new Error(lines[0])); + } else { + e(new Error(nls.localize('linux.term.failed', "'{0}' failed with exit code {1}", exec, code))); + } + } + }); + }); + }); + } +} + +/** + * Quote args if necessary and combine into a space separated string. + */ +function quote(args: string[]): string { + let r = ''; + for (let a of args) { + if (a.indexOf(' ') >= 0) { + r += '"' + a + '"'; + } else { + r += a; + } + r += ' '; + } + return r; +} diff --git a/src/vs/workbench/parts/debug/node/v8Protocol.ts b/src/vs/workbench/parts/debug/node/v8Protocol.ts deleted file mode 100644 index d068e7a14c..0000000000 --- a/src/vs/workbench/parts/debug/node/v8Protocol.ts +++ /dev/null @@ -1,155 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import stream = require('stream'); -import { TPromise } from 'vs/base/common/winjs.base'; -import { canceled } from 'vs/base/common/errors'; - -export abstract class V8Protocol { - - private static readonly TWO_CRLF = '\r\n\r\n'; - - private outputStream: stream.Writable; - private sequence: number; - private pendingRequests: Map void>; - private rawData: Buffer; - private contentLength: number; - - constructor(private id: string) { - this.sequence = 1; - this.contentLength = -1; - this.pendingRequests = new Map void>(); - this.rawData = Buffer.allocUnsafe(0); - } - - public getId(): string { - return this.id; - } - - protected abstract onServerError(err: Error): void; - protected abstract onEvent(event: DebugProtocol.Event): void; - protected abstract dispatchRequest(request: DebugProtocol.Request, response: DebugProtocol.Response): void; - - protected connect(readable: stream.Readable, writable: stream.Writable): void { - - this.outputStream = writable; - - readable.on('data', (data: Buffer) => { - this.rawData = Buffer.concat([this.rawData, data]); - this.handleData(); - }); - } - - protected send(command: string, args: any): TPromise { - let errorCallback: (error: Error) => void; - return new TPromise((completeDispatch, errorDispatch) => { - errorCallback = errorDispatch; - this.doSend(command, args, (result: R) => { - if (result.success) { - completeDispatch(result); - } else { - errorDispatch(result); - } - }); - }, () => errorCallback(canceled())); - } - - public sendResponse(response: DebugProtocol.Response): void { - if (response.seq > 0) { - console.error(`attempt to send more than one response for command ${response.command}`); - } else { - this.sendMessage('response', response); - } - } - - private doSend(command: string, args: any, clb: (result: DebugProtocol.Response) => void): void { - - const request: any = { - command: command - }; - if (args && Object.keys(args).length > 0) { - request.arguments = args; - } - - this.sendMessage('request', request); - - if (clb) { - // store callback for this request - this.pendingRequests.set(request.seq, clb); - } - } - - private sendMessage(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void { - - message.type = typ; - message.seq = this.sequence++; - - const json = JSON.stringify(message); - const length = Buffer.byteLength(json, 'utf8'); - - this.outputStream.write('Content-Length: ' + length.toString() + V8Protocol.TWO_CRLF, 'utf8'); - this.outputStream.write(json, 'utf8'); - } - - private handleData(): void { - while (true) { - if (this.contentLength >= 0) { - if (this.rawData.length >= this.contentLength) { - const message = this.rawData.toString('utf8', 0, this.contentLength); - this.rawData = this.rawData.slice(this.contentLength); - this.contentLength = -1; - if (message.length > 0) { - this.dispatch(message); - } - continue; // there may be more complete messages to process - } - } else { - const s = this.rawData.toString('utf8', 0, this.rawData.length); - const idx = s.indexOf(V8Protocol.TWO_CRLF); - if (idx !== -1) { - const match = /Content-Length: (\d+)/.exec(s); - if (match && match[1]) { - this.contentLength = Number(match[1]); - this.rawData = this.rawData.slice(idx + V8Protocol.TWO_CRLF.length); - continue; // try to handle a complete message - } - } - } - break; - } - } - - private dispatch(body: string): void { - try { - const rawData = JSON.parse(body); - switch (rawData.type) { - case 'event': - this.onEvent(rawData); - break; - case 'response': - const response = rawData; - const clb = this.pendingRequests.get(response.request_seq); - if (clb) { - this.pendingRequests.delete(response.request_seq); - clb(response); - } - break; - case 'request': - const request = rawData; - const resp: DebugProtocol.Response = { - type: 'response', - seq: 0, - command: request.command, - request_seq: request.seq, - success: true - }; - this.dispatchRequest(request, resp); - break; - } - } catch (e) { - this.onServerError(new Error(e.message || e)); - } - } -} diff --git a/src/vs/workbench/parts/debug/test/common/debugUtils.test.ts b/src/vs/workbench/parts/debug/test/common/debugUtils.test.ts index fa15e687ce..1cacf62cbb 100644 --- a/src/vs/workbench/parts/debug/test/common/debugUtils.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugUtils.test.ts @@ -3,8 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import debug = require('vs/workbench/parts/debug/common/debug'); -import assert = require('assert'); +import * as debug from 'vs/workbench/parts/debug/common/debug'; +import * as assert from 'assert'; suite('Debug - Utils', () => { test('formatPII', () => { diff --git a/src/vs/workbench/parts/debug/test/common/mockDebug.ts b/src/vs/workbench/parts/debug/test/common/mockDebug.ts index d4272fb9d6..9df630dcb3 100644 --- a/src/vs/workbench/parts/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/parts/debug/test/common/mockDebug.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import uri from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { ILaunch, IDebugService, State, DebugEvent, IProcess, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, ISession } from 'vs/workbench/parts/debug/common/debug'; +import { ILaunch, IDebugService, State, DebugEvent, IProcess, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, ISession, IBreakpoint } from 'vs/workbench/parts/debug/common/debug'; export class MockDebugService implements IDebugService { public _serviceBrand: any; @@ -39,7 +39,7 @@ export class MockDebugService implements IDebugService { public focusStackFrame(focusedStackFrame: IStackFrame): void { } - public addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise { + public addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise { return TPromise.as(null); } @@ -111,6 +111,7 @@ export class MockDebugService implements IDebugService { } export class MockSession implements ISession { + public readyForBreakpoints = true; public emittedStopped = true; @@ -217,6 +218,10 @@ export class MockSession implements ISession { return TPromise.as(null); } + public terminateThreads(args: DebugProtocol.TerminateThreadsArguments): TPromise { + return TPromise.as(null); + } + public setVariable(args: DebugProtocol.SetVariableArguments): TPromise { return TPromise.as(null); } @@ -249,5 +254,5 @@ export class MockSession implements ISession { return TPromise.as(null); } - public onDidStop: Event = null; + public readonly onDidStop: Event = null; } diff --git a/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts b/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts deleted file mode 100644 index f3d8a6c970..0000000000 --- a/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import * as paths from 'vs/base/common/paths'; -import * as platform from 'vs/base/common/platform'; -import { IRawAdapter, IAdapterExecutable, IConfigurationManager } from 'vs/workbench/parts/debug/common/debug'; -import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; -import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import uri from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; - - -suite('Debug - Adapter', () => { - let adapter: Adapter; - const extensionFolderPath = 'a/b/c/'; - const rawAdapter = { - type: 'mock', - label: 'Mock Debug', - enableBreakpointsFor: { 'languageIds': ['markdown'] }, - program: './out/mock/mockDebug.js', - args: ['arg1', 'arg2'], - configurationAttributes: { - launch: { - required: ['program'], - properties: { - program: { - 'type': 'string', - 'description': 'Workspace relative path to a text file.', - 'default': 'readme.md' - } - } - } - }, - variables: null, - initialConfigurations: [ - { - name: 'Mock-Debug', - type: 'mock', - request: 'launch', - program: 'readme.md' - } - ] - }; - const configurationManager = { - debugAdapterExecutable(folderUri: uri | undefined, type: string): TPromise { - return TPromise.as(undefined); - } - }; - - setup(() => { - adapter = new Adapter(configurationManager, rawAdapter, { extensionFolderPath, id: 'adapter', name: 'myAdapter', version: '1.0.0', publisher: 'vscode', isBuiltin: false, engines: null }, - new TestConfigurationService(), null); - }); - - teardown(() => { - adapter = null; - }); - - test('attributes', () => { - assert.equal(adapter.type, rawAdapter.type); - assert.equal(adapter.label, rawAdapter.label); - - return adapter.getAdapterExecutable(undefined, false).then(details => { - assert.equal(details.command, paths.join(extensionFolderPath, rawAdapter.program)); - assert.deepEqual(details.args, rawAdapter.args); - }); - }); - - test('schema attributes', () => { - const schemaAttribute = adapter.getSchemaAttributes()[0]; - assert.notDeepEqual(schemaAttribute, rawAdapter.configurationAttributes); - Object.keys(rawAdapter.configurationAttributes.launch).forEach(key => { - assert.deepEqual(schemaAttribute[key], rawAdapter.configurationAttributes.launch[key]); - }); - - assert.equal(schemaAttribute['additionalProperties'], false); - assert.equal(!!schemaAttribute['properties']['request'], true); - assert.equal(!!schemaAttribute['properties']['name'], true); - assert.equal(!!schemaAttribute['properties']['type'], true); - assert.equal(!!schemaAttribute['properties']['preLaunchTask'], true); - }); - - test('merge', () => { - - const da: IRawAdapter = { - type: 'mock', - win: { - runtime: 'winRuntime' - }, - linux: { - runtime: 'linuxRuntime' - }, - osx: { - runtime: 'osxRuntime' - }, - runtimeArgs: ['first arg'], - program: 'mockprogram', - args: ['arg'] - }; - - adapter.merge(da, { - name: 'my name', - id: 'my_id', - version: '1.0', - publisher: 'mockPublisher', - isBuiltin: true, - extensionFolderPath: 'a/b/c/d', - engines: null - }); - - return adapter.getAdapterExecutable(undefined, false).then(details => { - assert.equal(details.command, platform.isLinux ? da.linux.runtime : platform.isMacintosh ? da.osx.runtime : da.win.runtime); - assert.deepEqual(details.args, da.runtimeArgs.concat(['a/b/c/d/mockprogram'].concat(da.args))); - }); - }); - - test('initial config file content', () => { - - const expected = ['{', - ' // Use IntelliSense to learn about possible attributes.', - ' // Hover to view descriptions of existing attributes.', - ' // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387', - ' "version": "0.2.0",', - ' "configurations": [', - ' {', - ' "name": "Mock-Debug",', - ' "type": "mock",', - ' "request": "launch",', - ' "program": "readme.md"', - ' }', - ' ]', - '}'].join('\n'); - - return adapter.getInitialConfigurationContent().then(content => { - assert.equal(content, expected); - }, err => assert.fail()); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/test/node/debugger.test.ts b/src/vs/workbench/parts/debug/test/node/debugger.test.ts new file mode 100644 index 0000000000..63a9a7d0a0 --- /dev/null +++ b/src/vs/workbench/parts/debug/test/node/debugger.test.ts @@ -0,0 +1,182 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as paths from 'vs/base/common/paths'; +import * as platform from 'vs/base/common/platform'; +import { IAdapterExecutable, IConfigurationManager } from 'vs/workbench/parts/debug/common/debug'; +import { Debugger } from 'vs/workbench/parts/debug/node/debugger'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import uri from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { DebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter'; + + +suite('Debug - Debugger', () => { + let _debugger: Debugger; + + const extensionFolderPath = 'a/b/c/'; + const debuggerContribution = { + type: 'mock', + label: 'Mock Debug', + enableBreakpointsFor: { 'languageIds': ['markdown'] }, + program: './out/mock/mockDebug.js', + args: ['arg1', 'arg2'], + configurationAttributes: { + launch: { + required: ['program'], + properties: { + program: { + 'type': 'string', + 'description': 'Workspace relative path to a text file.', + 'default': 'readme.md' + } + } + } + }, + variables: null, + initialConfigurations: [ + { + name: 'Mock-Debug', + type: 'mock', + request: 'launch', + program: 'readme.md' + } + ] + }; + + const extensionDescriptor0 = { + id: 'adapter', + name: 'myAdapter', + version: '1.0.0', + publisher: 'vscode', + extensionFolderPath: extensionFolderPath, + isBuiltin: false, + engines: null, + contributes: { + 'debuggers': [ + debuggerContribution + ] + } + }; + + const extensionDescriptor1 = { + id: 'extension1', + name: 'extension1', + version: '1.0.0', + publisher: 'vscode', + extensionFolderPath: '/e1/b/c/', + isBuiltin: false, + engines: null, + contributes: { + 'debuggers': [ + { + type: 'mock', + runtime: 'runtime', + runtimeArgs: ['rarg'], + program: 'mockprogram', + args: ['parg'] + } + ] + } + }; + + const extensionDescriptor2 = { + id: 'extension2', + name: 'extension2', + version: '1.0.0', + publisher: 'vscode', + extensionFolderPath: '/e2/b/c/', + isBuiltin: false, + engines: null, + contributes: { + 'debuggers': [ + { + type: 'mock', + win: { + runtime: 'winRuntime', + program: 'winProgram' + }, + linux: { + runtime: 'linuxRuntime', + program: 'linuxProgram' + }, + osx: { + runtime: 'osxRuntime', + program: 'osxProgram' + } + } + ] + } + }; + + + const configurationManager = { + debugAdapterExecutable(folderUri: uri | undefined, type: string): TPromise { + return TPromise.as(undefined); + } + }; + + setup(() => { + _debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, new TestConfigurationService(), null, null); + }); + + teardown(() => { + _debugger = null; + }); + + test('attributes', () => { + assert.equal(_debugger.type, debuggerContribution.type); + assert.equal(_debugger.label, debuggerContribution.label); + + const ae = DebugAdapter.platformAdapterExecutable([extensionDescriptor0], 'mock'); + + assert.equal(ae.command, paths.join(extensionFolderPath, debuggerContribution.program)); + assert.deepEqual(ae.args, debuggerContribution.args); + }); + + test('schema attributes', () => { + const schemaAttribute = _debugger.getSchemaAttributes()[0]; + assert.notDeepEqual(schemaAttribute, debuggerContribution.configurationAttributes); + Object.keys(debuggerContribution.configurationAttributes.launch).forEach(key => { + assert.deepEqual(schemaAttribute[key], debuggerContribution.configurationAttributes.launch[key]); + }); + + assert.equal(schemaAttribute['additionalProperties'], false); + assert.equal(!!schemaAttribute['properties']['request'], true); + assert.equal(!!schemaAttribute['properties']['name'], true); + assert.equal(!!schemaAttribute['properties']['type'], true); + assert.equal(!!schemaAttribute['properties']['preLaunchTask'], true); + }); + + test('merge platform specific attributes', () => { + const ae = DebugAdapter.platformAdapterExecutable([extensionDescriptor1, extensionDescriptor2], 'mock'); + assert.equal(ae.command, platform.isLinux ? 'linuxRuntime' : (platform.isMacintosh ? 'osxRuntime' : 'winRuntime')); + const xprogram = platform.isLinux ? 'linuxProgram' : (platform.isMacintosh ? 'osxProgram' : 'winProgram'); + assert.deepEqual(ae.args, ['rarg', '/e2/b/c/' + xprogram, 'parg']); + }); + + test('initial config file content', () => { + + const expected = ['{', + ' // Use IntelliSense to learn about possible attributes.', + ' // Hover to view descriptions of existing attributes.', + ' // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387', + ' "version": "0.2.0",', + ' "configurations": [', + ' {', + ' "name": "Mock-Debug",', + ' "type": "mock",', + ' "request": "launch",', + ' "program": "readme.md"', + ' }', + ' ]', + '}'].join('\n'); + + return _debugger.getInitialConfigurationContent().then(content => { + assert.equal(content, expected); + }, err => assert.fail(err)); + }); +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/emmet/browser/actions/showEmmetCommands.ts b/src/vs/workbench/parts/emmet/browser/actions/showEmmetCommands.ts index 569caded0b..783bae6506 100644 --- a/src/vs/workbench/parts/emmet/browser/actions/showEmmetCommands.ts +++ b/src/vs/workbench/parts/emmet/browser/actions/showEmmetCommands.ts @@ -5,7 +5,7 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { registerEditorAction, EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; diff --git a/src/vs/workbench/parts/emmet/electron-browser/actions/expandAbbreviation.ts b/src/vs/workbench/parts/emmet/electron-browser/actions/expandAbbreviation.ts index 78671c066b..d6ad7e045c 100644 --- a/src/vs/workbench/parts/emmet/electron-browser/actions/expandAbbreviation.ts +++ b/src/vs/workbench/parts/emmet/electron-browser/actions/expandAbbreviation.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { EmmetEditorAction } from 'vs/workbench/parts/emmet/electron-browser/emmetActions'; import { registerEditorAction } from 'vs/editor/browser/editorExtensions'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -23,7 +23,7 @@ class ExpandAbbreviationAction extends EmmetEditorAction { kbOpts: { primary: KeyCode.Tab, kbExpr: ContextKeyExpr.and( - EditorContextKeys.textFocus, + EditorContextKeys.editorTextFocus, EditorContextKeys.tabDoesNotMoveFocus, ContextKeyExpr.has('config.emmet.triggerExpansionOnTab') ) diff --git a/src/vs/workbench/parts/emmet/test/electron-browser/emmetAction.test.ts b/src/vs/workbench/parts/emmet/test/electron-browser/emmetAction.test.ts index dbb1cc3f95..84bd63b4a1 100644 --- a/src/vs/workbench/parts/emmet/test/electron-browser/emmetAction.test.ts +++ b/src/vs/workbench/parts/emmet/test/electron-browser/emmetAction.test.ts @@ -7,7 +7,7 @@ import { IGrammarContributions, ILanguageIdentifierResolver, EmmetEditorAction } from 'vs/workbench/parts/emmet/electron-browser/emmetActions'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; -import assert = require('assert'); +import * as assert from 'assert'; import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; // diff --git a/src/vs/workbench/parts/execution/electron-browser/execution.contribution.ts b/src/vs/workbench/parts/execution/electron-browser/execution.contribution.ts index 31dce6b2fc..f3be864382 100644 --- a/src/vs/workbench/parts/execution/electron-browser/execution.contribution.ts +++ b/src/vs/workbench/parts/execution/electron-browser/execution.contribution.ts @@ -9,13 +9,13 @@ import * as env from 'vs/base/common/platform'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import uri from 'vs/base/common/uri'; import { ITerminalService } from 'vs/workbench/parts/execution/common/execution'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; -import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; +import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { ITerminalService as IIntegratedTerminalService, KEYBINDING_CONTEXT_TERMINAL_NOT_FOCUSED } from 'vs/workbench/parts/terminal/common/terminal'; import { getDefaultTerminalWindows, getDefaultTerminalLinuxReady, DEFAULT_TERMINAL_OSX, ITerminalConfiguration } from 'vs/workbench/parts/execution/electron-browser/terminal'; import { WinTerminalService, MacTerminalService, LinuxTerminalService } from 'vs/workbench/parts/execution/electron-browser/terminalService'; @@ -38,7 +38,7 @@ if (env.isWindows) { } getDefaultTerminalLinuxReady().then(defaultTerminalLinux => { - let configurationRegistry = Registry.as(Extensions.Configuration); + let configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration({ 'id': 'externalTerminal', 'order': 100, @@ -52,26 +52,25 @@ getDefaultTerminalLinuxReady().then(defaultTerminalLinux => { 'external' ], 'description': nls.localize('explorer.openInTerminalKind', "Customizes what kind of terminal to launch."), - 'default': 'integrated', - 'isExecutable': false + 'default': 'integrated' }, 'terminal.external.windowsExec': { 'type': 'string', 'description': nls.localize('terminal.external.windowsExec', "Customizes which terminal to run on Windows."), 'default': getDefaultTerminalWindows(), - 'isExecutable': true + 'scope': ConfigurationScope.APPLICATION }, 'terminal.external.osxExec': { 'type': 'string', 'description': nls.localize('terminal.external.osxExec', "Customizes which terminal application to run on OS X."), 'default': DEFAULT_TERMINAL_OSX, - 'isExecutable': true + 'scope': ConfigurationScope.APPLICATION }, 'terminal.external.linuxExec': { 'type': 'string', 'description': nls.localize('terminal.external.linuxExec', "Customizes which terminal to run on Linux."), 'default': defaultTerminalLinux, - 'isExecutable': true + 'scope': ConfigurationScope.APPLICATION } } }); @@ -92,7 +91,7 @@ CommandsRegistry.registerCommand({ const directoriesToOpen = distinct(stats.map(({ stat }) => stat.isDirectory ? stat.resource.fsPath : paths.dirname(stat.resource.fsPath))); return directoriesToOpen.map(dir => { if (configurationService.getValue().terminal.explorerKind === 'integrated') { - const instance = integratedTerminalService.createInstance({ cwd: dir }, true); + const instance = integratedTerminalService.createTerminal({ cwd: dir }, true); if (instance && (resources.length === 1 || !resource || dir === resource.fsPath || dir === paths.dirname(resource.fsPath))) { integratedTerminalService.setActiveInstance(instance); integratedTerminalService.showPanel(true); @@ -117,6 +116,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ const root = historyService.getLastActiveWorkspaceRoot(Schemas.file); if (root) { terminalService.openTerminal(root.fsPath); + } else { + // Opens current file's folder, if no folder is open in editor + const activeFile = historyService.getLastActiveFile(); + if (activeFile) { + terminalService.openTerminal(paths.dirname(activeFile.fsPath)); + } } } }); diff --git a/src/vs/workbench/parts/execution/electron-browser/terminal.ts b/src/vs/workbench/parts/execution/electron-browser/terminal.ts index dd2fd0f4e6..ccf4581392 100644 --- a/src/vs/workbench/parts/execution/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/execution/electron-browser/terminal.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import env = require('vs/base/common/platform'); +import * as env from 'vs/base/common/platform'; import * as pfs from 'vs/base/node/pfs'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -32,7 +32,7 @@ export function getDefaultTerminalLinuxReady(): TPromise { } c('xterm'); - }); + }, () => { }); } return _DEFAULT_TERMINAL_LINUX_READY; } @@ -42,7 +42,8 @@ export const DEFAULT_TERMINAL_OSX = 'Terminal.app'; let _DEFAULT_TERMINAL_WINDOWS: string = null; export function getDefaultTerminalWindows(): string { if (!_DEFAULT_TERMINAL_WINDOWS) { - _DEFAULT_TERMINAL_WINDOWS = `${process.env.windir}\\${process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') ? 'Sysnative' : 'System32'}\\cmd.exe`; + const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + _DEFAULT_TERMINAL_WINDOWS = `${process.env.windir ? process.env.windir : 'C:\\Windows'}\\${isWoW64 ? 'Sysnative' : 'System32'}\\cmd.exe`; } return _DEFAULT_TERMINAL_WINDOWS; } diff --git a/src/vs/workbench/parts/execution/electron-browser/terminalService.ts b/src/vs/workbench/parts/execution/electron-browser/terminalService.ts index 6e29ee2c6e..4797105607 100644 --- a/src/vs/workbench/parts/execution/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/execution/electron-browser/terminalService.ts @@ -5,11 +5,11 @@ 'use strict'; -import cp = require('child_process'); -import path = require('path'); -import processes = require('vs/base/node/processes'); -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); +import * as cp from 'child_process'; +import * as path from 'path'; +import * as processes from 'vs/base/node/processes'; +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; import { assign } from 'vs/base/common/objects'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITerminalService } from 'vs/workbench/parts/execution/common/execution'; diff --git a/src/vs/workbench/parts/extensions/browser/dependenciesViewer.ts b/src/vs/workbench/parts/extensions/browser/dependenciesViewer.ts index c35c0eaab4..66463dd375 100644 --- a/src/vs/workbench/parts/extensions/browser/dependenciesViewer.ts +++ b/src/vs/workbench/parts/extensions/browser/dependenciesViewer.ts @@ -59,7 +59,7 @@ export class Renderer implements IRenderer { private static readonly EXTENSION_TEMPLATE_ID = 'extension-template'; private static readonly UNKNOWN_EXTENSION_TEMPLATE_ID = 'unknown-extension-template'; - constructor( @IInstantiationService private instantiationService: IInstantiationService) { + constructor(@IInstantiationService private instantiationService: IInstantiationService) { } public getHeight(tree: ITree, element: IExtensionDependencies): number { @@ -198,7 +198,7 @@ class OpenExtensionAction extends Action { private _extensionDependencies: IExtensionDependencies; - constructor( @IExtensionsWorkbenchService private extensionsWorkdbenchService: IExtensionsWorkbenchService) { + constructor(@IExtensionsWorkbenchService private extensionsWorkdbenchService: IExtensionsWorkbenchService) { super('extensions.action.openDependency', ''); } diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 813a66fe65..0224f79ec7 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -9,15 +9,15 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, Action } from 'vs/base/common/actions'; import { Throttler } from 'vs/base/common/async'; import * as DOM from 'vs/base/browser/dom'; -import paths = require('vs/base/common/paths'); -import Event from 'vs/base/common/event'; +import * as paths from 'vs/base/common/paths'; +import { Event } from 'vs/base/common/event'; import * as json from 'vs/base/common/json'; import { ActionItem, IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, AutoUpdateConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; import { ExtensionsConfigurationInitialContent } from 'vs/workbench/parts/extensions/common/extensionsFileTemplate'; -import { LocalExtensionType, IExtensionEnablementService, IExtensionTipsService, EnablementState, ExtensionsLabel, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { LocalExtensionType, IExtensionEnablementService, IExtensionTipsService, EnablementState, ExtensionsLabel } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ToggleViewletAction } from 'vs/workbench/browser/viewlet'; @@ -44,36 +44,29 @@ import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; -class DownloadExtensionAction extends Action { - - constructor( - private extension: IExtension, - @IOpenerService private openerService: IOpenerService, - @INotificationService private notificationService: INotificationService, - @IInstantiationService private instantiationService: IInstantiationService - ) { - super('extensions.download', localize('download', "Download Manually"), '', true); - } - - run(): TPromise { - return this.openerService.open(URI.parse(this.extension.downloadUrl)).then(() => { - this.notificationService.notify({ - severity: Severity.Info, - message: localize('install vsix', 'Once downloaded, please manually install the downloaded VSIX of \'{0}\'.', this.extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL) - ] - } - }); - }); - } -} +const promptDownloadManually = (extension: IExtension, message: string, instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService) => { + notificationService.prompt(Severity.Error, message, [{ + label: localize('download', "Download Manually"), + run: () => openerService.open(URI.parse(extension.downloadUrl)).then(() => { + notificationService.prompt( + Severity.Info, + localize('install vsix', 'Once downloaded, please manually install the downloaded VSIX of \'{0}\'.', extension.id), + [{ + label: InstallVSIXAction.LABEL, + run: () => { + const action = instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL); + action.run(); + action.dispose(); + } + }] + ); + }) + }]); +}; export class InstallAction extends Action { @@ -91,7 +84,8 @@ export class InstallAction extends Action { constructor( @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @IInstantiationService private instantiationService: IInstantiationService, - @INotificationService private notificationService: INotificationService + @INotificationService private notificationService: INotificationService, + @IOpenerService private openerService: IOpenerService ) { super('extensions.install', InstallAction.InstallLabel, InstallAction.Class, false); @@ -133,15 +127,8 @@ export class InstallAction extends Action { } console.error(err); - this.notificationService.notify({ - severity: Severity.Error, - message: localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(DownloadExtensionAction, extension) - ] - } - }); + + promptDownloadManually(extension, localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), this.instantiationService, this.notificationService, this.openerService); }); } @@ -306,7 +293,8 @@ export class UpdateAction extends Action { constructor( @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @IInstantiationService private instantiationService: IInstantiationService, - @INotificationService private notificationService: INotificationService + @INotificationService private notificationService: INotificationService, + @IOpenerService private openerService: IOpenerService ) { super('extensions.update', UpdateAction.Label, UpdateAction.DisabledClass, false); @@ -348,15 +336,8 @@ export class UpdateAction extends Action { } console.error(err); - this.notificationService.notify({ - severity: Severity.Error, - message: localize('failedToUpdate', "Failed to update \'{0}\'.", extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(DownloadExtensionAction, extension) - ] - } - }); + + promptDownloadManually(extension, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.id), this.instantiationService, this.notificationService, this.openerService); }); } @@ -833,7 +814,8 @@ export class UpdateAllAction extends Action { label = UpdateAllAction.LABEL, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @INotificationService private notificationService: INotificationService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IOpenerService private openerService: IOpenerService ) { super(id, label, '', false); @@ -860,15 +842,8 @@ export class UpdateAllAction extends Action { } console.error(err); - this.notificationService.notify({ - severity: Severity.Error, - message: localize('failedToUpdate', "Failed to update \'{0}\'.", extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(DownloadExtensionAction, extension) - ] - } - }); + + promptDownloadManually(extension, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.id), this.instantiationService, this.notificationService, this.openerService); }); } @@ -916,17 +891,17 @@ export class ReloadAction extends Action { if (state === ExtensionState.Installing || state === ExtensionState.Uninstalling) { return TPromise.wrap(null); } - return TPromise.join([this.extensionService.getExtensions(), this.extensionEnablementService.getDisabledExtensions()]) - .then(([runningExtensions, disabledExtensions]) => this.computeReloadState(runningExtensions, disabledExtensions)); + return this.extensionService.getExtensions() + .then(runningExtensions => this.computeReloadState(runningExtensions)); }).done(() => { this.class = this.enabled ? ReloadAction.EnabledClass : ReloadAction.DisabledClass; }); } - private computeReloadState(runningExtensions: IExtensionDescription[], disabledExtensions: IExtensionIdentifier[]): void { + private computeReloadState(runningExtensions: IExtensionDescription[]): void { const isInstalled = this.extensionsWorkbenchService.local.some(e => e.id === this.extension.id); const isUninstalled = this.extension.state === ExtensionState.Uninstalled; - const isDisabled = this.isDisabled(disabledExtensions); + const isDisabled = this.extension.local ? !this.extensionEnablementService.isEnabled(this.extension.local) : false; const filteredExtensions = runningExtensions.filter(e => areSameExtensions(e, this.extension)); const isExtensionRunning = filteredExtensions.length > 0; @@ -968,14 +943,6 @@ export class ReloadAction extends Action { } } - private isDisabled(disabledExtensions: IExtensionIdentifier[]): boolean { - const identifier = { id: this.extension.id, uuid: this.extension.uuid }; - if (this.extension.type === LocalExtensionType.System) { - return disabledExtensions.some(d => areSameExtensions(d, identifier)); - } - return !this.extensionEnablementService.isEnabled({ id: this.extension.id, uuid: this.extension.uuid }); - } - run(): TPromise { return this.windowService.reloadWindow(); } @@ -1018,7 +985,7 @@ export class ShowEnabledExtensionsAction extends Action { return this.viewletService.openViewlet(VIEWLET_ID, true) .then(viewlet => viewlet as IExtensionsViewlet) .then(viewlet => { - viewlet.search('@enabled'); + viewlet.search('@enabled '); viewlet.focus(); }); } @@ -1041,7 +1008,7 @@ export class ShowInstalledExtensionsAction extends Action { return this.viewletService.openViewlet(VIEWLET_ID, true) .then(viewlet => viewlet as IExtensionsViewlet) .then(viewlet => { - viewlet.search('@installed'); + viewlet.search('@installed '); viewlet.focus(); }); } @@ -1213,7 +1180,8 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action { @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @IExtensionTipsService private extensionTipsService: IExtensionTipsService, @INotificationService private notificationService: INotificationService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IOpenerService private openerService: IOpenerService ) { super(id, label, 'extension-action'); this.extensionsWorkbenchService.onChange(() => this.update(), this, this.disposables); @@ -1245,7 +1213,7 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action { return TPromise.as(null); } - viewlet.search('@recommended'); + viewlet.search('@recommended '); viewlet.focus(); return this.extensionsWorkbenchService.queryGallery({ names: toInstall, source: 'install-all-workspace-recommendations' }).then(pager => { @@ -1277,15 +1245,8 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action { } console.error(err); - this.notificationService.notify({ - severity: Severity.Error, - message: localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(DownloadExtensionAction, extension) - ] - } - }); + + promptDownloadManually(extension, localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), this.instantiationService, this.notificationService, this.openerService); }); } @@ -1308,7 +1269,8 @@ export class InstallRecommendedExtensionAction extends Action { @IViewletService private viewletService: IViewletService, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @INotificationService private notificationService: INotificationService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IOpenerService private openerService: IOpenerService ) { super(InstallRecommendedExtensionAction.ID, InstallRecommendedExtensionAction.LABEL, null); this.extensionId = extensionId; @@ -1330,7 +1292,7 @@ export class InstallRecommendedExtensionAction extends Action { return TPromise.as(null); } - viewlet.search('@recommended'); + viewlet.search('@recommended '); viewlet.focus(); return this.extensionsWorkbenchService.queryGallery({ names: [this.extensionId], source: 'install-recommendation' }).then(pager => { @@ -1346,15 +1308,8 @@ export class InstallRecommendedExtensionAction extends Action { } console.error(err); - this.notificationService.notify({ - severity: Severity.Error, - message: localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), - actions: { - primary: [ - this.instantiationService.createInstance(DownloadExtensionAction, extension) - ] - } - }); + + promptDownloadManually(extension, localize('failedToInstall', "Failed to install \'{0}\'.", extension.id), this.instantiationService, this.notificationService, this.openerService); }); } @@ -1550,7 +1505,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio selection } })), - error => TPromise.wrapError(new Error(localize('OpenExtensionsFile.failed', "Unable to create 'extensions.json' file inside the '.vscode' folder ({0}).", error)))); + error => TPromise.wrapError(new Error(localize('OpenExtensionsFile.failed', "Unable to create 'extensions.json' file inside the '.vscode' folder ({0}).", error)))); } protected openWorkspaceConfigurationFile(workspaceConfigurationFile: URI): TPromise { @@ -1725,6 +1680,45 @@ export class MaliciousStatusLabelAction extends Action { } } +export class DisabledStatusLabelAction extends Action { + + private static readonly Class = 'disable-status'; + + private _extension: IExtension; + get extension(): IExtension { return this._extension; } + set extension(extension: IExtension) { this._extension = extension; this.update(); } + + private disposables: IDisposable[] = []; + private throttler: Throttler = new Throttler(); + + constructor( + @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, + @IExtensionService private extensionService: IExtensionService + ) { + super('extensions.install', localize('disabled', "Disabled"), `${DisabledStatusLabelAction.Class} hide`, false); + this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update())); + this.update(); + } + + private update(): void { + this.throttler.queue(() => this.extensionService.getExtensions() + .then(runningExtensions => { + this.class = `${DisabledStatusLabelAction.Class} hide`; + this.tooltip = ''; + if (this.extension && !this.extension.isMalicious && !runningExtensions.some(e => e.id === this.extension.id)) { + if (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) { + this.class = `${DisabledStatusLabelAction.Class}`; + this.tooltip = this.extension.enablementState === EnablementState.Disabled ? localize('disabled globally', "Disabled") : localize('disabled workspace', "Disabled for this Workspace"); + } + } + })); + } + + run(): TPromise { + return TPromise.as(null); + } +} + export class DisableAllAction extends Action { static readonly ID = 'workbench.extensions.action.disableAll'; @@ -1891,14 +1885,14 @@ export class InstallVSIXAction extends Action { id = InstallVSIXAction.ID, label = InstallVSIXAction.LABEL, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, - @IChoiceService private choiceService: IChoiceService, - @IWindowService private windowsService: IWindowService + @INotificationService private notificationService: INotificationService, + @IWindowService private windowService: IWindowService ) { super(id, label, 'extension-action install-vsix', true); } run(): TPromise { - return this.windowsService.showOpenDialog({ + return this.windowService.showOpenDialog({ title: localize('installFromVSIX', "Install from VSIX"), filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }], properties: ['openFile'], @@ -1909,19 +1903,19 @@ export class InstallVSIXAction extends Action { } return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix))).then(() => { - return this.choiceService.choose(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => { - if (choice === 0) { - return this.windowsService.reloadWindow(); - } - - return TPromise.as(undefined); - }); + this.notificationService.prompt( + Severity.Info, + localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), + [{ + label: localize('InstallVSIXAction.reloadNow', "Reload Now"), + run: () => this.windowService.reloadWindow() + }] + ); }); }); } } - export class ReinstallAction extends Action { static readonly ID = 'workbench.extensions.action.reinstall'; @@ -1965,19 +1959,14 @@ export class ReinstallAction extends Action { private reinstallExtension(extension: IExtension): TPromise { return this.extensionsWorkbenchService.reinstall(extension) .then(() => { - this.notificationService.notify({ - message: localize('ReinstallAction.success', "Successfully reinstalled the extension."), - severity: Severity.Info, - actions: { - primary: [{ - id: 'reload', - label: localize('ReinstallAction.reloadNow', "Reload Now"), - enabled: true, - run: () => this.windowService.reloadWindow(), - dispose: () => null - }] - } - }); + this.notificationService.prompt( + Severity.Info, + localize('ReinstallAction.success', "Successfully reinstalled the extension."), + [{ + label: localize('ReinstallAction.reloadNow', "Reload Now"), + run: () => this.windowService.reloadWindow() + }] + ); }, error => this.notificationService.error(error)); } } diff --git a/src/vs/workbench/parts/extensions/browser/extensionsList.ts b/src/vs/workbench/parts/extensions/browser/extensionsList.ts index 703a7dd1e9..161251ba29 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsList.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsList.ts @@ -15,7 +15,7 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; import { once } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { IExtension, IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions'; -import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; +import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction, DisabledStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { Label, RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -97,13 +97,14 @@ export class Renderer implements IPagedRenderer { const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, ratings, { small: true }); const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, false); + const disabledStatusAction = this.instantiationService.createInstance(DisabledStatusLabelAction); const installAction = this.instantiationService.createInstance(InstallAction); const updateAction = this.instantiationService.createInstance(UpdateAction); const reloadAction = this.instantiationService.createInstance(ReloadAction); const manageAction = this.instantiationService.createInstance(ManageExtensionAction); - actionbar.push([reloadAction, updateAction, installAction, maliciousStatusAction, manageAction], actionOptions); - const disposables = [versionWidget, installCountWidget, ratingsWidget, maliciousStatusAction, updateAction, reloadAction, manageAction, actionbar, bookmarkStyler]; + actionbar.push([updateAction, reloadAction, installAction, disabledStatusAction, maliciousStatusAction, manageAction], actionOptions); + const disposables = [versionWidget, installCountWidget, ratingsWidget, maliciousStatusAction, disabledStatusAction, updateAction, reloadAction, manageAction, actionbar, bookmarkStyler]; return { root, element, icon, name, installCount, ratings, author, description, disposables, @@ -113,6 +114,7 @@ export class Renderer implements IPagedRenderer { installCountWidget.extension = extension; ratingsWidget.extension = extension; maliciousStatusAction.extension = extension; + disabledStatusAction.extension = extension; installAction.extension = extension; updateAction.extension = extension; reloadAction.extension = extension; diff --git a/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts index 3c7098b4c3..a6483b34c4 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts @@ -42,7 +42,7 @@ export class ExtensionsHandler extends QuickOpenHandler { public static readonly ID = 'workbench.picker.extensions'; - constructor( @IViewletService private viewletService: IViewletService) { + constructor(@IViewletService private viewletService: IViewletService) { super(); } diff --git a/src/vs/workbench/parts/extensions/browser/media/extensionActions.css b/src/vs/workbench/parts/extensions/browser/media/extensionActions.css index 10bd349d14..abff9ef213 100644 --- a/src/vs/workbench/parts/extensions/browser/media/extensionActions.css +++ b/src/vs/workbench/parts/extensions/browser/media/extensionActions.css @@ -30,10 +30,12 @@ .monaco-action-bar .action-item.disabled .action-label.extension-action.enable, .monaco-action-bar .action-item.disabled .action-label.extension-action.disable, .monaco-action-bar .action-item.disabled .action-label.extension-action.reload, +.monaco-action-bar .action-item.disabled .action-label.disable-status.hide, .monaco-action-bar .action-item.disabled .action-label.malicious-status.not-malicious { display: none; } +.monaco-action-bar .action-item .action-label.disable-status, .monaco-action-bar .action-item .action-label.malicious-status { border-radius: 4px; color: inherit; @@ -44,6 +46,7 @@ line-height: initial; } +.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.disable-status, .extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.malicious-status { font-weight: normal; } diff --git a/src/vs/workbench/parts/extensions/common/extensions.ts b/src/vs/workbench/parts/extensions/common/extensions.ts index 1133ce18f2..10ed2a9ead 100644 --- a/src/vs/workbench/parts/extensions/common/extensions.ts +++ b/src/vs/workbench/parts/extensions/common/extensions.ts @@ -5,7 +5,7 @@ import { IViewlet } from 'vs/workbench/common/viewlet'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IPager } from 'vs/base/common/paging'; import { IQueryOptions, IExtensionManifest, LocalExtensionType, EnablementState, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; diff --git a/src/vs/workbench/parts/extensions/browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts similarity index 95% rename from src/vs/workbench/parts/extensions/browser/extensionEditor.ts rename to src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts index 17410eae79..a37278d174 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts @@ -12,12 +12,11 @@ import { marked } from 'vs/base/common/marked/marked'; import { always } from 'vs/base/common/async'; import * as arrays from 'vs/base/common/arrays'; import { OS } from 'vs/base/common/platform'; -import Event, { Emitter, once, chain } from 'vs/base/common/event'; +import { Event, Emitter, once, chain } from 'vs/base/common/event'; import Cache from 'vs/base/common/cache'; import { Action } from 'vs/base/common/actions'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import { Builder } from 'vs/base/browser/builder'; import { domEvent } from 'vs/base/browser/event'; import { append, $, addClass, removeClass, finalHandler, join, toggleClass } from 'vs/base/browser/dom'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; @@ -32,8 +31,8 @@ import { Renderer, DataSource, Controller } from 'vs/workbench/parts/extensions/ import { RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; import { EditorOptions } from 'vs/workbench/common/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; +import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction, DisabledStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; +import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; @@ -181,7 +180,8 @@ export class ExtensionEditor extends BaseEditor { private contentDisposables: IDisposable[] = []; private transientDisposables: IDisposable[] = []; private disposables: IDisposable[]; - private activeWebview: Webview; + private activeWebview: WebviewElement; + private editorLoadComplete: boolean = false; constructor( @ITelemetryService telemetryService: ITelemetryService, @@ -209,10 +209,8 @@ export class ExtensionEditor extends BaseEditor { this.findInputFocusContextKey = KEYBINDING_CONTEXT_EXTENSIONEDITOR_FIND_WIDGET_INPUT_FOCUSED.bindTo(this.contextKeyService); } - createEditor(parent: Builder): void { - const container = parent.getHTMLElement(); - - const root = append(container, $('.extension-editor')); + createEditor(parent: HTMLElement): void { + const root = append(parent, $('.extension-editor')); this.header = append(root, $('.header')); this.icon = append(this.header, $('img.icon', { draggable: false })); @@ -274,6 +272,7 @@ export class ExtensionEditor extends BaseEditor { } setInput(input: ExtensionsInput, options: EditorOptions): TPromise { + this.editorLoadComplete = false; const extension = input.extension; this.transientDisposables = dispose(this.transientDisposables); @@ -308,7 +307,7 @@ export class ExtensionEditor extends BaseEditor { /* __GDPR__ "extensionGallery:openExtension" : { - "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "${include}": [ "${GalleryExtensionTelemetryData}" ] @@ -358,6 +357,7 @@ export class ExtensionEditor extends BaseEditor { //this.transientDisposables.push(ratings); const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, true); + const disabledStatusAction = this.instantiationService.createInstance(DisabledStatusLabelAction); const installAction = this.instantiationService.createInstance(CombinedInstallAction); const updateAction = this.instantiationService.createInstance(UpdateAction); const enableAction = this.instantiationService.createInstance(EnableAction); @@ -366,14 +366,15 @@ export class ExtensionEditor extends BaseEditor { installAction.extension = extension; maliciousStatusAction.extension = extension; + disabledStatusAction.extension = extension; updateAction.extension = extension; enableAction.extension = extension; disableAction.extension = extension; reloadAction.extension = extension; this.extensionActionBar.clear(); - this.extensionActionBar.push([reloadAction, updateAction, enableAction, disableAction, installAction, maliciousStatusAction], { icon: true, label: true }); - this.transientDisposables.push(enableAction, updateAction, reloadAction, disableAction, installAction, maliciousStatusAction); + this.extensionActionBar.push([disabledStatusAction, reloadAction, updateAction, enableAction, disableAction, installAction, maliciousStatusAction], { icon: true, label: true }); + this.transientDisposables.push(enableAction, updateAction, reloadAction, disableAction, installAction, maliciousStatusAction, disabledStatusAction); this.content.innerHTML = ''; // Clear content before setting navbar actions. @@ -384,6 +385,7 @@ export class ExtensionEditor extends BaseEditor { this.navbar.push(NavbarSection.Changelog, localize('changelog', "Changelog")); this.navbar.push(NavbarSection.Dependencies, localize('dependencies', "Dependencies")); + this.editorLoadComplete = true; return super.setInput(input, options); } @@ -411,6 +413,18 @@ export class ExtensionEditor extends BaseEditor { } private onNavbarChange(extension: IExtension, id: string): void { + if (this.editorLoadComplete) { + /* __GDPR__ + "extensionEditor:navbarChange" : { + "navItem": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "${include}": [ + "${GalleryExtensionTelemetryData}" + ] + } + */ + this.telemetryService.publicLog('extensionEditor:navbarChange', assign(extension.telemetryData, { navItem: id })); + } + this.contentDisposables = dispose(this.contentDisposables); this.content.innerHTML = ''; this.activeWebview = null; @@ -430,7 +444,8 @@ export class ExtensionEditor extends BaseEditor { .then(body => { const allowedBadgeProviders = this.extensionsWorkbenchService.allowedBadgeProviders; const webViewOptions = allowedBadgeProviders.length > 0 ? { allowScripts: false, allowSvgs: false, svgWhiteList: allowedBadgeProviders } : {}; - this.activeWebview = new Webview(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions); + this.activeWebview = new WebviewElement(this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions); + this.activeWebview.mountTo(this.content); const removeLayoutParticipant = arrays.insert(this.layoutParticipants, this.activeWebview); this.contentDisposables.push(toDisposable(removeLayoutParticipant)); this.activeWebview.contents = body; @@ -645,7 +660,7 @@ export class ExtensionEditor extends BaseEditor { const details = $('details', { open: true, ontoggle: onDetailsToggle }, $('summary', null, localize('localizations', "Localizations ({0})", localizations.length)), $('table', null, - $('tr', null, $('th', null, localize('localizations language id', "Language Id")), $('th', null, localize('localizations language name', "Langauge Name")), $('th', null, localize('localizations localized language name', "Langauge Name (Localized)"))), + $('tr', null, $('th', null, localize('localizations language id', "Language Id")), $('th', null, localize('localizations language name', "Language Name")), $('th', null, localize('localizations localized language name', "Language Name (Localized)"))), ...localizations.map(localization => $('tr', null, $('td', null, localization.languageId), $('td', null, localization.languageName), $('td', null, localization.languageNameLocalized))) ) ); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts index 65e8795f52..a2e5a6e5cc 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts @@ -6,7 +6,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionHostProfile, ProfileSession, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionHostProfileService, ProfileSessionState, RuntimeExtensionsInput } from 'vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWindowsService } from 'vs/platform/windows/common/windows'; -import { IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { randomPort } from 'vs/base/node/ports'; import product from 'vs/platform/node/product'; @@ -43,7 +43,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IWindowsService private readonly _windowsService: IWindowsService, - @IConfirmationService private readonly _confirmationService: IConfirmationService + @IDialogService private readonly _dialogService: IDialogService ) { super(); this._profile = null; @@ -75,14 +75,14 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio } if (!this._extensionService.canProfileExtensionHost()) { - return this._confirmationService.confirm({ + return this._dialogService.confirm({ type: 'info', message: nls.localize('restart1', "Profile Extensions"), detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", product.nameLong), primaryButton: nls.localize('restart3', "Restart"), secondaryButton: nls.localize('cancel', "Cancel") - }).then(restart => { - if (restart) { + }).then(res => { + if (res.confirmed) { this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] }); } }); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index 9719200438..8cd16bb175 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -34,9 +34,9 @@ import { getHashedRemotesFromUri } from 'vs/workbench/parts/stats/node/workspace import { IRequestService } from 'vs/platform/request/node/request'; import { asJson } from 'vs/base/node/request'; import { isNumber } from 'vs/base/common/types'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; import { language, LANGUAGE_DEFAULT } from 'vs/base/common/platform'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { INotificationService } from 'vs/platform/notification/common/notification'; interface IExtensionsContent { recommendations: string[]; @@ -73,7 +73,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe @IExtensionGalleryService private readonly _galleryService: IExtensionGalleryService, @IModelService private readonly _modelService: IModelService, @IStorageService private storageService: IStorageService, - @IChoiceService private choiceService: IChoiceService, @IExtensionManagementService private extensionsService: IExtensionManagementService, @IInstantiationService private instantiationService: IInstantiationService, @IFileService private fileService: IFileService, @@ -83,7 +82,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe @IEnvironmentService private environmentService: IEnvironmentService, @IExtensionService private extensionService: IExtensionService, @IRequestService private requestService: IRequestService, - @IViewletService private viewletService: IViewletService + @IViewletService private viewletService: IViewletService, + @INotificationService private notificationService: INotificationService ) { super(); @@ -162,15 +162,13 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe if (!pager || !pager.firstPage || !pager.firstPage.length) { return; } - const message = localize('showLanguagePackExtensions', "The Marketplace has extensions that can help localizing VS Code to '{0}' locale", language); - const options: Choice[] = [ - searchMarketplace, - { label: choiceNever } - ]; - this.choiceService.choose(Severity.Info, message, options).done(choice => { - switch (choice) { - case 0 /* Search Marketplace */: + this.notificationService.prompt( + Severity.Info, + localize('showLanguagePackExtensions', "The Marketplace has extensions that can help localizing VS Code to '{0}' locale", language), + [{ + label: searchMarketplace, + run: () => { /* __GDPR__ "languagePackSuggestion:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -184,8 +182,12 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe viewlet.search(`tag:lp-${language}`); viewlet.focus(); }); - break; - case 1 /* Never show again */: + } + }, + { + label: choiceNever, + isSecondary: true, + run: () => { languagePackSuggestionIgnoreList.push(language); this.storageService.store( 'extensionsAssistant/languagePackSuggestionIgnore', @@ -199,17 +201,18 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } */ this.telemetryService.publicLog('languagePackSuggestion:popup', { userReaction: 'neverShowAgain', language }); - break; - } - }, () => { - /* __GDPR__ - "languagePackSuggestion:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "language": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } - */ - this.telemetryService.publicLog('languagePackSuggestion:popup', { userReaction: 'cancelled', language }); - }); + }], + () => { + /* __GDPR__ + "languagePackSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "language": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('languagePackSuggestion:popup', { userReaction: 'cancelled', language }); + } + ); }); }); } @@ -319,11 +322,13 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe }); } - if (countBadRecommendations > 0) { - console.log('The below ' + + if (countBadRecommendations > 0 && this.notificationService) { + this.notificationService.warn( + 'The below ' + countBadRecommendations + ' extension(s) in workspace recommendations have issues:\n' + - badRecommendationsString); + badRecommendationsString + ); } return validRecommendations; @@ -495,26 +500,25 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe message = localize('reallyRecommendedExtensionPack', "The '{0}' extension pack is recommended for this file type.", name); } - const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); - const installAction = this.instantiationService.createInstance(InstallRecommendedExtensionAction, id); - const options: Choice[] = [ - localize('install', 'Install'), - recommendationsAction.label, - { label: choiceNever } - ]; - - this.choiceService.choose(Severity.Info, message, options).done(choice => { - switch (choice) { - case 0 /* Install */: + this.notificationService.prompt(Severity.Info, message, + [{ + label: localize('install', 'Install'), + run: () => { /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } */ this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'install', extensionId: name }); - return installAction.run(); - case 1 /* Show Recommendations */: + + const installAction = this.instantiationService.createInstance(InstallRecommendedExtensionAction, id); + installAction.run(); + installAction.dispose(); + } + }, { + label: localize('showRecommendations', "Show Recommendations"), + run: () => { /* __GDPR__ "extensionRecommendations:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -522,8 +526,15 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } */ this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'show', extensionId: name }); - return recommendationsAction.run(); - case 2 /* Never show again */: + + const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); + recommendationsAction.run(); + recommendationsAction.dispose(); + } + }, { + label: choiceNever, + isSecondary: true, + run: () => { importantRecommendationsIgnoreList.push(id); this.storageService.store( 'extensionsAssistant/importantRecommendationsIgnore', @@ -537,17 +548,19 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } */ this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId: name }); - return this.ignoreExtensionRecommendations(); - } - }, () => { - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + this.ignoreExtensionRecommendations(); } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); - }); + }], + () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); + } + ); }); const mimeTypesPromise = this.getMimeTypes(uri.fsPath); @@ -576,19 +589,16 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe return; } - const message = localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension); - const options: Choice[] = [ - searchMarketplace, - { label: choiceNever } - ]; - - this.choiceService.choose(Severity.Info, message, options).done(choice => { - switch (choice) { - case 0 /* Search Marketplace */: + this.notificationService.prompt( + Severity.Info, + localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension), + [{ + label: searchMarketplace, + run: () => { /* __GDPR__ "fileExtensionSuggestion:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + "fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'ok', fileExtension: fileExtension }); @@ -598,8 +608,11 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe viewlet.search(`ext:${fileExtension}`); viewlet.focus(); }); - break; - case 1 /* Never show again */: + } + }, { + label: choiceNever, + isSecondary: true, + run: () => { fileExtensionSuggestionIgnoreList.push(fileExtension); this.storageService.store( 'extensionsAssistant/fileExtensionsSuggestionIgnore', @@ -609,21 +622,22 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe /* __GDPR__ "fileExtensionSuggestion:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + "fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'neverShowAgain', fileExtension: fileExtension }); - break; - } - }, () => { - /* __GDPR__ - "fileExtensionSuggestion:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } - */ - this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension }); - }); + }], + () => { + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension }); + } + ); }); }); }); @@ -643,73 +657,88 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe .filter(id => local.every(local => `${local.manifest.publisher.toLowerCase()}.${local.manifest.name.toLowerCase()}` !== id)); if (!recommendations.length) { - return; + return TPromise.as(void 0); } - const message = localize('workspaceRecommended', "This workspace has extension recommendations."); - const showAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); - const installAllAction = this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, localize('installAll', "Install All")); + return new TPromise(c => { + this.notificationService.prompt( + Severity.Info, + localize('workspaceRecommended', "This workspace has extension recommendations."), + [{ + label: localize('installAll', "Install All"), + run: () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'install' }); - const options: Choice[] = [ - installAllAction.label, - showAction.label, - { label: choiceNever } - ]; + const installAllAction = this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, localize('installAll', "Install All")); + installAllAction.run(); + installAllAction.dispose(); - return this.choiceService.choose(Severity.Info, message, options).done(choice => { - switch (choice) { - case 0 /* Install */: + c(void 0); + } + }, { + label: localize('showRecommendations', "Show Recommendations"), + run: () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'show' }); + + const showAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); + showAction.run(); + showAction.dispose(); + + c(void 0); + } + }, { + label: choiceNever, + isSecondary: true, + run: () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'neverShowAgain' }); + this.storageService.store(storageKey, true, StorageScope.WORKSPACE); + + c(void 0); + } + }], + () => { /* __GDPR__ "extensionRecommendations:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'install' }); - return installAllAction.run(); - case 1 /* Show Recommendations */: - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'show' }); - return showAction.run(); - case 2 /* Never show again */: - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'neverShowAgain' }); - return this.storageService.store(storageKey, true, StorageScope.WORKSPACE); - } - }, () => { - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'cancelled' }); + + c(void 0); } - */ - this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'cancelled' }); + ); }); }); }); } private ignoreExtensionRecommendations() { - const message = localize('ignoreExtensionRecommendations', "Do you want to ignore all extension recommendations?"); - const options = [ - localize('ignoreAll', "Yes, Ignore All"), - localize('no', "No") - ]; - - this.choiceService.choose(Severity.Info, message, options).done(choice => { - switch (choice) { - case 0: // If the user ignores the current message and selects different file type - return this.setIgnoreRecommendationsConfig(true); - case 1: - return this.setIgnoreRecommendationsConfig(false); - } - }); + this.notificationService.prompt( + Severity.Info, + localize('ignoreExtensionRecommendations', "Do you want to ignore all extension recommendations?"), + [{ + label: localize('ignoreAll', "Yes, Ignore All"), + run: () => this.setIgnoreRecommendationsConfig(true) + }, { + label: localize('no', "No"), + run: () => this.setIgnoreRecommendationsConfig(false) + }] + ); } private _suggestBasedOnExecutables(): TPromise { @@ -785,8 +814,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe this._dynamicWorkspaceRecommendations = storedRecommendationsJson['recommendations']; /* __GDPR__ "dynamicWorkspaceRecommendations" : { - "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "cache" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "cache" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('dynamicWorkspaceRecommendations', { count: this._dynamicWorkspaceRecommendations.length, cache: 1 }); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index c9dc2e654b..7a7360885e 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -26,15 +26,15 @@ import { } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; -import { ExtensionEditor } from 'vs/workbench/parts/extensions/browser/extensionEditor'; -import { StatusUpdater, ExtensionsViewlet, MaliciousExtensionChecker } from 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; +import { ExtensionEditor } from 'vs/workbench/parts/extensions/electron-browser/extensionEditor'; +import { StatusUpdater, ExtensionsViewlet, MaliciousExtensionChecker, ExtensionsViewletViewsContribution } from 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import jsonContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import * as jsonContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId } from 'vs/workbench/parts/extensions/common/extensionsFileTemplate'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { KeymapExtensions, BetterMergeDisabled } from 'vs/workbench/parts/extensions/electron-browser/extensionsUtils'; +import { KeymapExtensions } from 'vs/workbench/parts/extensions/electron-browser/extensionsUtils'; import { adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { GalleryExtensionsHandler, ExtensionsHandler } from 'vs/workbench/parts/extensions/browser/extensionsQuickOpen'; import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; @@ -54,7 +54,7 @@ workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Ru workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(ConfigureRecommendedExtensionsCommandsContributor, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Running); -workbenchRegistry.registerWorkbenchContribution(BetterMergeDisabled, LifecyclePhase.Running); +workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Starting); Registry.as(OutputExtensions.OutputChannels) .registerChannel(ExtensionsChannelId, ExtensionsLabel); @@ -121,7 +121,7 @@ const viewletDescriptor = new ViewletDescriptor( VIEWLET_ID, localize('extensions', "Extensions"), 'extensions', - 100 + 4 ); Registry.as(ViewletExtensions.Viewlets) @@ -205,7 +205,8 @@ Registry.as(ConfigurationExtensions.Configuration) 'extensions.autoUpdate': { type: 'boolean', description: localize('extensionsAutoUpdate', "Automatically update extensions"), - default: true + default: true, + scope: ConfigurationScope.APPLICATION }, 'extensions.ignoreRecommendations': { type: 'boolean', diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index 1dd7aa03a9..80fd964c73 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -5,8 +5,8 @@ import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Action, IAction } from 'vs/base/common/actions'; -import paths = require('vs/base/common/paths'); +import { Action } from 'vs/base/common/actions'; +import * as paths from 'vs/base/common/paths'; import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/parts/extensions/common/extensions'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; @@ -14,7 +14,6 @@ import { IFileService } from 'vs/platform/files/common/files'; import URI from 'vs/base/common/uri'; import Severity from 'vs/base/common/severity'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -59,14 +58,14 @@ export class InstallVSIXAction extends Action { id = InstallVSIXAction.ID, label = InstallVSIXAction.LABEL, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, - @IChoiceService private choiceService: IChoiceService, - @IWindowService private windowsService: IWindowService + @INotificationService private notificationService: INotificationService, + @IWindowService private windowService: IWindowService ) { super(id, label, 'extension-action install-vsix', true); } run(): TPromise { - return this.windowsService.showOpenDialog({ + return this.windowService.showOpenDialog({ title: localize('installFromVSIX', "Install from VSIX"), filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }], properties: ['openFile'], @@ -77,13 +76,14 @@ export class InstallVSIXAction extends Action { } return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix))).then(() => { - return this.choiceService.choose(Severity.Info, localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), [localize('InstallVSIXAction.reloadNow', "Reload Now")]).then(choice => { - if (choice === 0) { - return this.windowsService.reloadWindow(); - } - - return TPromise.as(undefined); - }); + this.notificationService.prompt( + Severity.Info, + localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."), + [{ + label: localize('InstallVSIXAction.reloadNow', "Reload Now"), + run: () => this.windowService.reloadWindow() + }] + ); }); }); } @@ -132,19 +132,14 @@ export class ReinstallAction extends Action { private reinstallExtension(extension: IExtension): TPromise { return this.extensionsWorkbenchService.reinstall(extension) .then(() => { - this.notificationService.notify({ - message: localize('ReinstallAction.success', "Successfully reinstalled the extension."), - severity: Severity.Info, - actions: { - primary: [{ - id: 'reload', - label: localize('ReinstallAction.reloadNow', "Reload Now"), - enabled: true, - run: () => this.windowService.reloadWindow(), - dispose: () => null - }] - } - }); + this.notificationService.prompt( + Severity.Info, + localize('ReinstallAction.success', "Successfully reinstalled the extension."), + [{ + label: localize('ReinstallAction.reloadNow', "Reload Now"), + run: () => this.windowService.reloadWindow() + }] + ); }, error => this.notificationService.error(error)); } } \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts index 8dc32db499..024cbc1029 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts @@ -7,21 +7,18 @@ import * as arrays from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; -import Event, { chain, anyEvent, debounceEvent } from 'vs/base/common/event'; -import { onUnexpectedError, canceled } from 'vs/base/common/errors'; +import { Event, chain, anyEvent, debounceEvent } from 'vs/base/common/event'; +import { onUnexpectedError } from 'vs/base/common/errors'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService, IExtensionTipsService, LocalExtensionType, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService, IExtensionTipsService, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { BetterMergeDisabledNowKey, BetterMergeId, areSameExtensions, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { areSameExtensions, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { Severity } from 'vs/platform/notification/common/notification'; +import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; export interface IExtensionStatus { identifier: IExtensionIdentifier; @@ -37,8 +34,8 @@ export class KeymapExtensions implements IWorkbenchContribution { @IInstantiationService private instantiationService: IInstantiationService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @IExtensionTipsService private tipsService: IExtensionTipsService, - @IChoiceService private choiceService: IChoiceService, @ILifecycleService lifecycleService: ILifecycleService, + @INotificationService private notificationService: INotificationService, @ITelemetryService private telemetryService: ITelemetryService, ) { this.disposables.push( @@ -64,36 +61,37 @@ export class KeymapExtensions implements IWorkbenchContribution { }); } - private promptForDisablingOtherKeymaps(newKeymap: IExtensionStatus, oldKeymaps: IExtensionStatus[]): TPromise { - const message = localize('disableOtherKeymapsConfirmation', "Disable other keymaps ({0}) to avoid conflicts between keybindings?", oldKeymaps.map(k => `'${k.local.manifest.displayName}'`).join(', ')); - const options = [ - localize('yes', "Yes"), - localize('no', "No") - ]; - return this.choiceService.choose(Severity.Info, message, options) - .then(value => { - const confirmed = value === 0; - const telemetryData: { [key: string]: any; } = { - newKeymap: newKeymap.identifier, - oldKeymaps: oldKeymaps.map(k => k.identifier), - confirmed - }; - /* __GDPR__ - "disableOtherKeymaps" : { - "newKeymap" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "oldKeymaps": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "confirmed" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('disableOtherKeymaps', telemetryData); - if (confirmed) { - return TPromise.join(oldKeymaps.map(keymap => { - return this.extensionEnablementService.setEnablement(keymap.local, EnablementState.Disabled); - })); + private promptForDisablingOtherKeymaps(newKeymap: IExtensionStatus, oldKeymaps: IExtensionStatus[]): void { + const onPrompt = (confirmed: boolean) => { + const telemetryData: { [key: string]: any; } = { + newKeymap: newKeymap.identifier, + oldKeymaps: oldKeymaps.map(k => k.identifier), + confirmed + }; + /* __GDPR__ + "disableOtherKeymaps" : { + "newKeymap": { "${inline}": [ "${ExtensionIdentifier}" ] }, + "oldKeymaps": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "confirmed" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } - return undefined; - }, error => TPromise.wrapError(canceled())) - .then(() => { /* drop resolved value */ }); + */ + this.telemetryService.publicLog('disableOtherKeymaps', telemetryData); + if (confirmed) { + TPromise.join(oldKeymaps.map(keymap => { + return this.extensionEnablementService.setEnablement(keymap.local, EnablementState.Disabled); + })); + } + }; + + this.notificationService.prompt(Severity.Info, localize('disableOtherKeymapsConfirmation', "Disable other keymaps ({0}) to avoid conflicts between keybindings?", oldKeymaps.map(k => `'${k.local.manifest.displayName}'`).join(', ')), + [{ + label: localize('yes', "Yes"), + run: () => onPrompt(true) + }, { + label: localize('no', "No"), + run: () => onPrompt(false) + }] + ); } dispose(): void { @@ -144,29 +142,3 @@ export function isKeymapExtension(tipsService: IExtensionTipsService, extension: function stripVersion(id: string): string { return getIdAndVersionFromLocalExtensionId(id).id; } - -export class BetterMergeDisabled implements IWorkbenchContribution { - - constructor( - @IStorageService storageService: IStorageService, - @IChoiceService choiceService: IChoiceService, - @IExtensionService extensionService: IExtensionService, - @IExtensionManagementService extensionManagementService: IExtensionManagementService, - @ITelemetryService telemetryService: ITelemetryService, - ) { - extensionService.whenInstalledExtensionsRegistered().then(() => { - if (storageService.getBoolean(BetterMergeDisabledNowKey, StorageScope.GLOBAL, false)) { - storageService.remove(BetterMergeDisabledNowKey, StorageScope.GLOBAL); - - choiceService.choose(Severity.Info, localize('betterMergeDisabled', "The Better Merge extension is now built-in, the installed extension was disabled and can be uninstalled."), [localize('uninstall', "Uninstall")]).then(choice => { - if (choice === 0) { - extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => { - return Promise.all(extensions.filter(e => stripVersion(e.identifier.id) === BetterMergeId) - .map(e => extensionManagementService.uninstall(e, true))); - }); - } - }); - } - }); - } -} diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index b1679a40f2..3c25db9db5 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -12,8 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { isPromiseCanceledError, onUnexpectedError, create as createError } from 'vs/base/common/errors'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Builder, Dimension } from 'vs/base/browser/builder'; -import EventOf, { mapEvent, chain } from 'vs/base/common/event'; +import { Event as EventOf, mapEvent, chain } from 'vs/base/common/event'; import { IAction } from 'vs/base/common/actions'; import { domEvent } from 'vs/base/browser/event'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -21,7 +20,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { append, $, addStandardDisposableListener, EventType, addClass, removeClass, toggleClass } from 'vs/base/browser/dom'; +import { append, $, addStandardDisposableListener, EventType, addClass, removeClass, toggleClass, Dimension } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -33,7 +32,7 @@ import { } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { LocalExtensionType, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; -import { ExtensionsListView, InstalledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView } from './extensionsViews'; +import { ExtensionsListView, InstalledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView } from './extensionsViews'; import { OpenGlobalSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -52,7 +51,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { getGalleryExtensionIdFromLocal, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IPartService } from 'vs/workbench/services/part/common/partService'; @@ -68,65 +66,11 @@ const SearchBuiltInExtensionsContext = new RawContextKey('searchBuiltIn const RecommendedExtensionsContext = new RawContextKey('recommendedExtensions', false); const DefaultRecommendedExtensionsContext = new RawContextKey('defaultRecommendedExtensions', false); -export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtensionsViewlet { - - private onSearchChange: EventOf; - private nonEmptyWorkspaceContextKey: IContextKey; - private searchExtensionsContextKey: IContextKey; - private searchInstalledExtensionsContextKey: IContextKey; - private searchBuiltInExtensionsContextKey: IContextKey; - private recommendedExtensionsContextKey: IContextKey; - private defaultRecommendedExtensionsContextKey: IContextKey; - - private searchDelayer: ThrottledDelayer; - private root: HTMLElement; - - private searchBox: HTMLInputElement; - private extensionsBox: HTMLElement; - private primaryActions: IAction[]; - private secondaryActions: IAction[]; - private disposables: IDisposable[] = []; +export class ExtensionsViewletViewsContribution implements IWorkbenchContribution { constructor( - @IPartService partService: IPartService, - @ITelemetryService telemetryService: ITelemetryService, - @IProgressService private progressService: IProgressService, - @IInstantiationService instantiationService: IInstantiationService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IEditorGroupService private editorInputService: IEditorGroupService, - @IExtensionManagementService private extensionManagementService: IExtensionManagementService, - @INotificationService private notificationService: INotificationService, - @IViewletService private viewletService: IViewletService, - @IThemeService themeService: IThemeService, - @IConfigurationService private configurationService: IConfigurationService, - @IStorageService storageService: IStorageService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @IContextKeyService contextKeyService: IContextKeyService, - @IContextMenuService contextMenuService: IContextMenuService, - @IExtensionService extensionService: IExtensionService ) { - super(VIEWLET_ID, ViewLocation.Extensions, `${VIEWLET_ID}.state`, true, partService, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService); - this.registerViews(); - this.searchDelayer = new ThrottledDelayer(500); - this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService); - this.searchExtensionsContextKey = SearchExtensionsContext.bindTo(contextKeyService); - this.searchInstalledExtensionsContextKey = SearchInstalledExtensionsContext.bindTo(contextKeyService); - this.searchBuiltInExtensionsContextKey = SearchBuiltInExtensionsContext.bindTo(contextKeyService); - this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService); - this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService); - this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue(ShowRecommendationsOnlyOnDemandKey)); - this.disposables.push(this.viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables)); - - this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { - this.secondaryActions = null; - this.updateTitleArea(); - } - if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) { - this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue(ShowRecommendationsOnlyOnDemandKey)); - } - }, this, this.disposables); } private registerViews(): void { @@ -135,6 +79,8 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens viewDescriptors.push(this.createInstalledExtensionsListViewDescriptor()); viewDescriptors.push(this.createSearchInstalledExtensionsListViewDescriptor()); viewDescriptors.push(this.createSearchBuiltInExtensionsListViewDescriptor()); + viewDescriptors.push(this.createSearchBuiltInBasicsExtensionsListViewDescriptor()); + viewDescriptors.push(this.createSearchBuiltInThemesExtensionsListViewDescriptor()); viewDescriptors.push(this.createDefaultRecommendedExtensionsListViewDescriptor()); viewDescriptors.push(this.createOtherRecommendedExtensionsListViewDescriptor()); viewDescriptors.push(this.createWorkspaceRecommendedExtensionsListViewDescriptor()); @@ -216,17 +162,103 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens private createSearchBuiltInExtensionsListViewDescriptor(): IViewDescriptor { return { id: 'extensions.builtInExtensionsList', - name: localize('builtInExtensions', "Built-In"), + name: localize('builtInExtensions', "Features"), location: ViewLocation.Extensions, ctor: BuiltInExtensionsView, when: ContextKeyExpr.has('searchBuiltInExtensions'), - weight: 100 + weight: 100, + canToggleVisibility: true }; } - async create(parent: Builder): TPromise { - parent.addClass('extensions-viewlet'); - this.root = parent.getHTMLElement(); + private createSearchBuiltInThemesExtensionsListViewDescriptor(): IViewDescriptor { + return { + id: 'extensions.builtInThemesExtensionsList', + name: localize('builtInThemesExtensions', "Themes"), + location: ViewLocation.Extensions, + ctor: BuiltInThemesExtensionsView, + when: ContextKeyExpr.has('searchBuiltInExtensions'), + weight: 100, + canToggleVisibility: true + }; + } + + private createSearchBuiltInBasicsExtensionsListViewDescriptor(): IViewDescriptor { + return { + id: 'extensions.builtInBasicsExtensionsList', + name: localize('builtInBasicsExtensions', "Programming Languages"), + location: ViewLocation.Extensions, + ctor: BuiltInBasicsExtensionsView, + when: ContextKeyExpr.has('searchBuiltInExtensions'), + weight: 100, + canToggleVisibility: true + }; + } +} + +export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtensionsViewlet { + + private onSearchChange: EventOf; + private nonEmptyWorkspaceContextKey: IContextKey; + private searchExtensionsContextKey: IContextKey; + private searchInstalledExtensionsContextKey: IContextKey; + private searchBuiltInExtensionsContextKey: IContextKey; + private recommendedExtensionsContextKey: IContextKey; + private defaultRecommendedExtensionsContextKey: IContextKey; + + private searchDelayer: ThrottledDelayer; + private root: HTMLElement; + + private searchBox: HTMLInputElement; + private extensionsBox: HTMLElement; + private primaryActions: IAction[]; + private secondaryActions: IAction[]; + private disposables: IDisposable[] = []; + + constructor( + @IPartService partService: IPartService, + @ITelemetryService telemetryService: ITelemetryService, + @IProgressService private progressService: IProgressService, + @IInstantiationService instantiationService: IInstantiationService, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IEditorGroupService private editorInputService: IEditorGroupService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @INotificationService private notificationService: INotificationService, + @IViewletService private viewletService: IViewletService, + @IThemeService themeService: IThemeService, + @IConfigurationService private configurationService: IConfigurationService, + @IStorageService storageService: IStorageService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IContextKeyService contextKeyService: IContextKeyService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService + ) { + super(VIEWLET_ID, ViewLocation.Extensions, `${VIEWLET_ID}.state`, true, partService, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService); + + this.searchDelayer = new ThrottledDelayer(500); + this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService); + this.searchExtensionsContextKey = SearchExtensionsContext.bindTo(contextKeyService); + this.searchInstalledExtensionsContextKey = SearchInstalledExtensionsContext.bindTo(contextKeyService); + this.searchBuiltInExtensionsContextKey = SearchBuiltInExtensionsContext.bindTo(contextKeyService); + this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService); + this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService); + this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue(ShowRecommendationsOnlyOnDemandKey)); + this.disposables.push(this.viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables)); + + this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { + this.secondaryActions = null; + this.updateTitleArea(); + } + if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) { + this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue(ShowRecommendationsOnlyOnDemandKey)); + } + }, this, this.disposables); + } + + async create(parent: HTMLElement): TPromise { + addClass(parent, 'extensions-viewlet'); + this.root = parent; const header = append(this.root, $('.header')); @@ -253,7 +285,7 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens this.onSearchChange = mapEvent(onSearchInput, e => e.target.value); - await super.create(new Builder(this.extensionsBox)); + await super.create(this.extensionsBox); const installed = await this.extensionManagementService.getInstalled(LocalExtensionType.User); @@ -353,7 +385,7 @@ export class ExtensionsViewlet extends PersistentViewsViewlet implements IExtens private async doSearch(): TPromise { const value = this.searchBox.value || ''; this.searchExtensionsContextKey.set(!!value); - this.searchInstalledExtensionsContextKey.set(InstalledExtensionsView.isInsalledExtensionsQuery(value)); + this.searchInstalledExtensionsContextKey.set(InstalledExtensionsView.isInstalledExtensionsQuery(value)); this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value)); this.recommendedExtensionsContextKey.set(ExtensionsListView.isRecommendedExtensionsQuery(value)); this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY); @@ -490,7 +522,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution { @IExtensionManagementService private extensionsManagementService: IExtensionManagementService, @IWindowService private windowService: IWindowService, @ILogService private logService: ILogService, - @IChoiceService private choiceService: IChoiceService + @INotificationService private notificationService: INotificationService ) { this.loopCheckForMaliciousExtensions(); } @@ -511,13 +543,14 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution { if (maliciousExtensions.length) { return TPromise.join(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e, true).then(() => { - return this.choiceService.choose(Severity.Warning, localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", getGalleryExtensionIdFromLocal(e)), [localize('reloadNow', "Reload Now")]).then(choice => { - if (choice === 0) { - return this.windowService.reloadWindow(); - } - - return TPromise.as(undefined); - }); + this.notificationService.prompt( + Severity.Warning, + localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", getGalleryExtensionIdFromLocal(e)), + [{ + label: localize('reloadNow', "Reload Now"), + run: () => this.windowService.reloadWindow() + }] + ); }))); } else { return TPromise.as(null); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts index 33d5a7c7bd..fa0cfdadf5 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts @@ -145,25 +145,56 @@ export class ExtensionsListView extends ViewsViewletPanel { case 'name': options = assign(options, { sortBy: SortBy.Title }); break; } - if (!value || ExtensionsListView.isBuiltInExtensionsQuery(value)) { - // Show installed extensions - value = value ? value.replace(/@builtin/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase() : ''; + if (/@builtin/i.test(value)) { + const showThemesOnly = /@builtin:themes/i.test(value); + if (showThemesOnly) { + value = value.replace(/@builtin:themes/g, ''); + } + const showBasicsOnly = /@builtin:basics/i.test(value); + if (showBasicsOnly) { + value = value.replace(/@builtin:basics/g, ''); + } + const showFeaturesOnly = /@builtin:features/i.test(value); + if (showFeaturesOnly) { + value = value.replace(/@builtin:features/g, ''); + } + value = value.replace(/@builtin/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase(); let result = await this.extensionsWorkbenchService.queryLocal(); result = result .filter(e => e.type === LocalExtensionType.System && (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)); - const themesExtensions = result.filter(e => { - return e.local.manifest - && e.local.manifest.contributes - && Array.isArray(e.local.manifest.contributes.themes) - && e.local.manifest.contributes.themes.length; - }); - const themesExtensionsIds = themesExtensions.map(e => e.id); - const others = result.filter(e => themesExtensionsIds.indexOf(e.id) === -1); + if (showThemesOnly) { + const themesExtensions = result.filter(e => { + return e.local.manifest + && e.local.manifest.contributes + && Array.isArray(e.local.manifest.contributes.themes) + && e.local.manifest.contributes.themes.length; + }); + return new PagedModel(this.sortExtensions(themesExtensions, options)); + } + if (showBasicsOnly) { + const basics = result.filter(e => { + return e.local.manifest + && e.local.manifest.contributes + && Array.isArray(e.local.manifest.contributes.languages) + && e.local.manifest.contributes.languages.length + && e.local.identifier.id !== 'git'; + }); + return new PagedModel(this.sortExtensions(basics, options)); + } + if (showFeaturesOnly) { + const others = result.filter(e => { + return e.local.manifest + && e.local.manifest.contributes + && (!Array.isArray(e.local.manifest.contributes.languages) || e.local.identifier.id === 'git') + && !Array.isArray(e.local.manifest.contributes.themes); + }); + return new PagedModel(this.sortExtensions(others, options)); + } - return new PagedModel([...this.sortExtensions(others, options), ...this.sortExtensions(themesExtensions, options)]); + return new PagedModel(this.sortExtensions(result, options)); } if (!value || ExtensionsListView.isInstalledExtensionsQuery(value)) { @@ -173,12 +204,12 @@ export class ExtensionsListView extends ViewsViewletPanel { let result = await this.extensionsWorkbenchService.queryLocal(); result = result - .filter(e => e.type === LocalExtensionType.User && e.name.toLowerCase().indexOf(value) > -1); + .filter(e => e.type === LocalExtensionType.User && (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)); return new PagedModel(this.sortExtensions(result, options)); } - const idMatch = /@id:([a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*)/.exec(value); + const idMatch = /@id:(([a-z0-9A-Z][a-z0-9\-A-Z]*)\.([a-z0-9A-Z][a-z0-9\-A-Z]*))/.exec(value); if (idMatch) { const name = idMatch[1]; @@ -193,7 +224,7 @@ export class ExtensionsListView extends ViewsViewletPanel { const local = await this.extensionsWorkbenchService.queryLocal(); const result = local .sort((e1, e2) => e1.displayName.localeCompare(e2.displayName)) - .filter(extension => extension.outdated && extension.name.toLowerCase().indexOf(value) > -1); + .filter(extension => extension.outdated && (extension.name.toLowerCase().indexOf(value) > -1 || extension.displayName.toLowerCase().indexOf(value) > -1)); return new PagedModel(this.sortExtensions(result, options)); } @@ -206,7 +237,7 @@ export class ExtensionsListView extends ViewsViewletPanel { const result = local .sort((e1, e2) => e1.displayName.localeCompare(e2.displayName)) - .filter(e => runningExtensions.every(r => !areSameExtensions(r, e)) && e.name.toLowerCase().indexOf(value) > -1); + .filter(e => runningExtensions.every(r => !areSameExtensions(r, e)) && (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)); return new PagedModel(this.sortExtensions(result, options)); } @@ -220,7 +251,7 @@ export class ExtensionsListView extends ViewsViewletPanel { .sort((e1, e2) => e1.displayName.localeCompare(e2.displayName)) .filter(e => e.type === LocalExtensionType.User && (e.enablementState === EnablementState.Enabled || e.enablementState === EnablementState.WorkspaceEnabled) && - e.name.toLowerCase().indexOf(value) > -1 + (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1) ); return new PagedModel(this.sortExtensions(result, options)); @@ -310,7 +341,7 @@ export class ExtensionsListView extends ViewsViewletPanel { /* __GDPR__ "extensionAllRecommendations:open" : { - "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('extensionAllRecommendations:open', { count: names.length }); @@ -348,7 +379,7 @@ export class ExtensionsListView extends ViewsViewletPanel { /* __GDPR__ "extensionRecommendations:open" : { - "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('extensionRecommendations:open', { count: names.length }); @@ -438,7 +469,7 @@ export class ExtensionsListView extends ViewsViewletPanel { const names = recommendations.filter(name => name.toLowerCase().indexOf(value) > -1); /* __GDPR__ "extensionWorkspaceRecommendations:open" : { - "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('extensionWorkspaceRecommendations:open', { count: names.length }); @@ -529,7 +560,7 @@ export class ExtensionsListView extends ViewsViewletPanel { } static isBuiltInExtensionsQuery(query: string): boolean { - return /@builtin/i.test(query); + return /^\s*@builtin\s*$/i.test(query); } static isInstalledExtensionsQuery(query: string): boolean { @@ -572,7 +603,7 @@ export class ExtensionsListView extends ViewsViewletPanel { export class InstalledExtensionsView extends ExtensionsListView { - public static isInsalledExtensionsQuery(query: string): boolean { + public static isInstalledExtensionsQuery(query: string): boolean { return ExtensionsListView.isInstalledExtensionsQuery(query) || ExtensionsListView.isOutdatedExtensionsQuery(query) || ExtensionsListView.isDisabledExtensionsQuery(query) @@ -580,7 +611,7 @@ export class InstalledExtensionsView extends ExtensionsListView { } async show(query: string): TPromise> { - if (InstalledExtensionsView.isInsalledExtensionsQuery(query)) { + if (InstalledExtensionsView.isInstalledExtensionsQuery(query)) { return super.show(query); } let searchInstalledQuery = '@installed'; @@ -592,12 +623,22 @@ export class InstalledExtensionsView extends ExtensionsListView { export class BuiltInExtensionsView extends ExtensionsListView { async show(query: string): TPromise> { - if (!ExtensionsListView.isBuiltInExtensionsQuery(query)) { - return super.show(query); - } - let searchBuiltInQuery = '@builtin'; - searchBuiltInQuery = query ? searchBuiltInQuery + ' ' + query : searchBuiltInQuery; - return super.show(searchBuiltInQuery); + return super.show(query.replace('@builtin', '@builtin:features')); + } + +} + +export class BuiltInThemesExtensionsView extends ExtensionsListView { + + async show(query: string): TPromise> { + return super.show(query.replace('@builtin', '@builtin:themes')); + } +} + +export class BuiltInBasicsExtensionsView extends ExtensionsListView { + + async show(query: string): TPromise> { + return super.show(query.replace('@builtin', '@builtin:basics')); } } diff --git a/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css b/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css similarity index 99% rename from src/vs/workbench/parts/extensions/browser/media/extensionEditor.css rename to src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css index 1390bc3ca2..2b92814931 100644 --- a/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css @@ -34,6 +34,7 @@ flex: 1; padding-left: 20px; overflow: hidden; + user-select: text; } .extension-editor > .header > .details > .title { @@ -57,7 +58,6 @@ padding: 0px 4px; border-radius: 4px; user-select: text; - -webkit-user-select: text; white-space: nowrap; } @@ -78,6 +78,7 @@ margin-left: 10px; padding: 0px 4px; border-radius: 4px; + user-select: none; } .extension-editor > .header > .details > .subtitle { diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css b/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css index 9f778efe37..7a95cc3314 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css @@ -191,10 +191,14 @@ opacity: 0.9; } -.extensions-viewlet > .extensions .extension.disabled > .icon, -.extensions-viewlet > .extensions .extension.disabled > .details > .header-container, -.extensions-viewlet > .extensions .extension.disabled > .details > .description -.extensions-viewlet > .extensions .extension.disabled > .details > .footer > .author { +.vs .extensions-viewlet > .extensions .extension.disabled > .icon, +.vs-dark .extensions-viewlet > .extensions .extension.disabled > .icon, +.vs .extensions-viewlet > .extensions .extension.disabled > .details > .header-container, +.vs-dark .extensions-viewlet > .extensions .extension.disabled > .details > .header-container, +.vs .extensions-viewlet > .extensions .extension.disabled > .details > .description, +.vs-dark .extensions-viewlet > .extensions .extension.disabled > .details > .description, +.vs .extensions-viewlet > .extensions .extension.disabled > .details > .footer > .author, +.vs-dark .extensions-viewlet > .extensions .extension.disabled > .details > .footer > .author { opacity: 0.5; } diff --git a/src/vs/workbench/parts/extensions/browser/media/markdown.css b/src/vs/workbench/parts/extensions/electron-browser/media/markdown.css similarity index 100% rename from src/vs/workbench/parts/extensions/browser/media/markdown.css rename to src/vs/workbench/parts/extensions/electron-browser/media/markdown.css diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css b/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css index 6a2fe98805..444f6587fe 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css @@ -70,7 +70,6 @@ .hc-black .monaco-action-bar .extension-host-profile-stop { background: url('profile-stop-inverse.svg') center center no-repeat; animation:fade 1000ms infinite; - -webkit-animation:fade 1000ms infinite; } .monaco-action-bar .save-extension-host-profile { @@ -101,17 +100,10 @@ height: 16px; vertical-align: middle; animation:fade 1000ms infinite; - -webkit-animation:fade 1000ms infinite; } @keyframes fade { from { opacity: 1.0; } 50% { opacity: 0.5; } to { opacity: 1.0; } -} - -@-webkit-keyframes fade { - from { opacity: 1.0; } - 50% { opacity: 0.5; } - to { opacity: 1.0; } } \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts index 7852a79d27..b4b8ceb89e 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -14,7 +14,6 @@ import { EditorInput } from 'vs/workbench/common/editor'; import pkg from 'vs/platform/node/package'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action, IAction } from 'vs/base/common/actions'; -import { Builder, Dimension } from 'vs/base/browser/builder'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -24,7 +23,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IExtensionService, IExtensionDescription, IExtensionsStatus, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; -import { append, $, addClass, toggleClass } from 'vs/base/browser/dom'; +import { append, $, addClass, toggleClass, Dimension } from 'vs/base/browser/dom'; import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -36,7 +35,7 @@ import { writeFile } from 'vs/base/node/pfs'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { memoize } from 'vs/base/common/decorators'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { DisableForWorkspaceAction, DisableGloballyAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -212,10 +211,8 @@ export class RuntimeExtensionsEditor extends BaseEditor { return result; } - protected createEditor(parent: Builder): void { - const container = parent.getHTMLElement(); - - addClass(container, 'runtime-extensions-editor'); + protected createEditor(parent: HTMLElement): void { + addClass(parent, 'runtime-extensions-editor'); const TEMPLATE_ID = 'runtimeExtensionElementTemplate'; @@ -299,7 +296,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime; data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`; data.actionbar.context = element; - toggleClass(data.actionbar.getContainer().getHTMLElement(), 'hidden', element.marketplaceInfo && element.marketplaceInfo.type === LocalExtensionType.User && (!element.description.repository || !element.description.repository.url)); + toggleClass(data.actionbar.getContainer(), 'hidden', element.marketplaceInfo && element.marketplaceInfo.type === LocalExtensionType.User && (!element.description.repository || !element.description.repository.url)); let title: string; if (activationTimes.activationEvent === '*') { @@ -307,15 +304,30 @@ export class RuntimeExtensionsEditor extends BaseEditor { } else if (/^workspaceContains:/.test(activationTimes.activationEvent)) { let fileNameOrGlob = activationTimes.activationEvent.substr('workspaceContains:'.length); if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) { - title = nls.localize('workspaceContainsGlobActivation', "Activated because a file matching {0} exists in your workspace", fileNameOrGlob); + title = nls.localize({ + key: 'workspaceContainsGlobActivation', + comment: [ + '{0} will be a glob pattern' + ] + }, "Activated because a file matching {0} exists in your workspace", fileNameOrGlob); } else { - title = nls.localize('workspaceContainsFileActivation', "Activated because file {0} exists in your workspace", fileNameOrGlob); + title = nls.localize({ + key: 'workspaceContainsFileActivation', + comment: [ + '{0} will be a file name' + ] + }, "Activated because file {0} exists in your workspace", fileNameOrGlob); } } else if (/^onLanguage:/.test(activationTimes.activationEvent)) { let language = activationTimes.activationEvent.substr('onLanguage:'.length); title = nls.localize('languageActivation', "Activated because you opened a {0} file", language); } else { - title = nls.localize('workspaceGenericActivation', "Activated on {0}", activationTimes.activationEvent); + title = nls.localize({ + key: 'workspaceGenericActivation', + comment: [ + 'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.' + ] + }, "Activated on {0}", activationTimes.activationEvent); } data.activationTime.title = title; if (!isFalsyOrEmpty(element.status.runtimeErrors)) { @@ -362,7 +374,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { } }; - this._list = this._instantiationService.createInstance(WorkbenchList, container, delegate, [renderer], { + this._list = this._instantiationService.createInstance(WorkbenchList, parent, delegate, [renderer], { multipleSelectionSupport: false }) as WorkbenchList; diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 961b7a8446..1b3e279f29 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -5,11 +5,11 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { readFile } from 'vs/base/node/pfs'; import * as semver from 'semver'; import * as path from 'path'; -import Event, { Emitter, chain } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { index } from 'vs/base/common/arrays'; import { assign } from 'vs/base/common/objects'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -30,12 +30,12 @@ import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IURLService } from 'vs/platform/url/common/url'; +import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; import product from 'vs/platform/node/product'; import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; interface IExtensionStateProvider { @@ -335,42 +335,20 @@ class ExtensionDependencies implements IExtensionDependencies { } } -enum Operation { - Installing, - Updating, - Uninstalling -} - -interface IActiveExtension { - operation: Operation; - extension: Extension; - start: Date; -} - -function toTelemetryEventName(operation: Operation) { - switch (operation) { - case Operation.Installing: return 'extensionGallery:install'; - case Operation.Updating: return 'extensionGallery:update'; - case Operation.Uninstalling: return 'extensionGallery:uninstall'; - } - - return ''; -} - -export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { +export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, IURLHandler { private static readonly SyncPeriod = 1000 * 60 * 60 * 12; // 12 hours _serviceBrand: any; private stateProvider: IExtensionStateProvider; - private installing: IActiveExtension[] = []; - private uninstalling: IActiveExtension[] = []; + private installing: Extension[] = []; + private uninstalling: Extension[] = []; private installed: Extension[] = []; private syncDelayer: ThrottledDelayer; private autoUpdateDelayer: ThrottledDelayer; private disposables: IDisposable[] = []; - private _onChange: Emitter = new Emitter(); + private readonly _onChange: Emitter = new Emitter(); get onChange(): Event { return this._onChange.event; } private _extensionAllowedBadgeProviders: string[]; @@ -382,8 +360,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { @IExtensionGalleryService private galleryService: IExtensionGalleryService, @IConfigurationService private configurationService: IConfigurationService, @ITelemetryService private telemetryService: ITelemetryService, + @IDialogService private dialogService: IDialogService, @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService, @IURLService urlService: IURLService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @IWindowService private windowService: IWindowService, @@ -402,9 +380,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { this.syncDelayer = new ThrottledDelayer(ExtensionsWorkbenchService.SyncPeriod); this.autoUpdateDelayer = new ThrottledDelayer(1000); - chain(urlService.onOpenURL) - .filter(uri => /^extension/.test(uri.path)) - .on(this.onOpenExtensionUrl, this, this.disposables); + urlService.registerHandler(this); this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(AutoUpdateConfigurationKey)) { @@ -420,8 +396,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { get local(): IExtension[] { const installing = this.installing - .filter(e => !this.installed.some(installed => installed.id === e.extension.id)) - .map(e => e.extension); + .filter(e => !this.installed.some(installed => installed.id === e.id)) + .map(e => e); return [...this.installed, ...installing]; } @@ -432,7 +408,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { this.installed = result.map(local => { const extension = installedById[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, local, null, this.telemetryService); extension.local = local; - extension.enablementState = this.extensionEnablementService.getEnablementState({ id: extension.id, uuid: extension.uuid }); + extension.enablementState = this.extensionEnablementService.getEnablementState(local); return extension; }); @@ -602,8 +578,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.progressService.withProgress({ location: ProgressLocation.Extensions, title: nls.localize('installingVSIXExtension', 'Installing extension from VSIX...'), - tooltip: `${extension}` - }, () => this.extensionService.install(extension)); + source: `${extension}` + }, () => this.extensionService.install(extension).then(() => null)); } if (!(extension instanceof Extension)) { @@ -624,13 +600,13 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.progressService.withProgress({ location: ProgressLocation.Extensions, title: nls.localize('installingMarketPlaceExtension', 'Installing extension from Marketplace....'), - tooltip: `${extension.id}` + source: `${extension.id}` // {{SQL CARBON EDIT}} }, () => this.downloadOrBrowse(ext)); } // {{SQL CARBON EDIT}} - private downloadOrBrowse(ext: Extension): TPromise { + private downloadOrBrowse(ext: Extension): TPromise { if (ext.gallery.assets.downloadPage && ext.gallery.assets.downloadPage.uri) { window.open(ext.gallery.assets.downloadPage.uri); return TPromise.wrap(void 0); @@ -676,7 +652,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.progressService.withProgress({ location: ProgressLocation.Extensions, title: nls.localize('uninstallingExtension', 'Uninstalling extension....'), - tooltip: `${local.identifier.id}` + source: `${local.identifier.id}` }, () => this.extensionService.uninstall(local)); } @@ -694,8 +670,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.progressService.withProgress({ location: ProgressLocation.Extensions, - tooltip: `${local.identifier.id}` - }, () => this.extensionService.reinstall(local)); + source: `${local.identifier.id}` + }, () => this.extensionService.reinstallFromGallery(local).then(() => null)); } private promptAndSetEnablement(extension: IExtension, enablementState: EnablementState, enable: boolean): TPromise { @@ -712,11 +688,11 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { private promptForDependenciesAndEnable(extension: IExtension, dependencies: IExtension[], enablementState: EnablementState, enable: boolean): TPromise { const message = nls.localize('enableDependeciesConfirmation', "Enabling '{0}' also enables its dependencies. Would you like to continue?", extension.displayName); - const options = [ + const buttons = [ nls.localize('enable', "Yes"), nls.localize('doNotEnable', "No") ]; - return this.choiceService.choose(Severity.Info, message, options, 1, true) + return this.dialogService.show(Severity.Info, message, buttons, { cancelId: 1 }) .then(value => { if (value === 0) { return this.checkAndSetEnablement(extension, dependencies, enablementState, enable); @@ -727,12 +703,12 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { private promptForDependenciesAndDisable(extension: IExtension, dependencies: IExtension[], enablementState: EnablementState, enable: boolean): TPromise { const message = nls.localize('disableDependeciesConfirmation', "Would you like to disable '{0}' only or its dependencies also?", extension.displayName); - const options = [ + const buttons = [ nls.localize('disableOnly', "Only"), nls.localize('disableAll', "All"), nls.localize('cancel', "Cancel") ]; - return this.choiceService.choose(Severity.Info, message, options, 2, true) + return this.dialogService.show(Severity.Info, message, buttons, { cancelId: 2 }) .then(value => { if (value === 0) { return this.checkAndSetEnablement(extension, [], enablementState, enable); @@ -837,43 +813,29 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { extension.gallery = gallery; - const start = new Date(); - const operation = Operation.Installing; - this.installing.push({ operation, extension, start }); + this.installing.push(extension); this._onChange.fire(); } private onDidInstallExtension(event: DidInstallExtensionEvent): void { const { local, zipPath, error, gallery } = event; - const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e.extension, gallery.identifier))[0] : null; - const extension: Extension = installingExtension ? installingExtension.extension : zipPath ? new Extension(this.galleryService, this.stateProvider, null, null, this.telemetryService) : null; + const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e, gallery.identifier))[0] : null; + const extension: Extension = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, null, null, this.telemetryService) : null; if (extension) { this.installing = installingExtension ? this.installing.filter(e => e !== installingExtension) : this.installing; - - if (error) { - if (extension.gallery) { - // Updating extension can be only a gallery extension - const installed = this.installed.filter(e => e.id === extension.id)[0]; - if (installed && installingExtension) { - installingExtension.operation = Operation.Updating; - } - } - } else { + const installed = this.installed.filter(e => e.id === extension.id)[0]; + if (!error) { extension.local = local; - const installed = this.installed.filter(e => e.id === extension.id)[0]; if (installed) { - if (installingExtension) { - installingExtension.operation = Operation.Updating; - } installed.local = local; } else { this.installed.push(extension); } } - if (extension.gallery) { - // Report telemetry only for gallery extensions - this.reportTelemetry(installingExtension, error); + if (extension.gallery && !installed) { + // Report recommendation telemetry only for gallery extensions that are first time installs + this.reportExtensionRecommendationsTelemetry(installingExtension); } } this._onChange.fire(); @@ -888,10 +850,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return; } - const start = new Date(); - const operation = Operation.Uninstalling; - const uninstalling = this.uninstalling.filter(e => e.extension.local.identifier.id === id)[0] || { id, operation, extension, start }; - this.uninstalling = [uninstalling, ...this.uninstalling.filter(e => e.extension.local.identifier.id !== id)]; + const uninstalling = this.uninstalling.filter(e => e.local.identifier.id === id)[0] || extension; + this.uninstalling = [uninstalling, ...this.uninstalling.filter(e => e.local.identifier.id !== id)]; this._onChange.fire(); } @@ -902,23 +862,19 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { this.installed = this.installed.filter(e => e.local.identifier.id !== id); } - const uninstalling = this.uninstalling.filter(e => e.extension.local.identifier.id === id)[0]; - this.uninstalling = this.uninstalling.filter(e => e.extension.local.identifier.id !== id); + const uninstalling = this.uninstalling.filter(e => e.local.identifier.id === id)[0]; + this.uninstalling = this.uninstalling.filter(e => e.local.identifier.id !== id); if (!uninstalling) { return; } - if (!error) { - this.reportTelemetry(uninstalling); - } - this._onChange.fire(); } - private onEnablementChanged(extensionIdentifier: IExtensionIdentifier) { - const [extension] = this.local.filter(e => areSameExtensions(e, extensionIdentifier)); + private onEnablementChanged(identifier: IExtensionIdentifier) { + const [extension] = this.local.filter(e => areSameExtensions(e, identifier)); if (extension) { - const enablementState = this.extensionEnablementService.getEnablementState({ id: extension.id, uuid: extension.uuid }); + const enablementState = this.extensionEnablementService.getEnablementState(extension.local); if (enablementState !== extension.enablementState) { extension.enablementState = enablementState; this._onChange.fire(); @@ -927,11 +883,11 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } private getExtensionState(extension: Extension): ExtensionState { - if (extension.gallery && this.installing.some(e => e.extension.gallery && areSameExtensions(e.extension.gallery.identifier, extension.gallery.identifier))) { + if (extension.gallery && this.installing.some(e => e.gallery && areSameExtensions(e.gallery.identifier, extension.gallery.identifier))) { return ExtensionState.Installing; } - if (this.uninstalling.some(e => e.extension.id === extension.id)) { + if (this.uninstalling.some(e => e.id === extension.id)) { return ExtensionState.Uninstalling; } @@ -939,46 +895,22 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return local ? ExtensionState.Installed : ExtensionState.Uninstalled; } - private reportTelemetry(active: IActiveExtension, errorcode?: string): void { - const data = active.extension.telemetryData; - const duration = new Date().getTime() - active.start.getTime(); - const eventName = toTelemetryEventName(active.operation); + private reportExtensionRecommendationsTelemetry(extension: Extension): void { const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason() || {}; - const recommendationsData = extRecommendations[active.extension.id.toLowerCase()] ? { recommendationReason: extRecommendations[active.extension.id.toLowerCase()].reasonId } : {}; - /* __GDPR__ - "extensionGallery:install" : { - "success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "${include}": [ - "${GalleryExtensionTelemetryData}" - ] - } - */ - /* __GDPR__ - "extensionGallery:update" : { - "success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "${include}": [ - "${GalleryExtensionTelemetryData}" - ] - } - */ - /* __GDPR__ - "extensionGallery:uninstall" : { - "success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "${include}": [ - "${GalleryExtensionTelemetryData}" - ] - } - */ - this.telemetryService.publicLog(eventName, assign(data, { success: !errorcode, duration, errorcode }, recommendationsData)); + const recommendationReason = extRecommendations[extension.id.toLowerCase()]; + if (recommendationReason) { + const recommendationsData = { recommendationReason: recommendationReason.reasonId }; + const data = extension.telemetryData; + /* __GDPR__ + "extensionGallery:install:recommendations" : { + "recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "${include}": [ + "${GalleryExtensionTelemetryData}" + ] + } + */ + this.telemetryService.publicLog('extensionGallery:install:recommendations', assign(data, recommendationsData)); + } } private onError(err: any): void { @@ -995,6 +927,15 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { this.notificationService.error(err); } + async handleURL(uri: URI): TPromise { + if (!/^extension/.test(uri.path)) { + return false; + } + + this.onOpenExtensionUrl(uri); + return true; + } + private onOpenExtensionUrl(uri: URI): void { const match = /^extension\/([^/]+)$/.exec(uri.path); @@ -1021,17 +962,14 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return this.windowService.show().then(() => { return this.open(extension).then(() => { - const message = nls.localize('installConfirmation', "Would you like to install the '{0}' extension?", extension.displayName, extension.publisher); - const options = [ - nls.localize('install', "Install") - ]; - return this.choiceService.choose(Severity.Info, message, options).then(value => { - if (value === 0) { - return this.install(extension); - } - - return TPromise.as(null); - }); + this.notificationService.prompt( + Severity.Info, + nls.localize('installConfirmation', "Would you like to install the '{0}' extension?", extension.displayName, extension.publisher), + [{ + label: nls.localize('install', "Install"), + run: () => this.install(extension).done(undefined, error => this.onError(error)) + }] + ); }); }); }); diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts index 7f2e32e1ad..8c27b21f8e 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts @@ -33,6 +33,7 @@ import { TestContextService, TestWindowService } from 'vs/workbench/test/workben import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IWindowService } from 'vs/platform/windows/common/windows'; +import { URLService } from 'vs/platform/url/common/urlService'; suite('ExtensionsActions Test', () => { @@ -51,7 +52,6 @@ suite('ExtensionsActions Test', () => { didUninstallEvent = new Emitter(); instantiationService = new TestInstantiationService(); - instantiationService.stub(IURLService, { onOpenURL: new Emitter().event }); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(ILogService, NullLogService); instantiationService.stub(IWindowService, TestWindowService); @@ -71,6 +71,7 @@ suite('ExtensionsActions Test', () => { instantiationService.stub(IExtensionTipsService, ExtensionTipsService); instantiationService.stub(IExtensionTipsService, 'getKeymapRecommendations', () => []); + instantiationService.stub(IURLService, URLService); }); setup(() => { diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts index 674ea7914a..28bf05be1e 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts @@ -10,7 +10,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; import { TPromise } from 'vs/base/common/winjs.base'; -import uuid = require('vs/base/common/uuid'); +import * as uuid from 'vs/base/common/uuid'; import { mkdirp } from 'vs/base/node/pfs'; import { IExtensionGalleryService, IGalleryExtensionAssets, IGalleryExtension, IExtensionManagementService, LocalExtensionType, @@ -23,18 +23,18 @@ import { Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { TestTextResourceConfigurationService, TestContextService, TestLifecycleService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices'; +import { TestTextResourceConfigurationService, TestContextService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import URI from 'vs/base/common/uri'; import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { IFileService } from 'vs/platform/files/common/files'; -import { FileService } from 'vs/workbench/services/files/node/fileService'; -import extfs = require('vs/base/node/extfs'); +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; +import * as extfs from 'vs/base/node/extfs'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IPager } from 'vs/base/common/paging'; import { assign } from 'vs/base/common/objects'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { generateUuid } from 'vs/base/common/uuid'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IExtensionsWorkbenchService, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; @@ -46,7 +46,8 @@ import product from 'vs/platform/node/product'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService, Severity, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { URLService } from 'vs/platform/url/common/urlService'; const mockExtensionGallery: IGalleryExtension[] = [ aGalleryExtension('MockExtension1', { @@ -155,7 +156,7 @@ function aGalleryExtension(name: string, properties: any = {}, galleryExtensionP assign(galleryExtension, { name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {} }, properties); assign(galleryExtension.properties, { dependencies: [] }, galleryExtensionProperties); assign(galleryExtension.assets, assets); - galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; + galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: uuid.generateUuid() }; return galleryExtension; } diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index c117790e83..895a8db04b 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -24,7 +24,7 @@ import { TestExtensionEnablementService } from 'vs/platform/extensionManagement/ import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { IURLService } from 'vs/platform/url/common/url'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IPager } from 'vs/base/common/paging'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; @@ -35,7 +35,9 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IProgressService2 } from 'vs/platform/progress/common/progress'; import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { URLService } from 'vs/platform/url/common/urlService'; suite('ExtensionsWorkbenchService Test', () => { @@ -54,13 +56,13 @@ suite('ExtensionsWorkbenchService Test', () => { didUninstallEvent = new Emitter(); instantiationService = new TestInstantiationService(); - instantiationService.stub(IURLService, { onOpenURL: new Emitter().event }); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(ILogService, NullLogService); instantiationService.stub(IWindowService, TestWindowService); instantiationService.stub(IProgressService2, ProgressService2); instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); + instantiationService.stub(IURLService, URLService); instantiationService.stub(IWorkspaceContextService, new TestContextService()); instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, onDidChangeConfiguration: () => { }, getConfiguration: () => ({}) }); @@ -76,14 +78,16 @@ suite('ExtensionsWorkbenchService Test', () => { instantiationService.stub(IExtensionTipsService, ExtensionTipsService); instantiationService.stub(IExtensionTipsService, 'getKeymapRecommendations', () => []); - instantiationService.stub(IChoiceService, { choose: () => null }); + instantiationService.stub(INotificationService, { prompt: () => null }); + instantiationService.stub(IDialogService, { show: () => TPromise.as(0) }); }); setup(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []); instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage()); - instantiationService.stubPromise(IChoiceService, 'choose', 0); + instantiationService.stub(IDialogService, { show: () => TPromise.as(0) }); + instantiationService.stubPromise(INotificationService, 'prompt', 0); (instantiationService.get(IExtensionEnablementService)).reset(); }); @@ -854,7 +858,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) @@ -909,7 +913,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); return testObject.setEnablement(testObject.local[0], EnablementState.Disabled).then(() => assert.fail('Should fail'), error => assert.ok(true)); }); @@ -925,7 +929,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Disabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); @@ -947,7 +951,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); @@ -969,7 +973,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); @@ -988,7 +992,7 @@ suite('ExtensionsWorkbenchService Test', () => { .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) .then(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + instantiationService.stubPromise(IDialogService, 'show', 1); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedback.ts b/src/vs/workbench/parts/feedback/electron-browser/feedback.ts index 34e7394e5a..c2cb498131 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedback.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedback.ts @@ -6,7 +6,7 @@ 'use strict'; import 'vs/css!./media/feedback'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Builder, $ } from 'vs/base/browser/builder'; import { Dropdown } from 'vs/base/browser/ui/dropdown/dropdown'; @@ -17,10 +17,12 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import * as errors from 'vs/base/common/errors'; import { IIntegrityService } from 'vs/platform/integrity/common/integrity'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { attachStylerCallback } from 'vs/platform/theme/common/styler'; -import { editorWidgetBackground, widgetShadow, inputBorder, inputForeground, inputBackground, inputActiveOptionBorder, editorBackground, buttonBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { attachButtonStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; +import { editorWidgetBackground, widgetShadow, inputBorder, inputForeground, inputBackground, inputActiveOptionBorder, editorBackground, buttonBackground, contrastBorder, darken } from 'vs/platform/theme/common/colorRegistry'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry'; +import { IAnchor } from 'vs/base/browser/ui/contextview/contextview'; +import { Button } from 'vs/base/browser/ui/button/button'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; export const FEEDBACK_VISIBLE_CONFIG = 'workbench.statusBar.feedback.visible'; @@ -37,6 +39,7 @@ export interface IFeedbackService { export interface IFeedbackDropdownOptions { contextViewProvider: IContextViewService; feedbackService?: IFeedbackService; + onFeedbackVisibilityChange?: (visible: boolean) => void; } enum FormEvent { @@ -59,7 +62,8 @@ export class FeedbackDropdown extends Dropdown { private feedbackDescriptionInput: HTMLTextAreaElement; private smileyInput: Builder; private frownyInput: Builder; - private sendButton: Builder; + private sendButton: Button; + private $sendButton: Builder; private hideButton: HTMLInputElement; private remainingCharacterCount: Builder; @@ -69,7 +73,7 @@ export class FeedbackDropdown extends Dropdown { constructor( container: HTMLElement, - options: IFeedbackDropdownOptions, + private options: IFeedbackDropdownOptions, @ICommandService private commandService: ICommandService, @ITelemetryService private telemetryService: ITelemetryService, @IIntegrityService private integrityService: IIntegrityService, @@ -92,8 +96,8 @@ export class FeedbackDropdown extends Dropdown { } }); - this.element.addClass('send-feedback'); - this.element.title(nls.localize('sendFeedback', "Tweet Feedback")); + dom.addClass(this.element, 'send-feedback'); + this.element.title = nls.localize('sendFeedback', "Tweet Feedback"); this.feedbackService = options.feedbackService; @@ -108,10 +112,22 @@ export class FeedbackDropdown extends Dropdown { this.frownyInput = null; this.sendButton = null; + this.$sendButton = null; this.requestFeatureLink = product.sendASmile.requestFeatureUrl; } + protected getAnchor(): HTMLElement | IAnchor { + const res = dom.getDomNodePagePosition(this.element); + + return { + x: res.left, + y: res.top - 9, /* above the status bar */ + width: res.width, + height: res.height + } as IAnchor; + } + protected renderContents(container: HTMLElement): IDisposable { const $form = $('form.feedback-form').attr({ action: 'javascript:void(0);' @@ -123,7 +139,27 @@ export class FeedbackDropdown extends Dropdown { $('h2.title').text(nls.localize("label.sendASmile", "Tweet us your feedback.")).appendTo($form); - this.invoke($('div.cancel').attr('tabindex', '0'), () => { + const cancelBtn = $('div.cancel').attr('tabindex', '0'); + cancelBtn.on(dom.EventType.MOUSE_OVER, () => { + const theme = this.themeService.getTheme(); + let darkenFactor: number; + switch (theme.type) { + case 'light': + darkenFactor = 0.1; + break; + case 'dark': + darkenFactor = 0.2; + break; + } + + if (darkenFactor) { + cancelBtn.getHTMLElement().style.backgroundColor = darken(theme.getColor(editorWidgetBackground), darkenFactor)(theme).toString(); + } + }); + cancelBtn.on(dom.EventType.MOUSE_OUT, () => { + cancelBtn.getHTMLElement().style.backgroundColor = null; + }); + this.invoke(cancelBtn, () => { this.hide(); }).appendTo($form); @@ -213,25 +249,31 @@ export class FeedbackDropdown extends Dropdown { $('label').attr('for', 'hide-button').text(nls.localize('showFeedback', "Show Feedback Smiley in Status Bar")).appendTo($hideButtonContainer); - this.sendButton = this.invoke($('input.send').type('submit').attr('disabled', '').value(nls.localize('tweet', "Tweet")).appendTo($buttons), () => { + this.sendButton = new Button($buttons.getHTMLElement()); + this.sendButton.enabled = false; + this.sendButton.label = nls.localize('tweet', "Tweet"); + this.$sendButton = new Builder(this.sendButton.element); + this.$sendButton.addClass('send'); + this.toDispose.push(attachButtonStyler(this.sendButton, this.themeService)); + + this.invoke(this.$sendButton, () => { if (this.isSendingFeedback) { return; } - this.onSubmit(); }); this.toDispose.push(attachStylerCallback(this.themeService, { widgetShadow, editorWidgetBackground, inputBackground, inputForeground, inputBorder, editorBackground, contrastBorder }, colors => { - $form.style('background-color', colors.editorWidgetBackground); - $form.style('box-shadow', colors.widgetShadow ? `0 5px 8px ${colors.widgetShadow}` : null); + $form.style('background-color', colors.editorWidgetBackground ? colors.editorWidgetBackground.toString() : null); + $form.style('box-shadow', colors.widgetShadow ? `0 0 8px ${colors.widgetShadow}` : null); if (this.feedbackDescriptionInput) { - this.feedbackDescriptionInput.style.backgroundColor = colors.inputBackground; - this.feedbackDescriptionInput.style.color = colors.inputForeground; + this.feedbackDescriptionInput.style.backgroundColor = colors.inputBackground ? colors.inputBackground.toString() : null; + this.feedbackDescriptionInput.style.color = colors.inputForeground ? colors.inputForeground.toString() : null; this.feedbackDescriptionInput.style.border = `1px solid ${colors.inputBorder || 'transparent'}`; } - $contactUs.style('background-color', colors.editorBackground); + $contactUs.style('background-color', colors.editorBackground ? colors.editorBackground.toString() : null); $contactUs.style('border', `1px solid ${colors.contrastBorder || 'transparent'}`); })); @@ -256,7 +298,7 @@ export class FeedbackDropdown extends Dropdown { private updateCharCountText(): void { this.remainingCharacterCount.text(this.getCharCountText(this.feedbackDescriptionInput.value.length)); - this.feedbackDescriptionInput.value ? this.sendButton.removeAttribute('disabled') : this.sendButton.attr('disabled', ''); + this.sendButton.enabled = this.feedbackDescriptionInput.value.length > 0; } private setSentiment(smile: boolean): void { @@ -293,6 +335,20 @@ export class FeedbackDropdown extends Dropdown { return element; } + public show(): void { + super.show(); + + if (this.options.onFeedbackVisibilityChange) { + this.options.onFeedbackVisibilityChange(true); + } + } + + protected onHide(): void { + if (this.options.onFeedbackVisibilityChange) { + this.options.onFeedbackVisibilityChange(false); + } + } + public hide(): void { if (this.feedbackDescriptionInput) { this.feedback = this.feedbackDescriptionInput.value; @@ -339,25 +395,28 @@ export class FeedbackDropdown extends Dropdown { switch (event) { case FormEvent.SENDING: this.isSendingFeedback = true; - this.sendButton.setClass('send in-progress'); - this.sendButton.value(nls.localize('feedbackSending', "Sending")); + this.sendButton.label = nls.localize('feedbackSending', "Sending"); + this.$sendButton.addClass('in-progress'); break; case FormEvent.SENT: this.isSendingFeedback = false; - this.sendButton.setClass('send success').value(nls.localize('feedbackSent', "Thanks")); + this.sendButton.label = nls.localize('feedbackSent', "Thanks"); + this.$sendButton.addClass('success'); this.resetForm(); this.autoHideTimeout = setTimeout(() => { this.hide(); }, 1000); - this.sendButton.off(['click', 'keypress']); - this.invoke(this.sendButton, () => { + this.$sendButton.off(['click', 'keypress']); + this.invoke(this.$sendButton, () => { this.hide(); - this.sendButton.off(['click', 'keypress']); + this.$sendButton.off(['click', 'keypress']); + this.$sendButton.removeClass('in-progress'); }); break; case FormEvent.SEND_ERROR: this.isSendingFeedback = false; - this.sendButton.setClass('send error').value(nls.localize('feedbackSendingError', "Try again")); + this.$sendButton.addClass('error'); + this.sendButton.label = nls.localize('feedbackSendingError', "Try again"); break; } } diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts index 7a0d6fc47a..49f34d5ea2 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts @@ -7,7 +7,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; -import { FeedbackDropdown, IFeedback, IFeedbackService, FEEDBACK_VISIBLE_CONFIG } from 'vs/workbench/parts/feedback/electron-browser/feedback'; +import { FeedbackDropdown, IFeedback, IFeedbackService, FEEDBACK_VISIBLE_CONFIG, IFeedbackDropdownOptions } from 'vs/workbench/parts/feedback/electron-browser/feedback'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import product from 'vs/platform/node/product'; @@ -16,7 +16,7 @@ import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; -import { clearNode, EventHelper } from 'vs/base/browser/dom'; +import { clearNode, EventHelper, addClass, removeClass } from 'vs/base/browser/dom'; import { $ } from 'vs/base/browser/builder'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -95,7 +95,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { super.updateStyles(); if (this.dropdown) { - this.dropdown.label.style('background-color', this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); + $(this.dropdown.label).style('background-color', this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); } } @@ -130,8 +130,15 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { if (!this.dropdown) { this.dropdown = this.instantiationService.createInstance(FeedbackDropdown, this.container, { contextViewProvider: this.contextViewService, - feedbackService: this.instantiationService.createInstance(TwitterFeedbackService) - }); + feedbackService: this.instantiationService.createInstance(TwitterFeedbackService), + onFeedbackVisibilityChange: visible => { + if (visible) { + addClass(this.container, 'has-beak'); + } else { + removeClass(this.container, 'has-beak'); + } + } + } as IFeedbackDropdownOptions); this.toUnbind.push(this.dropdown); this.updateStyles(); @@ -167,6 +174,6 @@ class HideAction extends Action { registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND); if (statusBarItemHoverBackground) { - collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item .dropdown.send-feedback:hover { background-color: ${statusBarItemHoverBackground}; }`); + collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item .monaco-dropdown.send-feedback:hover { background-color: ${statusBarItemHoverBackground}; }`); } }); diff --git a/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css b/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css index 6b014f30c0..b1d31bb9e1 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css +++ b/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css @@ -100,23 +100,6 @@ text-align: right; } -.monaco-shell .feedback-form .send { - padding: .5em 1.5em; - font-size: 1.1em; - margin: 0; - box-sizing: border-box; - transition: width 200ms ease-out; -} - -.monaco-shell .feedback-form .send.in-progress { - width: 22%; -} - -.monaco-shell .feedback-form .send.success, -.monaco-shell .feedback-form .send.error { - width: 20%; -} - .monaco-shell .feedback-form .sentiment { height: 32px; width: 32px; @@ -131,11 +114,11 @@ } /* Statusbar */ -.monaco-shell .statusbar-item > .dropdown.send-feedback { +.monaco-shell .statusbar-item > .monaco-dropdown.send-feedback { display: inline-block; } -.monaco-shell .statusbar-item > .dropdown.send-feedback > .dropdown-label.send-feedback { +.monaco-shell .statusbar-item > .monaco-dropdown.send-feedback > .dropdown-label.send-feedback { -webkit-mask: url('smiley.svg') no-repeat 50% 50%; /* use mask to be able to change color dynamically */ width: 26px; } @@ -151,10 +134,6 @@ background: url('close.svg') center center no-repeat; } -.monaco-shell.vs .feedback-form .cancel:hover { - background-color: #eaeaea; -} - .monaco-shell .feedback-form .form-buttons { display: flex; } @@ -169,19 +148,14 @@ } .monaco-shell .feedback-form .form-buttons .send { - color: white; - border: none; - cursor: pointer; + width: auto; background-image: url('twitter.svg'); - background-color: #007ACC; - background-position: left; + background-position: 12px center; background-size: 20px; background-repeat: no-repeat; - padding-left: 30px; - padding-right: 12px; - border: 4px solid #007ACC; - border-radius: 4px; + padding: 8px 12px 8px 38px; margin-left: auto; + transition: width 200ms ease-out; } .monaco-shell .feedback-form .form-buttons .send.in-progress, @@ -221,10 +195,6 @@ background: url('close-dark.svg') center center no-repeat; } -.monaco-shell.vs-dark .feedback-form .cancel:hover { - background-color: rgba(30,30,30,0.8); -} - .monaco-shell .feedback-form .sentiment.smile { background-image: url('happy.svg'); background-position: center; @@ -264,13 +234,6 @@ padding: 10px; float: right; } -.monaco-shell.hc-black .feedback-form .cancel { - opacity: 0.6; -} - -.monaco-shell.hc-black .feedback-form .cancel:hover { - opacity: 1; -} .monaco-shell.hc-black .feedback-form .form-buttons .send, .monaco-shell.hc-black .feedback-form .form-buttons .send.in-progress, diff --git a/src/vs/workbench/parts/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/parts/files/browser/editors/binaryFileEditor.ts index 8d0c5e32a8..ae89cee1e2 100644 --- a/src/vs/workbench/parts/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/parts/files/browser/editors/binaryFileEditor.ts @@ -4,12 +4,17 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/binaryEditor'; -import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { onUnexpectedError } from 'vs/base/common/errors'; +import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput'; +import URI from 'vs/base/common/uri'; +import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; /** * An implementation of editor for binary files like images. @@ -21,12 +26,38 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { constructor( @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, - @IWindowsService windowsService: IWindowsService + @IWindowsService private windowsService: IWindowsService, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService ) { - super(BinaryFileEditor.ID, telemetryService, themeService, windowsService); + super( + BinaryFileEditor.ID, + { + openInternal: (input, options) => this.openInternal(input, options), + openExternal: resource => this.openExternal(resource) + }, + telemetryService, + themeService + ); + } + + private openInternal(input: EditorInput, options: EditorOptions): void { + if (input instanceof FileEditorInput) { + input.setForceOpenAsText(); + this.editorService.openEditor(input, options, this.position).done(null, onUnexpectedError); + } + } + + private openExternal(resource: URI): void { + this.windowsService.openExternal(resource.toString()).then(didOpen => { + if (!didOpen) { + return this.windowsService.showItemInFolder(resource.fsPath); + } + + return void 0; + }); } public getTitle(): string { return this.input ? this.input.getName() : nls.localize('binaryFileEditor', "Binary File Viewer"); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts index f4e70faaae..c16d1f70f2 100644 --- a/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts @@ -6,14 +6,13 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import { IEditorViewState } from 'vs/editor/common/editorCommon'; import { toResource, SideBySideEditorInput, IEditorGroup, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; -import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; import { ITextFileService, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; -import { FileOperationEvent, FileOperation, IFileService, FileChangeType, FileChangesEvent, indexOf } from 'vs/platform/files/common/files'; +import { FileOperationEvent, FileOperation, IFileService, FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -28,6 +27,8 @@ import { ResourceMap } from 'vs/base/common/map'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; export class FileEditorTracker implements IWorkbenchContribution { @@ -46,6 +47,7 @@ export class FileEditorTracker implements IWorkbenchContribution { @IEnvironmentService private environmentService: IEnvironmentService, @IConfigurationService private configurationService: IConfigurationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IWindowService private windowService: IWindowService ) { this.toUnbind = []; this.modelLoadQueue = new ResourceQueue(); @@ -67,6 +69,9 @@ export class FileEditorTracker implements IWorkbenchContribution { // Editor changing this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); + // Update visible editors when focus is gained + this.toUnbind.push(this.windowService.onDidChangeFocus(e => this.onWindowFocusChange(e))); + // Lifecycle this.lifecycleService.onShutdown(this.dispose, this); @@ -82,6 +87,24 @@ export class FileEditorTracker implements IWorkbenchContribution { } } + private onWindowFocusChange(focused: boolean): void { + if (focused) { + // the window got focus and we use this as a hint that files might have been changed outside + // of this window. since file events can be unreliable, we queue a load for models that + // are visible in any editor. since this is a fast operation in the case nothing has changed, + // we tolerate the additional work. + distinct( + this.editorService.getVisibleEditors() + .map(editor => { + const resource = toResource(editor.input, { supportSideBySide: true }); + return resource ? this.textFileService.models.get(resource) : void 0; + }) + .filter(model => model && !model.isDirty()), + m => m.getResource().toString() + ).forEach(model => this.queueModelLoad(model)); + } + } + // Note: there is some duplication with the other file event handler below. Since we cannot always rely on the disk events // carrying all necessary data in all environments, we also use the file operation events to make sure operations are handled. // In any case there is no guarantee if the local event is fired first or the disk one. Thus, code must handle the case @@ -208,7 +231,7 @@ export class FileEditorTracker implements IWorkbenchContribution { if (oldResource.toString() === resource.toString()) { reopenFileResource = newResource; // file got moved } else { - const index = indexOf(resource.path, oldResource.path, !isLinux /* ignorecase */); + const index = this.getIndexOfPath(resource.path, oldResource.path); reopenFileResource = newResource.with({ path: paths.join(newResource.path, resource.path.substr(index + oldResource.path.length + 1)) }); // parent folder got moved } @@ -229,7 +252,24 @@ export class FileEditorTracker implements IWorkbenchContribution { }); } - private getViewStateFor(resource: URI, group: IEditorGroup): IEditorViewState { + private getIndexOfPath(path: string, candidate: string): number { + if (candidate.length > path.length) { + return -1; + } + + if (path === candidate) { + return 0; + } + + if (!isLinux /* ignore case */) { + path = path.toLowerCase(); + candidate = candidate.toLowerCase(); + } + + return path.indexOf(candidate); + } + + private getViewStateFor(resource: URI, group: IEditorGroup): IEditorViewState | undefined { const stacks = this.editorGroupService.getStacksModel(); const editors = this.editorService.getVisibleEditors(); diff --git a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts index 286863d49d..6a6dcfab00 100644 --- a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts @@ -5,13 +5,13 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import types = require('vs/base/common/types'); -import paths = require('vs/base/common/paths'); +import * as types from 'vs/base/common/types'; +import * as paths from 'vs/base/common/paths'; import { Action } from 'vs/base/common/actions'; -import { VIEWLET_ID, TEXT_FILE_EDITOR_ID, IExplorerViewlet } from 'vs/workbench/parts/files/common/files'; +import { VIEWLET_ID, IExplorerViewlet, TEXT_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; import { ITextFileEditorModel, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { EditorOptions, TextEditorOptions, IEditorCloseEvent } from 'vs/workbench/common/editor'; @@ -24,10 +24,13 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { PreferencesEditor } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ScrollType } from 'vs/editor/common/editorCommon'; +import { IWindowsService } from 'vs/platform/windows/common/windows'; /** * An implementation of editor for file system resources. @@ -48,6 +51,8 @@ export class TextFileEditor extends BaseTextEditor { @IThemeService themeService: IThemeService, @IEditorGroupService editorGroupService: IEditorGroupService, @ITextFileService textFileService: ITextFileService, + @IWindowsService private windowsService: IWindowsService, + @IPreferencesService private preferencesService: IPreferencesService ) { super(TextFileEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorGroupService); @@ -165,6 +170,29 @@ export class TextFileEditor extends BaseTextEditor { })); } + if ((error).fileOperationResult === FileOperationResult.FILE_EXCEED_MEMORY_LIMIT) { + let memoryLimit = Math.max(2048, +this.configurationService.getValue(null, 'files.maxMemoryForLargeFilesMB') || 4096); + + return TPromise.wrapError(errors.create(toErrorMessage(error), { + actions: [ + new Action('workbench.window.action.relaunchWithIncreasedMemoryLimit', nls.localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), null, true, () => { + return this.windowsService.relaunch({ + addArgs: [ + `--max-memory=${memoryLimit}` + ] + }); + }), + new Action('workbench.window.action.configureMemoryLimit', nls.localize('configureMemoryLimit', 'Configure Memory Limit'), null, true, () => { + return this.preferencesService.openGlobalSettings().then(editor => { + if (editor instanceof PreferencesEditor) { + editor.focusSearch('files.maxMemoryForLargeFilesMB'); + } + }); + }) + ] + })); + } + // Otherwise make sure the error bubbles up return TPromise.wrapError(error); }); @@ -232,4 +260,4 @@ export class TextFileEditor extends BaseTextEditor { this.saveTextEditorViewState(input.getResource()); } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/files/browser/files.ts b/src/vs/workbench/parts/files/browser/files.ts index 26e97aa677..75f428da5b 100644 --- a/src/vs/workbench/parts/files/browser/files.ts +++ b/src/vs/workbench/parts/files/browser/files.ts @@ -8,23 +8,31 @@ import URI from 'vs/base/common/uri'; import { IListService } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { FileStat, OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem, OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; import { toResource } from 'vs/workbench/common/editor'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { List } from 'vs/base/browser/ui/list/listWidget'; -import { IFileStat } from 'vs/platform/files/common/files'; // Commands can get exeucted from a command pallete, from a context menu or from some list using a keybinding // To cover all these cases we need to properly compute the resource on which the command is being executed -export function getResourceForCommand(resource: URI, listService: IListService, editorService: IWorkbenchEditorService): URI { +export function getResourceForCommand(resource: URI | object, listService: IListService, editorService: IWorkbenchEditorService): URI { if (URI.isUri(resource)) { return resource; } - const list = listService.lastFocusedList; + let list = listService.lastFocusedList; if (list && list.isDOMFocused()) { - const focus = list.getFocus(); - if (focus instanceof FileStat) { + let focus: any; + if (list instanceof List) { + const focused = list.getFocusedElements(); + if (focused.length) { + focus = focused[0]; + } + } else { + focus = list.getFocus(); + } + + if (focus instanceof ExplorerItem) { return focus.resource; } else if (focus instanceof OpenEditor) { return focus.getResource(); @@ -34,31 +42,30 @@ export function getResourceForCommand(resource: URI, listService: IListService, return toResource(editorService.getActiveEditorInput(), { supportSideBySide: true }); } -export function getMultiSelectedResources(resource: URI, listService: IListService, editorService: IWorkbenchEditorService): URI[] { +export function getMultiSelectedResources(resource: URI | object, listService: IListService, editorService: IWorkbenchEditorService): URI[] { const list = listService.lastFocusedList; if (list && list.isDOMFocused()) { // Explorer if (list instanceof Tree) { - const focus: IFileStat = list.getFocus(); + const selection = list.getSelection().map((fs: ExplorerItem) => fs.resource); + const focus = list.getFocus(); + const mainUriStr = URI.isUri(resource) ? resource.toString() : focus instanceof ExplorerItem ? focus.resource.toString() : undefined; // If the resource is passed it has to be a part of the returned context. - if (focus && (!URI.isUri(resource) || focus.resource.toString() === resource.toString())) { - const selection = list.getSelection(); - // We only respect the selection if it contains the focused element. - if (selection && selection.indexOf(focus) >= 0) { - return selection.map(fs => fs.resource); - } + // We only respect the selection if it contains the focused element. + if (selection.some(s => s.toString() === mainUriStr)) { + return selection; } } + // Open editors view if (list instanceof List) { - const focus = list.getFocusedElements(); - // If the resource is passed it has to be a part of the returned context. - if (focus.length && (!URI.isUri(resource) || (focus[0] instanceof OpenEditor && focus[0].getResource().toString() === resource.toString()))) { - const selection = list.getSelectedElements(); - // We only respect the selection if it contains the focused element. - if (selection && selection.indexOf(focus[0]) >= 0) { - return selection.filter(s => s instanceof OpenEditor).map((oe: OpenEditor) => oe.getResource()); - } + const selection = list.getSelectedElements().filter(s => s instanceof OpenEditor).map((oe: OpenEditor) => oe.getResource()); + const focusedElements = list.getFocusedElements(); + const focus = focusedElements.length ? focusedElements[0] : undefined; + const mainUriStr = URI.isUri(resource) ? resource.toString() : (focus instanceof OpenEditor) ? focus.getResource().toString() : undefined; + // We only respect the selection if it contains the main element. + if (selection.some(s => s.toString() === mainUriStr)) { + return selection; } } } diff --git a/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts b/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts index 98ffa92e29..8df151710d 100644 --- a/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts +++ b/src/vs/workbench/parts/files/common/dirtyFilesTracker.ts @@ -5,8 +5,8 @@ 'use strict'; -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; import { TextFileModelChangeEvent, ITextFileService, AutoSaveMode, ModelState } from 'vs/workbench/services/textfile/common/textfiles'; @@ -21,7 +21,7 @@ import URI from 'vs/base/common/uri'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import arrays = require('vs/base/common/arrays'); +import * as arrays from 'vs/base/common/arrays'; export class DirtyFilesTracker implements IWorkbenchContribution { private isDocumentedEdited: boolean; diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index 18c2be403f..c6cff8a7e5 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -7,15 +7,14 @@ import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { memoize } from 'vs/base/common/decorators'; -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); -import labels = require('vs/base/common/labels'); +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; +import * as labels from 'vs/base/common/labels'; import URI from 'vs/base/common/uri'; import { EncodingMode, ConfirmResult, EditorInput, IFileEditorInput, ITextEditorModel } from 'vs/workbench/common/editor'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; -import { BINARY_FILE_EDITOR_ID, TEXT_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID } from 'vs/workbench/parts/files/common/files'; import { ITextFileService, AutoSaveMode, ModelState, TextFileModelChangeEvent } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -25,12 +24,15 @@ import { Verbosity, IRevertOptions } from 'vs/platform/editor/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; +import { FILE_EDITOR_INPUT_ID, TEXT_FILE_EDITOR_ID, BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; /** * A file editor input is the input type for the file editor of file system resources. */ export class FileEditorInput extends EditorInput implements IFileEditorInput { + private preferredEncoding: string; private forceOpenAsBinary: boolean; + private forceOpenAsText: boolean; private textModelReference: TPromise>; private name: string; private toUnbind: IDisposable[]; @@ -40,7 +42,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { */ constructor( private resource: URI, - private preferredEncoding: string, + preferredEncoding: string, @IInstantiationService private instantiationService: IInstantiationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService, @@ -52,6 +54,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { this.toUnbind = []; + this.setPreferredEncoding(preferredEncoding); + this.registerListeners(); } @@ -83,6 +87,10 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { public setPreferredEncoding(encoding: string): void { this.preferredEncoding = encoding; + + if (encoding) { + this.forceOpenAsText = true; // encoding is a good hint to open the file as text + } } public getEncoding(): string { @@ -107,8 +115,14 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { } } + public setForceOpenAsText(): void { + this.forceOpenAsText = true; + this.forceOpenAsBinary = false; + } + public setForceOpenAsBinary(): void { this.forceOpenAsBinary = true; + this.forceOpenAsText = false; } public getTypeId(): string { @@ -234,11 +248,17 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { // Resolve as binary if (this.forceOpenAsBinary) { - return this.resolveAsBinary(); + return this.doResolveAsBinary(); } // Resolve as text - return this.textFileService.models.loadOrCreate(this.resource, { encoding: this.preferredEncoding, reload: refresh }).then(model => { + return this.doResolveAsText(refresh); + } + + private doResolveAsText(reload?: boolean): TPromise { + + // Resolve as text + return this.textFileService.models.loadOrCreate(this.resource, { encoding: this.preferredEncoding, reload, allowBinary: this.forceOpenAsText }).then(model => { // This is a bit ugly, because we first resolve the model and then resolve a model reference. the reason being that binary // or very large files do not resolve to a text file model but should be opened as binary files without text. First calling into @@ -253,7 +273,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { // In case of an error that indicates that the file is binary or too large, just return with the binary editor model if ((error).fileOperationResult === FileOperationResult.FILE_IS_BINARY || (error).fileOperationResult === FileOperationResult.FILE_TOO_LARGE) { - return this.resolveAsBinary(); + return this.doResolveAsBinary(); } // Bubble any other error up @@ -261,7 +281,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { }); } - private resolveAsBinary(): TPromise { + private doResolveAsBinary(): TPromise { return this.instantiationService.createInstance(BinaryEditorModel, this.resource, this.getName()).load().then(m => m as BinaryEditorModel); } @@ -306,4 +326,4 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { return false; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index caae28849a..d03e1169c3 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -6,8 +6,8 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; import { ResourceMap } from 'vs/base/common/map'; import { isLinux } from 'vs/base/common/platform'; import { IFileStat } from 'vs/platform/files/common/files'; @@ -17,15 +17,16 @@ import { IEditorGroup, toResource, IEditorIdentifier } from 'vs/workbench/common import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { getPathLabel } from 'vs/base/common/labels'; import { Schemas } from 'vs/base/common/network'; +import { startsWith, startsWithIgnoreCase, rtrim } from 'vs/base/common/strings'; export class Model { - private _roots: FileStat[]; + private _roots: ExplorerItem[]; private _listener: IDisposable; - constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { const setRoots = () => this._roots = this.contextService.getWorkspace().folders.map(folder => { - const root = new FileStat(folder.uri, undefined); + const root = new ExplorerItem(folder.uri, undefined); root.name = folder.name; return root; @@ -34,7 +35,7 @@ export class Model { setRoots(); } - public get roots(): FileStat[] { + public get roots(): ExplorerItem[] { return this._roots; } @@ -43,7 +44,7 @@ export class Model { * Starts matching from the first root. * Will return empty array in case the FileStat does not exist. */ - public findAll(resource: URI): FileStat[] { + public findAll(resource: URI): ExplorerItem[] { return this.roots.map(root => root.find(resource)).filter(stat => !!stat); } @@ -52,7 +53,7 @@ export class Model { * In case multiple FileStat are matching the resource (same folder opened multiple times) returns the FileStat that has the closest root. * Will return null in case the FileStat does not exist. */ - public findClosest(resource: URI): FileStat { + public findClosest(resource: URI): ExplorerItem { const folder = this.contextService.getWorkspaceFolder(resource); if (folder) { const root = this.roots.filter(r => r.resource.toString() === folder.uri.toString()).pop(); @@ -69,19 +70,19 @@ export class Model { } } -export class FileStat implements IFileStat { +export class ExplorerItem { public resource: URI; public name: string; public mtime: number; public etag: string; private _isDirectory: boolean; private _isSymbolicLink: boolean; - public children: FileStat[]; - public parent: FileStat; + private children: Map; + public parent: ExplorerItem; public isDirectoryResolved: boolean; - constructor(resource: URI, public root: FileStat, isSymbolicLink?: boolean, isDirectory?: boolean, name: string = getPathLabel(resource), mtime?: number, etag?: string) { + constructor(resource: URI, public root: ExplorerItem, isSymbolicLink?: boolean, isDirectory?: boolean, name: string = getPathLabel(resource), mtime?: number, etag?: string) { this.resource = resource; this.name = name; this.isDirectory = !!isDirectory; @@ -108,7 +109,7 @@ export class FileStat implements IFileStat { if (value !== this._isDirectory) { this._isDirectory = value; if (this._isDirectory) { - this.children = []; + this.children = new Map(); } else { this.children = undefined; } @@ -128,8 +129,8 @@ export class FileStat implements IFileStat { return this.resource.toString() === this.root.resource.toString(); } - public static create(raw: IFileStat, root: FileStat, resolveTo?: URI[]): FileStat { - const stat = new FileStat(raw.resource, root, raw.isSymbolicLink, raw.isDirectory, raw.name, raw.mtime, raw.etag); + public static create(raw: IFileStat, root: ExplorerItem, resolveTo?: URI[]): ExplorerItem { + const stat = new ExplorerItem(raw.resource, root, raw.isSymbolicLink, raw.isDirectory, raw.name, raw.mtime, raw.etag); // Recursively add children if present if (stat.isDirectory) { @@ -144,9 +145,9 @@ export class FileStat implements IFileStat { // Recurse into children if (raw.children) { for (let i = 0, len = raw.children.length; i < len; i++) { - const child = FileStat.create(raw.children[i], root, resolveTo); + const child = ExplorerItem.create(raw.children[i], root, resolveTo); child.parent = stat; - stat.children.push(child); + stat.addChild(child); } } } @@ -159,7 +160,7 @@ export class FileStat implements IFileStat { * and children. The merge will only consider resolved stat elements to avoid overwriting data which * exists locally. */ - public static mergeLocalWithDisk(disk: FileStat, local: FileStat): void { + public static mergeLocalWithDisk(disk: ExplorerItem, local: ExplorerItem): void { if (disk.resource.toString() !== local.resource.toString()) { return; // Merging only supported for stats with the same resource } @@ -176,36 +177,36 @@ export class FileStat implements IFileStat { local.isDirectory = disk.isDirectory; local.mtime = disk.mtime; local.isDirectoryResolved = disk.isDirectoryResolved; + local._isSymbolicLink = disk.isSymbolicLink; // Merge Children if resolved if (mergingDirectories && disk.isDirectoryResolved) { // Map resource => stat - const oldLocalChildren = new ResourceMap(); + const oldLocalChildren = new ResourceMap(); if (local.children) { - local.children.forEach((localChild: FileStat) => { - oldLocalChildren.set(localChild.resource, localChild); + local.children.forEach(child => { + oldLocalChildren.set(child.resource, child); }); } // Clear current children - local.children = []; + local.children = new Map(); // Merge received children - disk.children.forEach((diskChild: FileStat) => { + disk.children.forEach(diskChild => { const formerLocalChild = oldLocalChildren.get(diskChild.resource); - // Existing child: merge if (formerLocalChild) { - FileStat.mergeLocalWithDisk(diskChild, formerLocalChild); + ExplorerItem.mergeLocalWithDisk(diskChild, formerLocalChild); formerLocalChild.parent = local; - local.children.push(formerLocalChild); + local.addChild(formerLocalChild); } // New child: add else { diskChild.parent = local; - local.children.push(diskChild); + local.addChild(diskChild); } }); } @@ -214,31 +215,78 @@ export class FileStat implements IFileStat { /** * Adds a child element to this folder. */ - public addChild(child: FileStat): void { + public addChild(child: ExplorerItem): void { + if (!this.children) { + this.isDirectory = true; + } // Inherit some parent properties to child child.parent = this; child.updateResource(false); - this.children.push(child); + this.children.set(this.getPlatformAwareName(child.name), child); + } + + public getChild(name: string): ExplorerItem { + if (!this.children) { + return undefined; + } + + return this.children.get(this.getPlatformAwareName(name)); + } + + /** + * Only use this method if you need all the children since it converts a map to an array + */ + public getChildrenArray(): ExplorerItem[] { + if (!this.children) { + return undefined; + } + + const items: ExplorerItem[] = []; + this.children.forEach(child => { + items.push(child); + }); + + return items; + } + + public getChildrenCount(): number { + if (!this.children) { + return 0; + } + + return this.children.size; + } + + public getChildrenNames(): string[] { + if (!this.children) { + return []; + } + + const names: string[] = []; + this.children.forEach(child => { + names.push(child.name); + }); + + return names; } /** * Removes a child element from this folder. */ - public removeChild(child: FileStat): void { - for (let i = 0; i < this.children.length; i++) { - if (this.children[i].resource.toString() === child.resource.toString()) { - this.children.splice(i, 1); - break; - } - } + public removeChild(child: ExplorerItem): void { + this.children.delete(this.getPlatformAwareName(child.name)); + } + + private getPlatformAwareName(name: string): string { + return (isLinux || !name) ? name : name.toLowerCase(); } /** * Moves this element under a new parent element. */ - public move(newParent: FileStat, fnBetweenStates?: (callback: () => void) => void, fnDone?: () => void): void { + public move(newParent: ExplorerItem, fnBetweenStates?: (callback: () => void) => void, fnDone?: () => void): void { if (!fnBetweenStates) { fnBetweenStates = (cb: () => void) => { cb(); }; } @@ -260,7 +308,7 @@ export class FileStat implements IFileStat { if (recursive) { if (this.isDirectory && this.children) { - this.children.forEach((child: FileStat) => { + this.children.forEach(child => { child.updateResource(true); }); } @@ -271,7 +319,7 @@ export class FileStat implements IFileStat { * Tells this stat that it was renamed. This requires changes to all children of this stat (if any) * so that the path property can be updated properly. */ - public rename(renamedStat: IFileStat): void { + public rename(renamedStat: { name: string, mtime: number }): void { // Merge a subset of Properties that can change on rename this.name = renamedStat.name; @@ -285,44 +333,59 @@ export class FileStat implements IFileStat { * Returns a child stat from this stat that matches with the provided path. * Will return "null" in case the child does not exist. */ - public find(resource: URI): FileStat { - + public find(resource: URI): ExplorerItem { // Return if path found - if (resources.isEqual(resource, this.resource, !isLinux /* ignorecase */)) { - return this; - } - - // Return if not having any children - if (!this.children) { - return null; - } - - for (let i = 0; i < this.children.length; i++) { - const child = this.children[i]; - - if (resources.isEqual(resource, child.resource, !isLinux /* ignorecase */)) { - return child; - } - - if (child.isDirectory && resources.isEqualOrParent(resource, child.resource, !isLinux /* ignorecase */)) { - return child.find(resource); - } + if (resource && this.resource.scheme === resource.scheme && this.resource.authority === resource.authority && + (isLinux ? startsWith(resource.path, this.resource.path) : startsWithIgnoreCase(resource.path, this.resource.path)) + ) { + return this.findByPath(rtrim(resource.path, paths.sep), this.resource.path.length); } return null; //Unable to find } + + private findByPath(path: string, index: number): ExplorerItem { + if (paths.isEqual(rtrim(this.resource.path, paths.sep), path, !isLinux)) { + return this; + } + + if (this.children) { + // Ignore separtor to more easily deduct the next name to search + while (index < path.length && path[index] === paths.sep) { + index++; + } + + let indexOfNextSep = path.indexOf(paths.sep, index); + if (indexOfNextSep === -1) { + // If there is no separator take the remainder of the path + indexOfNextSep = path.length; + } + // The name to search is between two separators + const name = path.substring(index, indexOfNextSep); + + const child = this.children.get(this.getPlatformAwareName(name)); + + if (child) { + // We found a child with the given name, search inside it + return child.findByPath(path, indexOfNextSep); + } + } + + return null; + } } /* A helper that can be used to show a placeholder when creating a new stat */ -export class NewStatPlaceholder extends FileStat { +export class NewStatPlaceholder extends ExplorerItem { + public static NAME = ''; private static ID = 0; private id: number; private directoryPlaceholder: boolean; - constructor(isDirectory: boolean, root: FileStat) { - super(URI.file(''), root, false, false, ''); + constructor(isDirectory: boolean, root: ExplorerItem) { + super(URI.file(''), root, false, false, NewStatPlaceholder.NAME); this.id = NewStatPlaceholder.ID++; this.isDirectoryResolved = isDirectory; @@ -366,12 +429,12 @@ export class NewStatPlaceholder extends FileStat { return null; } - public static addNewStatPlaceholder(parent: FileStat, isDirectory: boolean): NewStatPlaceholder { + public static addNewStatPlaceholder(parent: ExplorerItem, isDirectory: boolean): NewStatPlaceholder { const child = new NewStatPlaceholder(isDirectory, parent.root); // Inherit some parent properties to child child.parent = parent; - parent.children.push(child); + parent.addChild(child); return child; } diff --git a/src/vs/workbench/parts/files/common/files.ts b/src/vs/workbench/parts/files/common/files.ts index e348072301..547f21815e 100644 --- a/src/vs/workbench/parts/files/common/files.ts +++ b/src/vs/workbench/parts/files/common/files.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { IFilesConfiguration, FileChangeType, IFileService } from 'vs/platform/files/common/files'; -import { FileStat, OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem, OpenEditor } from 'vs/workbench/parts/files/common/explorerModel'; import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -59,20 +59,26 @@ export const FilesExplorerFocusCondition = ContextKeyExpr.and(ContextKeyExpr.has export const ExplorerFocusCondition = ContextKeyExpr.and(ContextKeyExpr.has(explorerViewletVisibleId), ContextKeyExpr.has(explorerViewletFocusId), ContextKeyExpr.not(InputFocusedContextKey)); /** - * File editor input id. + * Preferences editor id. */ -export const FILE_EDITOR_INPUT_ID = 'workbench.editors.files.fileEditorInput'; +export const PREFERENCES_EDITOR_ID = 'workbench.editor.preferencesEditor'; /** * Text file editor id. */ export const TEXT_FILE_EDITOR_ID = 'workbench.editors.files.textFileEditor'; +/** + * File editor input id. + */ +export const FILE_EDITOR_INPUT_ID = 'workbench.editors.files.fileEditorInput'; + /** * Binary file editor id. */ export const BINARY_FILE_EDITOR_ID = 'workbench.editors.files.binaryFileEditor'; + export interface IFilesConfiguration extends IFilesConfiguration, IWorkbenchEditorConfiguration { explorer: { openEditors: { @@ -98,9 +104,9 @@ export interface IFileResource { /** * Helper to get an explorer item from an object. */ -export function explorerItemToFileResource(obj: FileStat | OpenEditor): IFileResource { - if (obj instanceof FileStat) { - const stat = obj as FileStat; +export function explorerItemToFileResource(obj: ExplorerItem | OpenEditor): IFileResource { + if (obj instanceof ExplorerItem) { + const stat = obj as ExplorerItem; return { resource: stat.resource, @@ -151,7 +157,7 @@ export class FileOnDiskContentProvider implements ITextModelContentProvider { // Make sure to keep contents on disk up to date when it changes if (!this.fileWatcher) { this.fileWatcher = this.fileService.onFileChanges(changes => { - if (changes.contains(fileOnDiskResource, FileChangeType.UPDATED)) { // + if (changes.contains(fileOnDiskResource, FileChangeType.UPDATED)) { this.resolveEditorModel(resource, false /* do not create if missing */).done(null, onUnexpectedError); // update model when resource changes } }); diff --git a/src/vs/workbench/parts/files/electron-browser/explorerViewlet.ts b/src/vs/workbench/parts/files/electron-browser/explorerViewlet.ts index 77455fc9aa..dc667350ee 100644 --- a/src/vs/workbench/parts/files/electron-browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/electron-browser/explorerViewlet.ts @@ -10,7 +10,6 @@ import { localize } from 'vs/nls'; import { IActionRunner } from 'vs/base/common/actions'; import { TPromise } from 'vs/base/common/winjs.base'; import * as DOM from 'vs/base/browser/dom'; -import { Builder } from 'vs/base/browser/builder'; import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration, OpenEditorsVisibleContext, OpenEditorsVisibleCondition, IExplorerViewlet } from 'vs/workbench/parts/files/common/files'; import { PersistentViewsViewlet, IViewletViewOptions, ViewsViewletPanel } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; @@ -36,7 +35,6 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IPartService } from 'vs/workbench/services/part/common/partService'; - export class ExplorerViewletViewsContribution extends Disposable implements IWorkbenchContribution { private openEditorsVisibleContextKey: IContextKey; @@ -172,11 +170,10 @@ export class ExplorerViewlet extends PersistentViewsViewlet implements IExplorer this._register(this.contextService.onDidChangeWorkspaceName(e => this.updateTitleArea())); } - async create(parent: Builder): TPromise { + async create(parent: HTMLElement): TPromise { await super.create(parent); - const el = parent.getHTMLElement(); - DOM.addClass(el, 'explorer-viewlet'); + DOM.addClass(parent, 'explorer-viewlet'); } private isOpenEditorsVisible(): boolean { @@ -256,6 +253,15 @@ export class ExplorerViewlet extends PersistentViewsViewlet implements IExplorer return this.viewletState; } + focus(): void { + const explorerView = this.getExplorerView(); + if (explorerView && explorerView.isExpanded()) { + explorerView.focus(); + } else { + super.focus(); + } + } + protected loadViewsStates(): void { super.loadViewsStates(); @@ -264,4 +270,4 @@ export class ExplorerViewlet extends PersistentViewsViewlet implements IExplorer this.viewsStates.delete(OpenEditorsView.ID); } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts index 134d0beb9c..9a99e324fb 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { GlobalNewUntitledFileAction, ShowOpenedFileInNewWindow, CopyPathAction, FocusOpenEditorsView, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler } from 'vs/workbench/parts/files/electron-browser/fileActions'; import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/parts/files/electron-browser/saveErrorHandler'; @@ -175,7 +175,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { group: 'navigation', order: 10, command: openToSideCommand, - when: ResourceContextKey.HasResource + when: ResourceContextKey.IsFile }); const revealInOsCommand = { @@ -208,7 +208,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { title: SAVE_FILE_LABEL, precondition: DirtyEditorContext }, - when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay')) + when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay') && AutoSaveContext.notEqualsTo('')) }); MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { @@ -219,7 +219,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { title: nls.localize('revert', "Revert File"), precondition: DirtyEditorContext }, - when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay')) + when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay') && AutoSaveContext.notEqualsTo('')) }); MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { @@ -237,7 +237,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { id: SAVE_ALL_IN_GROUP_COMMAND_ID, title: nls.localize('saveAll', "Save All") }, - when: ContextKeyExpr.and(OpenEditorsGroupContext, AutoSaveContext.notEqualsTo('afterDelay')) + when: ContextKeyExpr.and(OpenEditorsGroupContext, AutoSaveContext.notEqualsTo('afterDelay') && AutoSaveContext.notEqualsTo('')) }); MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { @@ -248,7 +248,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { title: nls.localize('compareWithSaved', "Compare with Saved"), precondition: DirtyEditorContext }, - when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay'), WorkbenchListDoubleSelection.toNegated()) + when: ContextKeyExpr.and(ResourceContextKey.IsFile, AutoSaveContext.notEqualsTo('afterDelay') && AutoSaveContext.notEqualsTo(''), WorkbenchListDoubleSelection.toNegated()) }); const compareResourceCommand = { diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.ts index 02a9e15b2c..c1e2ee8e5d 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.ts @@ -7,16 +7,17 @@ import 'vs/css!./media/fileactions'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { isWindows, isLinux } from 'vs/base/common/platform'; import { sequence, ITask, always } from 'vs/base/common/async'; -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; import URI from 'vs/base/common/uri'; -import errors = require('vs/base/common/errors'); +import { posix } from 'path'; +import * as errors from 'vs/base/common/errors'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import strings = require('vs/base/common/strings'); -import diagnostics = require('vs/base/common/diagnostics'); +import * as strings from 'vs/base/common/strings'; +import * as diagnostics from 'vs/base/common/diagnostics'; import { Action, IAction } from 'vs/base/common/actions'; import { MessageType, IInputValidator } from 'vs/base/browser/ui/inputbox/inputBox'; import { ITree, IHighlightEvent } from 'vs/base/parts/tree/browser/tree'; @@ -25,7 +26,7 @@ import { VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; import { toResource } from 'vs/workbench/common/editor'; -import { FileStat, Model, NewStatPlaceholder } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem, Model, NewStatPlaceholder } from 'vs/workbench/parts/files/common/explorerModel'; import { ExplorerView } from 'vs/workbench/parts/files/electron-browser/views/explorerView'; import { ExplorerViewlet } from 'vs/workbench/parts/files/electron-browser/explorerViewlet'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -49,10 +50,8 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IListService, ListWidget } from 'vs/platform/list/browser/listService'; import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { distinctParents, basenameOrAuthority } from 'vs/base/common/resources'; import { Schemas } from 'vs/base/common/network'; -import { IConfirmationService, IConfirmationResult, IConfirmation, IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { getConfirmMessage } from 'vs/workbench/services/dialogs/electron-browser/dialogs'; +import { IDialogService, IConfirmationResult, IConfirmation, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; // {{SQL CARBON EDIT}} @@ -67,9 +66,9 @@ export interface IEditableData { } export interface IFileViewletState { - getEditableData(stat: IFileStat): IEditableData; - setEditable(stat: IFileStat, editableData: IEditableData): void; - clearEditable(stat: IFileStat): void; + getEditableData(stat: ExplorerItem): IEditableData; + setEditable(stat: ExplorerItem, editableData: IEditableData): void; + clearEditable(stat: ExplorerItem): void; } export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; @@ -110,25 +109,18 @@ export class BaseErrorReportingAction extends Action { this._notificationService.error(toErrorMessage(error, false)); } - protected onErrorWithRetry(error: any, retry: () => TPromise, extraAction?: Action): void { - const actions = [ - new Action(this.id, nls.localize('retry', "Retry"), null, true, () => retry()), - ]; - - if (extraAction) { - actions.unshift(extraAction); - } - - this._notificationService.notify({ - severity: Severity.Error, - message: toErrorMessage(error, false), - actions: { primary: actions } - }); + protected onErrorWithRetry(error: any, retry: () => TPromise): void { + this._notificationService.prompt(Severity.Error, toErrorMessage(error, false), + [{ + label: nls.localize('retry', "Retry"), + run: () => retry() + }] + ); } } export class BaseFileAction extends BaseErrorReportingAction { - public element: FileStat; + public element: ExplorerItem; constructor( id: string, @@ -160,7 +152,7 @@ class TriggerRenameFileAction extends BaseFileAction { constructor( tree: ITree, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -174,7 +166,15 @@ class TriggerRenameFileAction extends BaseFileAction { this._updateEnablement(); } - public validateFileName(parent: IFileStat, name: string): string { + public validateFileName(name: string): string { + const names: string[] = name.split(/[\\/]/).filter(part => !!part); + if (names.length > 1) { // error only occurs on multi-path + const comparer = isLinux ? strings.compare : strings.compareIgnoreCase; + if (comparer(names[0], this.element.name) === 0) { + return nls.localize('renameWhenSourcePathIsParentOfTargetError', "Please use the 'New Folder' or 'New File' command to add children to an existing folder"); + } + } + return this.renameAction.validateFileName(this.element.parent, name); } @@ -188,7 +188,7 @@ class TriggerRenameFileAction extends BaseFileAction { return TPromise.wrapError(new Error('Invalid viewlet state provided to BaseEnableFileRenameAction.')); } - const stat = context.stat; + const stat = context.stat; if (!stat) { return TPromise.wrapError(new Error('Invalid stat provided to BaseEnableFileRenameAction.')); } @@ -196,7 +196,7 @@ class TriggerRenameFileAction extends BaseFileAction { viewletState.setEditable(stat, { action: this.renameAction, validator: (value) => { - const message = this.validateFileName(this.element.parent, value); + const message = this.validateFileName(value); if (!message) { return null; @@ -231,7 +231,7 @@ export abstract class BaseRenameAction extends BaseFileAction { constructor( id: string, label: string, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService @@ -268,7 +268,7 @@ export abstract class BaseRenameAction extends BaseFileAction { return promise; } - public validateFileName(parent: IFileStat, name: string): string { + public validateFileName(parent: ExplorerItem, name: string): string { let source = this.element.name; let target = name; @@ -292,7 +292,7 @@ class RenameFileAction extends BaseRenameAction { public static readonly ID = 'workbench.files.action.renameFile'; constructor( - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -346,7 +346,7 @@ class RenameFileAction extends BaseRenameAction { /* Base New File/Folder Action */ export class BaseNewAction extends BaseFileAction { - private presetFolder: FileStat; + private presetFolder: ExplorerItem; private tree: ITree; private isFile: boolean; private renameAction: BaseRenameAction; @@ -357,7 +357,7 @@ export class BaseNewAction extends BaseFileAction { tree: ITree, isFile: boolean, editableAction: BaseRenameAction, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService @@ -385,11 +385,11 @@ export class BaseNewAction extends BaseFileAction { let folder = this.presetFolder; if (!folder) { - const focus = this.tree.getFocus(); + const focus = this.tree.getFocus(); if (focus) { folder = focus.isDirectory ? focus : focus.parent; } else { - const input: FileStat | Model = this.tree.getInput(); + const input: ExplorerItem | Model = this.tree.getInput(); folder = input instanceof Model ? input.roots[0] : input; } } @@ -397,6 +397,10 @@ export class BaseNewAction extends BaseFileAction { if (!folder) { return TPromise.wrapError(new Error('Invalid parent folder to create.')); } + if (!!folder.getChild(NewStatPlaceholder.NAME)) { + // Do not allow to creatae a new file/folder while in the process of creating a new file/folder #47606 + return TPromise.as(new Error('Parent folder is already in the process of creating a file')); + } return this.tree.reveal(folder, 0.5).then(() => { return this.tree.expand(folder).then(() => { @@ -446,7 +450,7 @@ export class NewFileAction extends BaseNewAction { constructor( tree: ITree, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -464,7 +468,7 @@ export class NewFolderAction extends BaseNewAction { constructor( tree: ITree, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -505,7 +509,7 @@ export class GlobalNewUntitledFileAction extends Action { /* Create New File/Folder (only used internally by explorerViewer) */ export abstract class BaseCreateAction extends BaseRenameAction { - public validateFileName(parent: IFileStat, name: string): string { + public validateFileName(parent: ExplorerItem, name: string): string { if (this.element instanceof NewStatPlaceholder) { return validateFileName(parent, name, false); } @@ -521,7 +525,7 @@ class CreateFileAction extends BaseCreateAction { public static readonly LABEL = nls.localize('createNewFile', "New File"); constructor( - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @INotificationService notificationService: INotificationService, @@ -549,7 +553,7 @@ class CreateFolderAction extends BaseCreateAction { public static readonly LABEL = nls.localize('createNewFolder', "New Folder"); constructor( - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService @@ -575,14 +579,13 @@ class BaseDeleteFileAction extends BaseFileAction { constructor( private tree: ITree, - private elements: FileStat[], + private elements: ExplorerItem[], private useTrash: boolean, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, - @IConfirmationService private confirmationService: IConfirmationService, + @IDialogService private dialogService: IDialogService, @ITextFileService textFileService: ITextFileService, - @IConfigurationService private configurationService: IConfigurationService, - @IChoiceService private choiceService: IChoiceService + @IConfigurationService private configurationService: IConfigurationService ) { super('moveFileToTrash', MOVE_FILE_TO_TRASH_LABEL, fileService, notificationService, textFileService); @@ -606,7 +609,7 @@ class BaseDeleteFileAction extends BaseFileAction { primaryButton = nls.localize({ key: 'deleteButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Delete"); } - const distinctElements = distinctParents(this.elements, e => e.resource); + const distinctElements = resources.distinctParents(this.elements, e => e.resource); // Handle dirty let confirmDirtyPromise: TPromise = TPromise.as(true); @@ -625,13 +628,13 @@ class BaseDeleteFileAction extends BaseFileAction { message = nls.localize('dirtyMessageFileDelete', "You are deleting a file with unsaved changes. Do you want to continue?"); } - confirmDirtyPromise = this.confirmationService.confirm({ + confirmDirtyPromise = this.dialogService.confirm({ message, type: 'warning', detail: nls.localize('dirtyWarning', "Your changes will be lost if you don't save them."), primaryButton - }).then(confirmed => { - if (!confirmed) { + }).then(res => { + if (!res.confirmed) { return false; } @@ -655,12 +658,11 @@ class BaseDeleteFileAction extends BaseFileAction { // Confirm for moving to trash else if (this.useTrash) { - const message = distinctElements.length > 1 ? getConfirmMessage(nls.localize('confirmMoveTrashMessageMultiple', "Are you sure you want to delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource)) - : distinctElements[0].isDirectory ? nls.localize('confirmMoveTrashMessageFolder', "Are you sure you want to delete '{0}' and its contents?", distinctElements[0].name) - : nls.localize('confirmMoveTrashMessageFile', "Are you sure you want to delete '{0}'?", distinctElements[0].name); - confirmDeletePromise = this.confirmationService.confirmWithCheckbox({ + const message = this.getMoveToTrashMessage(distinctElements); + + confirmDeletePromise = this.dialogService.confirm({ message, - detail: isWindows ? nls.localize('undoBin', "You can restore from the recycle bin.") : nls.localize('undoTrash', "You can restore from the trash."), + detail: isWindows ? nls.localize('undoBin', "You can restore from the Recycle Bin.") : nls.localize('undoTrash', "You can restore from the Trash."), primaryButton, checkbox: { label: nls.localize('doNotAskAgain', "Do not ask me again") @@ -671,10 +673,8 @@ class BaseDeleteFileAction extends BaseFileAction { // Confirm for deleting permanently else { - const message = distinctElements.length > 1 ? getConfirmMessage(nls.localize('confirmDeleteMessageMultiple', "Are you sure you want to permanently delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource)) - : distinctElements[0].isDirectory ? nls.localize('confirmDeleteMessageFolder', "Are you sure you want to permanently delete '{0}' and its contents?", distinctElements[0].name) - : nls.localize('confirmDeleteMessageFile', "Are you sure you want to permanently delete '{0}'?", distinctElements[0].name); - confirmDeletePromise = this.confirmationService.confirmWithCheckbox({ + const message = this.getDeleteMessage(distinctElements); + confirmDeletePromise = this.dialogService.confirm({ message, detail: nls.localize('irreversible', "This action is irreversible!"), primaryButton, @@ -703,36 +703,38 @@ class BaseDeleteFileAction extends BaseFileAction { this.tree.setFocus(distinctElements[0].parent); // move focus to parent } }, (error: any) => { - const choices = [nls.localize('retry', "Retry"), nls.localize('cancel', "Cancel")]; + + // Handle error to delete file(s) from a modal confirmation dialog + let errorMessage: string; + let detailMessage: string; + let primaryButton: string; if (this.useTrash) { - choices.unshift(nls.localize('permDelete', "Delete Permanently")); + errorMessage = isWindows ? nls.localize('binFailed', "Failed to delete using the Recycle Bin. Do you want to permanently delete instead?") : nls.localize('trashFailed', "Failed to delete using the Trash. Do you want to permanently delete instead?"); + detailMessage = nls.localize('irreversible', "This action is irreversible!"); + primaryButton = nls.localize({ key: 'deletePermanentlyButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Delete Permanently"); + } else { + errorMessage = toErrorMessage(error, false); + primaryButton = nls.localize({ key: 'retryButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Retry"); } - return this.choiceService.choose(Severity.Error, toErrorMessage(error, false), choices, choices.length - 1, true).then(choice => { + return this.dialogService.confirm({ + message: errorMessage, + detail: detailMessage, + type: 'warning', + primaryButton + }).then(res => { // Focus back to tree - this.tree.DOMFocus(); + this.tree.domFocus(); - - if (this.useTrash) { - switch (choice) { - case 0: /* Delete Permanently*/ - this.useTrash = false; - this.skipConfirm = true; - - return this.run(); - case 1: /* Retry */ - this.skipConfirm = true; - - return this.run(); + if (res.confirmed) { + if (this.useTrash) { + this.useTrash = false; // Delete Permanently } - } else { - switch (choice) { - case 0: /* Retry */ - this.skipConfirm = true; - return this.run(); - } + this.skipConfirm = true; + + return this.run(); } return TPromise.as(void 0); @@ -744,24 +746,71 @@ class BaseDeleteFileAction extends BaseFileAction { }); }); } + + private getMoveToTrashMessage(distinctElements: ExplorerItem[]): string { + if (this.containsBothDirectoryAndFile(distinctElements)) { + return getConfirmMessage(nls.localize('confirmMoveTrashMessageFilesAndDirectories', "Are you sure you want to delete the following {0} files/directories and their contents?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + if (distinctElements.length > 1) { + if (distinctElements[0].isDirectory) { + return getConfirmMessage(nls.localize('confirmMoveTrashMessageMultipleDirectories', "Are you sure you want to delete the following {0} directories and their contents?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + return getConfirmMessage(nls.localize('confirmMoveTrashMessageMultiple', "Are you sure you want to delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + if (distinctElements[0].isDirectory) { + return nls.localize('confirmMoveTrashMessageFolder', "Are you sure you want to delete '{0}' and its contents?", distinctElements[0].name); + } + + return nls.localize('confirmMoveTrashMessageFile', "Are you sure you want to delete '{0}'?", distinctElements[0].name); + } + + private getDeleteMessage(distinctElements: ExplorerItem[]): string { + if (this.containsBothDirectoryAndFile(distinctElements)) { + return getConfirmMessage(nls.localize('confirmDeleteMessageFilesAndDirectories', "Are you sure you want to permanently delete the following {0} files/directories and their contents?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + if (distinctElements.length > 1) { + if (distinctElements[0].isDirectory) { + return getConfirmMessage(nls.localize('confirmDeleteMessageMultipleDirectories', "Are you sure you want to permanently delete the following {0} directories and their contents?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + return getConfirmMessage(nls.localize('confirmDeleteMessageMultiple', "Are you sure you want to permanently delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource)); + } + + if (distinctElements[0].isDirectory) { + return nls.localize('confirmDeleteMessageFolder', "Are you sure you want to permanently delete '{0}' and its contents?", distinctElements[0].name); + } + + return nls.localize('confirmDeleteMessageFile', "Are you sure you want to permanently delete '{0}'?", distinctElements[0].name); + } + + private containsBothDirectoryAndFile(distinctElements: ExplorerItem[]): boolean { + const directories = distinctElements.filter(element => element.isDirectory); + const files = distinctElements.filter(element => !element.isDirectory); + + return directories.length > 0 && files.length > 0; + } } -/* Import File */ -export class ImportFileAction extends BaseFileAction { +/* Add File */ +export class AddFilesAction extends BaseFileAction { private tree: ITree; constructor( tree: ITree, - element: FileStat, + element: ExplorerItem, clazz: string, @IFileService fileService: IFileService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IConfirmationService private confirmationService: IConfirmationService, + @IDialogService private dialogService: IDialogService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService ) { - super('workbench.files.action.importFile', nls.localize('importFiles', "Import Files"), fileService, notificationService, textFileService); + super('workbench.files.action.addFile', nls.localize('addFiles', "Add Files"), fileService, notificationService, textFileService); this.tree = tree; this.element = element; @@ -774,15 +823,15 @@ export class ImportFileAction extends BaseFileAction { } public run(resources: URI[]): TPromise { - const importPromise = TPromise.as(null).then(() => { + const addPromise = TPromise.as(null).then(() => { if (resources && resources.length > 0) { - // Find parent for import - let targetElement: FileStat; + // Find parent to add to + let targetElement: ExplorerItem; if (this.element) { targetElement = this.element; } else { - const input: FileStat | Model = this.tree.getInput(); + const input: ExplorerItem | Model = this.tree.getInput(); targetElement = this.tree.getFocus() || (input instanceof Model ? input.roots[0] : input); } @@ -794,14 +843,14 @@ export class ImportFileAction extends BaseFileAction { return this.fileService.resolveFile(targetElement.resource).then((targetStat: IFileStat) => { // Check for name collisions - const targetNames: { [name: string]: IFileStat } = {}; + const targetNames = new Set(); targetStat.children.forEach((child) => { - targetNames[isLinux ? child.name : child.name.toLowerCase()] = child; + targetNames.add(isLinux ? child.name : child.name.toLowerCase()); }); - let overwritePromise = TPromise.as(true); + let overwritePromise: TPromise = TPromise.as({ confirmed: true }); if (resources.some(resource => { - return !!targetNames[isLinux ? paths.basename(resource.fsPath) : paths.basename(resource.fsPath).toLowerCase()]; + return targetNames.has(isLinux ? paths.basename(resource.fsPath) : paths.basename(resource.fsPath).toLowerCase()); })) { const confirm: IConfirmation = { message: nls.localize('confirmOverwrite', "A file or folder with the same name already exists in the destination folder. Do you want to replace it?"), @@ -810,23 +859,23 @@ export class ImportFileAction extends BaseFileAction { type: 'warning' }; - overwritePromise = this.confirmationService.confirm(confirm); + overwritePromise = this.dialogService.confirm(confirm); } - return overwritePromise.then(overwrite => { - if (!overwrite) { + return overwritePromise.then(res => { + if (!res.confirmed) { return void 0; } - // Run import in sequence - const importPromisesFactory: ITask>[] = []; + // Run add in sequence + const addPromisesFactory: ITask>[] = []; resources.forEach(resource => { - importPromisesFactory.push(() => { + addPromisesFactory.push(() => { const sourceFile = resource; const targetFile = targetElement.resource.with({ path: paths.join(targetElement.resource.path, paths.basename(sourceFile.path)) }); // if the target exists and is dirty, make sure to revert it. otherwise the dirty contents - // of the target file would replace the contents of the imported file. since we already + // of the target file would replace the contents of the added file. since we already // confirmed the overwrite before, this is OK. let revertPromise = TPromise.wrap(null); if (this.textFileService.isDirty(targetFile)) { @@ -834,18 +883,19 @@ export class ImportFileAction extends BaseFileAction { } return revertPromise.then(() => { - return this.fileService.importFile(sourceFile, targetElement.resource).then(res => { + const target = targetElement.resource.with({ path: posix.join(targetElement.resource.path, posix.basename(sourceFile.path)) }); + return this.fileService.copyFile(sourceFile, target, true).then(stat => { - // if we only import one file, just open it directly + // if we only add one file, just open it directly if (resources.length === 1) { - this.editorService.openEditor({ resource: res.stat.resource, options: { pinned: true } }).done(null, errors.onUnexpectedError); + this.editorService.openEditor({ resource: stat.resource, options: { pinned: true } }).done(null, errors.onUnexpectedError); } }, error => this.onError(error)); }); }); }); - return sequence(importPromisesFactory); + return sequence(addPromisesFactory); }); }); } @@ -853,7 +903,7 @@ export class ImportFileAction extends BaseFileAction { return void 0; }); - return importPromise.then(() => { + return addPromise.then(() => { this.tree.clearHighlight(); }, (error: any) => { this.onError(error); @@ -868,7 +918,7 @@ class CopyFileAction extends BaseFileAction { private tree: ITree; constructor( tree: ITree, - private elements: FileStat[], + private elements: ExplorerItem[], @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -891,7 +941,7 @@ class CopyFileAction extends BaseFileAction { this.tree.clearHighlight(); } - this.tree.DOMFocus(); + this.tree.domFocus(); return TPromise.as(null); } @@ -906,7 +956,7 @@ class PasteFileAction extends BaseFileAction { constructor( tree: ITree, - element: FileStat, + element: ExplorerItem, @IFileService fileService: IFileService, @INotificationService notificationService: INotificationService, @ITextFileService textFileService: ITextFileService, @@ -917,7 +967,7 @@ class PasteFileAction extends BaseFileAction { this.tree = tree; this.element = element; if (!this.element) { - const input: FileStat | Model = this.tree.getInput(); + const input: ExplorerItem | Model = this.tree.getInput(); this.element = input instanceof Model ? input.roots[0] : input; } this._updateEnablement(); @@ -938,7 +988,7 @@ class PasteFileAction extends BaseFileAction { } // Find target - let target: FileStat; + let target: ExplorerItem; if (this.element.resource.toString() === fileToPaste.toString()) { target = this.element.parent; } else { @@ -955,7 +1005,7 @@ class PasteFileAction extends BaseFileAction { return void 0; }, error => this.onError(error)).then(() => { - this.tree.DOMFocus(); + this.tree.domFocus(); }); }, error => { this.onError(new Error(nls.localize('fileDeleted', "File to paste was deleted or moved meanwhile"))); @@ -966,12 +1016,12 @@ class PasteFileAction extends BaseFileAction { // Duplicate File/Folder export class DuplicateFileAction extends BaseFileAction { private tree: ITree; - private target: FileStat; + private target: ExplorerItem; constructor( tree: ITree, - fileToDuplicate: FileStat, - target: FileStat, + fileToDuplicate: ExplorerItem, + target: ExplorerItem, @IFileService fileService: IFileService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @INotificationService notificationService: INotificationService, @@ -1005,8 +1055,8 @@ export class DuplicateFileAction extends BaseFileAction { } } -function findValidPasteFileTarget(targetFolder: FileStat, fileToPaste: { resource: URI, isDirectory?: boolean }): URI { - let name = basenameOrAuthority(fileToPaste.resource); +function findValidPasteFileTarget(targetFolder: ExplorerItem, fileToPaste: { resource: URI, isDirectory?: boolean }): URI { + let name = resources.basenameOrAuthority(fileToPaste.resource); let candidate = targetFolder.resource.with({ path: paths.join(targetFolder.resource.path, name) }); while (true) { @@ -1234,7 +1284,7 @@ export class FocusFilesExplorer extends Action { const view = viewlet.getExplorerView(); if (view) { view.setExpanded(true); - view.getViewer().DOMFocus(); + view.getViewer().domFocus(); } }); } @@ -1364,7 +1414,7 @@ export class CopyPathAction extends Action { } -export function validateFileName(parent: IFileStat, name: string, allowOverwriting: boolean = false): string { +export function validateFileName(parent: ExplorerItem, name: string, allowOverwriting: boolean = false): string { // Produce a well formed file name name = getWellFormedFileName(name); @@ -1374,25 +1424,22 @@ export function validateFileName(parent: IFileStat, name: string, allowOverwriti return nls.localize('emptyFileNameError', "A file or folder name must be provided."); } + // Relative paths only + if (name[0] === '/' || name[0] === '\\') { + return nls.localize('fileNameStartsWithSlashError', "A file or folder name cannot start with a slash."); + } + const names: string[] = name.split(/[\\/]/).filter(part => !!part); + const analyzedPath = analyzePath(parent, names); // Do not allow to overwrite existing file - if (!allowOverwriting) { - let p = parent; - const alreadyExisting = names.every((folderName) => { - let { exists, child } = alreadyExists(p, folderName); + if (!allowOverwriting && analyzedPath.fullPathAlreadyExists) { + return nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name); + } - if (!exists) { - return false; - } else { - p = child; - return true; - } - }); - - if (alreadyExisting) { - return nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name); - } + // A file must always be a leaf + if (analyzedPath.lastExistingPathSegment.isFile) { + return nls.localize('fileUsedAsFolderError', "**{0}** is a file and cannot have any descendants.", analyzedPath.lastExistingPathSegment.name); } // Invalid File name @@ -1411,23 +1458,30 @@ export function validateFileName(parent: IFileStat, name: string, allowOverwriti return null; } -function alreadyExists(parent: IFileStat, name: string): { exists: boolean, child: IFileStat | undefined } { - let duplicateChild: IFileStat; +function analyzePath(parent: ExplorerItem, pathNames: string[]): { fullPathAlreadyExists: boolean; lastExistingPathSegment: { isFile: boolean; name: string; } } { + let lastExistingPathSegment = { isFile: false, name: '' }; - if (parent.children) { - let exists: boolean = parent.children.some((c) => { - let found: boolean; - if (isLinux) { - found = c.name === name; - } else { - found = c.name.toLowerCase() === name.toLowerCase(); - } - if (found) { - duplicateChild = c; - } - return found; - }); - return { exists, child: duplicateChild }; + for (const name of pathNames) { + const { exists, child } = alreadyExists(parent, name); + + if (exists) { + lastExistingPathSegment = { isFile: !child.isDirectory, name }; + parent = child; + } else { + return { fullPathAlreadyExists: false, lastExistingPathSegment }; + } + } + + return { fullPathAlreadyExists: true, lastExistingPathSegment }; +} + + +function alreadyExists(parent: ExplorerItem, name: string): { exists: boolean, child: ExplorerItem | undefined } { + let duplicateChild: ExplorerItem; + + if (parent && parent.isDirectory) { + duplicateChild = parent.getChild(name); + return { exists: !!duplicateChild, child: duplicateChild }; } return { exists: false, child: undefined }; @@ -1446,11 +1500,14 @@ export function getWellFormedFileName(filename: string): string { return filename; } - // Trim whitespaces - filename = strings.trim(strings.trim(filename, ' '), '\t'); + // Trim tabs + filename = strings.trim(filename, '\t'); - // Remove trailing dots + // Remove trailing dots, slashes, and spaces filename = strings.rtrim(filename, '.'); + filename = strings.rtrim(filename, ' '); + filename = strings.rtrim(filename, '/'); + filename = strings.rtrim(filename, '\\'); return filename; } @@ -1529,8 +1586,8 @@ if (!diag) { interface IExplorerContext { viewletState: IFileViewletState; - stat: FileStat; - selection: FileStat[]; + stat: ExplorerItem; + selection: ExplorerItem[]; } function getContext(listWidget: ListWidget, viewletService: IViewletService): IExplorerContext { @@ -1545,7 +1602,7 @@ function getContext(listWidget: ListWidget, viewletService: IViewletService): IE // TODO@isidor these commands are calling into actions due to the complex inheritance action structure. // It should be the other way around, that actions call into commands. -function openExplorerAndRunAction(accessor: ServicesAccessor, constructor: IConstructorSignature2): TPromise { +function openExplorerAndRunAction(accessor: ServicesAccessor, constructor: IConstructorSignature2): TPromise { const instantationService = accessor.get(IInstantiationService); const listService = accessor.get(IListService); const viewletService = accessor.get(IViewletService); @@ -1628,7 +1685,7 @@ export const pasteFileHandler = (accessor: ServicesAccessor) => { const clipboardService = accessor.get(IClipboardService); const explorerContext = getContext(listService.lastFocusedList, accessor.get(IViewletService)); - return TPromise.join(distinctParents(clipboardService.readFiles(), r => r).map(toCopy => { + return TPromise.join(resources.distinctParents(clipboardService.readFiles(), r => r).map(toCopy => { const pasteFileAction = instantationService.createInstance(PasteFileAction, listService.lastFocusedList, explorerContext.stat); return pasteFileAction.run(toCopy); })); diff --git a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts index fac49b5928..0eea5eb1df 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts @@ -5,8 +5,8 @@ 'use strict'; -import nls = require('vs/nls'); -import paths = require('vs/base/common/paths'); +import * as nls from 'vs/nls'; +import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; import * as labels from 'vs/base/common/labels'; import URI from 'vs/base/common/uri'; @@ -22,7 +22,6 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { basename } from 'vs/base/common/paths'; import { IListService } from 'vs/platform/list/browser/listService'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -42,6 +41,7 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; import { Schemas } from 'vs/base/common/network'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; // {{SQL CARBON EDIT}} import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService'; @@ -254,7 +254,7 @@ function saveAll(saveAllArguments: any, editorService: IWorkbenchEditorService, CommandsRegistry.registerCommand({ id: REVERT_FILE_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const editorService = accessor.get(IWorkbenchEditorService); const textFileService = accessor.get(ITextFileService); const notificationService = accessor.get(INotificationService); @@ -263,7 +263,7 @@ CommandsRegistry.registerCommand({ if (resources.length) { return textFileService.revertAll(resources, { force: true }).then(null, error => { - notificationService.error(nls.localize('genericRevertError', "Failed to revert '{0}': {1}", resources.map(r => basename(r.fsPath)).join(', '), toErrorMessage(error, false))); + notificationService.error(nls.localize('genericRevertError', "Failed to revert '{0}': {1}", resources.map(r => paths.basename(r.fsPath)).join(', '), toErrorMessage(error, false))); }); } @@ -278,7 +278,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ mac: { primary: KeyMod.WinCtrl | KeyCode.Enter }, - id: OPEN_TO_SIDE_COMMAND_ID, handler: (accessor, resource: URI) => { + id: OPEN_TO_SIDE_COMMAND_ID, handler: (accessor, resource: URI | object) => { const editorService = accessor.get(IWorkbenchEditorService); const editorGroupService = accessor.get(IEditorGroupService); const listService = accessor.get(IListService); @@ -322,7 +322,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ when: undefined, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_D), - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { if (!provider) { const instantiationService = accessor.get(IInstantiationService); const textModelService = accessor.get(ITextModelService); @@ -331,13 +331,13 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } const editorService = accessor.get(IWorkbenchEditorService); - resource = getResourceForCommand(resource, accessor.get(IListService), editorService); + const uri = getResourceForCommand(resource, accessor.get(IListService), editorService); - if (resource && resource.scheme === Schemas.file /* only files on disk supported for now */) { - const name = paths.basename(resource.fsPath); + if (uri && uri.scheme === Schemas.file /* only files on disk supported for now */) { + const name = paths.basename(uri.fsPath); const editorLabel = nls.localize('modifiedLabel', "{0} (on disk) ↔ {1}", name, name); - return editorService.openEditor({ leftResource: URI.from({ scheme: COMPARE_WITH_SAVED_SCHEMA, path: resource.fsPath }), rightResource: resource, label: editorLabel }).then(() => void 0); + return editorService.openEditor({ leftResource: URI.from({ scheme: COMPARE_WITH_SAVED_SCHEMA, path: uri.fsPath }), rightResource: uri, label: editorLabel }).then(() => void 0); } return TPromise.as(true); @@ -348,13 +348,13 @@ let globalResourceToCompare: URI; let resourceSelectedForCompareContext: IContextKey; CommandsRegistry.registerCommand({ id: SELECT_FOR_COMPARE_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const listService = accessor.get(IListService); const tree = listService.lastFocusedList; // Remove highlight if (tree instanceof Tree) { tree.clearHighlight(); - tree.DOMFocus(); + tree.domFocus(); } globalResourceToCompare = getResourceForCommand(resource, listService, accessor.get(IWorkbenchEditorService)); @@ -367,7 +367,7 @@ CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({ id: COMPARE_SELECTED_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const editorService = accessor.get(IWorkbenchEditorService); const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService); @@ -384,7 +384,7 @@ CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({ id: COMPARE_RESOURCE_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const editorService = accessor.get(IWorkbenchEditorService); const listService = accessor.get(IListService); const tree = listService.lastFocusedList; @@ -401,9 +401,11 @@ CommandsRegistry.registerCommand({ } }); -function revealResourcesInOS(resources: URI[], windowsService: IWindowsService, notificationService: INotificationService): void { +function revealResourcesInOS(resources: URI[], windowsService: IWindowsService, notificationService: INotificationService, workspaceContextService: IWorkspaceContextService): void { if (resources.length) { sequence(resources.map(r => () => windowsService.showItemInFolder(paths.normalize(r.fsPath, true)))); + } else if (workspaceContextService.getWorkspace().folders.length) { + windowsService.showItemInFolder(paths.normalize(workspaceContextService.getWorkspace().folders[0].uri.fsPath, true)); } else { notificationService.info(nls.localize('openFileToReveal', "Open a file first to reveal")); } @@ -411,14 +413,14 @@ function revealResourcesInOS(resources: URI[], windowsService: IWindowsService, KeybindingsRegistry.registerCommandAndKeybindingRule({ id: REVEAL_IN_OS_COMMAND_ID, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ExplorerFocusCondition, + when: EditorContextKeys.editorTextFocus.toNegated(), primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R, win: { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_R }, - handler: (accessor: ServicesAccessor, resource: URI) => { + handler: (accessor: ServicesAccessor, resource: URI | object) => { const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IWorkbenchEditorService)); - revealResourcesInOS(resources, accessor.get(IWindowsService), accessor.get(INotificationService)); + revealResourcesInOS(resources, accessor.get(IWindowsService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService)); } }); KeybindingsRegistry.registerCommandAndKeybindingRule({ @@ -426,11 +428,11 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ when: undefined, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_R), id: 'workbench.action.files.revealActiveFileInWindows', - handler: (accessor: ServicesAccessor, resource: URI) => { + handler: (accessor: ServicesAccessor) => { const editorService = accessor.get(IWorkbenchEditorService); const activeInput = editorService.getActiveEditorInput(); const resources = activeInput && activeInput.getResource() ? [activeInput.getResource()] : []; - revealResourcesInOS(resources, accessor.get(IWindowsService), accessor.get(INotificationService)); + revealResourcesInOS(resources, accessor.get(IWindowsService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService)); } }); @@ -445,13 +447,13 @@ function resourcesToClipboard(resources: URI[], clipboardService: IClipboardServ } KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ExplorerFocusCondition, + when: EditorContextKeys.editorTextFocus.toNegated(), primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C, win: { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_C }, id: COPY_PATH_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IWorkbenchEditorService)); resourcesToClipboard(resources, accessor.get(IClipboardService), accessor.get(INotificationService)); } @@ -462,7 +464,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ when: undefined, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_P), id: 'workbench.action.files.copyPathOfActiveFile', - handler: (accessor, resource: URI) => { + handler: (accessor) => { const editorService = accessor.get(IWorkbenchEditorService); const activeInput = editorService.getActiveEditorInput(); const resources = activeInput && activeInput.getResource() ? [activeInput.getResource()] : []; @@ -472,18 +474,18 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ CommandsRegistry.registerCommand({ id: REVEAL_IN_EXPLORER_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const viewletService = accessor.get(IViewletService); const contextService = accessor.get(IWorkspaceContextService); - resource = getResourceForCommand(resource, accessor.get(IListService), accessor.get(IWorkbenchEditorService)); + const uri = getResourceForCommand(resource, accessor.get(IListService), accessor.get(IWorkbenchEditorService)); viewletService.openViewlet(VIEWLET_ID, false).then((viewlet: ExplorerViewlet) => { - const isInsideWorkspace = contextService.isInsideWorkspace(resource); + const isInsideWorkspace = contextService.isInsideWorkspace(uri); if (isInsideWorkspace) { const explorerView = viewlet.getExplorerView(); if (explorerView) { explorerView.setExpanded(true); - explorerView.select(resource, true); + explorerView.select(uri, true); } } else { const openEditorsView = viewlet.getOpenEditorsView(); @@ -500,9 +502,15 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: undefined, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S, - handler: (accessor, resource: URI) => { + handler: (accessor, resourceOrObject: URI | object | { from: string }) => { const editorService = accessor.get(IWorkbenchEditorService); - resource = getResourceForCommand(resource, accessor.get(IListService), editorService); + let resource: URI = undefined; + if (resourceOrObject && 'from' in resourceOrObject && resourceOrObject.from === 'menu') { + resource = toResource(editorService.getActiveEditorInput()); + } else { + resource = getResourceForCommand(resourceOrObject, accessor.get(IListService), editorService); + } + // {{SQL CARBON EDIT}} return save(resource, true, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupService), accessor.get(IQueryEditorService)); } @@ -513,7 +521,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyMod.CtrlCmd | KeyCode.KEY_S, id: SAVE_FILE_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const editorService = accessor.get(IWorkbenchEditorService); const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService); @@ -535,7 +543,7 @@ CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({ id: SAVE_ALL_IN_GROUP_COMMAND_ID, - handler: (accessor, resource: URI, editorContext: IEditorCommandsContext) => { + handler: (accessor, resource: URI | object, editorContext: IEditorCommandsContext) => { const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService)); const editorGroupService = accessor.get(IEditorGroupService); let saveAllArg: any; @@ -568,7 +576,7 @@ CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({ id: REMOVE_ROOT_FOLDER_COMMAND_ID, - handler: (accessor, resource: URI) => { + handler: (accessor, resource: URI | object) => { const workspaceEditingService = accessor.get(IWorkspaceEditingService); const contextService = accessor.get(IWorkspaceContextService); const workspace = contextService.getWorkspace(); diff --git a/src/vs/workbench/parts/files/electron-browser/files.contribution.ts b/src/vs/workbench/parts/files/electron-browser/files.contribution.ts index c32696671b..6d80139b94 100644 --- a/src/vs/workbench/parts/files/electron-browser/files.contribution.ts +++ b/src/vs/workbench/parts/files/electron-browser/files.contribution.ts @@ -7,7 +7,7 @@ import URI from 'vs/base/common/uri'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ToggleViewletAction } from 'vs/workbench/browser/viewlet'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; @@ -15,7 +15,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IEditorInputFactory, EditorInput, IFileEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions } from 'vs/workbench/common/editor'; import { AutoSaveConfiguration, HotExitConfiguration, SUPPORTED_ENCODINGS } from 'vs/platform/files/common/files'; -import { FILE_EDITOR_INPUT_ID, VIEWLET_ID, SortOrderConfiguration } from 'vs/workbench/parts/files/common/files'; +import { VIEWLET_ID, SortOrderConfiguration, FILE_EDITOR_INPUT_ID } from 'vs/workbench/parts/files/common/files'; import { FileEditorTracker } from 'vs/workbench/parts/files/browser/editors/fileEditorTracker'; import { SaveErrorHandler } from 'vs/workbench/parts/files/electron-browser/saveErrorHandler'; import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput'; @@ -243,7 +243,7 @@ configurationRegistry.registerConfiguration({ }, 'files.autoSave': { 'type': 'string', - 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, , AutoSaveConfiguration.ON_WINDOW_CHANGE], + 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE], 'enumDescriptions': [ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "A dirty file is never automatically saved."), nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "A dirty file is automatically saved after the configured 'files.autoSaveDelay'."), @@ -283,6 +283,11 @@ configurationRegistry.registerConfiguration({ 'files.defaultLanguage': { 'type': 'string', 'description': nls.localize('defaultLanguage', "The default language mode that is assigned to new files.") + }, + 'files.maxMemoryForLargeFilesMB': { + 'type': 'number', + 'default': 4096, + 'description': nls.localize('maxMemoryForLargeFilesMB', "Controls the memory available to VS Code after restart when trying to open large files. Same affect as specifying --max-memory=NEWSIZE on the command line.") } } }); @@ -299,6 +304,13 @@ configurationRegistry.registerConfiguration({ 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be auto-saved, and editor must not be shutting down."), 'overridable': true, 'scope': ConfigurationScope.RESOURCE + }, + 'editor.formatOnSaveTimeout': { + 'type': 'number', + 'default': 750, + 'description': nls.localize('formatOnSaveTimeout', "Format on save timeout. Specifies a time limit in milliseconds for formatOnSave-commands. Commands taking longer than the specified timeout will be cancelled."), + 'overridable': true, + 'scope': ConfigurationScope.RESOURCE } } }); diff --git a/src/vs/workbench/parts/files/electron-browser/media/explorerviewlet.css b/src/vs/workbench/parts/files/electron-browser/media/explorerviewlet.css index 51357ef8dc..cf5d7936a3 100644 --- a/src/vs/workbench/parts/files/electron-browser/media/explorerviewlet.css +++ b/src/vs/workbench/parts/files/electron-browser/media/explorerviewlet.css @@ -109,7 +109,6 @@ .monaco-workbench.linux .explorer-viewlet .explorer-item .monaco-inputbox, .monaco-workbench.mac .explorer-viewlet .explorer-item .monaco-inputbox { height: 22px; - margin-left: -1px; } .explorer-viewlet .explorer-item .monaco-inputbox > .wrapper > .input { diff --git a/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts b/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts index 1a70a93c60..94c6803025 100644 --- a/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts +++ b/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts @@ -5,10 +5,10 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import { Action } from 'vs/base/common/actions'; import URI from 'vs/base/common/uri'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; @@ -34,6 +34,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ExecuteCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { once } from 'vs/base/common/event'; export const CONFLICT_RESOLUTION_CONTEXT = 'saveConflictResolutionContext'; export const CONFLICT_RESOLUTION_SCHEME = 'conflictResolution'; @@ -177,7 +178,9 @@ export class SaveErrorHandler implements ISaveErrorHandler, IWorkbenchContributi } // Show message and keep function to hide in case the file gets saved/reverted - this.messages.set(model.getResource(), this.notificationService.notify({ severity: Severity.Error, message, actions })); + const handle = this.notificationService.notify({ severity: Severity.Error, message, actions }); + once(handle.onDidClose)(() => dispose(...actions.primary, ...actions.secondary)); + this.messages.set(model.getResource(), handle); } public dispose(): void { @@ -262,6 +265,7 @@ class ResolveSaveConflictAction extends Action { actions.secondary.push(this.instantiationService.createInstance(DoNotShowResolveConflictLearnMoreAction)); const handle = this.notificationService.notify({ severity: Severity.Info, message: conflictEditorHelp, actions }); + once(handle.onDidClose)(() => dispose(...actions.primary, ...actions.secondary)); pendingResolveSaveConflictMessages.push(handle); }); } diff --git a/src/vs/workbench/parts/files/electron-browser/views/emptyView.ts b/src/vs/workbench/parts/files/electron-browser/views/emptyView.ts index f3d259f523..b5942f2d70 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/emptyView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/emptyView.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as errors from 'vs/base/common/errors'; -import env = require('vs/base/common/platform'); -import DOM = require('vs/base/browser/dom'); +import * as env from 'vs/base/common/platform'; +import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction } from 'vs/base/common/actions'; import { Button } from 'vs/base/browser/ui/button/button'; @@ -56,7 +56,7 @@ export class EmptyView extends ViewsViewletPanel { let section = $('div.section').appendTo(container); - this.button = new Button(section); + this.button = new Button(section.getHTMLElement()); attachButtonStyler(this.button, this.themeService); this.disposables.push(this.button.onDidClick(() => { diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts index 8e36b13178..b41a18d76d 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts @@ -6,7 +6,7 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { Model } from 'vs/workbench/parts/files/common/explorerModel'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -22,7 +22,7 @@ export class ExplorerDecorationsProvider implements IDecorationsProvider { @IWorkspaceContextService contextService: IWorkspaceContextService ) { contextService.onDidChangeWorkspaceFolders(e => { - this._onDidChange.fire(e.changed.map(wf => wf.uri)); + this._onDidChange.fire(e.changed.concat(e.added).map(wf => wf.uri)); }); } diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts index 95d65d24ae..af5fec3c77 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import { Builder, $ } from 'vs/base/browser/builder'; import URI from 'vs/base/common/uri'; import { ThrottledDelayer, Delayer } from 'vs/base/common/async'; -import errors = require('vs/base/common/errors'); -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); -import glob = require('vs/base/common/glob'); +import * as errors from 'vs/base/common/errors'; +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; +import * as glob from 'vs/base/common/glob'; import { Action, IAction } from 'vs/base/common/actions'; import { memoize } from 'vs/base/common/decorators'; import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, SortOrderConfiguration, SortOrder, IExplorerView, ExplorerRootContext } from 'vs/workbench/parts/files/common/files'; @@ -25,7 +24,7 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer import * as DOM from 'vs/base/browser/dom'; import { CollapseAction } from 'vs/workbench/browser/viewlet'; import { IViewletViewOptions, IViewOptions, TreeViewsViewletPanel, FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { FileStat, Model } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem, Model } from 'vs/workbench/parts/files/common/explorerModel'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ExplorerDecorationsProvider } from 'vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider'; @@ -160,7 +159,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView public renderBody(container: HTMLElement): void { this.treeContainer = DOM.append(container, DOM.$('.explorer-folders-view')); - this.tree = this.createViewer($(this.treeContainer)); + this.tree = this.createViewer(this.treeContainer); if (this.toolbar) { this.toolbar.setActions(this.getActions(), this.getSecondaryActions())(); @@ -227,7 +226,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView this.settings[ExplorerView.MEMENTO_LAST_ACTIVE_FILE_RESOURCE] = activeFile.toString(); // Select file if input is inside workspace - if (this.isVisible() && this.contextService.isInsideWorkspace(activeFile)) { + if (this.isVisible() && !this.isDisposed && this.contextService.isInsideWorkspace(activeFile)) { const selection = this.hasSingleSelection(activeFile); if (!selection) { this.select(activeFile).done(null, errors.onUnexpectedError); @@ -299,7 +298,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } // Pass Focus to Viewer - this.explorerViewer.DOMFocus(); + this.explorerViewer.domFocus(); keepFocus = true; } @@ -364,7 +363,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } private openFocusedElement(preserveFocus?: boolean): void { - const stat: FileStat = this.explorerViewer.getFocus(); + const stat: ExplorerItem = this.explorerViewer.getFocus(); if (stat && !stat.isDirectory) { this.editorService.openEditor({ resource: stat.resource, options: { preserveFocus, revealIfVisible: true } }).done(null, errors.onUnexpectedError); } @@ -394,7 +393,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView return model; } - private createViewer(container: Builder): WorkbenchTree { + private createViewer(container: HTMLElement): WorkbenchTree { const dataSource = this.instantiationService.createInstance(FileDataSource); const renderer = this.instantiationService.createInstance(FileRenderer, this.viewletState); const controller = this.instantiationService.createInstance(FileController); @@ -406,7 +405,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView const dnd = this.instantiationService.createInstance(FileDragAndDrop); const accessibilityProvider = this.instantiationService.createInstance(FileAccessibilityProvider); - this.explorerViewer = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, container.getHTMLElement(), { + this.explorerViewer = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, container, { dataSource, renderer, controller, @@ -428,7 +427,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView this.disposables.push(this.fileService.onFileChanges(e => this.onFileChanges(e))); // Update resource context based on focused element - this.disposables.push(this.explorerViewer.onDidChangeFocus((e: { focus: FileStat }) => { + this.disposables.push(this.explorerViewer.onDidChangeFocus((e: { focus: ExplorerItem }) => { const isSingleFolder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER; const resource = e.focus ? e.focus.resource : isSingleFolder ? this.contextService.getWorkspace().folders[0].uri : undefined; this.resourceContext.set(resource); @@ -441,7 +440,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView if (event && event.payload && event.payload.origin === 'keyboard') { const element = this.tree.getSelection(); - if (Array.isArray(element) && element[0] instanceof FileStat) { + if (Array.isArray(element) && element[0] instanceof ExplorerItem) { if (element[0].isDirectory) { this.explorerViewer.toggleExpansion(element[0]); } @@ -471,7 +470,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } // Add - if (e.operation === FileOperation.CREATE || e.operation === FileOperation.IMPORT || e.operation === FileOperation.COPY) { + if (e.operation === FileOperation.CREATE || e.operation === FileOperation.COPY) { const addedElement = e.target; const parentResource = resources.dirname(addedElement.resource); const parents = this.model.findAll(parentResource); @@ -483,11 +482,11 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // We have to check if the parent is resolved #29177 (p.isDirectoryResolved ? TPromise.as(null) : this.fileService.resolveFile(p.resource)).then(stat => { if (stat) { - const modelStat = FileStat.create(stat, p.root); - FileStat.mergeLocalWithDisk(modelStat, p); + const modelStat = ExplorerItem.create(stat, p.root); + ExplorerItem.mergeLocalWithDisk(modelStat, p); } - const childElement = FileStat.create(addedElement, p.root); + const childElement = ExplorerItem.create(addedElement, p.root); p.removeChild(childElement); // make sure to remove any previous version of the file if any p.addChild(childElement); // Refresh the Parent (View) @@ -513,7 +512,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // Only update focus if renamed/moved element is selected let restoreFocus = false; - const focus: FileStat = this.explorerViewer.getFocus(); + const focus: ExplorerItem = this.explorerViewer.getFocus(); if (focus && focus.resource && focus.resource.toString() === oldResource.toString()) { restoreFocus = true; } @@ -580,7 +579,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // Ensure viewer has keyboard focus if event originates from viewer if (restoreFocus) { - this.explorerViewer.DOMFocus(); + this.explorerViewer.domFocus(); } }, errors.onUnexpectedError); } @@ -611,24 +610,21 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } private shouldRefreshFromEvent(e: FileChangesEvent): boolean { - - // Filter to the ones we care - e = this.filterFileEvents(e); - if (!this.isCreated) { return false; } - if (e.gotAdded()) { - const added = e.getAdded(); + // Filter to the ones we care + e = this.filterToViewRelevantEvents(e); + + // Handle added files/folders + const added = e.getAdded(); + if (added.length) { // Check added: Refresh if added file/folder is not part of resolved root and parent is part of it const ignoredPaths: { [resource: string]: boolean } = <{ [resource: string]: boolean }>{}; for (let i = 0; i < added.length; i++) { const change = added[i]; - if (!this.contextService.isInsideWorkspace(change.resource)) { - continue; // out of workspace file - } // Find parent const parent = resources.dirname(change.resource); @@ -651,15 +647,13 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } } - if (e.gotDeleted()) { - const deleted = e.getDeleted(); + // Handle deleted files/folders + const deleted = e.getDeleted(); + if (deleted.length) { // Check deleted: Refresh if deleted file/folder part of resolved root for (let j = 0; j < deleted.length; j++) { const del = deleted[j]; - if (!this.contextService.isInsideWorkspace(del.resource)) { - continue; // out of workspace file - } if (this.model.findClosest(del.resource)) { return true; @@ -667,15 +661,13 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } } - if (this.sortOrder === SortOrderConfiguration.MODIFIED && e.gotUpdated()) { + // Handle updated files/folders if we sort by modified + if (this.sortOrder === SortOrderConfiguration.MODIFIED) { const updated = e.getUpdated(); // Check updated: Refresh if updated file/folder part of resolved root for (let j = 0; j < updated.length; j++) { const upd = updated[j]; - if (!this.contextService.isInsideWorkspace(upd.resource)) { - continue; // out of workspace file - } if (this.model.findClosest(upd.resource)) { return true; @@ -686,8 +678,12 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView return false; } - private filterFileEvents(e: FileChangesEvent): FileChangesEvent { + private filterToViewRelevantEvents(e: FileChangesEvent): FileChangesEvent { return new FileChangesEvent(e.changes.filter(change => { + if (change.type === FileChangeType.UPDATED && this.sortOrder !== SortOrderConfiguration.MODIFIED) { + return false; // we only are about updated if we sort by modified time + } + if (!this.contextService.isInsideWorkspace(change.resource)) { return false; // exclude changes for resources outside of workspace } @@ -701,7 +697,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } private refreshFromEvent(newRoots: IWorkspaceFolder[] = []): void { - if (this.isVisible()) { + if (this.isVisible() && !this.isDisposed) { this.explorerRefreshDelayer.trigger(() => { if (!this.explorerViewer.getHighlight()) { return this.doRefresh(newRoots.map(r => r.uri)).then(() => { @@ -729,7 +725,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } // Focus - this.explorerViewer.DOMFocus(); + this.explorerViewer.domFocus(); // Find resource to focus from active editor input if set let resourceToFocus: URI; @@ -738,7 +734,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView if (!resourceToFocus) { const selection = this.explorerViewer.getSelection(); if (selection && selection.length === 1) { - resourceToFocus = (selection[0]).resource; + resourceToFocus = (selection[0]).resource; } } } @@ -788,11 +784,11 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView return promise; } - private resolveRoots(targetsToResolve: { root: FileStat, resource: URI, options: { resolveTo: any[] } }[], targetsToExpand: URI[]): TPromise { + private resolveRoots(targetsToResolve: { root: ExplorerItem, resource: URI, options: { resolveTo: any[] } }[], targetsToExpand: URI[]): TPromise { // Display roots only when multi folder workspace const input = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? this.model.roots[0] : this.model; - const errorFileStat = (resource: URI, root: FileStat) => FileStat.create({ + const errorFileStat = (resource: URI, root: ExplorerItem) => ExplorerItem.create({ resource: resource, name: paths.basename(resource.fsPath), mtime: 0, @@ -800,7 +796,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView isDirectory: true }, root); - const setInputAndExpand = (input: FileStat | Model, statsToExpand: FileStat[]) => { + const setInputAndExpand = (input: ExplorerItem | Model, statsToExpand: ExplorerItem[]) => { // Make sure to expand all folders that where expanded in the previous session // Special case: we are switching to multi workspace view, thus expand all the roots (they might just be added) if (input === this.model && statsToExpand.every(fs => fs && !fs.isRoot)) { @@ -815,8 +811,8 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView return this.fileService.resolveFiles(targetsToResolve).then(results => { // Convert to model const modelStats = results.map((result, index) => { - if (result.success) { - return FileStat.create(result.stat, targetsToResolve[index].root, targetsToResolve[index].options.resolveTo); + if (result.success && result.stat.isDirectory) { + return ExplorerItem.create(result.stat, targetsToResolve[index].root, targetsToResolve[index].options.resolveTo); } return errorFileStat(targetsToResolve[index].resource, targetsToResolve[index].root); @@ -824,11 +820,11 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // Subsequent refresh: Merge stat into our local model and refresh tree modelStats.forEach((modelStat, index) => { if (index < this.model.roots.length) { - FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index]); + ExplorerItem.mergeLocalWithDisk(modelStat, this.model.roots[index]); } }); - const statsToExpand: FileStat[] = this.explorerViewer.getExpandedElements().concat(targetsToExpand.map(expand => this.model.findClosest(expand))); + const statsToExpand: ExplorerItem[] = this.explorerViewer.getExpandedElements().concat(targetsToExpand.map(expand => this.model.findClosest(expand))); if (input === this.explorerViewer.getInput()) { return this.explorerViewer.refresh().then(() => this.explorerViewer.expandAll(statsToExpand)); } @@ -838,18 +834,18 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } // There is a remote root, resolve the roots sequantally - let statsToExpand: FileStat[] = []; + let statsToExpand: ExplorerItem[] = []; let delayer = new Delayer(100); let delayerPromise: TPromise; return TPromise.join(targetsToResolve.map((target, index) => this.fileService.resolveFile(target.resource, target.options) - .then(result => FileStat.create(result, target.root, target.options.resolveTo), err => errorFileStat(target.resource, target.root)) + .then(result => result.isDirectory ? ExplorerItem.create(result, target.root, target.options.resolveTo) : errorFileStat(target.resource, target.root), err => errorFileStat(target.resource, target.root)) .then(modelStat => { // Subsequent refresh: Merge stat into our local model and refresh tree if (index < this.model.roots.length) { - FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index]); + ExplorerItem.mergeLocalWithDisk(modelStat, this.model.roots[index]); } - let toExpand: FileStat[] = this.explorerViewer.getExpandedElements().concat(targetsToExpand.map(target => this.model.findClosest(target))); + let toExpand: ExplorerItem[] = this.explorerViewer.getExpandedElements().concat(targetsToExpand.map(target => this.model.findClosest(target))); if (input === this.explorerViewer.getInput()) { statsToExpand = statsToExpand.concat(toExpand); if (!delayer.isTriggered()) { @@ -869,7 +865,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView /** * Given a stat, fills an array of path that make all folders below the stat that are resolved directories. */ - private getResolvedDirectories(stat: FileStat, resolvedDirectories: URI[]): void { + private getResolvedDirectories(stat: ExplorerItem, resolvedDirectories: URI[]): void { if (stat.isDirectoryResolved) { if (!stat.isRoot) { @@ -886,10 +882,9 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView } // Recurse into children - for (let i = 0; i < stat.children.length; i++) { - const child = stat.children[i]; + stat.getChildrenArray().forEach(child => { this.getResolvedDirectories(child, resolvedDirectories); - } + }); } } @@ -928,9 +923,9 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // Convert to model const root = this.model.roots.filter(r => r.resource.toString() === rootUri.toString()).pop(); - const modelStat = FileStat.create(stat, root, options.resolveTo); + const modelStat = ExplorerItem.create(stat, root, options.resolveTo); // Update Input with disk Stat - FileStat.mergeLocalWithDisk(modelStat, root); + ExplorerItem.mergeLocalWithDisk(modelStat, root); // Select and Reveal return this.explorerViewer.refresh(root).then(() => this.doSelect(root.find(resource), reveal)); @@ -938,14 +933,14 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView }, e => { this.notificationService.error(e); }); } - private hasSingleSelection(resource: URI): FileStat { - const currentSelection: FileStat[] = this.explorerViewer.getSelection(); + private hasSingleSelection(resource: URI): ExplorerItem { + const currentSelection: ExplorerItem[] = this.explorerViewer.getSelection(); return currentSelection.length === 1 && currentSelection[0].resource.toString() === resource.toString() ? currentSelection[0] : undefined; } - private doSelect(fileStat: FileStat, reveal: boolean): TPromise { + private doSelect(fileStat: ExplorerItem, reveal: boolean): TPromise { if (!fileStat) { return TPromise.as(null); } @@ -988,8 +983,8 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView // Keep list of expanded folders to restore on next load if (this.isCreated) { const expanded = this.explorerViewer.getExpandedElements() - .filter(e => e instanceof FileStat) - .map((e: FileStat) => e.resource.toString()); + .filter(e => e instanceof ExplorerItem) + .map((e: ExplorerItem) => e.resource.toString()); if (expanded.length) { this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES] = expanded; diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts index 2b2d5ded6d..07b984e697 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts @@ -5,31 +5,30 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import lifecycle = require('vs/base/common/lifecycle'); -import objects = require('vs/base/common/objects'); -import DOM = require('vs/base/browser/dom'); +import * as nls from 'vs/nls'; +import * as objects from 'vs/base/common/objects'; +import * as DOM from 'vs/base/browser/dom'; +import * as path from 'path'; import URI from 'vs/base/common/uri'; import { once } from 'vs/base/common/functional'; -import paths = require('vs/base/common/paths'); -import resources = require('vs/base/common/resources'); -import errors = require('vs/base/common/errors'); +import * as paths from 'vs/base/common/paths'; +import * as resources from 'vs/base/common/resources'; +import * as errors from 'vs/base/common/errors'; import { IAction, ActionRunner as BaseActionRunner, IActionRunner } from 'vs/base/common/actions'; -import comparers = require('vs/base/common/comparers'); +import * as comparers from 'vs/base/common/comparers'; import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { isMacintosh, isLinux } from 'vs/base/common/platform'; -import glob = require('vs/base/common/glob'); +import * as glob from 'vs/base/common/glob'; import { FileLabel, IFileLabelOptions } from 'vs/workbench/browser/labels'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, empty as EmptyDisposable } from 'vs/base/common/lifecycle'; import { IFilesConfiguration, SortOrder } from 'vs/workbench/parts/files/common/files'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { FileOperationError, FileOperationResult, IFileService, FileKind } from 'vs/platform/files/common/files'; -import { ResourceMap } from 'vs/base/common/map'; -import { DuplicateFileAction, ImportFileAction, IEditableData, IFileViewletState, FileCopiedContext } from 'vs/workbench/parts/files/electron-browser/fileActions'; +import { DuplicateFileAction, AddFilesAction, IEditableData, IFileViewletState, FileCopiedContext } from 'vs/workbench/parts/files/electron-browser/fileActions'; import { IDataSource, ITree, IAccessibilityProvider, IRenderer, ContextMenuEvent, ISorter, IFilter, IDragAndDropData, IDragOverReaction, DRAG_OVER_ACCEPT_BUBBLE_DOWN, DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY, DRAG_OVER_ACCEPT_BUBBLE_UP, DRAG_OVER_ACCEPT_BUBBLE_UP_COPY, DRAG_OVER_REJECT } from 'vs/base/parts/tree/browser/tree'; import { DesktopDragAndDropData, ExternalElementsDragAndDropData } from 'vs/base/parts/tree/browser/treeDnd'; import { ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults'; -import { FileStat, NewStatPlaceholder, Model } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem, NewStatPlaceholder, Model } from 'vs/workbench/parts/files/common/explorerModel'; import { DragMouseEvent, IMouseEvent } from 'vs/base/browser/mouseEvent'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; @@ -50,15 +49,13 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { extractResources, SimpleFileResourceDragAndDrop, CodeDataTransfers, fillResourceDataTransfers } from 'vs/workbench/browser/dnd'; -import { relative } from 'path'; -import { distinctParents } from 'vs/base/common/resources'; import { WorkbenchTree, WorkbenchTreeController } from 'vs/platform/list/browser/listService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { DataTransfers } from 'vs/base/browser/dnd'; import { Schemas } from 'vs/base/common/network'; import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; -import { IConfirmationService, IConfirmationResult, IConfirmation } from 'vs/platform/dialogs/common/dialogs'; -import { getConfirmMessage } from 'vs/workbench/services/dialogs/electron-browser/dialogs'; +import { rtrim } from 'vs/base/common/strings'; +import { IDialogService, IConfirmationResult, IConfirmation, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; export class FileDataSource implements IDataSource { @@ -69,7 +66,7 @@ export class FileDataSource implements IDataSource { @IPartService private partService: IPartService ) { } - public getId(tree: ITree, stat: FileStat | Model): string { + public getId(tree: ITree, stat: ExplorerItem | Model): string { if (stat instanceof Model) { return 'model'; } @@ -77,18 +74,18 @@ export class FileDataSource implements IDataSource { return `${stat.root.resource.toString()}:${stat.getId()}`; } - public hasChildren(tree: ITree, stat: FileStat | Model): boolean { - return stat instanceof Model || (stat instanceof FileStat && stat.isDirectory); + public hasChildren(tree: ITree, stat: ExplorerItem | Model): boolean { + return stat instanceof Model || (stat instanceof ExplorerItem && (stat.isDirectory || stat.isRoot)); } - public getChildren(tree: ITree, stat: FileStat | Model): TPromise { + public getChildren(tree: ITree, stat: ExplorerItem | Model): TPromise { if (stat instanceof Model) { return TPromise.as(stat.roots); } // Return early if stat is already resolved if (stat.isDirectoryResolved) { - return TPromise.as(stat.children); + return TPromise.as(stat.getChildrenArray()); } // Resolve children and add to fileStat for future lookup @@ -98,18 +95,24 @@ export class FileDataSource implements IDataSource { const promise = this.fileService.resolveFile(stat.resource, { resolveSingleChildDescendants: true }).then(dirStat => { // Convert to view model - const modelDirStat = FileStat.create(dirStat, stat.root); + const modelDirStat = ExplorerItem.create(dirStat, stat.root); // Add children to folder - for (let i = 0; i < modelDirStat.children.length; i++) { - stat.addChild(modelDirStat.children[i]); + const children = modelDirStat.getChildrenArray(); + if (children) { + children.forEach(child => { + stat.addChild(child); + }); } stat.isDirectoryResolved = true; - return stat.children; + return stat.getChildrenArray(); }, (e: any) => { - this.notificationService.error(e); + // Do not show error for roots since we already use an explorer decoration to notify user + if (!(stat instanceof ExplorerItem && stat.isRoot)) { + this.notificationService.error(e); + } return []; // we could not resolve any children because of an error }); @@ -120,7 +123,7 @@ export class FileDataSource implements IDataSource { } } - public getParent(tree: ITree, stat: FileStat | Model): TPromise { + public getParent(tree: ITree, stat: ExplorerItem | Model): TPromise { if (!stat) { return TPromise.as(null); // can be null if nothing selected in the tree } @@ -131,7 +134,7 @@ export class FileDataSource implements IDataSource { } // Return if parent already resolved - if (stat instanceof FileStat && stat.parent) { + if (stat instanceof ExplorerItem && stat.parent) { return TPromise.as(stat.parent); } @@ -143,24 +146,24 @@ export class FileDataSource implements IDataSource { } export class FileViewletState implements IFileViewletState { - private editableStats: ResourceMap; + private editableStats: Map; constructor() { - this.editableStats = new ResourceMap(); + this.editableStats = new Map(); } - public getEditableData(stat: FileStat): IEditableData { - return this.editableStats.get(stat.resource); + public getEditableData(stat: ExplorerItem): IEditableData { + return this.editableStats.get(stat); } - public setEditable(stat: FileStat, editableData: IEditableData): void { + public setEditable(stat: ExplorerItem, editableData: IEditableData): void { if (editableData) { - this.editableStats.set(stat.resource, editableData); + this.editableStats.set(stat, editableData); } } - public clearEditable(stat: FileStat): void { - this.editableStats.delete(stat.resource); + public clearEditable(stat: ExplorerItem): void { + this.editableStats.delete(stat); } } @@ -179,6 +182,7 @@ export class ActionRunner extends BaseActionRunner implements IActionRunner { } export interface IFileTemplateData { + elementDisposable: IDisposable; label: FileLabel; container: HTMLElement; } @@ -224,16 +228,20 @@ export class FileRenderer implements IRenderer { } public disposeTemplate(tree: ITree, templateId: string, templateData: IFileTemplateData): void { + templateData.elementDisposable.dispose(); templateData.label.dispose(); } public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): IFileTemplateData { + const elementDisposable = EmptyDisposable; const label = this.instantiationService.createInstance(FileLabel, container, void 0); - return { label, container }; + return { elementDisposable, label, container }; } - public renderElement(tree: ITree, stat: FileStat, templateId: string, templateData: IFileTemplateData): void { + public renderElement(tree: ITree, stat: ExplorerItem, templateId: string, templateData: IFileTemplateData): void { + templateData.elementDisposable.dispose(); + const editableData: IEditableData = this.state.getEditableData(stat); // File Label @@ -246,16 +254,21 @@ export class FileRenderer implements IRenderer { extraClasses, fileDecorations: this.config.explorer.decorations }); + + templateData.elementDisposable = templateData.label.onDidRender(() => { + tree.updateWidth(stat); + }); } // Input Box else { templateData.label.element.style.display = 'none'; this.renderInputBox(templateData.container, tree, stat, editableData); + templateData.elementDisposable = EmptyDisposable; } } - private renderInputBox(container: HTMLElement, tree: ITree, stat: FileStat, editableData: IEditableData): void { + private renderInputBox(container: HTMLElement, tree: ITree, stat: ExplorerItem, editableData: IEditableData): void { // Use a file label only for the icon next to the input box const label = this.instantiationService.createInstance(FileLabel, container, void 0); @@ -294,9 +307,9 @@ export class FileRenderer implements IRenderer { setTimeout(() => { if (!blur) { // https://github.com/Microsoft/vscode/issues/20269 - tree.DOMFocus(); + tree.domFocus(); } - lifecycle.dispose(toDispose); + dispose(toDispose); container.removeChild(label.element); }, 0); }); @@ -313,12 +326,12 @@ export class FileRenderer implements IRenderer { } }), DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => { - const initialRelPath: string = relative(stat.root.resource.fsPath, stat.parent.resource.fsPath); + const initialRelPath: string = path.relative(stat.root.resource.path, stat.parent.resource.path); let projectFolderName: string = ''; if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - projectFolderName = paths.basename(stat.root.resource.fsPath); // show root folder name in multi-folder project + projectFolderName = paths.basename(stat.root.resource.path); // show root folder name in multi-folder project } - this.displayCurrentPath(inputBox, initialRelPath, fileKind, projectFolderName); + this.displayCurrentPath(inputBox, initialRelPath, projectFolderName, editableData.action.id); }), DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => { done(inputBox.isInputValid(), true); @@ -328,20 +341,39 @@ export class FileRenderer implements IRenderer { ]; } - private displayCurrentPath(inputBox: InputBox, initialRelPath: string, fileKind: FileKind, projectFolderName?: string) { + private displayCurrentPath(inputBox: InputBox, initialRelPath: string, projectFolderName: string = '', actionID: string) { if (inputBox.validate()) { const value = inputBox.value; - if (value && value.search(/[\\/]/) !== -1) { // only show if there's a slash + if (value && /.[\\/]./.test(value)) { // only show if there's at least one slash enclosed in the string + let displayPath = path.normalize(path.join(projectFolderName, initialRelPath, value)); + displayPath = rtrim(displayPath, paths.nativeSep); - const newPath = paths.normalize(paths.join(projectFolderName, initialRelPath, value), true); - const fileType: string = FileKind[fileKind].toLowerCase(); + const indexLastSlash: number = displayPath.lastIndexOf(paths.nativeSep); + const name: string = displayPath.substring(indexLastSlash + 1); + const leadingPathPart: string = displayPath.substring(0, indexLastSlash); + + let msg: string; + switch (actionID) { + case 'workbench.files.action.createFileFromExplorer': + msg = nls.localize('createFileFromExplorerInfoMessage', "Create file **{0}** in **{1}**", name, leadingPathPart); + break; + case 'workbench.files.action.renameFile': + msg = nls.localize('renameFileFromExplorerInfoMessage', "Move and rename to **{0}**", displayPath); + break; + case 'workbench.files.action.createFolderFromExplorer': // fallthrough + default: + msg = nls.localize('createFolderFromExplorerInfoMessage', "Create folder **{0}** in **{1}**", name, leadingPathPart); + } inputBox.showMessage({ type: MessageType.INFO, - content: nls.localize('constructedPath', "Create {0} in **{1}**", fileType, newPath), + content: msg, formatContent: true }); } + else { // fixes #46744: inputbox hides again if all slashes are removed + inputBox.hideMessage(); + } } } } @@ -349,7 +381,7 @@ export class FileRenderer implements IRenderer { // Explorer Accessibility Provider export class FileAccessibilityProvider implements IAccessibilityProvider { - public getAriaLabel(tree: ITree, stat: FileStat): string { + public getAriaLabel(tree: ITree, stat: ExplorerItem): string { return nls.localize('filesExplorerViewerAriaLabel', "{0}, Files Explorer", stat.name); } } @@ -359,7 +391,7 @@ export class FileController extends WorkbenchTreeController implements IDisposab private fileCopiedContextKey: IContextKey; private contributedContextMenu: IMenu; private toDispose: IDisposable[]; - private previousSelectionRangeStop: FileStat; + private previousSelectionRangeStop: ExplorerItem; constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @@ -376,7 +408,7 @@ export class FileController extends WorkbenchTreeController implements IDisposab this.toDispose = []; } - public onLeftClick(tree: WorkbenchTree, stat: FileStat | Model, event: IMouseEvent, origin: string = 'mouse'): boolean { + public onLeftClick(tree: WorkbenchTree, stat: ExplorerItem | Model, event: IMouseEvent, origin: string = 'mouse'): boolean { const payload = { origin: origin }; const isDoubleClick = (origin === 'mouse' && event.detail === 2); @@ -408,7 +440,7 @@ export class FileController extends WorkbenchTreeController implements IDisposab event.stopPropagation(); // Set DOM focus - tree.DOMFocus(); + tree.domFocus(); if (stat instanceof NewStatPlaceholder) { return true; } @@ -468,7 +500,7 @@ export class FileController extends WorkbenchTreeController implements IDisposab return true; } - public onContextMenu(tree: WorkbenchTree, stat: FileStat | Model, event: ContextMenuEvent): boolean { + public onContextMenu(tree: WorkbenchTree, stat: ExplorerItem | Model, event: ContextMenuEvent): boolean { if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') { return false; } @@ -492,23 +524,23 @@ export class FileController extends WorkbenchTreeController implements IDisposab getAnchor: () => anchor, getActions: () => { const actions: IAction[] = []; - fillInActions(this.contributedContextMenu, { arg: stat instanceof FileStat ? stat.resource : {}, shouldForwardArgs: true }, actions, this.contextMenuService); + fillInActions(this.contributedContextMenu, { arg: stat instanceof ExplorerItem ? stat.resource : {}, shouldForwardArgs: true }, actions, this.contextMenuService); return TPromise.as(actions); }, onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } }, getActionsContext: () => selection && selection.indexOf(stat) >= 0 - ? selection.map((fs: FileStat) => fs.resource) - : stat instanceof FileStat ? [stat.resource] : [] + ? selection.map((fs: ExplorerItem) => fs.resource) + : stat instanceof ExplorerItem ? [stat.resource] : [] }); return true; } - public openEditor(stat: FileStat, options: { preserveFocus: boolean; sideBySide: boolean; pinned: boolean; }): void { + public openEditor(stat: ExplorerItem, options: { preserveFocus: boolean; sideBySide: boolean; pinned: boolean; }): void { if (stat && !stat.isDirectory) { /* __GDPR__ "workbenchActionExecuted" : { @@ -551,7 +583,7 @@ export class FileSorter implements ISorter { this.sortOrder = this.configurationService.getValue('explorer.sortOrder') || 'default'; } - public compare(tree: ITree, statA: FileStat, statB: FileStat): number { + public compare(tree: ITree, statA: ExplorerItem, statB: ExplorerItem): number { // Do not sort roots if (statA.isRoot) { @@ -673,25 +705,27 @@ export class FileFilter implements IFilter { return needsRefresh; } - public isVisible(tree: ITree, stat: FileStat): boolean { + public isVisible(tree: ITree, stat: ExplorerItem): boolean { return this.doIsVisible(stat); } - private doIsVisible(stat: FileStat): boolean { + private doIsVisible(stat: ExplorerItem): boolean { if (stat instanceof NewStatPlaceholder || stat.isRoot) { return true; // always visible } // Workaround for O(N^2) complexity (https://github.com/Microsoft/vscode/issues/9962) - let siblings = stat.parent && stat.parent.children && stat.parent.children; - if (siblings && siblings.length > FileFilter.MAX_SIBLINGS_FILTER_THRESHOLD) { - siblings = void 0; + let siblingsFn: () => string[]; + let siblingCount = stat.parent && stat.parent.getChildrenCount(); + if (siblingCount && siblingCount > FileFilter.MAX_SIBLINGS_FILTER_THRESHOLD) { + siblingsFn = () => void 0; + } else { + siblingsFn = () => stat.parent ? stat.parent.getChildrenNames() : void 0; } // Hide those that match Hidden Patterns - const siblingsFn = () => siblings && siblings.map(c => c.name); const expression = this.hiddenExpressionPerRoot.get(stat.root.resource.toString()) || Object.create(null); - if (glob.match(expression, paths.normalize(relative(stat.root.resource.fsPath, stat.resource.fsPath), true), siblingsFn)) { + if (glob.match(expression, paths.normalize(path.relative(stat.root.resource.path, stat.resource.path), true), siblingsFn)) { return false; // hidden through pattern } @@ -713,7 +747,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { constructor( @INotificationService private notificationService: INotificationService, - @IConfirmationService private confirmationService: IConfirmationService, + @IDialogService private dialogService: IDialogService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IFileService private fileService: IFileService, @IConfigurationService private configurationService: IConfigurationService, @@ -732,7 +766,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { this.registerListeners(); } - private statToResource(stat: FileStat): URI { + private statToResource(stat: ExplorerItem): URI { if (stat.isDirectory) { return URI.from({ scheme: 'folder', path: stat.resource.path }); // indicates that we are dragging a folder } @@ -749,7 +783,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } public onDragStart(tree: ITree, data: IDragAndDropData, originalEvent: DragMouseEvent): void { - const sources: FileStat[] = data.getData(); + const sources: ExplorerItem[] = data.getData(); if (sources && sources.length) { // When dragging folders, make sure to collapse them to free up some space @@ -771,7 +805,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } } - public onDragOver(tree: ITree, data: IDragAndDropData, target: FileStat | Model, originalEvent: DragMouseEvent): IDragOverReaction { + public onDragOver(tree: ITree, data: IDragAndDropData, target: ExplorerItem | Model, originalEvent: DragMouseEvent): IDragOverReaction { if (!this.dropEnabled) { return DRAG_OVER_REJECT; } @@ -799,9 +833,9 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // In-Explorer DND else { - const sources: FileStat[] = data.getData(); + const sources: ExplorerItem[] = data.getData(); if (target instanceof Model) { - if (sources.length === 1 && sources[0].isRoot) { + if (sources[0].isRoot) { return DRAG_OVER_ACCEPT_BUBBLE_DOWN(false); } @@ -817,8 +851,8 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return true; // NewStatPlaceholders can not be moved } - if (source.isRoot && (sources.length > 1 || target instanceof FileStat && !target.isRoot)) { - return true; // Root folder can not be moved to a non root file stat. Do not allow root folder move when multi selection drag. + if (source.isRoot && target instanceof ExplorerItem && !target.isRoot) { + return true; // Root folder can not be moved to a non root file stat. } if (source.resource.toString() === target.resource.toString()) { @@ -858,7 +892,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return DRAG_OVER_REJECT; } - public drop(tree: ITree, data: IDragAndDropData, target: FileStat | Model, originalEvent: DragMouseEvent): void { + public drop(tree: ITree, data: IDragAndDropData, target: ExplorerItem | Model, originalEvent: DragMouseEvent): void { let promise: TPromise = TPromise.as(null); // Desktop DND (Import file) @@ -877,7 +911,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // {{SQL CARBON EDIT}} public dropAbort(tree: ITree, data: IDragAndDropData): void { } - private handleExternalDrop(tree: ITree, data: DesktopDragAndDropData, target: FileStat | Model, originalEvent: DragMouseEvent): TPromise { + private handleExternalDrop(tree: ITree, data: DesktopDragAndDropData, target: ExplorerItem | Model, originalEvent: DragMouseEvent): TPromise { const droppedResources = extractResources(originalEvent.browserEvent as DragEvent, true); // Check for dropped external files to be folders @@ -891,17 +925,17 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { if (folders.length > 0) { // If we are in no-workspace context, ask for confirmation to create a workspace - let confirmedPromise = TPromise.wrap(true); + let confirmedPromise: TPromise = TPromise.wrap({ confirmed: true }); if (this.contextService.getWorkbenchState() !== WorkbenchState.WORKSPACE) { - confirmedPromise = this.confirmationService.confirm({ + confirmedPromise = this.dialogService.confirm({ message: folders.length > 1 ? nls.localize('dropFolders', "Do you want to add the folders to the workspace?") : nls.localize('dropFolder', "Do you want to add the folder to the workspace?"), type: 'question', primaryButton: folders.length > 1 ? nls.localize('addFolders', "&&Add Folders") : nls.localize('addFolder', "&&Add Folder") }); } - return confirmedPromise.then(confirmed => { - if (confirmed) { + return confirmedPromise.then(res => { + if (res.confirmed) { return this.workspaceEditingService.addFolders(folders); } @@ -910,18 +944,18 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } // Handle dropped files (only support FileStat as target) - else if (target instanceof FileStat) { - const importAction = this.instantiationService.createInstance(ImportFileAction, tree, target, null); + else if (target instanceof ExplorerItem) { + const addFilesAction = this.instantiationService.createInstance(AddFilesAction, tree, target, null); - return importAction.run(droppedResources.map(res => res.resource)); + return addFilesAction.run(droppedResources.map(res => res.resource)); } return void 0; }); } - private handleExplorerDrop(tree: ITree, data: IDragAndDropData, target: FileStat | Model, originalEvent: DragMouseEvent): TPromise { - const sources: FileStat[] = distinctParents(data.getData(), s => s.resource); + private handleExplorerDrop(tree: ITree, data: IDragAndDropData, target: ExplorerItem | Model, originalEvent: DragMouseEvent): TPromise { + const sources: ExplorerItem[] = resources.distinctParents(data.getData(), s => s.resource); const isCopy = (originalEvent.ctrlKey && !isMacintosh) || (originalEvent.altKey && isMacintosh); let confirmPromise: TPromise; @@ -929,9 +963,11 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // Handle confirm setting const confirmDragAndDrop = !isCopy && this.configurationService.getValue(FileDragAndDrop.CONFIRM_DND_SETTING_KEY); if (confirmDragAndDrop) { - confirmPromise = this.confirmationService.confirmWithCheckbox({ - message: sources.length > 1 ? getConfirmMessage(nls.localize('confirmMultiMove', "Are you sure you want to move the following {0} files?", sources.length), sources.map(s => s.resource)) - : nls.localize('confirmMove', "Are you sure you want to move '{0}'?", sources[0].name), + confirmPromise = this.dialogService.confirm({ + message: sources.length > 1 && sources.every(s => s.isRoot) ? nls.localize('confirmRootsMove', "Are you sure you want to change the order of multiple root folders in your workspace?") + : sources.length > 1 ? getConfirmMessage(nls.localize('confirmMultiMove', "Are you sure you want to move the following {0} files?", sources.length), sources.map(s => s.resource)) + : sources[0].isRoot ? nls.localize('confirmRootMove', "Are you sure you want to change the order of root folder '{0}' in your workspace?", sources[0].name) + : nls.localize('confirmMove', "Are you sure you want to move '{0}'?", sources[0].name), checkbox: { label: nls.localize('doNotAskAgain', "Do not ask me again") }, @@ -942,17 +978,18 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { confirmPromise = TPromise.as({ confirmed: true } as IConfirmationResult); } - return confirmPromise.then(confirmation => { + return confirmPromise.then(res => { // Check for confirmation checkbox let updateConfirmSettingsPromise: TPromise = TPromise.as(void 0); - if (confirmation.confirmed && confirmation.checkboxChecked === true) { + if (res.confirmed && res.checkboxChecked === true) { updateConfirmSettingsPromise = this.configurationService.updateValue(FileDragAndDrop.CONFIRM_DND_SETTING_KEY, false, ConfigurationTarget.USER); } return updateConfirmSettingsPromise.then(() => { - if (confirmation.confirmed) { - return TPromise.join(sources.map(source => this.doHandleExplorerDrop(tree, source, target, isCopy))).then(() => void 0); + if (res.confirmed) { + const rootDropPromise = this.doHandleRootDrop(sources.filter(s => s.isRoot), target); + return TPromise.join(sources.filter(s => !s.isRoot).map(source => this.doHandleExplorerDrop(tree, source, target, isCopy)).concat(rootDropPromise)).then(() => void 0); } return TPromise.as(void 0); @@ -960,39 +997,40 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { }); } - private doHandleExplorerDrop(tree: ITree, source: FileStat, target: FileStat | Model, isCopy: boolean): TPromise { - return tree.expand(target).then(() => { - if (source.isRoot) { - const folders = this.contextService.getWorkspace().folders; - let sourceIndex: number; - let targetIndex: number; - const workspaceCreationData: IWorkspaceFolderCreationData[] = []; - const targetUri = target instanceof FileStat ? target.resource : folders[folders.length - 1].uri; + private doHandleRootDrop(roots: ExplorerItem[], target: ExplorerItem | Model): TPromise { + if (roots.length === 0) { + return TPromise.as(undefined); + } - for (let index = 0; index < folders.length; index++) { - if (folders[index].uri.toString() === source.resource.toString()) { - sourceIndex = index; - } - if (folders[index].uri.toString() === targetUri.toString()) { - targetIndex = index; - } - workspaceCreationData.push({ - name: folders[index].name, - uri: folders[index].uri - }); + const folders = this.contextService.getWorkspace().folders; + let targetIndex: number; + const workspaceCreationData: IWorkspaceFolderCreationData[] = []; + const rootsToMove: IWorkspaceFolderCreationData[] = []; - if (sourceIndex && targetIndex) { - break; - } - } - - const swap = workspaceCreationData[sourceIndex]; - workspaceCreationData[sourceIndex] = workspaceCreationData[targetIndex]; - workspaceCreationData[targetIndex] = swap; - - return this.workspaceEditingService.updateFolders(Math.min(sourceIndex, targetIndex), workspaceCreationData.length, workspaceCreationData); + for (let index = 0; index < folders.length; index++) { + const data = { + uri: folders[index].uri + }; + if (target instanceof ExplorerItem && folders[index].uri.toString() === target.resource.toString()) { + targetIndex = workspaceCreationData.length; } + if (roots.every(r => r.resource.toString() !== folders[index].uri.toString())) { + workspaceCreationData.push(data); + } else { + rootsToMove.push(data); + } + } + if (target instanceof Model) { + targetIndex = workspaceCreationData.length; + } + + workspaceCreationData.splice(targetIndex, 0, ...rootsToMove); + return this.workspaceEditingService.updateFolders(0, workspaceCreationData.length, workspaceCreationData); + } + + private doHandleExplorerDrop(tree: ITree, source: ExplorerItem, target: ExplorerItem | Model, isCopy: boolean): TPromise { + return tree.expand(target).then(() => { // Reuse duplicate action if user copies if (isCopy) { return this.instantiationService.createInstance(DuplicateFileAction, tree, source, target).run(); @@ -1010,7 +1048,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return TPromise.join(dirtyMoved.map(d => this.backupFileService.discardResourceBackup(d))); }; - if (!(target instanceof FileStat)) { + if (!(target instanceof ExplorerItem)) { return TPromise.as(void 0); } @@ -1055,8 +1093,8 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { }; // Move with overwrite if the user confirms - return this.confirmationService.confirm(confirm).then(confirmed => { - if (confirmed) { + return this.dialogService.confirm(confirm).then(res => { + if (res.confirmed) { const targetDirty = this.textFileService.getDirty().filter(d => resources.isEqualOrParent(d, targetResource, !isLinux /* ignorecase */)); // Make sure to revert all dirty in target first to be able to overwrite properly diff --git a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts index c1adcd95a8..eea5c55273 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts @@ -580,8 +580,8 @@ class OpenEditorRenderer implements IRenderer - this.editorGroupService.moveEditor(oe.editor, model.positionOfGroup(oe.group), positionOfTargetGroup, { index, preserveFocus: true })); + this.transfer.getData(OpenEditor.prototype).forEach((oe, offset) => + this.editorGroupService.moveEditor(oe.editor, model.positionOfGroup(oe.group), positionOfTargetGroup, { index: index + offset, preserveFocus: true })); this.editorGroupService.activateGroup(positionOfTargetGroup); } else { const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: false }); diff --git a/src/vs/workbench/parts/files/test/browser/fileEditorInput.test.ts b/src/vs/workbench/parts/files/test/browser/fileEditorInput.test.ts index 1dfb76d612..70e842bec0 100644 --- a/src/vs/workbench/parts/files/test/browser/fileEditorInput.test.ts +++ b/src/vs/workbench/parts/files/test/browser/fileEditorInput.test.ts @@ -43,7 +43,7 @@ suite('Files - FileEditorInput', () => { accessor = instantiationService.createInstance(ServiceAccessor); }); - test('Basics', function (done) { + test('Basics', function () { let input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/file.js'), void 0); const otherInput = instantiationService.createInstance(FileEditorInput, toResource(this, 'foo/bar/otherfile.js'), void 0); const otherInputSame = instantiationService.createInstance(FileEditorInput, toResource(this, 'foo/bar/file.js'), void 0); @@ -96,8 +96,6 @@ suite('Files - FileEditorInput', () => { stat = (resolved as TextFileEditorModel).getStat(); return inputToResolve.resolve(false).then(resolved => { assert(stat === (resolved as TextFileEditorModel).getStat()); // Same stat, because not refreshed - - done(); }); }); }); @@ -121,7 +119,7 @@ suite('Files - FileEditorInput', () => { assert.strictEqual(input1.matches(input2Upper), false); }); - test('getEncoding/setEncoding', function (done) { + test('getEncoding/setEncoding', function () { const input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/updatefile.js'), void 0); input.setEncoding('utf16', EncodingMode.Encode); @@ -131,46 +129,40 @@ suite('Files - FileEditorInput', () => { assert.equal(input.getEncoding(), resolved.getEncoding()); resolved.dispose(); - - done(); }); }); - test('save', function (done) { + test('save', function () { const input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/updatefile.js'), void 0); return input.resolve(true).then((resolved: TextFileEditorModel) => { resolved.textEditorModel.setValue('changed'); assert.ok(input.isDirty()); - input.save().then(() => { + return input.save().then(() => { assert.ok(!input.isDirty()); resolved.dispose(); - - done(); }); }); }); - test('revert', function (done) { + test('revert', function () { const input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/updatefile.js'), void 0); return input.resolve(true).then((resolved: TextFileEditorModel) => { resolved.textEditorModel.setValue('changed'); assert.ok(input.isDirty()); - input.revert().then(() => { + return input.revert().then(() => { assert.ok(!input.isDirty()); resolved.dispose(); - - done(); }); }); }); - test('resolve handles binary files', function (done) { + test('resolve handles binary files', function () { const input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/updatefile.js'), void 0); accessor.textFileService.setResolveTextContentErrorOnce(new FileOperationError('error', FileOperationResult.FILE_IS_BINARY)); @@ -179,17 +171,27 @@ suite('Files - FileEditorInput', () => { assert.ok(resolved); resolved.dispose(); - - done(); }); }); - test('disposes model when not open anymore', function (done) { + test('resolve handles too large files', function () { + const input = instantiationService.createInstance(FileEditorInput, toResource(this, '/foo/bar/updatefile.js'), void 0); + + accessor.textFileService.setResolveTextContentErrorOnce(new FileOperationError('error', FileOperationResult.FILE_TOO_LARGE)); + + return input.resolve(true).then(resolved => { + assert.ok(resolved); + + resolved.dispose(); + }); + }); + + test('disposes model when not open anymore', function () { const resource = toResource(this, '/path/index.txt'); const input = createFileInput(instantiationService, resource); - input.resolve().then((model: TextFileEditorModel) => { + return input.resolve().then((model: TextFileEditorModel) => { const stacks = accessor.editorGroupService.getStacksModel(); const group = stacks.openGroup('group', true); group.openEditor(input); @@ -204,8 +206,6 @@ suite('Files - FileEditorInput', () => { model.dispose(); assert.ok(!accessor.modelService.getModel(model.getResource())); - - done(); }); }); }); \ No newline at end of file diff --git a/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts b/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts index 78fa5f0bf1..d50f95b3e5 100644 --- a/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts +++ b/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts @@ -184,16 +184,16 @@ suite('Files - FileEditorTracker', () => { tracker.dispose(); }); - test('file change event updates model', function (done) { + test('file change event updates model', function () { const tracker = instantiationService.createInstance(FileEditorTracker); const resource = toResource(this, '/path/index.txt'); - accessor.textFileService.models.loadOrCreate(resource).then((model: TextFileEditorModel) => { + return accessor.textFileService.models.loadOrCreate(resource).then((model: TextFileEditorModel) => { model.textEditorModel.setValue('Super Good'); assert.equal(snapshotToString(model.createSnapshot()), 'Super Good'); - model.save().then(() => { + return model.save().then(() => { // change event (watcher) accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource, type: FileChangeType.UPDATED }])); @@ -201,8 +201,6 @@ suite('Files - FileEditorTracker', () => { assert.equal(snapshotToString(model.createSnapshot()), 'Hello Html'); tracker.dispose(); - - done(); }); }); }); diff --git a/src/vs/workbench/parts/files/test/electron-browser/explorerModel.test.ts b/src/vs/workbench/parts/files/test/electron-browser/explorerModel.test.ts index c558ff79ab..04e718a005 100644 --- a/src/vs/workbench/parts/files/test/electron-browser/explorerModel.test.ts +++ b/src/vs/workbench/parts/files/test/electron-browser/explorerModel.test.ts @@ -6,15 +6,15 @@ 'use strict'; import * as assert from 'assert'; -import { isUndefinedOrNull, isArray } from 'vs/base/common/types'; +import { isUndefinedOrNull } from 'vs/base/common/types'; import { isLinux, isWindows } from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; import { join } from 'vs/base/common/paths'; import { validateFileName } from 'vs/workbench/parts/files/electron-browser/fileActions'; -import { FileStat } from 'vs/workbench/parts/files/common/explorerModel'; +import { ExplorerItem } from 'vs/workbench/parts/files/common/explorerModel'; -function createStat(path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number): FileStat { - return new FileStat(toResource(path), undefined, false, isFolder, name, mtime); +function createStat(path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number): ExplorerItem { + return new ExplorerItem(toResource(path), undefined, false, isFolder, name, mtime); } function toResource(path) { @@ -32,10 +32,10 @@ suite('Files - View Model', () => { assert.strictEqual(s.name, 'sName'); assert.strictEqual(s.isDirectory, true); assert.strictEqual(s.mtime, new Date(d).getTime()); - assert(isArray(s.children) && s.children.length === 0); + assert.strictEqual(s.getChildrenArray().length, 0); s = createStat('/path/to/stat', 'sName', false, false, 8096, d); - assert(isUndefinedOrNull(s.children)); + assert(isUndefinedOrNull(s.getChildrenArray())); }); test('Add and Remove Child, check for hasChild', function () { @@ -47,14 +47,14 @@ suite('Files - View Model', () => { s.addChild(child1); - assert(s.children.length === 1); + assert(s.getChildrenArray().length === 1); s.removeChild(child1); s.addChild(child1); - assert(s.children.length === 1); + assert(s.getChildrenArray().length === 1); s.removeChild(child1); - assert(s.children.length === 0); + assert(s.getChildrenArray().length === 0); // Assert that adding a child updates its path properly s.addChild(child4); @@ -75,9 +75,9 @@ suite('Files - View Model', () => { s4.move(s1); - assert.strictEqual(s3.children.length, 0); + assert.strictEqual(s3.getChildrenArray().length, 0); - assert.strictEqual(s1.children.length, 2); + assert.strictEqual(s1.getChildrenArray().length, 2); // Assert the new path of the moved element assert.strictEqual(s4.resource.fsPath, toResource('/' + s4.name).fsPath); @@ -156,6 +156,7 @@ suite('Files - View Model', () => { assert.strictEqual(s1.find(toResource('foobar')), null); assert.strictEqual(s1.find(toResource('/')), s1); + assert.strictEqual(s1.find(toResource('')), s1); }); test('Find with mixed case', function () { @@ -194,11 +195,6 @@ suite('Files - View Model', () => { assert(validateFileName(s, '') !== null); assert(validateFileName(s, ' ') !== null); assert(validateFileName(s, 'Read Me') === null, 'name containing space'); - assert(validateFileName(s, 'foo/bar') === null); - assert(validateFileName(s, 'foo\\bar') === null); - assert(validateFileName(s, 'all/slashes/are/same') === null); - assert(validateFileName(s, 'theres/one/different\\slash') === null); - assert(validateFileName(s, '/slashAtBeginning') === null); if (isWindows) { assert(validateFileName(s, 'foo:bar') !== null); @@ -236,34 +232,66 @@ suite('Files - View Model', () => { assert(validateFileName(s, 'foo') === null); }); + test('Validate Multi-Path File Names', function () { + const d = new Date().getTime(); + const wsFolder = createStat('/', 'workspaceFolder', true, false, 8096, d); + + assert(validateFileName(wsFolder, 'foo/bar') === null); + assert(validateFileName(wsFolder, 'foo\\bar') === null); + assert(validateFileName(wsFolder, 'all/slashes/are/same') === null); + assert(validateFileName(wsFolder, 'theres/one/different\\slash') === null); + assert(validateFileName(wsFolder, '/slashAtBeginning') !== null); + + // validation should detect if user tries to add a child to a file + const fileInRoot = createStat('/fileInRoot', 'fileInRoot', false, false, 8096, d); + wsFolder.addChild(fileInRoot); + assert(validateFileName(wsFolder, 'fileInRoot/aChild') !== null); + wsFolder.removeChild(fileInRoot); + + // attempting to add a child to a deeply nested file + const s1 = createStat('/path', 'path', true, false, 8096, d); + const s2 = createStat('/path/to', 'to', true, false, 8096, d); + const s3 = createStat('/path/to/stat', 'stat', true, false, 8096, d); + wsFolder.addChild(s1); + s1.addChild(s2); + s2.addChild(s3); + const fileDeeplyNested = createStat('/path/to/stat/fileNested', 'fileNested', false, false, 8096, d); + s3.addChild(fileDeeplyNested); + assert(validateFileName(wsFolder, '/path/to/stat/fileNested/aChild') !== null); + + // detect if path already exists + assert(validateFileName(wsFolder, '/path/to/stat/fileNested') !== null); + assert(validateFileName(wsFolder, '/path/to/stat/') !== null); + }); + test('Merge Local with Disk', function () { const d = new Date().toUTCString(); - const merge1 = new FileStat(URI.file(join('C:\\', '/path/to')), undefined, false, true, 'to', Date.now(), d); - const merge2 = new FileStat(URI.file(join('C:\\', '/path/to')), undefined, false, true, 'to', Date.now(), new Date(0).toUTCString()); + const merge1 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), undefined, false, true, 'to', Date.now(), d); + const merge2 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), undefined, false, true, 'to', Date.now(), new Date(0).toUTCString()); // Merge Properties - FileStat.mergeLocalWithDisk(merge2, merge1); + ExplorerItem.mergeLocalWithDisk(merge2, merge1); assert.strictEqual(merge1.mtime, merge2.mtime); // Merge Child when isDirectoryResolved=false is a no-op - merge2.addChild(new FileStat(URI.file(join('C:\\', '/path/to/foo.html')), undefined, false, true, 'foo.html', Date.now(), d)); - FileStat.mergeLocalWithDisk(merge2, merge1); - assert.strictEqual(merge1.children.length, 0); + merge2.addChild(new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), undefined, false, true, 'foo.html', Date.now(), d)); + ExplorerItem.mergeLocalWithDisk(merge2, merge1); + assert.strictEqual(merge1.getChildrenArray().length, 0); // Merge Child with isDirectoryResolved=true - const child = new FileStat(URI.file(join('C:\\', '/path/to/foo.html')), undefined, false, true, 'foo.html', Date.now(), d); + const child = new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), undefined, false, true, 'foo.html', Date.now(), d); merge2.removeChild(child); merge2.addChild(child); merge2.isDirectoryResolved = true; - FileStat.mergeLocalWithDisk(merge2, merge1); - assert.strictEqual(merge1.children.length, 1); - assert.strictEqual(merge1.children[0].name, 'foo.html'); - assert.deepEqual(merge1.children[0].parent, merge1, 'Check parent'); + ExplorerItem.mergeLocalWithDisk(merge2, merge1); + assert.strictEqual(merge1.getChildrenArray().length, 1); + assert.strictEqual(merge1.getChild('foo.html').name, 'foo.html'); + assert.deepEqual(merge1.getChild('foo.html').parent, merge1, 'Check parent'); // Verify that merge does not replace existing children, but updates properties in that case - const existingChild = merge1.children[0]; - FileStat.mergeLocalWithDisk(merge2, merge1); - assert.ok(existingChild === merge1.children[0]); + const existingChild = merge1.getChild('foo.html'); + ExplorerItem.mergeLocalWithDisk(merge2, merge1); + assert.ok(existingChild === merge1.getChild(existingChild.name)); }); }); diff --git a/src/vs/workbench/parts/html/common/htmlInput.ts b/src/vs/workbench/parts/html/common/htmlInput.ts index ab70960e85..6d351e3c8d 100644 --- a/src/vs/workbench/parts/html/common/htmlInput.ts +++ b/src/vs/workbench/parts/html/common/htmlInput.ts @@ -2,18 +2,16 @@ * 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 URI from 'vs/base/common/uri'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; - export interface HtmlInputOptions { - allowScripts?: boolean; - allowSvgs?: boolean; - svgWhiteList?: string[]; + readonly allowScripts?: boolean; + readonly allowSvgs?: boolean; + readonly svgWhiteList?: string[]; } export function areHtmlInputOptionsEqual(left: HtmlInputOptions, right: HtmlInputOptions) { diff --git a/src/vs/workbench/parts/html/browser/html.contribution.ts b/src/vs/workbench/parts/html/electron-browser/html.contribution.ts similarity index 94% rename from src/vs/workbench/parts/html/browser/html.contribution.ts rename to src/vs/workbench/parts/html/electron-browser/html.contribution.ts index 1f7ff03161..200fce0ec2 100644 --- a/src/vs/workbench/parts/html/browser/html.contribution.ts +++ b/src/vs/workbench/parts/html/electron-browser/html.contribution.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import 'vs/css!./media/htmlPreviewPart'; import URI from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -12,15 +11,13 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Position as EditorPosition } from 'vs/platform/editor/common/editor'; import { HtmlInput, HtmlInputOptions } from '../common/htmlInput'; -import { HtmlPreviewPart } from 'vs/workbench/parts/html/browser/htmlPreviewPart'; +import { HtmlPreviewPart } from './htmlPreviewPart'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; -import './webview.contribution'; - function getActivePreviewsForResource(accessor: ServicesAccessor, resource: URI | string) { const uri = resource instanceof URI ? resource : URI.parse(resource); return accessor.get(IWorkbenchEditorService).getVisibleEditors() @@ -31,7 +28,7 @@ function getActivePreviewsForResource(accessor: ServicesAccessor, resource: URI // --- Register Editor -(Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( +(Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( HtmlPreviewPart, HtmlPreviewPart.ID, localize('html.editor.label', "Html Preview")), diff --git a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts b/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.ts similarity index 66% rename from src/vs/workbench/parts/html/browser/htmlPreviewPart.ts rename to src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.ts index 7757306006..1ba8b44685 100644 --- a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts +++ b/src/vs/workbench/parts/html/electron-browser/htmlPreviewPart.ts @@ -8,9 +8,8 @@ import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModel } from 'vs/editor/common/model'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { empty as EmptyDisposable, IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; -import { EditorOptions, EditorInput } from 'vs/workbench/common/editor'; +import { EditorOptions, EditorInput, EditorViewStateMemento } from 'vs/workbench/common/editor'; import { Position } from 'vs/platform/editor/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; @@ -21,17 +20,21 @@ import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/r import { Parts, IPartService } from 'vs/workbench/services/part/common/partService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; - -import { Webview, WebviewOptions } from './webview'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { WebviewEditor } from './webviewEditor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { Scope } from 'vs/workbench/common/memento'; +import { Dimension } from 'vs/base/browser/dom'; +import { BaseWebviewEditor } from 'vs/workbench/parts/webview/electron-browser/baseWebviewEditor'; +import { WebviewElement, WebviewOptions } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; +export interface HtmlPreviewEditorViewState { + scrollYPercentage: number; +} /** * An implementation of editor for showing HTML content in an IFrame by leveraging the HTML input. */ -export class HtmlPreviewPart extends WebviewEditor { +export class HtmlPreviewPart extends BaseWebviewEditor { static readonly ID: string = 'workbench.editor.htmlPreviewPart'; static class: string = 'htmlPreviewPart'; @@ -43,20 +46,25 @@ export class HtmlPreviewPart extends WebviewEditor { private _modelChangeSubscription = EmptyDisposable; private _themeChangeSubscription = EmptyDisposable; - private scrollYPercentage: number = 0; + private _content: HTMLElement; + private _scrollYPercentage: number = 0; + + private editorViewStateMemento: EditorViewStateMemento; constructor( @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, - @IStorageService storageService: IStorageService, @IContextKeyService contextKeyService: IContextKeyService, - @ITextModelService private readonly textModelResolverService: ITextModelService, - @IOpenerService private readonly openerService: IOpenerService, - @IPartService private readonly partService: IPartService, @IContextViewService private readonly _contextViewService: IContextViewService, - @IEnvironmentService private readonly _environmentService: IEnvironmentService + @IEnvironmentService private readonly _environmentService: IEnvironmentService, + @IOpenerService private readonly _openerService: IOpenerService, + @IPartService private readonly _partService: IPartService, + @IStorageService readonly _storageService: IStorageService, + @ITextModelService private readonly _textModelResolverService: ITextModelService ) { - super(HtmlPreviewPart.ID, telemetryService, themeService, storageService, contextKeyService); + super(HtmlPreviewPart.ID, telemetryService, themeService, contextKeyService); + + this.editorViewStateMemento = new EditorViewStateMemento(this.getMemento(_storageService, Scope.WORKSPACE), this.viewStateStorageKey); } dispose(): void { @@ -72,23 +80,22 @@ export class HtmlPreviewPart extends WebviewEditor { super.dispose(); } - protected createEditor(parent: Builder): void { - this.content = document.createElement('div'); - this.content.style.position = 'absolute'; - this.content.classList.add(HtmlPreviewPart.class); - parent.getHTMLElement().appendChild(this.content); + protected createEditor(parent: HTMLElement): void { + this._content = document.createElement('div'); + this._content.style.position = 'absolute'; + this._content.classList.add(HtmlPreviewPart.class); + parent.appendChild(this._content); } - private get webview(): Webview { + private get webview(): WebviewElement { if (!this._webview) { let webviewOptions: WebviewOptions = {}; if (this.input && this.input instanceof HtmlInput) { webviewOptions = this.input.options; } - this._webview = new Webview( - this.content, - this.partService.getContainer(Parts.EDITOR_PART), + this._webview = new WebviewElement( + this._partService.getContainer(Parts.EDITOR_PART), this.themeService, this._environmentService, this._contextViewService, @@ -98,20 +105,21 @@ export class HtmlPreviewPart extends WebviewEditor { ...webviewOptions, useSameOriginForRoot: true }); + this._webview.mountTo(this._content); if (this.input && this.input instanceof HtmlInput) { - const state = this.loadViewState(this.input.getResource()); - this.scrollYPercentage = state ? state.scrollYPercentage : 0; - this.webview.initialScrollProgress = this.scrollYPercentage; + const state = this.loadHTMLPreviewViewState(this.input); + this._scrollYPercentage = state ? state.scrollYPercentage : 0; + this.webview.initialScrollProgress = this._scrollYPercentage; const resourceUri = this.input.getResource(); this.webview.baseUrl = resourceUri.toString(true); } this._webviewDisposables = [ this._webview, - this._webview.onDidClickLink(uri => this.openerService.open(uri)), + this._webview.onDidClickLink(uri => this._openerService.open(uri)), this._webview.onDidScroll(data => { - this.scrollYPercentage = data.scrollYPercentage; + this._scrollYPercentage = data.scrollYPercentage; }), ]; } @@ -154,16 +162,16 @@ export class HtmlPreviewPart extends WebviewEditor { public layout(dimension: Dimension): void { const { width, height } = dimension; - this.content.style.width = `${width}px`; - this.content.style.height = `${height}px`; + this._content.style.width = `${width}px`; + this._content.style.height = `${height}px`; super.layout(dimension); } public clearInput(): void { if (this.input instanceof HtmlInput) { - this.saveViewState(this.input.getResource(), { - scrollYPercentage: this.scrollYPercentage + this.saveHTMLPreviewViewState(this.input, { + scrollYPercentage: this._scrollYPercentage }); } dispose(this._modelRef); @@ -173,8 +181,8 @@ export class HtmlPreviewPart extends WebviewEditor { public shutdown(): void { if (this.input instanceof HtmlInput) { - this.saveViewState(this.input.getResource(), { - scrollYPercentage: this.scrollYPercentage + this.saveHTMLPreviewViewState(this.input, { + scrollYPercentage: this._scrollYPercentage }); } super.shutdown(); @@ -194,8 +202,8 @@ export class HtmlPreviewPart extends WebviewEditor { if (this.input instanceof HtmlInput) { oldOptions = this.input.options; - this.saveViewState(this.input.getResource(), { - scrollYPercentage: this.scrollYPercentage + this.saveHTMLPreviewViewState(this.input, { + scrollYPercentage: this._scrollYPercentage }); } @@ -210,7 +218,7 @@ export class HtmlPreviewPart extends WebviewEditor { return super.setInput(input, options).then(() => { const resourceUri = input.getResource(); - return this.textModelResolverService.createModelReference(resourceUri).then(ref => { + return this._textModelResolverService.createModelReference(resourceUri).then(ref => { const model = ref.object; if (model instanceof BaseTextEditorModel) { @@ -227,18 +235,39 @@ export class HtmlPreviewPart extends WebviewEditor { this._modelChangeSubscription = this.model.onDidChangeContent(() => { if (this.model) { - this.scrollYPercentage = 0; + this._scrollYPercentage = 0; this.webview.contents = this.model.getLinesContent().join('\n'); } }); - const state = this.loadViewState(resourceUri); - this.scrollYPercentage = state ? state.scrollYPercentage : 0; + const state = this.loadHTMLPreviewViewState(input); + this._scrollYPercentage = state ? state.scrollYPercentage : 0; this.webview.baseUrl = resourceUri.toString(true); this.webview.options = input.options; this.webview.contents = this.model.getLinesContent().join('\n'); - this.webview.initialScrollProgress = this.scrollYPercentage; + this.webview.initialScrollProgress = this._scrollYPercentage; return undefined; }); }); } + + + private get viewStateStorageKey(): string { + return this.getId() + '.editorViewState'; + } + + private saveHTMLPreviewViewState(input: HtmlInput, editorViewState: HtmlPreviewEditorViewState): void { + this.editorViewStateMemento.saveState(input, this.position, editorViewState); + } + + private loadHTMLPreviewViewState(input: HtmlInput): HtmlPreviewEditorViewState { + return this.editorViewStateMemento.loadState(input, this.position); + } + + protected saveMemento(): void { + + // ensure to first save our view state memento + this.editorViewStateMemento.save(); + + super.saveMemento(); + } } diff --git a/src/vs/workbench/parts/localizations/browser/localizations.contribution.ts b/src/vs/workbench/parts/localizations/browser/localizations.contribution.ts deleted file mode 100644 index 6a63b380f3..0000000000 --- a/src/vs/workbench/parts/localizations/browser/localizations.contribution.ts +++ /dev/null @@ -1,110 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from 'vs/nls'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { ConfigureLocaleAction } from 'vs/workbench/parts/localizations/browser/localizationsActions'; -import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; -import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { language } from 'vs/base/common/platform'; - -// Register action to configure locale and related settings -const registry = Registry.as(Extensions.WorkbenchActions); -registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Language'); - -export class LocalesSchemaUpdater extends Disposable implements IWorkbenchContribution { - constructor( - @ILocalizationsService private localizationService: ILocalizationsService - ) { - super(); - this.update(); - this._register(this.localizationService.onDidLanguagesChange(() => this.update())); - } - - private update(): void { - this.localizationService.getLanguageIds() - .then(languageIds => registerLocaleDefinitionSchema(languageIds)); - } -} - -function registerLocaleDefinitionSchema(languages: string[]): void { - const localeDefinitionFileSchemaId = 'vscode://schemas/locale'; - const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); - // Keep en-US since we generated files with that content. - jsonRegistry.registerSchema(localeDefinitionFileSchemaId, { - id: localeDefinitionFileSchemaId, - allowComments: true, - description: 'Locale Definition file', - type: 'object', - default: { - 'locale': 'en' - }, - required: ['locale'], - properties: { - locale: { - type: 'string', - enum: languages, - description: localize('JsonSchema.locale', 'The UI Language to use.') - } - } - }); -} - -registerLocaleDefinitionSchema([language]); -const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); -workbenchRegistry.registerWorkbenchContribution(LocalesSchemaUpdater, LifecyclePhase.Eventually); - -ExtensionsRegistry.registerExtensionPoint('localizations', [], { - description: localize('vscode.extension.contributes.localizations', "Contributes localizations to the editor"), - type: 'array', - default: [], - items: { - type: 'object', - required: ['languageId', 'translations'], - defaultSnippets: [{ body: { languageId: '', languageName: '', languageNameLocalized: '', translations: [{ id: 'vscode', path: '' }] } }], - properties: { - languageId: { - description: localize('vscode.extension.contributes.localizations.languageId', 'Id of the language into which the display strings are translated.'), - type: 'string' - }, - languageName: { - description: localize('vscode.extension.contributes.localizations.languageName', 'Name of the language in English.'), - type: 'string' - }, - languageNameLocalized: { - description: localize('vscode.extension.contributes.localizations.languageNameLocalized', 'Name of the language in contributed language.'), - type: 'string' - }, - translations: { - description: localize('vscode.extension.contributes.localizations.translations', 'List of translations associated to the language.'), - type: 'array', - default: [{ id: 'vscode', path: '' }], - items: { - type: 'object', - required: ['id', 'path'], - properties: { - id: { - type: 'string', - description: localize('vscode.extension.contributes.localizations.translations.id', "Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`."), - pattern: '^((vscode)|([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*))$', - patternErrorMessage: localize('vscode.extension.contributes.localizations.translations.id.pattern', "Id should be `vscode` or in format `publisherId.extensionName` for translating VS code or an extension respectively.") - }, - path: { - type: 'string', - description: localize('vscode.extension.contributes.localizations.translations.path', "A relative path to a file containing translations for the language.") - } - }, - defaultSnippets: [{ body: { id: '', path: '' } }], - }, - } - } - } -}); \ No newline at end of file diff --git a/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts new file mode 100644 index 0000000000..6a226f4749 --- /dev/null +++ b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts @@ -0,0 +1,217 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; +import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; +import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { ConfigureLocaleAction } from 'vs/workbench/parts/localizations/electron-browser/localizationsActions'; +import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; +import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; +import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; +import * as platform from 'vs/base/common/platform'; +import { IExtensionManagementService, DidInstallExtensionEvent, LocalExtensionType, IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import Severity from 'vs/base/common/severity'; +import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import URI from 'vs/base/common/uri'; +import { join } from 'vs/base/common/paths'; +import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IStorageService, } from 'vs/platform/storage/common/storage'; +import { TPromise } from 'vs/base/common/winjs.base'; +import product from 'vs/platform/node/product'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { VIEWLET_ID as EXTENSIONS_VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions'; + +// Register action to configure locale and related settings +const registry = Registry.as(Extensions.WorkbenchActions); +registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Language'); + +export class LocalizationWorkbenchContribution extends Disposable implements IWorkbenchContribution { + constructor( + @ILocalizationsService private localizationService: ILocalizationsService, + @INotificationService private notificationService: INotificationService, + @IJSONEditingService private jsonEditingService: IJSONEditingService, + @IEnvironmentService private environmentService: IEnvironmentService, + @IWindowsService private windowsService: IWindowsService, + @IStorageService private storageService: IStorageService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private galleryService: IExtensionGalleryService, + @IViewletService private viewletService: IViewletService + ) { + super(); + this.updateLocaleDefintionSchema(); + this.checkAndInstall(); + this._register(this.localizationService.onDidLanguagesChange(() => this.updateLocaleDefintionSchema())); + this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e))); + } + + private updateLocaleDefintionSchema(): void { + this.localizationService.getLanguageIds() + .then(languageIds => { + let lowercaseLanguageIds: string[] = []; + languageIds.forEach((languageId) => { + let lowercaseLanguageId = languageId.toLowerCase(); + if (lowercaseLanguageId !== languageId) { + lowercaseLanguageIds.push(lowercaseLanguageId); + } + }); + registerLocaleDefinitionSchema([...languageIds, ...lowercaseLanguageIds]); + }); + } + + private onDidInstallExtension(e: DidInstallExtensionEvent): void { + const donotAskUpdateKey = 'langugage.update.donotask'; + if (!this.storageService.getBoolean(donotAskUpdateKey) && e.local && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) { + const locale = e.local.manifest.contributes.localizations[0].languageId; + if (platform.language !== locale) { + this.notificationService.prompt( + Severity.Info, + localize('updateLocale', "Would you like to change VS Code's UI language to {0} and restart?", e.local.manifest.contributes.localizations[0].languageName || e.local.manifest.contributes.localizations[0].languageId), + [{ + label: localize('yes', "Yes"), + run: () => { + const file = URI.file(join(this.environmentService.appSettingsHome, 'locale.json')); + this.jsonEditingService.write(file, { key: 'locale', value: locale }, true) + .then(() => this.windowsService.relaunch({}), e => this.notificationService.error(e)); + } + }, { + label: localize('no', "No"), + run: () => { } + }, { + label: localize('neverAgain', "Don't Show Again"), + isSecondary: true, + run: () => this.storageService.store(donotAskUpdateKey, true) + }] + ); + } + } + } + + private checkAndInstall(): void { + const language = platform.language; + if (language !== 'en' && language !== 'en_us') { + this.isLanguageInstalled(language) + .then(installed => { + if (!installed) { + this.getLanguagePackExtension(language) + .then(extension => { + if (extension) { + this.notificationService.prompt(Severity.Warning, localize('install language pack', "In the near future, VS Code will only support language packs in the form of Marketplace extensions. Please install the '{0}' extension in order to continue to use the currently configured language. ", extension.displayName || extension.displayName), + [ + { label: localize('install', "Install"), run: () => this.installExtension(extension) }, + { label: localize('more information', "More Information..."), run: () => window.open('https://go.microsoft.com/fwlink/?linkid=872941') } + ]); + } + }); + } + }); + } + } + + private getLanguagePackExtension(language: string): TPromise { + return this.localizationService.getLanguageIds(LanguageType.Core) + .then(coreLanguages => { + if (coreLanguages.some(c => c.toLowerCase() === language)) { + const extensionIdPrefix = language === 'zh-cn' ? 'zh-hans' : language === 'zh-tw' ? 'zh-hant' : language; + const extensionId = product.quality === 'insider' ? `MS-CEINTL.vscode-insiders-language-pack-${extensionIdPrefix}` : `MS-CEINTL.vscode-language-pack-${extensionIdPrefix}`; + return this.galleryService.query({ names: [extensionId], pageSize: 1 }) + .then(result => result.total === 1 ? result.firstPage[0] : null); + } + return null; + }); + } + + private isLanguageInstalled(language: string): TPromise { + return this.extensionManagementService.getInstalled(LocalExtensionType.User) + .then(installed => installed.some(i => i.manifest && i.manifest.contributes && i.manifest.contributes.localizations && i.manifest.contributes.localizations.length && i.manifest.contributes.localizations.some(l => l.languageId.toLowerCase() === language))); + } + + private installExtension(extension: IGalleryExtension): TPromise { + return this.viewletService.openViewlet(EXTENSIONS_VIEWLET_ID) + .then(viewlet => viewlet as IExtensionsViewlet) + .then(viewlet => viewlet.search(`@id:${extension.identifier.id}`)) + .then(() => this.extensionManagementService.installFromGallery(extension)) + .then(() => null, err => this.notificationService.error(err)); + } +} + +function registerLocaleDefinitionSchema(languages: string[]): void { + const localeDefinitionFileSchemaId = 'vscode://schemas/locale'; + const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); + // Keep en-US since we generated files with that content. + jsonRegistry.registerSchema(localeDefinitionFileSchemaId, { + id: localeDefinitionFileSchemaId, + allowComments: true, + description: 'Locale Definition file', + type: 'object', + default: { + 'locale': 'en' + }, + required: ['locale'], + properties: { + locale: { + type: 'string', + enum: languages, + description: localize('JsonSchema.locale', 'The UI Language to use.') + } + } + }); +} + +registerLocaleDefinitionSchema([platform.language]); +const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); +workbenchRegistry.registerWorkbenchContribution(LocalizationWorkbenchContribution, LifecyclePhase.Eventually); + +ExtensionsRegistry.registerExtensionPoint('localizations', [], { + description: localize('vscode.extension.contributes.localizations', "Contributes localizations to the editor"), + type: 'array', + default: [], + items: { + type: 'object', + required: ['languageId', 'translations'], + defaultSnippets: [{ body: { languageId: '', languageName: '', languageNameLocalized: '', translations: [{ id: 'vscode', path: '' }] } }], + properties: { + languageId: { + description: localize('vscode.extension.contributes.localizations.languageId', 'Id of the language into which the display strings are translated.'), + type: 'string' + }, + languageName: { + description: localize('vscode.extension.contributes.localizations.languageName', 'Name of the language in English.'), + type: 'string' + }, + languageNameLocalized: { + description: localize('vscode.extension.contributes.localizations.languageNameLocalized', 'Name of the language in contributed language.'), + type: 'string' + }, + translations: { + description: localize('vscode.extension.contributes.localizations.translations', 'List of translations associated to the language.'), + type: 'array', + default: [{ id: 'vscode', path: '' }], + items: { + type: 'object', + required: ['id', 'path'], + properties: { + id: { + type: 'string', + description: localize('vscode.extension.contributes.localizations.translations.id', "Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`."), + pattern: '^((vscode)|([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*))$', + patternErrorMessage: localize('vscode.extension.contributes.localizations.translations.id.pattern', "Id should be `vscode` or in format `publisherId.extensionName` for translating VS code or an extension respectively.") + }, + path: { + type: 'string', + description: localize('vscode.extension.contributes.localizations.translations.path', "A relative path to a file containing translations for the language.") + } + }, + defaultSnippets: [{ body: { id: '', path: '' } }], + }, + } + } + } +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/localizations/browser/localizationsActions.ts b/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.ts similarity index 100% rename from src/vs/workbench/parts/localizations/browser/localizationsActions.ts rename to src/vs/workbench/parts/localizations/electron-browser/localizationsActions.ts diff --git a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts index eac817db60..c3a9afeee2 100644 --- a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts +++ b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts @@ -28,7 +28,7 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { @IInstantiationService instantiationService: IInstantiationService ) { super(); - let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); + let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); outputChannelRegistry.registerChannel(Constants.mainLogChannelId, nls.localize('mainLog', "Log (Main)"), URI.file(join(this.environmentService.logsPath, `main.log`))); outputChannelRegistry.registerChannel(Constants.sharedLogChannelId, nls.localize('sharedLog', "Log (Shared)"), URI.file(join(this.environmentService.logsPath, `sharedprocess.log`))); outputChannelRegistry.registerChannel(Constants.rendererLogChannelId, nls.localize('rendererLog', "Log (Window)"), URI.file(join(this.environmentService.logsPath, `renderer${this.windowService.getCurrentWindowId()}.log`))); diff --git a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts deleted file mode 100644 index b7cfe63348..0000000000 --- a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts +++ /dev/null @@ -1,151 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Delayer } from 'vs/base/common/async'; -import * as DOM from 'vs/base/browser/dom'; -import * as lifecycle from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { IAction, Action } from 'vs/base/common/actions'; -import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; -import { KeyCode } from 'vs/base/common/keyCodes'; -import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; -import Messages from 'vs/workbench/parts/markers/common/messages'; -import Constants from 'vs/workbench/parts/markers/common/constants'; -import { MarkersPanel } from 'vs/workbench/parts/markers/browser/markersPanel'; -import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { CollapseAllAction as TreeCollapseAction } from 'vs/base/parts/tree/browser/treeDefaults'; -import Tree = require('vs/base/parts/tree/browser/tree'); -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; -import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; - -export class ToggleMarkersPanelAction extends TogglePanelAction { - - public static readonly ID = 'workbench.actions.view.problems'; - public static readonly LABEL = Messages.MARKERS_PANEL_TOGGLE_LABEL; - - constructor(id: string, label: string, - @IPartService partService: IPartService, - @IPanelService panelService: IPanelService, - ) { - super(id, label, Constants.MARKERS_PANEL_ID, panelService, partService); - } -} - -export class ShowProblemsPanelAction extends Action { - - public static readonly ID = 'workbench.action.problems.focus'; - public static readonly LABEL = Messages.MARKERS_PANEL_SHOW_LABEL; - - constructor(id: string, label: string, - @IPanelService private panelService: IPanelService - ) { - super(id, label); - } - - public run(): TPromise { - return this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true); - } -} - -export class CollapseAllAction extends TreeCollapseAction { - - constructor(viewer: Tree.ITree, enabled: boolean) { - super(viewer, enabled); - } -} - -export class FilterAction extends Action { - - public static readonly ID: string = 'workbench.actions.problems.filter'; - - constructor() { - super(FilterAction.ID, Messages.MARKERS_PANEL_ACTION_TOOLTIP_FILTER, 'markers-panel-action-filter', true); - } - -} - -export class FilterInputBoxActionItem extends BaseActionItem { - - protected toDispose: lifecycle.IDisposable[]; - - private delayedFilterUpdate: Delayer; - - constructor(private markersPanel: MarkersPanel, action: IAction, - @IContextViewService private contextViewService: IContextViewService, - @IThemeService private themeService: IThemeService, - @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService, - @ITelemetryService private telemetryService: ITelemetryService) { - super(markersPanel, action); - this.toDispose = []; - this.delayedFilterUpdate = new Delayer(500); - } - - public render(container: HTMLElement): void { - DOM.addClass(container, 'markers-panel-action-filter'); - let filterInputBox = new InputBox(container, this.contextViewService, { - placeholder: Messages.MARKERS_PANEL_FILTER_PLACEHOLDER, - ariaLabel: Messages.MARKERS_PANEL_FILTER_PLACEHOLDER - }); - this.toDispose.push(attachInputBoxStyler(filterInputBox, this.themeService)); - filterInputBox.value = this.markersWorkbenchService.markersModel.filterOptions.completeFilter; - this.toDispose.push(filterInputBox.onDidChange(filter => this.delayedFilterUpdate.trigger(() => this.updateFilter(filter)))); - this.toDispose.push(DOM.addStandardDisposableListener(filterInputBox.inputElement, 'keyup', (keyboardEvent) => this.onInputKeyUp(keyboardEvent, filterInputBox))); - this.toDispose.push(DOM.addStandardDisposableListener(container, 'keydown', this.handleKeyboardEvent)); - this.toDispose.push(DOM.addStandardDisposableListener(container, 'keyup', this.handleKeyboardEvent)); - } - - private updateFilter(filter: string) { - this.markersPanel.updateFilter(filter); - this.reportFilteringUsed(); - } - - private reportFilteringUsed(): void { - let data = {}; - data['errors'] = this.markersWorkbenchService.markersModel.filterOptions.filterErrors; - data['warnings'] = this.markersWorkbenchService.markersModel.filterOptions.filterWarnings; - data['infos'] = this.markersWorkbenchService.markersModel.filterOptions.filterInfos; - /* __GDPR__ - "problems.filter" : { - "errors" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "warnings": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "infos": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('problems.filter', data); - } - - public dispose(): void { - this.toDispose = lifecycle.dispose(this.toDispose); - super.dispose(); - } - - // Action toolbar is swallowing some keys for action items which should not be for an input box - private handleKeyboardEvent(e: IKeyboardEvent) { - switch (e.keyCode) { - case KeyCode.Space: - case KeyCode.LeftArrow: - case KeyCode.RightArrow: - case KeyCode.Escape: - e.stopPropagation(); - break; - } - } - - private onInputKeyUp(keyboardEvent: IKeyboardEvent, filterInputBox: InputBox) { - switch (keyboardEvent.keyCode) { - case KeyCode.Escape: - filterInputBox.value = ''; - return; - default: - return; - } - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/markersTreeViewer.ts b/src/vs/workbench/parts/markers/browser/markersTreeViewer.ts deleted file mode 100644 index 16d7bd4038..0000000000 --- a/src/vs/workbench/parts/markers/browser/markersTreeViewer.ts +++ /dev/null @@ -1,230 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { TPromise, Promise } from 'vs/base/common/winjs.base'; -import * as dom from 'vs/base/browser/dom'; -import * as network from 'vs/base/common/network'; -import { IDataSource, ITree, IRenderer, IAccessibilityProvider, ISorter } from 'vs/base/parts/tree/browser/tree'; -import Severity from 'vs/base/common/severity'; -import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; -import { FileLabel, ResourceLabel } from 'vs/workbench/browser/labels'; -import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; -import { IMarker } from 'vs/platform/markers/common/markers'; -import { MarkersModel, Resource, Marker } from 'vs/workbench/parts/markers/common/markersModel'; -import Messages from 'vs/workbench/parts/markers/common/messages'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IDisposable } from 'vs/base/common/lifecycle'; - -interface IAnyResourceTemplateData { - count: CountBadge; - styler: IDisposable; -} - -interface IResourceTemplateData extends IAnyResourceTemplateData { - resourceLabel: ResourceLabel; -} - -interface IFileResourceTemplateData extends IAnyResourceTemplateData { - fileLabel: FileLabel; -} - -interface IMarkerTemplateData { - icon: HTMLElement; - source: HighlightedLabel; - description: HighlightedLabel; - lnCol: HTMLElement; -} - -export class DataSource implements IDataSource { - public getId(tree: ITree, element: any): string { - if (element instanceof MarkersModel) { - return 'root'; - } - if (element instanceof Resource) { - return element.uri.toString(); - } - if (element instanceof Marker) { - return (element).id; - } - return ''; - } - - public hasChildren(tree: ITree, element: any): boolean { - return element instanceof MarkersModel || element instanceof Resource; - } - - public getChildren(tree: ITree, element: any): Promise { - if (element instanceof MarkersModel) { - return TPromise.as((element).filteredResources); - } - if (element instanceof Resource) { - return TPromise.as(element.markers); - } - return null; - } - - public getParent(tree: ITree, element: any): Promise { - return TPromise.as(null); - } -} - -export class Renderer implements IRenderer { - - private static readonly RESOURCE_TEMPLATE_ID = 'resource-template'; - private static readonly FILE_RESOURCE_TEMPLATE_ID = 'file-resource-template'; - private static readonly MARKER_TEMPLATE_ID = 'marker-template'; - - constructor( - @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService private themeService: IThemeService - ) { - } - - public getHeight(tree: ITree, element: any): number { - return 22; - } - - public getTemplateId(tree: ITree, element: any): string { - if (element instanceof Resource) { - if ((element).uri.scheme === network.Schemas.file || (element).uri.scheme === network.Schemas.untitled) { - return Renderer.FILE_RESOURCE_TEMPLATE_ID; - } else { - return Renderer.RESOURCE_TEMPLATE_ID; - } - } - if (element instanceof Marker) { - return Renderer.MARKER_TEMPLATE_ID; - } - return ''; - } - - public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any { - dom.addClass(container, 'markers-panel-tree-entry'); - switch (templateId) { - case Renderer.FILE_RESOURCE_TEMPLATE_ID: - return this.renderFileResourceTemplate(container); - case Renderer.RESOURCE_TEMPLATE_ID: - return this.renderResourceTemplate(container); - case Renderer.MARKER_TEMPLATE_ID: - return this.renderMarkerTemplate(container); - } - } - - private renderFileResourceTemplate(container: HTMLElement): IFileResourceTemplateData { - const data: IFileResourceTemplateData = Object.create(null); - const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container')); - data.fileLabel = this.instantiationService.createInstance(FileLabel, resourceLabelContainer, { supportHighlights: true }); - - const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper')); - data.count = new CountBadge(badgeWrapper); - data.styler = attachBadgeStyler(data.count, this.themeService); - - return data; - } - - private renderResourceTemplate(container: HTMLElement): IResourceTemplateData { - const data: IResourceTemplateData = Object.create(null); - const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container')); - data.resourceLabel = this.instantiationService.createInstance(ResourceLabel, resourceLabelContainer, { supportHighlights: true }); - - const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper')); - data.count = new CountBadge(badgeWrapper); - data.styler = attachBadgeStyler(data.count, this.themeService); - - return data; - } - - private renderMarkerTemplate(container: HTMLElement): IMarkerTemplateData { - const data: IMarkerTemplateData = Object.create(null); - data.icon = dom.append(container, dom.$('.marker-icon')); - data.source = new HighlightedLabel(dom.append(container, dom.$(''))); - data.description = new HighlightedLabel(dom.append(container, dom.$('.marker-description'))); - data.lnCol = dom.append(container, dom.$('span.marker-line')); - return data; - } - - public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void { - switch (templateId) { - case Renderer.FILE_RESOURCE_TEMPLATE_ID: - case Renderer.RESOURCE_TEMPLATE_ID: - return this.renderResourceElement(tree, element, templateData); - case Renderer.MARKER_TEMPLATE_ID: - return this.renderMarkerElement(tree, (element), templateData); - } - } - - private renderResourceElement(tree: ITree, element: Resource, templateData: IAnyResourceTemplateData) { - if ((templateData).fileLabel) { - (templateData).fileLabel.setFile(element.uri, { matches: element.matches }); - } else if ((templateData).resourceLabel) { - (templateData).resourceLabel.setLabel({ name: element.name, description: element.uri.toString(), resource: element.uri }, { matches: element.matches }); - } - templateData.count.setCount(element.markers.length); - } - - private renderMarkerElement(tree: ITree, element: Marker, templateData: IMarkerTemplateData) { - let marker = element.marker; - templateData.icon.className = 'icon ' + Renderer.iconClassNameFor(marker); - templateData.description.set(marker.message, element.labelMatches); - templateData.description.element.title = marker.message; - - dom.toggleClass(templateData.source.element, 'marker-source', !!marker.source); - templateData.source.set(marker.source, element.sourceMatches); - - templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn); - } - - private static iconClassNameFor(element: IMarker): string { - switch (element.severity) { - case Severity.Ignore: - return 'info'; - case Severity.Info: - return 'info'; - case Severity.Warning: - return 'warning'; - case Severity.Error: - return 'error'; - } - return ''; - } - - public disposeTemplate(tree: ITree, templateId: string, templateData: any): void { - if (templateId === Renderer.FILE_RESOURCE_TEMPLATE_ID) { - (templateData).fileLabel.dispose(); - (templateData).styler.dispose(); - } else if (templateId === Renderer.RESOURCE_TEMPLATE_ID) { - (templateData).resourceLabel.dispose(); - (templateData).styler.dispose(); - } else if (templateId === Renderer.MARKER_TEMPLATE_ID) { - (templateData).description.dispose(); - (templateData).source.dispose(); - } - } -} - -export class MarkersTreeAccessibilityProvider implements IAccessibilityProvider { - - public getAriaLabel(tree: ITree, element: any): string { - if (element instanceof Resource) { - return Messages.MARKERS_TREE_ARIA_LABEL_RESOURCE(element.name, element.markers.length); - } - if (element instanceof Marker) { - return Messages.MARKERS_TREE_ARIA_LABEL_MARKER(element.marker); - } - return null; - } - -} - -export class Sorter implements ISorter { - - public compare(tree: ITree, element: any, otherElement: any): number { - return MarkersModel.compare(element, otherElement); - } - -} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts deleted file mode 100644 index 59d2450379..0000000000 --- a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import Messages from 'vs/workbench/parts/markers/common/messages'; -import Constants from 'vs/workbench/parts/markers/common/constants'; -import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; -import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { ToggleMarkersPanelAction, ShowProblemsPanelAction } from 'vs/workbench/parts/markers/browser/markersPanelActions'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { MarkersPanel } from 'vs/workbench/parts/markers/browser/markersPanel'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IMarkersWorkbenchService, MarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; - -export function registerContributions(): void { - - registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService); - - KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: Constants.MARKER_OPEN_SIDE_ACTION_ID, - weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ContextKeyExpr.and(Constants.MarkerFocusContextKey), - primary: KeyMod.CtrlCmd | KeyCode.Enter, - mac: { - primary: KeyMod.WinCtrl | KeyCode.Enter - }, - handler: (accessor, args: any) => { - const markersPanel = (accessor.get(IPanelService).getActivePanel()); - markersPanel.openFileAtElement(markersPanel.getFocusElement(), false, true, true); - } - }); - - KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: Constants.MARKER_SHOW_PANEL_ID, - weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: undefined, - primary: undefined, - handler: (accessor, args: any) => { - accessor.get(IPanelService).openPanel(Constants.MARKERS_PANEL_ID); - } - }); - - // configuration - Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': 'problems', - 'order': 101, - 'title': Messages.PROBLEMS_PANEL_CONFIGURATION_TITLE, - 'type': 'object', - 'properties': { - 'problems.autoReveal': { - 'description': Messages.PROBLEMS_PANEL_CONFIGURATION_AUTO_REVEAL, - 'type': 'boolean', - 'default': true - } - } - }); - - - // markers panel - Registry.as(PanelExtensions.Panels).registerPanel(new PanelDescriptor( - MarkersPanel, - Constants.MARKERS_PANEL_ID, - Messages.MARKERS_PANEL_TITLE_PROBLEMS, - 'markersPanel', - 10, - ToggleMarkersPanelAction.ID - )); - - // actions - const registry = Registry.as(ActionExtensions.WorkbenchActions); - registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMarkersPanelAction, ToggleMarkersPanelAction.ID, ToggleMarkersPanelAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M - }), 'View: Toggle Problems (Errors, Warnings, Infos)', Messages.MARKERS_PANEL_VIEW_CATEGORY); - registry.registerWorkbenchAction(new SyncActionDescriptor(ShowProblemsPanelAction, ShowProblemsPanelAction.ID, ShowProblemsPanelAction.LABEL), 'View: Focus Problems (Errors, Warnings, Infos)', Messages.MARKERS_PANEL_VIEW_CATEGORY); -} diff --git a/src/vs/workbench/parts/markers/common/markers.ts b/src/vs/workbench/parts/markers/common/markers.ts deleted file mode 100644 index 8486198e6e..0000000000 --- a/src/vs/workbench/parts/markers/common/markers.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { MarkersModel, FilterOptions } from 'vs/workbench/parts/markers/common/markersModel'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; -import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; -import { localize } from 'vs/nls'; -import Constants from 'vs/workbench/parts/markers/common/constants'; -import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; - -export const IMarkersWorkbenchService = createDecorator('markersWorkbenchService'); - -export interface IMarkersWorkbenchService { - _serviceBrand: any; - - readonly onDidChangeMarkersForResources: Event; - readonly markersModel: MarkersModel; - - filter(filter: string): void; -} - -export class MarkersWorkbenchService extends Disposable implements IMarkersWorkbenchService { - _serviceBrand: any; - - readonly markersModel: MarkersModel; - - private readonly _onDidChangeMarkersForResources: Emitter = this._register(new Emitter()); - readonly onDidChangeMarkersForResources: Event = this._onDidChangeMarkersForResources.event; - - constructor( - @IMarkerService private markerService: IMarkerService, - @IActivityService private activityService: IActivityService - ) { - super(); - this.markersModel = this._register(new MarkersModel(this.markerService.read())); - this._register(markerService.onMarkerChanged(resources => this.onMarkerChanged(resources))); - } - - filter(filter: string): void { - this.markersModel.update(new FilterOptions(filter)); - this.refreshBadge(); - } - - private onMarkerChanged(resources: URI[]): void { - const bulkUpdater = this.markersModel.getBulkUpdater(); - for (const resource of resources) { - bulkUpdater.add(resource, this.markerService.read({ resource })); - } - bulkUpdater.done(); - this.refreshBadge(); - this._onDidChangeMarkersForResources.fire(resources); - } - - private refreshBadge(): void { - const total = this.markersModel.total(); - const count = this.markersModel.count(); - const message = total === count ? localize('totalProblems', 'Total {0} Problems', total) : localize('filteredProblems', 'Showing {0} of {1} Problems', count, total); - this.activityService.showActivity(Constants.MARKERS_PANEL_ID, new NumberBadge(count, () => message)); - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/common/markersModel.ts b/src/vs/workbench/parts/markers/common/markersModel.ts deleted file mode 100644 index c7227f41ae..0000000000 --- a/src/vs/workbench/parts/markers/common/markersModel.ts +++ /dev/null @@ -1,351 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 paths from 'vs/base/common/paths'; -import * as types from 'vs/base/common/types'; -import Severity from 'vs/base/common/severity'; -import URI from 'vs/base/common/uri'; -import { Range, IRange } from 'vs/editor/common/core/range'; -import { IMarker, MarkerStatistics } from 'vs/platform/markers/common/markers'; -import { IFilter, IMatch, or, matchesContiguousSubString, matchesPrefix, matchesFuzzy } from 'vs/base/common/filters'; -import Messages from 'vs/workbench/parts/markers/common/messages'; -import { Schemas } from 'vs/base/common/network'; - -export interface BulkUpdater { - add(resource: URI, markers: IMarker[]): void; - done(): void; -} - -export class Resource { - - private _name: string = null; - private _path: string = null; - - constructor(public uri: URI, public markers: Marker[], - public statistics: MarkerStatistics, - public matches: IMatch[] = []) { - } - - public get path(): string { - if (this._path === null) { - this._path = this.uri.fsPath; - } - return this._path; - } - - public get name(): string { - if (this._name === null) { - this._name = paths.basename(this.uri.fsPath); - } - return this._name; - } -} - -export class Marker { - constructor(public id: string, public marker: IMarker, - public labelMatches: IMatch[] = [], - public sourceMatches: IMatch[] = []) { } - - public get resource(): URI { - return this.marker.resource; - } - - public get range(): IRange { - return this.marker; - } - - public toString(): string { - return [ - `file: '${this.marker.resource}'`, - `severity: '${Severity.toString(this.marker.severity)}'`, - `message: '${this.marker.message}'`, - `at: '${this.marker.startLineNumber},${this.marker.startColumn}'`, - `source: '${this.marker.source ? this.marker.source : ''}'`, - `code: '${this.marker.code ? this.marker.code : ''}'` - ].join('\n'); - } - -} - -export class FilterOptions { - - static _filter: IFilter = or(matchesPrefix, matchesContiguousSubString); - static _fuzzyFilter: IFilter = or(matchesPrefix, matchesContiguousSubString, matchesFuzzy); - - private _filterErrors: boolean = false; - private _filterWarnings: boolean = false; - private _filterInfos: boolean = false; - private _filter: string = ''; - private _completeFilter: string = ''; - - constructor(filter: string = '') { - if (filter) { - this.parse(filter); - } - } - - public get filterErrors(): boolean { - return this._filterErrors; - } - - public get filterWarnings(): boolean { - return this._filterWarnings; - } - - public get filterInfos(): boolean { - return this._filterInfos; - } - - public get filter(): string { - return this._filter; - } - - public get completeFilter(): string { - return this._completeFilter; - } - - public hasFilters(): boolean { - return !!this._filter; - } - - private parse(filter: string) { - this._completeFilter = filter; - this._filter = filter.trim(); - this._filterErrors = this.matches(this._filter, Messages.MARKERS_PANEL_FILTER_ERRORS); - this._filterWarnings = this.matches(this._filter, Messages.MARKERS_PANEL_FILTER_WARNINGS); - this._filterInfos = this.matches(this._filter, Messages.MARKERS_PANEL_FILTER_INFOS); - } - - private matches(prefix: string, word: string): boolean { - let result = matchesPrefix(prefix, word); - return result && result.length > 0; - } -} - -export class MarkersModel { - - private markersByResource: Map; - - private _filteredResources: Resource[]; - private _nonFilteredResources: Resource[]; - private _filterOptions: FilterOptions; - - constructor(markers: IMarker[] = []) { - this.markersByResource = new Map(); - this._filterOptions = new FilterOptions(); - this.update(markers); - } - - public get filterOptions(): FilterOptions { - return this._filterOptions; - } - - public get filteredResources(): Resource[] { - return this._filteredResources; - } - - public hasFilteredResources(): boolean { - return this.filteredResources.length > 0; - } - - public hasResources(): boolean { - return this.markersByResource.size > 0; - } - - public hasResource(resource: URI): boolean { - return this.markersByResource.has(resource.toString()); - } - - public total(): number { - let total = 0; - this.markersByResource.forEach(markers => total = total + markers.length); - return total; - } - - public count(): number { - let count = 0; - this.filteredResources.forEach(resource => count = count + resource.markers.length); - return count; - } - - public get nonFilteredResources(): Resource[] { - return this._nonFilteredResources; - } - - public getBulkUpdater(): BulkUpdater { - return { - add: (resourceUri: URI, markers: IMarker[]) => { - this.updateResource(resourceUri, markers); - }, - done: () => { - this.refresh(); - } - }; - } - - public update(filterOptions: FilterOptions): void; - public update(resourceUri: URI, markers: IMarker[]): void; - public update(markers: IMarker[]): void; - public update(arg1?: any, arg2?: any) { - if (arg1 instanceof FilterOptions) { - this._filterOptions = arg1; - } - - if (arg1 instanceof URI) { - this.updateResource(arg1, arg2); - } - - if (types.isArray(arg1)) { - this.updateMarkers(arg1); - } - - this.refresh(); - } - - private refresh(): void { - this.refreshResources(); - } - - private refreshResources(): void { - this._nonFilteredResources = []; - this._filteredResources = []; - this.markersByResource.forEach((values, uri) => { - const filteredResource = this.toFilteredResource(URI.parse(uri), values); - if (filteredResource.markers.length) { - this._filteredResources.push(filteredResource); - } else { - this._nonFilteredResources.push(filteredResource); - } - }); - } - - private updateResource(resourceUri: URI, markers: IMarker[]) { - if (this.markersByResource.has(resourceUri.toString())) { - this.markersByResource.delete(resourceUri.toString()); - } - if (markers.length > 0) { - this.markersByResource.set(resourceUri.toString(), markers); - } - } - - private updateMarkers(markers: IMarker[]) { - markers.forEach((marker: IMarker) => { - let uri: URI = marker.resource; - let markers: IMarker[] = this.markersByResource.get(uri.toString()); - if (!markers) { - markers = []; - this.markersByResource.set(uri.toString(), markers); - } - markers.push(marker); - }); - } - - private toFilteredResource(uri: URI, values: IMarker[]) { - let markers: Marker[] = []; - for (let i = 0; i < values.length; i++) { - const m = values[i]; - if (uri.scheme !== Schemas.walkThrough && uri.scheme !== Schemas.walkThroughSnippet && (!this._filterOptions.hasFilters() || this.filterMarker(m))) { - markers.push(this.toMarker(m, i, uri.toString())); - } - } - const matches = this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, paths.basename(uri.fsPath)) : []; - return new Resource(uri, markers, this.getStatistics(values), matches || []); - } - - private toMarker(marker: IMarker, index: number, uri: string): Marker { - const labelMatches = this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, marker.message) : []; - const sourceMatches = marker.source && this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, marker.source) : []; - return new Marker(uri + index, marker, labelMatches || [], sourceMatches || []); - } - - private filterMarker(marker: IMarker): boolean { - if (this._filterOptions.filterErrors && Severity.Error === marker.severity) { - return true; - } - if (this._filterOptions.filterWarnings && Severity.Warning === marker.severity) { - return true; - } - if (this._filterOptions.filterInfos && Severity.Info === marker.severity) { - return true; - } - if (!!FilterOptions._fuzzyFilter(this._filterOptions.filter, marker.message)) { - return true; - } - if (!!FilterOptions._filter(this._filterOptions.filter, paths.basename(marker.resource.fsPath))) { - return true; - } - if (!!marker.source && !!FilterOptions._filter(this._filterOptions.filter, marker.source)) { - return true; - } - return false; - } - - private getStatistics(markers: IMarker[]): MarkerStatistics { - let errors = 0, warnings = 0, infos = 0, unknowns = 0; - for (const marker of markers) { - switch (marker.severity) { - case Severity.Error: - errors++; - break; - case Severity.Warning: - warnings++; - break; - case Severity.Info: - infos++; - break; - default: - unknowns++; - break; - } - } - return { errors, warnings, infos, unknowns }; - } - - public dispose(): void { - this.markersByResource.clear(); - this._filteredResources = []; - this._nonFilteredResources = []; - } - - public getMessage(): string { - if (this.hasFilteredResources()) { - return ''; - } - if (this.hasResources()) { - if (this._filterOptions.hasFilters()) { - return Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS; - } - } - return Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT; - } - - public static compare(a: any, b: any): number { - if (a instanceof Resource && b instanceof Resource) { - return MarkersModel.compareResources(a, b); - } - if (a instanceof Marker && b instanceof Marker) { - return MarkersModel.compareMarkers(a, b); - } - return 0; - } - - private static compareResources(a: Resource, b: Resource): number { - if (a.statistics.errors === 0 && b.statistics.errors > 0) { - return 1; - } - if (b.statistics.errors === 0 && a.statistics.errors > 0) { - return -1; - } - return a.path.localeCompare(b.path) || a.name.localeCompare(b.name); - } - - private static compareMarkers(a: Marker, b: Marker): number { - if (a.marker.severity === b.marker.severity) { - return Range.compareRangesUsingStarts(a.marker, b.marker); - } - return a.marker.severity > b.marker.severity ? -1 : 1; - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/common/constants.ts b/src/vs/workbench/parts/markers/electron-browser/constants.ts similarity index 79% rename from src/vs/workbench/parts/markers/common/constants.ts rename to src/vs/workbench/parts/markers/electron-browser/constants.ts index 7d5eb06b28..dda0ecf42d 100644 --- a/src/vs/workbench/parts/markers/common/constants.ts +++ b/src/vs/workbench/parts/markers/electron-browser/constants.ts @@ -9,8 +9,10 @@ export default { MARKERS_PANEL_ID: 'workbench.panel.markers', MARKER_COPY_ACTION_ID: 'problems.action.copy', MARKER_COPY_MESSAGE_ACTION_ID: 'problems.action.copyMessage', + RELATED_INFORMATION_COPY_MESSAGE_ACTION_ID: 'problems.action.copyRelatedInformationMessage', MARKER_OPEN_SIDE_ACTION_ID: 'problems.action.openToSide', MARKER_SHOW_PANEL_ID: 'workbench.action.showErrorsWarnings', - MarkerFocusContextKey: new RawContextKey('problemFocus', true) + MarkerFocusContextKey: new RawContextKey('problemFocus', true), + RelatedInformationFocusContextKey: new RawContextKey('relatedInformationFocus', true) }; diff --git a/src/vs/workbench/parts/markers/electron-browser/markers.contribution.ts b/src/vs/workbench/parts/markers/electron-browser/markers.contribution.ts new file mode 100644 index 0000000000..38f60f366b --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/markers.contribution.ts @@ -0,0 +1,214 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { clipboard } from 'electron'; +import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; +import { KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { localize } from 'vs/nls'; +import { Marker, RelatedInformation } from 'vs/workbench/parts/markers/electron-browser/markersModel'; +import { MarkersPanel } from 'vs/workbench/parts/markers/electron-browser/markersPanel'; +import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { ToggleMarkersPanelAction, ShowProblemsPanelAction } from 'vs/workbench/parts/markers/electron-browser/markersPanelActions'; +import Constants from 'vs/workbench/parts/markers/electron-browser/constants'; +import Messages from 'vs/workbench/parts/markers/electron-browser/messages'; + +import './markers'; +import './markersFileDecorations'; + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: Constants.MARKER_OPEN_SIDE_ACTION_ID, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), + when: ContextKeyExpr.and(Constants.MarkerFocusContextKey), + primary: KeyMod.CtrlCmd | KeyCode.Enter, + mac: { + primary: KeyMod.WinCtrl | KeyCode.Enter + }, + handler: (accessor, args: any) => { + const markersPanel = (accessor.get(IPanelService).getActivePanel()); + markersPanel.openFileAtElement(markersPanel.getFocusElement(), false, true, true); + } +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: Constants.MARKER_SHOW_PANEL_ID, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), + when: undefined, + primary: undefined, + handler: (accessor, args: any) => { + accessor.get(IPanelService).openPanel(Constants.MARKERS_PANEL_ID); + } +}); + +// configuration +Registry.as(Extensions.Configuration).registerConfiguration({ + 'id': 'problems', + 'order': 101, + 'title': Messages.PROBLEMS_PANEL_CONFIGURATION_TITLE, + 'type': 'object', + 'properties': { + 'problems.autoReveal': { + 'description': Messages.PROBLEMS_PANEL_CONFIGURATION_AUTO_REVEAL, + 'type': 'boolean', + 'default': true + } + } +}); + + +// markers panel +Registry.as(PanelExtensions.Panels).registerPanel(new PanelDescriptor( + MarkersPanel, + Constants.MARKERS_PANEL_ID, + Messages.MARKERS_PANEL_TITLE_PROBLEMS, + 'markersPanel', + 10, + ToggleMarkersPanelAction.ID +)); + +// actions +const registry = Registry.as(ActionExtensions.WorkbenchActions); +registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMarkersPanelAction, ToggleMarkersPanelAction.ID, ToggleMarkersPanelAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M +}), 'View: Toggle Problems (Errors, Warnings, Infos)', Messages.MARKERS_PANEL_VIEW_CATEGORY); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowProblemsPanelAction, ShowProblemsPanelAction.ID, ShowProblemsPanelAction.LABEL), 'View: Focus Problems (Errors, Warnings, Infos)', Messages.MARKERS_PANEL_VIEW_CATEGORY); +registerAction({ + id: Constants.MARKER_COPY_ACTION_ID, + title: localize('copyMarker', "Copy"), + handler(accessor) { + copyMarker(accessor.get(IPanelService)); + }, + menu: { + menuId: MenuId.ProblemsPanelContext, + when: Constants.MarkerFocusContextKey, + group: 'navigation' + }, + keybinding: { + keys: { + primary: KeyMod.CtrlCmd | KeyCode.KEY_C + }, + when: Constants.MarkerFocusContextKey + } +}); +registerAction({ + id: Constants.MARKER_COPY_MESSAGE_ACTION_ID, + title: localize('copyMessage', "Copy Message"), + handler(accessor) { + copyMessage(accessor.get(IPanelService)); + }, + menu: { + menuId: MenuId.ProblemsPanelContext, + when: Constants.MarkerFocusContextKey, + group: 'navigation' + } +}); +registerAction({ + id: Constants.RELATED_INFORMATION_COPY_MESSAGE_ACTION_ID, + title: localize('copyMessage', "Copy Message"), + handler(accessor) { + copyRelatedInformationMessage(accessor.get(IPanelService)); + }, + menu: { + menuId: MenuId.ProblemsPanelContext, + when: Constants.RelatedInformationFocusContextKey, + group: 'navigation' + } +}); + + +function copyMarker(panelService: IPanelService) { + const activePanel = panelService.getActivePanel(); + if (activePanel instanceof MarkersPanel) { + const element = (activePanel).getFocusElement(); + if (element instanceof Marker) { + clipboard.writeText(`${element}`); + } + } +} + +function copyMessage(panelService: IPanelService) { + const activePanel = panelService.getActivePanel(); + if (activePanel instanceof MarkersPanel) { + const element = (activePanel).getFocusElement(); + if (element instanceof Marker) { + clipboard.writeText(element.raw.message); + } + } +} + +function copyRelatedInformationMessage(panelService: IPanelService) { + const activePanel = panelService.getActivePanel(); + if (activePanel instanceof MarkersPanel) { + const element = (activePanel).getFocusElement(); + if (element instanceof RelatedInformation) { + clipboard.writeText(element.raw.message); + } + } +} + +interface IActionDescriptor { + id: string; + handler: ICommandHandler; + + // ICommandUI + title: string; + category?: string; + f1?: boolean; + + // + menu?: { + menuId: MenuId, + when?: ContextKeyExpr; + group?: string; + }; + + // + keybinding?: { + when?: ContextKeyExpr; + weight?: number; + keys: IKeybindings; + }; +} + +function registerAction(desc: IActionDescriptor) { + + const { id, handler, title, category, menu, keybinding } = desc; + + // 1) register as command + CommandsRegistry.registerCommand(id, handler); + + // 2) menus + let command = { id, title, category }; + if (menu) { + let { menuId, when, group } = menu; + MenuRegistry.appendMenuItem(menuId, { + command, + when, + group + }); + } + + // 3) keybindings + if (keybinding) { + let { when, weight, keys } = keybinding; + KeybindingsRegistry.registerKeybindingRule({ + id, + when, + weight, + primary: keys.primary, + secondary: keys.secondary, + linux: keys.linux, + mac: keys.mac, + win: keys.win + }); + } +} diff --git a/src/vs/workbench/parts/markers/electron-browser/markers.ts b/src/vs/workbench/parts/markers/electron-browser/markers.ts new file mode 100644 index 0000000000..c9cd203688 --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/markers.ts @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { MarkersModel, FilterOptions } from './markersModel'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IMarkerService, MarkerSeverity, IMarker } from 'vs/platform/markers/common/markers'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; +import { localize } from 'vs/nls'; +import Constants from './constants'; +import URI from 'vs/base/common/uri'; +import { Event, Emitter } from 'vs/base/common/event'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { deepClone, mixin } from 'vs/base/common/objects'; +import { IExpression, getEmptyExpression } from 'vs/base/common/glob'; +import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { join, isAbsolute } from 'vs/base/common/paths'; + +export const IMarkersWorkbenchService = createDecorator('markersWorkbenchService'); + +export interface IFilter { + filterText: string; + useFilesExclude: boolean; +} + +export interface IMarkersWorkbenchService { + _serviceBrand: any; + + readonly onDidChange: Event; + readonly markersModel: MarkersModel; + + filter(filter: IFilter): void; +} + +export class MarkersWorkbenchService extends Disposable implements IMarkersWorkbenchService { + _serviceBrand: any; + + readonly markersModel: MarkersModel; + + private readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; + + private useFilesExclude: boolean = false; + + constructor( + @IMarkerService private markerService: IMarkerService, + @IConfigurationService private configurationService: IConfigurationService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, + @IActivityService private activityService: IActivityService + ) { + super(); + this.markersModel = this._register(new MarkersModel(this.readMarkers())); + this._register(markerService.onMarkerChanged(resources => this.onMarkerChanged(resources))); + this._register(configurationService.onDidChangeConfiguration(e => { + if (this.useFilesExclude && e.affectsConfiguration('files.exclude')) { + this.doFilter(this.markersModel.filterOptions.filter, this.getExcludeExpression()); + } + })); + } + + filter(filter: IFilter): void { + this.useFilesExclude = filter.useFilesExclude; + this.doFilter(filter.filterText, this.getExcludeExpression()); + } + + private onMarkerChanged(resources: URI[]): void { + this.markersModel.updateMarkers(updater => { + for (const resource of resources) { + updater(resource, this.readMarkers(resource)); + } + }); + this.refreshBadge(); + this._onDidChange.fire(resources); + } + + private readMarkers(resource?: URI): IMarker[] { + return this.markerService.read({ resource, severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info }); + } + + private getExcludeExpression(): IExpression { + if (this.useFilesExclude) { + const workspaceFolders = this.workspaceContextService.getWorkspace().folders; + if (workspaceFolders.length) { + const result = getEmptyExpression(); + for (const workspaceFolder of workspaceFolders) { + mixin(result, this.getExcludesForFolder(workspaceFolder)); + } + return result; + } else { + return this.getFilesExclude(); + } + } + return {}; + } + + private doFilter(filterText: string, filesExclude: IExpression): void { + this.markersModel.updateFilterOptions(new FilterOptions(filterText, filesExclude)); + this.refreshBadge(); + this._onDidChange.fire([]); + } + + private refreshBadge(): void { + const { total } = this.markersModel.stats(); + const message = localize('totalProblems', 'Total {0} Problems', total); + this.activityService.showActivity(Constants.MARKERS_PANEL_ID, new NumberBadge(total, () => message)); + } + + private getExcludesForFolder(workspaceFolder: IWorkspaceFolder): IExpression { + const expression = this.getFilesExclude(workspaceFolder.uri); + return this.getAbsoluteExpression(expression, workspaceFolder.uri.fsPath); + } + + private getFilesExclude(resource?: URI): IExpression { + return deepClone(this.configurationService.getValue('files.exclude', { resource })) || {}; + } + + private getAbsoluteExpression(expr: IExpression, root: string): IExpression { + return Object.keys(expr) + .reduce((absExpr: IExpression, key: string) => { + if (expr[key] && !isAbsolute(key)) { + const absPattern = join(root, key); + absExpr[absPattern] = expr[key]; + } + + return absExpr; + }, Object.create(null)); + } +} + +registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService); \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/electron-browser/markersElectronContributions.ts b/src/vs/workbench/parts/markers/electron-browser/markersElectronContributions.ts deleted file mode 100644 index 9457b2a1ed..0000000000 --- a/src/vs/workbench/parts/markers/electron-browser/markersElectronContributions.ts +++ /dev/null @@ -1,128 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { localize } from 'vs/nls'; -import { clipboard } from 'electron'; -import { Marker } from 'vs/workbench/parts/markers/common/markersModel'; -import Constants from 'vs/workbench/parts/markers/common/constants'; -import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; -import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { MarkersPanel } from 'vs/workbench/parts/markers/browser/markersPanel'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; - - -export function registerContributions(): void { - registerAction({ - id: Constants.MARKER_COPY_ACTION_ID, - title: localize('copyMarker', "Copy"), - handler(accessor) { - copyMarker(accessor.get(IPanelService)); - }, - menu: { - menuId: MenuId.ProblemsPanelContext, - when: Constants.MarkerFocusContextKey, - group: 'navigation' - }, - keybinding: { - keys: { - primary: KeyMod.CtrlCmd | KeyCode.KEY_C - }, - when: Constants.MarkerFocusContextKey - } - }); - registerAction({ - id: Constants.MARKER_COPY_MESSAGE_ACTION_ID, - title: localize('copyMarkerMessage', "Copy Message"), - handler(accessor) { - copyMessage(accessor.get(IPanelService)); - }, - menu: { - menuId: MenuId.ProblemsPanelContext, - when: Constants.MarkerFocusContextKey, - group: 'navigation' - } - }); -} - -function copyMarker(panelService: IPanelService) { - const activePanel = panelService.getActivePanel(); - if (activePanel instanceof MarkersPanel) { - const element = (activePanel).getFocusElement(); - if (element instanceof Marker) { - clipboard.writeText(`${element}`); - } - } -} - -function copyMessage(panelService: IPanelService) { - const activePanel = panelService.getActivePanel(); - if (activePanel instanceof MarkersPanel) { - const element = (activePanel).getFocusElement(); - if (element instanceof Marker) { - clipboard.writeText(element.marker.message); - } - } -} - -interface IActionDescriptor { - id: string; - handler: ICommandHandler; - - // ICommandUI - title: string; - category?: string; - f1?: boolean; - - // - menu?: { - menuId: MenuId, - when?: ContextKeyExpr; - group?: string; - }; - - // - keybinding?: { - when?: ContextKeyExpr; - weight?: number; - keys: IKeybindings; - }; -} - -function registerAction(desc: IActionDescriptor) { - - const { id, handler, title, category, menu, keybinding } = desc; - - // 1) register as command - CommandsRegistry.registerCommand(id, handler); - - // 2) menus - let command = { id, title, category }; - if (menu) { - let { menuId, when, group } = menu; - MenuRegistry.appendMenuItem(menuId, { - command, - when, - group - }); - } - - // 3) keybindings - if (keybinding) { - let { when, weight, keys } = keybinding; - KeybindingsRegistry.registerKeybindingRule({ - id, - when, - weight, - primary: keys.primary, - secondary: keys.secondary, - linux: keys.linux, - mac: keys.mac, - win: keys.win - }); - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts b/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.ts similarity index 91% rename from src/vs/workbench/parts/markers/browser/markersFileDecorations.ts rename to src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.ts index 3692895d84..8de93d1397 100644 --- a/src/vs/workbench/parts/markers/browser/markersFileDecorations.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersFileDecorations.ts @@ -6,14 +6,13 @@ 'use strict'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { IMarkerService, IMarker } from 'vs/platform/markers/common/markers'; +import { IMarkerService, IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { IDecorationsService, IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import Severity from 'vs/base/common/severity'; import { editorErrorForeground, editorWarningForeground } from 'vs/editor/common/view/editorColorRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; @@ -31,7 +30,10 @@ class MarkersDecorationsProvider implements IDecorationsProvider { } provideDecorations(resource: URI): IDecorationData { - let markers = this._markerService.read({ resource }); + let markers = this._markerService.read({ + resource, + severities: MarkerSeverity.Error | MarkerSeverity.Warning + }); let first: IMarker; for (const marker of markers) { if (!first || marker.severity > first.severity) { @@ -48,7 +50,7 @@ class MarkersDecorationsProvider implements IDecorationsProvider { bubble: true, tooltip: markers.length === 1 ? localize('tooltip.1', "1 problem in this file") : localize('tooltip.N', "{0} problems in this file", markers.length), letter: markers.length < 10 ? markers.length.toString() : '+9', - color: first.severity === Severity.Error ? editorErrorForeground : editorWarningForeground, + color: first.severity === MarkerSeverity.Error ? editorErrorForeground : editorWarningForeground, }; } } diff --git a/src/vs/workbench/parts/markers/electron-browser/markersModel.ts b/src/vs/workbench/parts/markers/electron-browser/markersModel.ts new file mode 100644 index 0000000000..e6a229c2f5 --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/markersModel.ts @@ -0,0 +1,376 @@ +/*--------------------------------------------------------------------------------------------- + * 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 paths from 'vs/base/common/paths'; +import URI from 'vs/base/common/uri'; +import { Range, IRange } from 'vs/editor/common/core/range'; +import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers'; +import { IFilter, IMatch, or, matchesContiguousSubString, matchesPrefix, matchesFuzzy } from 'vs/base/common/filters'; +import Messages from 'vs/workbench/parts/markers/electron-browser/messages'; +import { Schemas } from 'vs/base/common/network'; +import { groupBy, isFalsyOrEmpty, flatten } from 'vs/base/common/arrays'; +import { values } from 'vs/base/common/map'; +import * as glob from 'vs/base/common/glob'; +import * as strings from 'vs/base/common/strings'; + +function compareUris(a: URI, b: URI) { + if (a.toString() < b.toString()) { + return -1; + } else if (a.toString() > b.toString()) { + return 1; + } else { + return 0; + } +} + +export abstract class NodeWithId { + constructor(readonly id: string) { } +} + +export class ResourceMarkers extends NodeWithId { + + private _name: string = null; + private _path: string = null; + + readonly markers: Marker[]; + isExcluded: boolean = false; + isIncluded: boolean = false; + filteredCount: number; + uriMatches: IMatch[] = []; + + constructor( + readonly uri: URI, + markers: Marker[] + ) { + super(uri.toString()); + this.markers = markers.sort(Marker.compare); + } + + public get path(): string { + if (this._path === null) { + this._path = this.uri.fsPath; + } + return this._path; + } + + public get name(): string { + if (this._name === null) { + this._name = paths.basename(this.uri.fsPath); + } + return this._name; + } + + static compare(a: ResourceMarkers, b: ResourceMarkers): number { + let [firstMarkerOfA] = a.markers; + let [firstMarkerOfB] = b.markers; + let res = 0; + if (firstMarkerOfA && firstMarkerOfB) { + res = MarkerSeverity.compare(firstMarkerOfA.raw.severity, firstMarkerOfB.raw.severity); + } + if (res === 0) { + res = a.path.localeCompare(b.path) || a.name.localeCompare(b.name); + } + return res; + } +} + +export class Marker extends NodeWithId { + + isSelected: boolean = false; + messageMatches: IMatch[] = []; + sourceMatches: IMatch[] = []; + resourceRelatedInformation: RelatedInformation[] = []; + + constructor( + id: string, + readonly raw: IMarker, + ) { + super(id); + } + + public get resource(): URI { + return this.raw.resource; + } + + public get range(): IRange { + return this.raw; + } + + public toString(): string { + return JSON.stringify({ + ...this.raw, + resource: this.raw.resource.path, + relatedInformation: this.resourceRelatedInformation.length ? this.resourceRelatedInformation.map(r => ({ ...r.raw, resource: r.raw.resource.path })) : void 0 + }, null, '\t'); + } + + static compare(a: Marker, b: Marker): number { + return MarkerSeverity.compare(a.raw.severity, b.raw.severity) + || Range.compareRangesUsingStarts(a.raw, b.raw); + } +} + +export class RelatedInformation extends NodeWithId { + + messageMatches: IMatch[]; + uriMatches: IMatch[]; + + constructor(id: string, readonly raw: IRelatedInformation) { + super(id); + } +} + +export class FilterOptions { + + static readonly _filter: IFilter = or(matchesPrefix, matchesContiguousSubString); + static readonly _fuzzyFilter: IFilter = or(matchesPrefix, matchesContiguousSubString, matchesFuzzy); + + readonly filterErrors: boolean = false; + readonly filterWarnings: boolean = false; + readonly filterInfos: boolean = false; + readonly excludePattern: glob.ParsedExpression = null; + readonly includePattern: glob.ParsedExpression = null; + readonly textFilter: string = ''; + + constructor(readonly filter: string = '', excludePatterns: glob.IExpression = {}) { + filter = filter.trim(); + for (const key of Object.keys(excludePatterns)) { + if (excludePatterns[key]) { + this.setPattern(excludePatterns, key); + } + delete excludePatterns[key]; + } + const includePatterns: glob.IExpression = glob.getEmptyExpression(); + if (filter) { + const filters = glob.splitGlobAware(filter, ',').map(s => s.trim()).filter(s => !!s.length); + for (const f of filters) { + this.filterErrors = this.filterErrors || this.matches(f, Messages.MARKERS_PANEL_FILTER_ERRORS); + this.filterWarnings = this.filterWarnings || this.matches(f, Messages.MARKERS_PANEL_FILTER_WARNINGS); + this.filterInfos = this.filterInfos || this.matches(f, Messages.MARKERS_PANEL_FILTER_INFOS); + if (strings.startsWith(f, '!')) { + this.setPattern(excludePatterns, strings.ltrim(f, '!')); + } else { + this.setPattern(includePatterns, f); + this.textFilter += ` ${f}`; + } + } + } + if (Object.keys(excludePatterns).length) { + this.excludePattern = glob.parse(excludePatterns); + } + if (Object.keys(includePatterns).length) { + this.includePattern = glob.parse(includePatterns); + } + this.textFilter = this.textFilter.trim(); + } + + private setPattern(expression: glob.IExpression, pattern: string) { + if (pattern[0] === '.') { + pattern = '*' + pattern; // convert ".js" to "*.js" + } + expression[`**/${pattern}/**`] = true; + expression[`**/${pattern}`] = true; + } + + private matches(prefix: string, word: string): boolean { + let result = matchesPrefix(prefix, word); + return result && result.length > 0; + } +} + +export class MarkersModel { + + private _cachedSortedResources: ResourceMarkers[]; + private _markersByResource: Map; + private _filterOptions: FilterOptions; + + constructor(markers: IMarker[] = []) { + this._markersByResource = new Map(); + this._filterOptions = new FilterOptions(); + + for (const group of groupBy(markers, MarkersModel._compareMarkersByUri)) { + const resource = this.createResource(group[0].resource, group); + this._markersByResource.set(resource.uri.toString(), resource); + } + } + + private static _compareMarkersByUri(a: IMarker, b: IMarker) { + return compareUris(a.resource, b.resource); + } + + public get filterOptions(): FilterOptions { + return this._filterOptions; + } + + public get resources(): ResourceMarkers[] { + if (!this._cachedSortedResources) { + this._cachedSortedResources = values(this._markersByResource).sort(ResourceMarkers.compare); + } + return this._cachedSortedResources; + } + + public forEachFilteredResource(callback: (resource: ResourceMarkers) => any) { + this._markersByResource.forEach(resource => { + if (resource.filteredCount > 0) { + callback(resource); + } + }); + } + + public hasFilteredResources(): boolean { + let res = false; + this._markersByResource.forEach(resource => { + res = res || resource.filteredCount > 0; + }); + return res; + } + + public hasResources(): boolean { + return this._markersByResource.size > 0; + } + + public hasResource(resource: URI): boolean { + return this._markersByResource.has(resource.toString()); + } + + public stats(): { total: number, filtered: number } { + let total = 0; + let filtered = 0; + this._markersByResource.forEach(resource => { + total += resource.markers.length; + filtered += resource.filteredCount; + }); + return { total, filtered }; + + } + + public updateMarkers(callback: (updater: (resource: URI, markers: IMarker[]) => any) => void): void { + callback((resource, markers) => { + if (isFalsyOrEmpty(markers)) { + this._markersByResource.delete(resource.toString()); + } else { + this._markersByResource.set(resource.toString(), this.createResource(resource, markers)); + } + }); + this._cachedSortedResources = undefined; + } + + public updateFilterOptions(filterOptions: FilterOptions): void { + this._filterOptions = filterOptions; + this._markersByResource.forEach(resource => { + this.updateResource(resource); + for (const marker of resource.markers) { + this.updateMarker(marker, resource); + } + this.updateFilteredCount(resource); + }); + } + + private createResource(uri: URI, rawMarkers: IMarker[]): ResourceMarkers { + + let markers: Marker[] = []; + const resource = new ResourceMarkers(uri, markers); + this.updateResource(resource); + + rawMarkers.forEach((rawMarker, index) => { + const marker = new Marker(uri.toString() + index, rawMarker); + if (rawMarker.relatedInformation) { + const groupedByResource = groupBy(rawMarker.relatedInformation, MarkersModel._compareMarkersByUri); + groupedByResource.sort((a, b) => compareUris(a[0].resource, b[0].resource)); + marker.resourceRelatedInformation = flatten(groupedByResource).map((r, index) => new RelatedInformation(marker.id + index, r)); + } + this.updateMarker(marker, resource); + markers.push(marker); + }); + + this.updateFilteredCount(resource); + + return resource; + } + + private updateResource(resource: ResourceMarkers): void { + resource.isExcluded = this.isResourceExcluded(resource); + resource.isIncluded = this.isResourceIncluded(resource); + resource.uriMatches = this._filterOptions.textFilter ? FilterOptions._filter(this._filterOptions.textFilter, paths.basename(resource.uri.fsPath)) : []; + } + + private updateFilteredCount(resource: ResourceMarkers): void { + if (resource.isExcluded) { + resource.filteredCount = 0; + } else if (resource.isIncluded) { + resource.filteredCount = resource.markers.length; + } else { + resource.filteredCount = resource.markers.filter(m => m.isSelected).length; + } + } + + private updateMarker(marker: Marker, resource: ResourceMarkers): void { + marker.messageMatches = !resource.isExcluded && this._filterOptions.textFilter ? FilterOptions._fuzzyFilter(this._filterOptions.textFilter, marker.raw.message) : []; + marker.sourceMatches = !resource.isExcluded && marker.raw.source && this._filterOptions.textFilter ? FilterOptions._filter(this._filterOptions.textFilter, marker.raw.source) : []; + marker.resourceRelatedInformation.forEach(r => { + r.uriMatches = !resource.isExcluded && this._filterOptions.textFilter ? FilterOptions._filter(this._filterOptions.textFilter, paths.basename(r.raw.resource.fsPath)) : []; + r.messageMatches = !resource.isExcluded && this._filterOptions.textFilter ? FilterOptions._fuzzyFilter(this._filterOptions.textFilter, r.raw.message) : []; + }); + marker.isSelected = this.isMarkerSelected(marker.raw, resource); + } + + private isResourceExcluded(resource: ResourceMarkers): boolean { + if (resource.uri.scheme === Schemas.walkThrough || resource.uri.scheme === Schemas.walkThroughSnippet) { + return true; + } + if (this.filterOptions.excludePattern && !!this.filterOptions.excludePattern(resource.uri.fsPath)) { + return true; + } + return false; + } + + private isResourceIncluded(resource: ResourceMarkers): boolean { + if (this.filterOptions.includePattern && this.filterOptions.includePattern(resource.uri.fsPath)) { + return true; + } + if (this._filterOptions.textFilter && !!FilterOptions._filter(this._filterOptions.textFilter, paths.basename(resource.uri.fsPath))) { + return true; + } + return false; + } + + private isMarkerSelected(marker: IMarker, resource: ResourceMarkers): boolean { + if (resource.isExcluded) { + return false; + } + if (resource.isIncluded) { + return true; + } + if (this._filterOptions.filterErrors && MarkerSeverity.Error === marker.severity) { + return true; + } + if (this._filterOptions.filterWarnings && MarkerSeverity.Warning === marker.severity) { + return true; + } + if (this._filterOptions.filterInfos && MarkerSeverity.Info === marker.severity) { + return true; + } + if (!this._filterOptions.textFilter) { + return true; + } + if (!!FilterOptions._fuzzyFilter(this._filterOptions.textFilter, marker.message)) { + return true; + } + if (!!marker.source && !!FilterOptions._filter(this._filterOptions.textFilter, marker.source)) { + return true; + } + if (!!marker.relatedInformation && marker.relatedInformation.some(r => + !!FilterOptions._filter(this._filterOptions.textFilter, paths.basename(r.resource.fsPath)) || ! + !FilterOptions._filter(this._filterOptions.textFilter, r.message))) { + return true; + } + return false; + } + + public dispose(): void { + this._markersByResource.clear(); + } +} diff --git a/src/vs/workbench/parts/markers/browser/markersPanel.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts similarity index 60% rename from src/vs/workbench/parts/markers/browser/markersPanel.ts rename to src/vs/workbench/parts/markers/electron-browser/markersPanel.ts index 656346549a..b7175f621e 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts @@ -9,29 +9,30 @@ import * as errors from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { Delayer } from 'vs/base/common/async'; -import dom = require('vs/base/browser/dom'); -import builder = require('vs/base/browser/builder'); -import { IAction, Action } from 'vs/base/common/actions'; -import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import * as dom from 'vs/base/browser/dom'; +import { IAction, IActionItem } from 'vs/base/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { Panel } from 'vs/workbench/browser/panel'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import Constants from 'vs/workbench/parts/markers/common/constants'; -import { Marker, Resource } from 'vs/workbench/parts/markers/common/markersModel'; -import { Controller } from 'vs/workbench/parts/markers/browser/markersTreeController'; -import * as Viewer from 'vs/workbench/parts/markers/browser/markersTreeViewer'; +import Constants from 'vs/workbench/parts/markers/electron-browser/constants'; +import { Marker, ResourceMarkers, RelatedInformation } from 'vs/workbench/parts/markers/electron-browser/markersModel'; +import { Controller } from 'vs/workbench/parts/markers/electron-browser/markersTreeController'; +import * as Viewer from 'vs/workbench/parts/markers/electron-browser/markersTreeViewer'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CollapseAllAction, FilterAction, FilterInputBoxActionItem } from 'vs/workbench/parts/markers/browser/markersPanelActions'; +import { CollapseAllAction, MarkersFilterActionItem, MarkersFilterAction } from 'vs/workbench/parts/markers/electron-browser/markersPanelActions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import Messages from 'vs/workbench/parts/markers/common/messages'; +import Messages from 'vs/workbench/parts/markers/electron-browser/messages'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { debounceEvent } from 'vs/base/common/event'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { TreeResourceNavigator, WorkbenchTree } from 'vs/platform/list/browser/listService'; -import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; +import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/electron-browser/markers'; import { SimpleFileResourceDragAndDrop } from 'vs/workbench/browser/dnd'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { Scope } from 'vs/workbench/common/memento'; +import { localize } from 'vs/nls'; export class MarkersPanel extends Panel { @@ -45,12 +46,12 @@ export class MarkersPanel extends Panel { private rangeHighlightDecorations: RangeHighlightDecorations; private actions: IAction[]; - private filterAction: FilterAction; private collapseAllAction: IAction; + private filterInputActionItem: MarkersFilterActionItem; private treeContainer: HTMLElement; private messageBoxContainer: HTMLElement; - private messageBox: HTMLElement; + private panelSettings: any; private currentResourceGotAddedToMarkersData: boolean = false; @@ -61,29 +62,32 @@ export class MarkersPanel extends Panel { @IConfigurationService private configurationService: IConfigurationService, @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, - @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService + @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService, + @IStorageService storageService: IStorageService, ) { super(Constants.MARKERS_PANEL_ID, telemetryService, themeService); this.delayedRefresh = new Delayer(500); this.autoExpanded = new Set(); + this.panelSettings = this.getMemento(storageService, Scope.WORKSPACE); } - public create(parent: builder.Builder): TPromise { + public create(parent: HTMLElement): TPromise { super.create(parent); this.rangeHighlightDecorations = this.instantiationService.createInstance(RangeHighlightDecorations); this.toUnbind.push(this.rangeHighlightDecorations); - dom.addClass(parent.getHTMLElement(), 'markers-panel'); + dom.addClass(parent, 'markers-panel'); - let container = dom.append(parent.getHTMLElement(), dom.$('.markers-panel-container')); + let container = dom.append(parent, dom.$('.markers-panel-container')); this.createMessageBox(container); this.createTree(container); - this.createActions(); this.createListeners(); + this.updateFilter(); + return this.render(); } @@ -91,8 +95,10 @@ export class MarkersPanel extends Panel { return Messages.MARKERS_PANEL_TITLE_PROBLEMS; } - public layout(dimension: builder.Dimension): void { - this.tree.layout(dimension.height); + public layout(dimension: dom.Dimension): void { + this.treeContainer.style.height = `${dimension.height}px`; + this.tree.layout(dimension.height, dimension.width); + this.filterInputActionItem.toggleLayout(dimension.width < 1200); } public focus(): void { @@ -101,14 +107,14 @@ export class MarkersPanel extends Panel { } if (this.markersWorkbenchService.markersModel.hasFilteredResources()) { - this.tree.DOMFocus(); + this.tree.domFocus(); if (this.tree.getSelection().length === 0) { this.tree.focusFirst(); } this.highlightCurrentSelectedMarkerRange(); this.autoReveal(true); } else { - this.messageBox.focus(); + this.messageBoxContainer.focus(); } } @@ -127,30 +133,27 @@ export class MarkersPanel extends Panel { } public getActions(): IAction[] { - this.collapseAllAction.enabled = this.markersWorkbenchService.markersModel.hasFilteredResources(); + if (!this.actions) { + this.createActions(); + } return this.actions; } public openFileAtElement(element: any, preserveFocus: boolean, sideByside: boolean, pinned: boolean): boolean { - if (element instanceof Marker) { - const marker: Marker = element; - /* __GDPR__ - "problems.marker.opened" : { - "source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('problems.marker.opened', { source: marker.marker.source }); + const { resource, selection } = element instanceof Marker ? { resource: element.resource, selection: element.range } : + element instanceof RelatedInformation ? { resource: element.raw.resource, selection: element.raw } : { resource: null, selection: null }; + if (resource && selection) { this.editorService.openEditor({ - resource: marker.resource, + resource, options: { - selection: marker.range, + selection, preserveFocus, pinned, revealIfVisible: true }, }, sideByside).done(editor => { if (editor && preserveFocus) { - this.rangeHighlightDecorations.highlightRange(marker, editor.getControl()); + this.rangeHighlightDecorations.highlightRange({ resource, range: selection }, editor.getControl()); } else { this.rangeHighlightDecorations.removeHighlightRange(); } @@ -176,39 +179,44 @@ export class MarkersPanel extends Panel { return TPromise.as(null); } - public updateFilter(filter: string) { - this.markersWorkbenchService.filter(filter); + private updateFilter() { this.autoExpanded = new Set(); - this.refreshPanel(); - this.autoReveal(); + this.markersWorkbenchService.filter({ filterText: this.filterInputActionItem.getFilterText(), useFilesExclude: this.filterInputActionItem.useFilesExclude }); } private createMessageBox(parent: HTMLElement): void { this.messageBoxContainer = dom.append(parent, dom.$('.message-box-container')); - this.messageBox = dom.append(this.messageBoxContainer, dom.$('span')); - this.messageBox.setAttribute('tabindex', '0'); } private createTree(parent: HTMLElement): void { this.treeContainer = dom.append(parent, dom.$('.tree-container')); dom.addClass(this.treeContainer, 'show-file-icons'); const renderer = this.instantiationService.createInstance(Viewer.Renderer); - const dnd = this.instantiationService.createInstance(SimpleFileResourceDragAndDrop, obj => obj instanceof Resource ? obj.uri : void 0); + const dnd = this.instantiationService.createInstance(SimpleFileResourceDragAndDrop, obj => obj instanceof ResourceMarkers ? obj.uri : void 0); const controller = this.instantiationService.createInstance(Controller); this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new Viewer.DataSource(), + filter: new Viewer.DataFilter(), renderer, controller, - sorter: new Viewer.Sorter(), accessibilityProvider: new Viewer.MarkersTreeAccessibilityProvider(), dnd }, { - indentPixels: 0, twistiePixels: 20, ariaLabel: Messages.MARKERS_PANEL_ARIA_LABEL_PROBLEMS_TREE }); - Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService); + const markerFocusContextKey = Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService); + const relatedInformationFocusContextKey = Constants.RelatedInformationFocusContextKey.bindTo(this.tree.contextKeyService); + this._register(this.tree.onDidChangeFocus((e: { focus: any }) => { + markerFocusContextKey.set(e.focus instanceof Marker); + relatedInformationFocusContextKey.set(e.focus instanceof RelatedInformation); + })); + const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement())); + this._register(focusTracker.onDidBlur(() => { + markerFocusContextKey.set(false); + relatedInformationFocusContextKey.set(false); + })); const markersNavigator = this._register(new TreeResourceNavigator(this.tree, { openOnFocus: true })); this._register(debounceEvent(markersNavigator.openResource, (last, event) => event, 75, true)(options => { @@ -218,25 +226,22 @@ export class MarkersPanel extends Panel { private createActions(): void { this.collapseAllAction = this.instantiationService.createInstance(CollapseAllAction, this.tree, true); - this.filterAction = new FilterAction(); - this.actions = [ - this.filterAction, - this.collapseAllAction - ]; - this.actions.forEach(a => { - this.toUnbind.push(a); - }); + const filterAction = this.instantiationService.createInstance(MarkersFilterAction); + this.filterInputActionItem = this.instantiationService.createInstance(MarkersFilterActionItem, { filterText: this.panelSettings['filter'] || '', filterHistory: this.panelSettings['filterHistory'] || [], useFilesExclude: !!this.panelSettings['useFilesExclude'] }, filterAction); + this.actions = [filterAction, this.collapseAllAction]; } private createListeners(): void { - this.toUnbind.push(this.markersWorkbenchService.onDidChangeMarkersForResources(this.onMarkerChanged, this)); + this.toUnbind.push(this.markersWorkbenchService.onDidChange(resources => this.onDidChange(resources))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(this.onEditorsChanged, this)); this.toUnbind.push(this.tree.onDidChangeSelection(() => this.onSelected())); + this.toUnbind.push(this.filterInputActionItem.onDidChange(() => this.updateFilter())); + this.actions.forEach(a => this.toUnbind.push(a)); } - private onMarkerChanged(changedResources: URI[]) { - this.currentResourceGotAddedToMarkersData = this.currentResourceGotAddedToMarkersData || this.isCurrentResourceGotAddedToMarkersData(changedResources); - this.updateResources(changedResources); + private onDidChange(resources: URI[]) { + this.currentResourceGotAddedToMarkersData = this.currentResourceGotAddedToMarkersData || this.isCurrentResourceGotAddedToMarkersData(resources); + this.updateResources(resources); this.delayedRefresh.trigger(() => { this.refreshPanel(); this.updateRangeHighlights(); @@ -289,18 +294,53 @@ export class MarkersPanel extends Panel { } private renderMessage(): void { - this.messageBox.textContent = this.markersWorkbenchService.markersModel.getMessage(); - dom.toggleClass(this.messageBoxContainer, 'hidden', this.markersWorkbenchService.markersModel.hasFilteredResources()); + const markersModel = this.markersWorkbenchService.markersModel; + const hasFilteredResources = markersModel.hasFilteredResources(); + dom.clearNode(this.messageBoxContainer); + dom.toggleClass(this.messageBoxContainer, 'hidden', hasFilteredResources); + if (!hasFilteredResources) { + if (markersModel.hasResources()) { + if (markersModel.filterOptions.filter) { + this.renderFilteredByFilterMessage(this.messageBoxContainer); + } else { + this.renderFilteredByFilesExcludeMessage(this.messageBoxContainer); + } + } else { + this.renderNoProblemsMessage(this.messageBoxContainer); + } + } + } + + private renderFilteredByFilesExcludeMessage(container: HTMLElement) { + const span1 = dom.append(container, dom.$('span')); + span1.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_FILE_EXCLUSIONS_FILTER; + const link = dom.append(container, dom.$('a.messageAction')); + link.textContent = localize('disableFilesExclude', "Disable Files Exclude Filter."); + link.setAttribute('tabIndex', '0'); + dom.addDisposableListener(link, dom.EventType.CLICK, () => this.filterInputActionItem.useFilesExclude = false); + } + + private renderFilteredByFilterMessage(container: HTMLElement) { + const span1 = dom.append(container, dom.$('span')); + span1.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS; + const link = dom.append(container, dom.$('a.messageAction')); + link.textContent = localize('clearFilter', "Clear Filter."); + link.setAttribute('tabIndex', '0'); + dom.addDisposableListener(link, dom.EventType.CLICK, () => this.filterInputActionItem.clear()); + } + + private renderNoProblemsMessage(container: HTMLElement) { + const span = dom.append(container, dom.$('span')); + span.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT; } private autoExpand(): void { - for (const resource of this.markersWorkbenchService.markersModel.filteredResources) { - const resourceUri = resource.uri.toString(); - if (!this.autoExpanded.has(resourceUri)) { + this.markersWorkbenchService.markersModel.forEachFilteredResource(resource => { + if (!this.autoExpanded.has(resource.uri.toString())) { this.tree.expand(resource).done(null, errors.onUnexpectedError); - this.autoExpanded.add(resourceUri); + this.autoExpanded.add(resource.uri.toString()); } - } + }); } private autoReveal(focus: boolean = false): void { @@ -331,21 +371,23 @@ export class MarkersPanel extends Panel { } } - private getResourceForCurrentActiveResource(): Resource { + private getResourceForCurrentActiveResource(): ResourceMarkers { + let res: ResourceMarkers = null; if (this.currentActiveResource) { - let resources = this.markersWorkbenchService.markersModel.filteredResources.filter((resource): boolean => { - return this.currentActiveResource.toString() === resource.uri.toString(); + this.markersWorkbenchService.markersModel.forEachFilteredResource(resource => { + if (!res && resource.uri.toString() === this.currentActiveResource.toString()) { + res = resource; + } }); - return resources.length > 0 ? resources[0] : null; } - return null; + return res; } - private hasSelectedMarkerFor(resource: Resource): boolean { + private hasSelectedMarkerFor(resource: ResourceMarkers): boolean { let selectedElement = this.tree.getSelection(); if (selectedElement && selectedElement.length > 0) { if (selectedElement[0] instanceof Marker) { - if (resource.uri.toString() === selectedElement[0].marker.resource.toString()) { + if (resource.uri.toString() === (selectedElement[0]).raw.resource.toString()) { return true; } } @@ -368,15 +410,24 @@ export class MarkersPanel extends Panel { } } - public getActionItem(action: Action): IActionItem { - if (action.id === FilterAction.ID) { - return this.instantiationService.createInstance(FilterInputBoxActionItem, this, action); + public getFocusElement(): ResourceMarkers | Marker { + return this.tree.getFocus(); + } + + public getActionItem(action: IAction): IActionItem { + if (action.id === MarkersFilterAction.ID) { + return this.filterInputActionItem; } return super.getActionItem(action); } - public getFocusElement(): Resource | Marker { - return this.tree.getFocus(); + public shutdown(): void { + // store memento + this.panelSettings['filter'] = this.filterInputActionItem.getFilterText(); + this.panelSettings['filterHistory'] = this.filterInputActionItem.getFilterHistory(); + this.panelSettings['useFilesExclude'] = this.filterInputActionItem.useFilesExclude; + + super.shutdown(); } public dispose(): void { diff --git a/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts new file mode 100644 index 0000000000..705bf74345 --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts @@ -0,0 +1,294 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Delayer } from 'vs/base/common/async'; +import * as DOM from 'vs/base/browser/dom'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Action, IAction } from 'vs/base/common/actions'; +import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { TogglePanelAction } from 'vs/workbench/browser/panel'; +import Messages from 'vs/workbench/parts/markers/electron-browser/messages'; +import Constants from 'vs/workbench/parts/markers/electron-browser/constants'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { CollapseAllAction as TreeCollapseAction } from 'vs/base/parts/tree/browser/treeDefaults'; +import * as Tree from 'vs/base/parts/tree/browser/tree'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { attachInputBoxStyler, attachStylerCallback, attachCheckboxStyler } from 'vs/platform/theme/common/styler'; +import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/electron-browser/markers'; +import { Event, Emitter } from 'vs/base/common/event'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { HistoryNavigator } from 'vs/base/common/history'; +import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { badgeBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { localize } from 'vs/nls'; +import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox'; + +export class ToggleMarkersPanelAction extends TogglePanelAction { + + public static readonly ID = 'workbench.actions.view.problems'; + public static readonly LABEL = Messages.MARKERS_PANEL_TOGGLE_LABEL; + + constructor(id: string, label: string, + @IPartService partService: IPartService, + @IPanelService panelService: IPanelService, + @IMarkersWorkbenchService markersWorkbenchService: IMarkersWorkbenchService + ) { + super(id, label, Constants.MARKERS_PANEL_ID, panelService, partService); + } +} + +export class ShowProblemsPanelAction extends Action { + + public static readonly ID = 'workbench.action.problems.focus'; + public static readonly LABEL = Messages.MARKERS_PANEL_SHOW_LABEL; + + constructor(id: string, label: string, + @IPanelService private panelService: IPanelService + ) { + super(id, label); + } + + public run(): TPromise { + return this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true); + } +} + +export class CollapseAllAction extends TreeCollapseAction { + + constructor(viewer: Tree.ITree, enabled: boolean) { + super(viewer, enabled); + } +} + +export class MarkersFilterAction extends Action { + + public static readonly ID: string = 'workbench.actions.problems.filter'; + + constructor() { + super(MarkersFilterAction.ID, Messages.MARKERS_PANEL_ACTION_TOOLTIP_FILTER, 'markers-panel-action-filter', true); + } + +} + + +export interface IMarkersFilterActionItemOptions { + filterText: string; + filterHistory: string[]; + useFilesExclude: boolean; +} + +export class MarkersFilterActionItem extends BaseActionItem { + + private _toDispose: IDisposable[] = []; + + private readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; + + private delayedFilterUpdate: Delayer; + private container: HTMLElement; + private filterInputBox: InputBox; + private filterHistory: HistoryNavigator; + private controlsContainer: HTMLInputElement; + private filterBadge: HTMLInputElement; + private filesExcludeFilter: Checkbox; + + constructor( + private itemOptions: IMarkersFilterActionItemOptions, + action: IAction, + @IContextViewService private contextViewService: IContextViewService, + @IThemeService private themeService: IThemeService, + @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService, + @ITelemetryService private telemetryService: ITelemetryService + ) { + super(null, action); + this.delayedFilterUpdate = new Delayer(500); + this.filterHistory = new HistoryNavigator(itemOptions.filterHistory || []); + } + + render(container: HTMLElement): void { + this.container = container; + DOM.addClass(this.container, 'markers-panel-action-filter'); + this.createInput(this.container); + this.createControls(this.container); + this.adjustInputBox(); + } + + clear(): void { + this.filterInputBox.value = ''; + } + + getFilterText(): string { + return this.filterInputBox ? this.filterInputBox.value : this.itemOptions.filterText; + } + + getFilterHistory(): string[] { + return this.filterHistory.getHistory(); + } + + get useFilesExclude(): boolean { + return this.filesExcludeFilter ? this.filesExcludeFilter.checked : this.itemOptions.useFilesExclude; + } + + set useFilesExclude(useFilesExclude: boolean) { + if (this.filesExcludeFilter) { + if (this.filesExcludeFilter.checked !== useFilesExclude) { + this.filesExcludeFilter.checked = useFilesExclude; + this._onDidChange.fire(); + } + } + } + + toggleLayout(small: boolean) { + if (this.container) { + DOM.toggleClass(this.container, 'small', small); + DOM.toggleClass(this.filterBadge, 'small', small); + } + } + + private createInput(container: HTMLElement): void { + this.filterInputBox = new InputBox(container, this.contextViewService, { + placeholder: Messages.MARKERS_PANEL_FILTER_PLACEHOLDER, + ariaLabel: Messages.MARKERS_PANEL_FILTER_ARIA_LABEL + }); + this._register(attachInputBoxStyler(this.filterInputBox, this.themeService)); + this.filterInputBox.value = this.itemOptions.filterText; + this._register(this.filterInputBox.onDidChange(filter => this.delayedFilterUpdate.trigger(() => this.onDidInputChange()))); + this._register(DOM.addStandardDisposableListener(this.filterInputBox.inputElement, 'keydown', (keyboardEvent) => this.onInputKeyDown(keyboardEvent, this.filterInputBox))); + this._register(DOM.addStandardDisposableListener(container, 'keydown', this.handleKeyboardEvent)); + this._register(DOM.addStandardDisposableListener(container, 'keyup', this.handleKeyboardEvent)); + } + + private createControls(container: HTMLElement): void { + this.controlsContainer = DOM.append(container, DOM.$('.markers-panel-filter-controls')); + this.createBadge(this.controlsContainer); + this.createFilesExcludeCheckbox(this.controlsContainer); + } + + private createBadge(container: HTMLElement): void { + this.filterBadge = DOM.append(container, DOM.$('.markers-panel-filter-badge')); + this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder }, colors => { + const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; + const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; + + this.filterBadge.style.backgroundColor = background; + + this.filterBadge.style.borderWidth = border ? '1px' : null; + this.filterBadge.style.borderStyle = border ? 'solid' : null; + this.filterBadge.style.borderColor = border; + })); + this.updateBadge(); + this._register(this.markersWorkbenchService.onDidChange(() => this.updateBadge())); + } + + private createFilesExcludeCheckbox(container: HTMLElement): void { + this.filesExcludeFilter = new Checkbox({ + actionClassName: 'markers-panel-filter-filesExclude', + title: this.itemOptions.useFilesExclude ? Messages.MARKERS_PANEL_ACTION_TOOLTIP_DO_NOT_USE_FILES_EXCLUDE : Messages.MARKERS_PANEL_ACTION_TOOLTIP_USE_FILES_EXCLUDE, + isChecked: this.itemOptions.useFilesExclude, + onChange: () => { + this.filesExcludeFilter.domNode.title = this.filesExcludeFilter.checked ? Messages.MARKERS_PANEL_ACTION_TOOLTIP_DO_NOT_USE_FILES_EXCLUDE : Messages.MARKERS_PANEL_ACTION_TOOLTIP_USE_FILES_EXCLUDE; + this._onDidChange.fire(); + } + }); + this._register(attachCheckboxStyler(this.filesExcludeFilter, this.themeService)); + container.appendChild(this.filesExcludeFilter.domNode); + } + + private onDidInputChange() { + const filterText = this.filterInputBox.value; + if (filterText && filterText !== this.filterHistory.current()) { + this.filterHistory.add(this.getFilterText()); + } + this._onDidChange.fire(); + this.reportFilteringUsed(); + } + + private updateBadge(): void { + const { total, filtered } = this.markersWorkbenchService.markersModel.stats(); + DOM.toggleClass(this.filterBadge, 'hidden', total === filtered || filtered === 0); + this.filterBadge.textContent = localize('showing filtered problems', "Showing {0} of {1}", filtered, total); + this.adjustInputBox(); + } + + private adjustInputBox(): void { + this.filterInputBox.inputElement.style.paddingRight = (DOM.getTotalWidth(this.controlsContainer) || 20) + 'px'; + } + + // Action toolbar is swallowing some keys for action items which should not be for an input box + private handleKeyboardEvent(e: IKeyboardEvent) { + switch (e.keyCode) { + case KeyCode.Space: + case KeyCode.LeftArrow: + case KeyCode.RightArrow: + case KeyCode.Escape: + e.stopPropagation(); + break; + } + } + + private showNextFilter() { + let next = this.filterHistory.next(); + if (next) { + this.filterInputBox.value = next; + } + } + + private showPreviousFilter() { + let previous = this.filterHistory.previous(); + if (this.filterInputBox.value) { + this.filterHistory.addIfNotPresent(this.filterInputBox.value); + } + if (previous) { + this.filterInputBox.value = previous; + } + } + + private onInputKeyDown(keyboardEvent: IKeyboardEvent, filterInputBox: InputBox) { + let handled = false; + switch (keyboardEvent.keyCode) { + case KeyCode.Escape: + filterInputBox.value = ''; + handled = true; + break; + case KeyCode.UpArrow: + this.showPreviousFilter(); + handled = true; + break; + case KeyCode.DownArrow: + this.showNextFilter(); + handled = true; + break; + } + if (handled) { + keyboardEvent.stopPropagation(); + keyboardEvent.preventDefault(); + } + } + + private reportFilteringUsed(): void { + let data = {}; + data['errors'] = this.markersWorkbenchService.markersModel.filterOptions.filterErrors; + data['warnings'] = this.markersWorkbenchService.markersModel.filterOptions.filterWarnings; + data['infos'] = this.markersWorkbenchService.markersModel.filterOptions.filterInfos; + /* __GDPR__ + "problems.filter" : { + "errors" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "warnings": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "infos": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + this.telemetryService.publicLog('problems.filter', data); + } + + private _register(t: T): T { + this._toDispose.push(t); + return t; + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/markersTreeController.ts b/src/vs/workbench/parts/markers/electron-browser/markersTreeController.ts similarity index 92% rename from src/vs/workbench/parts/markers/browser/markersTreeController.ts rename to src/vs/workbench/parts/markers/electron-browser/markersTreeController.ts index 7247895554..fb99f02de5 100644 --- a/src/vs/workbench/parts/markers/browser/markersTreeController.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersTreeController.ts @@ -6,8 +6,8 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as mouse from 'vs/base/browser/mouseEvent'; -import tree = require('vs/base/parts/tree/browser/tree'); -import { MarkersModel } from 'vs/workbench/parts/markers/common/markersModel'; +import * as tree from 'vs/base/parts/tree/browser/tree'; +import { MarkersModel } from 'vs/workbench/parts/markers/electron-browser/markersModel'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IAction } from 'vs/base/common/actions'; @@ -43,7 +43,8 @@ export class Controller extends WorkbenchTreeController { } public onContextMenu(tree: WorkbenchTree, element: any, event: tree.ContextMenuEvent): boolean { - tree.setFocus(element); + tree.setFocus(element, { preventOpenOnFocus: true }); + const actions = this._getMenuActions(tree); if (!actions.length) { return true; @@ -66,7 +67,7 @@ export class Controller extends WorkbenchTreeController { onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - tree.DOMFocus(); + tree.domFocus(); } } }); diff --git a/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts b/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts new file mode 100644 index 0000000000..d464d7e1f9 --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts @@ -0,0 +1,269 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TPromise, Promise } from 'vs/base/common/winjs.base'; +import * as dom from 'vs/base/browser/dom'; +import * as network from 'vs/base/common/network'; +import * as paths from 'vs/base/common/paths'; +import { IDataSource, ITree, IRenderer, IAccessibilityProvider, IFilter } from 'vs/base/parts/tree/browser/tree'; +import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; +import { FileLabel, ResourceLabel } from 'vs/workbench/browser/labels'; +import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; +import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers'; +import { MarkersModel, ResourceMarkers, Marker, RelatedInformation, NodeWithId } from 'vs/workbench/parts/markers/electron-browser/markersModel'; +import Messages from 'vs/workbench/parts/markers/electron-browser/messages'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IDisposable } from 'vs/base/common/lifecycle'; + +interface IResourceMarkersTemplateData { + resourceLabel: ResourceLabel; + count: CountBadge; + styler: IDisposable; +} + +interface IMarkerTemplateData { + icon: HTMLElement; + source: HighlightedLabel; + description: HighlightedLabel; + lnCol: HTMLElement; +} + +interface IRelatedInformationTemplateData { + resourceLabel: HighlightedLabel; + lnCol: HTMLElement; + description: HighlightedLabel; +} + +export class DataSource implements IDataSource { + public getId(tree: ITree, element: any): string { + if (element instanceof MarkersModel) { + return 'root'; + } + if (element instanceof NodeWithId) { + return element.id; + } + return ''; + } + + public hasChildren(tree: ITree, element: any): boolean { + return element instanceof MarkersModel || element instanceof ResourceMarkers || (element instanceof Marker && element.resourceRelatedInformation.length > 0); + } + + public getChildren(tree: ITree, element: any): Promise { + if (element instanceof MarkersModel) { + return Promise.as(element.resources); + } + if (element instanceof ResourceMarkers) { + return Promise.as(element.markers); + } + if (element instanceof Marker && element.resourceRelatedInformation.length > 0) { + return Promise.as(element.resourceRelatedInformation); + } + return null; + } + + public getParent(tree: ITree, element: any): Promise { + return TPromise.as(null); + } +} + +export class DataFilter implements IFilter { + public isVisible(tree: ITree, element: any): boolean { + if (element instanceof ResourceMarkers) { + return element.filteredCount > 0; + } + if (element instanceof Marker) { + return element.isSelected; + } + return true; + } +} + +export class Renderer implements IRenderer { + + private static readonly RESOURCE_MARKERS_TEMPLATE_ID = 'resource-markers-template'; + private static readonly FILE_RESOURCE_MARKERS_TEMPLATE_ID = 'file-resource-markers-template'; + private static readonly MARKER_TEMPLATE_ID = 'marker-template'; + private static readonly RELATED_INFO_TEMPLATE_ID = 'related-info-template'; + + constructor( + @IInstantiationService private instantiationService: IInstantiationService, + @IThemeService private themeService: IThemeService + ) { + } + + public getHeight(tree: ITree, element: any): number { + return 22; + } + + public getTemplateId(tree: ITree, element: any): string { + if (element instanceof ResourceMarkers) { + if ((element).uri.scheme === network.Schemas.file || (element).uri.scheme === network.Schemas.untitled) { + return Renderer.FILE_RESOURCE_MARKERS_TEMPLATE_ID; + } else { + return Renderer.RESOURCE_MARKERS_TEMPLATE_ID; + } + } + if (element instanceof Marker) { + return Renderer.MARKER_TEMPLATE_ID; + } + if (element instanceof RelatedInformation) { + return Renderer.RELATED_INFO_TEMPLATE_ID; + } + return ''; + } + + public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any { + dom.addClass(container, 'markers-panel-tree-entry'); + switch (templateId) { + case Renderer.FILE_RESOURCE_MARKERS_TEMPLATE_ID: + return this.renderFileResourceMarkersTemplate(container); + case Renderer.RESOURCE_MARKERS_TEMPLATE_ID: + return this.renderResourceMarkersTemplate(container); + case Renderer.MARKER_TEMPLATE_ID: + return this.renderMarkerTemplate(container); + case Renderer.RELATED_INFO_TEMPLATE_ID: + return this.renderRelatedInfoTemplate(container); + } + } + + private renderFileResourceMarkersTemplate(container: HTMLElement): IResourceMarkersTemplateData { + const data = Object.create(null); + + const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container')); + data.resourceLabel = this.instantiationService.createInstance(FileLabel, resourceLabelContainer, { supportHighlights: true }); + + const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper')); + data.count = new CountBadge(badgeWrapper); + data.styler = attachBadgeStyler(data.count, this.themeService); + + return data; + } + + private renderResourceMarkersTemplate(container: HTMLElement): IResourceMarkersTemplateData { + const data = Object.create(null); + + const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container')); + data.resourceLabel = this.instantiationService.createInstance(ResourceLabel, resourceLabelContainer, { supportHighlights: true }); + + const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper')); + data.count = new CountBadge(badgeWrapper); + data.styler = attachBadgeStyler(data.count, this.themeService); + + return data; + } + + private renderRelatedInfoTemplate(container: HTMLElement): IRelatedInformationTemplateData { + const data: IRelatedInformationTemplateData = Object.create(null); + + data.resourceLabel = new HighlightedLabel(dom.append(container, dom.$('.related-info-resource'))); + data.lnCol = dom.append(container, dom.$('span.marker-line')); + + const separator = dom.append(container, dom.$('span.related-info-resource-separator')); + separator.textContent = ':'; + separator.style.paddingRight = '4px'; + + data.description = new HighlightedLabel(dom.append(container, dom.$('.marker-description'))); + return data; + } + + private renderMarkerTemplate(container: HTMLElement): IMarkerTemplateData { + const data: IMarkerTemplateData = Object.create(null); + data.icon = dom.append(container, dom.$('.marker-icon')); + data.source = new HighlightedLabel(dom.append(container, dom.$(''))); + data.description = new HighlightedLabel(dom.append(container, dom.$('.marker-description'))); + data.lnCol = dom.append(container, dom.$('span.marker-line')); + return data; + } + + public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void { + switch (templateId) { + case Renderer.FILE_RESOURCE_MARKERS_TEMPLATE_ID: + case Renderer.RESOURCE_MARKERS_TEMPLATE_ID: + return this.renderResourceMarkersElement(tree, element, templateData); + case Renderer.MARKER_TEMPLATE_ID: + return this.renderMarkerElement(tree, (element), templateData); + case Renderer.RELATED_INFO_TEMPLATE_ID: + return this.renderRelatedInfoElement(tree, element, templateData); + } + } + + private renderResourceMarkersElement(tree: ITree, element: ResourceMarkers, templateData: IResourceMarkersTemplateData) { + if (templateData.resourceLabel instanceof FileLabel) { + templateData.resourceLabel.setFile(element.uri, { matches: element.uriMatches }); + } else { + templateData.resourceLabel.setLabel({ name: element.name, description: element.uri.toString(), resource: element.uri }, { matches: element.uriMatches }); + } + (templateData).count.setCount(element.filteredCount); + } + + private renderMarkerElement(tree: ITree, element: Marker, templateData: IMarkerTemplateData) { + let marker = element.raw; + templateData.icon.className = 'icon ' + Renderer.iconClassNameFor(marker); + + templateData.source.set(marker.source, element.sourceMatches); + dom.toggleClass(templateData.source.element, 'marker-source', !!marker.source); + + templateData.description.set(marker.message, element.messageMatches); + templateData.description.element.title = marker.message; + + templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn); + } + + private renderRelatedInfoElement(tree: ITree, element: RelatedInformation, templateData: IRelatedInformationTemplateData) { + templateData.resourceLabel.set(paths.basename(element.raw.resource.fsPath), element.uriMatches); + templateData.resourceLabel.element.title = element.raw.resource.toString(); + templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(element.raw.startLineNumber, element.raw.startColumn); + templateData.description.set(element.raw.message, element.messageMatches); + templateData.description.element.title = element.raw.message; + } + + private static iconClassNameFor(element: IMarker): string { + switch (element.severity) { + case MarkerSeverity.Hint: + return 'info'; + case MarkerSeverity.Info: + return 'info'; + case MarkerSeverity.Warning: + return 'warning'; + case MarkerSeverity.Error: + return 'error'; + } + return ''; + } + + public disposeTemplate(tree: ITree, templateId: string, templateData: any): void { + if (templateId === Renderer.RESOURCE_MARKERS_TEMPLATE_ID || templateId === Renderer.FILE_RESOURCE_MARKERS_TEMPLATE_ID) { + (templateData).resourceLabel.dispose(); + (templateData).styler.dispose(); + } else if (templateId === Renderer.MARKER_TEMPLATE_ID) { + (templateData).description.dispose(); + (templateData).source.dispose(); + } else if (templateId === Renderer.RELATED_INFO_TEMPLATE_ID) { + (templateData).description.dispose(); + (templateData).resourceLabel.dispose(); + } + } +} + +export class MarkersTreeAccessibilityProvider implements IAccessibilityProvider { + + public getAriaLabel(tree: ITree, element: any): string { + if (element instanceof ResourceMarkers) { + return Messages.MARKERS_TREE_ARIA_LABEL_RESOURCE(element.name, element.filteredCount); + } + if (element instanceof Marker) { + return Messages.MARKERS_TREE_ARIA_LABEL_MARKER(element); + } + if (element instanceof RelatedInformation) { + return Messages.MARKERS_TREE_ARIA_LABEL_RELATED_INFORMATION(element.raw); + } + return null; + } +} + diff --git a/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings-dark.svg b/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings-dark.svg new file mode 100755 index 0000000000..3eeedcb41c --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings.svg b/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings.svg new file mode 100755 index 0000000000..79decb032b --- /dev/null +++ b/src/vs/workbench/parts/markers/electron-browser/media/excludeSettings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/media/markers.css b/src/vs/workbench/parts/markers/electron-browser/media/markers.css similarity index 64% rename from src/vs/workbench/parts/markers/browser/media/markers.css rename to src/vs/workbench/parts/markers/electron-browser/media/markers.css index 7d19bb409f..d350426cce 100644 --- a/src/vs/workbench/parts/markers/browser/media/markers.css +++ b/src/vs/workbench/parts/markers/electron-browser/media/markers.css @@ -4,11 +4,18 @@ *--------------------------------------------------------------------------------------------*/ .monaco-action-bar .action-item.markers-panel-action-filter { - max-width: 400px; - min-width: 150px; - flex: 1; cursor: default; margin: 4px 10px 0 0; + min-width: 150px; + max-width: 500px; +} + +.monaco-action-bar .action-item.markers-panel-action-filter { + flex: 0.7; +} + +.monaco-action-bar .action-item.markers-panel-action-filter.small { + flex: 0.5; } .monaco-action-bar .action-item.markers-panel-action-filter .monaco-inputbox { @@ -20,6 +27,37 @@ border: 1px solid #ddd; } +.markers-panel-action-filter > .markers-panel-filter-controls { + position: absolute; + top: 0px; + right: 4px; + display: flex; +} + +.markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-badge { + margin: 4px 0px; + padding: 0px 8px; + border-radius: 2px; +} + +.markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-badge.hidden, +.markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-badge.small { + display: none; +} + +.markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-filesExclude { + margin: 3px 0 0 3px; +} + +.vs .markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-filesExclude { + background: url('excludeSettings.svg') center center no-repeat; +} + +.vs-dark .markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-filesExclude, +.hc-black .markers-panel-action-filter > .markers-panel-filter-controls > .markers-panel-filter-filesExclude { + background: url('excludeSettings-dark.svg') center center no-repeat; +} + .markers-panel .markers-panel-container { height: 100%; } @@ -29,18 +67,16 @@ padding-left: 20px; } -.markers-panel .markers-panel-container .message-box-container span:focus { - outline: none; +.markers-panel .markers-panel-container .message-box-container .messageAction { + margin-left: 4px; + cursor: pointer; + text-decoration: underline; } .markers-panel .markers-panel-container .hidden { display: none; } -.markers-panel .markers-panel-container .tree-container { - height: 100%; -} - .markers-panel .markers-panel-container .tree-container.hidden, .markers-panel .markers-panel-container .message-box-container.hidden { display: none; @@ -71,6 +107,10 @@ overflow: hidden; } +.markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .marker-source { + margin-right: 5px; +} + .markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .marker-source:before { content: '['; } @@ -80,9 +120,10 @@ } .markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .marker-source, +.markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .related-info-resource, +.markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .related-info-resource-separator, .markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .marker-line { opacity: 0.7; - margin-right: 5px; } .markers-panel .markers-panel-container .tree-container .markers-panel-tree-entry .highlight { @@ -91,8 +132,7 @@ .markers-panel .icon { height: 22px; - margin-right: 4px; - margin-left: 4px; + margin-right: 6px; flex: 0 0 16px; } @@ -118,4 +158,4 @@ .vs-dark .markers-panel .icon.info { background: url('status-info-inverse.svg') center center no-repeat; -} +} \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/media/status-error-inverse.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-error-inverse.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-error-inverse.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-error-inverse.svg diff --git a/src/vs/workbench/parts/markers/browser/media/status-error.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-error.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-error.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-error.svg diff --git a/src/vs/workbench/parts/markers/browser/media/status-info-inverse.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-info-inverse.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-info-inverse.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-info-inverse.svg diff --git a/src/vs/workbench/parts/markers/browser/media/status-info.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-info.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-info.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-info.svg diff --git a/src/vs/workbench/parts/markers/browser/media/status-warning-inverse.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-warning-inverse.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-warning-inverse.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-warning-inverse.svg diff --git a/src/vs/workbench/parts/markers/browser/media/status-warning.svg b/src/vs/workbench/parts/markers/electron-browser/media/status-warning.svg similarity index 100% rename from src/vs/workbench/parts/markers/browser/media/status-warning.svg rename to src/vs/workbench/parts/markers/electron-browser/media/status-warning.svg diff --git a/src/vs/workbench/parts/markers/common/messages.ts b/src/vs/workbench/parts/markers/electron-browser/messages.ts similarity index 55% rename from src/vs/workbench/parts/markers/common/messages.ts rename to src/vs/workbench/parts/markers/electron-browser/messages.ts index 8c7ca9af96..55a0a34c98 100644 --- a/src/vs/workbench/parts/markers/common/messages.ts +++ b/src/vs/workbench/parts/markers/electron-browser/messages.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); -import Severity from 'vs/base/common/severity'; -import { IMarker } from 'vs/platform/markers/common/markers'; +import * as nls from 'vs/nls'; +import * as paths from 'vs/base/common/paths'; +import { MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers'; +import { Marker } from './markersModel'; export default class Messages { @@ -21,10 +22,14 @@ export default class Messages { public static MARKERS_PANEL_ARIA_LABEL_PROBLEMS_TREE: string = nls.localize('markers.panel.aria.label.problems.tree', "Problems grouped by files"); public static MARKERS_PANEL_NO_PROBLEMS_BUILT: string = nls.localize('markers.panel.no.problems.build', "No problems have been detected in the workspace so far."); - public static MARKERS_PANEL_NO_PROBLEMS_FILTERS: string = nls.localize('markers.panel.no.problems.filters', "No results found with provided filter criteria"); + public static MARKERS_PANEL_NO_PROBLEMS_FILTERS: string = nls.localize('markers.panel.no.problems.filters', "No results found with provided filter criteria."); + public static MARKERS_PANEL_NO_PROBLEMS_FILE_EXCLUSIONS_FILTER: string = nls.localize('markers.panel.no.problems.file.exclusions', "All problems are hidden because files exclude filter is enabled."); + public static MARKERS_PANEL_ACTION_TOOLTIP_USE_FILES_EXCLUDE: string = nls.localize('markers.panel.action.useFilesExclude', "Filter using Files Exclude Setting"); + public static MARKERS_PANEL_ACTION_TOOLTIP_DO_NOT_USE_FILES_EXCLUDE: string = nls.localize('markers.panel.action.donotUseFilesExclude', "Do not use Files Exclude Setting"); public static MARKERS_PANEL_ACTION_TOOLTIP_FILTER: string = nls.localize('markers.panel.action.filter', "Filter Problems"); - public static MARKERS_PANEL_FILTER_PLACEHOLDER: string = nls.localize('markers.panel.filter.placeholder', "Filter by type or text"); + public static MARKERS_PANEL_FILTER_ARIA_LABEL: string = nls.localize('markers.panel.filter.ariaLabel', "Filter Problems"); + public static MARKERS_PANEL_FILTER_PLACEHOLDER: string = nls.localize('markers.panel.filter.placeholder', "Filter. Eg: text, **/*.ts, !**/node_modules/**"); public static MARKERS_PANEL_FILTER_ERRORS: string = nls.localize('markers.panel.filter.errors', "errors"); public static MARKERS_PANEL_FILTER_WARNINGS: string = nls.localize('markers.panel.filter.warnings', "warnings"); public static MARKERS_PANEL_FILTER_INFOS: string = nls.localize('markers.panel.filter.infos', "infos"); @@ -41,23 +46,24 @@ export default class Messages { public static readonly MARKERS_PANEL_AT_LINE_COL_NUMBER = (ln: number, col: number): string => { return nls.localize('markers.panel.at.ln.col.number', "({0}, {1})", '' + ln, '' + col); }; public static readonly MARKERS_TREE_ARIA_LABEL_RESOURCE = (fileName: string, noOfProblems: number): string => { return nls.localize('problems.tree.aria.label.resource', "{0} with {1} problems", fileName, noOfProblems); }; - public static readonly MARKERS_TREE_ARIA_LABEL_MARKER = (marker: IMarker): string => { - switch (marker.severity) { - case Severity.Error: - return marker.source ? nls.localize('problems.tree.aria.label.error.marker', "Error generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn) - : nls.localize('problems.tree.aria.label.error.marker.nosource', "Error: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn); - case Severity.Warning: - return marker.source ? nls.localize('problems.tree.aria.label.warning.marker', "Warning generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn) - : nls.localize('problems.tree.aria.label.warning.marker.nosource', "Warning: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn); + public static readonly MARKERS_TREE_ARIA_LABEL_MARKER = (marker: Marker): string => { + const relatedInformationMessage = marker.resourceRelatedInformation.length ? nls.localize('problems.tree.aria.label.marker.relatedInformation', " This problem has references to {0} locations.", marker.resourceRelatedInformation.length) : ''; + switch (marker.raw.severity) { + case MarkerSeverity.Error: + return marker.raw.source ? nls.localize('problems.tree.aria.label.error.marker', "Error generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage) + : nls.localize('problems.tree.aria.label.error.marker.nosource', "Error: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage); + case MarkerSeverity.Warning: + return marker.raw.source ? nls.localize('problems.tree.aria.label.warning.marker', "Warning generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage) + : nls.localize('problems.tree.aria.label.warning.marker.nosource', "Warning: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage, relatedInformationMessage); - case Severity.Info: - return marker.source ? nls.localize('problems.tree.aria.label.info.marker', "Info generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn) - : nls.localize('problems.tree.aria.label.info.marker.nosource', "Info: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn); + case MarkerSeverity.Info: + return marker.raw.source ? nls.localize('problems.tree.aria.label.info.marker', "Info generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage) + : nls.localize('problems.tree.aria.label.info.marker.nosource', "Info: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage); default: - return marker.source ? nls.localize('problems.tree.aria.label.marker', "Problem generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn) - : nls.localize('problems.tree.aria.label.marker.nosource', "Problem: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn); + return marker.raw.source ? nls.localize('problems.tree.aria.label.marker', "Problem generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage) + : nls.localize('problems.tree.aria.label.marker.nosource', "Problem: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage); } } - + public static readonly MARKERS_TREE_ARIA_LABEL_RELATED_INFORMATION = (relatedInformation: IRelatedInformation): string => nls.localize('problems.tree.aria.label.relatedinfo.message', "{0} at line {1} and character {2} in {3}", relatedInformation.message, relatedInformation.startLineNumber, relatedInformation.startColumn, paths.basename(relatedInformation.resource.fsPath)); public static SHOW_ERRORS_WARNINGS_ACTION_LABEL: string = nls.localize('errors.warnings.show.label', "Show Errors and Warnings"); -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/markers/markers.contribution.ts b/src/vs/workbench/parts/markers/markers.contribution.ts deleted file mode 100644 index 9722e24d3c..0000000000 --- a/src/vs/workbench/parts/markers/markers.contribution.ts +++ /dev/null @@ -1,11 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { registerContributions } from 'vs/workbench/parts/markers/browser/markersWorkbenchContributions'; -import { registerContributions as registerElectronContributions } from 'vs/workbench/parts/markers/electron-browser/markersElectronContributions'; - -import './browser/markersFileDecorations'; - -registerContributions(); -registerElectronContributions(); diff --git a/src/vs/workbench/parts/markers/test/common/markersModel.test.ts b/src/vs/workbench/parts/markers/test/electron-browser/markersModel.test.ts similarity index 52% rename from src/vs/workbench/parts/markers/test/common/markersModel.test.ts rename to src/vs/workbench/parts/markers/test/electron-browser/markersModel.test.ts index 0a3320aba5..5188bdfb99 100644 --- a/src/vs/workbench/parts/markers/test/common/markersModel.test.ts +++ b/src/vs/workbench/parts/markers/test/electron-browser/markersModel.test.ts @@ -5,11 +5,29 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; -import { IMarker } from 'vs/platform/markers/common/markers'; -import { MarkersModel, Marker, Resource } from 'vs/workbench/parts/markers/common/markersModel'; +import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers'; +import { MarkersModel, Marker, ResourceMarkers, RelatedInformation } from 'vs/workbench/parts/markers/electron-browser/markersModel'; + +class TestMarkersModel extends MarkersModel { + + get filteredResources(): ResourceMarkers[] { + let res: ResourceMarkers[] = []; + this.forEachFilteredResource(resource => res.push(resource)); + return res; + } + + static compare(a: any, b: any): number { + if (a instanceof ResourceMarkers && b instanceof ResourceMarkers) { + return ResourceMarkers.compare(a, b); + } + if (a instanceof Marker && b instanceof Marker) { + return Marker.compare(a, b); + } + return 0; + } +} suite('MarkersModel Test', () => { @@ -20,7 +38,7 @@ suite('MarkersModel Test', () => { let marker4 = aMarker('res3'); let marker5 = aMarker('res4'); let marker6 = aMarker('res2'); - let testObject = new MarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); + let testObject = new TestMarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); let actuals = testObject.filteredResources; @@ -46,15 +64,15 @@ suite('MarkersModel Test', () => { }); test('sort palces resources with no errors at the end', function () { - let marker1 = aMarker('a/res1', Severity.Warning); + let marker1 = aMarker('a/res1', MarkerSeverity.Warning); let marker2 = aMarker('a/res2'); let marker3 = aMarker('res4'); let marker4 = aMarker('b/res3'); let marker5 = aMarker('res4'); - let marker6 = aMarker('c/res2', Severity.Info); - let testObject = new MarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); + let marker6 = aMarker('c/res2', MarkerSeverity.Info); + let testObject = new TestMarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); - let actuals = testObject.filteredResources.sort(MarkersModel.compare); + let actuals = testObject.filteredResources.sort(TestMarkersModel.compare); assert.equal(5, actuals.length); assert.ok(compareResource(actuals[0], 'a/res2')); @@ -71,9 +89,9 @@ suite('MarkersModel Test', () => { let marker4 = aMarker('b/res3'); let marker5 = aMarker('res4'); let marker6 = aMarker('c/res2'); - let testObject = new MarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); + let testObject = new TestMarkersModel([marker1, marker2, marker3, marker4, marker5, marker6]); - let actuals = testObject.filteredResources.sort(MarkersModel.compare); + let actuals = testObject.filteredResources.sort(TestMarkersModel.compare); assert.equal(5, actuals.length); assert.ok(compareResource(actuals[0], 'a/res1')); @@ -99,43 +117,54 @@ suite('MarkersModel Test', () => { let marker13 = aWarningWithRange(5); let marker14 = anErrorWithRange(4); let marker15 = anErrorWithRange(8, 2, 8, 4); - let testObject = new MarkersModel([marker1, marker2, marker3, marker4, marker5, marker6, marker7, marker8, marker9, marker10, marker11, marker12, marker13, marker14, marker15]); + let testObject = new TestMarkersModel([marker1, marker2, marker3, marker4, marker5, marker6, marker7, marker8, marker9, marker10, marker11, marker12, marker13, marker14, marker15]); - let actuals = testObject.filteredResources[0].markers.sort(MarkersModel.compare); + let actuals = testObject.filteredResources[0].markers.sort(TestMarkersModel.compare); - assert.equal(actuals[0].marker, marker6); - assert.equal(actuals[1].marker, marker14); - assert.equal(actuals[2].marker, marker7); - assert.equal(actuals[3].marker, marker9); - assert.equal(actuals[4].marker, marker11); - assert.equal(actuals[5].marker, marker3); - assert.equal(actuals[6].marker, marker15); - assert.equal(actuals[7].marker, marker10); - assert.equal(actuals[8].marker, marker2); - assert.equal(actuals[9].marker, marker13); - assert.equal(actuals[10].marker, marker1); - assert.equal(actuals[11].marker, marker8); - assert.equal(actuals[12].marker, marker5); - assert.equal(actuals[13].marker, marker12); - assert.equal(actuals[14].marker, marker4); + assert.equal(actuals[0].raw, marker6); + assert.equal(actuals[1].raw, marker14); + assert.equal(actuals[2].raw, marker7); + assert.equal(actuals[3].raw, marker9); + assert.equal(actuals[4].raw, marker11); + assert.equal(actuals[5].raw, marker3); + assert.equal(actuals[6].raw, marker15); + assert.equal(actuals[7].raw, marker10); + assert.equal(actuals[8].raw, marker2); + assert.equal(actuals[9].raw, marker13); + assert.equal(actuals[10].raw, marker1); + assert.equal(actuals[11].raw, marker8); + assert.equal(actuals[12].raw, marker5); + assert.equal(actuals[13].raw, marker12); + assert.equal(actuals[14].raw, marker4); }); test('toString()', function () { - const res1Marker = aMarker('a/res1'); - res1Marker.code = '1234'; - assert.equal(`file: 'file:///a/res1'\nseverity: 'Error'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'\ncode: '1234'`, new Marker('', res1Marker).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: 'Warning'\nmessage: 'some message'\nat: '10,5'\nsource: 'tslint'\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Warning)).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: 'Info'\nmessage: 'Info'\nat: '1,2'\nsource: ''\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Info, 1, 2, 1, 8, 'Info', '')).toString()); - assert.equal(`file: 'file:///a/res2'\nseverity: ''\nmessage: 'Ignore message'\nat: '1,2'\nsource: 'Ignore'\ncode: ''`, new Marker('', aMarker('a/res2', Severity.Ignore, 1, 2, 1, 8, 'Ignore message', 'Ignore')).toString()); + let marker = aMarker('a/res1'); + marker.code = '1234'; + assert.equal(JSON.stringify({ ...marker, resource: marker.resource.path }, null, '\t'), new Marker('', marker).toString()); + + marker = aMarker('a/res2', MarkerSeverity.Warning); + assert.equal(JSON.stringify({ ...marker, resource: marker.resource.path }, null, '\t'), new Marker('', marker).toString()); + + marker = aMarker('a/res2', MarkerSeverity.Info, 1, 2, 1, 8, 'Info', ''); + assert.equal(JSON.stringify({ ...marker, resource: marker.resource.path }, null, '\t'), new Marker('', marker).toString()); + + marker = aMarker('a/res2', MarkerSeverity.Hint, 1, 2, 1, 8, 'Ignore message', 'Ignore'); + assert.equal(JSON.stringify({ ...marker, resource: marker.resource.path }, null, '\t'), new Marker('', marker).toString()); + + marker = aMarker('a/res2', MarkerSeverity.Warning, 1, 2, 1, 8, 'Warning message', '', [{ startLineNumber: 2, startColumn: 5, endLineNumber: 2, endColumn: 10, message: 'some info', resource: URI.file('a/res3') }]); + const testObject = new Marker('', marker); + testObject.resourceRelatedInformation = marker.relatedInformation.map(r => new RelatedInformation('', r)); + assert.equal(JSON.stringify({ ...marker, resource: marker.resource.path, relatedInformation: marker.relatedInformation.map(r => ({ ...r, resource: r.resource.path })) }, null, '\t'), testObject.toString()); }); function hasMarker(markers: Marker[], marker: IMarker): boolean { return markers.filter((m): boolean => { - return m.marker === marker; + return m.raw === marker; }).length === 1; } - function compareResource(a: Resource, b: string): boolean { + function compareResource(a: ResourceMarkers, b: string): boolean { return a.uri.toString() === URI.file(b).toString(); } @@ -145,7 +174,7 @@ suite('MarkersModel Test', () => { endColumn: number = startColumn + 5, message: string = 'some message', ): IMarker { - return aMarker('some resource', Severity.Error, startLineNumber, startColumn, endLineNumber, endColumn, message); + return aMarker('some resource', MarkerSeverity.Error, startLineNumber, startColumn, endLineNumber, endColumn, message); } function aWarningWithRange(startLineNumber: number = 10, @@ -154,7 +183,7 @@ suite('MarkersModel Test', () => { endColumn: number = startColumn + 5, message: string = 'some message', ): IMarker { - return aMarker('some resource', Severity.Warning, startLineNumber, startColumn, endLineNumber, endColumn, message); + return aMarker('some resource', MarkerSeverity.Warning, startLineNumber, startColumn, endLineNumber, endColumn, message); } function anInfoWithRange(startLineNumber: number = 10, @@ -163,7 +192,7 @@ suite('MarkersModel Test', () => { endColumn: number = startColumn + 5, message: string = 'some message', ): IMarker { - return aMarker('some resource', Severity.Info, startLineNumber, startColumn, endLineNumber, endColumn, message); + return aMarker('some resource', MarkerSeverity.Info, startLineNumber, startColumn, endLineNumber, endColumn, message); } function anIgnoreWithRange(startLineNumber: number = 10, @@ -172,17 +201,18 @@ suite('MarkersModel Test', () => { endColumn: number = startColumn + 5, message: string = 'some message', ): IMarker { - return aMarker('some resource', Severity.Ignore, startLineNumber, startColumn, endLineNumber, endColumn, message); + return aMarker('some resource', MarkerSeverity.Hint, startLineNumber, startColumn, endLineNumber, endColumn, message); } function aMarker(resource: string = 'some resource', - severity: Severity = Severity.Error, + severity: MarkerSeverity = MarkerSeverity.Error, startLineNumber: number = 10, startColumn: number = 5, endLineNumber: number = startLineNumber + 1, endColumn: number = startColumn + 5, message: string = 'some message', - source: string = 'tslint' + source: string = 'tslint', + relatedInformation?: IRelatedInformation[] ): IMarker { return { owner: 'someOwner', @@ -193,7 +223,8 @@ suite('MarkersModel Test', () => { startColumn, endLineNumber, endColumn, - source + source, + relatedInformation }; } -}); \ No newline at end of file +}); diff --git a/src/vs/workbench/parts/output/browser/media/open_log_file.svg b/src/vs/workbench/parts/output/browser/media/open_log_file.svg new file mode 100644 index 0000000000..d23a23c6b5 --- /dev/null +++ b/src/vs/workbench/parts/output/browser/media/open_log_file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions/markdown/media/ViewSource_inverse.svg b/src/vs/workbench/parts/output/browser/media/open_log_file_inverse.svg similarity index 100% rename from extensions/markdown/media/ViewSource_inverse.svg rename to src/vs/workbench/parts/output/browser/media/open_log_file_inverse.svg diff --git a/src/vs/workbench/parts/output/browser/media/output.css b/src/vs/workbench/parts/output/browser/media/output.css index 9076cbf901..a94cbeed76 100644 --- a/src/vs/workbench/parts/output/browser/media/output.css +++ b/src/vs/workbench/parts/output/browser/media/output.css @@ -29,3 +29,12 @@ .hc-black .monaco-workbench .output-action.output-scroll-unlock { background: url('output_unlock_inverse.svg') center center no-repeat; } + +.monaco-workbench .output-action.open-log-file { + background: url('open_log_file.svg') center center no-repeat; +} + +.vs-dark .monaco-workbench .output-action.open-log-file, +.hc-black .monaco-workbench .output-action.open-log-file { + background: url('open_log_file_inverse.svg') center center no-repeat; +} diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index 43461abc8d..426c7901bc 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -5,9 +5,9 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { IAction, Action } from 'vs/base/common/actions'; -import { IOutputService, OUTPUT_PANEL_ID, IOutputChannelRegistry, Extensions as OutputExt } from 'vs/workbench/parts/output/common/output'; +import { IOutputService, OUTPUT_PANEL_ID, IOutputChannelRegistry, Extensions as OutputExt, IOutputChannelIdentifier, COMMAND_OPEN_LOG_VIEWER } from 'vs/workbench/parts/output/common/output'; import { SelectActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -17,6 +17,9 @@ import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { Registry } from 'vs/platform/registry/common/platform'; +import { groupBy } from 'vs/base/common/arrays'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import URI from 'vs/base/common/uri'; export class ToggleOutputAction extends TogglePanelAction { @@ -39,15 +42,13 @@ export class ClearOutputAction extends Action { constructor( id: string, label: string, - @IOutputService private outputService: IOutputService, - @IPanelService private panelService: IPanelService + @IOutputService private outputService: IOutputService ) { super(id, label, 'output-action clear-output'); } public run(): TPromise { this.outputService.getActiveChannel().clear(); - this.panelService.getActivePanel().focus(); return TPromise.as(true); } @@ -94,7 +95,7 @@ export class SwitchOutputAction extends Action { public static readonly ID = 'workbench.output.action.switchBetweenOutputs'; - constructor( @IOutputService private outputService: IOutputService) { + constructor(@IOutputService private outputService: IOutputService) { super(SwitchOutputAction.ID, nls.localize('switchToOutput.label', "Switch to Output")); this.class = 'output-action switch-to-output'; @@ -107,6 +108,8 @@ export class SwitchOutputAction extends Action { export class SwitchOutputActionItem extends SelectActionItem { + private static readonly SEPARATOR = '─────────'; + constructor( action: IAction, @IOutputService private outputService: IOutputService, @@ -115,35 +118,74 @@ export class SwitchOutputActionItem extends SelectActionItem { ) { super(null, action, [], 0, contextViewService); - let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); - this.toDispose.push(outputChannelRegistry.onDidRegisterChannel(() => this.updateOtions())); - this.toDispose.push(outputChannelRegistry.onDidRemoveChannel(() => this.updateOtions())); - this.toDispose.push(this.outputService.onActiveOutputChannel(activeChannelId => this.setOptions(this.getOptions(), this.getSelected(activeChannelId)))); + let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); + this.toDispose.push(outputChannelRegistry.onDidRegisterChannel(() => this.updateOtions(this.outputService.getActiveChannel().id))); + this.toDispose.push(outputChannelRegistry.onDidRemoveChannel(() => this.updateOtions(this.outputService.getActiveChannel().id))); + this.toDispose.push(this.outputService.onActiveOutputChannel(activeChannelId => this.updateOtions(activeChannelId))); this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService)); - this.setOptions(this.getOptions(), this.getSelected(this.outputService.getActiveChannel().id)); + this.updateOtions(this.outputService.getActiveChannel().id); } protected getActionContext(option: string): string { const channel = this.outputService.getChannels().filter(channelData => channelData.label === option).pop(); - return channel ? channel.id : option; } - private getOptions(): string[] { - return this.outputService.getChannels().map(c => c.label); - } - - private updateOtions(): void { - const activeChannelIndex = this.getSelected(this.outputService.getActiveChannel().id); - this.setOptions(this.getOptions(), activeChannelIndex); - } - - private getSelected(outputId: string): number { - if (!outputId) { - return undefined; + private updateOtions(selectedChannel: string): void { + const groups = groupBy(this.outputService.getChannels(), (c1: IOutputChannelIdentifier, c2: IOutputChannelIdentifier) => { + if (!c1.file && c2.file) { + return -1; + } + if (c1.file && !c2.file) { + return 1; + } + return 0; + }); + const channels = groups[0] || []; + const fileChannels = groups[1] || []; + const showSeparator = channels.length && fileChannels.length; + const separatorIndex = showSeparator ? channels.length : -1; + const options: string[] = [...channels.map(c => c.label), ...(showSeparator ? [SwitchOutputActionItem.SEPARATOR] : []), ...fileChannels.map(c => c.label)]; + let selected = 0; + if (selectedChannel) { + selected = channels.map(c => c.id).indexOf(selectedChannel); + if (selected === -1) { + selected = separatorIndex + 1 + fileChannels.map(c => c.id).indexOf(selectedChannel); + } } - - return Math.max(0, this.outputService.getChannels().map(c => c.id).indexOf(outputId)); + this.setOptions(options, Math.max(0, selected), separatorIndex !== -1 ? separatorIndex : void 0); + } +} + +export class OpenLogOutputFile extends Action { + + public static readonly ID = 'workbench.output.action.openLogOutputFile'; + public static readonly LABEL = nls.localize('openInLogViewer', "Open Log File"); + + private disposables: IDisposable[] = []; + + constructor( + @ICommandService private commandService: ICommandService, + @IOutputService private outputService: IOutputService + ) { + super(OpenLogOutputFile.ID, OpenLogOutputFile.LABEL, 'output-action open-log-file'); + this.outputService.onActiveOutputChannel(this.update, this, this.disposables); + this.update(); + } + + private update(): void { + const logFile = this.getActiveLogChannelFile(); + this.enabled = !!logFile; + } + + public run(): TPromise { + return this.commandService.executeCommand(COMMAND_OPEN_LOG_VIEWER, this.getActiveLogChannelFile()); + } + + private getActiveLogChannelFile(): URI { + const channel = this.outputService.getActiveChannel(); + const identifier = channel ? this.outputService.getChannels().filter(c => c.id === channel.id)[0] : null; + return identifier ? identifier.file : null; } } diff --git a/src/vs/workbench/parts/output/browser/outputPanel.ts b/src/vs/workbench/parts/output/browser/outputPanel.ts index eb05e6b99c..d1dd4866f8 100644 --- a/src/vs/workbench/parts/output/browser/outputPanel.ts +++ b/src/vs/workbench/parts/output/browser/outputPanel.ts @@ -4,10 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/output'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action, IAction } from 'vs/base/common/actions'; -import { Builder } from 'vs/base/browser/builder'; import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -19,7 +18,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { OUTPUT_PANEL_ID, IOutputService, CONTEXT_IN_OUTPUT } from 'vs/workbench/parts/output/common/output'; -import { SwitchOutputAction, SwitchOutputActionItem, ClearOutputAction, ToggleOutputScrollLockAction } from 'vs/workbench/parts/output/browser/outputActions'; +import { SwitchOutputAction, SwitchOutputActionItem, ClearOutputAction, ToggleOutputScrollLockAction, OpenLogOutputFile } from 'vs/workbench/parts/output/browser/outputActions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -55,7 +54,8 @@ export class OutputPanel extends AbstractTextResourceEditor { this.actions = [ this.instantiationService.createInstance(SwitchOutputAction), this.instantiationService.createInstance(ClearOutputAction, ClearOutputAction.ID, ClearOutputAction.LABEL), - this.instantiationService.createInstance(ToggleOutputScrollLockAction, ToggleOutputScrollLockAction.ID, ToggleOutputScrollLockAction.LABEL) + this.instantiationService.createInstance(ToggleOutputScrollLockAction, ToggleOutputScrollLockAction.ID, ToggleOutputScrollLockAction.LABEL), + this.instantiationService.createInstance(OpenLogOutputFile) ]; this.actions.forEach(a => { @@ -120,9 +120,9 @@ export class OutputPanel extends AbstractTextResourceEditor { super.clearInput(); } - protected createEditor(parent: Builder): void { + protected createEditor(parent: HTMLElement): void { // First create the scoped instantation service and only then construct the editor using the scoped service - const scopedContextKeyService = this.contextKeyService.createScoped(parent.getHTMLElement()); + const scopedContextKeyService = this.contextKeyService.createScoped(parent); this.toUnbind.push(scopedContextKeyService); this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, scopedContextKeyService])); super.createEditor(parent); diff --git a/src/vs/workbench/parts/output/common/output.ts b/src/vs/workbench/parts/output/common/output.ts index fa35cb3dfd..2993f885f8 100644 --- a/src/vs/workbench/parts/output/common/output.ts +++ b/src/vs/workbench/parts/output/common/output.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -61,6 +61,8 @@ export const MAX_OUTPUT_LENGTH = 10000 /* Max. number of output lines to show in export const CONTEXT_IN_OUTPUT = new RawContextKey('inOutput', false); +export const CONTEXT_ACTIVE_LOG_OUTPUT = new RawContextKey('activeLogOutput', false); + export const IOutputService = createDecorator(OUTPUT_SERVICE_ID); /** @@ -165,10 +167,10 @@ export interface IOutputChannelRegistry { class OutputChannelRegistry implements IOutputChannelRegistry { private channels = new Map(); - private _onDidRegisterChannel: Emitter = new Emitter(); + private readonly _onDidRegisterChannel: Emitter = new Emitter(); readonly onDidRegisterChannel: Event = this._onDidRegisterChannel.event; - private _onDidRemoveChannel: Emitter = new Emitter(); + private readonly _onDidRemoveChannel: Emitter = new Emitter(); readonly onDidRemoveChannel: Event = this._onDidRemoveChannel.event; public registerChannel(id: string, label: string, file?: URI): void { diff --git a/src/vs/workbench/parts/output/common/outputLinkComputer.ts b/src/vs/workbench/parts/output/common/outputLinkComputer.ts index 3d6a661358..a365d94c50 100644 --- a/src/vs/workbench/parts/output/common/outputLinkComputer.ts +++ b/src/vs/workbench/parts/output/common/outputLinkComputer.ts @@ -8,9 +8,9 @@ import { IMirrorModel, IWorkerContext } from 'vs/editor/common/services/editorSi import { ILink } from 'vs/editor/common/modes'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import strings = require('vs/base/common/strings'); -import arrays = require('vs/base/common/arrays'); +import * as paths from 'vs/base/common/paths'; +import * as strings from 'vs/base/common/strings'; +import * as arrays from 'vs/base/common/arrays'; import { Range } from 'vs/editor/common/core/range'; export interface ICreateData { @@ -94,23 +94,28 @@ export class OutputLinkComputer { ]); workspaceFolderVariants.forEach(workspaceFolderVariant => { + const validPathCharacterPattern = '[^\\s\\(\\):<>"]'; + const validPathCharacterOrSpacePattern = `(?:${validPathCharacterPattern}| ${validPathCharacterPattern})`; + const pathPattern = `${validPathCharacterOrSpacePattern}+\\.${validPathCharacterPattern}+`; + const strictPathPattern = `${validPathCharacterPattern}+`; // Example: /workspaces/express/server.js on line 8, column 13 - patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + '(\\S*) on line ((\\d+)(, column (\\d+))?)', 'gi')); + patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + `(${pathPattern}) on line ((\\d+)(, column (\\d+))?)`, 'gi')); // Example: /workspaces/express/server.js:line 8, column 13 - patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + '(\\S*):line ((\\d+)(, column (\\d+))?)', 'gi')); + patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + `(${pathPattern}):line ((\\d+)(, column (\\d+))?)`, 'gi')); // Example: /workspaces/mankala/Features.ts(45): error // Example: /workspaces/mankala/Features.ts (45): error // Example: /workspaces/mankala/Features.ts(45,18): error // Example: /workspaces/mankala/Features.ts (45,18): error - patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + '([^\\s\\(\\)]*)(\\s?\\((\\d+)(,(\\d+))?)\\)', 'gi')); + // Example: /workspaces/mankala/Features Special.ts (45,18): error + patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + `(${pathPattern})(\\s?\\((\\d+)(,(\\d+))?)\\)`, 'gi')); // Example: at /workspaces/mankala/Game.ts // Example: at /workspaces/mankala/Game.ts:336 // Example: at /workspaces/mankala/Game.ts:336:9 - patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + '([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?', 'gi')); + patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceFolderVariant) + `(${strictPathPattern})(:(\\d+))?(:(\\d+))?`, 'gi')); }); return patterns; diff --git a/src/vs/workbench/parts/output/electron-browser/output.contribution.ts b/src/vs/workbench/parts/output/electron-browser/output.contribution.ts index 3552732f08..75bcd0809c 100644 --- a/src/vs/workbench/parts/output/electron-browser/output.contribution.ts +++ b/src/vs/workbench/parts/output/electron-browser/output.contribution.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -12,8 +12,8 @@ import { KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { OutputService, LogContentProvider } from 'vs/workbench/parts/output/electron-browser/outputServices'; -import { ToggleOutputAction, ClearOutputAction } from 'vs/workbench/parts/output/browser/outputActions'; -import { OUTPUT_MODE_ID, OUTPUT_MIME, OUTPUT_PANEL_ID, IOutputService, CONTEXT_IN_OUTPUT, LOG_SCHEME, COMMAND_OPEN_LOG_VIEWER, LOG_MODE_ID, LOG_MIME } from 'vs/workbench/parts/output/common/output'; +import { ToggleOutputAction, ClearOutputAction, OpenLogOutputFile } from 'vs/workbench/parts/output/browser/outputActions'; +import { OUTPUT_MODE_ID, OUTPUT_MIME, OUTPUT_PANEL_ID, IOutputService, CONTEXT_IN_OUTPUT, LOG_SCHEME, COMMAND_OPEN_LOG_VIEWER, LOG_MODE_ID, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT } from 'vs/workbench/parts/output/common/output'; import { PanelRegistry, Extensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -168,6 +168,18 @@ registerAction({ } }); +registerAction({ + id: 'workbench.action.openActiveLogOutputFile', + title: nls.localize('openActiveLogOutputFile', "View: Open Active Log Output File"), + menu: { + menuId: MenuId.CommandPalette, + when: CONTEXT_ACTIVE_LOG_OUTPUT + }, + handler(accessor) { + accessor.get(IInstantiationService).createInstance(OpenLogOutputFile).run(); + } +}); + CommandsRegistry.registerCommand(COMMAND_OPEN_LOG_VIEWER, function (accessor: ServicesAccessor, file: URI) { if (file) { const editorService = accessor.get(IWorkbenchEditorService); diff --git a/src/vs/workbench/parts/output/electron-browser/outputServices.ts b/src/vs/workbench/parts/output/electron-browser/outputServices.ts index 4c6e922a2a..a2c1da855c 100644 --- a/src/vs/workbench/parts/output/electron-browser/outputServices.ts +++ b/src/vs/workbench/parts/output/electron-browser/outputServices.ts @@ -9,14 +9,14 @@ import * as strings from 'vs/base/common/strings'; import * as extfs from 'vs/base/node/extfs'; import * as fs from 'fs'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorOptions } from 'vs/workbench/common/editor'; -import { IOutputChannelIdentifier, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, OUTPUT_MIME, MAX_OUTPUT_LENGTH, LOG_SCHEME, LOG_MIME } from 'vs/workbench/parts/output/common/output'; +import { IOutputChannelIdentifier, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, OUTPUT_MIME, MAX_OUTPUT_LENGTH, LOG_SCHEME, LOG_MIME, CONTEXT_ACTIVE_LOG_OUTPUT } from 'vs/workbench/parts/output/common/output'; import { OutputPanel } from 'vs/workbench/parts/output/browser/outputPanel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -37,9 +37,9 @@ import { toLocalISOString } from 'vs/base/common/date'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { ILogService } from 'vs/platform/log/common/log'; import { binarySearch } from 'vs/base/common/arrays'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Schemas } from 'vs/base/common/network'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel'; @@ -315,7 +315,7 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out class OutputFileListener extends Disposable { - private _onDidChange: Emitter = new Emitter(); + private readonly _onDidChange: Emitter = new Emitter(); readonly onDidContentChange: Event = this._onDidChange.event; private watching: boolean = false; @@ -423,7 +423,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo private activeChannel: IOutputChannel; private readonly outputDir: string; - private _onActiveOutputChannel: Emitter = new Emitter(); + private readonly _onActiveOutputChannel: Emitter = new Emitter(); readonly onActiveOutputChannel: Event = this._onActiveOutputChannel.event; private _outputPanel: OutputPanel; @@ -436,9 +436,9 @@ export class OutputService extends Disposable implements IOutputService, ITextMo @ITextModelService textModelResolverService: ITextModelService, @IEnvironmentService environmentService: IEnvironmentService, @IWindowService windowService: IWindowService, - @ITelemetryService private telemetryService: ITelemetryService, @ILogService private logService: ILogService, @ILifecycleService private lifecycleService: ILifecycleService, + @IContextKeyService private contextKeyService: IContextKeyService, ) { super(); this.activeChannelIdInStorage = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, null); @@ -470,7 +470,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo } provideTextContent(resource: URI): TPromise { - const channel = this.getChannel(resource.fsPath); + const channel = this.getChannel(resource.path); if (channel) { return channel.loadModel(); } @@ -510,21 +510,24 @@ export class OutputService extends Disposable implements IOutputService, ITextMo this.channels.set(channelId, channel); if (this.activeChannelIdInStorage === channelId) { this.activeChannel = channel; - this.onDidPanelOpen(this.panelService.getActivePanel()); + this.onDidPanelOpen(this.panelService.getActivePanel()) + .then(() => this._onActiveOutputChannel.fire(channelId)); } } - private onDidPanelOpen(panel: IPanel): void { + private onDidPanelOpen(panel: IPanel): TPromise { if (panel && panel.getId() === OUTPUT_PANEL_ID) { this._outputPanel = this.panelService.getActivePanel(); if (this.activeChannel) { - this.doShowChannel(this.activeChannel, true); + return this.doShowChannel(this.activeChannel, true); } } + return TPromise.as(null); } private onDidPanelClose(panel: IPanel): void { if (this._outputPanel && panel.getId() === OUTPUT_PANEL_ID) { + CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(false); this._outputPanel.clearInput(); } } @@ -571,19 +574,23 @@ export class OutputService extends Disposable implements IOutputService, ITextMo try { return this.instantiationService.createInstance(OutputChannelBackedByFile, { id, label: channelData ? channelData.label : '' }, this.outputDir, uri); } catch (e) { + // Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883) this.logService.error(e); - this.telemetryService.publicLog('output.used.bufferedChannel'); return this.instantiationService.createInstance(BufferredOutputChannel, { id, label: channelData ? channelData.label : '' }); } } - private doShowChannel(channel: IOutputChannel, preserveFocus: boolean): void { + private doShowChannel(channel: IOutputChannel, preserveFocus: boolean): TPromise { if (this._outputPanel) { - this._outputPanel.setInput(this.createInput(channel), EditorOptions.create({ preserveFocus: preserveFocus })); - if (!preserveFocus) { - this._outputPanel.focus(); - } + CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(channel instanceof FileOutputChannel); + return this._outputPanel.setInput(this.createInput(channel), EditorOptions.create({ preserveFocus: preserveFocus })) + .then(() => { + if (!preserveFocus) { + this._outputPanel.focus(); + } + }); } + return TPromise.as(null); } private isChannelShown(channel: IOutputChannel): boolean { @@ -639,8 +646,7 @@ export class LogContentProvider { return channel; } } - -// Remove this channel when there are no issues using Output channel backed by file +// Remove this channel when https://github.com/Microsoft/vscode/issues/47883 is fixed class BufferredOutputChannel extends Disposable implements OutputChannel { readonly id: string; @@ -651,7 +657,7 @@ class BufferredOutputChannel extends Disposable implements OutputChannel { protected _onDidAppendedContent: Emitter = new Emitter(); readonly onDidAppendedContent: Event = this._onDidAppendedContent.event; - private _onDispose: Emitter = new Emitter(); + private readonly _onDispose: Emitter = new Emitter(); readonly onDispose: Event = this._onDispose.event; private modelUpdater: RunOnceScheduler; @@ -779,4 +785,4 @@ class BufferedContent { return { value, id }; } } -} +} \ No newline at end of file diff --git a/src/vs/workbench/parts/output/test/outputLinkProvider.test.ts b/src/vs/workbench/parts/output/test/outputLinkProvider.test.ts index 8be51e10ec..cf0c248b66 100644 --- a/src/vs/workbench/parts/output/test/outputLinkProvider.test.ts +++ b/src/vs/workbench/parts/output/test/outputLinkProvider.test.ts @@ -115,7 +115,7 @@ suite('Workbench - OutputWorker', () => { line = toOSPath(' at C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\Game.ts] in'); result = OutputLinkComputer.detectLinks(line, 1, patternsSlash, contextService); assert.equal(result.length, 1); - assert.equal(result[0].url, contextService.toResource('/Game.ts').toString()); + assert.equal(result[0].url, contextService.toResource('/Game.ts]').toString()); // Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\express\server.js on line 8 line = toOSPath('C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\Game.ts on line 8'); @@ -385,6 +385,20 @@ suite('Workbench - OutputWorker', () => { assert.equal(result[0].range.startColumn, 1); assert.equal(result[0].range.endColumn, 106); + // Example: C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\lib\\something\\Features Special.ts (45,18): error. + line = toOSPath('C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\lib\\something\\Features Special.ts (45,18): error'); + result = OutputLinkComputer.detectLinks(line, 1, patternsSlash, contextService); + assert.equal(result.length, 1); + assert.equal(result[0].url, contextService.toResource('/lib/something/Features Special.ts').toString() + '#45,18'); + assert.equal(result[0].range.startColumn, 1); + assert.equal(result[0].range.endColumn, 114); + + result = OutputLinkComputer.detectLinks(line, 1, patternsBackSlash, contextService); + assert.equal(result.length, 1); + assert.equal(result[0].url, contextService.toResource('/lib/something/Features Special.ts').toString() + '#45,18'); + assert.equal(result[0].range.startColumn, 1); + assert.equal(result[0].range.endColumn, 114); + // Example: at C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\Game.ts. line = toOSPath(' at C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\Game.ts. in'); result = OutputLinkComputer.detectLinks(line, 1, patternsSlash, contextService); @@ -415,8 +429,8 @@ suite('Workbench - OutputWorker', () => { line = toOSPath(' at \'C:\\Users\\someone\\AppData\\Local\\Temp\\_monacodata_9888\\workspaces\\mankala\\Game.ts\' in'); result = OutputLinkComputer.detectLinks(line, 1, patternsSlash, contextService); assert.equal(result.length, 1); - assert.equal(result[0].url, contextService.toResource('/Game.ts').toString()); + assert.equal(result[0].url, contextService.toResource('/Game.ts\'').toString()); assert.equal(result[0].range.startColumn, 6); - assert.equal(result[0].range.endColumn, 85); + assert.equal(result[0].range.endColumn, 86); }); }); \ No newline at end of file diff --git a/src/vs/workbench/parts/performance/electron-browser/startupProfiler.ts b/src/vs/workbench/parts/performance/electron-browser/startupProfiler.ts index 43c7f3bada..c28a41f86b 100644 --- a/src/vs/workbench/parts/performance/electron-browser/startupProfiler.ts +++ b/src/vs/workbench/parts/performance/electron-browser/startupProfiler.ts @@ -18,13 +18,13 @@ import { join, dirname } from 'path'; import { localize } from 'vs/nls'; import { readdir, del, readFile } from 'vs/base/node/pfs'; import { basename } from 'vs/base/common/paths'; -import { IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; class StartupProfiler implements IWorkbenchContribution { constructor( @IWindowsService private readonly _windowsService: IWindowsService, - @IConfirmationService private readonly _confirmationService: IConfirmationService, + @IDialogService private readonly _dialogService: IDialogService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @ILifecycleService lifecycleService: ILifecycleService, @@ -59,21 +59,21 @@ class StartupProfiler implements IWorkbenchContribution { }).then(files => { const profileFiles = files.reduce((prev, cur) => `${prev}${join(dir, cur)}\n`, '\n'); - return this._confirmationService.confirm({ + return this._dialogService.confirm({ type: 'info', message: localize('prof.message', "Successfully created profiles."), detail: localize('prof.detail', "Please create an issue and manually attach the following files:\n{0}", profileFiles), primaryButton: localize('prof.restartAndFileIssue', "Create Issue and Restart"), secondaryButton: localize('prof.restart', "Restart") - }).then(primaryButton => { - if (primaryButton) { + }).then(res => { + if (res.confirmed) { const action = this._instantiationService.createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL); TPromise.join([ this._windowsService.showItemInFolder(join(dir, files[0])), action.run(`:warning: Make sure to **attach** these files from your *home*-directory: :warning:\n${files.map(file => `-\`${file}\``).join('\n')}`) ]).then(() => { // keep window stable until restart is selected - return this._confirmationService.confirm({ + return this._dialogService.confirm({ type: 'info', message: localize('prof.thanks', "Thanks for helping us."), detail: localize('prof.detail.restart', "A final restart is required to continue to use '{0}'. Again, thank you for your contribution.", this._environmentService.appNameLong), diff --git a/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts b/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts index 874bf72454..97e931cd70 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import { OS } from 'vs/base/common/platform'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { Widget } from 'vs/base/browser/ui/widget'; import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes'; @@ -17,7 +17,6 @@ import { InputBox, IInputOptions } from 'vs/base/browser/ui/inputbox/inputBox'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { Dimension } from 'vs/base/browser/builder'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from 'vs/editor/browser/editorBrowser'; @@ -189,7 +188,7 @@ export class DefineKeybindingWidget extends Widget { }); } - layout(layout: Dimension): void { + layout(layout: dom.Dimension): void { let top = Math.round((layout.height - DefineKeybindingWidget.HEIGHT) / 2); this._domNode.setTop(top); @@ -206,7 +205,11 @@ export class DefineKeybindingWidget extends Widget { dom.append(this._domNode.domNode, dom.$('.message', null, nls.localize('defineKeybinding.initial', "Press desired key combination and then press ENTER."))); this._register(attachStylerCallback(this.themeService, { editorWidgetBackground, widgetShadow }, colors => { - this._domNode.domNode.style.backgroundColor = colors.editorWidgetBackground; + if (colors.editorWidgetBackground) { + this._domNode.domNode.style.backgroundColor = colors.editorWidgetBackground.toString(); + } else { + this._domNode.domNode.style.backgroundColor = null; + } if (colors.widgetShadow) { this._domNode.domNode.style.boxShadow = `0 2px 8px ${colors.widgetShadow}`; @@ -286,7 +289,7 @@ export class DefineKeybindingOverlayWidget extends Disposable implements IOverla public start(): TPromise { this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth); const layoutInfo = this._editor.getLayoutInfo(); - this._widget.layout(new Dimension(layoutInfo.width, layoutInfo.height)); + this._widget.layout(new dom.Dimension(layoutInfo.width, layoutInfo.height)); return this._widget.define(); } } diff --git a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts index bf507dd183..cc970ae5b3 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts @@ -11,23 +11,23 @@ import * as DOM from 'vs/base/browser/dom'; import { OS } from 'vs/base/common/platform'; import { dispose } from 'vs/base/common/lifecycle'; import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox'; -import { Builder, Dimension } from 'vs/base/browser/builder'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { IAction } from 'vs/base/common/actions'; import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { EditorOptions } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { KeybindingsEditorModel, IKeybindingItemEntry, IListEntry, KEYBINDING_ENTRY_TEMPLATE_ID, KEYBINDING_HEADER_TEMPLATE_ID } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; +import { KeybindingsEditorModel, IKeybindingItemEntry, IListEntry, KEYBINDING_ENTRY_TEMPLATE_ID, KEYBINDING_HEADER_TEMPLATE_ID } from 'vs/workbench/services/preferences/common/keybindingsEditorModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService, IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; import { SearchWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { DefineKeybindingWidget } from 'vs/workbench/parts/preferences/browser/keybindingWidgets'; import { - IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_COPY, - KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR + IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_COPY, + KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, + KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS } from 'vs/workbench/parts/preferences/common/preferences'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; @@ -42,36 +42,11 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +import { KeybindingsEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; let $ = DOM.$; -export class KeybindingsEditorInput extends EditorInput { - - public static readonly ID: string = 'workbench.input.keybindings'; - public readonly keybindingsModel: KeybindingsEditorModel; - - constructor( @IInstantiationService instantiationService: IInstantiationService) { - super(); - this.keybindingsModel = instantiationService.createInstance(KeybindingsEditorModel, OS); - } - - getTypeId(): string { - return KeybindingsEditorInput.ID; - } - - getName(): string { - return localize('keybindingsInputName', "Keyboard Shortcuts"); - } - - resolve(refresh?: boolean): TPromise { - return TPromise.as(this.keybindingsModel); - } - - matches(otherInput: any): boolean { - return otherInput instanceof KeybindingsEditorInput; - } -} - export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor { public static readonly ID: string = 'workbench.editor.keybindings'; @@ -89,7 +64,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor private listEntries: IListEntry[]; private keybindingsList: List; - private dimension: Dimension; + private dimension: DOM.Dimension; private delayedFiltering: Delayer; private latestEmptyFilters: string[] = []; private delayedFilterLogging: Delayer; @@ -121,16 +96,14 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor this.delayedFilterLogging = new Delayer(1000); } - createEditor(parent: Builder): void { - const parentElement = parent.getHTMLElement(); - - const keybindingsEditorElement = DOM.append(parentElement, $('div', { class: 'keybindings-editor' })); + createEditor(parent: HTMLElement): void { + const keybindingsEditorElement = DOM.append(parent, $('div', { class: 'keybindings-editor' })); this.createOverlayContainer(keybindingsEditorElement); this.createHeader(keybindingsEditorElement); this.createBody(keybindingsEditorElement); - const focusTracker = this._register(DOM.trackFocus(parentElement)); + const focusTracker = this._register(DOM.trackFocus(parent)); this._register(focusTracker.onDidFocus(() => this.keybindingsEditorContextKey.set(true))); this._register(focusTracker.onDidBlur(() => this.keybindingsEditorContextKey.reset())); } @@ -151,7 +124,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor this.keybindingFocusContextKey.reset(); } - layout(dimension: Dimension): void { + layout(dimension: DOM.Dimension): void { this.dimension = dimension; this.searchWidget.layout(dimension); @@ -176,6 +149,29 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor return focusedElement && focusedElement.templateId === KEYBINDING_ENTRY_TEMPLATE_ID ? focusedElement : null; } + getSecondaryActions(): IAction[] { + return [ + { + label: localize('showDefaultKeybindings', "Show Default Keybindings"), + enabled: true, + id: KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, + run: (): TPromise => { + this.searchWidget.setValue('@source:default'); + return TPromise.as(null); + } + }, + { + label: localize('showUserKeybindings', "Show User Keybindings"), + enabled: true, + id: KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, + run: (): TPromise => { + this.searchWidget.setValue('@source:user'); + return TPromise.as(null); + } + } + ]; + } + defineKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise { this.selectEntry(keybindingEntry); this.showOverlayContainer(); @@ -210,10 +206,10 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor this.reportKeybindingAction(KEYBINDINGS_EDITOR_COMMAND_REMOVE, keybindingEntry.keybindingItem.command, keybindingEntry.keybindingItem.keybinding); return this.keybindingEditingService.removeKeybinding(keybindingEntry.keybindingItem.keybindingItem) .then(() => this.focus(), - error => { - this.onKeybindingEditingError(error); - this.selectEntry(keybindingEntry); - }); + error => { + this.onKeybindingEditingError(error); + this.selectEntry(keybindingEntry); + }); } return TPromise.as(null); } @@ -228,10 +224,10 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor } this.selectEntry(keybindingEntry); }, - error => { - this.onKeybindingEditingError(error); - this.selectEntry(keybindingEntry); - }); + error => { + this.onKeybindingEditingError(error); + this.selectEntry(keybindingEntry); + }); } copyKeybinding(keybinding: IKeybindingItemEntry): TPromise { diff --git a/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts index 62fff2b391..93733d4eea 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts @@ -364,7 +364,7 @@ class DefineKeybindingCommand extends EditorCommand { id: DefineKeybindingCommand.ID, precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.languageId.isEqualTo('jsonc')), kbOpts: { - kbExpr: EditorContextKeys.textFocus, + kbExpr: EditorContextKeys.editorTextFocus, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K) } }); diff --git a/src/vs/workbench/parts/preferences/browser/media/preferences.css b/src/vs/workbench/parts/preferences/browser/media/preferences.css index 9dd4b67d77..9d1b9ba2de 100644 --- a/src/vs/workbench/parts/preferences/browser/media/preferences.css +++ b/src/vs/workbench/parts/preferences/browser/media/preferences.css @@ -48,10 +48,14 @@ text-overflow: ellipsis; } -.settings-tabs-widget > .monaco-action-bar .action-item .action-label:not([aria-haspopup]) { +.settings-tabs-widget > .monaco-action-bar .action-item .action-label { display: block; } +.settings-tabs-widget > .monaco-action-bar .action-item .action-label.folder-settings { + display: flex; +} + .settings-tabs-widget > .monaco-action-bar .actions-container { justify-content: flex-start; } @@ -213,7 +217,6 @@ width: 100%; cursor: pointer; font-weight: bold; - -webkit-user-select: none; user-select: none; display: flex; } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts index 8732c9ed81..29542be58e 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts @@ -11,7 +11,7 @@ import { Action } from 'vs/base/common/actions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; @@ -34,6 +34,24 @@ export class OpenRawDefaultSettingsAction extends Action { } } +export class OpenSettingsAction extends Action { + + public static readonly ID = 'workbench.action.openSettings'; + public static readonly LABEL = nls.localize('openSettings', "Open Settings"); + + constructor( + id: string, + label: string, + @IPreferencesService private preferencesService: IPreferencesService + ) { + super(id, label); + } + + public run(event?: any): TPromise { + return this.preferencesService.openSettings(); + } +} + export class OpenGlobalSettingsAction extends Action { public static readonly ID = 'workbench.action.openGlobalSettings'; diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 0c267f149a..711929f0d2 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -11,24 +11,25 @@ import { onUnexpectedError, isPromiseCanceledError, getErrorMessage } from 'vs/b import * as DOM from 'vs/base/browser/dom'; import { Delayer, ThrottledDelayer } from 'vs/base/common/async'; import * as arrays from 'vs/base/common/arrays'; -import { Dimension, Builder } from 'vs/base/browser/builder'; import { ArrayNavigator } from 'vs/base/common/iterator'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; -import { SideBySideEditorInput, EditorOptions, EditorInput, PREFERENCES_EDITOR_ID } from 'vs/workbench/common/editor'; +import { EditorOptions, EditorInput } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; -import { IEditorControl, Position, Verbosity } from 'vs/platform/editor/common/editor'; -import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; +import { IEditorControl, Position } from 'vs/platform/editor/common/editor'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { - IPreferencesService, ISettingsGroup, ISetting, IFilterResult, IPreferencesSearchService, - CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, ISearchProvider, ISearchResult, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING + IPreferencesSearchService, + CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, ISearchProvider, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; -import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; +import { + IPreferencesService, ISettingsGroup, ISetting, IFilterResult, ISettingsEditorModel, ISearchResult +} from 'vs/workbench/services/preferences/common/preferences'; +import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { SearchWidget, SettingsTargetsWidget, SettingsTarget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { ContextKeyExpr, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -38,7 +39,6 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { VSash } from 'vs/base/browser/ui/sash/sash'; import { Widget } from 'vs/base/browser/ui/widget'; import { IPreferencesRenderer, DefaultSettingsRenderer, UserSettingsRenderer, WorkspaceSettingsRenderer, FolderSettingsRenderer } from 'vs/workbench/parts/preferences/browser/preferencesRenderers'; @@ -53,55 +53,15 @@ import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRe import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { MessageController } from 'vs/editor/contrib/message/messageController'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { IHashService } from 'vs/workbench/services/hash/common/hashService'; -import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IStringDictionary } from 'vs/base/common/collections'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { ILogService } from 'vs/platform/log/common/log'; - -export class PreferencesEditorInput extends SideBySideEditorInput { - public static readonly ID: string = 'workbench.editorinputs.preferencesEditorInput'; - - getTypeId(): string { - return PreferencesEditorInput.ID; - } - - public supportsSplitEditor(): boolean { - return true; - } - - public getTitle(verbosity: Verbosity): string { - return this.master.getTitle(verbosity); - } -} - -export class DefaultPreferencesEditorInput extends ResourceEditorInput { - public static readonly ID = 'workbench.editorinputs.defaultpreferences'; - constructor(defaultSettingsResource: URI, - @ITextModelService textModelResolverService: ITextModelService, - @IHashService hashService: IHashService - ) { - super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService, hashService); - } - - getTypeId(): string { - return DefaultPreferencesEditorInput.ID; - } - - matches(other: any): boolean { - if (other instanceof DefaultPreferencesEditorInput) { - return true; - } - if (!super.matches(other)) { - return false; - } - return true; - } -} +import { PreferencesEditorInput, DefaultPreferencesEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; +import { PREFERENCES_EDITOR_ID } from 'vs/workbench/parts/files/common/files'; export class PreferencesEditor extends BaseEditor { @@ -138,11 +98,10 @@ export class PreferencesEditor extends BaseEditor { this.remoteSearchThrottle = new ThrottledDelayer(200); } - public createEditor(parent: Builder): void { - const parentElement = parent.getHTMLElement(); - DOM.addClass(parentElement, 'preferences-editor'); + public createEditor(parent: HTMLElement): void { + DOM.addClass(parent, 'preferences-editor'); - this.headerContainer = DOM.append(parentElement, DOM.$('.preferences-header')); + this.headerContainer = DOM.append(parent, DOM.$('.preferences-header')); this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, this.headerContainer, { ariaLabel: nls.localize('SearchSettingsWidget.AriaLabel', "Search settings"), @@ -154,7 +113,7 @@ export class PreferencesEditor extends BaseEditor { this._register(this.searchWidget.onFocus(() => this.lastFocusedWidget = this.searchWidget)); this.lastFocusedWidget = this.searchWidget; - const editorsContainer = DOM.append(parentElement, DOM.$('.preferences-editors-container')); + const editorsContainer = DOM.append(parent, DOM.$('.preferences-editors-container')); this.sideBySidePreferencesWidget = this._register(this.instantiationService.createInstance(SideBySidePreferencesWidget, editorsContainer)); this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget)); this._register(this.sideBySidePreferencesWidget.onDidSettingsTargetChange(target => this.switchSettings(target))); @@ -192,11 +151,11 @@ export class PreferencesEditor extends BaseEditor { return super.setInput(newInput, options).then(() => this.updateInput(oldInput, newInput, options)); } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { DOM.toggleClass(this.headerContainer, 'vertical-layout', dimension.width < 700); this.searchWidget.layout(dimension); const headerHeight = DOM.getTotalHeight(this.headerContainer); - this.sideBySidePreferencesWidget.layout(new Dimension(dimension.width, dimension.height - headerHeight)); + this.sideBySidePreferencesWidget.layout(new DOM.Dimension(dimension.width, dimension.height - headerHeight)); } public getControl(): IEditorControl { @@ -230,6 +189,10 @@ export class PreferencesEditor extends BaseEditor { super.clearInput(); } + public supportsCenteredLayout(): boolean { + return false; + } + protected setEditorVisible(visible: boolean, position: Position): void { this.sideBySidePreferencesWidget.setEditorVisible(visible, position); super.setEditorVisible(visible, position); @@ -347,10 +310,12 @@ export class PreferencesEditor extends BaseEditor { /* __GDPR__ "defaultSettings.filter" : { - "filter": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "durations" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "counts" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "requestCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "filter": { "classification": "CustomerContent", "purpose": "FeatureInsight" }, + "durations.nlpresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "counts.nlpresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "durations.filterresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "counts.filterresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "requestCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('defaultSettings.filter', data); @@ -396,8 +361,8 @@ class PreferencesRenderersController extends Disposable { private _lastQuery: string; private _lastFilterResult: IFilterResult; - private _onDidFilterResultsCountChange: Emitter = this._register(new Emitter()); - public onDidFilterResultsCountChange: Event = this._onDidFilterResultsCountChange.event; + private readonly _onDidFilterResultsCountChange: Emitter = this._register(new Emitter()); + public readonly onDidFilterResultsCountChange: Event = this._onDidFilterResultsCountChange.event; constructor( @IPreferencesSearchService private preferencesSearchService: IPreferencesSearchService, @@ -717,10 +682,10 @@ class PreferencesRenderersController extends Disposable { "defaultSettingsActions.copySetting" : { "userConfigurationKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "query" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "displayIdx" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "editableSide" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "displayIdx" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "editableSide" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('defaultSettingsActions.copySetting', data); @@ -770,7 +735,7 @@ class PreferencesRenderersController extends Disposable { class SideBySidePreferencesWidget extends Widget { - private dimension: Dimension; + private dimension: DOM.Dimension; private defaultPreferencesHeader: HTMLElement; private defaultPreferencesEditor: DefaultPreferencesEditor; @@ -780,10 +745,10 @@ class SideBySidePreferencesWidget extends Widget { private settingsTargetsWidget: SettingsTargetsWidget; - private _onFocus: Emitter = new Emitter(); + private readonly _onFocus: Emitter = new Emitter(); readonly onFocus: Event = this._onFocus.event; - private _onDidSettingsTargetChange: Emitter = new Emitter(); + private readonly _onDidSettingsTargetChange: Emitter = new Emitter(); readonly onDidSettingsTargetChange: Event = this._onDidSettingsTargetChange.event; private lastFocusedEditor: BaseEditor; @@ -815,7 +780,7 @@ class SideBySidePreferencesWidget extends Widget { this.defaultPreferencesHeader.textContent = nls.localize('defaultSettings', "Default Settings"); this.defaultPreferencesEditor = this._register(this.instantiationService.createInstance(DefaultPreferencesEditor)); - this.defaultPreferencesEditor.create(new Builder(this.defaultPreferencesEditorContainer)); + this.defaultPreferencesEditor.create(this.defaultPreferencesEditorContainer); this.defaultPreferencesEditor.setVisible(true); (this.defaultPreferencesEditor.getControl()).onDidFocusEditor(() => this.lastFocusedEditor = this.defaultPreferencesEditor); @@ -848,16 +813,28 @@ class SideBySidePreferencesWidget extends Widget { return TPromise.join([this.updateInput(this.defaultPreferencesEditor, defaultPreferencesEditorInput, DefaultSettingsEditorContribution.ID, editablePreferencesEditorInput.getResource(), options), this.updateInput(this.editablePreferencesEditor, editablePreferencesEditorInput, SettingsEditorContribution.ID, defaultPreferencesEditorInput.getResource(), options)]) .then(([defaultPreferencesRenderer, editablePreferencesRenderer]) => { - this.defaultPreferencesHeader.textContent = defaultPreferencesRenderer && (defaultPreferencesRenderer.preferencesModel).configurationScope === ConfigurationScope.RESOURCE ? nls.localize('defaultFolderSettings', "Default Folder Settings") : nls.localize('defaultSettings', "Default Settings"); + this.defaultPreferencesHeader.textContent = defaultPreferencesRenderer && this.getDefaultPreferencesHeaderText((defaultPreferencesRenderer.preferencesModel).target); return { defaultPreferencesRenderer, editablePreferencesRenderer }; }); } + private getDefaultPreferencesHeaderText(target: ConfigurationTarget): string { + switch (target) { + case ConfigurationTarget.USER: + return nls.localize('defaultUserSettings', "Default User Settings"); + case ConfigurationTarget.WORKSPACE: + return nls.localize('defaultWorkspaceSettings', "Default Workspace Settings"); + case ConfigurationTarget.WORKSPACE_FOLDER: + return nls.localize('defaultFolderSettings', "Default Folder Settings"); + } + return ''; + } + public setResultCount(settingsTarget: SettingsTarget, count: number): void { this.settingsTargetsWidget.setResultCount(settingsTarget, count); } - public layout(dimension: Dimension): void { + public layout(dimension: DOM.Dimension): void { this.dimension = dimension; this.sash.setDimenesion(this.dimension); } @@ -900,7 +877,7 @@ class SideBySidePreferencesWidget extends Widget { const descriptor = Registry.as(EditorExtensions.Editors).getEditor(editorInput); const editor = descriptor.instantiate(this.instantiationService); this.editablePreferencesEditor = editor; - this.editablePreferencesEditor.create(new Builder(this.editablePreferencesEditorContainer)); + this.editablePreferencesEditor.create(this.editablePreferencesEditorContainer); this.editablePreferencesEditor.setVisible(true); (this.editablePreferencesEditor.getControl()).onDidFocusEditor(() => this.lastFocusedEditor = this.editablePreferencesEditor); this.lastFocusedEditor = this.editablePreferencesEditor; @@ -933,8 +910,8 @@ class SideBySidePreferencesWidget extends Widget { this.editablePreferencesEditorContainer.style.height = `${this.dimension.height}px`; this.editablePreferencesEditorContainer.style.left = `${splitPoint}px`; - this.defaultPreferencesEditor.layout(new Dimension(detailsEditorWidth, this.dimension.height - 34 /* height of header container */)); - this.editablePreferencesEditor.layout(new Dimension(masterEditorWidth, this.dimension.height - 34 /* height of header container */)); + this.defaultPreferencesEditor.layout(new DOM.Dimension(detailsEditorWidth, this.dimension.height - 34 /* height of header container */)); + this.editablePreferencesEditor.layout(new DOM.Dimension(masterEditorWidth, this.dimension.height - 34 /* height of header container */)); } private getSettingsTarget(resource: URI): SettingsTarget { @@ -988,8 +965,8 @@ export class DefaultPreferencesEditor extends BaseTextEditor { super(DefaultPreferencesEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorGroupService); } - public createEditorControl(parent: Builder, configuration: IEditorOptions): editorCommon.IEditor { - const editor = this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration); + public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): editorCommon.IEditor { + const editor = this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent, configuration); // Inform user about editor being readonly if user starts type this.toUnbind.push(editor.onDidType(() => this.showReadonlyHint(editor))); @@ -1040,10 +1017,14 @@ export class DefaultPreferencesEditor extends BaseTextEditor { super.clearInput(); } - public layout(dimension: Dimension) { + public layout(dimension: DOM.Dimension) { this.getControl().layout(dimension); } + public supportsCenteredLayout(): boolean { + return false; + } + protected getAriaLabel(): string { return nls.localize('preferencesAriaLabel', "Default preferences. Readonly text editor."); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 6756c01af1..c101bf16de 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -12,24 +12,22 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Position } from 'vs/editor/common/core/position'; import { IAction } from 'vs/base/common/actions'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { Range, IRange } from 'vs/editor/common/core/range'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IWorkbenchSettingsConfiguration, IExtensionSetting, IScoredResults } from 'vs/workbench/parts/preferences/common/preferences'; -import { SettingsEditorModel, DefaultSettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; +import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IExtensionSetting, IScoredResults } from 'vs/workbench/services/preferences/common/preferences'; +import { SettingsEditorModel, DefaultSettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { SettingsGroupTitleWidget, EditPreferenceWidget, SettingsHeaderWidget, DefaultSettingsHeaderWidget, FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; -import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers'; import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { MarkdownString } from 'vs/base/common/htmlContent'; import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModel, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/model'; @@ -40,8 +38,9 @@ import { IssueType, ISettingsSearchIssueReporterData, ISettingSearchResult } fro import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService } from 'vs/platform/notification/common/notification'; import { ContextSubMenu } from 'vs/base/browser/contextmenu'; +import { IWorkbenchSettingsConfiguration } from 'vs/workbench/parts/preferences/common/preferences'; export interface IPreferencesRenderer extends IDisposable { readonly preferencesModel: IPreferencesEditorModel; @@ -69,13 +68,13 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend private modelChangeDelayer: Delayer = new Delayer(200); private associatedPreferencesModel: IPreferencesEditorModel; - private _onFocusPreference: Emitter = new Emitter(); + private readonly _onFocusPreference: Emitter = new Emitter(); public readonly onFocusPreference: Event = this._onFocusPreference.event; - private _onClearFocusPreference: Emitter = new Emitter(); + private readonly _onClearFocusPreference: Emitter = new Emitter(); public readonly onClearFocusPreference: Event = this._onClearFocusPreference.event; - private _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); + private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); public readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event; private filterResult: IFilterResult; @@ -188,7 +187,6 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer { - private unsupportedSettingsRenderer: UnsupportedSettingsRenderer; private workspaceConfigurationRenderer: WorkspaceConfigurationRenderer; constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, @@ -198,7 +196,6 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I @IInstantiationService instantiationService: IInstantiationService ) { super(editor, preferencesModel, preferencesService, configurationService, instantiationService); - this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel)); this.workspaceConfigurationRenderer = this._register(instantiationService.createInstance(WorkspaceConfigurationRenderer, editor, preferencesModel)); } @@ -213,15 +210,12 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I public render(): void { super.render(); - this.unsupportedSettingsRenderer.render(); this.workspaceConfigurationRenderer.render(this.getAssociatedPreferencesModel()); } } export class FolderSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer { - private unsupportedSettingsRenderer: UnsupportedSettingsRenderer; - constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, @IPreferencesService preferencesService: IPreferencesService, @ITelemetryService telemetryService: ITelemetryService, @@ -229,17 +223,12 @@ export class FolderSettingsRenderer extends UserSettingsRenderer implements IPre @IInstantiationService instantiationService: IInstantiationService ) { super(editor, preferencesModel, preferencesService, configurationService, instantiationService); - this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel)); } protected createHeader(): void { this._register(new SettingsHeaderWidget(this.editor, '')).setMessage(nls.localize('emptyFolderSettingsHeader', "Place your folder settings here to overwrite those from the Workspace Settings.")); } - public render(): void { - super.render(); - this.unsupportedSettingsRenderer.render(); - } } export class DefaultSettingsRenderer extends Disposable implements IPreferencesRenderer { @@ -257,13 +246,13 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR private extensionCodelensRenderer: ExtensionCodelensRenderer; private filterResult: IFilterResult; - private _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); + private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); public readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event; - private _onFocusPreference: Emitter = new Emitter(); + private readonly _onFocusPreference: Emitter = new Emitter(); public readonly onFocusPreference: Event = this._onFocusPreference.event; - private _onClearFocusPreference: Emitter = new Emitter(); + private readonly _onClearFocusPreference: Emitter = new Emitter(); public readonly onClearFocusPreference: Event = this._onClearFocusPreference.event; constructor(protected editor: ICodeEditor, public readonly preferencesModel: DefaultSettingsEditorModel, @@ -273,7 +262,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR ) { super(); this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference)); - this.settingsHeaderRenderer = this._register(instantiationService.createInstance(DefaultSettingsHeaderRenderer, editor, preferencesModel.configurationScope)); + this.settingsHeaderRenderer = this._register(instantiationService.createInstance(DefaultSettingsHeaderRenderer, editor)); this.settingsGroupTitleRenderer = this._register(instantiationService.createInstance(SettingsGroupTitleRenderer, editor)); this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor)); this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, this.settingHighlighter)); @@ -465,9 +454,9 @@ export class BracesHidingRenderer extends Disposable implements HiddenAreasProvi class DefaultSettingsHeaderRenderer extends Disposable { private settingsHeaderWidget: DefaultSettingsHeaderWidget; - public onClick: Event; + public readonly onClick: Event; - constructor(editor: ICodeEditor, scope: ConfigurationScope) { + constructor(editor: ICodeEditor) { super(); this.settingsHeaderWidget = this._register(new DefaultSettingsHeaderWidget(editor, '')); this.onClick = this.settingsHeaderWidget.onClick; @@ -481,7 +470,7 @@ class DefaultSettingsHeaderRenderer extends Disposable { export class SettingsGroupTitleRenderer extends Disposable implements HiddenAreasProvider { - private _onHiddenAreasChanged: Emitter = new Emitter(); + private readonly _onHiddenAreasChanged: Emitter = new Emitter(); get onHiddenAreasChanged(): Event { return this._onHiddenAreasChanged.event; } private settingsGroups: ISettingsGroup[]; @@ -732,10 +721,10 @@ export class FeedbackWidgetRenderer extends Disposable { "userComment" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "expectedResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "buildNumber" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "buildNumber" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "alts" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "autoIngest" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "autoIngest" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ return this.telemetryService.publicLog('settingsSearchResultFeedback', { @@ -879,29 +868,27 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr public render(result: IFilterResult, allSettingsGroups: ISettingsGroup[]): void { const model = this.editor.getModel(); this.hiddenAreas = []; - this.editor.changeDecorations(changeAccessor => { - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []); - }); if (result) { this.hiddenAreas = this.computeHiddenRanges(result.filteredGroups, result.allGroups, model); - this.editor.changeDecorations(changeAccessor => { - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, result.matches.map(match => this.createDecoration(match, model))); - }); + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, result.matches.map(match => this.createDecoration(match, model))); } else { this.hiddenAreas = this.computeHiddenRanges(null, allSettingsGroups, model); + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []); } } private createDecoration(range: IRange, model: ITextModel): IModelDeltaDecoration { return { range, - options: { - stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'findMatch' - } + options: FilteredMatchesRenderer._FIND_MATCH }; } + private static readonly _FIND_MATCH = ModelDecorationOptions.register({ + stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + className: 'findMatch' + }); + private computeHiddenRanges(filteredGroups: ISettingsGroup[], allSettingsGroups: ISettingsGroup[], model: ITextModel): IRange[] { // Hide the contents of hidden groups const notMatchesRanges: IRange[] = []; @@ -920,11 +907,7 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr } public dispose() { - if (this.decorationIds) { - this.decorationIds = this.editor.changeDecorations(changeAccessor => { - return changeAccessor.deltaDecorations(this.decorationIds, []); - }); - } + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []); super.dispose(); } } @@ -940,14 +923,7 @@ export class HighlightMatchesRenderer extends Disposable { public render(matches: IRange[]): void { const model = this.editor.getModel(); - this.editor.changeDecorations(changeAccessor => { - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []) || []; - }); - if (matches.length) { - this.editor.changeDecorations(changeAccessor => { - this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, matches.map(match => this.createDecoration(match, model))) || []; - }); - } + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, matches.map(match => this.createDecoration(match, model))); } private static readonly _FIND_MATCH = ModelDecorationOptions.register({ @@ -963,11 +939,7 @@ export class HighlightMatchesRenderer extends Disposable { } public dispose() { - if (this.decorationIds) { - this.decorationIds = this.editor.changeDecorations(changeAccessor => { - return changeAccessor.deltaDecorations(this.decorationIds, []); - }) || []; - } + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []); super.dispose(); } } @@ -1031,7 +1003,7 @@ class EditSettingRenderer extends Disposable { public associatedPreferencesModel: IPreferencesEditorModel; private toggleEditPreferencesForMouseMoveDelayer: Delayer; - private _onUpdateSetting: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); + private readonly _onUpdateSetting: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); public readonly onUpdateSetting: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdateSetting.event; constructor(private editor: ICodeEditor, private masterSettingsModel: ISettingsEditorModel, @@ -1295,7 +1267,7 @@ class SettingHighlighter extends Disposable { private volatileHighlighter: RangeHighlightDecorations; private highlightedSetting: ISetting; - constructor(private editor: ICodeEditor, private focusEventEmitter: Emitter, private clearFocusEventEmitter: Emitter, + constructor(private editor: ICodeEditor, private readonly focusEventEmitter: Emitter, private readonly clearFocusEventEmitter: Emitter, @IInstantiationService instantiationService: IInstantiationService ) { super(); @@ -1329,104 +1301,6 @@ class SettingHighlighter extends Disposable { } } -class UnsupportedSettingsRenderer extends Disposable { - - private decorationIds: string[] = []; - private renderingDelayer: Delayer = new Delayer(200); - - constructor( - private editor: ICodeEditor, - private settingsEditorModel: SettingsEditorModel, - @IMarkerService private markerService: IMarkerService, - @IEnvironmentService private environmentService: IEnvironmentService - ) { - super(); - this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render()))); - } - - public render(): void { - const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); - const ranges: IRange[] = []; - const markerData: IMarkerData[] = []; - for (const settingsGroup of this.settingsEditorModel.settingsGroups) { - for (const section of settingsGroup.sections) { - for (const setting of section.settings) { - if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE || this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { - // Show warnings for executable settings - if (configurationRegistry[setting.key] && configurationRegistry[setting.key].isExecutable) { - markerData.push({ - severity: Severity.Warning, - startLineNumber: setting.keyRange.startLineNumber, - startColumn: setting.keyRange.startColumn, - endLineNumber: setting.keyRange.endLineNumber, - endColumn: setting.keyRange.endColumn, - message: this.getMarkerMessage(setting.key) - }); - } - } - if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { - // Dim and show information for window settings - if (configurationRegistry[setting.key] && configurationRegistry[setting.key].scope === ConfigurationScope.WINDOW) { - ranges.push({ - startLineNumber: setting.keyRange.startLineNumber, - startColumn: setting.keyRange.startColumn - 1, - endLineNumber: setting.valueRange.endLineNumber, - endColumn: setting.valueRange.endColumn - }); - } - } - } - } - } - if (markerData.length) { - this.markerService.changeOne('preferencesEditor', this.settingsEditorModel.uri, markerData); - } else { - this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]); - } - this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel())))); - } - - private createDecoration(range: IRange, model: ITextModel): IModelDeltaDecoration { - return { - range, - options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedSettingsRenderer._DIM_CONFIGUARATION_ - }; - } - - private getMarkerMessage(settingKey: string): string { - switch (settingKey) { - case 'php.validate.executablePath': - return nls.localize('unsupportedPHPExecutablePathSetting', "This setting must be a User Setting. To configure PHP for the workspace, open a PHP file and click on 'PHP Path' in the status bar."); - default: - return nls.localize('unsupportedWorkspaceSetting', "This setting must be a User Setting."); - } - } - - public dispose(): void { - this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]); - if (this.decorationIds) { - this.decorationIds = this.editor.changeDecorations(changeAccessor => { - return changeAccessor.deltaDecorations(this.decorationIds, []); - }); - } - super.dispose(); - } - - private static readonly _DIM_CONFIGUARATION_ = ModelDecorationOptions.register({ - stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - inlineClassName: 'dim-configuration', - beforeContentClassName: 'unsupportedWorkbenhSettingInfo', - hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSetting', "This setting cannot be applied now. It will be applied when you open this folder directly.")) - }); - - private static readonly _DIM_CONFIGUARATION_DEV_MODE = ModelDecorationOptions.register({ - stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - inlineClassName: 'dim-configuration', - beforeContentClassName: 'unsupportedWorkbenhSettingInfo', - hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSettingDevMode', "This setting cannot be applied now. It will be applied if you define it's scope as 'resource' while registering, or when you open this folder directly.")) - }); -} - class WorkspaceConfigurationRenderer extends Disposable { private decorationIds: string[] = []; @@ -1444,8 +1318,6 @@ class WorkspaceConfigurationRenderer extends Disposable { this.associatedSettingsEditorModel = associatedSettingsEditorModel; // Dim other configurations in workspace configuration file only in the context of Settings Editor if (this.associatedSettingsEditorModel && this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceSettingsEditorModel instanceof WorkspaceConfigurationEditorModel) { - this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, [])); - const ranges: IRange[] = []; for (const settingsGroup of this.workspaceSettingsEditorModel.configurationGroups) { for (const section of settingsGroup.sections) { @@ -1461,7 +1333,7 @@ class WorkspaceConfigurationRenderer extends Disposable { } } } - this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel())))); + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel()))); } } @@ -1478,11 +1350,7 @@ class WorkspaceConfigurationRenderer extends Disposable { } public dispose(): void { - if (this.decorationIds) { - this.decorationIds = this.editor.changeDecorations(changeAccessor => { - return changeAccessor.deltaDecorations(this.decorationIds, []); - }); - } + this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []); super.dispose(); } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 51e9d8e10d..5983f638d3 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -5,19 +5,19 @@ import { localize } from 'vs/nls'; import URI from 'vs/base/common/uri'; -import { Dimension, $ } from 'vs/base/browser/builder'; +import { $ } from 'vs/base/browser/builder'; import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Widget } from 'vs/base/browser/ui/widget'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference, IViewZone, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { InputBox, IInputOptions } from 'vs/base/browser/ui/inputbox/inputBox'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ISettingsGroup } from 'vs/workbench/parts/preferences/common/preferences'; +import { ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IAction, Action } from 'vs/base/common/actions'; @@ -102,7 +102,7 @@ export class SettingsHeaderWidget extends Widget implements IViewZone { export class DefaultSettingsHeaderWidget extends SettingsHeaderWidget { private _onClick = this._register(new Emitter()); - public onClick: Event = this._onClick.event; + public readonly onClick: Event = this._onClick.event; protected create() { super.create(); @@ -130,7 +130,7 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { private title: HTMLElement; private _onToggled = this._register(new Emitter()); - public onToggled: Event = this._onToggled.event; + public readonly onToggled: Event = this._onToggled.event; private previousPosition: Position; @@ -324,7 +324,7 @@ export class FolderSettingsActionItem extends BaseActionItem { this.labelElement = DOM.$('.action-title'); this.detailsElement = DOM.$('.action-details'); this.dropDownElement = DOM.$('.dropdown-icon.octicon.octicon-triangle-down.hide'); - this.anchorElement = DOM.$('a.action-label', { + this.anchorElement = DOM.$('a.action-label.folder-settings', { role: 'button', 'aria-haspopup': 'true', 'tabindex': '0' @@ -461,7 +461,7 @@ export class SettingsTargetsWidget extends Widget { private _settingsTarget: SettingsTarget; - private _onDidTargetChange: Emitter = new Emitter(); + private readonly _onDidTargetChange: Emitter = new Emitter(); public readonly onDidTargetChange: Event = this._onDidTargetChange.event; constructor( @@ -573,10 +573,10 @@ export class SearchWidget extends Widget { private inputBox: InputBox; private controlsDiv: HTMLElement; - private _onDidChange: Emitter = this._register(new Emitter()); + private readonly _onDidChange: Emitter = this._register(new Emitter()); public readonly onDidChange: Event = this._onDidChange.event; - private _onFocus: Emitter = this._register(new Emitter()); + private readonly _onFocus: Emitter = this._register(new Emitter()); public readonly onFocus: Event = this._onFocus.event; constructor(parent: HTMLElement, protected options: SearchOptions, @@ -649,7 +649,7 @@ export class SearchWidget extends Widget { this.countElement.style.color = color ? color.toString() : null; } - public layout(dimension: Dimension) { + public layout(dimension: DOM.Dimension) { if (dimension.width < 400) { if (this.countElement) { DOM.addClass(this.countElement, 'hide'); @@ -705,8 +705,8 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { private _domNode: HTMLElement; - private _onClick: Emitter = this._register(new Emitter()); - public onClick: Event = this._onClick.event; + private readonly _onClick: Emitter = this._register(new Emitter()); + public readonly onClick: Event = this._onClick.event; constructor( private editor: ICodeEditor, @@ -728,8 +728,8 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { public render() { this._domNode = DOM.$('.floating-click-widget'); this._register(attachStylerCallback(this.themeService, { buttonBackground, buttonForeground }, colors => { - this._domNode.style.backgroundColor = colors.buttonBackground; - this._domNode.style.color = colors.buttonForeground; + this._domNode.style.backgroundColor = colors.buttonBackground ? colors.buttonBackground.toString() : null; + this._domNode.style.color = colors.buttonForeground ? colors.buttonForeground.toString() : null; })); DOM.append(this._domNode, DOM.$('')).textContent = this.label; @@ -766,7 +766,7 @@ export class EditPreferenceWidget extends Disposable { private _editPreferenceDecoration: string[]; - private _onClick: Emitter = new Emitter(); + private readonly _onClick: Emitter = new Emitter(); public get onClick(): Event { return this._onClick.event; } constructor(private editor: ICodeEditor diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index 1334544734..1f266ac0a8 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -3,21 +3,13 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localize } from 'vs/nls'; -import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IEditor, Position, IEditorOptions } from 'vs/platform/editor/common/editor'; -import { ITextModel } from 'vs/editor/common/model'; -import { IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; -import { IRange } from 'vs/editor/common/core/range'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { join } from 'vs/base/common/paths'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import Event from 'vs/base/common/event'; -import { IStringDictionary } from 'vs/base/common/collections'; -import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ISettingsEditorModel, ISearchResult } from 'vs/workbench/services/preferences/common/preferences'; +import { IEditor } from 'vs/platform/editor/common/editor'; +import { IKeybindingItemEntry } from 'vs/workbench/services/preferences/common/keybindingsEditorModel'; export interface IWorkbenchSettingsConfiguration { workbench: { @@ -33,164 +25,6 @@ export interface IWorkbenchSettingsConfiguration { }; } -export interface ISettingsGroup { - id: string; - range: IRange; - title: string; - titleRange: IRange; - sections: ISettingsSection[]; -} - -export interface ISettingsSection { - titleRange?: IRange; - title?: string; - settings: ISetting[]; -} - -export interface ISetting { - range: IRange; - key: string; - keyRange: IRange; - value: any; - valueRange: IRange; - description: string[]; - descriptionRanges: IRange[]; - overrides?: ISetting[]; - overrideOf?: ISetting; -} - -export interface IExtensionSetting extends ISetting { - extensionName: string; - extensionPublisher: string; -} - -export interface ISearchResult { - filterMatches: ISettingMatch[]; - metadata?: IFilterMetadata; -} - -export interface ISearchResultGroup { - id: string; - label: string; - result: ISearchResult; - order: number; -} - -export interface IFilterResult { - query?: string; - filteredGroups: ISettingsGroup[]; - allGroups: ISettingsGroup[]; - matches: IRange[]; - metadata?: IStringDictionary; -} - -export interface ISettingMatch { - setting: ISetting; - matches: IRange[]; - score: number; -} - -export interface IScoredResults { - [key: string]: IRemoteSetting; -} - -export interface IRemoteSetting { - score: number; - key: string; - id: string; - defaultValue: string; - description: string; - packageId: string; - extensionName?: string; - extensionPublisher?: string; -} - -export interface IFilterMetadata { - requestUrl: string; - requestBody: string; - timestamp: number; - duration: number; - scoredResults: IScoredResults; - extensions?: ILocalExtension[]; - - /** The number of requests made, since requests are split by number of filters */ - requestCount?: number; - - /** The name of the server that actually served the request */ - context: string; -} - -export interface IPreferencesEditorModel { - uri: URI; - getPreference(key: string): T; - dispose(): void; -} - -export type IGroupFilter = (group: ISettingsGroup) => boolean; -export type ISettingMatcher = (setting: ISetting, group: ISettingsGroup) => { matches: IRange[], score: number }; - -export interface ISettingsEditorModel extends IPreferencesEditorModel { - readonly onDidChangeGroups: Event; - settingsGroups: ISettingsGroup[]; - filterSettings(filter: string, groupFilter: IGroupFilter, settingMatcher: ISettingMatcher): ISettingMatch[]; - findValueMatches(filter: string, setting: ISetting): IRange[]; - updateResultGroup(id: string, resultGroup: ISearchResultGroup): IFilterResult; -} - -export interface IKeybindingsEditorModel extends IPreferencesEditorModel { -} - -export const IPreferencesService = createDecorator('preferencesService'); - -export interface IPreferencesService { - _serviceBrand: any; - - userSettingsResource: URI; - workspaceSettingsResource: URI; - getFolderSettingsResource(resource: URI): URI; - - resolveModel(uri: URI): TPromise; - createPreferencesEditorModel(uri: URI): TPromise>; - - openRawDefaultSettings(): TPromise; - openGlobalSettings(options?: IEditorOptions, position?: Position): TPromise; - openWorkspaceSettings(options?: IEditorOptions, position?: Position): TPromise; - openFolderSettings(folder: URI, options?: IEditorOptions, position?: Position): TPromise; - switchSettings(target: ConfigurationTarget, resource: URI): TPromise; - openGlobalKeybindingSettings(textual: boolean): TPromise; - - configureSettingsForLanguage(language: string): void; -} - - -export interface IKeybindingsEditor extends IEditor { - - activeKeybindingEntry: IKeybindingItemEntry; - - search(filter: string): void; - clearSearchResults(): void; - focusKeybindings(): void; - defineKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; - removeKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; - resetKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; - copyKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; - copyKeybindingCommand(keybindingEntry: IKeybindingItemEntry): TPromise; - showSimilarKeybindings(keybindingEntry: IKeybindingItemEntry): TPromise; -} - -export function getSettingsTargetName(target: ConfigurationTarget, resource: URI, workspaceContextService: IWorkspaceContextService): string { - switch (target) { - case ConfigurationTarget.USER: - return localize('userSettingsTarget', "User Settings"); - case ConfigurationTarget.WORKSPACE: - return localize('workspaceSettingsTarget', "Workspace Settings"); - case ConfigurationTarget.WORKSPACE_FOLDER: - const folder = workspaceContextService.getWorkspaceFolder(resource); - return folder ? folder.name : ''; - } - return ''; -} - export interface IEndpointDetails { urlBase: string; key?: string; @@ -209,6 +43,21 @@ export interface ISearchProvider { searchModel(preferencesModel: ISettingsEditorModel): TPromise; } +export interface IKeybindingsEditor extends IEditor { + + activeKeybindingEntry: IKeybindingItemEntry; + + search(filter: string): void; + clearSearchResults(): void; + focusKeybindings(): void; + defineKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; + removeKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; + resetKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; + copyKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; + copyKeybindingCommand(keybindingEntry: IKeybindingItemEntry): TPromise; + showSimilarKeybindings(keybindingEntry: IKeybindingItemEntry): TPromise; +} + export const CONTEXT_SETTINGS_EDITOR = new RawContextKey('inSettingsEditor', false); export const CONTEXT_SETTINGS_SEARCH_FOCUS = new RawContextKey('inSettingsSearch', false); export const CONTEXT_KEYBINDINGS_EDITOR = new RawContextKey('inKeybindings', false); @@ -230,6 +79,8 @@ export const KEYBINDINGS_EDITOR_COMMAND_COPY = 'keybindings.editor.copyKeybindin export const KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND = 'keybindings.editor.copyCommandKeybindingEntry'; export const KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR = 'keybindings.editor.showConflicts'; export const KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS = 'keybindings.editor.focusKeybindings'; +export const KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS = 'keybindings.editor.showDefaultKeybindings'; +export const KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS = 'keybindings.editor.showUserKeybindings'; // {{SQL CARBON EDIT}} export const FOLDER_SETTINGS_PATH = join('.sqlops', 'settings.json'); diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index a7ed3ae198..81e6eef8ac 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -9,11 +9,11 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModel } from 'vs/editor/common/model'; -import JSONContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); +import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IPreferencesService, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/services/preferences/common/preferences'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { endsWith } from 'vs/base/common/strings'; diff --git a/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts index 4286d7e061..630175d6d3 100644 --- a/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import 'vs/css!../browser/media/preferences'; import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -14,14 +15,14 @@ import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { DefaultPreferencesEditorInput, PreferencesEditor, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; -import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor'; -import { OpenRawDefaultSettingsAction, OpenGlobalSettingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OpenGlobalKeybindingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions'; +import { PreferencesEditor } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; +import { DefaultPreferencesEditorInput, PreferencesEditorInput, KeybindingsEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; +import { KeybindingsEditor } from 'vs/workbench/parts/preferences/browser/keybindingsEditor'; +import { OpenRawDefaultSettingsAction, OpenSettingsAction, OpenGlobalSettingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OpenGlobalKeybindingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions'; import { - IPreferencesService, IKeybindingsEditor, IPreferencesSearchService, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH, + IKeybindingsEditor, IPreferencesSearchService, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/parts/preferences/common/preferences'; -import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { PreferencesContribution } from 'vs/workbench/parts/preferences/common/preferencesContribution'; @@ -31,8 +32,8 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { PreferencesSearchService } from 'vs/workbench/parts/preferences/electron-browser/preferencesSearch'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; -registerSingleton(IPreferencesService, PreferencesService); registerSingleton(IPreferencesSearchService, PreferencesSearchService); Registry.as(EditorExtensions.Editors).registerEditor( @@ -165,7 +166,8 @@ Registry.as(EditorInputExtensions.EditorInputFactor const category = nls.localize('preferences', "Preferences"); const registry = Registry.as(Extensions.WorkbenchActions); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRawDefaultSettingsAction, OpenRawDefaultSettingsAction.ID, OpenRawDefaultSettingsAction.LABEL), 'Preferences: Open Raw Default Settings', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_COMMA }), 'Preferences: Open User Settings', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(OpenSettingsAction, OpenSettingsAction.ID, OpenSettingsAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_COMMA }), 'Preferences: Open Settings', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL), 'Preferences: Open User Settings', category); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalKeybindingsAction, OpenGlobalKeybindingsAction.ID, OpenGlobalKeybindingsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_S) }), 'Preferences: Open Keyboard Shortcuts', category); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalKeybindingsFileAction, OpenGlobalKeybindingsFileAction.ID, OpenGlobalKeybindingsFileAction.LABEL, { primary: null }), 'Preferences: Open Keyboard Shortcuts File', category); registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLanguageBasedSettingsAction, ConfigureLanguageBasedSettingsAction.ID, ConfigureLanguageBasedSettingsAction.LABEL), 'Preferences: Configure Language Specific Settings...', category); diff --git a/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts index 81e29a600d..29e1fbd977 100644 --- a/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import { ISettingsEditorModel, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService, ISearchResult, ISearchProvider, IGroupFilter, ISettingMatcher, IScoredResults, ISettingMatch, IRemoteSetting, IExtensionSetting } from 'vs/workbench/parts/preferences/common/preferences'; +import { ISettingsEditorModel, ISetting, ISettingsGroup, IFilterMetadata, ISearchResult, IGroupFilter, ISettingMatcher, IScoredResults, ISettingMatch, IRemoteSetting, IExtensionSetting } from 'vs/workbench/services/preferences/common/preferences'; import { IRange } from 'vs/editor/common/core/range'; import { distinct, top } from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; @@ -20,6 +20,7 @@ import { asJson } from 'vs/base/node/request'; import { Disposable } from 'vs/base/common/lifecycle'; import { IExtensionManagementService, LocalExtensionType, ILocalExtension, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ILogService } from 'vs/platform/log/common/log'; +import { IPreferencesSearchService, ISearchProvider, IWorkbenchSettingsConfiguration } from 'vs/workbench/parts/preferences/common/preferences'; export interface IEndpointDetails { urlBase: string; @@ -44,8 +45,8 @@ export class PreferencesSearchService extends Disposable implements IPreferences this._installedExtensions = this.extensionManagementService.getInstalled(LocalExtensionType.User).then(exts => { // Filter to enabled extensions that have settings return exts - .filter(ext => this.extensionEnablementService.isEnabled(ext.identifier)) - .filter(ext => ext.manifest.contributes && ext.manifest.contributes.configuration) + .filter(ext => this.extensionEnablementService.isEnabled(ext)) + .filter(ext => ext.manifest && ext.manifest.contributes && ext.manifest.contributes.configuration) .filter(ext => !!ext.identifier.uuid); }); } diff --git a/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts b/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts index d3a3cfaef0..57b2abfac7 100644 --- a/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/commandsHandler.ts @@ -6,9 +6,9 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import arrays = require('vs/base/common/arrays'); -import types = require('vs/base/common/types'); +import * as nls from 'vs/nls'; +import * as arrays from 'vs/base/common/arrays'; +import * as types from 'vs/base/common/types'; import { language, LANGUAGE_DEFAULT } from 'vs/base/common/platform'; import { Action } from 'vs/base/common/actions'; import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen'; diff --git a/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts index f70df6a16e..d13de7224a 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts @@ -211,7 +211,7 @@ export class GotoLineHandler extends QuickOpenHandler { private rangeHighlightDecorationId: IEditorLineDecoration; private lastKnownEditorViewState: IEditorViewState; - constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService) { + constructor(@IWorkbenchEditorService private editorService: IWorkbenchEditorService) { super(); } diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index 429c40915a..065f582871 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -7,14 +7,14 @@ import 'vs/css!./media/gotoSymbolHandler'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); -import types = require('vs/base/common/types'); -import strings = require('vs/base/common/strings'); +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; +import * as types from 'vs/base/common/types'; +import * as strings from 'vs/base/common/strings'; import { IEntryRunContext, Mode, IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenModel, IHighlight } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenHandler, EditorQuickOpenEntryGroup, QuickOpenAction } from 'vs/workbench/browser/quickopen'; -import filters = require('vs/base/common/filters'); +import * as filters from 'vs/base/common/filters'; import { IEditor, IDiffEditorModel, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; import { IModelDecorationsChangeAccessor, OverviewRulerLane, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/parts/quickopen/browser/helpHandler.ts b/src/vs/workbench/parts/quickopen/browser/helpHandler.ts index 67b5ffc3e2..e8b098164b 100644 --- a/src/vs/workbench/parts/quickopen/browser/helpHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/helpHandler.ts @@ -5,8 +5,8 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import types = require('vs/base/common/types'); +import * as nls from 'vs/nls'; +import * as types from 'vs/base/common/types'; import { Registry } from 'vs/platform/registry/common/platform'; import { Mode, IEntryRunContext, IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenModel, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; @@ -62,14 +62,14 @@ export class HelpHandler extends QuickOpenHandler { public static readonly ID = 'workbench.picker.help'; - constructor( @IQuickOpenService private quickOpenService: IQuickOpenService) { + constructor(@IQuickOpenService private quickOpenService: IQuickOpenService) { super(); } public getResults(searchValue: string): TPromise { searchValue = searchValue.trim(); - const registry = (Registry.as(Extensions.Quickopen)); + const registry = (Registry.as(Extensions.Quickopen)); const handlerDescriptors = registry.getQuickOpenHandlers(); const defaultHandler = registry.getDefaultQuickOpenHandler(); diff --git a/src/vs/workbench/parts/quickopen/browser/media/gotoSymbolHandler.css b/src/vs/workbench/parts/quickopen/browser/media/gotoSymbolHandler.css index ae0dbe9c6f..d90ff68e25 100644 --- a/src/vs/workbench/parts/quickopen/browser/media/gotoSymbolHandler.css +++ b/src/vs/workbench/parts/quickopen/browser/media/gotoSymbolHandler.css @@ -3,152 +3,152 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant { background-image: url('Constant_16x.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constant { background-image: url('Constant_16x_inverse.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member { background-image: url('EnumItem_16x.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum-member { background-image: url('EnumItem_inverse_16x.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct { background-image: url('Structure_16x_vscode.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.struct { background-image: url('Structure_16x_vscode_inverse.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event { background-image: url('Event_16x_vscode.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.event { background-image: url('Event_16x_vscode_inverse.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator { background-image: url('Operator_16x_vscode.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.operator { background-image: url('Operator_16x_vscode_inverse.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter { background-image: url('Template_16x_vscode.svg'); background-repeat: no-repeat; background-position: 0 -2px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter { +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.type-parameter { background-image: url('Template_16x_vscode_inverse.svg'); } -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, -.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, +.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { background-image: url('symbol-sprite.svg'); background-repeat: no-repeat; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -3px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -3px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -3px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string { background-position: -202px -3px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array { background-position: -302px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number { background-position: -322px -4px; } -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, -.vs .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { background-position: -343px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -3px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -3px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -3px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string { background-position: -202px -3px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array { background-position: -302px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number { background-position: -322px -4px; } +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, +.vs .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { background-position: -343px -4px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -23px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -23px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string { background-position: -202px -23px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -23px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array { background-position: -302px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number { background-position: -322px -24px; } -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, -.vs-dark .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, -.hc-black .monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { background-position: -342px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor { background-position: 0 -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable { background-position: -22px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class { background-position: -43px -23px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface { background-position: -63px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.object, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.namespace, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.package, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module { background-position: -82px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property { background-position: -102px -23px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.key, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string { background-position: -202px -23px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum { background-position: -122px -23px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule { background-position: -242px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file { background-position: -262px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.array { background-position: -302px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.number { background-position: -322px -24px; } +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, +.vs-dark .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.null, +.hc-black .monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.boolean { background-position: -342px -24px; } diff --git a/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.ts b/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.ts index 77adc63a34..079b9a4cfb 100644 --- a/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.ts +++ b/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.ts @@ -5,8 +5,8 @@ 'use strict'; -import env = require('vs/base/common/platform'); -import nls = require('vs/nls'); +import * as env from 'vs/base/common/platform'; +import * as nls from 'vs/nls'; import { QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions as QuickOpenExtensions } from 'vs/workbench/browser/quickopen'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -22,7 +22,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; // Register Actions -const registry = Registry.as(ActionExtensions.WorkbenchActions); +const registry = Registry.as(ActionExtensions.WorkbenchActions); registry.registerWorkbenchAction(new SyncActionDescriptor(ClearCommandHistoryAction, ClearCommandHistoryAction.ID, ClearCommandHistoryAction.LABEL), 'Clear Command History'); registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllCommandsAction, ShowAllCommandsAction.ID, ShowAllCommandsAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P, diff --git a/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts b/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts index 68b3f95f24..a6d609d147 100644 --- a/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts @@ -5,8 +5,8 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); -import errors = require('vs/base/common/errors'); +import * as nls from 'vs/nls'; +import * as errors from 'vs/base/common/errors'; import { Mode, IEntryRunContext, IAutoFocus, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenModel, QuickOpenEntryGroup, QuickOpenEntry } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenHandler, QuickOpenAction } from 'vs/workbench/browser/quickopen'; @@ -19,12 +19,10 @@ import { Action } from 'vs/base/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { fuzzyContains, stripWildcards } from 'vs/base/common/strings'; import { matchesFuzzy } from 'vs/base/common/filters'; -import { ViewsRegistry, ViewLocation, IViewsViewlet } from 'vs/workbench/common/views'; +import { ViewsRegistry, ViewLocation, IViewsService } from 'vs/workbench/common/views'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; -import { VIEWLET_ID as DEBUG_VIEWLET_ID } from 'vs/workbench/parts/debug/common/debug'; -import { VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; +import { VIEWLET_ID as SCM_VIEWLET_ID } from 'vs/workbench/parts/scm/common/scm'; export const VIEW_PICKER_PREFIX = 'view '; @@ -73,6 +71,7 @@ export class ViewPickerHandler extends QuickOpenHandler { constructor( @IViewletService private viewletService: IViewletService, + @IViewsService private viewsService: IViewsService, @IOutputService private outputService: IOutputService, @ITerminalService private terminalService: ITerminalService, @IPanelService private panelService: IPanelService, @@ -129,7 +128,7 @@ export class ViewPickerHandler extends QuickOpenHandler { if (views.length) { for (const view of views) { if (this.contextKeyService.contextMatchesRules(view.when)) { - result.push(new ViewEntry(view.name, viewlet.name, () => this.viewletService.openViewlet(viewlet.id, true).done(viewlet => (viewlet).openView(view.id, true), errors.onUnexpectedError))); + result.push(new ViewEntry(view.name, viewlet.name, () => this.viewsService.openView(view.id, true))); } } } @@ -144,13 +143,9 @@ export class ViewPickerHandler extends QuickOpenHandler { const panels = this.panelService.getPanels(); panels.forEach((panel, index) => viewEntries.push(new ViewEntry(panel.name, nls.localize('panels', "Panels"), () => this.panelService.openPanel(panel.id, true).done(null, errors.onUnexpectedError)))); - // Views + // Viewlet Views viewlets.forEach((viewlet, index) => { - const viewLocation: ViewLocation = viewlet.id === EXPLORER_VIEWLET_ID ? ViewLocation.Explorer - : viewlet.id === DEBUG_VIEWLET_ID ? ViewLocation.Debug - : viewlet.id === EXTENSIONS_VIEWLET_ID ? ViewLocation.Extensions - : null; - + const viewLocation: ViewLocation = viewlet.id === SCM_VIEWLET_ID ? ViewLocation.SCM : ViewLocation.get(viewlet.id); if (viewLocation) { const viewEntriesForViewlet: ViewEntry[] = getViewEntriesForViewlet(viewlet, viewLocation); viewEntries.push(...viewEntriesForViewlet); diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index 0bcf019f8d..39b5ada66d 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -17,14 +17,17 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { RunOnceScheduler } from 'vs/base/common/async'; import URI from 'vs/base/common/uri'; import { isEqual } from 'vs/base/common/resources'; -import { isLinux } from 'vs/base/common/platform'; +import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { equals } from 'vs/base/common/objects'; interface IConfiguration extends IWindowsConfiguration { update: { channel: string; }; telemetry: { enableCrashReporter: boolean }; keyboard: { touchbar: { enabled: boolean } }; + workbench: { tree: { horizontalScrolling: boolean } }; + files: { useExperimentalFileWatcher: boolean, watcherExclude: object }; } export class SettingsChangeRelauncher implements IWorkbenchContribution { @@ -33,9 +36,14 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private titleBarStyle: 'native' | 'custom'; private nativeTabs: boolean; + private clickThroughInactive: boolean; private updateChannel: string; private enableCrashReporter: boolean; private touchbarEnabled: boolean; + private treeHorizontalScrolling: boolean; + private windowsSmoothScrollingWorkaround: boolean; + private experimentalFileWatcher: boolean; + private fileWatcherExclude: object; private firstFolderResource: URI; private extensionHostRestarter: RunOnceScheduler; @@ -47,7 +55,7 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IWindowService private windowService: IWindowService, @IConfigurationService private configurationService: IConfigurationService, @IEnvironmentService private envService: IEnvironmentService, - @IConfirmationService private confirmationService: IConfirmationService, + @IDialogService private dialogService: IDialogService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IExtensionService private extensionService: IExtensionService ) { @@ -69,18 +77,24 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private onConfigurationChange(config: IConfiguration, notify: boolean): void { let changed = false; - // Titlebar style - if (config.window && config.window.titleBarStyle !== this.titleBarStyle && (config.window.titleBarStyle === 'native' || config.window.titleBarStyle === 'custom')) { + // macOS: Titlebar style + if (isMacintosh && config.window && config.window.titleBarStyle !== this.titleBarStyle && (config.window.titleBarStyle === 'native' || config.window.titleBarStyle === 'custom')) { this.titleBarStyle = config.window.titleBarStyle; changed = true; } - // Native tabs - if (config.window && typeof config.window.nativeTabs === 'boolean' && config.window.nativeTabs !== this.nativeTabs) { + // macOS: Native tabs + if (isMacintosh && config.window && typeof config.window.nativeTabs === 'boolean' && config.window.nativeTabs !== this.nativeTabs) { this.nativeTabs = config.window.nativeTabs; changed = true; } + // macOS: Click through (accept first mouse) + if (isMacintosh && config.window && typeof config.window.clickThroughInactive === 'boolean' && config.window.clickThroughInactive !== this.clickThroughInactive) { + this.clickThroughInactive = config.window.clickThroughInactive; + changed = true; + } + // Update channel if (config.update && typeof config.update.channel === 'string' && config.update.channel !== this.updateChannel) { this.updateChannel = config.update.channel; @@ -93,12 +107,38 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { changed = true; } - // Touchbar config - if (config.keyboard && config.keyboard.touchbar && typeof config.keyboard.touchbar.enabled === 'boolean' && config.keyboard.touchbar.enabled !== this.touchbarEnabled) { + // Experimental File Watcher + if (config.files && typeof config.files.useExperimentalFileWatcher === 'boolean' && config.files.useExperimentalFileWatcher !== this.experimentalFileWatcher) { + this.experimentalFileWatcher = config.files.useExperimentalFileWatcher; + changed = true; + } + + // File Watcher Excludes (only if in folder workspace mode) + if (!this.experimentalFileWatcher && this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + if (config.files && typeof config.files.watcherExclude === 'object' && !equals(config.files.watcherExclude, this.fileWatcherExclude)) { + this.fileWatcherExclude = config.files.watcherExclude; + changed = true; + } + } + + // macOS: Touchbar config + if (isMacintosh && config.keyboard && config.keyboard.touchbar && typeof config.keyboard.touchbar.enabled === 'boolean' && config.keyboard.touchbar.enabled !== this.touchbarEnabled) { this.touchbarEnabled = config.keyboard.touchbar.enabled; changed = true; } + // Tree horizontal scrolling support + if (config.workbench && config.workbench.tree && typeof config.workbench.tree.horizontalScrolling === 'boolean' && config.workbench.tree.horizontalScrolling !== this.treeHorizontalScrolling) { + this.treeHorizontalScrolling = config.workbench.tree.horizontalScrolling; + changed = true; + } + + // Windows: smooth scrolling workaround + if (isWindows && config.window && typeof config.window.smoothScrollingWorkaround === 'boolean' && config.window.smoothScrollingWorkaround !== this.windowsSmoothScrollingWorkaround) { + this.windowsSmoothScrollingWorkaround = config.window.smoothScrollingWorkaround; + changed = true; + } + // Notify only when changed and we are the focused window (avoids notification spam across windows) if (notify && changed) { this.doConfirm( @@ -146,13 +186,13 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private doConfirm(message: string, detail: string, primaryButton: string, confirmed: () => void): void { this.windowService.isFocused().then(focused => { if (focused) { - return this.confirmationService.confirm({ + return this.dialogService.confirm({ type: 'info', message, detail, primaryButton - }).then(confirm => { - if (confirm) { + }).then(res => { + if (res.confirmed) { confirmed(); } }); @@ -167,5 +207,5 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { } } -const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); +const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(SettingsChangeRelauncher, LifecyclePhase.Running); diff --git a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts index fbbfcd0c05..15f467218e 100644 --- a/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/parts/scm/electron-browser/dirtydiffDecorator.ts @@ -5,13 +5,13 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import 'vs/css!./media/dirtydiffDecorator'; import { ThrottledDelayer, always } from 'vs/base/common/async'; import { IDisposable, dispose, toDisposable, empty as EmptyDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, anyEvent as anyEvent, filterEvent, once } from 'vs/base/common/event'; +import { Event, Emitter, anyEvent as anyEvent, filterEvent, once } from 'vs/base/common/event'; import * as ext from 'vs/workbench/common/contributions'; import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -25,7 +25,6 @@ import { ISCMService, ISCMRepository } from 'vs/workbench/services/scm/common/sc import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { registerThemingParticipant, ITheme, ICssStyleCollector, themeColorFromId, IThemeService } from 'vs/platform/theme/common/themeService'; import { registerColor } from 'vs/platform/theme/common/colorRegistry'; -import { localize } from 'vs/nls'; import { Color, RGBA } from 'vs/base/common/color'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; @@ -52,8 +51,8 @@ import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ISplice } from 'vs/base/common/sequence'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { createStyleSheet } from '../../../../base/browser/dom'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { createStyleSheet } from 'vs/base/browser/dom'; // TODO@Joao // Need to subclass MenuItemActionItem in order to respect @@ -257,8 +256,8 @@ class DirtyDiffWidget extends PeekViewWidget { private renderTitle(): void { const detail = this.model.changes.length > 1 - ? localize('changes', "{0} of {1} changes", this.index + 1, this.model.changes.length) - : localize('change', "{0} of {1} change", this.index + 1, this.model.changes.length); + ? nls.localize('changes', "{0} of {1} changes", this.index + 1, this.model.changes.length) + : nls.localize('change', "{0} of {1} change", this.index + 1, this.model.changes.length); this.setTitle(this.title, detail); } @@ -374,7 +373,7 @@ export class ShowPreviousChangeAction extends EditorAction { label: nls.localize('show previous change', "Show Previous Change"), alias: 'Show Previous Change', precondition: null, - kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F3 } + kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F3 } }); } @@ -408,7 +407,7 @@ export class ShowNextChangeAction extends EditorAction { label: nls.localize('show next change', "Show Next Change"), alias: 'Show Next Change', precondition: null, - kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.Alt | KeyCode.F3 } + kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.F3 } }); } @@ -442,7 +441,7 @@ export class MoveToPreviousChangeAction extends EditorAction { label: nls.localize('move to previous change', "Move to Previous Change"), alias: 'Move to Previous Change', precondition: null, - kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F5 } + kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F5 } }); } @@ -484,7 +483,7 @@ export class MoveToNextChangeAction extends EditorAction { label: nls.localize('move to next change', "Move to Next Change"), alias: 'Move to Next Change', precondition: null, - kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.Alt | KeyCode.F5 } + kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.F5 } }); } @@ -764,7 +763,7 @@ export class DirtyDiffController implements IEditorContribution { } dispose(): void { - return; + this.disposables = dispose(this.disposables); } } @@ -772,19 +771,19 @@ export const editorGutterModifiedBackground = registerColor('editorGutter.modifi dark: new Color(new RGBA(12, 125, 157)), light: new Color(new RGBA(102, 175, 224)), hc: new Color(new RGBA(0, 73, 122)) -}, localize('editorGutterModifiedBackground', "Editor gutter background color for lines that are modified.")); +}, nls.localize('editorGutterModifiedBackground', "Editor gutter background color for lines that are modified.")); export const editorGutterAddedBackground = registerColor('editorGutter.addedBackground', { dark: new Color(new RGBA(88, 124, 12)), light: new Color(new RGBA(129, 184, 139)), hc: new Color(new RGBA(27, 82, 37)) -}, localize('editorGutterAddedBackground', "Editor gutter background color for lines that are added.")); +}, nls.localize('editorGutterAddedBackground', "Editor gutter background color for lines that are added.")); export const editorGutterDeletedBackground = registerColor('editorGutter.deletedBackground', { dark: new Color(new RGBA(148, 21, 27)), light: new Color(new RGBA(202, 75, 81)), hc: new Color(new RGBA(141, 14, 20)) -}, localize('editorGutterDeletedBackground', "Editor gutter background color for lines that are deleted.")); +}, nls.localize('editorGutterDeletedBackground', "Editor gutter background color for lines that are deleted.")); const overviewRulerDefault = new Color(new RGBA(0, 122, 204, 0.6)); export const overviewRulerModifiedForeground = registerColor('editorOverviewRuler.modifiedForeground', { dark: overviewRulerDefault, light: overviewRulerDefault, hc: overviewRulerDefault }, nls.localize('overviewRulerModifiedForeground', 'Overview ruler marker color for modified content.')); @@ -952,7 +951,7 @@ export class DirtyDiffModel { onDidChange(this.triggerDiff, this, disposables); const onDidRemoveThis = filterEvent(this.scmService.onDidRemoveRepository, r => r === repository); - onDidRemoveThis(() => dispose(disposables)); + onDidRemoveThis(() => dispose(disposables), null, disposables); this.triggerDiff(); } @@ -1005,6 +1004,10 @@ export class DirtyDiffModel { this._originalURIPromise = this.getOriginalResource() .then(originalUri => { + if (!this._editorModel) { // disposed + return null; + } + if (!originalUri) { this._originalModel = null; return null; @@ -1012,6 +1015,10 @@ export class DirtyDiffModel { return this.textModelResolverService.createModelReference(originalUri) .then(ref => { + if (!this._editorModel) { // disposed + return null; + } + this._originalModel = ref.object.textEditorModel; this.disposables.push(ref); diff --git a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts index 461e852500..678cd0c330 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts @@ -39,16 +39,16 @@ const viewletDescriptor = new ViewletDescriptor( VIEWLET_ID, localize('source control', "Source Control"), 'scm', - 36 + 2 ); Registry.as(ViewletExtensions.Viewlets) .registerViewlet(viewletDescriptor); -Registry.as(WorkbenchExtensions.Workbench) +Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Running); -Registry.as(WorkbenchExtensions.Workbench) +Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(StatusBarController, LifecyclePhase.Running); // Register Action to Open Viewlet diff --git a/src/vs/workbench/parts/scm/electron-browser/scmMenus.ts b/src/vs/workbench/parts/scm/electron-browser/scmMenus.ts index cfcc91ce16..3ef6dda4f4 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmMenus.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmMenus.ts @@ -6,7 +6,7 @@ 'use strict'; import 'vs/css!./media/scmViewlet'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index e0e8653f49..37eb74d994 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -8,14 +8,13 @@ import 'vs/css!./media/scmViewlet'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, chain, mapEvent, anyEvent, filterEvent } from 'vs/base/common/event'; +import { Event, Emitter, chain, mapEvent, anyEvent, filterEvent, latch } from 'vs/base/common/event'; import { domEvent, stop } from 'vs/base/browser/event'; import { basename } from 'vs/base/common/paths'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable, dispose, combinedDisposable, empty as EmptyDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { Builder, Dimension } from 'vs/base/browser/builder'; import { PanelViewlet, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet'; -import { append, $, addClass, toggleClass, trackFocus } from 'vs/base/browser/dom'; +import { append, $, addClass, toggleClass, trackFocus, Dimension, addDisposableListener } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { List } from 'vs/base/browser/ui/list/listWidget'; import { IDelegate, IRenderer, IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list'; @@ -47,7 +46,7 @@ import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Command } from 'vs/editor/common/modes'; -import { render as renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; +import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import * as platform from 'vs/base/common/platform'; import { format } from 'vs/base/common/strings'; @@ -58,6 +57,10 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ThrottledDelayer } from 'vs/base/common/async'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IPartService } from 'vs/workbench/services/part/common/partService'; +import { IViewDescriptorRef, PersistentContributableViewsModel, IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/contributableViews'; +import { ViewLocation, IViewDescriptor, IViewsViewlet } from 'vs/workbench/common/views'; +import { ViewsViewletPanel } from 'vs/workbench/browser/parts/views/viewsViewlet'; +import { IPanelDndController, Panel } from 'vs/base/browser/ui/splitview/panelview'; export interface ISpliceEvent { index: number; @@ -249,12 +252,13 @@ class MainPanel extends ViewletPanel { identityProvider: repository => repository.provider.id }) as WorkbenchList; - this.disposables.push(this.list); this.list.onSelectionChange(this.onListSelectionChange, this, this.disposables); this.list.onContextMenu(this.onListContextMenu, this, this.disposables); this.viewModel.onDidChangeVisibility(this.onDidChangeVisibility, this, this.disposables); this.onDidChangeVisibility(this.viewModel.isVisible()); + + this.disposables.push(this.list); } private onDidChangeVisibility(visible: boolean): void { @@ -354,6 +358,11 @@ class MainPanel extends ViewletPanel { this.list.setSelection(selection); this.list.setFocus([selection[0]]); } + + dispose(): void { + this.visibilityDisposables = dispose(this.visibilityDisposables); + super.dispose(); + } } interface ResourceGroupTemplate { @@ -1010,7 +1019,7 @@ export class RepositoryPanel extends ViewletPanel { class InstallAdditionalSCMProvidersAction extends Action { - constructor( @IViewletService private viewletService: IViewletService) { + constructor(@IViewletService private viewletService: IViewletService) { super('scm.installAdditionalSCMProviders', localize('installAdditionalSCMProviders', "Install Additional SCM Providers..."), '', true); } @@ -1023,7 +1032,18 @@ class InstallAdditionalSCMProvidersAction extends Action { } } -export class SCMViewlet extends PanelViewlet implements IViewModel { +class SCMPanelDndController implements IPanelDndController { + + canDrag(panel: Panel): boolean { + return !(panel instanceof MainPanel) && !(panel instanceof RepositoryPanel); + } + + canDrop(panel: Panel, overPanel: Panel): boolean { + return !(overPanel instanceof MainPanel) && !(overPanel instanceof RepositoryPanel); + } +} + +export class SCMViewlet extends PanelViewlet implements IViewModel, IViewsViewlet { private el: HTMLElement; private menus: SCMMenus; @@ -1047,6 +1067,9 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { get repositories(): ISCMRepository[] { return this._repositories; } get selectedRepositories(): ISCMRepository[] { return this.repositoryPanels.map(p => p.repository); } + private contributedViews: PersistentContributableViewsModel; + private contributedViewDisposables: IDisposable[] = []; + constructor( @IPartService partService: IPartService, @ITelemetryService telemetryService: ITelemetryService, @@ -1066,19 +1089,22 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { @IExtensionService extensionService: IExtensionService, @IConfigurationService private configurationService: IConfigurationService, ) { - super(VIEWLET_ID, { showHeaderInTitleWhenSingleView: true }, partService, contextMenuService, telemetryService, themeService); + super(VIEWLET_ID, { showHeaderInTitleWhenSingleView: true, dnd: new SCMPanelDndController() }, partService, contextMenuService, telemetryService, themeService); this.menus = instantiationService.createInstance(SCMMenus, undefined); this.menus.onDidChangeTitle(this.updateTitleArea, this, this.disposables); + + this.contributedViews = new PersistentContributableViewsModel(ViewLocation.SCM, 'scm.views', contextKeyService, storageService, contextService); + this.disposables.push(this.contributedViews); } - async create(parent: Builder): TPromise { + async create(parent: HTMLElement): TPromise { await super.create(parent); - this.el = parent.getHTMLElement(); + this.el = parent; addClass(this.el, 'scm-viewlet'); addClass(this.el, 'empty'); - append(parent.getHTMLElement(), $('div.empty-message', null, localize('no open repo', "There are no active source control providers."))); + append(parent, $('div.empty-message', null, localize('no open repo', "There are no active source control providers."))); this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables); this.scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.disposables); @@ -1088,6 +1114,19 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { onDidUpdateConfiguration(this.onDidChangeRepositories, this, this.disposables); this.onDidChangeRepositories(); + + this.contributedViews.onDidAdd(this.onDidAddContributedView, this, this.disposables); + this.contributedViews.onDidRemove(this.onDidRemoveContributedView, this, this.disposables); + + let index = this.getContributedViewsStartIndex(); + for (const viewDescriptor of this.contributedViews.visibleViewDescriptors) { + const size = this.contributedViews.getSize(viewDescriptor.id); + const collapsed = this.contributedViews.isCollapsed(viewDescriptor.id); + + this.onDidAddContributedView({ viewDescriptor, index: index++, size, collapsed }); + } + + this.onDidSashChange(this.saveContributedViewSizes, this, this.disposables); } private onDidAddRepository(repository: ISCMRepository): void { @@ -1129,13 +1168,13 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { if (shouldMainPanelBeVisible) { this.mainPanel = this.instantiationService.createInstance(MainPanel, this); - this.addPanel(this.mainPanel, this.mainPanel.minimumSize, 0); + this.addPanels([{ panel: this.mainPanel, size: this.mainPanel.minimumSize, index: 0 }]); const selectionChangeDisposable = this.mainPanel.onSelectionChange(this.onSelectionChange, this); this.onSelectionChange(this.mainPanel.getSelection()); this.mainPanelDisposable = toDisposable(() => { - this.removePanel(this.mainPanel); + this.removePanels([this.mainPanel]); selectionChangeDisposable.dispose(); this.mainPanel.dispose(); }); @@ -1146,15 +1185,28 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { } } + private getContributedViewsStartIndex(): number { + return (this.mainPanel ? 1 : 0) + this.repositoryPanels.length; + } + setVisible(visible: boolean): TPromise { - const result = super.setVisible(visible); + const promises: TPromise[] = []; + promises.push(super.setVisible(visible)); if (!visible) { this.cachedMainPanelHeight = this.getPanelSize(this.mainPanel); } this._onDidChangeVisibility.fire(visible); - return result; + + const start = this.getContributedViewsStartIndex(); + + for (let i = 0; i < this.contributedViews.viewDescriptors.length; i++) { + const panel = this.panels[start + i] as ViewsViewletPanel; + promises.push(panel.setVisible(visible)); + } + + return TPromise.join(promises) as TPromise; } getOptimalWidth(): number { @@ -1174,8 +1226,7 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { getActions(): IAction[] { if (this.isSingleView()) { - const [panel] = this.repositoryPanels; - return panel.getActions(); + return this.panels[0].getActions(); } return this.menus.getTitleActions(); @@ -1185,14 +1236,14 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { let result: IAction[]; if (this.isSingleView()) { - const [panel] = this.repositoryPanels; + const [panel] = this.panels; result = [ ...panel.getSecondaryActions(), new Separator() ]; } else { - result = this.menus.getTitleSecondaryActions(); + result = [...this.menus.getTitleSecondaryActions()]; if (result.length > 0) { result.push(new Separator()); @@ -1213,13 +1264,33 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { return new ContextAwareMenuItemActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService); } + private didLayout = false; layout(dimension: Dimension): void { super.layout(dimension); this._height = dimension.height; + + if (this.didLayout) { + // this.saveViewSizes(); + } else { + this.didLayout = true; + this.restoreContributedViewSizes(); + } + } + + movePanel(from: ViewletPanel, to: ViewletPanel): void { + const start = this.getContributedViewsStartIndex(); + const fromIndex = firstIndex(this.panels, panel => panel === from) - start; + const toIndex = firstIndex(this.panels, panel => panel === to) - start; + const fromViewDescriptor = this.contributedViews.viewDescriptors[fromIndex]; + const toViewDescriptor = this.contributedViews.viewDescriptors[toIndex]; + + super.movePanel(from, to); + this.contributedViews.move(fromViewDescriptor.id, toViewDescriptor.id); } private onSelectionChange(repositories: ISCMRepository[]): void { const wasSingleView = this.isSingleView(); + const contributableViewsHeight = this.getContributableViewsSize(); // Collect unselected panels const panelsToRemove = this.repositoryPanels @@ -1235,14 +1306,15 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { .map(r => this.instantiationService.createInstance(RepositoryPanel, r, this)); // Add new selected panels + let index = repositoryPanels.length + (this.mainPanel ? 1 : 0); this.repositoryPanels = [...repositoryPanels, ...newRepositoryPanels]; newRepositoryPanels.forEach(panel => { - this.addPanel(panel, panel.minimumSize, this.length); + this.addPanels([{ panel, size: panel.minimumSize, index: index++ }]); panel.repository.focus(); }); // Remove unselected panels - panelsToRemove.forEach(panel => this.removePanel(panel)); + this.removePanels(panelsToRemove); // Restore main panel height if (this.isVisible() && typeof this.cachedMainPanelHeight === 'number') { @@ -1253,11 +1325,14 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { // Resize all panels equally const height = typeof this.height === 'number' ? this.height : 1000; const mainPanelHeight = this.getPanelSize(this.mainPanel); - const size = (height - mainPanelHeight) / repositories.length; + const size = (height - mainPanelHeight - contributableViewsHeight) / repositories.length; for (const panel of this.repositoryPanels) { this.resizePanel(panel, size); } + // Resize contributed view sizes + this.restoreContributedViewSizes(); + // React to menu changes for single view mode if (wasSingleView !== this.isSingleView()) { this.singleRepositoryPanelTitleActionsDisposable.dispose(); @@ -1270,8 +1345,133 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { } } + private getContributableViewsSize(): number { + let value = 0; + + for (let i = this.getContributedViewsStartIndex(); i < this.length; i++) { + value += this.getPanelSize(this.panels[i]); + } + + return value; + } + + onDidAddContributedView({ viewDescriptor, index, size, collapsed }: IAddedViewDescriptorRef): void { + const start = this.getContributedViewsStartIndex(); + const panel = this.instantiationService.createInstance(viewDescriptor.ctor, { + id: viewDescriptor.id, + name: viewDescriptor.name, + actionRunner: this.getActionRunner(), + expanded: !collapsed, + viewletSettings: {} // what is this + }) as ViewsViewletPanel; + + this.addPanels([{ panel, size: size || panel.minimumSize, index: start + index }]); + panel.setVisible(true); + + const contextMenuDisposable = addDisposableListener(panel.draggableElement, 'contextmenu', e => { + e.stopPropagation(); + e.preventDefault(); + this.onViewHeaderContextMenu(new StandardMouseEvent(e), viewDescriptor); + }); + + const collapseDisposable = latch(mapEvent(panel.onDidChange, () => !panel.isExpanded()))(collapsed => { + this.contributedViews.setCollapsed(viewDescriptor.id, collapsed); + }); + + this.contributedViewDisposables.splice(index, 0, combinedDisposable([contextMenuDisposable, collapseDisposable])); + } + + private onViewHeaderContextMenu(event: StandardMouseEvent, viewDescriptor: IViewDescriptor): void { + const actions: IAction[] = []; + actions.push({ + id: `${viewDescriptor.id}.removeView`, + label: localize('hideView', "Hide"), + enabled: viewDescriptor.canToggleVisibility, + run: () => this.contributedViews.setVisible(viewDescriptor.id, !this.contributedViews.isVisible(viewDescriptor.id)) + }); + + const otherActions = this.getContextMenuActions(); + if (otherActions.length) { + actions.push(...[new Separator(), ...otherActions]); + } + + let anchor: { x: number, y: number } = { x: event.posx, y: event.posy }; + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + getActions: () => TPromise.as(actions) + }); + } + + getContextMenuActions(): IAction[] { + const result: IAction[] = []; + const viewToggleActions = this.contributedViews.viewDescriptors.map(viewDescriptor => ({ + id: `${viewDescriptor.id}.toggleVisibility`, + label: viewDescriptor.name, + checked: this.contributedViews.isVisible(viewDescriptor.id), + enabled: viewDescriptor.canToggleVisibility, + run: () => this.contributedViews.setVisible(viewDescriptor.id, !this.contributedViews.isVisible(viewDescriptor.id)) + })); + + result.push(...viewToggleActions); + const parentActions = super.getContextMenuActions(); + if (viewToggleActions.length && parentActions.length) { + result.push(new Separator()); + } + result.push(...parentActions); + return result; + } + + onDidRemoveContributedView({ viewDescriptor, index }: IViewDescriptorRef): void { + const start = this.getContributedViewsStartIndex(); + const panel = this.panels[start + index]; + + this.removePanels([panel]); + + const [disposable] = this.contributedViewDisposables.splice(index, 1); + disposable.dispose(); + } + + private saveContributedViewSizes(): void { + const start = this.getContributedViewsStartIndex(); + + for (let i = 0; i < this.contributedViews.viewDescriptors.length; i++) { + const viewDescriptor = this.contributedViews.viewDescriptors[i]; + const size = this.getPanelSize(this.panels[start + i]); + + this.contributedViews.setSize(viewDescriptor.id, size); + } + } + + private restoreContributedViewSizes(): void { + if (!this.didLayout) { + return; + } + + const start = this.getContributedViewsStartIndex(); + + for (let i = 0; i < this.contributedViews.viewDescriptors.length; i++) { + const panel = this.panels[start + i]; + const viewDescriptor = this.contributedViews.viewDescriptors[i]; + const size = this.contributedViews.getSize(viewDescriptor.id); + + if (typeof size === 'number') { + this.resizePanel(panel, size); + } + } + } + protected isSingleView(): boolean { - return super.isSingleView() && this.repositoryPanels.length === 1; + return super.isSingleView() && this.repositoryPanels.length + this.contributedViews.visibleViewDescriptors.length === 1; + } + + openView(id: string, focus?: boolean): TPromise { + this.contributedViews.setVisible(id, true); + const panel = this.panels.filter(panel => panel instanceof ViewsViewletPanel && panel.id === id)[0]; + if (panel) { + panel.setExpanded(true); + panel.focus(); + } + return TPromise.as(null); } hide(repository: ISCMRepository): void { @@ -1282,8 +1482,14 @@ export class SCMViewlet extends PanelViewlet implements IViewModel { this.mainPanel.hide(repository); } + shutdown(): void { + this.contributedViews.saveViewsStates(); + super.shutdown(); + } + dispose(): void { this.disposables = dispose(this.disposables); + this.contributedViewDisposables = dispose(this.contributedViewDisposables); this.mainPanelDisposable.dispose(); super.dispose(); } diff --git a/src/vs/workbench/parts/search/browser/media/searchview.css b/src/vs/workbench/parts/search/browser/media/searchview.css index 026ed17d99..934bc64d48 100644 --- a/src/vs/workbench/parts/search/browser/media/searchview.css +++ b/src/vs/workbench/parts/search/browser/media/searchview.css @@ -18,13 +18,7 @@ left: 0; width: 16px; height: 100%; - - -webkit-box-sizing: border-box; - -o-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; box-sizing: border-box; - background-position: center center; background-repeat: no-repeat; cursor: pointer; @@ -59,6 +53,10 @@ margin-left: 3px; } +.search-view .search-widget .replace-container .monaco-action-bar { + height: 25px; +} + .search-view .search-widget .replace-container .monaco-action-bar .action-item .icon { background-repeat: no-repeat; width: 20px; @@ -166,7 +164,6 @@ margin-top: 0px; margin-bottom: 0px; padding-bottom: 4px; - -webkit-user-select: text; user-select: text; } @@ -182,8 +179,15 @@ padding: 0; } -.search-view .foldermatch .monaco-icon-label, -.search-view .filematch .monaco-icon-label { +.search-view:not(.wide) .foldermatch .monaco-icon-label, +.search-view:not(.wide) .filematch .monaco-icon-label { + flex: 1; +} + +.search-view:not(.wide) .monaco-tree .monaco-tree-row:hover:not(.highlighted) .foldermatch .monaco-icon-label, +.search-view:not(.wide) .monaco-tree .monaco-tree-row.focused .foldermatch .monaco-icon-label, +.search-view:not(.wide) .monaco-tree .monaco-tree-row:hover:not(.highlighted) .filematch .monaco-icon-label, +.search-view:not(.wide) .monaco-tree .monaco-tree-row.focused .filematch .monaco-icon-label { flex: 1; } @@ -194,6 +198,11 @@ margin-left: 0.8em; } +.search-view.wide .foldermatch .badge, +.search-view.wide .filematch .badge { + margin-left: 10px; +} + .search-view .linematch { position: relative; line-height: 22px; @@ -273,15 +282,24 @@ margin-right: 12px; } -.search-view > .results > .monaco-tree .monaco-tree-row:hover .content .filematch .monaco-count-badge, -.search-view > .results > .monaco-tree .monaco-tree-row:hover .content .foldermatch .monaco-count-badge, -.search-view > .results > .monaco-tree .monaco-tree-row:hover .content .linematch .monaco-count-badge, -.search-view > .results > .monaco-tree.focused .monaco-tree-row.focused .content .filematch .monaco-count-badge, -.search-view > .results > .monaco-tree.focused .monaco-tree-row.focused .content .foldermatch .monaco-count-badge, -.search-view > .results > .monaco-tree.focused .monaco-tree-row.focused .content .linematch .monaco-count-badge { +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row:hover .content .filematch .monaco-count-badge, +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row:hover .content .foldermatch .monaco-count-badge, +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row:hover .content .linematch .monaco-count-badge, +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row.focused .content .filematch .monaco-count-badge, +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row.focused .content .foldermatch .monaco-count-badge, +.search-view:not(.wide) > .results > .monaco-tree .monaco-tree-row.focused .content .linematch .monaco-count-badge { display: none; } +.search-view.wide > .results > .monaco-tree .monaco-tree-row:hover .content .filematch .badge, +.search-view.wide > .results > .monaco-tree .monaco-tree-row:hover .content .foldermatch .badge, +.search-view.wide > .results > .monaco-tree .monaco-tree-row:hover .content .linematch .badge, +.search-view.wide > .results > .monaco-tree .monaco-tree-row.focused .content .filematch .badge, +.search-view.wide > .results > .monaco-tree .monaco-tree-row.focused .content .foldermatch .badge, +.search-view.wide > .results > .monaco-tree .monaco-tree-row.focused .content .linematch .badge { + flex: 1; +} + .search-view .focused .monaco-tree-row.selected:not(.highlighted) > .content.actions .action-remove, .vs-dark .monaco-workbench .search-view .focused .monaco-tree-row.selected:not(.highlighted) > .content.actions .action-remove { background: url("action-remove-focus.svg") center center no-repeat; @@ -362,11 +380,11 @@ /* Theming */ -.vs .viewlet .search-view .search-widget .toggle-replace-button:hover { +.vs .search-view .search-widget .toggle-replace-button:hover { background-color: rgba(0, 0, 0, 0.1) !important; } -.vs-dark .viewlet .search-view .search-widget .toggle-replace-button:hover { +.vs-dark .search-view .search-widget .toggle-replace-button:hover { background-color: rgba(255, 255, 255, 0.1) !important; } diff --git a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts index 202d309cb6..a1962e5705 100644 --- a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts +++ b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts @@ -7,9 +7,9 @@ import * as arrays from 'vs/base/common/arrays'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { ThrottledDelayer } from 'vs/base/common/async'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenEntry, QuickOpenModel, QuickOpenItemAccessor } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenHandler } from 'vs/workbench/browser/quickopen'; diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index 0e760ee057..46e90df241 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -5,10 +5,10 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import errors = require('vs/base/common/errors'); -import nls = require('vs/nls'); -import paths = require('vs/base/common/paths'); -import labels = require('vs/base/common/labels'); +import * as errors from 'vs/base/common/errors'; +import * as nls from 'vs/nls'; +import * as paths from 'vs/base/common/paths'; +import * as labels from 'vs/base/common/labels'; import * as objects from 'vs/base/common/objects'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import URI from 'vs/base/common/uri'; diff --git a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts index 46b1846528..be17910b29 100644 --- a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts +++ b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -12,11 +12,11 @@ import { ThrottledDelayer } from 'vs/base/common/async'; import { QuickOpenHandler, EditorQuickOpenEntry } from 'vs/workbench/browser/quickopen'; import { QuickOpenModel, QuickOpenEntry, compareEntries } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IAutoFocus, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen'; -import filters = require('vs/base/common/filters'); -import strings = require('vs/base/common/strings'); +import * as filters from 'vs/base/common/filters'; +import * as strings from 'vs/base/common/strings'; import { Range } from 'vs/editor/common/core/range'; import { EditorInput, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; -import labels = require('vs/base/common/labels'); +import * as labels from 'vs/base/common/labels'; import { SymbolInformation, symbolKindToCssClass } from 'vs/editor/common/modes'; import { IResourceInput } from 'vs/platform/editor/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -137,7 +137,7 @@ export class OpenSymbolHandler extends QuickOpenHandler { private delayer: ThrottledDelayer; private options: IOpenSymbolOptions; - constructor( @IInstantiationService private instantiationService: IInstantiationService) { + constructor(@IInstantiationService private instantiationService: IInstantiationService) { super(); this.delayer = new ThrottledDelayer(OpenSymbolHandler.SEARCH_DELAY); diff --git a/src/vs/workbench/parts/search/browser/patternInputWidget.ts b/src/vs/workbench/parts/search/browser/patternInputWidget.ts index a104a0eaef..0453b10388 100644 --- a/src/vs/workbench/parts/search/browser/patternInputWidget.ts +++ b/src/vs/workbench/parts/search/browser/patternInputWidget.ts @@ -3,16 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as dom from 'vs/base/browser/dom'; -import { $ } from 'vs/base/browser/builder'; import { Widget } from 'vs/base/browser/ui/widget'; import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { InputBox, IInputValidator } from 'vs/base/browser/ui/inputbox/inputBox'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import CommonEvent, { Emitter } from 'vs/base/common/event'; +import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler, attachCheckboxStyler } from 'vs/platform/theme/common/styler'; import { HistoryNavigator } from 'vs/base/common/history'; @@ -22,6 +21,8 @@ export interface IOptions { width?: number; validation?: IInputValidator; ariaLabel?: string; + history?: string[]; + historyLimit?: number; } export class PatternInputWidget extends Widget { @@ -48,7 +49,7 @@ export class PatternInputWidget extends Widget { constructor(parent: HTMLElement, private contextViewProvider: IContextViewProvider, protected themeService: IThemeService, options: IOptions = Object.create(null)) { super(); - this.history = new HistoryNavigator(); + this.history = new HistoryNavigator(options.history || [], options.historyLimit); this.onOptionChange = null; this.width = options.width || 100; this.placeholder = options.placeholder || ''; @@ -73,7 +74,7 @@ export class PatternInputWidget extends Widget { switch (eventType) { case 'keydown': case 'keyup': - $(this.inputBox.inputElement).on(eventType, handler); + this._register(dom.addDisposableListener(this.inputBox.inputElement, eventType, handler)); break; case PatternInputWidget.OPTION_CHANGE: this.onOptionChange = handler; @@ -124,8 +125,8 @@ export class PatternInputWidget extends Widget { return this.history.getHistory(); } - public setHistory(history: string[]) { - this.history = new HistoryNavigator(history); + public clearHistory(): void { + this.history.clear(); } public onSearchSubmit(): void { @@ -158,7 +159,7 @@ export class PatternInputWidget extends Widget { private render(): void { this.domNode = document.createElement('div'); this.domNode.style.width = this.width + 'px'; - $(this.domNode).addClass('monaco-findInput'); + dom.addClass(this.domNode, 'monaco-findInput'); this.inputBox = new InputBox(this.domNode, this.contextViewProvider, { placeholder: this.placeholder || '', diff --git a/src/vs/workbench/parts/search/browser/replaceService.ts b/src/vs/workbench/parts/search/browser/replaceService.ts index 878a8ec18b..9abc32c72c 100644 --- a/src/vs/workbench/parts/search/browser/replaceService.ts +++ b/src/vs/workbench/parts/search/browser/replaceService.ts @@ -26,6 +26,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IFileService } from 'vs/platform/files/common/files'; import { ResourceTextEdit } from 'vs/editor/common/modes'; import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; +import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; const REPLACE_PREVIEW = 'replacePreview'; @@ -95,6 +96,7 @@ export class ReplaceService implements IReplaceService { constructor( @IFileService private fileService: IFileService, + @ITextFileService private textFileService: ITextFileService, @IEditorService private editorService: IWorkbenchEditorService, @ITextModelService private textModelResolverService: ITextModelService ) { } @@ -104,11 +106,13 @@ export class ReplaceService implements IReplaceService { public replace(match: FileMatchOrMatch, progress?: IProgressRunner, resource?: URI): TPromise; public replace(arg: any, progress: IProgressRunner = null, resource: URI = null): TPromise { + const edits: ResourceTextEdit[] = []; + let bulkEdit = new BulkEdit(null, progress, this.textModelResolverService, this.fileService); if (arg instanceof Match) { let match = arg; - bulkEdit.add([this.createEdit(match, match.replaceString, resource)]); + edits.push(this.createEdit(match, match.replaceString, resource)); } if (arg instanceof FileMatch) { @@ -119,14 +123,13 @@ export class ReplaceService implements IReplaceService { arg.forEach(element => { let fileMatch = element; if (fileMatch.count() > 0) { - fileMatch.matches().forEach(match => { - bulkEdit.add([this.createEdit(match, match.replaceString, resource)]); - }); + edits.push(...fileMatch.matches().map(match => this.createEdit(match, match.replaceString, resource))); } }); } - return bulkEdit.perform(); + bulkEdit.add(edits); + return bulkEdit.perform().then(() => this.textFileService.saveAll(edits.map(e => e.resource))); } public openReplacePreview(element: FileMatchOrMatch, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): TPromise { diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index 43d9bbe3ec..ecd752576c 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -3,30 +3,35 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); -import DOM = require('vs/base/browser/dom'); +import * as nls from 'vs/nls'; +import * as DOM from 'vs/base/browser/dom'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { ITree } from 'vs/base/parts/tree/browser/tree'; import { INavigator } from 'vs/base/common/iterator'; import { SearchView } from 'vs/workbench/parts/search/browser/searchView'; -import { Match, FileMatch, FileMatchOrMatch, FolderMatch, RenderableMatch } from 'vs/workbench/parts/search/common/searchModel'; +import { Match, FileMatch, FileMatchOrMatch, FolderMatch, RenderableMatch, SearchResult } from 'vs/workbench/parts/search/common/searchModel'; import { IReplaceService } from 'vs/workbench/parts/search/common/replace'; import * as Constants from 'vs/workbench/parts/search/common/constants'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ResolvedKeybinding, createKeybinding } from 'vs/base/common/keyCodes'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { OS } from 'vs/base/common/platform'; -import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { OS, isWindows } from 'vs/base/common/platform'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { VIEW_ID } from 'vs/platform/search/common/search'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { ICommandHandler } from 'vs/platform/commands/common/commands'; +import { Schemas } from 'vs/base/common/network'; +import { getPathLabel } from 'vs/base/common/labels'; +import URI from 'vs/base/common/uri'; export function isSearchViewFocused(viewletService: IViewletService, panelService: IPanelService): boolean { let searchView = getSearchView(viewletService, panelService); let activeElement = document.activeElement; - return searchView && activeElement && DOM.isAncestor(activeElement, searchView.getContainer().getHTMLElement()); + return searchView && activeElement && DOM.isAncestor(activeElement, searchView.getContainer()); } export function appendKeyBindingLabel(label: string, keyBinding: number | ResolvedKeybinding, keyBindingService2: IKeybindingService): string { @@ -83,7 +88,6 @@ export class ShowNextSearchIncludeAction extends Action { public static readonly ID = 'search.history.showNextIncludePattern'; public static readonly LABEL = nls.localize('nextSearchIncludePattern', "Show Next Search Include Pattern"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -91,7 +95,7 @@ export class ShowNextSearchIncludeAction extends Action { @IContextKeyService private contextKeyService: IContextKeyService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowNextSearchIncludeAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -105,7 +109,6 @@ export class ShowPreviousSearchIncludeAction extends Action { public static readonly ID = 'search.history.showPreviousIncludePattern'; public static readonly LABEL = nls.localize('previousSearchIncludePattern', "Show Previous Search Include Pattern"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -113,7 +116,7 @@ export class ShowPreviousSearchIncludeAction extends Action { @IContextKeyService private contextKeyService: IContextKeyService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowPreviousSearchIncludeAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -127,7 +130,6 @@ export class ShowNextSearchExcludeAction extends Action { public static readonly ID = 'search.history.showNextExcludePattern'; public static readonly LABEL = nls.localize('nextSearchExcludePattern', "Show Next Search Exclude Pattern"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternExcludesFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -135,7 +137,7 @@ export class ShowNextSearchExcludeAction extends Action { @IContextKeyService private contextKeyService: IContextKeyService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowNextSearchExcludeAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -149,7 +151,6 @@ export class ShowPreviousSearchExcludeAction extends Action { public static readonly ID = 'search.history.showPreviousExcludePattern'; public static readonly LABEL = nls.localize('previousSearchExcludePattern', "Show Previous Search Exclude Pattern"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternExcludesFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -157,7 +158,7 @@ export class ShowPreviousSearchExcludeAction extends Action { @IPanelService private panelService: IPanelService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowPreviousSearchExcludeAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -171,7 +172,6 @@ export class ShowNextSearchTermAction extends Action { public static readonly ID = 'search.history.showNext'; public static readonly LABEL = nls.localize('nextSearchTerm', "Show Next Search Term"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -179,7 +179,7 @@ export class ShowNextSearchTermAction extends Action { @IPanelService private panelService: IPanelService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowNextSearchTermAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -193,7 +193,6 @@ export class ShowPreviousSearchTermAction extends Action { public static readonly ID = 'search.history.showPrevious'; public static readonly LABEL = nls.localize('previousSearchTerm', "Show Previous Search Term"); - public static CONTEXT_KEY_EXPRESSION: ContextKeyExpr = ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey); constructor(id: string, label: string, @IViewletService private viewletService: IViewletService, @@ -201,7 +200,7 @@ export class ShowPreviousSearchTermAction extends Action { @IPanelService private panelService: IPanelService ) { super(id, label); - this.enabled = this.contextKeyService.contextMatchesRules(ShowPreviousSearchTermAction.CONTEXT_KEY_EXPRESSION); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); } public run(): TPromise { @@ -264,21 +263,16 @@ export abstract class FindOrReplaceInFilesAction extends Action { } public run(): TPromise { - const searchView = getSearchView(this.viewletService, this.panelService); return openSearchView(this.viewletService, this.panelService, true).then(openedView => { - if (!searchView || this.expandSearchReplaceWidget) { - const searchAndReplaceWidget = openedView.searchAndReplaceWidget; - searchAndReplaceWidget.toggleReplace(this.expandSearchReplaceWidget); - // Focus replace only when there is text in the searchInput box - const focusReplace = this.focusReplace && searchAndReplaceWidget.searchInput.getValue(); - searchAndReplaceWidget.focus(this.selectWidgetText, !!focusReplace); - } + const searchAndReplaceWidget = openedView.searchAndReplaceWidget; + searchAndReplaceWidget.toggleReplace(this.expandSearchReplaceWidget); + // Focus replace only when there is text in the searchInput box + const focusReplace = this.focusReplace && searchAndReplaceWidget.searchInput.getValue(); + searchAndReplaceWidget.focus(this.selectWidgetText, !!focusReplace); }); } } -export const SHOW_SEARCH_LABEL = nls.localize('showSearchViewlet', "Show Search"); - export class FindInFilesAction extends FindOrReplaceInFilesAction { public static readonly LABEL = nls.localize('findInFiles', "Find in Files"); @@ -377,7 +371,7 @@ export class CollapseDeepestExpandedLevelAction extends Action { viewer.collapseDeepestExpandedLevel(); viewer.clearSelection(); viewer.clearFocus(); - viewer.DOMFocus(); + viewer.domFocus(); viewer.focusFirst(); } return TPromise.as(null); @@ -399,7 +393,7 @@ export class ClearSearchResultsAction extends Action { update(): void { const searchView = getSearchView(this.viewletService, this.panelService); - this.enabled = searchView && searchView.hasSearchResults(); + this.enabled = searchView && searchView.isSearchSubmitted(); } public run(): TPromise { @@ -497,7 +491,9 @@ export abstract class AbstractSearchAndReplaceAction extends Action { // If file match is removed then next element is the next file match while (!!navigator.next() && !(navigator.current() instanceof FileMatch)) { } } else { - navigator.next(); + while (navigator.next() && !(navigator.current() instanceof Match)) { + viewer.expand(navigator.current()); + } } return navigator.current(); } @@ -505,11 +501,32 @@ export abstract class AbstractSearchAndReplaceAction extends Action { public getPreviousElementAfterRemoved(viewer: ITree, element: RenderableMatch): RenderableMatch { let navigator: INavigator = this.getNavigatorAt(element, viewer); let previousElement = navigator.previous(); - if (element instanceof Match && element.parent().matches().length === 1) { - // If this is the only match, then the file match is also removed - // Hence take the previous element to file match + + // If this is the only match, then the file/folder match is also removed + // Hence take the previous element. + const parent = element.parent(); + if (parent === previousElement) { previousElement = navigator.previous(); } + + if (parent instanceof FileMatch && parent.parent() === previousElement) { + previousElement = navigator.previous(); + } + + // If the previous element is a File or Folder, expand it and go to its last child. + // Spell out the two cases, would be too easy to create an infinite loop, like by adding another level... + if (previousElement && previousElement instanceof FolderMatch) { + navigator.next(); + viewer.expand(previousElement); + previousElement = navigator.previous(); + } + + if (previousElement && previousElement instanceof FileMatch) { + navigator.next(); + viewer.expand(previousElement); + previousElement = navigator.previous(); + } + return previousElement; } @@ -522,8 +539,10 @@ export abstract class AbstractSearchAndReplaceAction extends Action { export class RemoveAction extends AbstractSearchAndReplaceAction { + public static LABEL = nls.localize('RemoveAction.label', "Dismiss"); + constructor(private viewer: ITree, private element: RenderableMatch) { - super('remove', nls.localize('RemoveAction.label', "Dismiss"), 'action-remove'); + super('remove', RemoveAction.LABEL, 'action-remove'); } public run(): TPromise { @@ -548,7 +567,7 @@ export class RemoveAction extends AbstractSearchAndReplaceAction { elementToRefresh = parent.count() === 0 ? parent.parent() : parent; } - this.viewer.DOMFocus(); + this.viewer.domFocus(); return this.viewer.refresh(elementToRefresh); } @@ -556,9 +575,11 @@ export class RemoveAction extends AbstractSearchAndReplaceAction { export class ReplaceAllAction extends AbstractSearchAndReplaceAction { + public static readonly LABEL = nls.localize('file.replaceAll.label', "Replace All"); + constructor(private viewer: ITree, private fileMatch: FileMatch, private viewlet: SearchView, @IKeybindingService keyBindingService: IKeybindingService) { - super(Constants.ReplaceAllInFileActionId, appendKeyBindingLabel(nls.localize('file.replaceAll.label', "Replace All"), keyBindingService.lookupKeybinding(Constants.ReplaceAllInFileActionId), keyBindingService), 'action-replace-all'); + super(Constants.ReplaceAllInFileActionId, appendKeyBindingLabel(ReplaceAllAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFileActionId), keyBindingService), 'action-replace-all'); } public run(): TPromise { @@ -567,7 +588,7 @@ export class ReplaceAllAction extends AbstractSearchAndReplaceAction { if (nextFocusElement) { this.viewer.setFocus(nextFocusElement); } - this.viewer.DOMFocus(); + this.viewer.domFocus(); this.viewlet.open(this.fileMatch, true); }); } @@ -575,10 +596,12 @@ export class ReplaceAllAction extends AbstractSearchAndReplaceAction { export class ReplaceAllInFolderAction extends AbstractSearchAndReplaceAction { + public static readonly LABEL = nls.localize('file.replaceAll.label', "Replace All"); + constructor(private viewer: ITree, private folderMatch: FolderMatch, @IKeybindingService keyBindingService: IKeybindingService ) { - super(Constants.ReplaceAllInFolderActionId, nls.localize('file.replaceAll.label', "Replace All"), 'action-replace-all'); + super(Constants.ReplaceAllInFolderActionId, appendKeyBindingLabel(ReplaceAllInFolderAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceAllInFolderActionId), keyBindingService), 'action-replace-all'); } public async run(): TPromise { @@ -588,17 +611,19 @@ export class ReplaceAllInFolderAction extends AbstractSearchAndReplaceAction { if (nextFocusElement) { this.viewer.setFocus(nextFocusElement); } - this.viewer.DOMFocus(); + this.viewer.domFocus(); } } export class ReplaceAction extends AbstractSearchAndReplaceAction { + public static readonly LABEL = nls.localize('match.replace.label', "Replace"); + constructor(private viewer: ITree, private element: Match, private viewlet: SearchView, @IReplaceService private replaceService: IReplaceService, @IKeybindingService keyBindingService: IKeybindingService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService) { - super(Constants.ReplaceActionId, appendKeyBindingLabel(nls.localize('match.replace.label', "Replace"), keyBindingService.lookupKeybinding(Constants.ReplaceActionId), keyBindingService), 'action-replace'); + super(Constants.ReplaceActionId, appendKeyBindingLabel(ReplaceAction.LABEL, keyBindingService.lookupKeybinding(Constants.ReplaceActionId), keyBindingService), 'action-replace'); } public run(): TPromise { @@ -610,7 +635,7 @@ export class ReplaceAction extends AbstractSearchAndReplaceAction { this.viewer.setFocus(elementToFocus); } let elementToShowReplacePreview = this.getElementToShowReplacePreview(elementToFocus); - this.viewer.DOMFocus(); + this.viewer.domFocus(); if (!elementToShowReplacePreview || this.hasToOpenFile()) { this.viewlet.open(this.element, true); } else { @@ -670,3 +695,100 @@ export class ReplaceAction extends AbstractSearchAndReplaceAction { return false; } } + +function uriToClipboardString(resource: URI): string { + return resource.scheme === Schemas.file ? getPathLabel(resource) : resource.toString(); +} + +export const copyPathCommand: ICommandHandler = (accessor, fileMatch: FileMatch | FolderMatch) => { + const clipboardService = accessor.get(IClipboardService); + + const text = uriToClipboardString(fileMatch.resource()); + clipboardService.writeText(text); +}; + +function matchToString(match: Match): string { + return `${match.range().startLineNumber},${match.range().startColumn}: ${match.text()}`; +} + +const lineDelimiter = isWindows ? '\r\n' : '\n'; +function fileMatchToString(fileMatch: FileMatch, maxMatches: number): { text: string, count: number } { + const matchTextRows = fileMatch.matches() + .slice(0, maxMatches) + .map(matchToString) + .map(matchText => ' ' + matchText); + + return { + text: `${uriToClipboardString(fileMatch.resource())}${lineDelimiter}${matchTextRows.join(lineDelimiter)}`, + count: matchTextRows.length + }; +} + +function folderMatchToString(folderMatch: FolderMatch, maxMatches: number): { text: string, count: number } { + const fileResults: string[] = []; + let numMatches = 0; + + for (let i = 0; i < folderMatch.fileCount() && numMatches < maxMatches; i++) { + const fileResult = fileMatchToString(folderMatch.matches()[i], maxMatches - numMatches); + numMatches += fileResult.count; + fileResults.push(fileResult.text); + } + + return { + text: fileResults.join(lineDelimiter + lineDelimiter), + count: numMatches + }; +} + +const maxClipboardMatches = 1e4; +export const copyMatchCommand: ICommandHandler = (accessor, match: RenderableMatch) => { + const clipboardService = accessor.get(IClipboardService); + + let text: string; + if (match instanceof Match) { + text = matchToString(match); + } else if (match instanceof FileMatch) { + text = fileMatchToString(match, maxClipboardMatches).text; + } else if (match instanceof FolderMatch) { + text = folderMatchToString(match, maxClipboardMatches).text; + } + + if (text) { + clipboardService.writeText(text); + } +}; + +function allFolderMatchesToString(folderMatches: FolderMatch[], maxMatches: number): string { + const folderResults: string[] = []; + let numMatches = 0; + + for (let i = 0; i < folderMatches.length && numMatches < maxMatches; i++) { + const folderResult = folderMatchToString(folderMatches[i], maxMatches - numMatches); + if (folderResult.count) { + numMatches += folderResult.count; + folderResults.push(folderResult.text); + } + } + + return folderResults.join(lineDelimiter + lineDelimiter); +} + +export const copyAllCommand: ICommandHandler = accessor => { + const viewletService = accessor.get(IViewletService); + const panelService = accessor.get(IPanelService); + const clipboardService = accessor.get(IClipboardService); + + const searchView = getSearchView(viewletService, panelService); + const root: SearchResult = searchView.getControl().getInput(); + + const text = allFolderMatchesToString(root.folderMatches(), maxClipboardMatches); + clipboardService.writeText(text); +}; + +export const clearHistoryCommand: ICommandHandler = accessor => { + const viewletService = accessor.get(IViewletService); + const panelService = accessor.get(IPanelService); + const searchView = getSearchView(viewletService, panelService); + + searchView.clearHistory(); +}; diff --git a/src/vs/workbench/parts/search/browser/searchResultsView.ts b/src/vs/workbench/parts/search/browser/searchResultsView.ts index 9aaa44927f..ae01b8d08e 100644 --- a/src/vs/workbench/parts/search/browser/searchResultsView.ts +++ b/src/vs/workbench/parts/search/browser/searchResultsView.ts @@ -12,7 +12,7 @@ import { IAction, IActionRunner } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { FileLabel } from 'vs/workbench/browser/labels'; -import { ITree, IDataSource, ISorter, IAccessibilityProvider, IFilter, IRenderer } from 'vs/base/parts/tree/browser/tree'; +import { ITree, IDataSource, ISorter, IAccessibilityProvider, IFilter, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree'; import { Match, SearchResult, FileMatch, FileMatchOrMatch, SearchModel, FolderMatch } from 'vs/workbench/parts/search/common/searchModel'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Range } from 'vs/editor/common/core/range'; @@ -23,6 +23,11 @@ import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { getPathLabel } from 'vs/base/common/labels'; import { FileKind } from 'vs/platform/files/common/files'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; +import { WorkbenchTreeController, WorkbenchTree } from 'vs/platform/list/browser/listService'; +import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; export class SearchDataSource implements IDataSource { @@ -31,7 +36,7 @@ export class SearchDataSource implements IDataSource { private includeFolderMatch: boolean; private listener: IDisposable; - constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { this.updateIncludeFolderMatch(); this.listener = this.contextService.onDidChangeWorkbenchState(() => this.updateIncludeFolderMatch()); } @@ -319,7 +324,7 @@ export class SearchRenderer extends Disposable implements IRenderer { export class SearchAccessibilityProvider implements IAccessibilityProvider { - constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { } public getAriaLabel(tree: ITree, element: FileMatchOrMatch): string { @@ -339,10 +344,12 @@ export class SearchAccessibilityProvider implements IAccessibilityProvider { const replace = searchModel.isReplaceActive() && !!searchModel.replaceString; const matchString = match.getMatchString(); const range = match.range(); + const matchText = match.text().substr(0, range.endColumn + 150); if (replace) { - return nls.localize('replacePreviewResultAria', "Replace term {0} with {1} at column position {2} in line with text {3}", matchString, match.replaceString, range.startColumn + 1, match.text()); + return nls.localize('replacePreviewResultAria', "Replace term {0} with {1} at column position {2} in line with text {3}", matchString, match.replaceString, range.startColumn + 1, matchText); } - return nls.localize('searchResultAria', "Found term {0} at column position {1} in line with text {2}", matchString, range.startColumn + 1, match.text()); + + return nls.localize('searchResultAria', "Found term {0} at column position {1} in line with text {2}", matchString, range.startColumn + 1, matchText); } return undefined; } @@ -354,3 +361,38 @@ export class SearchFilter implements IFilter { return !(element instanceof FileMatch || element instanceof FolderMatch) || element.matches().length > 0; } } + +export class SearchTreeController extends WorkbenchTreeController { + private contextMenu: IMenu; + + constructor( + @IContextMenuService private contextMenuService: IContextMenuService, + @IMenuService private menuService: IMenuService, + @IConfigurationService configurationService: IConfigurationService + ) { + super({}, configurationService); + } + + public onContextMenu(tree: WorkbenchTree, element: any, event: ContextMenuEvent): boolean { + if (!this.contextMenu) { + this.contextMenu = this.menuService.createMenu(MenuId.SearchContext, tree.contextKeyService); + } + + tree.setFocus(element, { preventOpenOnFocus: true }); + + const anchor = { x: event.posx, y: event.posy }; + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + + getActions: () => { + const actions: IAction[] = []; + fillInActions(this.contextMenu, { shouldForwardArgs: true }, actions, this.contextMenuService); + return TPromise.as(actions); + }, + + getActionsContext: () => element + }); + + return true; + } +} diff --git a/src/vs/workbench/parts/search/browser/searchView.ts b/src/vs/workbench/parts/search/browser/searchView.ts index 6bbbd0fa41..990637bfdf 100644 --- a/src/vs/workbench/parts/search/browser/searchView.ts +++ b/src/vs/workbench/parts/search/browser/searchView.ts @@ -6,24 +6,24 @@ 'use strict'; import 'vs/css!./media/searchview'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Emitter, debounceEvent } from 'vs/base/common/event'; -import errors = require('vs/base/common/errors'); -import aria = require('vs/base/browser/ui/aria/aria'); -import env = require('vs/base/common/platform'); +import * as errors from 'vs/base/common/errors'; +import * as aria from 'vs/base/browser/ui/aria/aria'; +import * as env from 'vs/base/common/platform'; import { Delayer } from 'vs/base/common/async'; import URI from 'vs/base/common/uri'; -import strings = require('vs/base/common/strings'); +import * as strings from 'vs/base/common/strings'; import * as paths from 'vs/base/common/paths'; -import dom = require('vs/base/browser/dom'); +import * as dom from 'vs/base/browser/dom'; import { IAction } from 'vs/base/common/actions'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { Dimension, Builder, $ } from 'vs/base/browser/builder'; +import { Builder, $ } from 'vs/base/browser/builder'; import { FindInput } from 'vs/base/browser/ui/findinput/findInput'; import { ITree, IFocusEvent } from 'vs/base/parts/tree/browser/tree'; import { Scope } from 'vs/workbench/common/memento'; -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files'; import { Match, FileMatch, SearchModel, FileMatchOrMatch, IChangeEvent, ISearchWorkbenchService, FolderMatch } from 'vs/workbench/parts/search/common/searchModel'; @@ -41,7 +41,7 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { KeyCode } from 'vs/base/common/keyCodes'; import { PatternInputWidget, ExcludePatternInputWidget } from 'vs/workbench/parts/search/browser/patternInputWidget'; -import { SearchRenderer, SearchDataSource, SearchSorter, SearchAccessibilityProvider, SearchFilter } from 'vs/workbench/parts/search/browser/searchResultsView'; +import { SearchRenderer, SearchDataSource, SearchSorter, SearchAccessibilityProvider, SearchFilter, SearchTreeController } from 'vs/workbench/parts/search/browser/searchResultsView'; import { SearchWidget, ISearchWidgetOptions } from 'vs/workbench/parts/search/browser/searchWidget'; import { RefreshAction, CollapseDeepestExpandedLevelAction, ClearSearchResultsAction, CancelSearchAction } from 'vs/workbench/parts/search/browser/searchActions'; import { IReplaceService } from 'vs/workbench/parts/search/common/replace'; @@ -56,7 +56,7 @@ import { isDiffEditor, isCodeEditor, ICodeEditor } from 'vs/editor/browser/edito import { TreeResourceNavigator, WorkbenchTree } from 'vs/platform/list/browser/listService'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { SimpleFileResourceDragAndDrop } from 'vs/workbench/browser/dnd'; -import { IConfirmation, IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; +import { IConfirmation, IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IPanel } from 'vs/workbench/common/panel'; import { IViewlet } from 'vs/workbench/common/viewlet'; @@ -65,9 +65,14 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; export class SearchView extends Viewlet implements IViewlet, IPanel { + private static readonly MAX_HISTORY_ITEMS = 100; + private static readonly MAX_TEXT_RESULTS = 10000; private static readonly SHOW_REPLACE_STORAGE_KEY = 'vs.search.show.replace'; + private static readonly WIDE_CLASS_NAME = 'wide'; + private static readonly WIDE_VIEW_SIZE = 600; + private isDisposed: boolean; private queryBuilder: QueryBuilder; @@ -79,9 +84,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private inputPatternExclusionsFocused: IContextKey; private firstMatchFocused: IContextKey; private fileMatchOrMatchFocused: IContextKey; + private fileMatchOrFolderMatchFocus: IContextKey; private fileMatchFocused: IContextKey; private folderMatchFocused: IContextKey; private matchFocused: IContextKey; + private hasSearchResultsKey: IContextKey; + private searchSubmitted: boolean; private searching: boolean; @@ -91,7 +99,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private messages: Builder; private searchWidgetsContainer: Builder; private searchWidget: SearchWidget; - private size: Dimension; + private size: dom.Dimension; private queryDetails: HTMLElement; private inputPatternExcludes: ExcludePatternInputWidget; private inputPatternIncludes: PatternInputWidget; @@ -99,7 +107,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private currentSelectedFileMatch: FileMatch; - private selectCurrentMatchEmitter: Emitter; + private readonly selectCurrentMatchEmitter: Emitter; private delayedRefresh: Delayer; private changedWhileHidden: boolean; @@ -113,7 +121,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { @IEditorGroupService private editorGroupService: IEditorGroupService, @IProgressService private progressService: IProgressService, @INotificationService private notificationService: INotificationService, - @IConfirmationService private confirmationService: IConfirmationService, + @IDialogService private dialogService: IDialogService, @IStorageService private storageService: IStorageService, @IContextViewService private contextViewService: IContextViewService, @IInstantiationService private instantiationService: IInstantiationService, @@ -134,9 +142,11 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.inputPatternExclusionsFocused = Constants.PatternExcludesFocusedKey.bindTo(this.contextKeyService); this.firstMatchFocused = Constants.FirstMatchFocusKey.bindTo(contextKeyService); this.fileMatchOrMatchFocused = Constants.FileMatchOrMatchFocusKey.bindTo(contextKeyService); + this.fileMatchOrFolderMatchFocus = Constants.FileMatchOrFolderMatchFocusKey.bindTo(contextKeyService); this.fileMatchFocused = Constants.FileFocusKey.bindTo(contextKeyService); this.folderMatchFocused = Constants.FolderFocusKey.bindTo(contextKeyService); this.matchFocused = Constants.MatchFocusKey.bindTo(this.contextKeyService); + this.hasSearchResultsKey = Constants.HasSearchResults.bindTo(this.contextKeyService); this.queryBuilder = this.instantiationService.createInstance(QueryBuilder); this.viewletSettings = this.getMemento(storageService, Scope.WORKSPACE); @@ -158,12 +168,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { } } - public create(parent: Builder): TPromise { + public create(parent: HTMLElement): TPromise { super.create(parent); this.viewModel = this.searchWorkbenchService.searchModel; let builder: Builder; - parent.div({ + $(parent).div({ 'class': 'search-view' }, (div) => { builder = div; @@ -175,39 +185,69 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.createSearchWidget(this.searchWidgetsContainer); const filePatterns = this.viewletSettings['query.filePatterns'] || ''; - const patternExclusions = this.viewletSettings['query.folderExclusions'] || ''; - const patternExclusionsHistory = this.viewletSettings['query.folderExclusionsHistory'] || []; - const patternIncludes = this.viewletSettings['query.folderIncludes'] || ''; - const patternIncludesHistory = this.viewletSettings['query.folderIncludesHistory'] || []; + let patternExclusions = this.viewletSettings['query.folderExclusions'] || ''; + const patternExclusionsHistory: string[] = this.viewletSettings['query.folderExclusionsHistory'] || []; + let patternIncludes = this.viewletSettings['query.folderIncludes'] || ''; + let patternIncludesHistory: string[] = this.viewletSettings['query.folderIncludesHistory'] || []; const queryDetailsExpanded = this.viewletSettings['query.queryDetailsExpanded'] || ''; const useExcludesAndIgnoreFiles = typeof this.viewletSettings['query.useExcludesAndIgnoreFiles'] === 'boolean' ? this.viewletSettings['query.useExcludesAndIgnoreFiles'] : true; + // Transition history from 1.22 combined include+exclude, to split include/exclude histories + const patternIncludesHistoryWithoutExcludes: string[] = []; + const patternExcludesHistoryFromIncludes: string[] = []; + patternIncludesHistory.forEach(historyEntry => { + const includeExclude = this.queryBuilder.parseIncludeExcludePattern(historyEntry); + if (includeExclude.includePattern) { + patternIncludesHistoryWithoutExcludes.push(includeExclude.includePattern); + } + + if (includeExclude.excludePattern) { + patternExcludesHistoryFromIncludes.push(includeExclude.excludePattern); + } + }); + + patternIncludesHistory = patternIncludesHistoryWithoutExcludes; + patternExclusionsHistory.push(...patternExcludesHistoryFromIncludes); + + // Split combined include/exclude to split include/exclude boxes + const includeExclude = this.queryBuilder.parseIncludeExcludePattern(patternIncludes); + patternIncludes = includeExclude.includePattern || ''; + + if (includeExclude.excludePattern) { + if (patternExclusions) { + patternExclusions += ', ' + includeExclude.excludePattern; + } else { + patternExclusions = includeExclude.excludePattern; + } + } + this.queryDetails = this.searchWidgetsContainer.div({ 'class': ['query-details'] }, (builder) => { builder.div({ 'class': 'more', 'tabindex': 0, 'role': 'button', 'title': nls.localize('moreSearch', "Toggle Search Details") }) .on(dom.EventType.CLICK, (e) => { dom.EventHelper.stop(e); - this.toggleQueryDetails(true); + this.toggleQueryDetails(); }).on(dom.EventType.KEY_UP, (e: KeyboardEvent) => { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { dom.EventHelper.stop(e); - this.toggleQueryDetails(); + this.toggleQueryDetails(false); } }); //folder includes list - builder.div({ 'class': 'file-types' }, (builder) => { + builder.div({ 'class': 'file-types includes' }, (builder) => { let title = nls.localize('searchScope.includes', "files to include"); builder.element('h4', { text: title }); this.inputPatternIncludes = new PatternInputWidget(builder.getContainer(), this.contextViewService, this.themeService, { - ariaLabel: nls.localize('label.includes', 'Search Include Patterns') + ariaLabel: nls.localize('label.includes', 'Search Include Patterns'), + history: patternIncludesHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); this.inputPatternIncludes.setValue(patternIncludes); - this.inputPatternIncludes.setHistory(patternIncludesHistory); this.inputPatternIncludes .on(FindInput.OPTION_CHANGE, (e) => { @@ -220,17 +260,18 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { }); //pattern exclusion list - builder.div({ 'class': 'file-types' }, (builder) => { + builder.div({ 'class': 'file-types excludes' }, (builder) => { let title = nls.localize('searchScope.excludes', "files to exclude"); builder.element('h4', { text: title }); this.inputPatternExcludes = new ExcludePatternInputWidget(builder.getContainer(), this.contextViewService, this.themeService, { - ariaLabel: nls.localize('label.excludes', 'Search Exclude Patterns') + ariaLabel: nls.localize('label.excludes', 'Search Exclude Patterns'), + history: patternExclusionsHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); this.inputPatternExcludes.setValue(patternExclusions); this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(useExcludesAndIgnoreFiles); - this.inputPatternExcludes.setHistory(patternExclusionsHistory); this.inputPatternExcludes .on(FindInput.OPTION_CHANGE, (e) => { @@ -296,7 +337,8 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { isRegex: isRegex, isCaseSensitive: isCaseSensitive, isWholeWords: isWholeWords, - history: searchHistory + history: searchHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); if (this.storageService.getBoolean(SearchView.SHOW_REPLACE_STORAGE_KEY, StorageScope.WORKSPACE, true)) { @@ -400,8 +442,8 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { type: 'question' }; - this.confirmationService.confirm(confirmation).then(confirmed => { - if (confirmed) { + this.dialogService.confirm(confirmation).then(res => { + if (res.confirmed) { this.searchWidget.setReplaceAllActionState(false); this.viewModel.searchResult.replaceAll(progressRunner).then(() => { progressRunner.done(); @@ -506,6 +548,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { renderer: renderer, sorter: new SearchSorter(), filter: new SearchFilter(), + controller: this.instantiationService.createInstance(SearchTreeController), accessibilityProvider: this.instantiationService.createInstance(SearchAccessibilityProvider), dnd }, { @@ -539,10 +582,11 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { if (treeHasFocus) { const focus = e.focus; this.firstMatchFocused.set(this.tree.getNavigator().first() === focus); - this.fileMatchOrMatchFocused.set(true); + this.fileMatchOrMatchFocused.set(!!focus); this.fileMatchFocused.set(focus instanceof FileMatch); this.folderMatchFocused.set(focus instanceof FolderMatch); this.matchFocused.set(focus instanceof Match); + this.fileMatchOrFolderMatchFocus.set(focus instanceof FileMatch || focus instanceof FolderMatch); } })); @@ -553,9 +597,8 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.fileMatchFocused.reset(); this.folderMatchFocused.reset(); this.matchFocused.reset(); + this.fileMatchOrFolderMatchFocus.reset(); })); - - }); } @@ -771,6 +814,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { return; } + if (this.size.width >= SearchView.WIDE_VIEW_SIZE) { + dom.addClass(this.getContainer(), SearchView.WIDE_CLASS_NAME); + } else { + dom.removeClass(this.getContainer(), SearchView.WIDE_CLASS_NAME); + } + this.searchWidget.setWidth(this.size.width - 28 /* container margin */); this.inputPatternExcludes.setWidth(this.size.width - 28 /* container margin */); @@ -786,7 +835,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.tree.layout(searchResultContainerSize); } - public layout(dimension: Dimension): void { + public layout(dimension: dom.Dimension): void { this.size = dimension; this.reLayout(); } @@ -827,7 +876,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private selectTreeIfNotSelected(): void { if (this.tree.getInput()) { - this.tree.DOMFocus(); + this.tree.domFocus(); let selection = this.tree.getSelection(); if (selection.length === 0) { this.tree.focusNext(); @@ -894,7 +943,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.onQueryChanged(true, true); } - public toggleQueryDetails(moveFocus?: boolean, show?: boolean, skipLayout?: boolean, reverse?: boolean): void { + public toggleQueryDetails(moveFocus = true, show?: boolean, skipLayout?: boolean, reverse?: boolean): void { let cls = 'more'; show = typeof show === 'undefined' ? !dom.hasClass(this.queryDetails, cls) : Boolean(show); this.viewletSettings['query.queryDetailsExpanded'] = show; @@ -1297,6 +1346,8 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private updateSearchResultCount(): void { const fileCount = this.viewModel.searchResult.fileCount(); + this.hasSearchResultsKey.set(fileCount > 0); + const msgWasHidden = this.messages.isHidden(); if (fileCount > 0) { const div = this.clearMessage(); @@ -1454,6 +1505,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.updateTitleArea(); } + public clearHistory(): void { + this.searchWidget.clearHistory(); + this.inputPatternExcludes.clearHistory(); + this.inputPatternIncludes.clearHistory(); + } + public shutdown(): void { const isRegex = this.searchWidget.searchInput.getRegex(); const isWholeWords = this.searchWidget.searchInput.getWholeWords(); @@ -1516,16 +1573,16 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { const diffInsertedOutlineColor = theme.getColor(diffInsertedOutline); if (diffInsertedOutlineColor) { - collector.addRule(`.monaco-workbench .search-view .replaceMatch:not(:empty) { border: 1px dashed ${diffInsertedOutlineColor}; }`); + collector.addRule(`.monaco-workbench .search-view .replaceMatch:not(:empty) { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${diffInsertedOutlineColor}; }`); } const diffRemovedOutlineColor = theme.getColor(diffRemovedOutline); if (diffRemovedOutlineColor) { - collector.addRule(`.monaco-workbench .search-view .replace.findInFileMatch { border: 1px dashed ${diffRemovedOutlineColor}; }`); + collector.addRule(`.monaco-workbench .search-view .replace.findInFileMatch { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${diffRemovedOutlineColor}; }`); } const findMatchHighlightBorder = theme.getColor(editorFindMatchHighlightBorder); if (findMatchHighlightBorder) { - collector.addRule(`.monaco-workbench .search-view .findInFileMatch { border: 1px dashed ${findMatchHighlightBorder}; }`); + collector.addRule(`.monaco-workbench .search-view .findInFileMatch { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${findMatchHighlightBorder}; }`); } }); diff --git a/src/vs/workbench/parts/search/browser/searchViewLocationUpdater.ts b/src/vs/workbench/parts/search/browser/searchViewLocationUpdater.ts index 77423925c6..08d0d202c8 100644 --- a/src/vs/workbench/parts/search/browser/searchViewLocationUpdater.ts +++ b/src/vs/workbench/parts/search/browser/searchViewLocationUpdater.ts @@ -30,7 +30,6 @@ export class SearchViewLocationUpdater implements IWorkbenchContribution { configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('search.location')) { updateSearchViewLocation(); - } }); diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 1c18080906..b312f39b20 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -12,27 +12,26 @@ import { Action } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { FindInput, IFindInputOptions } from 'vs/base/browser/ui/findinput/findInput'; import { InputBox, IMessage } from 'vs/base/browser/ui/inputbox/inputBox'; -import { Button } from 'vs/base/browser/ui/button/button'; +import { Button, IButtonOptions } from 'vs/base/browser/ui/button/button'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ContextKeyExpr, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Builder } from 'vs/base/browser/builder'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { isSearchViewFocused, appendKeyBindingLabel } from 'vs/workbench/parts/search/browser/searchActions'; import { HistoryNavigator } from 'vs/base/common/history'; import * as Constants from 'vs/workbench/parts/search/common/constants'; -import { attachInputBoxStyler, attachFindInputBoxStyler, attachButtonStyler } from 'vs/platform/theme/common/styler'; +import { attachInputBoxStyler, attachFindInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { CONTEXT_FIND_WIDGET_NOT_VISIBLE } from 'vs/editor/contrib/find/findModel'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ISearchConfigurationProperties } from '../../../../platform/search/common/search'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { ISearchConfigurationProperties } from 'vs/platform/search/common/search'; export interface ISearchWidgetOptions { value?: string; @@ -40,6 +39,7 @@ export interface ISearchWidgetOptions { isCaseSensitive?: boolean; isWholeWords?: boolean; history?: string[]; + historyLimit?: number; } class ReplaceAllAction extends Action { @@ -100,22 +100,22 @@ export class SearchWidget extends Widget { private previousGlobalFindBufferValue: string; private _onSearchSubmit = this._register(new Emitter()); - public onSearchSubmit: Event = this._onSearchSubmit.event; + public readonly onSearchSubmit: Event = this._onSearchSubmit.event; private _onSearchCancel = this._register(new Emitter()); - public onSearchCancel: Event = this._onSearchCancel.event; + public readonly onSearchCancel: Event = this._onSearchCancel.event; private _onReplaceToggled = this._register(new Emitter()); - public onReplaceToggled: Event = this._onReplaceToggled.event; + public readonly onReplaceToggled: Event = this._onReplaceToggled.event; private _onReplaceStateChange = this._register(new Emitter()); - public onReplaceStateChange: Event = this._onReplaceStateChange.event; + public readonly onReplaceStateChange: Event = this._onReplaceStateChange.event; private _onReplaceValueChanged = this._register(new Emitter()); - public onReplaceValueChanged: Event = this._onReplaceValueChanged.event; + public readonly onReplaceValueChanged: Event = this._onReplaceValueChanged.event; private _onReplaceAll = this._register(new Emitter()); - public onReplaceAll: Event = this._onReplaceAll.event; + public readonly onReplaceAll: Event = this._onReplaceAll.event; constructor( container: Builder, @@ -128,7 +128,7 @@ export class SearchWidget extends Widget { @IConfigurationService private configurationService: IConfigurationService ) { super(); - this.searchHistory = new HistoryNavigator(options.history); + this.searchHistory = new HistoryNavigator(options.history, options.historyLimit); this.replaceActive = Constants.ReplaceActiveKey.bindTo(this.keyBindingService); this.searchInputBoxFocused = Constants.SearchInputBoxFocusedKey.bindTo(this.keyBindingService); this.replaceInputBoxFocused = Constants.ReplaceInputBoxFocusedKey.bindTo(this.keyBindingService); @@ -180,6 +180,10 @@ export class SearchWidget extends Widget { return this.searchHistory.getHistory(); } + public clearHistory(): void { + this.searchHistory.clear(); + } + public showNextSearchTerm() { let next = this.searchHistory.next(); if (next) { @@ -217,11 +221,13 @@ export class SearchWidget extends Widget { } private renderToggleReplaceButton(parent: HTMLElement): void { - this.toggleReplaceButton = this._register(new Button(parent)); - attachButtonStyler(this.toggleReplaceButton, this.themeService, { - buttonBackground: SIDE_BAR_BACKGROUND, - buttonHoverBackground: SIDE_BAR_BACKGROUND - }); + const opts: IButtonOptions = { + buttonBackground: null, + buttonBorder: null, + buttonForeground: null, + buttonHoverBackground: null + }; + this.toggleReplaceButton = this._register(new Button(parent, opts)); this.toggleReplaceButton.icon = 'toggle-replace-button collapse'; // TODO@joh need to dispose this listener eventually this.toggleReplaceButton.onDidClick(() => this.onToggleReplaceButton()); diff --git a/src/vs/workbench/parts/search/common/constants.ts b/src/vs/workbench/parts/search/common/constants.ts index f56e930107..8836b86cfb 100644 --- a/src/vs/workbench/parts/search/common/constants.ts +++ b/src/vs/workbench/parts/search/common/constants.ts @@ -12,6 +12,10 @@ export const FocusSearchFromResults = 'search.action.focusSearchFromResults'; export const OpenMatchToSide = 'search.action.openResultToSide'; export const CancelActionId = 'search.action.cancel'; export const RemoveActionId = 'search.action.remove'; +export const CopyPathCommandId = 'search.action.copyPath'; +export const CopyMatchCommandId = 'search.action.copyMatch'; +export const CopyAllCommandId = 'search.action.copyAll'; +export const ClearSearchHistoryCommandId = 'search.action.clearHistory'; export const ReplaceActionId = 'search.action.replace'; export const ReplaceAllInFileActionId = 'search.action.replaceAllInFile'; export const ReplaceAllInFolderActionId = 'search.action.replaceAllInFolder'; @@ -20,6 +24,8 @@ export const ToggleCaseSensitiveCommandId = 'toggleSearchCaseSensitive'; export const ToggleWholeWordCommandId = 'toggleSearchWholeWord'; export const ToggleRegexCommandId = 'toggleSearchRegex'; +export const ToggleSearchViewPositionCommandId = 'search.action.toggleSearchViewPosition'; + export const SearchViewVisibleKey = new RawContextKey('searchViewletVisible', true); export const InputBoxFocusedKey = new RawContextKey('inputBoxFocus', false); export const SearchInputBoxFocusedKey = new RawContextKey('searchInputBoxFocus', false); @@ -27,9 +33,11 @@ export const ReplaceInputBoxFocusedKey = new RawContextKey('replaceInpu export const PatternIncludesFocusedKey = new RawContextKey('patternIncludesInputBoxFocus', false); export const PatternExcludesFocusedKey = new RawContextKey('patternExcludesInputBoxFocus', false); export const ReplaceActiveKey = new RawContextKey('replaceActive', false); +export const HasSearchResults = new RawContextKey('hasSearchResult', false); export const FirstMatchFocusKey = new RawContextKey('firstMatchFocus', false); -export const FileMatchOrMatchFocusKey = new RawContextKey('fileMatchOrMatchFocus', false); +export const FileMatchOrMatchFocusKey = new RawContextKey('fileMatchOrMatchFocus', false); // This is actually, Match or File or Folder +export const FileMatchOrFolderMatchFocusKey = new RawContextKey('fileMatchOrFolderMatchFocus', false); export const FileFocusKey = new RawContextKey('fileMatchFocus', false); export const FolderFocusKey = new RawContextKey('folderMatchFocus', false); export const MatchFocusKey = new RawContextKey('matchFocus', false); diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index c69028835d..0ac0422dc3 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as arrays from 'vs/base/common/arrays'; import * as objects from 'vs/base/common/objects'; import * as collections from 'vs/base/common/collections'; @@ -182,6 +182,28 @@ export class QueryBuilder { return Object.keys(excludeExpression).length ? excludeExpression : undefined; } + /** + * A helper that splits positive and negative patterns from a string that combines both. + */ + public parseIncludeExcludePattern(pattern: string): { includePattern?: string, excludePattern?: string } { + const grouped = collections.groupBy( + splitGlobPattern(pattern), + s => strings.startsWith(s, '!') ? 'excludePattern' : 'includePattern'); + + const result = {}; + if (grouped.includePattern) { + result['includePattern'] = grouped.includePattern.join(', '); + } + + if (grouped.excludePattern) { + result['excludePattern'] = grouped.excludePattern + .map(s => strings.ltrim(s, '!')) + .join(', '); + } + + return result; + } + private mergeExcludesFromFolderQueries(folderQueries: IFolderQuery[]): glob.IExpression | undefined { const mergedExcludes = folderQueries.reduce((merged: glob.IExpression, fq: IFolderQuery) => { if (fq.excludePattern) { diff --git a/src/vs/workbench/parts/search/common/searchModel.ts b/src/vs/workbench/parts/search/common/searchModel.ts index 745ee2e77a..d157168fd1 100644 --- a/src/vs/workbench/parts/search/common/searchModel.ts +++ b/src/vs/workbench/parts/search/common/searchModel.ts @@ -3,15 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import objects = require('vs/base/common/objects'); -import strings = require('vs/base/common/strings'); -import errors = require('vs/base/common/errors'); +import * as objects from 'vs/base/common/objects'; +import * as strings from 'vs/base/common/strings'; +import * as errors from 'vs/base/common/errors'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { TPromise, PPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { values, ResourceMap, TernarySearchTree } from 'vs/base/common/map'; -import Event, { Emitter, fromPromise, stopwatch, anyEvent } from 'vs/base/common/event'; +import { Event, Emitter, fromPromise, stopwatch, anyEvent } from 'vs/base/common/event'; import { ISearchService, ISearchProgressItem, ISearchComplete, ISearchQuery, IPatternInfo, IFileMatch } from 'vs/platform/search/common/search'; import { ReplacePattern } from 'vs/platform/search/common/replace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -95,6 +95,7 @@ export class FileMatch extends Disposable { private static readonly _CURRENT_FIND_MATCH = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + zIndex: 13, className: 'currentFindMatch', overviewRuler: { color: themeColorFromId(overviewRulerFindMatchForeground), @@ -118,10 +119,10 @@ export class FileMatch extends Disposable { } private _onChange = this._register(new Emitter()); - public onChange: Event = this._onChange.event; + public readonly onChange: Event = this._onChange.event; private _onDispose = this._register(new Emitter()); - public onDispose: Event = this._onDispose.event; + public readonly onDispose: Event = this._onDispose.event; private _resource: URI; private _model: ITextModel; @@ -338,10 +339,10 @@ export interface IChangeEvent { export class FolderMatch extends Disposable { private _onChange = this._register(new Emitter()); - public onChange: Event = this._onChange.event; + public readonly onChange: Event = this._onChange.event; private _onDispose = this._register(new Emitter()); - public onDispose: Event = this._onDispose.event; + public readonly onDispose: Event = this._onDispose.event; private _fileMatches: ResourceMap; private _unDisposedFileMatches: ResourceMap; @@ -499,7 +500,7 @@ export class FolderMatch extends Disposable { export class SearchResult extends Disposable { private _onChange = this._register(new Emitter()); - public onChange: Event = this._onChange.event; + public readonly onChange: Event = this._onChange.event; private _folderMatches: FolderMatch[] = []; private _folderMatchesMap: TernarySearchTree = TernarySearchTree.forPaths(); @@ -578,7 +579,7 @@ export class SearchResult extends Disposable { const onDone = stopwatch(fromPromise(promise)); /* __GDPR__ "replaceAll.started" : { - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ onDone(duration => this.telemetryService.publicLog('replaceAll.started', { duration })); @@ -682,12 +683,12 @@ export class SearchModel extends Disposable { private _replaceString: string = null; private _replacePattern: ReplacePattern = null; - private _onReplaceTermChanged: Emitter = this._register(new Emitter()); - public onReplaceTermChanged: Event = this._onReplaceTermChanged.event; + private readonly _onReplaceTermChanged: Emitter = this._register(new Emitter()); + public readonly onReplaceTermChanged: Event = this._onReplaceTermChanged.event; private currentRequest: PPromise; - constructor( @ISearchService private searchService: ISearchService, @ITelemetryService private telemetryService: ITelemetryService, @IInstantiationService private instantiationService: IInstantiationService) { + constructor(@ISearchService private searchService: ISearchService, @ITelemetryService private telemetryService: ITelemetryService, @IInstantiationService private instantiationService: IInstantiationService) { super(); this._searchResult = this.instantiationService.createInstance(SearchResult, this); } @@ -736,7 +737,7 @@ export class SearchModel extends Disposable { const onFirstRenderStopwatch = stopwatch(onFirstRender); /* __GDPR__ "searchResultsFirstRender" : { - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ onFirstRenderStopwatch(duration => this.telemetryService.publicLog('searchResultsFirstRender', { duration })); @@ -746,7 +747,7 @@ export class SearchModel extends Disposable { /* __GDPR__ "searchResultsFinished" : { - "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ onDoneStopwatch(duration => this.telemetryService.publicLog('searchResultsFinished', { duration })); @@ -775,11 +776,11 @@ export class SearchModel extends Disposable { delete options.pattern; /* __GDPR__ "searchResultsShown" : { - "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "fileCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "fileCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "options": { "${inline}": [ "${IPatternInfo}" ] }, - "duration": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "useRipgrep": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "duration": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "useRipgrep": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('searchResultsShown', { @@ -829,7 +830,7 @@ export class SearchWorkbenchService implements ISearchWorkbenchService { _serviceBrand: any; private _searchModel: SearchModel; - constructor( @IInstantiationService private instantiationService: IInstantiationService) { + constructor(@IInstantiationService private instantiationService: IInstantiationService) { } get searchModel(): SearchModel { diff --git a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts index 01ceedfcb8..44a17ff0cf 100644 --- a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts @@ -10,13 +10,13 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import { ExplorerFolderContext, ExplorerRootContext } from 'vs/workbench/parts/files/common/files'; -import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; +import { SyncActionDescriptor, MenuRegistry, MenuId, ICommandAction } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions as QuickOpenExtensions } from 'vs/workbench/browser/quickopen'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -53,16 +53,19 @@ import { getMultiSelectedResources } from 'vs/workbench/parts/files/browser/file import { Schemas } from 'vs/base/common/network'; import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowNextSearchExcludeAction, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, ShowPreviousSearchExcludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction } from 'vs/workbench/parts/search/browser/searchActions'; -import { VIEW_ID } from 'vs/platform/search/common/search'; +import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand, copyMatchCommand, copyAllCommand, ShowNextSearchExcludeAction, ShowPreviousSearchExcludeAction, clearHistoryCommand } from 'vs/workbench/parts/search/browser/searchActions'; +import { VIEW_ID, ISearchConfigurationProperties } from 'vs/platform/search/common/search'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { SearchViewLocationUpdater } from 'vs/workbench/parts/search/browser/searchViewLocationUpdater'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService); replaceContributions(); searchWidgetContributions(); +const category = nls.localize('search', "Search"); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'workbench.action.search.toggleQueryDetails', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), @@ -142,7 +145,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: Constants.ReplaceAllInFileActionId, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, Constants.FileFocusKey), - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter, + primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.KEY_1, + secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter], handler: (accessor, args: any) => { const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService)); const tree: ITree = searchView.getControl(); @@ -154,7 +158,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: Constants.ReplaceAllInFolderActionId, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, Constants.FolderFocusKey), - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter, + primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.KEY_1, + secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter], handler: (accessor, args: any) => { const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService)); const tree: ITree = searchView.getControl(); @@ -192,6 +197,138 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.ReplaceActionId, + title: ReplaceAction.LABEL + }, + when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.MatchFocusKey), + group: 'search', + order: 1 +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.ReplaceAllInFolderActionId, + title: ReplaceAllInFolderAction.LABEL + }, + when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.FolderFocusKey), + group: 'search', + order: 1 +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.ReplaceAllInFileActionId, + title: ReplaceAllAction.LABEL + }, + when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.FileFocusKey), + group: 'search', + order: 1 +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.RemoveActionId, + title: RemoveAction.LABEL + }, + when: Constants.FileMatchOrMatchFocusKey, + group: 'search', + order: 2 +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: Constants.CopyMatchCommandId, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), + when: Constants.FileMatchOrMatchFocusKey, + primary: KeyMod.CtrlCmd | KeyCode.KEY_C, + handler: copyMatchCommand +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.CopyMatchCommandId, + title: nls.localize('copyMatchLabel', "Copy") + }, + when: Constants.FileMatchOrMatchFocusKey, + group: 'search_2', + order: 1 +}); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: Constants.CopyPathCommandId, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), + when: Constants.FileMatchOrFolderMatchFocusKey, + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C, + win: { + primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_C + }, + handler: copyPathCommand +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.CopyPathCommandId, + title: nls.localize('copyPathLabel', "Copy Path") + }, + when: Constants.FileMatchOrFolderMatchFocusKey, + group: 'search_2', + order: 2 +}); + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: { + id: Constants.CopyAllCommandId, + title: nls.localize('copyAllLabel', "Copy All") + }, + when: Constants.HasSearchResults, + group: 'search_2', + order: 3 +}); + +CommandsRegistry.registerCommand({ + id: Constants.CopyAllCommandId, + handler: copyAllCommand +}); + +CommandsRegistry.registerCommand({ + id: Constants.ClearSearchHistoryCommandId, + handler: clearHistoryCommand +}); + +const clearSearchHistoryLabel = nls.localize('clearSearchHistoryLabel', "Clear Search History"); +const ClearSearchHistoryCommand: ICommandAction = { + id: Constants.ClearSearchHistoryCommandId, + title: clearSearchHistoryLabel, + category +}; +MenuRegistry.addCommand(ClearSearchHistoryCommand); + +CommandsRegistry.registerCommand({ + id: Constants.ToggleSearchViewPositionCommandId, + handler: (accessor) => { + const configurationService = accessor.get(IConfigurationService); + const currentValue = configurationService.getValue('search').location; + const toggleValue = currentValue === 'sidebar' ? 'panel' : 'sidebar'; + + configurationService.updateValue('search.location', toggleValue); + } +}); + +const toggleSearchViewPositionLabel = nls.localize('toggleSearchViewPositionLabel', "Toggle Search View Position"); +const ToggleSearchViewPositionCommand: ICommandAction = { + id: Constants.ToggleSearchViewPositionCommandId, + title: toggleSearchViewPositionLabel, + category +}; +MenuRegistry.addCommand(ToggleSearchViewPositionCommand); +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: ToggleSearchViewPositionCommand, + when: Constants.SearchViewVisibleKey, + group: 'search_9', + order: 1 +}); + const FIND_IN_FOLDER_ID = 'filesExplorer.findInFolder'; CommandsRegistry.registerCommand({ id: FIND_IN_FOLDER_ID, @@ -222,6 +359,13 @@ CommandsRegistry.registerCommand({ } }); +CommandsRegistry.registerCommand({ + id: ClearSearchResultsAction.ID, + handler: (accessor, args: any) => { + accessor.get(IInstantiationService).createInstance(ClearSearchResultsAction, ClearSearchResultsAction.ID, '').run(); + } +}); + const FIND_IN_WORKSPACE_ID = 'filesExplorer.findInWorkspace'; CommandsRegistry.registerCommand({ id: FIND_IN_WORKSPACE_ID, @@ -289,7 +433,7 @@ Registry.as(ViewletExtensions.Viewlets).registerViewlet(new Vie VIEW_ID, nls.localize('name', "Search"), 'search', - 10 + 1 )); Registry.as(PanelExtensions.Panels).registerPanel(new PanelDescriptor( @@ -305,7 +449,6 @@ Registry.as(WorkbenchExtensions.Workbench).regi // Actions const registry = Registry.as(ActionExtensions.WorkbenchActions); -const category = nls.localize('search', "Search"); registry.registerWorkbenchAction(new SyncActionDescriptor(FindInFilesAction, VIEW_ID, nls.localize('showSearchViewl', "Show Search"), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F }, Constants.SearchViewVisibleKey.toNegated()), 'View: Show Search', nls.localize('view', "View")); @@ -320,8 +463,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F }); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextSearchResultAction, FocusNextSearchResultAction.ID, FocusNextSearchResultAction.LABEL, { primary: KeyCode.F4 }), 'Focus Next Search Result', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousSearchResultAction, FocusPreviousSearchResultAction.ID, FocusPreviousSearchResultAction.LABEL, { primary: KeyMod.Shift | KeyCode.F4 }), 'Focus Previous Search Result', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextSearchResultAction, FocusNextSearchResultAction.ID, FocusNextSearchResultAction.LABEL, { primary: KeyCode.F4 }, ContextKeyExpr.and(Constants.HasSearchResults)), 'Focus Next Search Result', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousSearchResultAction, FocusPreviousSearchResultAction.ID, FocusPreviousSearchResultAction.LABEL, { primary: KeyMod.Shift | KeyCode.F4 }, ContextKeyExpr.and(Constants.HasSearchResults)), 'Focus Previous Search Result', category); registry.registerWorkbenchAction(new SyncActionDescriptor(ReplaceInFilesAction, ReplaceInFilesAction.ID, ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H }), 'Replace in Files', category); @@ -347,14 +490,14 @@ KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({ }, ToggleRegexKeybinding)); // Terms navigation actions -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchTermAction, ShowNextSearchTermAction.ID, ShowNextSearchTermAction.LABEL, ShowNextFindTermKeybinding, ShowNextSearchTermAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Next Search Term', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchTermAction, ShowPreviousSearchTermAction.ID, ShowPreviousSearchTermAction.LABEL, ShowPreviousFindTermKeybinding, ShowPreviousSearchTermAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Previous Search Term', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchTermAction, ShowNextSearchTermAction.ID, ShowNextSearchTermAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey)), 'Search: Show Next Search Term', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchTermAction, ShowPreviousSearchTermAction.ID, ShowPreviousSearchTermAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey)), 'Search: Show Previous Search Term', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchIncludeAction, ShowNextSearchIncludeAction.ID, ShowNextSearchIncludeAction.LABEL, ShowNextFindTermKeybinding, ShowNextSearchIncludeAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Next Search Include Pattern', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchIncludeAction, ShowPreviousSearchIncludeAction.ID, ShowPreviousSearchIncludeAction.LABEL, ShowPreviousFindTermKeybinding, ShowPreviousSearchIncludeAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Previous Search Include Pattern', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchIncludeAction, ShowNextSearchIncludeAction.ID, ShowNextSearchIncludeAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey)), 'Search: Show Next Search Include Pattern', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchIncludeAction, ShowPreviousSearchIncludeAction.ID, ShowPreviousSearchIncludeAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey)), 'Search: Show Previous Search Include Pattern', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchExcludeAction, ShowNextSearchExcludeAction.ID, ShowNextSearchExcludeAction.LABEL, ShowNextFindTermKeybinding, ShowNextSearchExcludeAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Next Search Exclude Pattern', category); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchExcludeAction, ShowPreviousSearchExcludeAction.ID, ShowPreviousSearchExcludeAction.LABEL, ShowPreviousFindTermKeybinding, ShowPreviousSearchExcludeAction.CONTEXT_KEY_EXPRESSION), 'Search: Show Previous Search Exclude Pattern', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchExcludeAction, ShowNextSearchExcludeAction.ID, ShowNextSearchExcludeAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternExcludesFocusedKey)), 'Search: Show Next Search Exclude Pattern', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchExcludeAction, ShowPreviousSearchExcludeAction.ID, ShowPreviousSearchExcludeAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternExcludesFocusedKey)), 'Search: Show Previous Search Exclude Pattern', category); registry.registerWorkbenchAction(new SyncActionDescriptor(CollapseDeepestExpandedLevelAction, CollapseDeepestExpandedLevelAction.ID, CollapseDeepestExpandedLevelAction.LABEL), 'Search: Collapse All', category); @@ -456,7 +599,7 @@ configurationRegistry.registerConfiguration({ 'search.location': { enum: ['sidebar', 'panel'], default: 'sidebar', - description: nls.localize('search.location', "Preview: controls if the search will be shown as a view in the sidebar or as a panel in the panel area for more horizontal space. Next release search in panel will have improved horizontal layout and this will no longer be a preview."), + description: nls.localize('search.location', "Controls if the search will be shown as a view in the sidebar or as a panel in the panel area for more horizontal space. Next release search in panel will have improved horizontal layout and this will no longer be a preview."), }, } }); diff --git a/src/vs/workbench/parts/search/test/browser/searchActions.test.ts b/src/vs/workbench/parts/search/test/browser/searchActions.test.ts index 283f07cad2..046e6e7634 100644 --- a/src/vs/workbench/parts/search/test/browser/searchActions.test.ts +++ b/src/vs/workbench/parts/search/test/browser/searchActions.test.ts @@ -35,7 +35,7 @@ suite('Search Actions', () => { counter = 0; }); - test('get next element to focus after removing a match when it has next sibling match', function () { + test('get next element to focus after removing a match when it has next sibling file', function () { let fileMatch1 = aFileMatch(); let fileMatch2 = aFileMatch(); let data = [fileMatch1, aMatch(fileMatch1), aMatch(fileMatch1), fileMatch2, aMatch(fileMatch2), aMatch(fileMatch2)]; @@ -45,7 +45,7 @@ suite('Search Actions', () => { let actual = testObject.getElementToFocusAfterRemoved(tree, target); - assert.equal(data[3], actual); + assert.equal(data[4], actual); }); test('get next element to focus after removing a match when it does not have next sibling match', function () { diff --git a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts index 324290588f..2cd6f32d9d 100644 --- a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts +++ b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts @@ -697,6 +697,51 @@ suite('QueryBuilder', () => { assert(query.sortByScore); }); }); + + suite('parseIncludeExcludePattern', () => { + test('nothing', () => { + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern(''), + {}); + }); + + test('includes', () => { + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern('src'), + { + includePattern: 'src' + }); + + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern('src, test'), + { + includePattern: 'src, test' + }); + }); + + test('excludes', () => { + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern('!src'), + { + excludePattern: 'src' + }); + + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern('!src, !test'), + { + excludePattern: 'src, test' + }); + }); + + test('includes and excludes', () => { + assert.deepEqual( + queryBuilder.parseIncludeExcludePattern('!src, test, !foo, bar'), + { + includePattern: 'test, bar', + excludePattern: 'src, foo' + }); + }); + }); }); function assertEqualQueries(actual: ISearchQuery, expected: ISearchQuery): void { diff --git a/src/vs/workbench/parts/search/test/common/searchModel.test.ts b/src/vs/workbench/parts/search/test/common/searchModel.test.ts index 35f2b481a9..6c6ee99056 100644 --- a/src/vs/workbench/parts/search/test/common/searchModel.test.ts +++ b/src/vs/workbench/parts/search/test/common/searchModel.test.ts @@ -19,6 +19,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; +import { timeout } from 'vs/base/common/async'; const nullEvent = new class { @@ -101,7 +102,7 @@ suite('SearchModel', () => { assert.ok(new Range(2, 1, 2, 2).equalsRange(actuaMatches[0].range())); }); - test('Search Model: Search adds to results during progress', function (done) { + test('Search Model: Search adds to results during progress', function () { let results = [aRawMatch('file://c:/1', aLineMatch('preview 1', 1, [[1, 3], [4, 7]])), aRawMatch('file://c:/2', aLineMatch('preview 2'))]; let promise = new DeferredPPromise(); instantiationService.stub(ISearchService, 'search', promise); @@ -113,7 +114,7 @@ suite('SearchModel', () => { promise.progress(results[1]); promise.complete({ results: [], stats: testSearchStats }); - result.done(() => { + return result.then(() => { let actual = testObject.searchResult.matches(); assert.equal(2, actual.length); @@ -130,8 +131,6 @@ suite('SearchModel', () => { assert.equal(1, actuaMatches.length); assert.equal('preview 2', actuaMatches[0].text()); assert.ok(new Range(2, 1, 2, 2).equalsRange(actuaMatches[0].range())); - - done(); }); }); @@ -149,7 +148,7 @@ suite('SearchModel', () => { assert.deepEqual(['searchResultsShown', { count: 3, fileCount: 2, options: {}, duration: -1, useRipgrep: undefined }], data); }); - test('Search Model: Search reports timed telemetry on search when progress is not called', function (done) { + test('Search Model: Search reports timed telemetry on search when progress is not called', function () { let target2 = sinon.spy(); stub(nullEvent, 'stop', target2); let target1 = sinon.stub().returns(nullEvent); @@ -160,17 +159,16 @@ suite('SearchModel', () => { let testObject = instantiationService.createInstance(SearchModel); const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: 1, folderQueries }); - setTimeout(() => { - result.done(() => { + return timeout(1).then(() => { + return result.then(() => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); - - done(); }); - }, 0); + + }); }); - test('Search Model: Search reports timed telemetry on search when progress is called', function (done) { + test('Search Model: Search reports timed telemetry on search when progress is called', function () { let target2 = sinon.spy(); stub(nullEvent, 'stop', target2); let target1 = sinon.stub().returns(nullEvent); @@ -185,18 +183,16 @@ suite('SearchModel', () => { promise.progress(aRawMatch('file://c:/1', aLineMatch('some preview'))); promise.complete({ results: [], stats: testSearchStats }); - setTimeout(() => { - result.done(() => { + return timeout(1).then(() => { + return result.then(() => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); // assert.equal(1, target2.callCount); - - done(); }); - }, 0); + }); }); - test('Search Model: Search reports timed telemetry on search when error is called', function (done) { + test('Search Model: Search reports timed telemetry on search when error is called', function () { let target2 = sinon.spy(); stub(nullEvent, 'stop', target2); let target1 = sinon.stub().returns(nullEvent); @@ -210,18 +206,16 @@ suite('SearchModel', () => { promise.error('error'); - setTimeout(() => { - result.done(() => { }, () => { + return timeout(1).then(() => { + return result.then(() => { }, () => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); // assert.ok(target2.calledOnce); - - done(); }); - }, 0); + }); }); - test('Search Model: Search reports timed telemetry on search when error is cancelled error', function (done) { + test('Search Model: Search reports timed telemetry on search when error is cancelled error', function () { let target2 = sinon.spy(); stub(nullEvent, 'stop', target2); let target1 = sinon.stub().returns(nullEvent); @@ -235,14 +229,13 @@ suite('SearchModel', () => { promise.cancel(); - setTimeout(() => { - result.done(() => { }, () => { + return timeout(1).then(() => { + return result.then(() => { }, () => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); // assert.ok(target2.calledOnce); - done(); }); - }, 0); + }); }); test('Search Model: Search results are cleared during search', function () { diff --git a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts index a5147e582f..280067a621 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/tabCompletion.ts @@ -144,7 +144,7 @@ registerEditorCommand(new TabCompletionCommand({ kbOpts: { weight: KeybindingsRegistry.WEIGHT.editorContrib(), kbExpr: ContextKeyExpr.and( - EditorContextKeys.textFocus, + EditorContextKeys.editorTextFocus, EditorContextKeys.tabDoesNotMoveFocus, SnippetController2.InSnippetMode.toNegated() ), diff --git a/src/vs/workbench/parts/stats/node/workspaceStats.ts b/src/vs/workbench/parts/stats/node/workspaceStats.ts index 4bcb71f623..831d8ccf0b 100644 --- a/src/vs/workbench/parts/stats/node/workspaceStats.ts +++ b/src/vs/workbench/parts/stats/node/workspaceStats.ts @@ -9,7 +9,7 @@ import * as crypto from 'crypto'; import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; -import { IFileService, IFileStat } from 'vs/platform/files/common/files'; +import { IFileService, IFileStat, IResolveFileResult } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -37,6 +37,26 @@ const SecondLevelDomainWhitelist = [ 'rhcloud.com', 'google.com' ]; +const ModulesToLookFor = [ + // Packages that suggest a node server + 'express', + 'sails', + 'koa', + 'hapi', + 'socket.io', + 'restify', + // JS frameworks + 'react', + 'react-native', + '@angular/core', + 'vue', + // Other interesting packages + 'aws-sdk', + 'azure', + 'azure-storage', + '@google-cloud/common', + 'heroku-cli' +]; type Tags = { [index: string]: boolean | number | string }; @@ -165,34 +185,48 @@ export class WorkspaceStats implements IWorkbenchContribution { /* __GDPR__FRAGMENT__ "WorkspaceTags" : { - "workbench.filesToOpen" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workbench.filesToCreate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workbench.filesToDiff" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "workspace.id" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.roots" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.empty" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.grunt" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.gulp" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.jake" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.tsconfig" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.jsconfig" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.config.xml" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.vsc.extension" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.ASP5" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.sln" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.unity" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.npm" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.bower" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.yeoman.code.ext" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.cordova.high" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.cordova.low" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.xamarin.android" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.xamarin.ios" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.android.cpp" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "workspace.reactNative" : { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "workbench.filesToOpen" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToCreate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workbench.filesToDiff" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "workspace.roots" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.empty" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.grunt" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.gulp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.jake" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.tsconfig" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.jsconfig" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.config.xml" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.vsc.extension" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.asp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.sln" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.unity" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.express" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.sails" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.koa" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.hapi" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.socket.io" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.restify" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.react" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.@angular/core" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.vue" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.aws-sdk" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.azure" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.azure-storage" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.@google-cloud/common" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.npm.heroku-cli" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.bower" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.yeoman.code.ext" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.cordova.high" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.cordova.low" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.xamarin.android" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.xamarin.ios" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.android.cpp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "workspace.reactNative" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ - private getWorkspaceTags(configuration: IWindowConfiguration): TPromise { + private async getWorkspaceTags(configuration: IWindowConfiguration): TPromise { const tags: Tags = Object.create(null); const state = this.contextService.getWorkbenchState(); @@ -223,89 +257,87 @@ export class WorkspaceStats implements IWorkbenchContribution { const folders = !isEmpty ? workspace.folders.map(folder => folder.uri) : this.environmentService.appQuality !== 'stable' && this.findFolders(configuration); if (folders && folders.length && this.fileService) { - return this.fileService.resolveFiles(folders.map(resource => ({ resource }))).then(results => { - const names = ([]).concat(...results.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); - const nameSet = names.reduce((s, n) => s.add(n.toLowerCase()), new Set()); + //return + const files: IResolveFileResult[] = await this.fileService.resolveFiles(folders.map(resource => ({ resource }))); + const names = ([]).concat(...files.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); + const nameSet = names.reduce((s, n) => s.add(n.toLowerCase()), new Set()); - tags['workspace.grunt'] = nameSet.has('gruntfile.js'); - tags['workspace.gulp'] = nameSet.has('gulpfile.js'); - tags['workspace.jake'] = nameSet.has('jakefile.js'); + tags['workspace.grunt'] = nameSet.has('gruntfile.js'); + tags['workspace.gulp'] = nameSet.has('gulpfile.js'); + tags['workspace.jake'] = nameSet.has('jakefile.js'); - tags['workspace.tsconfig'] = nameSet.has('tsconfig.json'); - tags['workspace.jsconfig'] = nameSet.has('jsconfig.json'); - tags['workspace.config.xml'] = nameSet.has('config.xml'); - tags['workspace.vsc.extension'] = nameSet.has('vsc-extension-quickstart.md'); + tags['workspace.tsconfig'] = nameSet.has('tsconfig.json'); + tags['workspace.jsconfig'] = nameSet.has('jsconfig.json'); + tags['workspace.config.xml'] = nameSet.has('config.xml'); + tags['workspace.vsc.extension'] = nameSet.has('vsc-extension-quickstart.md'); - tags['workspace.ASP5'] = nameSet.has('project.json') && this.searchArray(names, /^.+\.cs$/i); - tags['workspace.sln'] = this.searchArray(names, /^.+\.sln$|^.+\.csproj$/i); - tags['workspace.unity'] = nameSet.has('assets') && nameSet.has('library') && nameSet.has('projectsettings'); - tags['workspace.npm'] = nameSet.has('package.json') || nameSet.has('node_modules'); - tags['workspace.bower'] = nameSet.has('bower.json') || nameSet.has('bower_components'); + tags['workspace.ASP5'] = nameSet.has('project.json') && this.searchArray(names, /^.+\.cs$/i); + tags['workspace.sln'] = this.searchArray(names, /^.+\.sln$|^.+\.csproj$/i); + tags['workspace.unity'] = nameSet.has('assets') && nameSet.has('library') && nameSet.has('projectsettings'); + tags['workspace.npm'] = nameSet.has('package.json') || nameSet.has('node_modules'); + tags['workspace.bower'] = nameSet.has('bower.json') || nameSet.has('bower_components'); - tags['workspace.yeoman.code.ext'] = nameSet.has('vsc-extension-quickstart.md'); + tags['workspace.yeoman.code.ext'] = nameSet.has('vsc-extension-quickstart.md'); - let mainActivity = nameSet.has('mainactivity.cs') || nameSet.has('mainactivity.fs'); - let appDelegate = nameSet.has('appdelegate.cs') || nameSet.has('appdelegate.fs'); - let androidManifest = nameSet.has('androidmanifest.xml'); + let mainActivity = nameSet.has('mainactivity.cs') || nameSet.has('mainactivity.fs'); + let appDelegate = nameSet.has('appdelegate.cs') || nameSet.has('appdelegate.fs'); + let androidManifest = nameSet.has('androidmanifest.xml'); - let platforms = nameSet.has('platforms'); - let plugins = nameSet.has('plugins'); - let www = nameSet.has('www'); - let properties = nameSet.has('properties'); - let resources = nameSet.has('resources'); - let jni = nameSet.has('jni'); + let platforms = nameSet.has('platforms'); + let plugins = nameSet.has('plugins'); + let www = nameSet.has('www'); + let properties = nameSet.has('properties'); + let resources = nameSet.has('resources'); + let jni = nameSet.has('jni'); - if (tags['workspace.config.xml'] && - !tags['workspace.language.cs'] && !tags['workspace.language.vb'] && !tags['workspace.language.aspx']) { - if (platforms && plugins && www) { - tags['workspace.cordova.high'] = true; - } else { - tags['workspace.cordova.low'] = true; - } + if (tags['workspace.config.xml'] && + !tags['workspace.language.cs'] && !tags['workspace.language.vb'] && !tags['workspace.language.aspx']) { + if (platforms && plugins && www) { + tags['workspace.cordova.high'] = true; + } else { + tags['workspace.cordova.low'] = true; } + } - if (mainActivity && properties && resources) { - tags['workspace.xamarin.android'] = true; - } + if (mainActivity && properties && resources) { + tags['workspace.xamarin.android'] = true; + } - if (appDelegate && resources) { - tags['workspace.xamarin.ios'] = true; - } + if (appDelegate && resources) { + tags['workspace.xamarin.ios'] = true; + } - if (androidManifest && jni) { - tags['workspace.android.cpp'] = true; - } - - if (nameSet.has('package.json')) { - return TPromise.join(folders.map(workspaceUri => { - const uri = workspaceUri.with({ path: `${workspaceUri.path !== '/' ? workspaceUri.path : ''}/package.json` }); - return this.fileService.resolveFile(uri).then(stats => { - return this.fileService.resolveContent(uri, { acceptTextOnly: true }).then( - content => { - try { - const packageJsonContents = JSON.parse(content.value); - return !!(packageJsonContents['dependencies'] && packageJsonContents['dependencies']['react-native']); - } catch (e) { + if (androidManifest && jni) { + tags['workspace.android.cpp'] = true; + } + if (nameSet.has('package.json')) { + await TPromise.join(folders.map(async workspaceUri => { + const uri = workspaceUri.with({ path: `${workspaceUri.path !== '/' ? workspaceUri.path : ''}/package.json` }); + try { + const content = await this.fileService.resolveContent(uri, { acceptTextOnly: true }); + const packageJsonContents = JSON.parse(content.value); + if (packageJsonContents['dependencies']) { + for (let module of ModulesToLookFor) { + if ('react-native' === module) { + if (packageJsonContents['dependencies'][module]) { + tags['workspace.reactNative'] = true; } - return false; - }, - err => false - ); - }, err => false); - })).then(reactNatives => { - if (reactNatives.indexOf(true) !== -1) { - tags['workspace.reactNative'] = true; + } else { + if (packageJsonContents['dependencies'][module]) { + tags['workspace.npm.' + module] = true; + } + } + } } - return tags; - }); - } - - return tags; - }, error => { onUnexpectedError(error); return null; }); - } else { - return TPromise.as(tags); + } + catch (e) { + // Ignore errors when resolving file or parsing file contents + } + })); + } } + return TPromise.as(tags); } private findFolders(configuration: IWindowConfiguration): URI[] { @@ -359,7 +391,7 @@ export class WorkspaceStats implements IWorkbenchContribution { set.forEach(item => list.push(item)); /* __GDPR__ "workspace.remotes" : { - "domains" : { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "domains" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('workspace.remotes', { domains: list.sort() }); @@ -372,7 +404,7 @@ export class WorkspaceStats implements IWorkbenchContribution { })).then(hashedRemotes => { /* __GDPR__ "workspace.hashedRemotes" : { - "remotes" : { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "remotes" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('workspace.hashedRemotes', { remotes: hashedRemotes }); @@ -381,7 +413,7 @@ export class WorkspaceStats implements IWorkbenchContribution { /* __GDPR__FRAGMENT__ "AzureTags" : { - "node" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "node" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ private reportAzureNode(workspaceUris: URI[], tags: Tags): TPromise { @@ -407,7 +439,7 @@ export class WorkspaceStats implements IWorkbenchContribution { /* __GDPR__FRAGMENT__ "AzureTags" : { - "java" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "java" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ private reportAzureJava(workspaceUris: URI[], tags: Tags): TPromise { diff --git a/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts b/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts index acef28917c..a840df915d 100644 --- a/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts +++ b/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts @@ -12,13 +12,12 @@ import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as import { Registry } from 'vs/platform/registry/common/platform'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { FileChangeType, IFileService } from 'vs/platform/files/common/files'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import pkg from 'vs/platform/node/package'; import product, { ISurveyData } from 'vs/platform/node/product'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; -import { Severity } from 'vs/platform/notification/common/notification'; +import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; +import { ITextFileService, StateChange } from 'vs/workbench/services/textfile/common/textfiles'; class LanguageSurvey { @@ -26,10 +25,10 @@ class LanguageSurvey { data: ISurveyData, instantiationService: IInstantiationService, storageService: IStorageService, - choiceService: IChoiceService, + notificationService: INotificationService, telemetryService: ITelemetryService, - fileService: IFileService, - modelService: IModelService + modelService: IModelService, + textFileService: ITextFileService ) { const SESSION_COUNT_KEY = `${data.surveyId}.sessionCount`; const LAST_SESSION_DATE_KEY = `${data.surveyId}.lastSessionDate`; @@ -45,9 +44,9 @@ class LanguageSurvey { const date = new Date().toDateString(); if (storageService.getInteger(EDITED_LANGUAGE_COUNT_KEY, StorageScope.GLOBAL, 0) < data.editCount) { - fileService.onFileChanges(e => { - e.getUpdated().forEach(event => { - if (event.type === FileChangeType.UPDATED) { + textFileService.models.onModelsSaved(e => { + e.forEach(event => { + if (event.kind === StateChange.SAVED) { const model = modelService.getModel(event.resource); if (model && model.getModeId() === data.languageId && date !== storageService.get(EDITED_LANGUAGE_DATE_KEY, StorageScope.GLOBAL)) { const editedCount = storageService.getInteger(EDITED_LANGUAGE_COUNT_KEY, StorageScope.GLOBAL, 0) + 1; @@ -88,30 +87,36 @@ class LanguageSurvey { // __GDPR__TODO__ Need to move away from dynamic event names as those cannot be registered statically telemetryService.publicLog(`${data.surveyId}.survey/userAsked`); - const choices: Choice[] = [nls.localize('takeShortSurvey', "Take Short Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }]; - choiceService.choose(Severity.Info, nls.localize('helpUs', "Help us improve our support for {0}", data.languageId), choices).then(choice => { - switch (choice) { - case 0 /* Take Survey */: + notificationService.prompt( + Severity.Info, + nls.localize('helpUs', "Help us improve our support for {0}", data.languageId), + [{ + label: nls.localize('takeShortSurvey', "Take Short Survey"), + run: () => { telemetryService.publicLog(`${data.surveyId}.survey/takeShortSurvey`); telemetryService.getTelemetryInfo().then(info => { window.open(`${data.surveyUrl}?o=${encodeURIComponent(process.platform)}&v=${encodeURIComponent(pkg.version)}&m=${encodeURIComponent(info.machineId)}`); storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); storageService.store(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); }); - break; - case 1 /* Remind Later */: + } + }, { + label: nls.localize('remindLater', "Remind Me later"), + run: () => { telemetryService.publicLog(`${data.surveyId}.survey/remindMeLater`); storageService.store(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL); - break; - case 2 /* Never show again */: + } + }, { + label: nls.localize('neverAgain', "Don't Show Again"), + isSecondary: true, + run: () => { telemetryService.publicLog(`${data.surveyId}.survey/dontShowAgain`); storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); storageService.store(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); - break; - } - }); + } + }] + ); } - } class LanguageSurveysContribution implements IWorkbenchContribution { @@ -119,17 +124,17 @@ class LanguageSurveysContribution implements IWorkbenchContribution { constructor( @IInstantiationService instantiationService: IInstantiationService, @IStorageService storageService: IStorageService, - @IChoiceService choiceService: IChoiceService, + @INotificationService notificationService: INotificationService, @ITelemetryService telemetryService: ITelemetryService, - @IFileService fileService: IFileService, - @IModelService modelService: IModelService + @IModelService modelService: IModelService, + @ITextFileService textFileService: ITextFileService ) { product.surveys.filter(surveyData => surveyData.surveyId && surveyData.editCount && surveyData.languageId && surveyData.surveyUrl && surveyData.userProbability).map(surveyData => - new LanguageSurvey(surveyData, instantiationService, storageService, choiceService, telemetryService, fileService, modelService)); + new LanguageSurvey(surveyData, instantiationService, storageService, notificationService, telemetryService, modelService, textFileService)); } } if (language === 'en' && product.surveys && product.surveys.length) { - const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); + const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(LanguageSurveysContribution, LifecyclePhase.Running); -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts b/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts index 03dbb2b2fc..894f578157 100644 --- a/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts +++ b/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts @@ -15,8 +15,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; -import { Severity } from 'vs/platform/notification/common/notification'; +import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; const PROBABILITY = 0.15; const SESSION_COUNT_KEY = 'nps/sessionCount'; @@ -29,7 +28,7 @@ class NPSContribution implements IWorkbenchContribution { constructor( @IInstantiationService instantiationService: IInstantiationService, @IStorageService storageService: IStorageService, - @IChoiceService choiceService: IChoiceService, + @INotificationService notificationService: INotificationService, @ITelemetryService telemetryService: ITelemetryService ) { const skipVersion = storageService.get(SKIP_VERSION_KEY, StorageScope.GLOBAL, ''); @@ -63,29 +62,34 @@ class NPSContribution implements IWorkbenchContribution { return; } - const choices: Choice[] = [nls.localize('takeSurvey', "Take Survey"), nls.localize('remindLater', "Remind Me later"), { label: nls.localize('neverAgain', "Don't Show Again") }]; - choiceService.choose(Severity.Info, nls.localize('surveyQuestion', "Do you mind taking a quick feedback survey?"), choices).then(choice => { - switch (choice) { - case 0 /* Take Survey */: + notificationService.prompt( + Severity.Info, + nls.localize('surveyQuestion', "Do you mind taking a quick feedback survey?"), + [{ + label: nls.localize('takeSurvey', "Take Survey"), + run: () => { telemetryService.getTelemetryInfo().then(info => { window.open(`${product.npsSurveyUrl}?o=${encodeURIComponent(process.platform)}&v=${encodeURIComponent(pkg.version)}&m=${encodeURIComponent(info.machineId)}`); storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); storageService.store(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); }); - break; - case 1 /* Remind Later */: - storageService.store(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL); - break; - case 2 /* Never show again */: + } + }, { + label: nls.localize('remindLater', "Remind Me later"), + run: () => storageService.store(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL) + }, { + label: nls.localize('neverAgain', "Don't Show Again"), + isSecondary: true, + run: () => { storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); storageService.store(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); - break; - } - }); + } + }] + ); } } if (language === 'en' && product.npsSurveyUrl) { - const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); + const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(NPSContribution, LifecyclePhase.Running); } \ No newline at end of file diff --git a/src/vs/workbench/parts/tasks/browser/quickOpen.ts b/src/vs/workbench/parts/tasks/browser/quickOpen.ts index f866964ffb..4358e9f9c6 100644 --- a/src/vs/workbench/parts/tasks/browser/quickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/quickOpen.ts @@ -200,7 +200,7 @@ export class QuickOpenActionContributor extends ActionBarContributor { private action: CustomizeTaskAction; - constructor( @ITaskService taskService: ITaskService, @IQuickOpenService quickOpenService: IQuickOpenService) { + constructor(@ITaskService taskService: ITaskService, @IQuickOpenService quickOpenService: IQuickOpenService) { super(); this.action = new CustomizeTaskAction(taskService, quickOpenService); } diff --git a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts index 9c915ad6d1..1b980be154 100644 --- a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen'); -import Model = require('vs/base/parts/quickopen/browser/quickOpenModel'); +import * as QuickOpen from 'vs/base/parts/quickopen/common/quickOpen'; +import * as Model from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tasks'; diff --git a/src/vs/workbench/parts/tasks/common/problemCollectors.ts b/src/vs/workbench/parts/tasks/common/problemCollectors.ts index 5dab416624..9230b6c47f 100644 --- a/src/vs/workbench/parts/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/parts/tasks/common/problemCollectors.ts @@ -6,13 +6,13 @@ import { IStringDictionary, INumberDictionary } from 'vs/base/common/collections'; import URI from 'vs/base/common/uri'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILineMatcher, createLineMatcher, ProblemMatcher, ProblemMatch, ApplyToKind, WatchingPattern, getResource } from 'vs/workbench/parts/tasks/common/problemMatcher'; -import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers'; +import { IMarkerService, IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { generateUuid } from 'vs/base/common/uuid'; export enum ProblemCollectorEventKind { @@ -39,6 +39,7 @@ export class AbstractProblemCollector implements IDisposable { private matchers: INumberDictionary; private activeMatcher: ILineMatcher; private _numberOfMatches: number; + private _maxMarkerSeverity: MarkerSeverity; private buffer: string[]; private bufferLength: number; private openModels: IStringDictionary; @@ -73,6 +74,7 @@ export class AbstractProblemCollector implements IDisposable { this.buffer = []; this.activeMatcher = null; this._numberOfMatches = 0; + this._maxMarkerSeverity = undefined; this.openModels = Object.create(null); this.modelListeners = []; this.applyToByOwner = new Map(); @@ -110,12 +112,16 @@ export class AbstractProblemCollector implements IDisposable { return this._numberOfMatches; } + public get maxMarkerSeverity(): MarkerSeverity { + return this._maxMarkerSeverity; + } + protected tryFindMarker(line: string): ProblemMatch { let result: ProblemMatch = null; if (this.activeMatcher) { result = this.activeMatcher.next(line); if (result) { - this._numberOfMatches++; + this.captureMatch(result); return result; } this.clearBuffer(); @@ -170,7 +176,7 @@ export class AbstractProblemCollector implements IDisposable { let matcher = candidates[i]; let result = matcher.handle(this.buffer, startIndex); if (result.match) { - this._numberOfMatches++; + this.captureMatch(result.match); if (result.continue) { this.activeMatcher = matcher; } @@ -181,6 +187,13 @@ export class AbstractProblemCollector implements IDisposable { return null; } + private captureMatch(match: ProblemMatch): void { + this._numberOfMatches++; + if (this._maxMarkerSeverity === void 0 || match.marker.severity > this._maxMarkerSeverity) { + this._maxMarkerSeverity = match.marker.severity; + } + } + private clearBuffer(): void { if (this.buffer.length > 0) { this.buffer = []; @@ -300,6 +313,8 @@ export class AbstractProblemCollector implements IDisposable { } protected cleanMarkerCaches(): void { + this._numberOfMatches = 0; + this._maxMarkerSeverity = undefined; this.markers.clear(); this.deliveredMarkers.clear(); } @@ -464,10 +479,10 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement if (matches) { if (this._activeBackgroundMatchers.has(background.key)) { this._activeBackgroundMatchers.delete(background.key); + this.resetCurrentResource(); this._onDidStateChange.fire(ProblemCollectorEvent.create(ProblemCollectorEventKind.BackgroundProcessingEnds)); result = true; let owner = background.matcher.owner; - this.resetCurrentResource(); this.cleanMarkers(owner); this.cleanMarkerCaches(); } diff --git a/src/vs/workbench/parts/tasks/common/problemMatcher.ts b/src/vs/workbench/parts/tasks/common/problemMatcher.ts index a9afbb05c8..4146f59d77 100644 --- a/src/vs/workbench/parts/tasks/common/problemMatcher.ts +++ b/src/vs/workbench/parts/tasks/common/problemMatcher.ts @@ -20,7 +20,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ValidationStatus, ValidationState, IProblemReporter, Parser } from 'vs/base/common/parsers'; import { IStringDictionary } from 'vs/base/common/collections'; -import { IMarkerData } from 'vs/platform/markers/common/markers'; +import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry'; export enum FileLocationKind { @@ -127,6 +127,7 @@ export module ApplyToKind { export interface ProblemMatcher { owner: string; + source?: string; applyTo: ApplyToKind; fileLocation: FileLocationKind; filePrefix?: string; @@ -278,9 +279,12 @@ abstract class AbstractLineMatcher implements ILineMatcher { endColumn: location.endCharacter, message: data.message }; - if (!Types.isUndefined(data.code)) { + if (data.code !== void 0) { marker.code = data.code; } + if (this.matcher.source !== void 0) { + marker.source = this.matcher.source; + } return { description: this.matcher, resource: this.getResource(data.file), @@ -298,6 +302,9 @@ abstract class AbstractLineMatcher implements ILineMatcher { } private getLocation(data: ProblemData): Location { + if (data.kind === ProblemLocationKind.File) { + return this.createLocation(0, 0, 0, 0); + } if (data.location) { return this.parseLocationInfo(data.location); } @@ -335,7 +342,7 @@ abstract class AbstractLineMatcher implements ILineMatcher { return { startLineNumber: startLine, startCharacter: 1, endLineNumber: startLine, endCharacter: Number.MAX_VALUE }; } - private getSeverity(data: ProblemData): Severity { + private getSeverity(data: ProblemData): MarkerSeverity { let result: Severity = null; if (data.severity) { let value = data.severity; @@ -359,7 +366,7 @@ abstract class AbstractLineMatcher implements ILineMatcher { if (result === null || result === Severity.Ignore) { result = this.matcher.severity || Severity.Error; } - return result; + return MarkerSeverity.fromSeverity(result); } } @@ -379,7 +386,7 @@ class SingleLineMatcher extends AbstractLineMatcher { public handle(lines: string[], start: number = 0): HandleResult { Assert.ok(lines.length - start === 1); let data: ProblemData = Object.create(null); - if (this.pattern.kind) { + if (this.pattern.kind !== void 0) { data.kind = this.pattern.kind; } let matches = this.pattern.regexp.exec(lines[start]); @@ -638,21 +645,27 @@ export namespace Config { export interface ProblemMatcher { /** - * The name of a base problem matcher to use. If specified the - * base problem matcher will be used as a template and properties - * specified here will replace properties of the base problem - * matcher - */ + * The name of a base problem matcher to use. If specified the + * base problem matcher will be used as a template and properties + * specified here will replace properties of the base problem + * matcher + */ base?: string; /** - * The owner of the produced VSCode problem. This is typically - * the identifier of a VSCode language service if the problems are - * to be merged with the one produced by the language service - * or a generated internal id. Defaults to the generated internal id. - */ + * The owner of the produced VSCode problem. This is typically + * the identifier of a VSCode language service if the problems are + * to be merged with the one produced by the language service + * or a generated internal id. Defaults to the generated internal id. + */ owner?: string; + /** + * A human-readable string describing the source of this problem. + * E.g. 'typescript' or 'super lint'. + */ + source?: string; + /** * Specifies to which kind of documents the problems found by this * matcher are applied. Valid values are: @@ -1068,7 +1081,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry { } resolve(undefined); }); - }); + }, () => { }); } public onReady(): TPromise { @@ -1240,6 +1253,7 @@ export class ProblemMatcherParser extends Parser { let result: ProblemMatcher = null; let owner = description.owner ? description.owner : UUID.generateUuid(); + let source = Types.isString(description.source) ? description.source : undefined; let applyTo = Types.isString(description.applyTo) ? ApplyToKind.fromString(description.applyTo) : ApplyToKind.allDocuments; if (!applyTo) { applyTo = ApplyToKind.allDocuments; @@ -1289,6 +1303,9 @@ export class ProblemMatcherParser extends Parser { if (description.owner) { result.owner = owner; } + if (source) { + result.source = source; + } if (fileLocation) { result.fileLocation = fileLocation; } @@ -1310,6 +1327,9 @@ export class ProblemMatcherParser extends Parser { fileLocation: fileLocation, pattern: pattern, }; + if (source) { + result.source = source; + } if (filePrefix) { result.filePrefix = filePrefix; } @@ -1457,6 +1477,10 @@ export namespace Schemas { type: 'string', description: localize('ProblemMatcherSchema.owner', 'The owner of the problem inside Code. Can be omitted if base is specified. Defaults to \'external\' if omitted and base is not specified.') }, + source: { + type: 'string', + description: localize('ProblemMatcherSchema.source', 'A human-readable string describing the source of this diagnostic, e.g. \'typescript\' or \'super lint\'.') + }, severity: { type: 'string', enum: ['error', 'warning', 'info'], @@ -1611,7 +1635,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { } resolve(undefined); }); - }); + }, () => { }); } public onReady(): TPromise { @@ -1646,6 +1670,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { label: localize('lessCompile', 'Less problems'), deprecated: true, owner: 'lessCompile', + source: 'less', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Absolute, pattern: ProblemPatternRegistry.get('lessCompile'), @@ -1656,6 +1681,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'gulp-tsc', label: localize('gulp-tsc', 'Gulp TSC Problems'), owner: 'typescript', + source: 'ts', applyTo: ApplyToKind.closedDocuments, fileLocation: FileLocationKind.Relative, filePrefix: '${workspaceFolder}', @@ -1666,6 +1692,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'jshint', label: localize('jshint', 'JSHint problems'), owner: 'jshint', + source: 'jshint', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Absolute, pattern: ProblemPatternRegistry.get('jshint') @@ -1675,6 +1702,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'jshint-stylish', label: localize('jshint-stylish', 'JSHint stylish problems'), owner: 'jshint', + source: 'jshint', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Absolute, pattern: ProblemPatternRegistry.get('jshint-stylish') @@ -1684,6 +1712,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'eslint-compact', label: localize('eslint-compact', 'ESLint compact problems'), owner: 'eslint', + source: 'eslint', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Absolute, filePrefix: '${workspaceFolder}', @@ -1694,6 +1723,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'eslint-stylish', label: localize('eslint-stylish', 'ESLint stylish problems'), owner: 'eslint', + source: 'eslint', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Absolute, pattern: ProblemPatternRegistry.get('eslint-stylish') @@ -1703,6 +1733,7 @@ class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry { name: 'go', label: localize('go', 'Go problems'), owner: 'go', + source: 'go', applyTo: ApplyToKind.allDocuments, fileLocation: FileLocationKind.Relative, filePrefix: '${workspaceFolder}', diff --git a/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.ts b/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.ts index afe6e752c0..f011b31ed5 100644 --- a/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.ts +++ b/src/vs/workbench/parts/tasks/common/taskDefinitionRegistry.ts @@ -22,7 +22,7 @@ const taskDefinitionSchema: IJSONSchema = { properties: { type: { type: 'string', - description: nls.localize('TaskDefinition.description', 'The actual task type') + description: nls.localize('TaskDefinition.description', 'The actual task type. Please note that types starting with a \'$\' are reserved for internal usage.') }, required: { type: 'array', @@ -105,7 +105,7 @@ class TaskDefinitionRegistryImpl implements ITaskDefinitionRegistry { } resolve(undefined); }); - }); + }, () => { }); } public onReady(): TPromise { diff --git a/src/vs/workbench/parts/tasks/common/taskService.ts b/src/vs/workbench/parts/tasks/common/taskService.ts index e70b1a4d40..c512c3d291 100644 --- a/src/vs/workbench/parts/tasks/common/taskService.ts +++ b/src/vs/workbench/parts/tasks/common/taskService.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { LinkedMap } from 'vs/base/common/map'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -32,6 +32,11 @@ export interface CustomizationProperties { isBackground?: boolean; } +export interface TaskFilter { + version?: string; + type?: string; +} + export interface ITaskService { _serviceBrand: any; onDidStateChange: Event; @@ -45,11 +50,11 @@ export interface ITaskService { restart(task: Task): void; terminate(task: Task): TPromise; terminateAll(): TPromise; - tasks(): TPromise; + tasks(filter?: TaskFilter): TPromise; /** - * @param identifier The task's name, label or defined identifier. + * @param alias The task's name, label or defined identifier. */ - getTask(workspaceFolder: IWorkspaceFolder | string, identifier: string): TPromise; + getTask(workspaceFolder: IWorkspaceFolder | string, alias: string, compareId?: boolean): TPromise; getTasksForGroup(group: string): TPromise; getRecentlyUsedTasks(): LinkedMap; createSorter(): TaskSorter; diff --git a/src/vs/workbench/parts/tasks/common/taskSystem.ts b/src/vs/workbench/parts/tasks/common/taskSystem.ts index 774e993bca..af4b9da69a 100644 --- a/src/vs/workbench/parts/tasks/common/taskSystem.ts +++ b/src/vs/workbench/parts/tasks/common/taskSystem.ts @@ -7,7 +7,7 @@ import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { TerminateResponse } from 'vs/base/common/processes'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -42,8 +42,8 @@ export class TaskError { "runner": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "taskKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "command": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "exitCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "exitCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ export interface TelemetryEvent { diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index b86994cf55..5e7bbe739f 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -4,24 +4,85 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { UriComponents } from 'vs/base/common/uri'; import * as Types from 'vs/base/common/types'; import { IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import * as Objects from 'vs/base/common/objects'; +import { UriComponents } from 'vs/base/common/uri'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ProblemMatcher } from 'vs/workbench/parts/tasks/common/problemMatcher'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +export enum ShellQuoting { + /** + * Default is character escaping. + */ + Escape = 1, + + /** + * Default is strong quoting + */ + Strong = 2, + + /** + * Default is weak quoting. + */ + Weak = 3 +} + +export namespace ShellQuoting { + export function from(this: void, value: string): ShellQuoting { + if (!value) { + return ShellQuoting.Strong; + } + switch (value.toLowerCase()) { + case 'escape': + return ShellQuoting.Escape; + case 'strong': + return ShellQuoting.Strong; + case 'weak': + return ShellQuoting.Weak; + default: + return ShellQuoting.Strong; + } + } +} + +export interface ShellQuotingOptions { + /** + * The character used to do character escaping. + */ + escape?: string | { + escapeChar: string; + charsToEscape: string; + }; + + /** + * The character used for string quoting. + */ + strong?: string; + + /** + * The character used for weak quoting. + */ + weak?: string; +} + export interface ShellConfiguration { /** * The shell executable. */ executable: string; + /** * The arguments to be passed to the shell executable. */ args?: string[]; + + /** + * Which kind of quotes the shell supports. + */ + quoting?: ShellQuotingOptions; } export interface CommandOptions { @@ -63,7 +124,7 @@ export enum RevealKind { } export namespace RevealKind { - export function fromString(value: string): RevealKind { + export function fromString(this: void, value: string): RevealKind { switch (value.toLowerCase()) { case 'always': return RevealKind.Always; @@ -155,6 +216,23 @@ export namespace RuntimeType { } } +export interface QuotedString { + value: string; + quoting: ShellQuoting; +} + +export type CommandString = string | QuotedString; + +export namespace CommandString { + export function value(value: CommandString): string { + if (Types.isString(value)) { + return value; + } else { + return value.value; + } + } +} + export interface CommandConfiguration { /** @@ -165,7 +243,7 @@ export interface CommandConfiguration { /** * The command to execute */ - name: string; + name: CommandString; /** * Additional command options. @@ -175,7 +253,7 @@ export interface CommandConfiguration { /** * Command arguments. */ - args?: string[]; + args?: CommandString[]; /** * The task selector if needed. @@ -259,6 +337,7 @@ export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | InMemoryTas export interface TaskIdentifier { _key: string; type: string; + [name: string]: any; } export interface TaskDependency { @@ -298,6 +377,11 @@ export interface ConfigurationProperties { */ presentation?: PresentationOptions; + /** + * The command options; + */ + options?: CommandOptions; + /** * Whether the task is a background task or not. */ @@ -358,6 +442,20 @@ export namespace CustomTask { let candidate: CustomTask = value; return candidate && candidate.type === 'custom'; } + export function getDefinition(task: CustomTask): TaskIdentifier { + let type: string; + if (task.command !== void 0) { + type = task.command.runtime === RuntimeType.Shell ? 'shell' : 'process'; + } else { + type = '$composite'; + } + let result: TaskIdentifier = { + type, + _key: task._id, + id: task._id + }; + return result; + } } export interface ConfiguringTask extends CommonTask, ConfigurationProperties { @@ -499,8 +597,8 @@ export namespace Task { } } - export function matches(task: Task, alias: string): boolean { - return alias === task._label || alias === task.identifier; + export function matches(task: Task, alias: string, compareId: boolean = false): boolean { + return alias === task._label || alias === task.identifier || (compareId && alias === task._id); } export function getQualifiedLabel(task: Task): string { @@ -511,8 +609,30 @@ export namespace Task { return task._label; } } + + export function getTaskDefinition(task: Task): TaskIdentifier { + if (ContributedTask.is(task)) { + return task.defines; + } else if (CustomTask.is(task)) { + return CustomTask.getDefinition(task); + } else { + return undefined; + } + } + + export function getTaskExecution(task: Task): TaskExecution { + let result: TaskExecution = { + id: task._id, + task: task + }; + return result; + } } +export interface TaskExecution { + id: string; + task: Task; +} export enum ExecutionEngine { Process = 1, @@ -574,10 +694,12 @@ export class TaskSorter { } export enum TaskEventKind { + Start = 'start', Active = 'active', Inactive = 'inactive', - Terminated = 'terminated', Changed = 'changed', + Terminated = 'terminated', + End = 'end' } @@ -596,7 +718,7 @@ export interface TaskEvent { } export namespace TaskEvent { - export function create(kind: TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.Terminated, task: Task); + export function create(kind: TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.Terminated | TaskEventKind.Start | TaskEventKind.End, task: Task); export function create(kind: TaskEventKind.Changed); export function create(kind: TaskEventKind, task?: Task): TaskEvent { if (task) { diff --git a/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts b/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts index 0e96f33677..5664c987e2 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts @@ -149,6 +149,71 @@ const taskType: IJSONSchema = { description: nls.localize('JsonSchema.tasks.type', 'Defines whether the task is run as a process or as a command inside a shell.') }; +const command: IJSONSchema = { + oneOf: [ + { + type: 'string', + }, + { + type: 'object', + required: ['value', 'quoting'], + properties: { + value: { + type: 'string', + description: nls.localize('JsonSchema.command.quotedString.value', 'The actual command value') + }, + quoting: { + type: 'string', + enum: ['escape', 'strong', 'weak'], + enumDescriptions: [ + nls.localize('JsonSchema.tasks.quoting.escape', 'Escapes characters using the shell\'s escape character (e.g. ` under PowerShell and \\ under bash).'), + nls.localize('JsonSchema.tasks.quoting.strong', 'Quotes the argument using the shell\'s strong quote character (e.g. " under PowerShell and bash).'), + nls.localize('JsonSchema.tasks.quoting.weak', 'Quotes the argument using the shell\'s weak quote character (e.g. \' under PowerShell and bash).'), + ], + default: 'strong', + description: nls.localize('JsonSchema.command.quotesString.quote', 'How the command value should be quoted.') + } + } + + } + ], + description: nls.localize('JsonSchema.command', 'The command to be executed. Can be an external program or a shell command.') +}; + +const args: IJSONSchema = { + type: 'array', + items: { + oneOf: [ + { + type: 'string', + }, + { + type: 'object', + required: ['value', 'quoting'], + properties: { + value: { + type: 'string', + description: nls.localize('JsonSchema.args.quotedString.value', 'The actual argument value') + }, + quoting: { + type: 'string', + enum: ['escape', 'strong', 'weak'], + enumDescriptions: [ + nls.localize('JsonSchema.tasks.quoting.escape', 'Escapes characters using the shell\'s escape character (e.g. ` under PowerShell and \\ under bash).'), + nls.localize('JsonSchema.tasks.quoting.strong', 'Quotes the argument using the shell\'s strong quote character (e.g. " under PowerShell and bash).'), + nls.localize('JsonSchema.tasks.quoting.weak', 'Quotes the argument using the shell\'s weak quote character (e.g. \' under PowerShell and bash).'), + ], + default: 'strong', + description: nls.localize('JsonSchema.args.quotesString.quote', 'How the argument value should be quoted.') + } + } + + } + ] + }, + description: nls.localize('JsonSchema.tasks.args', 'Arguments passed to the command when this task is invoked.') +}; + const label: IJSONSchema = { type: 'string', description: nls.localize('JsonSchema.tasks.label', "The task's user interface label") @@ -165,6 +230,9 @@ const identifier: IJSONSchema = { description: nls.localize('JsonSchema.tasks.identifier', 'A user defined identifier to reference the task in launch.json or a dependsOn clause.') }; +const options: IJSONSchema = Objects.deepClone(commonSchema.definitions.options); +options.properties.shell = Objects.deepClone(commonSchema.definitions.shellConfiguration); + let taskConfiguration: IJSONSchema = { type: 'object', additionalProperties: false, @@ -191,6 +259,7 @@ let taskConfiguration: IJSONSchema = { default: false }, presentation: Objects.deepClone(presentation), + options: options, problemMatcher: { $ref: '#/definitions/problemMatcherType', description: nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.') @@ -231,6 +300,8 @@ let definitions = Objects.deepClone(commonSchema.definitions); let taskDescription: IJSONSchema = definitions.taskDescription; taskDescription.required = ['label']; taskDescription.properties.label = Objects.deepClone(label); +taskDescription.properties.command = Objects.deepClone(command); +taskDescription.properties.args = Objects.deepClone(args); taskDescription.properties.isShellCommand = Objects.deepClone(shellCommand); taskDescription.properties.dependsOn = dependsOn; taskDescription.properties.identifier = Objects.deepClone(identifier); diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 544d5af508..ff87dad93a 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -7,6 +7,7 @@ import 'vs/css!./media/task.contribution'; import * as nls from 'vs/nls'; +import * as semver from 'semver'; import { QuickOpenHandler } from 'vs/workbench/parts/tasks/browser/taskQuickOpen'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -17,8 +18,7 @@ import { IStringDictionary } from 'vs/base/common/collections'; import { Action } from 'vs/base/common/actions'; import * as Dom from 'vs/base/browser/dom'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; -import * as Builder from 'vs/base/browser/builder'; +import { Event, Emitter } from 'vs/base/common/event'; import * as Types from 'vs/base/common/types'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { TerminateResponseCode } from 'vs/base/common/processes'; @@ -46,11 +46,11 @@ import { IProgressService2, IProgressOptions, ProgressLocation } from 'vs/platfo import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IConfirmationService, IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; import { IModelService } from 'vs/editor/common/services/modelService'; -import jsonContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); +import * as jsonContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { IStatusbarItem, IStatusbarRegistry, Extensions as StatusbarExtensions, StatusbarItemDescriptor, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar'; @@ -58,7 +58,7 @@ import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandler import { IQuickOpenService, IPickOpenEntry, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import Constants from 'vs/workbench/parts/markers/common/constants'; +import Constants from 'vs/workbench/parts/markers/electron-browser/constants'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; @@ -71,8 +71,12 @@ import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; import { ITaskSystem, ITaskResolver, ITaskSummary, TaskExecuteKind, TaskError, TaskErrors, TaskTerminateResponse } from 'vs/workbench/parts/tasks/common/taskSystem'; -import { Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent, TaskEventKind, TaskSet, TaskGroup, GroupType, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier, TaskSorter } from 'vs/workbench/parts/tasks/common/tasks'; -import { ITaskService, ITaskProvider, RunOptions, CustomizationProperties } from 'vs/workbench/parts/tasks/common/taskService'; +import { + Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent, + TaskEventKind, TaskSet, TaskGroup, GroupType, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, + TaskIdentifier, TaskSorter +} from 'vs/workbench/parts/tasks/common/tasks'; +import { ITaskService, ITaskProvider, RunOptions, CustomizationProperties, TaskFilter } from 'vs/workbench/parts/tasks/common/taskService'; import { getTemplates as getTaskTemplates } from 'vs/workbench/parts/tasks/common/taskTemplates'; import * as TaskConfig from '../node/taskConfiguration'; @@ -84,7 +88,6 @@ import { QuickOpenActionContributor } from '../browser/quickOpen'; import { Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND } from 'vs/workbench/common/theme'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -let $ = Builder.$; let tasksCategory = nls.localize('tasksCategory', "Tasks"); namespace ConfigureTaskAction { @@ -137,11 +140,15 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { const info = document.createElement('div'); const building = document.createElement('div'); + const errorTitle = n => nls.localize('totalErrors', "{0} Errors", n); + const warningTitle = n => nls.localize('totalWarnings', "{0} Warnings", n); + const infoTitle = n => nls.localize('totalInfos', "{0} Infos", n); + Dom.addClass(element, 'task-statusbar-item'); + element.title = nls.localize('problems', "Problems"); Dom.addClass(label, 'task-statusbar-item-label'); element.appendChild(label); - element.title = nls.localize('problems', "Problems"); Dom.addClass(errorIcon, 'task-statusbar-item-label-error'); Dom.addClass(errorIcon, 'mask-icon'); @@ -150,6 +157,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { Dom.addClass(error, 'task-statusbar-item-label-counter'); error.innerHTML = '0'; + error.title = errorIcon.title = errorTitle(0); label.appendChild(error); Dom.addClass(warningIcon, 'task-statusbar-item-label-warning'); @@ -159,23 +167,23 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { Dom.addClass(warning, 'task-statusbar-item-label-counter'); warning.innerHTML = '0'; + warning.title = warningIcon.title = warningTitle(0); label.appendChild(warning); Dom.addClass(infoIcon, 'task-statusbar-item-label-info'); Dom.addClass(infoIcon, 'mask-icon'); label.appendChild(infoIcon); this.icons.push(infoIcon); - $(infoIcon).hide(); + Dom.hide(infoIcon); Dom.addClass(info, 'task-statusbar-item-label-counter'); label.appendChild(info); - $(info).hide(); + Dom.hide(info); Dom.addClass(building, 'task-statusbar-item-building'); element.appendChild(building); building.innerHTML = nls.localize('building', 'Building...'); - $(building).hide(); - + Dom.hide(building); callOnDispose.push(Dom.addDisposableListener(label, 'click', (e: MouseEvent) => { const panel = this.panelService.getActivePanel(); @@ -186,24 +194,22 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { } })); - let updateStatus = (element: HTMLDivElement, icon: HTMLDivElement, stats: number): boolean => { - if (stats > 0) { - element.innerHTML = stats.toString(); - $(element).show(); - $(icon).show(); - return true; - } else { - $(element).hide(); - $(icon).hide(); - return false; - } - }; - - let manyMarkers = nls.localize('manyMarkers', "99+"); + const manyProblems = nls.localize('manyProblems', "10K+"); + const packNumber = n => n > 9999 ? manyProblems : n > 999 ? n.toString().charAt(0) + 'K' : n.toString(); let updateLabel = (stats: MarkerStatistics) => { - error.innerHTML = stats.errors < 100 ? stats.errors.toString() : manyMarkers; - warning.innerHTML = stats.warnings < 100 ? stats.warnings.toString() : manyMarkers; - updateStatus(info, infoIcon, stats.infos); + error.innerHTML = packNumber(stats.errors); + error.title = errorIcon.title = errorTitle(stats.errors); + warning.innerHTML = packNumber(stats.warnings); + warning.title = warningIcon.title = warningTitle(stats.warnings); + if (stats.infos > 0) { + info.innerHTML = packNumber(stats.infos); + info.title = infoIcon.title = infoTitle(stats.infos); + Dom.show(info); + Dom.show(infoIcon); + } else { + Dom.hide(info); + Dom.hide(infoIcon); + } }; this.markerService.onMarkerChanged((changedResources) => { @@ -218,7 +224,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { case TaskEventKind.Active: this.activeCount++; if (this.activeCount === 1) { - $(building).show(); + Dom.show(building); } break; case TaskEventKind.Inactive: @@ -227,13 +233,13 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { if (this.activeCount > 0) { this.activeCount--; if (this.activeCount === 0) { - $(building).hide(); + Dom.hide(building); } } break; case TaskEventKind.Terminated: if (this.activeCount !== 0) { - $(building).hide(); + Dom.hide(building); this.activeCount = 0; } break; @@ -291,7 +297,7 @@ class TaskStatusBarItem extends Themable implements IStatusbarItem { let label = new OcticonLabel(labelElement); label.title = nls.localize('runningTasks', "Show Running Tasks"); - $(element).hide(); + Dom.hide(element); callOnDispose.push(Dom.addDisposableListener(labelElement, 'click', (e: MouseEvent) => { (this.taskService as TaskService).runShowTasks(); @@ -300,10 +306,10 @@ class TaskStatusBarItem extends Themable implements IStatusbarItem { let updateStatus = (): void => { this.taskService.getActiveTasks().then(tasks => { if (tasks.length === 0) { - $(element).hide(); + Dom.hide(element); } else { label.text = `$(tools) ${tasks.length}`; - $(element).show(); + Dom.show(element); } }); }; @@ -450,7 +456,7 @@ class TaskService implements ITaskService { private _recentlyUsedTasks: LinkedMap; private _outputChannel: IOutputChannel; - private _onDidStateChange: Emitter; + private readonly _onDidStateChange: Emitter; constructor( @IConfigurationService private configurationService: IConfigurationService, @@ -471,9 +477,8 @@ class TaskService implements ITaskService { @IProgressService2 private progressService: IProgressService2, @IOpenerService private openerService: IOpenerService, @IWindowService private readonly _windowService: IWindowService, - @IConfirmationService private confirmationService: IConfirmationService, - @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService + @IDialogService private dialogService: IDialogService, + @INotificationService private notificationService: INotificationService ) { this._configHasErrors = false; this._workspaceTasksPromise = undefined; @@ -491,14 +496,17 @@ class TaskService implements ITaskService { let folderSetup = this.computeWorkspaceFolderSetup(); if (this.executionEngine !== folderSetup[2]) { if (this._taskSystem && this._taskSystem.getActiveTasks().length > 0) { - this.choiceService.choose(Severity.Info, nls.localize( - 'TaskSystem.noHotSwap', - 'Changing the task execution engine with an active task running requires to reload the Window' - ), [nls.localize('reloadWindow', "Reload Window")]).then(choice => { - if (choice === 0) { - this._windowService.reloadWindow(); - } - }); + this.notificationService.prompt( + Severity.Info, + nls.localize( + 'TaskSystem.noHotSwap', + 'Changing the task execution engine with an active task running requires to reload the Window' + ), + [{ + label: nls.localize('reloadWindow', "Reload Window"), + run: () => this._windowService.reloadWindow() + }] + ); return; } else { this.disposeTaskSystemListeners(); @@ -655,7 +663,7 @@ class TaskService implements ITaskService { return this._providers.delete(handle); } - public getTask(folder: IWorkspaceFolder | string, alias: string): TPromise { + public getTask(folder: IWorkspaceFolder | string, alias: string, compareId: boolean = false): TPromise { let name = Types.isString(folder) ? folder : folder.name; if (this.ignoredWorkspaceFolders.some(ignored => ignored.name === name)) { return TPromise.wrapError(new Error(nls.localize('TaskServer.folderIgnored', 'The folder {0} is ignored since it uses task version 0.1.0', name))); @@ -666,7 +674,7 @@ class TaskService implements ITaskService { return undefined; } for (let task of values) { - if (Task.matches(task, alias)) { + if (Task.matches(task, alias, compareId)) { return task; } } @@ -674,8 +682,28 @@ class TaskService implements ITaskService { }); } - public tasks(): TPromise { - return this.getGroupedTasks().then(result => result.all()); + public tasks(filter?: TaskFilter): TPromise { + let range = filter && filter.version ? filter.version : undefined; + let engine = this.executionEngine; + + if (range && ((semver.satisfies('0.1.0', range) && engine === ExecutionEngine.Terminal) || (semver.satisfies('2.0.0', range) && engine === ExecutionEngine.Process))) { + return TPromise.as([]); + } + return this.getGroupedTasks().then((map) => { + if (!filter || !filter.type) { + return map.all(); + } + let result: Task[] = []; + map.forEach((tasks) => { + for (let task of tasks) { + let definition = Task.getTaskDefinition(task); + if (definition && definition.type === filter.type) { + result.push(task); + } + } + }); + return result; + }); } public createSorter(): TaskSorter { @@ -1147,11 +1175,22 @@ class TaskService implements ITaskService { if (executeResult.kind === TaskExecuteKind.Active) { let active = executeResult.active; if (active.same) { + let message; if (active.background) { - this.notificationService.info(nls.localize('TaskSystem.activeSame.background', 'The task \'{0}\' is already active and in background mode. To terminate it use \'Terminate Task...\' from the Tasks menu.', Task.getQualifiedLabel(task))); + message = nls.localize('TaskSystem.activeSame.background', 'The task \'{0}\' is already active and in background mode.', Task.getQualifiedLabel(task)); } else { - this.notificationService.info(nls.localize('TaskSystem.activeSame.noBackground', 'The task \'{0}\' is already active. To terminate it use \'Terminate Task...\' from the Tasks menu.', Task.getQualifiedLabel(task))); + message = nls.localize('TaskSystem.activeSame.noBackground', 'The task \'{0}\' is already active.', Task.getQualifiedLabel(task)); } + this.notificationService.prompt(Severity.Info, message, + [{ + label: nls.localize('terminateTask', "Terminate Task"), + run: () => this.terminate(task) + }, + { + label: nls.localize('restartTask', "Restart Task"), + run: () => this.restart(task) + }] + ); } else { throw new TaskError(Severity.Warning, nls.localize('TaskSystem.active', 'There is already a task running. Terminate it first before executing another task.'), TaskErrors.RunningTask); } @@ -1586,7 +1625,7 @@ class TaskService implements ITaskService { if (!config.command || this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return false; } - return ProcessRunnerDetector.supports(config.command); + return ProcessRunnerDetector.supports(TaskConfig.CommandString.value(config.command)); } public configureAction(): Action { @@ -1598,15 +1637,6 @@ class TaskService implements ITaskService { }; } - private configureBuildTask(): Action { - let run = () => { this.runConfigureTasks(); return TPromise.as(undefined); }; - return new class extends Action { - constructor() { - super(ConfigureTaskAction.ID, ConfigureTaskAction.TEXT, undefined, true, run); - } - }; - } - public beforeShutdown(): boolean | TPromise { if (!this._taskSystem) { return false; @@ -1621,19 +1651,19 @@ class TaskService implements ITaskService { return false; } - let terminatePromise: TPromise; + let terminatePromise: TPromise; if (this._taskSystem.canAutoTerminate()) { - terminatePromise = TPromise.wrap(true); + terminatePromise = TPromise.wrap({ confirmed: true }); } else { - terminatePromise = this.confirmationService.confirm({ + terminatePromise = this.dialogService.confirm({ message: nls.localize('TaskSystem.runningTask', 'There is a task running. Do you want to terminate it?'), primaryButton: nls.localize({ key: 'TaskSystem.terminateTask', comment: ['&& denotes a mnemonic'] }, "&&Terminate Task"), type: 'question' }); } - return terminatePromise.then(terminate => { - if (terminate) { + return terminatePromise.then(res => { + if (res.confirmed) { return this._taskSystem.terminateAll().then((responses) => { let success = true; let code: number = undefined; @@ -1650,11 +1680,11 @@ class TaskService implements ITaskService { this.disposeTaskSystemListeners(); return false; // no veto } else if (code && code === TerminateResponseCode.ProcessNotFound) { - return this.confirmationService.confirm({ + return this.dialogService.confirm({ message: nls.localize('TaskSystem.noProcess', 'The launched task doesn\'t exist anymore. If the task spawned background processes exiting VS Code might result in orphaned processes. To avoid this start the last background process with a wait flag.'), primaryButton: nls.localize({ key: 'TaskSystem.exitAnyways', comment: ['&& denotes a mnemonic'] }, "&&Exit Anyways"), type: 'info' - }).then(confirmed => !confirmed); + }).then(res => !res.confirmed); } return true; // veto }, (err) => { @@ -1666,15 +1696,6 @@ class TaskService implements ITaskService { }); } - private getConfigureAction(code: TaskErrors): Action { - switch (code) { - case TaskErrors.NoBuildTask: - return this.configureBuildTask(); - default: - return this.configureAction(); - } - } - private handleError(err: any): void { let showOutput = true; if (err instanceof TaskError) { @@ -1682,13 +1703,16 @@ class TaskService implements ITaskService { let needsConfig = buildError.code === TaskErrors.NotConfigured || buildError.code === TaskErrors.NoBuildTask || buildError.code === TaskErrors.NoTestTask; let needsTerminate = buildError.code === TaskErrors.RunningTask; if (needsConfig || needsTerminate) { - let action: Action = needsConfig - ? this.getConfigureAction(buildError.code) - : new Action( - 'workbench.action.tasks.terminate', - nls.localize('TerminateAction.label', "Terminate Task"), - undefined, true, () => { this.runTerminateCommand(); return TPromise.wrap(undefined); }); - this.notificationService.notify({ severity: buildError.severity, message: buildError.message, actions: { primary: [action] } }); + this.notificationService.prompt(buildError.severity, buildError.message, [{ + label: needsConfig ? ConfigureTaskAction.TEXT : nls.localize('TerminateAction.label', "Terminate Task"), + run: () => { + if (needsConfig) { + this.runConfigureTasks(); + } else { + this.runTerminateCommand(); + } + } + }]); } else { this.notificationService.notify({ severity: buildError.severity, message: buildError.message }); } @@ -1829,21 +1853,18 @@ class TaskService implements ITaskService { return TPromise.as(undefined); } - this.notificationService.notify({ - severity: Severity.Info, - message: nls.localize('TaskService.ignoredFolder', 'The following workspace folders are ignored since they use task version 0.1.0: {0}', this.ignoredWorkspaceFolders.map(f => f.name).join(', ')), - actions: { - secondary: [new Action('dontShowAgain', nls.localize('TaskService.notAgain', 'Don\'t Show Again'), null, true, (notification: IDisposable) => { + this.notificationService.prompt( + Severity.Info, + nls.localize('TaskService.ignoredFolder', 'The following workspace folders are ignored since they use task version 0.1.0: {0}', this.ignoredWorkspaceFolders.map(f => f.name).join(', ')), + [{ + label: nls.localize('TaskService.notAgain', 'Don\'t Show Again'), + isSecondary: true, + run: () => { this.storageService.store(TaskService.IgnoreTask010DonotShowAgain_key, true, StorageScope.WORKSPACE); this.__showIgnoreMessage = false; - - // Hide notification - notification.dispose(); - - return TPromise.as(true); - })] - } - }); + } + }] + ); return TPromise.as(undefined); } @@ -2093,6 +2114,12 @@ class TaskService implements ITaskService { content = content.replace(/(\n)(\t+)/g, (_, s1, s2) => s1 + strings.repeat(' ', s2.length * editorConfig.editor.tabSize)); } configFileCreated = true; + /* __GDPR__ + "taskService.template" : { + "templateId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "autoDetect" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ return this.fileService.createFile(resource, content).then((result): URI => { this.telemetryService.publicLog(TaskService.TemplateTelemetryEventName, { templateId: selection.id, @@ -2319,7 +2346,7 @@ MenuRegistry.addCommand({ id: 'workbench.action.tasks.configureDefaultTestTask', */ // Tasks Output channel. Register it before using it in Task Service. -let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); +let outputChannelRegistry = Registry.as(OutputExt.OutputChannels); outputChannelRegistry.registerChannel(TaskService.OutputChannelId, TaskService.OutputChannelLabel); @@ -2327,7 +2354,7 @@ outputChannelRegistry.registerChannel(TaskService.OutputChannelId, TaskService.O registerSingleton(ITaskService, TaskService); // Register Quick Open -const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); +const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); const tasksPickerContextKey = 'inTasksPicker'; quickOpenRegistry.registerQuickOpenHandler( @@ -2344,7 +2371,7 @@ const actionBarRegistry = Registry.as(ActionBarExtensions.Ac actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionContributor); // Status bar -let statusbarRegistry = Registry.as(StatusbarExtensions.Statusbar); +let statusbarRegistry = Registry.as(StatusbarExtensions.Statusbar); statusbarRegistry.registerStatusbarItem(new StatusbarItemDescriptor(BuildStatusBarItem, StatusbarAlignment.LEFT, 50 /* Medium Priority */)); statusbarRegistry.registerStatusbarItem(new StatusbarItemDescriptor(TaskStatusBarItem, StatusbarAlignment.LEFT, 50 /* Medium Priority */)); diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index 1324147be6..6d0aa8c927 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import fs = require('fs'); -import path = require('path'); +import * as fs from 'fs'; +import * as path from 'path'; import * as nls from 'vs/nls'; import * as Objects from 'vs/base/common/objects'; @@ -16,11 +16,11 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IStringDictionary } from 'vs/base/common/collections'; import { LinkedMap, Touch } from 'vs/base/common/map'; import Severity from 'vs/base/common/severity'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as TPath from 'vs/base/common/paths'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ProblemMatcher, ProblemMatcherRegistry /*, ProblemPattern, getResource */ } from 'vs/workbench/parts/tasks/common/problemMatcher'; @@ -33,7 +33,7 @@ import { IOutputService, IOutputChannel } from 'vs/workbench/parts/output/common import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEventKind } from 'vs/workbench/parts/tasks/common/problemCollectors'; import { Task, CustomTask, ContributedTask, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind, - TaskEvent, TaskEventKind + TaskEvent, TaskEventKind, ShellQuotingOptions, ShellQuoting, CommandString } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskSystem, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, ITaskResolver, @@ -55,13 +55,49 @@ export class TerminalTaskSystem implements ITaskSystem { public static TelemetryEventName: string = 'taskService'; + private static shellQuotes: IStringDictionary = { + 'cmd': { + strong: '"' + }, + 'powershell': { + escape: { + escapeChar: '`', + charsToEscape: ' "\'()' + }, + strong: '\'', + weak: '"' + }, + 'bash': { + escape: { + escapeChar: '\\', + charsToEscape: ' "\'' + }, + strong: '\'', + weak: '"' + }, + 'zsh': { + escape: { + escapeChar: '\\', + charsToEscape: ' "\'' + }, + strong: '\'', + weak: '"' + } + }; + + private static osShellQuotes: IStringDictionary = { + 'linux': TerminalTaskSystem.shellQuotes['bash'], + 'darwin': TerminalTaskSystem.shellQuotes['bash'], + 'win32': TerminalTaskSystem.shellQuotes['powershell'] + }; + private outputChannel: IOutputChannel; private activeTasks: IStringDictionary; private terminals: IStringDictionary; private idleTaskTerminals: LinkedMap; private sameTaskTerminals: IStringDictionary; - private _onDidStateChange: Emitter; + private readonly _onDidStateChange: Emitter; constructor(private terminalService: ITerminalService, private outputService: IOutputService, private markerService: IMarkerService, private modelService: IModelService, @@ -239,6 +275,7 @@ export class TerminalTaskSystem implements ITaskSystem { private executeCommand(task: CustomTask | ContributedTask, trigger: string): TPromise { let terminal: ITerminalInstance = undefined; let executedCommand: string = undefined; + let error: TaskError = undefined; let promise: TPromise = undefined; if (task.isBackground) { promise = new TPromise((resolve, reject) => { @@ -253,11 +290,22 @@ export class TerminalTaskSystem implements ITaskSystem { } else if (event.kind === ProblemCollectorEventKind.BackgroundProcessingEnds) { eventCounter--; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task)); + if (eventCounter === 0) { + let reveal = task.command.presentation.reveal; + if (reveal === RevealKind.Silent && watchingProblemMatcher.numberOfMatches > 0 && watchingProblemMatcher.maxMarkerSeverity >= MarkerSeverity.Error) { + this.terminalService.setActiveInstance(terminal); + this.terminalService.showPanel(false); + } + } } })); watchingProblemMatcher.aboutToStart(); let delayer: Async.Delayer = undefined; - [terminal, executedCommand] = this.createTerminal(task); + [terminal, executedCommand, error] = this.createTerminal(task); + if (error || !terminal) { + return; + } + this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task)); const registeredLinkMatchers = this.registerLinkMatchers(terminal, problemMatchers); const onData = terminal.onLineData((line) => { watchingProblemMatcher.processLine(line); @@ -283,6 +331,11 @@ export class TerminalTaskSystem implements ITaskSystem { this.idleTaskTerminals.set(key, terminal.id.toString(), Touch.AsOld); break; } + let reveal = task.command.presentation.reveal; + if (reveal === RevealKind.Silent && (exitCode !== 0 || watchingProblemMatcher.numberOfMatches > 0 && watchingProblemMatcher.maxMarkerSeverity >= MarkerSeverity.Error)) { + this.terminalService.setActiveInstance(terminal); + this.terminalService.showPanel(false); + } watchingProblemMatcher.done(); watchingProblemMatcher.dispose(); registeredLinkMatchers.forEach(handle => terminal.deregisterLinkMatcher(handle)); @@ -293,17 +346,17 @@ export class TerminalTaskSystem implements ITaskSystem { this._onDidStateChange.fire(event); } eventCounter = 0; - let reveal = task.command.presentation.reveal; - if (exitCode && exitCode === 1 && watchingProblemMatcher.numberOfMatches === 0 && reveal !== RevealKind.Never) { - this.terminalService.setActiveInstance(terminal); - this.terminalService.showPanel(false); - } + this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task)); resolve({ exitCode }); }); }); } else { promise = new TPromise((resolve, reject) => { - [terminal, executedCommand] = this.createTerminal(task); + [terminal, executedCommand, error] = this.createTerminal(task); + if (error || !terminal) { + return; + } + this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task)); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task)); let problemMatchers = this.resolveMatchers(task, task.problemMatchers); let startStopProblemMatcher = new StartStopProblemCollector(problemMatchers, this.markerService, this.modelService); @@ -325,23 +378,28 @@ export class TerminalTaskSystem implements ITaskSystem { this.idleTaskTerminals.set(key, terminal.id.toString(), Touch.AsOld); break; } + let reveal = task.command.presentation.reveal; + if (reveal === RevealKind.Silent && (exitCode !== 0 || startStopProblemMatcher.numberOfMatches > 0 && startStopProblemMatcher.maxMarkerSeverity >= MarkerSeverity.Error)) { + this.terminalService.setActiveInstance(terminal); + this.terminalService.showPanel(false); + } startStopProblemMatcher.done(); startStopProblemMatcher.dispose(); registeredLinkMatchers.forEach(handle => terminal.deregisterLinkMatcher(handle)); this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task)); - // See https://github.com/Microsoft/vscode/issues/31965 - if (exitCode === 0 && startStopProblemMatcher.numberOfMatches > 0) { - exitCode = 1; - } + this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task)); resolve({ exitCode }); }); }); } + if (error) { + return TPromise.wrapError(new Error(error.message)); + } if (!terminal) { return TPromise.wrapError(new Error(`Failed to create terminal for task ${task._label}`)); } - this.terminalService.setActiveInstance(terminal); if (task.command.presentation.reveal === RevealKind.Always || (task.command.presentation.reveal === RevealKind.Silent && task.problemMatchers.length === 0)) { + this.terminalService.setActiveInstance(terminal); this.terminalService.showPanel(task.command.presentation.focus); } this.activeTasks[Task.getMapKey(task)] = { terminal, task, promise }; @@ -390,9 +448,10 @@ export class TerminalTaskSystem implements ITaskSystem { }); } - private createTerminal(task: CustomTask | ContributedTask): [ITerminalInstance, string] { + private createTerminal(task: CustomTask | ContributedTask): [ITerminalInstance, string, TaskError | undefined] { let options = this.resolveOptions(task, task.command.options); let { command, args } = this.resolveCommandAndArgs(task); + let commandExecutable = CommandString.value(command); let workspaceFolder = Task.getWorkspaceFolder(task); let needsFolderQualification = workspaceFolder && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE; let terminalName = nls.localize('TerminalTaskSystem.terminalName', 'Task - {0}', needsFolderQualification ? Task.getQualifiedLabel(task) : task.name); @@ -407,9 +466,6 @@ export class TerminalTaskSystem implements ITaskSystem { let shellLaunchConfig: IShellLaunchConfig = undefined; let isShellCommand = task.command.runtime === RuntimeType.Shell; if (isShellCommand) { - if (Platform.isWindows && ((options.cwd && TPath.isUNC(options.cwd)) || (!options.cwd && TPath.isUNC(process.cwd())))) { - throw new TaskError(Severity.Error, nls.localize('TerminalTaskSystem', 'Can\'t execute a shell command on an UNC drive.'), TaskErrors.UnknownError); - } shellLaunchConfig = { name: terminalName, executable: null, args: null, waitOnExit }; let shellSpecified: boolean = false; let shellOptions: ShellConfiguration = task.command.options && task.command.options.shell; @@ -426,12 +482,15 @@ export class TerminalTaskSystem implements ITaskSystem { } let shellArgs = shellLaunchConfig.args.slice(0); let toAdd: string[] = []; - let commandLine = args && args.length > 0 ? `${command} ${args.join(' ')}` : `${command}`; + let commandLine = this.buildShellCommandLine(shellLaunchConfig.executable, shellOptions, command, args); let windowsShellArgs: boolean = false; if (Platform.isWindows) { windowsShellArgs = true; let basename = path.basename(shellLaunchConfig.executable).toLowerCase(); - if (basename === 'powershell.exe') { + if (basename === 'cmd.exe' && ((options.cwd && TPath.isUNC(options.cwd)) || (!options.cwd && TPath.isUNC(process.cwd())))) { + return [undefined, undefined, new TaskError(Severity.Error, nls.localize('TerminalTaskSystem', 'Can\'t execute a shell command on an UNC drive using cmd.exe.'), TaskErrors.UnknownError)]; + } + if (basename === 'powershell.exe' || basename === 'pwsh.exe') { if (!shellSpecified) { toAdd.push('-Command'); } @@ -468,11 +527,13 @@ export class TerminalTaskSystem implements ITaskSystem { let cwd = options && options.cwd ? options.cwd : process.cwd(); // On Windows executed process must be described absolute. Since we allowed command without an // absolute path (e.g. "command": "node") we need to find the executable in the CWD or PATH. - let executable = Platform.isWindows && !isShellCommand ? this.findExecutable(command, cwd) : command; + let executable = Platform.isWindows && !isShellCommand ? this.findExecutable(commandExecutable, cwd, options) : commandExecutable; + + // When we have a process task there is no need to quote arguments. So we go ahead and take the string value. shellLaunchConfig = { name: terminalName, executable: executable, - args, + args: args.map(a => Types.isString(a) ? a : a.value), waitOnExit }; if (task.command.presentation.echo) { @@ -525,10 +586,10 @@ export class TerminalTaskSystem implements ITaskSystem { } if (terminalToReuse) { terminalToReuse.terminal.reuseTerminal(shellLaunchConfig); - return [terminalToReuse.terminal, command]; + return [terminalToReuse.terminal, commandExecutable, undefined]; } - const result = this.terminalService.createInstance(shellLaunchConfig); + const result = this.terminalService.createTerminal(shellLaunchConfig); const terminalKey = result.id.toString(); result.onDisposed((terminal) => { let terminalData = this.terminals[terminalKey]; @@ -539,33 +600,145 @@ export class TerminalTaskSystem implements ITaskSystem { } }); this.terminals[terminalKey] = { terminal: result, lastTask: taskKey }; - return [result, command]; + return [result, commandExecutable, undefined]; } - private resolveCommandAndArgs(task: CustomTask | ContributedTask): { command: string, args: string[] } { + private buildShellCommandLine(shellExecutable: string, shellOptions: ShellConfiguration, command: CommandString, args: CommandString[]): string { + // If we have no args and the command is a string then use the + // command to stay backwards compatible with the old command line + // model. + if ((!args || args.length === 0) && Types.isString(command)) { + return command; + } + let basename = path.parse(shellExecutable).name.toLowerCase(); + let shellQuoteOptions = this.getOuotingOptions(basename, shellOptions); + + function needsQuotes(value: string): boolean { + if (value.length >= 2) { + let first = value[0] === shellQuoteOptions.strong ? shellQuoteOptions.strong : value[0] === shellQuoteOptions.weak ? shellQuoteOptions.weak : undefined; + if (first === value[value.length - 1]) { + return false; + } + } + for (let i = 0; i < value.length; i++) { + if (value[i] === ' ' && value[i - 1] !== shellQuoteOptions.escape) { + return true; + } + } + return false; + } + + function quote(value: string, kind: ShellQuoting): [string, boolean] { + if (kind === ShellQuoting.Strong && shellQuoteOptions.strong) { + return [shellQuoteOptions.strong + value + shellQuoteOptions.strong, true]; + } else if (kind === ShellQuoting.Weak && shellQuoteOptions.weak) { + return [shellQuoteOptions.weak + value + shellQuoteOptions.weak, true]; + } else if (kind === ShellQuoting.Escape && shellQuoteOptions.escape) { + if (Types.isString(shellQuoteOptions.escape)) { + return [value.replace(/ /g, shellQuoteOptions.escape + ' '), true]; + } else { + let buffer: string[] = []; + for (let ch of shellQuoteOptions.escape.charsToEscape) { + buffer.push(`\\${ch}`); + } + let regexp: RegExp = new RegExp('[' + buffer.join(',') + ']', 'g'); + let escapeChar = shellQuoteOptions.escape.escapeChar; + return [value.replace(regexp, (match) => escapeChar + match), true]; + } + } + return [value, false]; + } + + function quoteIfNecessary(value: CommandString): [string, boolean] { + if (Types.isString(value)) { + if (needsQuotes(value)) { + return quote(value, ShellQuoting.Strong); + } else { + return [value, false]; + } + } else { + return quote(value.value, value.quoting); + } + } + + let result: string[] = []; + let commandQuoted = false; + let argQuoted = false; + let value: string; + let quoted: boolean; + [value, quoted] = quoteIfNecessary(command); + result.push(value); + commandQuoted = quoted; + for (let arg of args) { + [value, quoted] = quoteIfNecessary(arg); + result.push(value); + argQuoted = argQuoted || quoted; + } + + let commandLine = result.join(' '); + // There are special rules quoted command line in cmd.exe + if (Platform.isWindows) { + if (basename === 'cmd' && commandQuoted && argQuoted) { + commandLine = '"' + commandLine + '"'; + } else if (basename === 'powershell' && commandQuoted) { + commandLine = '& ' + commandLine; + } + } + + if (basename === 'cmd' && Platform.isWindows && commandQuoted && argQuoted) { + commandLine = '"' + commandLine + '"'; + } + return commandLine; + } + + private getOuotingOptions(shellBasename: string, shellOptions: ShellConfiguration): ShellQuotingOptions { + if (shellOptions && shellOptions.quoting) { + return shellOptions.quoting; + } + return TerminalTaskSystem.shellQuotes[shellBasename] || TerminalTaskSystem.osShellQuotes[process.platform]; + } + + private resolveCommandAndArgs(task: CustomTask | ContributedTask): { command: CommandString, args: CommandString[] } { // First we need to use the command args: - let args: string[] = task.command.args ? task.command.args.slice() : []; + let args: CommandString[] = task.command.args ? task.command.args.slice() : []; args = this.resolveVariables(task, args); - let command: string = this.resolveVariable(task, task.command.name); + let command: CommandString = this.resolveVariable(task, task.command.name); return { command, args }; } - private findExecutable(command: string, cwd: string): string { + private findExecutable(command: string, cwd: string, options: CommandOptions): string { // If we have an absolute path then we take it. if (path.isAbsolute(command)) { return command; } let dir = path.dirname(command); if (dir !== '.') { - // We have a directory. So leave the command as is. - return command; + // We have a directory and the directory is relative (see above). Make the path absolute + // to the current working directory. + return path.join(cwd, command); + } + let paths: string[] = undefined; + // The options can override the PATH. So consider that PATH if present. + if (options && options.env) { + // Path can be named in many different ways and for the execution it doesn't matter + for (let key of Object.keys(options.env)) { + if (key.toLowerCase() === 'path') { + if (Types.isString(options.env[key])) { + paths = options.env[key].split(path.delimiter); + } + break; + } + } + } + if (paths === void 0 && Types.isString(process.env.PATH)) { + paths = process.env.PATH.split(path.delimiter); + } + // No PATH environment. Make path absolute to the cwd. + if (paths === void 0 || paths.length === 0) { + return path.join(cwd, command); } // We have a simple file name. We get the path variable from the env // and try to find the executable on the path. - if (!process.env.PATH) { - return command; - } - let paths: string[] = (process.env.PATH as string).split(path.delimiter); for (let pathEntry of paths) { // The path entry is absolute. let fullPath: string; @@ -586,10 +759,12 @@ export class TerminalTaskSystem implements ITaskSystem { return withExtension; } } - return command; + return path.join(cwd, command); } - private resolveVariables(task: CustomTask | ContributedTask, value: string[]): string[] { + private resolveVariables(task: CustomTask | ContributedTask, value: string[]): string[]; + private resolveVariables(task: CustomTask | ContributedTask, value: CommandString[]): CommandString[]; + private resolveVariables(task: CustomTask | ContributedTask, value: CommandString[]): CommandString[] { return value.map(s => this.resolveVariable(task, s)); } @@ -624,9 +799,18 @@ export class TerminalTaskSystem implements ITaskSystem { return result; } - private resolveVariable(task: CustomTask | ContributedTask, value: string): string { + private resolveVariable(task: CustomTask | ContributedTask, value: string): string; + private resolveVariable(task: CustomTask | ContributedTask, value: CommandString): CommandString; + private resolveVariable(task: CustomTask | ContributedTask, value: CommandString): CommandString { // TODO@Dirk Task.getWorkspaceFolder should return a WorkspaceFolder that is defined in workspace.ts - return this.configurationResolverService.resolve(Task.getWorkspaceFolder(task), value); + if (Types.isString(value)) { + return this.configurationResolverService.resolve(Task.getWorkspaceFolder(task), value); + } else { + return { + value: this.configurationResolverService.resolve(Task.getWorkspaceFolder(task), value.value), + quoting: value.quoting + }; + } } private resolveOptions(task: CustomTask | ContributedTask, options: CommandOptions): CommandOptions { diff --git a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts index 0adecaba09..cdc72d478f 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as Objects from 'vs/base/common/objects'; import * as Paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; -import Strings = require('vs/base/common/strings'); -import Collections = require('vs/base/common/collections'); +import * as Strings from 'vs/base/common/strings'; +import * as Collections from 'vs/base/common/collections'; import { CommandOptions, Source, ErrorData } from 'vs/base/common/processes'; import { LineProcess } from 'vs/base/node/processes'; @@ -170,14 +170,15 @@ export class ProcessRunnerDetector { } public detect(list: boolean = false, detectSpecific?: string): TPromise { - if (this.taskConfiguration && this.taskConfiguration.command && ProcessRunnerDetector.supports(this.taskConfiguration.command)) { - let config = ProcessRunnerDetector.detectorConfig(this.taskConfiguration.command); + let commandExecutable = TaskConfig.CommandString.value(this.taskConfiguration.command); + if (this.taskConfiguration && this.taskConfiguration.command && ProcessRunnerDetector.supports(commandExecutable)) { + let config = ProcessRunnerDetector.detectorConfig(commandExecutable); let args = (this.taskConfiguration.args || []).concat(config.arg); let options: CommandOptions = this.taskConfiguration.options ? this.resolveCommandOptions(this._workspaceRoot, this.taskConfiguration.options) : { cwd: this._cwd }; let isShellCommand = !!this.taskConfiguration.isShellCommand; return this.runDetection( - new LineProcess(this.taskConfiguration.command, this.configurationResolverService.resolve(this._workspaceRoot, args), isShellCommand, options), - this.taskConfiguration.command, isShellCommand, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list); + new LineProcess(commandExecutable, this.configurationResolverService.resolve(this._workspaceRoot, args.map(a => TaskConfig.CommandString.value(a))), isShellCommand, options), + commandExecutable, isShellCommand, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list); } else { if (detectSpecific) { let detectorPromise: TPromise; diff --git a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts index 02c43d1548..d31116e5e3 100644 --- a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts @@ -12,7 +12,7 @@ import { TPromise, Promise } from 'vs/base/common/winjs.base'; import * as Async from 'vs/base/common/async'; import Severity from 'vs/base/common/severity'; import * as Strings from 'vs/base/common/strings'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { SuccessData, ErrorData } from 'vs/base/common/processes'; import { LineProcess, LineData } from 'vs/base/node/processes'; @@ -54,7 +54,7 @@ export class ProcessTaskSystem implements ITaskSystem { private activeTask: CustomTask; private activeTaskPromise: TPromise; - private _onDidStateChange: Emitter; + private readonly _onDidStateChange: Emitter; constructor(markerService: IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService: IOutputService, configurationResolverService: IConfigurationResolverService, outputChannelId: string) { @@ -206,9 +206,19 @@ export class ProcessTaskSystem implements ITaskSystem { this.clearOutput(); } - let args: string[] = commandConfig.args ? commandConfig.args.slice() : []; + let args: string[] = []; + if (commandConfig.args) { + for (let arg of commandConfig.args) { + if (Types.isString(arg)) { + args.push(arg); + } else { + this.log(`Quoting individual arguments is not supported in the process runner. Using plain value: ${arg.value}`); + args.push(arg.value); + } + } + } args = this.resolveVariables(task, args); - let command: string = this.resolveVariable(task, commandConfig.name); + let command: string = this.resolveVariable(task, Types.isString(commandConfig.name) ? commandConfig.name : commandConfig.name.value); this.childProcess = new LineProcess(command, args, commandConfig.runtime === RuntimeType.Shell, this.resolveOptions(task, commandConfig.options)); telemetryEvent.command = this.childProcess.getSanitizedCommand(); // we have no problem matchers defined. So show the output log diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index 9c04fbab2a..c7769a0b45 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -6,7 +6,7 @@ import * as crypto from 'crypto'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as Objects from 'vs/base/common/objects'; import { IStringDictionary } from 'vs/base/common/collections'; @@ -25,9 +25,47 @@ import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import * as Tasks from '../common/tasks'; import { TaskDefinitionRegistry } from '../common/taskDefinitionRegistry'; +export enum ShellQuoting { + /** + * Default is character escaping. + */ + escape = 1, + + /** + * Default is strong quoting + */ + strong = 2, + + /** + * Default is weak quoting. + */ + weak = 3 +} + +export interface ShellQuotingOptions { + /** + * The character used to do character escaping. + */ + escape?: string | { + escapeChar: string; + charsToEscape: string; + }; + + /** + * The character used for string quoting. + */ + strong?: string; + + /** + * The character used for weak quoting. + */ + weak?: string; +} + export interface ShellConfiguration { executable: string; args?: string[]; + quoting?: ShellQuotingOptions; } export interface CommandOptions { @@ -144,18 +182,25 @@ export interface LegacyCommandProperties { isShellCommand?: boolean | ShellConfiguration; } -export interface BaseCommandProperties { +export type CommandString = string | { value: string, quoting: 'escape' | 'strong' | 'weak' }; - /** - * Whether the task is a shell task or a process task. - */ - runtime?: string; +export namespace CommandString { + export function value(value: CommandString): string { + if (Types.isString(value)) { + return value; + } else { + return value.value; + } + } +} + +export interface BaseCommandProperties { /** * The command to be executed. Can be an external program or a shell * command. */ - command?: string; + command?: CommandString; /** * The command options used when the command is executed. Can be omitted. @@ -166,7 +211,7 @@ export interface BaseCommandProperties { * The arguments passed to the command or additional arguments passed to the * command when using a global command. */ - args?: string[]; + args?: CommandString[]; } @@ -235,6 +280,11 @@ export interface ConfigurationProperties { */ presentation?: PresentationOptions; + /** + * Controls shell options. + */ + options?: CommandOptions; + /** * The problem matcher(s) to use to capture problems in the tasks * output. @@ -266,7 +316,7 @@ export interface BaseTaskRunnerConfiguration { * The command to be executed. Can be an external program or a shell * command. */ - command?: string; + command?: CommandString; /** * @deprecated Use type instead @@ -291,7 +341,7 @@ export interface BaseTaskRunnerConfiguration { /** * The arguments passed to the command. Can be omitted. */ - args?: string[]; + args?: CommandString[]; /** * Controls whether the output view of the running tasks is brought to front or not. @@ -563,7 +613,7 @@ interface ParseContext { namespace ShellConfiguration { - const properties: MetaData[] = [{ property: 'executable' }, { property: 'args' }]; + const properties: MetaData[] = [{ property: 'executable' }, { property: 'args' }, { property: 'quoting' }]; export function is(value: any): value is ShellConfiguration { let candidate: ShellConfiguration = value; @@ -578,6 +628,10 @@ namespace ShellConfiguration { if (config.args !== void 0) { result.args = config.args.slice(); } + if (config.quoting !== void 0) { + result.quoting = Objects.deepClone(config.quoting); + } + return result; } @@ -726,6 +780,24 @@ namespace CommandConfiguration { } } + namespace ShellString { + export function from(this: void, value: CommandString): Tasks.CommandString { + if (value === void 0 || value === null) { + return undefined; + } + if (Types.isString(value)) { + return value; + } + if (Types.isString(value.value)) { + return { + value: value.value, + quoting: Tasks.ShellQuoting.from(value.quoting) + }; + } + return undefined; + } + } + interface BaseCommandConfiguationShape extends BaseCommandProperties, LegacyCommandProperties { } @@ -764,9 +836,8 @@ namespace CommandConfiguration { runtime: undefined, presentation: undefined }; - if (Types.isString(config.command)) { - result.name = config.command; - } + + result.name = ShellString.from(config.command); if (Types.isString(config.type)) { if (config.type === 'shell' || config.type === 'process') { result.runtime = Tasks.RuntimeType.fromString(config.type); @@ -778,14 +849,16 @@ namespace CommandConfiguration { } else if (config.isShellCommand !== void 0) { result.runtime = !!config.isShellCommand ? Tasks.RuntimeType.Shell : Tasks.RuntimeType.Process; } - if (Types.isString(config.runtime)) { - result.runtime = Tasks.RuntimeType.fromString(config.runtime); - } + if (config.args !== void 0) { - if (Types.isStringArray(config.args)) { - result.args = config.args.slice(0); - } else { - context.problemReporter.error(nls.localize('ConfigurationParser.noargs', 'Error: command arguments must be an array of strings. Provided value is:\n{0}', config.args ? JSON.stringify(config.args, undefined, 4) : 'undefined')); + result.args = []; + for (let arg of config.args) { + let converted = ShellString.from(arg); + if (converted !== void 0) { + result.args.push(converted); + } else { + context.problemReporter.error(nls.localize('ConfigurationParser.inValidArg', 'Error: command argument must either be a string or a quoted string. Provided value is:\n{0}', context.problemReporter.error(nls.localize('ConfigurationParser.noargs', 'Error: command arguments must be an array of strings. Provided value is:\n{0}', arg ? JSON.stringify(arg, undefined, 4) : 'undefined')))); + } } } if (config.options !== void 0) { @@ -858,7 +931,7 @@ namespace CommandConfiguration { fillProperty(target, source, 'name'); fillProperty(target, source, 'taskSelector'); fillProperty(target, source, 'suppressTaskName'); - let args: string[] = source.args ? source.args.slice() : []; + let args: Tasks.CommandString[] = source.args ? source.args.slice() : []; if (!target.suppressTaskName) { if (target.taskSelector !== void 0) { args.push(target.taskSelector + taskName); @@ -1043,7 +1116,7 @@ namespace ConfigurationProperties { { property: 'presentation', type: CommandConfiguration.PresentationOptions }, { property: 'problemMatchers' } ]; - export function from(this: void, external: ConfigurationProperties, context: ParseContext, includePresentation: boolean): Tasks.ConfigurationProperties { + export function from(this: void, external: ConfigurationProperties, context: ParseContext, includeCommandOptions: boolean): Tasks.ConfigurationProperties { if (!external) { return undefined; } @@ -1082,9 +1155,12 @@ namespace ConfigurationProperties { result.dependsOn = external.dependsOn.map((task) => { return { workspaceFolder: context.workspaceFolder, task: task }; }); } } - if (includePresentation && (external.presentation !== void 0 || (external as LegacyCommandProperties).terminal !== void 0)) { + if (includeCommandOptions && (external.presentation !== void 0 || (external as LegacyCommandProperties).terminal !== void 0)) { result.presentation = CommandConfiguration.PresentationOptions.from(external, context); } + if (includeCommandOptions && (external.options !== void 0)) { + result.options = CommandOptions.from(external.options, context); + } if (external.problemMatcher) { result.problemMatchers = ProblemMatcherConverter.from(external.problemMatcher, context); } @@ -1328,6 +1404,7 @@ namespace CustomTask { assignProperty(resultConfigProps, configuredProps, 'promptOnClose'); result.command.presentation = CommandConfiguration.PresentationOptions.assignProperties( result.command.presentation, configuredProps.presentation); + result.command.options = CommandOptions.assignProperties(result.command.options, configuredProps.options); let contributedConfigProps: Tasks.ConfigurationProperties = contributedTask; fillProperty(resultConfigProps, contributedConfigProps, 'group'); @@ -1338,6 +1415,7 @@ namespace CustomTask { fillProperty(resultConfigProps, contributedConfigProps, 'promptOnClose'); result.command.presentation = CommandConfiguration.PresentationOptions.fillProperties( result.command.presentation, contributedConfigProps.presentation); + result.command.options = CommandOptions.fillProperties(result.command.options, contributedConfigProps.options); return result; } @@ -1372,17 +1450,6 @@ namespace TaskParser { if (customTask) { CustomTask.fillGlobals(customTask, globals); CustomTask.fillDefaults(customTask, context); - if (context.engine === Tasks.ExecutionEngine.Terminal && customTask.command && customTask.command.name && customTask.command.runtime === Tasks.RuntimeType.Shell && customTask.command.args && customTask.command.args.length > 0) { - if (customTask.command.args.some(hasUnescapedSpaces)) { - context.problemReporter.warn( - nls.localize( - 'taskConfiguration.shellArgs', - 'Warning: the task \'{0}\' is a shell command and one of its arguments might have unescaped spaces. To ensure correct command line quoting please merge args into the command.', - customTask.name - ) - ); - } - } if (schema2_0_0) { if ((customTask.command === void 0 || customTask.command.name === void 0) && (customTask.dependsOn === void 0 || customTask.dependsOn.length === 0)) { context.problemReporter.error(nls.localize( @@ -1461,23 +1528,6 @@ namespace TaskParser { } return target; } - - function hasUnescapedSpaces(this: void, value: string): boolean { - let escapeChar = Platform.isWindows ? '`' : '\\'; - - if (value.length >= 2 && ((value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') || (value.charAt(0) === '\'' && value.charAt(value.length - 1) === '\''))) { - return false; - } - for (let i = 0; i < value.length; i++) { - let ch = value.charAt(i); - if (ch === ' ') { - if (i === 0 || value.charAt(i - 1) !== escapeChar) { - return true; - } - } - } - return false; - } } interface Globals { @@ -1748,13 +1798,14 @@ class ConfigurationParser { if ((!result.custom || result.custom.length === 0) && (globals.command && globals.command.name)) { let matchers: ProblemMatcher[] = ProblemMatcherConverter.from(fileConfig.problemMatcher, context); let isBackground = fileConfig.isBackground ? !!fileConfig.isBackground : fileConfig.isWatching ? !!fileConfig.isWatching : undefined; + let name = Tasks.CommandString.value(globals.command.name); let task: Tasks.CustomTask = { - _id: context.uuidMap.getUUID(globals.command.name), + _id: context.uuidMap.getUUID(name), _source: Objects.assign({}, source, { config: { index: -1, element: fileConfig, workspaceFolder: context.workspaceFolder } }), - _label: globals.command.name, + _label: name, type: 'custom', - name: globals.command.name, - identifier: globals.command.name, + name: name, + identifier: name, group: Tasks.TaskGroup.Build, command: { name: undefined, diff --git a/src/vs/workbench/parts/tasks/test/common/problemMatcher.test.ts b/src/vs/workbench/parts/tasks/test/common/problemMatcher.test.ts index 60834644e4..48e26d833e 100644 --- a/src/vs/workbench/parts/tasks/test/common/problemMatcher.test.ts +++ b/src/vs/workbench/parts/tasks/test/common/problemMatcher.test.ts @@ -6,7 +6,7 @@ import * as matchers from 'vs/workbench/parts/tasks/common/problemMatcher'; -import assert = require('assert'); +import * as assert from 'assert'; import { ValidationState, IProblemReporter, ValidationStatus } from 'vs/base/common/parsers'; class ProblemReporter implements IProblemReporter { @@ -225,7 +225,6 @@ suite('ProblemPatternParser', () => { { regexp: 'test', file: 2, kind: 'file', message: 6 } ]; let parsed = parser.parse(problemPattern); - console.log(reporter.messages); assert(reporter.isOK()); assert.deepEqual(parsed, [{ diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalFindWidget.ts b/src/vs/workbench/parts/terminal/browser/terminalFindWidget.ts similarity index 100% rename from src/vs/workbench/parts/terminal/electron-browser/terminalFindWidget.ts rename to src/vs/workbench/parts/terminal/browser/terminalFindWidget.ts diff --git a/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts b/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts index 4908d52e87..d4bdd8e2c8 100644 --- a/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts +++ b/src/vs/workbench/parts/terminal/browser/terminalQuickOpen.ts @@ -2,9 +2,8 @@ * 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 nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { Mode, IEntryRunContext, IAutoFocus, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen'; import { QuickOpenModel, QuickOpenEntry } from 'vs/base/parts/quickopen/browser/quickOpenModel'; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalTab.ts b/src/vs/workbench/parts/terminal/browser/terminalTab.ts similarity index 89% rename from src/vs/workbench/parts/terminal/electron-browser/terminalTab.ts rename to src/vs/workbench/parts/terminal/browser/terminalTab.ts index cabebf0df8..646070d367 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalTab.ts +++ b/src/vs/workbench/parts/terminal/browser/terminalTab.ts @@ -3,12 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITerminalInstance, IShellLaunchConfig, ITerminalTab, Direction, ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; +import { ITerminalInstance, IShellLaunchConfig, ITerminalTab, Direction, ITerminalService, ITerminalConfigHelper } from 'vs/workbench/parts/terminal/common/terminal'; import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; -import Event, { Emitter, anyEvent } from 'vs/base/common/event'; +import { Event, Emitter, anyEvent } from 'vs/base/common/event'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { SplitView, Orientation, IView } from 'vs/base/browser/ui/splitview/splitview'; import { IPartService, Position } from 'vs/workbench/services/part/common/partService'; @@ -130,7 +127,6 @@ class SplitPaneContainer { this._withDisabledLayout(() => this._splitView.addView(child, size, index)); this.resetSize(); - this._refreshOrderClasses(); this._onDidChange = anyEvent(...this._children.map(c => c.onDidChange)); } @@ -146,26 +142,10 @@ class SplitPaneContainer { this._children.splice(index, 1); this._splitView.removeView(index); this.resetSize(); - this._refreshOrderClasses(); - } - } - - private _refreshOrderClasses(): void { - this._children.forEach((c, i) => { - c.setIsFirst(i === 0); - c.setIsLast(i === this._children.length - 1); - }); - // HACK: Force another layout, this isn't ideal but terminal instance uses the first/last CSS - // rules for sizing the terminal and the layout is performed when the split view is added. - if (this._children.length > 0) { - this.layout(this._width, this._height); } } public layout(width: number, height: number): void { - if (!this._isManuallySized) { - this.resetSize(); - } this._width = width; this._height = height; if (this.orientation === Orientation.HORIZONTAL) { @@ -175,6 +155,9 @@ class SplitPaneContainer { this._children.forEach(c => c.orthogonalLayout(width)); this._splitView.layout(height); } + if (!this._isManuallySized) { + this.resetSize(); + } } public setOrientation(orientation: Orientation): void { @@ -217,7 +200,6 @@ class SplitPane implements IView { public instance: ITerminalInstance; public orientation: Orientation | undefined; protected _size: number; - private _container: HTMLElement | undefined; private _onDidChange: Event = Event.None; public get onDidChange(): Event { return this._onDidChange; } @@ -231,22 +213,9 @@ class SplitPane implements IView { if (!container) { return; } - this._container = container; this.instance.attachToElement(container); } - public setIsFirst(isFirst: boolean): void { - if (this._container) { - this._container.classList.toggle('first', isFirst); - } - } - - public setIsLast(isLast: boolean): void { - if (this._container) { - this._container.classList.toggle('last', isLast); - } - } - public layout(size: number): void { // Only layout when both sizes are known this._size = size; @@ -276,17 +245,16 @@ export class TerminalTab extends Disposable implements ITerminalTab { public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } - private _onDisposed: Emitter; + private readonly _onDisposed: Emitter; public get onDisposed(): Event { return this._onDisposed.event; } - private _onInstancesChanged: Emitter; + private readonly _onInstancesChanged: Emitter; public get onInstancesChanged(): Event { return this._onInstancesChanged.event; } constructor( terminalFocusContextKey: IContextKey, - configHelper: TerminalConfigHelper, + configHelper: ITerminalConfigHelper, private _container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, - @IInstantiationService private readonly _instantiationService: IInstantiationService, @ITerminalService private readonly _terminalService: ITerminalService, @IPartService private readonly _partService: IPartService ) { @@ -294,11 +262,12 @@ export class TerminalTab extends Disposable implements ITerminalTab { this._onDisposed = new Emitter(); this._onInstancesChanged = new Emitter(); - const instance = this._instantiationService.createInstance(TerminalInstance, + const instance = this._terminalService.createInstance( terminalFocusContextKey, configHelper, undefined, - shellLaunchConfig); + shellLaunchConfig, + true); this._terminalInstances.push(instance); this._initInstanceListeners(instance); this._activeInstanceIndex = 0; @@ -420,14 +389,15 @@ export class TerminalTab extends Disposable implements ITerminalTab { public split( terminalFocusContextKey: IContextKey, - configHelper: TerminalConfigHelper, + configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig ): ITerminalInstance { - const instance = this._instantiationService.createInstance(TerminalInstance, + const instance = this._terminalService.createInstance( terminalFocusContextKey, configHelper, undefined, - shellLaunchConfig); + shellLaunchConfig, + true); this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance); this._initInstanceListeners(instance); this._setActiveInstance(instance); diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index ea2561c535..5d14b8b30b 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -2,9 +2,8 @@ * 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 Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { RawContextKey, ContextKeyExpr, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -104,26 +103,35 @@ export interface ITerminalFont { } export interface IShellLaunchConfig { - /** The name of the terminal, if this is not set the name of the process will be used. */ + /** + * The name of the terminal, if this is not set the name of the process will be used. + */ name?: string; - /** The shell executable (bash, cmd, etc.). */ + + /** + * The shell executable (bash, cmd, etc.). + */ executable?: string; + /** * The CLI arguments to use with executable, a string[] is in argv format and will be escaped, * a string is in "CommandLine" pre-escaped format and will be used as is. The string option is * only supported on Windows and will throw an exception if used on macOS or Linux. */ args?: string[] | string; + /** * The current working directory of the terminal, this overrides the `terminal.integrated.cwd` * settings key. */ cwd?: string; + /** * A custom environment for the terminal, if this is not set the environment will be inherited * from the VS Code process. */ env?: { [key: string]: string }; + /** * Whether to ignore a custom cwd from the `terminal.integrated.cwd` settings key (eg. if the * shell is being launched by an extension). @@ -149,14 +157,26 @@ export interface ITerminalService { configHelper: ITerminalConfigHelper; onActiveTabChanged: Event; onTabDisposed: Event; + onInstanceCreated: Event; onInstanceDisposed: Event; onInstanceProcessIdReady: Event; + onInstanceRequestExtHostProcess: Event; onInstancesChanged: Event; onInstanceTitleChanged: Event; terminalInstances: ITerminalInstance[]; terminalTabs: ITerminalTab[]; - createInstance(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; + /** + * Creates a terminal. + * @param shell The shell launch configuration to use. + * @param wasNewTerminalAction Whether this was triggered by a new terminal action, if so a + * default shell selection dialog may display. + */ + createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; + /** + * Creates a raw terminal instance, this should not be used outside of the terminal part. + */ + createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; getInstanceFromId(terminalId: number): ITerminalInstance; getInstanceFromIndex(terminalIndex: number): ITerminalInstance; getTabLabels(): string[]; @@ -164,7 +184,7 @@ export interface ITerminalService { setActiveInstance(terminalInstance: ITerminalInstance): void; setActiveInstanceByIndex(terminalIndex: number): void; getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance; - splitInstance(instance: ITerminalInstance): void; + splitInstance(instance: ITerminalInstance, shell?: IShellLaunchConfig): void; getActiveTab(): ITerminalTab; setActiveTabToNext(): void; @@ -181,6 +201,8 @@ export interface ITerminalService { setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; selectDefaultWindowsShell(): TPromise; setWorkspaceShellAllowed(isAllowed: boolean): void; + + requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): void; } export const enum Direction { @@ -216,9 +238,10 @@ export interface ITerminalInstance { id: number; /** - * The process ID of the shell process. + * The process ID of the shell process, this is undefined when there is no process associated + * with this terminal. */ - processId: number; + processId: number | undefined; /** * An event that fires when the terminal instance's title changes. @@ -234,6 +257,10 @@ export interface ITerminalInstance { onProcessIdReady: Event; + onRequestExtHostProcess: Event; + + processReady: TPromise; + /** * The title of the terminal. This is either title or the process currently running or an * explicit name given to the terminal instance through the extension API. @@ -267,6 +294,12 @@ export interface ITerminalInstance { */ disableLayout: boolean; + /** + * An object that tracks when commands are run and enables navigating and selecting between + * them. + */ + readonly commandTracker: ITerminalCommandTracker; + /** * Dispose the terminal instance, removing it from the panel/service and freeing up resources. */ @@ -406,6 +439,13 @@ export interface ITerminalInstance { */ setVisible(visible: boolean): void; + /** + * Attach a listener to the raw data stream coming from the pty, including ANSI escape + * sequecnes. + * @param listener The listener function. + */ + onData(listener: (data: string) => void): IDisposable; + /** * Attach a listener to listen for new lines added to this terminal instance. * @@ -440,3 +480,67 @@ export interface ITerminalInstance { addDisposable(disposable: IDisposable): void; } + +export interface ITerminalCommandTracker { + scrollToPreviousCommand(): void; + scrollToNextCommand(): void; + selectToPreviousCommand(): void; + selectToNextCommand(): void; +} + +export interface ITerminalProcessManager extends IDisposable { + readonly processState: ProcessState; + readonly ptyProcessReady: TPromise; + readonly shellProcessId: number; + readonly initialCwd: string; + + readonly onProcessReady: Event; + readonly onProcessData: Event; + readonly onProcessTitle: Event; + readonly onProcessExit: Event; + + addDisposable(disposable: IDisposable); + createProcess(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number); + write(data: string): void; + setDimensions(cols: number, rows: number): void; +} + +export enum ProcessState { + // The process has not been initialized yet. + UNINITIALIZED, + // The process is currently launching, the process is marked as launching + // for a short duration after being created and is helpful to indicate + // whether the process died as a result of bad shell and args. + LAUNCHING, + // The process is running normally. + RUNNING, + // The process was killed during launch, likely as a result of bad shell and + // args. + KILLED_DURING_LAUNCH, + // The process was killed by the user (the event originated from VS Code). + KILLED_BY_USER, + // The process was killed by itself, for example the shell crashed or `exit` + // was run. + KILLED_BY_PROCESS +} + + +export interface ITerminalProcessExtHostProxy extends IDisposable { + readonly terminalId: number; + + emitData(data: string): void; + emitTitle(title: string): void; + emitPid(pid: number): void; + emitExit(exitCode: number): void; + + onInput(listener: (data: string) => void): void; + onResize(listener: (cols: number, rows: number) => void): void; + onShutdown(listener: () => void): void; +} + +export interface ITerminalProcessExtHostRequest { + proxy: ITerminalProcessExtHostProxy; + shellLaunchConfig: IShellLaunchConfig; + cols: number; + rows: number; +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.ts b/src/vs/workbench/parts/terminal/common/terminalColorRegistry.ts similarity index 99% rename from src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.ts rename to src/vs/workbench/parts/terminal/common/terminalColorRegistry.ts index cdf3fbfcc6..bd833c28d0 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.ts +++ b/src/vs/workbench/parts/terminal/common/terminalColorRegistry.ts @@ -165,5 +165,4 @@ export function registerColors(): void { let colorName = id.substring(13); ansiColorIdentifiers[entry.index] = registerColor(id, entry.defaults, nls.localize('terminal.ansiColor', '\'{0}\' ANSI color in the terminal.', colorName)); } - } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalCommands.ts b/src/vs/workbench/parts/terminal/common/terminalCommands.ts similarity index 100% rename from src/vs/workbench/parts/terminal/electron-browser/terminalCommands.ts rename to src/vs/workbench/parts/terminal/common/terminalCommands.ts diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index d2432220cb..6324f6411d 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as errors from 'vs/base/common/errors'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TERMINAL_PANEL_ID, ITerminalTab } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TERMINAL_PANEL_ID, ITerminalTab, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest } from 'vs/workbench/parts/terminal/common/terminal'; import { TPromise } from 'vs/base/common/winjs.base'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -22,27 +22,32 @@ export abstract class TerminalService implements ITerminalService { protected _terminalFocusContextKey: IContextKey; protected _findWidgetVisible: IContextKey; protected _terminalContainer: HTMLElement; - protected _onInstancesChanged: Emitter; - protected _onTabDisposed: Emitter; - protected _onInstanceDisposed: Emitter; - protected _onInstanceProcessIdReady: Emitter; - protected _onInstanceTitleChanged: Emitter; protected _terminalTabs: ITerminalTab[]; protected abstract _terminalInstances: ITerminalInstance[]; private _activeTabIndex: number; - private _onActiveTabChanged: Emitter; public get activeTabIndex(): number { return this._activeTabIndex; } - public get onActiveTabChanged(): Event { return this._onActiveTabChanged.event; } - public get onTabDisposed(): Event { return this._onTabDisposed.event; } - public get onInstanceDisposed(): Event { return this._onInstanceDisposed.event; } - public get onInstanceProcessIdReady(): Event { return this._onInstanceProcessIdReady.event; } - public get onInstanceTitleChanged(): Event { return this._onInstanceTitleChanged.event; } - public get onInstancesChanged(): Event { return this._onInstancesChanged.event; } public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } public get terminalTabs(): ITerminalTab[] { return this._terminalTabs; } + private readonly _onActiveTabChanged: Emitter = new Emitter(); + public get onActiveTabChanged(): Event { return this._onActiveTabChanged.event; } + protected readonly _onInstanceCreated: Emitter = new Emitter(); + public get onInstanceCreated(): Event { return this._onInstanceCreated.event; } + protected readonly _onInstanceDisposed: Emitter = new Emitter(); + public get onInstanceDisposed(): Event { return this._onInstanceDisposed.event; } + protected readonly _onInstanceProcessIdReady: Emitter = new Emitter(); + public get onInstanceProcessIdReady(): Event { return this._onInstanceProcessIdReady.event; } + protected readonly _onInstanceRequestExtHostProcess: Emitter = new Emitter(); + public get onInstanceRequestExtHostProcess(): Event { return this._onInstanceRequestExtHostProcess.event; } + protected readonly _onInstancesChanged: Emitter = new Emitter(); + public get onInstancesChanged(): Event { return this._onInstancesChanged.event; } + protected readonly _onInstanceTitleChanged: Emitter = new Emitter(); + public get onInstanceTitleChanged(): Event { return this._onInstanceTitleChanged.event; } + protected readonly _onTabDisposed: Emitter = new Emitter(); + public get onTabDisposed(): Event { return this._onTabDisposed.event; } + public abstract get configHelper(): ITerminalConfigHelper; constructor( @@ -55,13 +60,6 @@ export abstract class TerminalService implements ITerminalService { this._activeTabIndex = 0; this._isShuttingDown = false; - this._onActiveTabChanged = new Emitter(); - this._onTabDisposed = new Emitter(); - this._onInstanceDisposed = new Emitter(); - this._onInstanceProcessIdReady = new Emitter(); - this._onInstanceTitleChanged = new Emitter(); - this._onInstancesChanged = new Emitter(); - lifecycleService.onWillShutdown(event => event.veto(this._onWillShutdown())); lifecycleService.onShutdown(() => this._onShutdown()); this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); @@ -72,10 +70,12 @@ export abstract class TerminalService implements ITerminalService { } protected abstract _showTerminalCloseConfirmation(): TPromise; - public abstract createInstance(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; + public abstract createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance; + public abstract createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance; public abstract getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance; public abstract selectDefaultWindowsShell(): TPromise; public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; + public abstract requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): void; private _restoreTabs(): void { if (!this.configHelper.config.experimentalRestore) { @@ -93,7 +93,7 @@ export abstract class TerminalService implements ITerminalService { } tabConfigs.forEach(tabConfig => { - const instance = this.createInstance(tabConfig.instances[0]); + const instance = this.createTerminal(tabConfig.instances[0]); for (let i = 1; i < tabConfig.instances.length; i++) { this.splitInstance(instance, tabConfig.instances[i]); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css index 1f191f4dd3..410de5eb02 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css @@ -33,10 +33,10 @@ bottom: 2px; /* Matches padding-bottom on .terminal-outer-container */ top: 0; } -.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view.first .terminal-wrapper { +.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view:first-child .terminal-wrapper { margin-left: 20px; } -.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view.last .terminal-wrapper { +.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view:last-child .terminal-wrapper { margin-right: 20px; } @@ -52,7 +52,7 @@ .monaco-workbench .panel.integrated-terminal .xterm-viewport { margin-right: -10px; } -.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view.last .xterm-viewport { +.monaco-workbench .panel.integrated-terminal .monaco-split-view2.horizontal .split-view-view:last-child .xterm-viewport { margin-right: -20px; } @@ -95,11 +95,6 @@ font-weight: normal !important; } -.monaco-workbench .panel.integrated-terminal .xterm a.active { - cursor: pointer; - text-decoration: underline; -} - /* Use the default cursor when alt is active to help with clicking to move cursor */ .monaco-workbench .panel.integrated-terminal .terminal-outer-container.alt-active .xterm { cursor: default; @@ -111,7 +106,7 @@ left: 0; user-select: none; } -.monaco-workbench .panel.integrated-terminal .monaco-split-view2.vertical .split-view-view:not(.last) .xterm { +.monaco-workbench .panel.integrated-terminal .monaco-split-view2.vertical .split-view-view:not(:last-child) .xterm { /* When vertical and NOT the bottom terminal, align to the top instead to prevent the output jumping around erratically */ top: 0; bottom: auto; @@ -161,8 +156,8 @@ .vs-dark .monaco-workbench .terminal-action.split, .hc-black .monaco-workbench .terminal-action.split { background: url('split-inverse.svg') center center no-repeat; } .vs-dark .monaco-workbench .panel.right .terminal-action.split, .hc-black .monaco-workbench .panel.right .terminal-action.split { background: url('split-horizontal-inverse.svg') center center no-repeat; } -.vs-dark .monaco-workbench.mac .panel.integrated-terminal .terminal:not(.enable-mouse-events), -.hc-black .monaco-workbench.mac .panel.integrated-terminal .terminal:not(.enable-mouse-events) { +.vs-dark .monaco-workbench.mac .panel.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events), +.hc-black .monaco-workbench.mac .panel.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events) { cursor: -webkit-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAL0lEQVQoz2NgCD3x//9/BhBYBWdhgFVAiVW4JBFKGIa4AqD0//9D3pt4I4tAdAMAHTQ/j5Zom30AAAAASUVORK5CYII=') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC') 2x) 5 8, text; } diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css index 2e853d4725..ff96cfb32e 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css @@ -44,8 +44,6 @@ font-feature-settings: "liga" 0; position: relative; user-select: none; - -ms-user-select: none; - -webkit-user-select: none; } .xterm.focus, @@ -121,11 +119,13 @@ visibility: hidden; } -.xterm .xterm-char-measure-element { +.xterm-char-measure-element { display: inline-block; visibility: hidden; position: absolute; + top: 0; left: -9999em; + line-height: normal; } .xterm.enable-mouse-events { @@ -159,3 +159,7 @@ height: 1px; overflow: hidden; } + +.xterm-cursor-pointer { + cursor: pointer !important; +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index edc218ec60..b2ac3c3501 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -11,14 +11,14 @@ import * as debugActions from 'vs/workbench/parts/debug/browser/debugActions'; import * as nls from 'vs/nls'; import * as panel from 'vs/workbench/browser/panel'; import * as platform from 'vs/base/common/platform'; -import * as terminalCommands from 'vs/workbench/parts/terminal/electron-browser/terminalCommands'; +import * as terminalCommands from 'vs/workbench/parts/terminal/common/terminalCommands'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TerminalCursorStyle } from 'vs/workbench/parts/terminal/common/terminal'; -import { getTerminalDefaultShellUnixLike, getTerminalDefaultShellWindows } from 'vs/workbench/parts/terminal/electron-browser/terminal'; +import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TerminalCursorStyle, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE } from 'vs/workbench/parts/terminal/common/terminal'; +import { getTerminalDefaultShellUnixLike, getTerminalDefaultShellWindows } from 'vs/workbench/parts/terminal/node/terminal'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, ClearSelectionTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, MoveToLineStartTerminalAction, MoveToLineEndTerminalAction, SplitTerminalAction, SplitInActiveWorkspaceTerminalAction, FocusPreviousPaneTerminalAction, FocusNextPaneTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, ResizePaneDownTerminalAction, ScrollToPreviousCommandAction, ScrollToNextCommandAction, SelectToPreviousCommandAction, SelectToNextCommandAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -28,7 +28,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { OpenNextRecentlyUsedEditorInGroupAction, OpenPreviousRecentlyUsedEditorInGroupAction, FocusActiveGroupAction, FocusFirstGroupAction, FocusSecondGroupAction, FocusThirdGroupAction } from 'vs/workbench/browser/parts/editor/editorActions'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { registerColors } from './terminalColorRegistry'; +import { registerColors } from 'vs/workbench/parts/terminal/common/terminalColorRegistry'; import { NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction } from 'vs/workbench/electron-browser/actions'; import { QUICKOPEN_ACTION_ID, getQuickNavigateHandler, QUICKOPEN_FOCUS_SECONDARY_ACTION_ID } from 'vs/workbench/browser/parts/quickopen/quickopen'; import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; @@ -38,7 +38,7 @@ import { TogglePanelAction } from 'vs/workbench/browser/parts/panel/panelActions import { TerminalPanel } from 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; import { TerminalPickerHandler } from 'vs/workbench/parts/terminal/browser/terminalQuickOpen'; -const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); +const quickOpenRegistry = (Registry.as(QuickOpenExtensions.Quickopen)); const inTerminalsPicker = 'inTerminalPicker'; @@ -61,12 +61,12 @@ CommandsRegistry.registerCommand( { id: quickOpenNavigatePreviousInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigatePreviousInTerminalPickerId, false) }); -const registry = Registry.as(ActionExtensions.WorkbenchActions); +const registry = Registry.as(ActionExtensions.WorkbenchActions); registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenTermAction, QuickOpenTermAction.ID, QuickOpenTermAction.LABEL), 'Terminal: Switch Active Terminal', nls.localize('terminal', "Terminal")); const actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionTermContributor); -let configurationRegistry = Registry.as(Extensions.Configuration); +let configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration({ 'id': 'terminal', 'order': 100, @@ -244,6 +244,7 @@ configurationRegistry.registerConfiguration({ ScrollUpPageTerminalAction.ID, ScrollToTopTerminalAction.ID, ClearTerminalAction.ID, + ClearSelectionTerminalAction.ID, debugActions.StartAction.ID, debugActions.StopAction.ID, debugActions.RunAction.ID, @@ -274,27 +275,41 @@ configurationRegistry.registerConfiguration({ TogglePanelAction.ID, 'workbench.action.quickOpenView', SplitTerminalAction.ID, + SplitInActiveWorkspaceTerminalAction.ID, FocusPreviousPaneTerminalAction.ID, FocusNextPaneTerminalAction.ID, ResizePaneLeftTerminalAction.ID, ResizePaneRightTerminalAction.ID, ResizePaneUpTerminalAction.ID, - ResizePaneDownTerminalAction.ID + ResizePaneDownTerminalAction.ID, + ScrollToPreviousCommandAction.ID, + ScrollToNextCommandAction.ID, + SelectToPreviousCommandAction.ID, + SelectToNextCommandAction.ID ].sort() }, 'terminal.integrated.env.osx': { 'description': nls.localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on OS X"), 'type': 'object', + 'additionalProperties': { + 'type': ['string', 'null'] + }, 'default': {} }, 'terminal.integrated.env.linux': { 'description': nls.localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux"), 'type': 'object', + 'additionalProperties': { + 'type': ['string', 'null'] + }, 'default': {} }, 'terminal.integrated.env.windows': { 'description': nls.localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows"), 'type': 'object', + 'additionalProperties': { + 'type': ['string', 'null'] + }, 'default': {} }, 'terminal.integrated.showExitAlert': { @@ -323,7 +338,7 @@ registerSingleton(ITerminalService, TerminalService); // On mac cmd+` is reserved to cycle between windows, that's why the keybindings use WinCtrl const category = nls.localize('terminalCategory', "Terminal"); -let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); +let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.LABEL), 'Terminal: Kill the Active Terminal Instance', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_C, @@ -333,6 +348,10 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTermina primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK } }), 'Terminal: Create New Integrated Terminal', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearSelectionTerminalAction, ClearSelectionTerminalAction.ID, ClearSelectionTerminalAction.LABEL, { + primary: KeyCode.Escape, + linux: { primary: KeyCode.Escape } +}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE)), 'Terminal: Escape selection', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewInActiveWorkspaceTerminalAction, CreateNewInActiveWorkspaceTerminalAction.ID, CreateNewInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (In Active Workspace)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category); @@ -359,7 +378,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAc mac: { primary: KeyMod.WinCtrl | KeyCode.US_BACKTICK } }), 'View: Toggle Integrated Terminal', nls.localize('viewCategory', "View")); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownTerminalAction, ScrollDownTerminalAction.ID, ScrollDownTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.DownArrow, + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageDown, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Line)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownPageTerminalAction, ScrollDownPageTerminalAction.ID, ScrollDownPageTerminalAction.LABEL, { @@ -371,7 +390,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToBottomTe linux: { primary: KeyMod.Shift | KeyCode.End } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Bottom', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpTerminalAction, ScrollUpTerminalAction.ID, ScrollUpTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.UpArrow, + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageUp, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Line)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpPageTerminalAction, ScrollUpPageTerminalAction.ID, ScrollUpPageTerminalAction.LABEL, { @@ -429,6 +448,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitTerminalAct secondary: [KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_5] } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitInActiveWorkspaceTerminalAction, SplitInActiveWorkspaceTerminalAction.ID, SplitInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Split Terminal (In Active Workspace)', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, { primary: KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.Alt | KeyCode.UpArrow], @@ -446,21 +466,41 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTer } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Next Pane', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow, + primary: null, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow }, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Left', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow, + primary: null, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow }, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Right', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow, + primary: null, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.UpArrow } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Up', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow, + primary: null, + linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.DownArrow } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Down', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToPreviousCommandAction, ScrollToPreviousCommandAction.ID, ScrollToPreviousCommandAction.LABEL, { + primary: null, + mac: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Previous Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToNextCommandAction, ScrollToNextCommandAction.ID, ScrollToNextCommandAction.LABEL, { + primary: null, + mac: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll To Next Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousCommandAction, SelectToPreviousCommandAction.ID, SelectToPreviousCommandAction.LABEL, { + primary: null, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Previous Command', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextCommandAction, SelectToNextCommandAction.ID, SelectToNextCommandAction.LABEL, { + primary: null, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow } +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Next Command', category); terminalCommands.setup(); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index e5e2693f84..0a1bf445aa 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -46,7 +46,11 @@ export class ToggleTerminalAction extends TogglePanelAction { if (this.terminalService.terminalInstances.length === 0) { // If there is not yet an instance attempt to create it here so that we can suggest a // new shell on Windows (and not do so when the panel is restored on reload). - this.terminalService.createInstance(undefined, true); + const newTerminalInstance = this.terminalService.createTerminal(undefined, true); + const toDispose = newTerminalInstance.onProcessIdReady(() => { + newTerminalInstance.focus(); + toDispose.dispose(); + }); } return super.run(); } @@ -254,7 +258,7 @@ export class CreateNewTerminalAction extends Action { if (folders.length <= 1) { // Allow terminal service to handle the path when there is only a // single root - instancePromise = TPromise.as(this.terminalService.createInstance(undefined, true)); + instancePromise = TPromise.as(this.terminalService.createTerminal(undefined, true)); } else { const options: IPickOptions = { placeHolder: nls.localize('workbench.action.terminal.newWorkspacePlaceholder', "Select current working directory for new terminal") @@ -264,7 +268,7 @@ export class CreateNewTerminalAction extends Action { // Don't create the instance if the workspace picker was canceled return null; } - return this.terminalService.createInstance({ cwd: workspace.uri.fsPath }, true); + return this.terminalService.createTerminal({ cwd: workspace.uri.fsPath }, true); }); } @@ -291,7 +295,7 @@ export class CreateNewInActiveWorkspaceTerminalAction extends Action { } public run(event?: any): TPromise { - const instance = this.terminalService.createInstance(undefined, true); + const instance = this.terminalService.createTerminal(undefined, true); if (!instance) { return TPromise.as(void 0); } @@ -306,11 +310,57 @@ export class SplitTerminalAction extends Action { constructor( id: string, label: string, - @ITerminalService private readonly _terminalService: ITerminalService + @ITerminalService private readonly _terminalService: ITerminalService, + @ICommandService private commandService: ICommandService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(id, label, 'terminal-action split'); } + public run(event?: any): TPromise { + const instance = this._terminalService.getActiveInstance(); + if (!instance) { + return TPromise.as(void 0); + } + + const folders = this.workspaceContextService.getWorkspace().folders; + + let pathPromise: TPromise = TPromise.as({}); + if (folders.length > 1) { + // Only choose a path when there's more than 1 folder + const options: IPickOptions = { + placeHolder: nls.localize('workbench.action.terminal.newWorkspacePlaceholder', "Select current working directory for new terminal") + }; + pathPromise = this.commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND_ID, [options]).then(workspace => { + if (!workspace) { + // Don't split the instance if the workspace picker was canceled + return null; + } + return TPromise.as({ cwd: workspace.uri.fsPath }); + }); + } + + return pathPromise.then(path => { + if (!path) { + return TPromise.as(void 0); + } + this._terminalService.splitInstance(instance, path); + return this._terminalService.showPanel(true); + }); + } +} + +export class SplitInActiveWorkspaceTerminalAction extends Action { + public static readonly ID = 'workbench.action.terminal.splitInActiveWorkspace'; + public static readonly LABEL = nls.localize('workbench.action.terminal.splitInActiveWorkspace', "Split Terminal (In Active Workspace)"); + + constructor( + id: string, label: string, + @ITerminalService private readonly _terminalService: ITerminalService + ) { + super(id, label); + } + public run(event?: any): TPromise { const instance = this._terminalService.getActiveInstance(); if (!instance) { @@ -783,6 +833,27 @@ export class ClearTerminalAction extends Action { } } +export class ClearSelectionTerminalAction extends Action { + + public static readonly ID = 'workbench.action.terminal.clearSelection'; + public static readonly LABEL = nls.localize('workbench.action.terminal.clearSelection', "Clear Selection"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(event?: any): TPromise { + let terminalInstance = this.terminalService.getActiveInstance(); + if (terminalInstance && terminalInstance.hasSelection()) { + terminalInstance.clearSelection(); + } + return TPromise.as(void 0); + } +} + export class AllowWorkspaceShellTerminalCommand extends Action { public static readonly ID = 'workbench.action.terminal.allowWorkspaceShell'; @@ -977,3 +1048,87 @@ export class RenameTerminalQuickOpenAction extends RenameTerminalAction { return TPromise.as(null); } } + +export class ScrollToPreviousCommandAction extends Action { + public static readonly ID = 'workbench.action.terminal.scrollToPreviousCommand'; + public static readonly LABEL = nls.localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(): TPromise { + const instance = this.terminalService.getActiveInstance(); + if (instance) { + instance.commandTracker.scrollToPreviousCommand(); + instance.focus(); + } + return TPromise.as(void 0); + } +} + +export class ScrollToNextCommandAction extends Action { + public static readonly ID = 'workbench.action.terminal.scrollToNextCommand'; + public static readonly LABEL = nls.localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(): TPromise { + const instance = this.terminalService.getActiveInstance(); + if (instance) { + instance.commandTracker.scrollToNextCommand(); + instance.focus(); + } + return TPromise.as(void 0); + } +} + +export class SelectToPreviousCommandAction extends Action { + public static readonly ID = 'workbench.action.terminal.selectToPreviousCommand'; + public static readonly LABEL = nls.localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(): TPromise { + const instance = this.terminalService.getActiveInstance(); + if (instance) { + instance.commandTracker.selectToPreviousCommand(); + instance.focus(); + } + return TPromise.as(void 0); + } +} + +export class SelectToNextCommandAction extends Action { + public static readonly ID = 'workbench.action.terminal.selectToNextCommand'; + public static readonly LABEL = nls.localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(): TPromise { + const instance = this.terminalService.getActiveInstance(); + if (instance) { + instance.commandTracker.selectToNextCommand(); + instance.focus(); + } + return TPromise.as(void 0); + } +} diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index 877a6305e5..dd4edf8552 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -12,9 +12,9 @@ import { IWorkspaceConfigurationService } from 'vs/workbench/services/configurat import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION } from 'vs/workbench/parts/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; -import { isFedora } from 'vs/workbench/parts/terminal/electron-browser/terminal'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { isFedora } from 'vs/workbench/parts/terminal/node/terminal'; import { Terminal as XTermTerminal } from 'vscode-xterm'; +import { INotificationService } from 'vs/platform/notification/common/notification'; const DEFAULT_LINE_HEIGHT = 1.0; @@ -35,7 +35,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { public constructor( @IConfigurationService private readonly _configurationService: IConfigurationService, @IWorkspaceConfigurationService private readonly _workspaceConfigurationService: IWorkspaceConfigurationService, - @IChoiceService private readonly _choiceService: IChoiceService, + @INotificationService private readonly _notificationService: INotificationService, @IStorageService private readonly _storageService: IStorageService ) { this._updateConfig(); @@ -163,18 +163,16 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { } else { // if (shellArgsConfigValue.workspace !== undefined) changeString = `shellArgs: ${argsString}`; } - const message = nls.localize('terminal.integrated.allowWorkspaceShell', "Do you allow {0} (defined as a workspace setting) to be launched in the terminal?", changeString); - const options = [nls.localize('allow', "Allow"), nls.localize('disallow', "Disallow")]; - this._choiceService.choose(Severity.Info, message, options).then(choice => { - switch (choice) { - case 0: /* Allow */ - this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, true, StorageScope.WORKSPACE); - break; - case 1: /* Disallow */ - this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, false, StorageScope.WORKSPACE); - break; - } - }); + this._notificationService.prompt(Severity.Info, nls.localize('terminal.integrated.allowWorkspaceShell', "Do you allow {0} (defined as a workspace setting) to be launched in the terminal?", changeString), + [{ + label: nls.localize('allow', "Allow"), + run: () => this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, true, StorageScope.WORKSPACE) + }, + { + label: nls.localize('disallow', "Disallow"), + run: () => this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, false, StorageScope.WORKSPACE) + }] + ); } shell.executable = (isWorkspaceShellAllowed ? shellConfigValue.value : shellConfigValue.user) || shellConfigValue.default; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f8caec9e20..413dc3e4e8 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -3,23 +3,18 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from 'child_process'; -import * as os from 'os'; -import * as path from 'path'; import * as lifecycle from 'vs/base/common/lifecycle'; import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; -import Event, { Emitter } from 'vs/base/common/event'; -import Uri from 'vs/base/common/uri'; -import { WindowsShellHelper } from 'vs/workbench/parts/terminal/electron-browser/windowsShellHelper'; +import * as paths from 'vs/base/common/paths'; +import { Event, Emitter } from 'vs/base/common/event'; +import { WindowsShellHelper } from 'vs/workbench/parts/terminal/node/windowsShellHelper'; import { Terminal as XTermTerminal } from 'vscode-xterm'; -import { Dimension } from 'vs/base/browser/builder'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { IStringDictionary } from 'vs/base/common/collections'; -import { ITerminalInstance, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalInstance, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, IShellLaunchConfig, ITerminalProcessManager, ProcessState } from 'vs/workbench/parts/terminal/common/terminal'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { TabFocus } from 'vs/editor/common/config/commonEditorConfig'; @@ -30,152 +25,110 @@ import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } import { scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { TPromise } from 'vs/base/common/winjs.base'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import pkg from 'vs/platform/node/package'; -import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; +import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/common/terminalColorRegistry'; import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; -import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ILogService } from 'vs/platform/log/common/log'; - -/** The amount of time to consider terminal errors to be related to the launch */ -const LAUNCHING_DURATION = 500; +import { TerminalCommandTracker } from 'vs/workbench/parts/terminal/node/terminalCommandTracker'; +import { TerminalProcessManager } from './terminalProcessManager'; let Terminal: typeof XTermTerminal; -enum ProcessState { - // The process has not been initialized yet. - UNINITIALIZED, - // The process is currently launching, the process is marked as launching - // for a short duration after being created and is helpful to indicate - // whether the process died as a result of bad shell and args. - LAUNCHING, - // The process is running normally. - RUNNING, - // The process was killed during launch, likely as a result of bad shell and - // args. - KILLED_DURING_LAUNCH, - // The process was killed by the user (the event originated from VS Code). - KILLED_BY_USER, - // The process was killed by itself, for example the shell crashed or `exit` - // was run. - KILLED_BY_PROCESS -} - export class TerminalInstance implements ITerminalInstance { private static readonly EOL_REGEX = /\r?\n/g; - private static _lastKnownDimensions: Dimension = null; + private static _lastKnownDimensions: dom.Dimension = null; private static _idCounter = 1; + private _processManager: ITerminalProcessManager | undefined; + private _id: number; private _isExiting: boolean; private _hadFocusOnExit: boolean; private _isVisible: boolean; - private _processState: ProcessState; - private _processReady: TPromise; private _isDisposed: boolean; - private _onDisposed: Emitter; - private _onFocused: Emitter; - private _onProcessIdReady: Emitter; - private _onTitleChanged: Emitter; - private _process: cp.ChildProcess; - private _processId: number; private _skipTerminalCommands: string[]; private _title: string; - private _instanceDisposables: lifecycle.IDisposable[]; - private _processDisposables: lifecycle.IDisposable[]; private _wrapperElement: HTMLDivElement; private _xterm: XTermTerminal; private _xtermElement: HTMLDivElement; private _terminalHasTextContextKey: IContextKey; private _cols: number; private _rows: number; - private _messageTitleListener: (message: { type: string, content: string }) => void; - private _preLaunchInputQueue: string; - private _initialCwd: string; private _windowsShellHelper: WindowsShellHelper; private _onLineDataListeners: ((lineData: string) => void)[]; private _xtermReadyPromise: TPromise; + private _disposables: lifecycle.IDisposable[]; + private _messageTitleDisposable: lifecycle.IDisposable; + private _widgetManager: TerminalWidgetManager; private _linkHandler: TerminalLinkHandler; + private _commandTracker: TerminalCommandTracker; public disableLayout: boolean; public get id(): number { return this._id; } - public get processId(): number { return this._processId; } - public get onDisposed(): Event { return this._onDisposed.event; } - public get onFocused(): Event { return this._onFocused.event; } - public get onProcessIdReady(): Event { return this._onProcessIdReady.event; } - public get onTitleChanged(): Event { return this._onTitleChanged.event; } + // TODO: Ideally processId would be merged into processReady + public get processId(): number | undefined { return this._processManager ? this._processManager.shellProcessId : undefined; } + // TODO: How does this work with detached processes? + // TODO: Should this be an event as it can fire twice? + public get processReady(): TPromise { return this._processManager ? this._processManager.ptyProcessReady : TPromise.as(void 0); } public get title(): string { return this._title; } public get hadFocusOnExit(): boolean { return this._hadFocusOnExit; } - public get isTitleSetByProcess(): boolean { return !!this._messageTitleListener; } + public get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; } public get shellLaunchConfig(): IShellLaunchConfig { return Object.freeze(this._shellLaunchConfig); } + public get commandTracker(): TerminalCommandTracker { return this._commandTracker; } + + + private readonly _onDisposed: Emitter = new Emitter(); + public get onDisposed(): Event { return this._onDisposed.event; } + private readonly _onFocused: Emitter = new Emitter(); + public get onFocused(): Event { return this._onFocused.event; } + private readonly _onProcessIdReady: Emitter = new Emitter(); + public get onProcessIdReady(): Event { return this._onProcessIdReady.event; } + private readonly _onTitleChanged: Emitter = new Emitter(); + public get onTitleChanged(): Event { return this._onTitleChanged.event; } + private readonly _onRequestExtHostProcess: Emitter = new Emitter(); + public get onRequestExtHostProcess(): Event { return this._onRequestExtHostProcess.event; } public constructor( private _terminalFocusContextKey: IContextKey, private _configHelper: TerminalConfigHelper, private _container: HTMLElement, private _shellLaunchConfig: IShellLaunchConfig, + doCreateProcess: boolean, @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IKeybindingService private readonly _keybindingService: IKeybindingService, @INotificationService private readonly _notificationService: INotificationService, @IPanelService private readonly _panelService: IPanelService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IClipboardService private readonly _clipboardService: IClipboardService, - @IHistoryService private readonly _historyService: IHistoryService, @IThemeService private readonly _themeService: IThemeService, - @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, - @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IConfigurationService private readonly _configurationService: IConfigurationService, @ILogService private _logService: ILogService ) { - this._instanceDisposables = []; - this._processDisposables = []; + this._disposables = []; this._skipTerminalCommands = []; this._onLineDataListeners = []; this._isExiting = false; this._hadFocusOnExit = false; - this._processState = ProcessState.UNINITIALIZED; this._isVisible = false; this._isDisposed = false; this._id = TerminalInstance._idCounter++; this._terminalHasTextContextKey = KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED.bindTo(this._contextKeyService); - this._preLaunchInputQueue = ''; this.disableLayout = false; this._logService.trace(`terminalInstance#ctor (id: ${this.id})`, this._shellLaunchConfig); - this._onDisposed = new Emitter(); - this._onFocused = new Emitter(); - this._onProcessIdReady = new Emitter(); - this._onTitleChanged = new Emitter(); - - // Create a promise that resolves when the pty is ready - this._processReady = new TPromise(c => { - this.onProcessIdReady(() => { - this._logService.debug(`Terminal process ready (id: ${this.id}, processId: ${this.processId})`); - c(void 0); - }); - }); - this._initDimensions(); - this._createProcess(); + if (doCreateProcess) { + this._createProcess(); + } this._xtermReadyPromise = this._createXterm(); this._xtermReadyPromise.then(() => { - if (platform.isWindows) { - this._processReady.then(() => { - if (!this._isDisposed) { - this._windowsShellHelper = new WindowsShellHelper(this._processId, this, this._xterm); - } - }); - } - // Only attach xterm.js to the DOM if the terminal panel has been opened before. if (_container) { this._attachToElement(_container); @@ -193,7 +146,7 @@ export class TerminalInstance implements ITerminalInstance { } public addDisposable(disposable: lifecycle.IDisposable): void { - this._instanceDisposables.push(disposable); + this._disposables.push(disposable); } private _initDimensions(): void { @@ -243,7 +196,7 @@ export class TerminalInstance implements ITerminalInstance { return dimension.width; } - private _getDimension(width: number, height: number): Dimension { + private _getDimension(width: number, height: number): dom.Dimension { // The font needs to have been initialized const font = this._configHelper.getFont(this._xterm); if (!font || !font.charWidth || !font.charHeight) { @@ -253,6 +206,14 @@ export class TerminalInstance implements ITerminalInstance { // The panel is minimized if (!this._isVisible) { return TerminalInstance._lastKnownDimensions; + } else { + // Trigger scroll event manually so that the viewport's scroll area is synced. This + // needs to happen otherwise its scrollTop value is invalid when the panel is toggled as + // it gets removed and then added back to the DOM (resetting scrollTop to 0). + // Upstream issue: https://github.com/sourcelair/xterm.js/issues/291 + if (this._xterm) { + this._xterm.emit('scroll', this._xterm.buffer.ydisp); + } } if (!this._wrapperElement) { @@ -267,7 +228,7 @@ export class TerminalInstance implements ITerminalInstance { const innerWidth = width - marginLeft - marginRight; const innerHeight = height - bottom; - TerminalInstance._lastKnownDimensions = new Dimension(innerWidth, innerHeight); + TerminalInstance._lastKnownDimensions = new dom.Dimension(innerWidth, innerHeight); return TerminalInstance._lastKnownDimensions; } @@ -306,23 +267,14 @@ export class TerminalInstance implements ITerminalInstance { } this._xterm.winptyCompatInit(); this._xterm.on('linefeed', () => this._onLineFeed()); - this._process.on('message', (message) => this._sendPtyDataToXterm(message)); - this._xterm.on('data', (data) => { - if (this._processId) { - // Send data if the pty is ready - this._process.send({ - event: 'input', - data - }); - } else { - // If the pty is not ready, queue the data received from - // xterm.js until the pty is ready - this._preLaunchInputQueue += data; - } - return false; - }); - this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, platform.platform, this._initialCwd); - this._instanceDisposables.push(this._themeService.onThemeChange(theme => this._updateTheme(theme))); + if (this._processManager) { + this._processManager.onProcessData(data => this._sendPtyDataToXterm(data)); + this._xterm.on('data', data => this._processManager.write(data)); + // TODO: How does the cwd work on detached processes? + this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, platform.platform, this._processManager.initialCwd); + } + this._commandTracker = new TerminalCommandTracker(this._xterm); + this._disposables.push(this._themeService.onThemeChange(theme => this._updateTheme(theme))); } public reattachToElement(container: HTMLElement): void { @@ -349,7 +301,6 @@ export class TerminalInstance implements ITerminalInstance { return; } - // TODO: Verify listeners still work // The container changed, reattach this._container.removeChild(this._wrapperElement); this._container = container; @@ -398,7 +349,7 @@ export class TerminalInstance implements ITerminalInstance { return undefined; }); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mousedown', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.element, 'mousedown', (event: KeyboardEvent) => { // We need to listen to the mouseup event on the document since the user may release // the mouse button anywhere outside of _xterm.element. const listener = dom.addDisposableListener(document, 'mouseup', (event: KeyboardEvent) => { @@ -410,7 +361,7 @@ export class TerminalInstance implements ITerminalInstance { })); // xterm.js currently drops selection on keyup as we need to handle this case. - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { // Wait until keyup has propagated through the DOM before evaluating // the new selection state. setTimeout(() => this._refreshSelectionContextKey(), 0); @@ -420,7 +371,7 @@ export class TerminalInstance implements ITerminalInstance { const focusTrap: HTMLElement = document.createElement('div'); focusTrap.setAttribute('tabindex', '0'); dom.addClass(focusTrap, 'focus-trap'); - this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { + this._disposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { let currentElement = focusTrap; while (!dom.hasClass(currentElement, 'part')) { currentElement = currentElement.parentElement; @@ -430,31 +381,34 @@ export class TerminalInstance implements ITerminalInstance { })); xtermHelper.insertBefore(focusTrap, this._xterm.textarea); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { this._terminalFocusContextKey.set(true); this._onFocused.fire(this); })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { this._terminalFocusContextKey.reset(); this._refreshSelectionContextKey(); })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { this._terminalFocusContextKey.set(true); })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { + this._disposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { this._terminalFocusContextKey.reset(); this._refreshSelectionContextKey(); })); this._wrapperElement.appendChild(this._xtermElement); - this._widgetManager = new TerminalWidgetManager(this._wrapperElement); - this._linkHandler.setWidgetManager(this._widgetManager); this._container.appendChild(this._wrapperElement); + if (this._processManager) { + this._widgetManager = new TerminalWidgetManager(this._wrapperElement); + this._linkHandler.setWidgetManager(this._widgetManager); + } + const computedStyle = window.getComputedStyle(this._container); const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); - this.layout(new Dimension(width, height)); + this.layout(new dom.Dimension(width, height)); this.setVisible(this._isVisible); this.updateConfig(); @@ -487,7 +441,7 @@ export class TerminalInstance implements ITerminalInstance { } } - get selection(): string | undefined { + public get selection(): string | undefined { return this.hasSelection() ? this._xterm.getSelection() : undefined; } @@ -536,22 +490,14 @@ export class TerminalInstance implements ITerminalInstance { this._xterm.destroy(); this._xterm = null; } - if (this._process) { - if (this._process.connected) { - // If the process was still connected this dispose came from - // within VS Code, not the process, so mark the process as - // killed by the user. - this._processState = ProcessState.KILLED_BY_USER; - this._process.send({ event: 'shutdown' }); - } - this._process = null; + if (this._processManager) { + this._processManager.dispose(); } if (!this._isDisposed) { this._isDisposed = true; this._onDisposed.fire(this); } - this._processDisposables = lifecycle.dispose(this._processDisposables); - this._instanceDisposables = lifecycle.dispose(this._instanceDisposables); + this._disposables = lifecycle.dispose(this._disposables); } public focus(force?: boolean): void { @@ -570,16 +516,13 @@ export class TerminalInstance implements ITerminalInstance { } public sendText(text: string, addNewLine: boolean): void { - this._processReady.then(() => { + this._processManager.ptyProcessReady.then(() => { // Normalize line endings to 'enter' press. text = text.replace(TerminalInstance.EOL_REGEX, '\r'); if (addNewLine && text.substr(text.length - 1) !== '\r') { text += '\r'; } - this._process.send({ - event: 'input', - data: text - }); + this._processManager.write(text); }); } @@ -602,7 +545,7 @@ export class TerminalInstance implements ITerminalInstance { const computedStyle = window.getComputedStyle(this._container); const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); - this.layout(new Dimension(width, height)); + this.layout(new dom.Dimension(width, height)); } } } @@ -642,149 +585,60 @@ export class TerminalInstance implements ITerminalInstance { this._terminalHasTextContextKey.set(isActive && this.hasSelection()); } - protected _getCwd(shell: IShellLaunchConfig, root: Uri): string { - if (shell.cwd) { - return shell.cwd; - } - - let cwd: string; - - // TODO: Handle non-existent customCwd - if (!shell.ignoreConfigurationCwd) { - // Evaluate custom cwd first - const customCwd = this._configHelper.config.cwd; - if (customCwd) { - if (path.isAbsolute(customCwd)) { - cwd = customCwd; - } else if (root) { - cwd = path.normalize(path.join(root.fsPath, customCwd)); - } - } - } - - // If there was no custom cwd or it was relative with no workspace - if (!cwd) { - cwd = root ? root.fsPath : os.homedir(); - } - - return TerminalInstance._sanitizeCwd(cwd); - } - protected _createProcess(): void { - const locale = this._configHelper.config.setLocaleVariables ? platform.locale : undefined; - if (!this._shellLaunchConfig.executable) { - this._configHelper.mergeDefaultShellPathAndArgs(this._shellLaunchConfig); - } - - const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file'); - this._initialCwd = this._getCwd(this._shellLaunchConfig, lastActiveWorkspaceRootUri); - - // Resolve env vars from config and shell - const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); - const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); - const envFromConfig = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot); - const envFromShell = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._shellLaunchConfig.env }, lastActiveWorkspaceRoot); - this._shellLaunchConfig.env = envFromShell; - - // Merge process env with the env from config - const parentEnv = { ...process.env }; - TerminalInstance.mergeEnvironments(parentEnv, envFromConfig); - - // Continue env initialization, merging in the env from the launch - // config and adding keys that are needed to create the process - const env = TerminalInstance.createTerminalEnv(parentEnv, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows); - this._process = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], { - env, - cwd: Uri.parse(path.dirname(require.toUrl('../node/terminalProcess'))).fsPath - }); - this._processState = ProcessState.LAUNCHING; + this._processManager = this._instantiationService.createInstance(TerminalProcessManager, this._id, this._configHelper); + this._processManager.onProcessReady(() => this._onProcessIdReady.fire(this)); + this._processManager.onProcessExit(exitCode => this._onProcessExit(exitCode)); + this._processManager.createProcess(this._shellLaunchConfig, this._cols, this._rows); if (this._shellLaunchConfig.name) { this.setTitle(this._shellLaunchConfig.name, false); } else { // Only listen for process title changes when a name is not provided this.setTitle(this._shellLaunchConfig.executable, true); - this._messageTitleListener = (message) => { - if (message.type === 'title') { - this.setTitle(message.content ? message.content : '', true); - } - }; - this._process.on('message', this._messageTitleListener); + this._messageTitleDisposable = this._processManager.onProcessTitle(title => this.setTitle(title ? title : '', true)); } - this._process.on('message', (message) => { - if (message.type === 'pid') { - this._processId = message.content; - // Send any queued data that's waiting - if (this._preLaunchInputQueue.length > 0) { - this._process.send({ - event: 'input', - data: this._preLaunchInputQueue - }); - this._preLaunchInputQueue = null; - } - this._onProcessIdReady.fire(this); - } - }); - this._process.on('exit', exitCode => this._onPtyProcessExit(exitCode)); - setTimeout(() => { - if (this._processState === ProcessState.LAUNCHING) { - this._processState = ProcessState.RUNNING; - } - }, LAUNCHING_DURATION); - } - - // TODO: Should be protected - private static resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: IStringDictionary, lastActiveWorkspaceRoot: IWorkspaceFolder): IStringDictionary { - Object.keys(env).forEach((key) => { - if (typeof env[key] === 'string') { - env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, env[key]); - } - }); - return env; - } - - private _sendPtyDataToXterm(message: { type: string, content: string }): void { - if (message.type === 'data') { - if (this._widgetManager) { - this._widgetManager.closeMessage(); - } - if (this._xterm) { - this._xterm.write(message.content); - } + if (platform.isWindows) { + this._processManager.ptyProcessReady.then(() => { + this._xtermReadyPromise.then(() => { + if (!this._isDisposed) { + this._windowsShellHelper = new WindowsShellHelper(this._processManager.shellProcessId, this, this._xterm); + } + }); + }); } } - private _onPtyProcessExit(exitCode: number): void { + private _sendPtyDataToXterm(data: string): void { + if (this._widgetManager) { + this._widgetManager.closeMessage(); + } + if (this._xterm) { + this._xterm.write(data); + } + } + + private _onProcessExit(exitCode: number): void { + this._logService.debug(`Terminal process exit (id: ${this.id}) with code ${exitCode}`); + // Prevent dispose functions being triggered multiple times if (this._isExiting) { return; } this._isExiting = true; - this._process = null; let exitCodeMessage: string; if (exitCode) { exitCodeMessage = nls.localize('terminal.integrated.exitedWithCode', 'The terminal process terminated with exit code: {0}', exitCode); } - // If the process is marked as launching then mark the process as killed - // during launch. This typically means that there is a problem with the - // shell and args. - if (this._processState === ProcessState.LAUNCHING) { - this._processState = ProcessState.KILLED_DURING_LAUNCH; - } - - // If TerminalInstance did not know about the process exit then it was - // triggered by the process, not on VS Code's side. - if (this._processState === ProcessState.RUNNING) { - this._processState = ProcessState.KILLED_BY_PROCESS; - } + this._logService.debug(`Terminal process exit (id: ${this.id}) state ${this._processManager.processState}`); // Only trigger wait on exit when the exit was *not* triggered by the // user (via the `workbench.action.terminal.kill` command). - if (this._shellLaunchConfig.waitOnExit && this._processState !== ProcessState.KILLED_BY_USER) { + if (this._shellLaunchConfig.waitOnExit && this._processManager.processState !== ProcessState.KILLED_BY_USER) { if (exitCode) { this._xterm.writeln(exitCodeMessage); } @@ -802,7 +656,7 @@ export class TerminalInstance implements ITerminalInstance { } else { this.dispose(); if (exitCode) { - if (this._processState === ProcessState.KILLED_DURING_LAUNCH) { + if (this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH) { let args = ''; if (typeof this._shellLaunchConfig.args === 'string') { args = this._shellLaunchConfig.args; @@ -814,7 +668,11 @@ export class TerminalInstance implements ITerminalInstance { return a; }).join(' '); } - this._notificationService.error(nls.localize('terminal.integrated.launchFailed', 'The terminal process command \'{0}{1}\' failed to launch (exit code: {2})', this._shellLaunchConfig.executable, args, exitCode)); + if (this._shellLaunchConfig.executable) { + this._notificationService.error(nls.localize('terminal.integrated.launchFailed', 'The terminal process command \'{0}{1}\' failed to launch (exit code: {2})', this._shellLaunchConfig.executable, args, exitCode)); + } else { + this._notificationService.error(nls.localize('terminal.integrated.launchFailedExtHost', 'The terminal process failed to launch (exit code: {0})', exitCode)); + } } else { if (this._configHelper.config.showExitAlert) { this._notificationService.error(exitCodeMessage); @@ -827,23 +685,15 @@ export class TerminalInstance implements ITerminalInstance { } private _attachPressAnyKeyToCloseListener() { - this._processDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'keypress', (event: KeyboardEvent) => { + this._processManager.addDisposable(dom.addDisposableListener(this._xterm.textarea, 'keypress', (event: KeyboardEvent) => { this.dispose(); event.preventDefault(); })); } public reuseTerminal(shell?: IShellLaunchConfig): void { - // Kill and clean up old process - if (this._process) { - this._process.removeAllListeners('exit'); - if (this._process.connected) { - this._process.kill(); - } - this._process = null; - } - lifecycle.dispose(this._processDisposables); - this._processDisposables = []; + // Kill and clear up the process, making the process manager ready for a new process + this._processManager.dispose(); // Ensure new processes' output starts at start of new line this._xterm.write('\n\x1b[G'); @@ -860,7 +710,7 @@ export class TerminalInstance implements ITerminalInstance { if (oldTitle !== this._title) { this.setTitle(this._title, true); } - this._process.on('message', (message) => this._sendPtyDataToXterm(message)); + this._processManager.onProcessData(data => this._sendPtyDataToXterm(data)); // Clean up waitOnExit state if (this._isExiting && this._shellLaunchConfig.waitOnExit) { @@ -872,67 +722,8 @@ export class TerminalInstance implements ITerminalInstance { this._shellLaunchConfig = shell; } - public static mergeEnvironments(parent: IStringDictionary, other: IStringDictionary) { - if (!other) { - return; - } - - // On Windows apply the new values ignoring case, while still retaining - // the case of the original key. - if (platform.isWindows) { - for (let configKey in other) { - let actualKey = configKey; - for (let envKey in parent) { - if (configKey.toLowerCase() === envKey.toLowerCase()) { - actualKey = envKey; - break; - } - } - const value = other[configKey]; - TerminalInstance._mergeEnvironmentValue(parent, actualKey, value); - } - } else { - Object.keys(other).forEach((key) => { - const value = other[key]; - TerminalInstance._mergeEnvironmentValue(parent, key, value); - }); - } - } - - private static _mergeEnvironmentValue(env: IStringDictionary, key: string, value: string | null) { - if (typeof value === 'string') { - env[key] = value; - } else { - delete env[key]; - } - } - - // TODO: This should be private/protected - public static createTerminalEnv(parentEnv: IStringDictionary, shell: IShellLaunchConfig, cwd: string, locale: string, cols?: number, rows?: number): IStringDictionary { - const env = { ...parentEnv }; - if (shell.env) { - TerminalInstance.mergeEnvironments(env, shell.env); - } - - env['PTYPID'] = process.pid.toString(); - env['PTYSHELL'] = shell.executable; - env['TERM_PROGRAM'] = 'vscode'; - env['TERM_PROGRAM_VERSION'] = pkg.version; - if (shell.args) { - if (typeof shell.args === 'string') { - env[`PTYSHELLCMDLINE`] = shell.args; - } else { - shell.args.forEach((arg, i) => env[`PTYSHELLARG${i}`] = arg); - } - } - env['PTYCWD'] = cwd; - env['LANG'] = TerminalInstance._getLangEnvVariable(locale); - if (cols && rows) { - env['PTYCOLS'] = cols.toString(); - env['PTYROWS'] = rows.toString(); - } - env['AMD_ENTRYPOINT'] = 'vs/workbench/parts/terminal/node/terminalProcess'; - return env; + public onData(listener: (data: string) => void): lifecycle.IDisposable { + return this._processManager.onProcessData(data => listener(data)); } public onLineData(listener: (lineData: string) => void): lifecycle.IDisposable { @@ -961,7 +752,7 @@ export class TerminalInstance implements ITerminalInstance { private _sendLineData(buffer: any, lineIndex: number): void { let lineData = buffer.translateBufferLineToString(lineIndex, true); while (lineIndex >= 0 && buffer.lines.get(lineIndex--).isWrapped) { - lineData = buffer.translateBufferLineToString(lineIndex, true) + lineData; + lineData = buffer.translateBufferLineToString(lineIndex, false) + lineData; } this._onLineDataListeners.forEach(listener => { try { @@ -973,57 +764,7 @@ export class TerminalInstance implements ITerminalInstance { } public onExit(listener: (exitCode: number) => void): lifecycle.IDisposable { - if (this._process) { - this._process.on('exit', listener); - } - return { - dispose: () => { - if (this._process) { - this._process.removeListener('exit', listener); - } - } - }; - } - - private static _sanitizeCwd(cwd: string) { - // Make the drive letter uppercase on Windows (see #9448) - if (platform.platform === platform.Platform.Windows && cwd && cwd[1] === ':') { - return cwd[0].toUpperCase() + cwd.substr(1); - } - return cwd; - } - - private static _getLangEnvVariable(locale?: string) { - const parts = locale ? locale.split('-') : []; - const n = parts.length; - if (n === 0) { - // Fallback to en_US to prevent possible encoding issues. - return 'en_US.UTF-8'; - } - if (n === 1) { - // app.getLocale can return just a language without a variant, fill in the variant for - // supported languages as many shells expect a 2-part locale. - const languageVariants = { - de: 'DE', - en: 'US', - es: 'ES', - fi: 'FI', - fr: 'FR', - it: 'IT', - ja: 'JP', - ko: 'KR', - pl: 'PL', - ru: 'RU', - zh: 'CN' - }; - if (parts[0] in languageVariants) { - parts.push(languageVariants[parts[0]]); - } - } else { - // Ensure the variant is uppercase - parts[1] = parts[1].toUpperCase(); - } - return parts.join('_') + '.UTF-8'; + return this._processManager.onProcessExit(listener); } public updateConfig(): void { @@ -1092,7 +833,7 @@ export class TerminalInstance implements ITerminalInstance { } } - public layout(dimension: Dimension): void { + public layout(dimension: dom.Dimension): void { if (this.disableLayout) { return; } @@ -1136,23 +877,9 @@ export class TerminalInstance implements ITerminalInstance { } } - this._processReady.then(() => { - if (this._process && this._process.connected) { - // The child process could aready be terminated - try { - this._process.send({ - event: 'resize', - cols: this._cols, - rows: this._rows - }); - } catch (error) { - // We tried to write to a closed pipe / channel. - if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') { - throw (error); - } - } - } - }); + if (this._processManager) { + this._processManager.ptyProcessReady.then(() => this._processManager.setDimensions(this._cols, this._rows)); + } } public setTitle(title: string, eventFromProcess: boolean): void { @@ -1160,7 +887,7 @@ export class TerminalInstance implements ITerminalInstance { return; } if (eventFromProcess) { - title = path.basename(title); + title = paths.basename(title); if (platform.isWindows) { // Remove the .exe extension title = title.split('.exe')[0]; @@ -1168,9 +895,9 @@ export class TerminalInstance implements ITerminalInstance { } else { // If the title has not been set by the API or the rename command, unregister the handler that // automatically updates the terminal name - if (this._process && this._messageTitleListener) { - this._process.removeListener('message', this._messageTitleListener); - this._messageTitleListener = null; + if (this._messageTitleDisposable) { + lifecycle.dispose(this._messageTitleDisposable); + this._messageTitleDisposable = null; } } const didTitleChange = title !== this._title; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 9e8a79004d..b068ee1a5c 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -3,21 +3,19 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as dom from 'vs/base/browser/dom'; import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; +import * as terminalEnvironment from 'vs/workbench/parts/terminal/node/terminalEnvironment'; import { Action, IAction } from 'vs/base/common/actions'; -import { Builder, Dimension } from 'vs/base/browser/builder'; import { IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; -import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; -import { TerminalFindWidget } from './terminalFindWidget'; +import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; +import { TerminalFindWidget } from 'vs/workbench/parts/terminal/browser/terminalFindWidget'; import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Panel } from 'vs/workbench/browser/panel'; @@ -25,7 +23,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { PANEL_BACKGROUND, PANEL_BORDER } from 'vs/workbench/common/theme'; -import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; +import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR } from 'vs/workbench/parts/terminal/common/terminalColorRegistry'; import { DataTransfers } from 'vs/base/browser/dnd'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; @@ -38,7 +36,6 @@ export class TerminalPanel extends Panel { private _fontStyleElement: HTMLElement; private _parentDomElement: HTMLElement; private _terminalContainer: HTMLElement; - private _themeStyleElement: HTMLElement; private _findWidget: TerminalFindWidget; constructor( @@ -53,11 +50,10 @@ export class TerminalPanel extends Panel { super(TERMINAL_PANEL_ID, telemetryService, themeService); } - public create(parent: Builder): TPromise { + public create(parent: HTMLElement): TPromise { super.create(parent); - this._parentDomElement = parent.getHTMLElement(); + this._parentDomElement = parent; dom.addClass(this._parentDomElement, 'integrated-terminal'); - this._themeStyleElement = document.createElement('style'); this._fontStyleElement = document.createElement('style'); this._terminalContainer = document.createElement('div'); @@ -65,14 +61,13 @@ export class TerminalPanel extends Panel { this._findWidget = this._instantiationService.createInstance(TerminalFindWidget); - this._parentDomElement.appendChild(this._themeStyleElement); this._parentDomElement.appendChild(this._fontStyleElement); this._parentDomElement.appendChild(this._terminalContainer); this._parentDomElement.appendChild(this._findWidget.getDomNode()); this._attachEventListeners(); - this._terminalService.setContainers(this.getContainer().getHTMLElement(), this._terminalContainer); + this._terminalService.setContainers(this.getContainer(), this._terminalContainer); this._register(this.themeService.onThemeChange(theme => this._updateTheme(theme))); this._register(this._configurationService.onDidChangeConfiguration(e => { @@ -84,11 +79,11 @@ export class TerminalPanel extends Panel { this._updateTheme(); // Force another layout (first is setContainers) since config has changed - this.layout(new Dimension(this._terminalContainer.offsetWidth, this._terminalContainer.offsetHeight)); + this.layout(new dom.Dimension(this._terminalContainer.offsetWidth, this._terminalContainer.offsetHeight)); return TPromise.as(void 0); } - public layout(dimension?: Dimension): void { + public layout(dimension?: dom.Dimension): void { if (!dimension) { return; } @@ -116,7 +111,7 @@ export class TerminalPanel extends Panel { return; } - const instance = this._terminalService.createInstance(); + const instance = this._terminalService.createTerminal(); if (instance) { this._updateFont(); this._updateTheme(); @@ -150,14 +145,13 @@ export class TerminalPanel extends Panel { this._copyContextMenuAction = this._instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, nls.localize('copy', "Copy")); this._contextMenuActions = [ this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), + this._instantiationService.createInstance(SplitTerminalAction, SplitTerminalAction.ID, nls.localize('split', "Split")), new Separator(), this._copyContextMenuAction, this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, nls.localize('paste', "Paste")), this._instantiationService.createInstance(SelectAllTerminalAction, SelectAllTerminalAction.ID, nls.localize('selectAll', "Select All")), new Separator(), - this._instantiationService.createInstance(ClearTerminalAction, ClearTerminalAction.ID, nls.localize('clear', "Clear")), - new Separator(), - this._instantiationService.createInstance(SplitTerminalAction, SplitTerminalAction.ID, nls.localize('split', "Split")) + this._instantiationService.createInstance(ClearTerminalAction, ClearTerminalAction.ID, nls.localize('clear', "Clear")) ]; this._contextMenuActions.forEach(a => { this._register(a); @@ -295,7 +289,7 @@ export class TerminalPanel extends Panel { } const terminal = this._terminalService.getActiveInstance(); - terminal.sendText(TerminalPanel.preparePathForTerminal(path), false); + terminal.sendText(terminalEnvironment.preparePathForTerminal(path), false); } })); } @@ -305,31 +299,6 @@ export class TerminalPanel extends Panel { theme = this.themeService.getTheme(); } - let css = ''; - - const backgroundColor = theme.getColor(TERMINAL_BACKGROUND_COLOR) || theme.getColor(PANEL_BACKGROUND); - this._terminalContainer.style.backgroundColor = backgroundColor ? backgroundColor.toString() : ''; - - const borderColor = theme.getColor(TERMINAL_BORDER_COLOR) || theme.getColor(PANEL_BORDER); - if (borderColor) { - css += `.monaco-workbench .panel.integrated-terminal .split-view-view:not(:first-child) { border-color: ${borderColor.toString()}; }`; - } - - // Borrow the editor's hover background for now - let hoverBackground = theme.getColor(editorHoverBackground); - if (hoverBackground) { - css += `.monaco-workbench .panel.integrated-terminal .terminal-message-widget { background-color: ${hoverBackground}; }`; - } - let hoverBorder = theme.getColor(editorHoverBorder); - if (hoverBorder) { - css += `.monaco-workbench .panel.integrated-terminal .terminal-message-widget { border: 1px solid ${hoverBorder}; }`; - } - let hoverForeground = theme.getColor(editorForeground); - if (hoverForeground) { - css += `.monaco-workbench .panel.integrated-terminal .terminal-message-widget { color: ${hoverForeground}; }`; - } - - this._themeStyleElement.innerHTML = css; this._findWidget.updateTheme(theme); } @@ -339,30 +308,30 @@ export class TerminalPanel extends Panel { } // TODO: Can we support ligatures? // dom.toggleClass(this._parentDomElement, 'enable-ligatures', this._terminalService.configHelper.config.fontLigatures); - this.layout(new Dimension(this._parentDomElement.offsetWidth, this._parentDomElement.offsetHeight)); - } - - /** - * Adds quotes to a path if it contains whitespaces - */ - public static preparePathForTerminal(path: string): string { - if (platform.isWindows) { - if (/\s+/.test(path)) { - return `"${path}"`; - } - return path; - } - path = path.replace(/(%5C|\\)/g, '\\\\'); - const charsToEscape = [ - ' ', '\'', '"', '?', ':', ';', '!', '*', '(', ')', '{', '}', '[', ']' - ]; - for (let i = 0; i < path.length; i++) { - const indexOfChar = charsToEscape.indexOf(path.charAt(i)); - if (indexOfChar >= 0) { - path = `${path.substring(0, i)}\\${path.charAt(i)}${path.substring(i + 1)}`; - i++; // Skip char due to escape char being added - } - } - return path; + this.layout(new dom.Dimension(this._parentDomElement.offsetWidth, this._parentDomElement.offsetHeight)); } } + +registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { + const backgroundColor = theme.getColor(TERMINAL_BACKGROUND_COLOR) || theme.getColor(PANEL_BACKGROUND); + collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-outer-container { background-color: ${backgroundColor ? backgroundColor.toString() : ''}; }`); + + const borderColor = theme.getColor(TERMINAL_BORDER_COLOR) || theme.getColor(PANEL_BORDER); + if (borderColor) { + collector.addRule(`.monaco-workbench .panel.integrated-terminal .split-view-view:not(:first-child) { border-color: ${borderColor.toString()}; }`); + } + + // Borrow the editor's hover background for now + let hoverBackground = theme.getColor(editorHoverBackground); + if (hoverBackground) { + collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-message-widget { background-color: ${hoverBackground}; }`); + } + let hoverBorder = theme.getColor(editorHoverBorder); + if (hoverBorder) { + collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-message-widget { border: 1px solid ${hoverBorder}; }`); + } + let hoverForeground = theme.getColor(editorForeground); + if (hoverForeground) { + collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-message-widget { color: ${hoverForeground}; }`); + } +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts new file mode 100644 index 0000000000..211e52672b --- /dev/null +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts @@ -0,0 +1,207 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as cp from 'child_process'; +import * as platform from 'vs/base/common/platform'; +import * as terminalEnvironment from 'vs/workbench/parts/terminal/node/terminalEnvironment'; +import Uri from 'vs/base/common/uri'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/parts/terminal/common/terminal'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ILogService } from 'vs/platform/log/common/log'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IHistoryService } from 'vs/workbench/services/history/common/history'; +import { ITerminalChildProcess, IMessageFromTerminalProcess } from 'vs/workbench/parts/terminal/node/terminal'; +import { TerminalProcessExtHostProxy } from 'vs/workbench/parts/terminal/node/terminalProcessExtHostProxy'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; + +/** The amount of time to consider terminal errors to be related to the launch */ +const LAUNCHING_DURATION = 500; + +/** + * Holds all state related to the creation and management of terminal processes. + * + * Internal definitions: + * - Process: The process launched with the terminalProcess.ts file, or the pty as a whole + * - Pty Process: The pseudoterminal master process (or the winpty agent process) + * - Shell Process: The pseudoterminal slave process (ie. the shell) + */ +export class TerminalProcessManager implements ITerminalProcessManager { + public processState: ProcessState = ProcessState.UNINITIALIZED; + public ptyProcessReady: TPromise; + public shellProcessId: number; + public initialCwd: string; + + private _process: ITerminalChildProcess; + private _preLaunchInputQueue: string[] = []; + private _disposables: IDisposable[] = []; + + private readonly _onProcessReady: Emitter = new Emitter(); + public get onProcessReady(): Event { return this._onProcessReady.event; } + private readonly _onProcessData: Emitter = new Emitter(); + public get onProcessData(): Event { return this._onProcessData.event; } + private readonly _onProcessTitle: Emitter = new Emitter(); + public get onProcessTitle(): Event { return this._onProcessTitle.event; } + private readonly _onProcessExit: Emitter = new Emitter(); + public get onProcessExit(): Event { return this._onProcessExit.event; } + + constructor( + private _terminalId: number, + private _configHelper: ITerminalConfigHelper, + @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, + @IHistoryService private readonly _historyService: IHistoryService, + @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ILogService private _logService: ILogService + ) { + this.ptyProcessReady = new TPromise(c => { + this.onProcessReady(() => { + this._logService.debug(`Terminal process ready (shellProcessId: ${this.shellProcessId})`); + c(void 0); + }); + }); + } + + public dispose(): void { + if (this._process) { + if (this._process.connected) { + // If the process was still connected this dispose came from + // within VS Code, not the process, so mark the process as + // killed by the user. + this.processState = ProcessState.KILLED_BY_USER; + this._process.send({ event: 'shutdown' }); + } + this._process = null; + } + this._disposables.forEach(d => d.dispose()); + this._disposables.length = 0; + } + + public addDisposable(disposable: IDisposable) { + this._disposables.push(disposable); + } + + public createProcess( + shellLaunchConfig: IShellLaunchConfig, + cols: number, + rows: number + ): void { + const extensionHostOwned = (this._configHelper.config).extHostProcess; + if (extensionHostOwned) { + this._process = this._instantiationService.createInstance(TerminalProcessExtHostProxy, this._terminalId, shellLaunchConfig, cols, rows); + } else { + const locale = this._configHelper.config.setLocaleVariables ? platform.locale : undefined; + if (!shellLaunchConfig.executable) { + this._configHelper.mergeDefaultShellPathAndArgs(shellLaunchConfig); + } + + const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file'); + this.initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, lastActiveWorkspaceRootUri, this._configHelper); + + // Resolve env vars from config and shell + const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); + const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); + const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot); + const envFromShell = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...shellLaunchConfig.env }, lastActiveWorkspaceRoot); + shellLaunchConfig.env = envFromShell; + + // Merge process env with the env from config + const parentEnv = { ...process.env }; + terminalEnvironment.mergeEnvironments(parentEnv, envFromConfig); + + // Continue env initialization, merging in the env from the launch + // config and adding keys that are needed to create the process + const env = terminalEnvironment.createTerminalEnv(parentEnv, shellLaunchConfig, this.initialCwd, locale, cols, rows); + const cwd = Uri.parse(require.toUrl('../node')).fsPath; + const options = { env, cwd }; + this._logService.debug(`Terminal process launching`, options); + + this._process = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], options); + } + this.processState = ProcessState.LAUNCHING; + + this._process.on('message', message => this._onMessage(message)); + this._process.on('exit', exitCode => this._onExit(exitCode)); + + setTimeout(() => { + if (this.processState === ProcessState.LAUNCHING) { + this.processState = ProcessState.RUNNING; + } + }, LAUNCHING_DURATION); + } + + public setDimensions(cols: number, rows: number): void { + if (this._process && this._process.connected) { + // The child process could aready be terminated + try { + this._process.send({ event: 'resize', cols, rows }); + } catch (error) { + // We tried to write to a closed pipe / channel. + if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') { + throw (error); + } + } + } + } + + public write(data: string): void { + if (this.shellProcessId) { + // Send data if the pty is ready + this._process.send({ + event: 'input', + data + }); + } else { + // If the pty is not ready, queue the data received to send later + this._preLaunchInputQueue.push(data); + } + } + + private _onMessage(message: IMessageFromTerminalProcess): void { + this._logService.trace(`terminalProcessManager#_onMessage (shellProcessId: ${this.shellProcessId}`, message); + switch (message.type) { + case 'data': + this._onProcessData.fire(message.content); + break; + case 'pid': + this.shellProcessId = message.content; + this._onProcessReady.fire(); + + // Send any queued data that's waiting + if (this._preLaunchInputQueue.length > 0) { + this._process.send({ + event: 'input', + data: this._preLaunchInputQueue.join('') + }); + this._preLaunchInputQueue.length = 0; + } + break; + case 'title': + this._onProcessTitle.fire(message.content); + break; + } + } + + private _onExit(exitCode: number): void { + this._process = null; + + // If the process is marked as launching then mark the process as killed + // during launch. This typically means that there is a problem with the + // shell and args. + if (this.processState === ProcessState.LAUNCHING) { + this.processState = ProcessState.KILLED_DURING_LAUNCH; + } + + // If TerminalInstance did not know about the process exit then it was + // triggered by the process, not on VS Code's side. + if (this.processState === ProcessState.RUNNING) { + this.processState = ProcessState.KILLED_BY_PROCESS; + } + + this._onProcessExit.fire(exitCode); + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index aa5b93915e..3a033df1a1 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -6,23 +6,28 @@ import * as nls from 'vs/nls'; import * as pfs from 'vs/base/node/pfs'; import * as platform from 'vs/base/common/platform'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IQuickOpenService, IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen'; -import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID, ITerminalProcessExtHostProxy } from 'vs/workbench/parts/terminal/common/terminal'; import { TerminalService as AbstractTerminalService } from 'vs/workbench/parts/terminal/common/terminalService'; import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import { TPromise } from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { getTerminalDefaultShellWindows } from 'vs/workbench/parts/terminal/electron-browser/terminal'; +import { getTerminalDefaultShellWindows } from 'vs/workbench/parts/terminal/node/terminal'; import { TerminalPanel } from 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; -import { TerminalTab } from 'vs/workbench/parts/terminal/electron-browser/terminalTab'; -import { IChoiceService, IConfirmationService, Choice } from 'vs/platform/dialogs/common/dialogs'; +import { TerminalTab } from 'vs/workbench/parts/terminal/browser/terminalTab'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ipcRenderer as ipc } from 'electron'; +import { IOpenFileRequest } from 'vs/platform/windows/common/windows'; +import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; export class TerminalService extends AbstractTerminalService implements ITerminalService { private _configHelper: TerminalConfigHelper; @@ -42,16 +47,30 @@ export class TerminalService extends AbstractTerminalService implements ITermina @IConfigurationService private readonly _configurationService: IConfigurationService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IQuickOpenService private readonly _quickOpenService: IQuickOpenService, - @IChoiceService private readonly _choiceService: IChoiceService, - @IConfirmationService private readonly _confirmationService: IConfirmationService + @INotificationService private readonly _notificationService: INotificationService, + @IDialogService private readonly _dialogService: IDialogService, + @IExtensionService private readonly _extensionService: IExtensionService ) { super(contextKeyService, panelService, partService, lifecycleService, storageService); this._terminalTabs = []; this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper); + + ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => { + // if the request to open files is coming in from the integrated terminal (identified though + // the termProgram variable) and we are instructed to wait for editors close, wait for the + // marker file to get deleted and then focus back to the integrated terminal. + if (request.termProgram === 'vscode' && request.filesToWait) { + pfs.whenDeleted(request.filesToWait.waitMarkerFilePath).then(() => { + if (this.terminalInstances.length > 0) { + this.getActiveInstance().focus(); + } + }); + } + }); } - public createInstance(shell: IShellLaunchConfig = {}, wasNewTerminalAction?: boolean): ITerminalInstance { + public createTerminal(shell: IShellLaunchConfig = {}, wasNewTerminalAction?: boolean): ITerminalInstance { const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalFocusContextKey, this._configHelper, @@ -71,6 +90,22 @@ export class TerminalService extends AbstractTerminalService implements ITermina return instance; } + public createInstance(terminalFocusContextKey: IContextKey, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance { + const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig, true); + this._onInstanceCreated.fire(instance); + return instance; + } + + public requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): void { + // Ensure extension host is ready before requesting a process + this._extensionService.whenInstalledExtensionsRegistered().then(() => { + // TODO: MainThreadTerminalService is not ready at this point, fix this + setTimeout(() => { + this._onInstanceRequestExtHostProcess.fire({ proxy, shellLaunchConfig, cols, rows }); + }, 500); + }); + } + public focusFindWidget(): TPromise { return this.showPanel(false).then(() => { let panel = this._panelService.getActivePanel() as TerminalPanel; @@ -126,17 +161,18 @@ export class TerminalService extends AbstractTerminalService implements ITermina return; } - const message = nls.localize('terminal.integrated.chooseWindowsShellInfo', "You can change the default terminal shell by selecting the customize button."); - const options: Choice[] = [nls.localize('customize', "Customize"), { label: nls.localize('never again', "Don't Show Again") }]; - this._choiceService.choose(Severity.Info, message, options).then(choice => { - switch (choice) { - case 0 /* Customize */: + this._notificationService.prompt( + Severity.Info, + nls.localize('terminal.integrated.chooseWindowsShellInfo', "You can change the default terminal shell by selecting the customize button."), + [{ + label: nls.localize('customize', "Customize"), + run: () => { this.selectDefaultWindowsShell().then(shell => { if (!shell) { return TPromise.as(null); } // Launch a new instance with the newly selected shell - const instance = this.createInstance({ + const instance = this.createTerminal({ executable: shell, args: this._configHelper.config.shellArgs.windows }); @@ -145,12 +181,14 @@ export class TerminalService extends AbstractTerminalService implements ITermina } return TPromise.as(null); }); - break; - case 1 /* Do not show again */: - this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true); - break; - } - }); + } + }, + { + label: nls.localize('never again', "Don't Show Again"), + isSecondary: true, + run: () => this._storageService.store(NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, true) + }] + ); } public selectDefaultWindowsShell(): TPromise { @@ -214,7 +252,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina public getActiveOrCreateInstance(wasNewTerminalAction?: boolean): ITerminalInstance { const activeInstance = this.getActiveInstance(); - return activeInstance ? activeInstance : this.createInstance(undefined, wasNewTerminalAction); + return activeInstance ? activeInstance : this.createTerminal(undefined, wasNewTerminalAction); } protected _showTerminalCloseConfirmation(): TPromise { @@ -225,10 +263,10 @@ export class TerminalService extends AbstractTerminalService implements ITermina message = nls.localize('terminalService.terminalCloseConfirmationPlural', "There are {0} active terminal sessions, do you want to kill them?", this.terminalInstances.length); } - return this._confirmationService.confirm({ + return this._dialogService.confirm({ message, type: 'warning', - }).then(confirmed => !confirmed); + }).then(res => !res.confirmed); } public setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts b/src/vs/workbench/parts/terminal/node/terminal.ts similarity index 74% rename from src/vs/workbench/parts/terminal/electron-browser/terminal.ts rename to src/vs/workbench/parts/terminal/node/terminal.ts index 9b15c27f56..c980e2bf6d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.ts @@ -2,13 +2,37 @@ * 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 os from 'os'; import * as platform from 'vs/base/common/platform'; import * as processes from 'vs/base/node/processes'; import { readFile, fileExists } from 'vs/base/node/pfs'; +export interface IMessageFromTerminalProcess { + type: 'pid' | 'data' | 'title'; + content: number | string; +} + +export interface IMessageToTerminalProcess { + event: 'resize' | 'input' | 'shutdown'; + data?: string; + cols?: number; + rows?: number; +} + +/** + * An interface representing a raw terminal child process, this is a subset of the + * child_process.ChildProcess node.js interface. + */ +export interface ITerminalChildProcess { + readonly connected: boolean; + + send(message: IMessageToTerminalProcess): boolean; + + on(event: 'exit', listener: (code: number) => void): this; + on(event: 'message', listener: (message: IMessageFromTerminalProcess) => void): this; +} + let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string = null; export function getTerminalDefaultShellUnixLike(): string { if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) { @@ -51,4 +75,4 @@ if (platform.isLinux) { }); } -export let isFedora = false; +export let isFedora = false; \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/terminalCommandTracker.ts b/src/vs/workbench/parts/terminal/node/terminalCommandTracker.ts new file mode 100644 index 0000000000..1a04cc5ac6 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalCommandTracker.ts @@ -0,0 +1,156 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Terminal, IMarker } from 'vscode-xterm'; +import { ITerminalCommandTracker } from 'vs/workbench/parts/terminal/common/terminal'; + +/** + * The minimize size of the prompt in which to assume the line is a command. + */ +const MINIMUM_PROMPT_LENGTH = 2; + +enum Boundary { + Top, + Bottom +} + +export enum ScrollPosition { + Top, + Middle +} + +export class TerminalCommandTracker implements ITerminalCommandTracker { + private _currentMarker: IMarker | Boundary = Boundary.Bottom; + private _selectionStart: IMarker | Boundary | null = null; + + constructor( + private _xterm: Terminal + ) { + this._xterm.on('key', key => this._onKey(key)); + } + + private _onKey(key: string): void { + if (key === '\x0d') { + this._onEnter(); + } + + // Clear the current marker so successive focus/selection actions are performed from the + // bottom of the buffer + this._currentMarker = Boundary.Bottom; + this._selectionStart = null; + } + + private _onEnter(): void { + if (this._xterm.buffer.x >= MINIMUM_PROMPT_LENGTH) { + this._xterm.addMarker(0); + } + } + + public scrollToPreviousCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + if (!retainSelection) { + this._selectionStart = null; + } + + let markerIndex; + if (this._currentMarker === Boundary.Bottom) { + markerIndex = this._xterm.markers.length - 1; + } else if (this._currentMarker === Boundary.Top) { + markerIndex = -1; + } else { + markerIndex = this._xterm.markers.indexOf(this._currentMarker) - 1; + } + + if (markerIndex < 0) { + this._currentMarker = Boundary.Top; + this._xterm.scrollToTop(); + return; + } + + this._currentMarker = this._xterm.markers[markerIndex]; + this._scrollToMarker(this._currentMarker, scrollPosition); + } + + public scrollToNextCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + if (!retainSelection) { + this._selectionStart = null; + } + + let markerIndex; + if (this._currentMarker === Boundary.Bottom) { + markerIndex = this._xterm.markers.length; + } else if (this._currentMarker === Boundary.Top) { + markerIndex = 0; + } else { + markerIndex = this._xterm.markers.indexOf(this._currentMarker) + 1; + } + + if (markerIndex >= this._xterm.markers.length) { + this._currentMarker = Boundary.Bottom; + this._xterm.scrollToBottom(); + return; + } + + this._currentMarker = this._xterm.markers[markerIndex]; + this._scrollToMarker(this._currentMarker, scrollPosition); + } + + private _scrollToMarker(marker: IMarker, position: ScrollPosition): void { + let line = marker.line; + if (position === ScrollPosition.Middle) { + line = Math.max(line - this._xterm.rows / 2, 0); + } + this._xterm.scrollToLine(line); + } + + public selectToPreviousCommand(): void { + if (this._selectionStart === null) { + this._selectionStart = this._currentMarker; + } + this.scrollToPreviousCommand(ScrollPosition.Middle, true); + this._selectLines(this._currentMarker, this._selectionStart); + } + + public selectToNextCommand(): void { + if (this._selectionStart === null) { + this._selectionStart = this._currentMarker; + } + this.scrollToNextCommand(ScrollPosition.Middle, true); + this._selectLines(this._currentMarker, this._selectionStart); + } + + private _selectLines(start: IMarker | Boundary, end: IMarker | Boundary | null): void { + if (end === null) { + end = Boundary.Bottom; + } + + let startLine = this._getLine(start); + let endLine = this._getLine(end); + + if (startLine > endLine) { + const temp = startLine; + startLine = endLine; + endLine = temp; + } + + // Subtract a line as the marker is on the line the command run, we do not want the next + // command in the selection for the current command + endLine -= 1; + + this._xterm.selectLines(startLine, endLine); + } + + private _getLine(marker: IMarker | Boundary): number { + // Use the _second last_ row as the last row is likely the prompt + if (marker === Boundary.Bottom) { + return this._xterm.buffer.ybase + this._xterm.rows - 1; + } + + if (marker === Boundary.Top) { + return 0; + } + + return marker.line; + } +} diff --git a/src/vs/workbench/parts/terminal/node/terminalEnvironment.ts b/src/vs/workbench/parts/terminal/node/terminalEnvironment.ts new file mode 100644 index 0000000000..9348cb349f --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalEnvironment.ts @@ -0,0 +1,182 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as os from 'os'; +import * as paths from 'vs/base/common/paths'; +import * as platform from 'vs/base/common/platform'; +import pkg from 'vs/platform/node/package'; +import Uri from 'vs/base/common/uri'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/parts/terminal/common/terminal'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; + +/** + * This module contains utility functions related to the environment, cwd and paths. + */ + +export function mergeEnvironments(parent: IStringDictionary, other: IStringDictionary) { + if (!other) { + return; + } + + // On Windows apply the new values ignoring case, while still retaining + // the case of the original key. + if (platform.isWindows) { + for (let configKey in other) { + let actualKey = configKey; + for (let envKey in parent) { + if (configKey.toLowerCase() === envKey.toLowerCase()) { + actualKey = envKey; + break; + } + } + const value = other[configKey]; + _mergeEnvironmentValue(parent, actualKey, value); + } + } else { + Object.keys(other).forEach((key) => { + const value = other[key]; + _mergeEnvironmentValue(parent, key, value); + }); + } +} + +function _mergeEnvironmentValue(env: IStringDictionary, key: string, value: string | null) { + if (typeof value === 'string') { + env[key] = value; + } else { + delete env[key]; + } +} + +export function createTerminalEnv(parentEnv: IStringDictionary, shell: IShellLaunchConfig, cwd: string, locale: string, cols?: number, rows?: number): IStringDictionary { + const env = { ...parentEnv }; + if (shell.env) { + mergeEnvironments(env, shell.env); + } + + env['PTYPID'] = process.pid.toString(); + env['PTYSHELL'] = shell.executable; + env['TERM_PROGRAM'] = 'vscode'; + env['TERM_PROGRAM_VERSION'] = pkg.version; + if (shell.args) { + if (typeof shell.args === 'string') { + env[`PTYSHELLCMDLINE`] = shell.args; + } else { + shell.args.forEach((arg, i) => env[`PTYSHELLARG${i}`] = arg); + } + } + env['PTYCWD'] = cwd; + env['LANG'] = _getLangEnvVariable(locale); + if (cols && rows) { + env['PTYCOLS'] = cols.toString(); + env['PTYROWS'] = rows.toString(); + } + env['AMD_ENTRYPOINT'] = 'vs/workbench/parts/terminal/node/terminalProcess'; + return env; +} + +export function resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: IStringDictionary, lastActiveWorkspaceRoot: IWorkspaceFolder): IStringDictionary { + Object.keys(env).forEach((key) => { + if (typeof env[key] === 'string') { + env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, env[key]); + } + }); + return env; +} + +function _getLangEnvVariable(locale?: string) { + const parts = locale ? locale.split('-') : []; + const n = parts.length; + if (n === 0) { + // Fallback to en_US to prevent possible encoding issues. + return 'en_US.UTF-8'; + } + if (n === 1) { + // app.getLocale can return just a language without a variant, fill in the variant for + // supported languages as many shells expect a 2-part locale. + const languageVariants = { + de: 'DE', + en: 'US', + es: 'ES', + fi: 'FI', + fr: 'FR', + it: 'IT', + ja: 'JP', + ko: 'KR', + pl: 'PL', + ru: 'RU', + zh: 'CN' + }; + if (parts[0] in languageVariants) { + parts.push(languageVariants[parts[0]]); + } + } else { + // Ensure the variant is uppercase + parts[1] = parts[1].toUpperCase(); + } + return parts.join('_') + '.UTF-8'; +} + +export function getCwd(shell: IShellLaunchConfig, root: Uri, configHelper: ITerminalConfigHelper): string { + if (shell.cwd) { + return shell.cwd; + } + + let cwd: string; + + // TODO: Handle non-existent customCwd + if (!shell.ignoreConfigurationCwd) { + // Evaluate custom cwd first + const customCwd = configHelper.config.cwd; + if (customCwd) { + if (paths.isAbsolute(customCwd)) { + cwd = customCwd; + } else if (root) { + cwd = paths.normalize(paths.join(root.fsPath, customCwd)); + } + } + } + + // If there was no custom cwd or it was relative with no workspace + if (!cwd) { + cwd = root ? root.fsPath : os.homedir(); + } + + return _sanitizeCwd(cwd); +} + +function _sanitizeCwd(cwd: string): string { + // Make the drive letter uppercase on Windows (see #9448) + if (platform.platform === platform.Platform.Windows && cwd && cwd[1] === ':') { + return cwd[0].toUpperCase() + cwd.substr(1); + } + return cwd; +} + +/** + * Adds quotes to a path if it contains whitespaces + */ +export function preparePathForTerminal(path: string): string { + if (platform.isWindows) { + if (/\s+/.test(path)) { + return `"${path}"`; + } + return path; + } + path = path.replace(/(%5C|\\)/g, '\\\\'); + const charsToEscape = [ + ' ', '\'', '"', '?', ':', ';', '!', '*', '(', ')', '{', '}', '[', ']' + ]; + for (let i = 0; i < path.length; i++) { + const indexOfChar = charsToEscape.indexOf(path.charAt(i)); + if (indexOfChar >= 0) { + path = `${path.substring(0, i)}\\${path.charAt(i)}${path.substring(i + 1)}`; + i++; // Skip char due to escape char being added + } + } + return path; +} diff --git a/src/vs/workbench/parts/terminal/node/terminalProcess.ts b/src/vs/workbench/parts/terminal/node/terminalProcess.ts index 95497834ca..1908c2ef2f 100644 --- a/src/vs/workbench/parts/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/parts/terminal/node/terminalProcess.ts @@ -24,7 +24,7 @@ var cols = process.env.PTYCOLS; var rows = process.env.PTYROWS; var currentTitle = ''; -setupPlanB(process.env.PTYPID); +setupPlanB(Number(process.env.PTYPID)); cleanEnv(); interface IOptions { @@ -43,7 +43,7 @@ if (cols && rows) { options.rows = parseInt(rows, 10); } -var ptyProcess = pty.fork(shell, args, options); +var ptyProcess = pty.spawn(shell, args, options); var closeTimeout: number; var exitCode: number; @@ -91,7 +91,7 @@ process.on('message', function (message) { sendProcessId(); setupTitlePolling(); -function getArgs() { +function getArgs(): string | string[] { if (process.env['PTYSHELLCMDLINE']) { return process.env['PTYSHELLCMDLINE']; } @@ -107,6 +107,7 @@ function getArgs() { function cleanEnv() { var keys = [ 'AMD_ENTRYPOINT', + 'ELECTRON_NO_ASAR', 'ELECTRON_RUN_AS_NODE', 'GOOGLE_API_KEY', 'PTYCWD', diff --git a/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts b/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts new file mode 100644 index 0000000000..762e4f47f6 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts @@ -0,0 +1,78 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITerminalChildProcess, IMessageToTerminalProcess, IMessageFromTerminalProcess } from 'vs/workbench/parts/terminal/node/terminal'; +import { EventEmitter } from 'events'; +import { ITerminalService, ITerminalProcessExtHostProxy, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; + +export class TerminalProcessExtHostProxy extends EventEmitter implements ITerminalChildProcess, ITerminalProcessExtHostProxy { + // For ext host processes connected checks happen on the ext host + public connected: boolean = true; + + private _disposables: IDisposable[] = []; + + constructor( + public terminalId: number, + shellLaunchConfig: IShellLaunchConfig, + cols: number, + rows: number, + @ITerminalService private _terminalService: ITerminalService + ) { + super(); + + // TODO: Return TPromise indicating success? Teardown if failure? + this._terminalService.requestExtHostProcess(this, shellLaunchConfig, cols, rows); + } + + public dispose(): void { + this._disposables.forEach(d => d.dispose()); + this._disposables.length = 0; + } + + public emitData(data: string): void { + this.emit('message', { type: 'data', content: data } as IMessageFromTerminalProcess); + } + + public emitTitle(title: string): void { + this.emit('message', { type: 'title', content: title } as IMessageFromTerminalProcess); + } + + public emitPid(pid: number): void { + this.emit('message', { type: 'pid', content: pid } as IMessageFromTerminalProcess); + } + + public emitExit(exitCode: number): void { + this.emit('exit', exitCode); + this.dispose(); + } + + public send(message: IMessageToTerminalProcess): boolean { + switch (message.event) { + case 'input': this.emit('input', message.data); break; + case 'resize': this.emit('resize', message.cols, message.rows); break; + case 'shutdown': this.emit('shutdown'); break; + } + return true; + } + + public onInput(listener: (data: string) => void): void { + const outerListener = (data) => listener(data); + this.on('input', outerListener); + this._disposables.push(toDisposable(() => this.removeListener('input', outerListener))); + } + + public onResize(listener: (cols: number, rows: number) => void): void { + const outerListener = (cols, rows) => listener(cols, rows); + this.on('resize', outerListener); + this._disposables.push(toDisposable(() => this.removeListener('resize', outerListener))); + } + + public onShutdown(listener: () => void): void { + const outerListener = () => listener(); + this.on('shutdown', outerListener); + this._disposables.push(toDisposable(() => this.removeListener('shutdown', outerListener))); + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts b/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts similarity index 68% rename from src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts rename to src/vs/workbench/parts/terminal/node/windowsShellHelper.ts index 3d362c7933..0c97596065 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts +++ b/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts @@ -8,10 +8,11 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Emitter, debounceEvent } from 'vs/base/common/event'; import { ITerminalInstance } from 'vs/workbench/parts/terminal/common/terminal'; import { Terminal as XTermTerminal } from 'vscode-xterm'; +import WindowsProcessTreeType = require('windows-process-tree'); const SHELL_EXECUTABLES = ['cmd.exe', 'powershell.exe', 'bash.exe']; -let windowsProcessTree; +let windowsProcessTree: typeof WindowsProcessTreeType; export class WindowsShellHelper { private _onCheckShell: Emitter>; @@ -28,34 +29,38 @@ export class WindowsShellHelper { throw new Error(`WindowsShellHelper cannot be instantiated on ${platform.platform}`); } - if (!windowsProcessTree) { - windowsProcessTree = require.__$__nodeRequire('windows-process-tree'); - } - this._isDisposed = false; - this._onCheckShell = new Emitter>(); - // The debounce is necessary to prevent multiple processes from spawning when - // the enter key or output is spammed - debounceEvent(this._onCheckShell.event, (l, e) => e, 150, true)(() => { - setTimeout(() => { - this.checkShell(); - }, 50); - }); - // We want to fire a new check for the shell on a linefeed, but only - // when parsing has finished which is indicated by the cursormove event. - // If this is done on every linefeed, parsing ends up taking - // significantly longer due to resetting timers. Note that this is - // private API. - this._xterm.on('linefeed', () => this._newLineFeed = true); - this._xterm.on('cursormove', () => { - if (this._newLineFeed) { - this._onCheckShell.fire(); + (import('windows-process-tree')).then(mod => { + if (this._isDisposed) { + return; } - }); - // Fire a new check for the shell when any key is pressed. - this._xterm.on('keypress', () => this._onCheckShell.fire()); + windowsProcessTree = mod; + this._onCheckShell = new Emitter>(); + // The debounce is necessary to prevent multiple processes from spawning when + // the enter key or output is spammed + debounceEvent(this._onCheckShell.event, (l, e) => e, 150, true)(() => { + setTimeout(() => { + this.checkShell(); + }, 50); + }); + + // We want to fire a new check for the shell on a linefeed, but only + // when parsing has finished which is indicated by the cursormove event. + // If this is done on every linefeed, parsing ends up taking + // significantly longer due to resetting timers. Note that this is + // private API. + this._xterm.on('linefeed', () => this._newLineFeed = true); + this._xterm.on('cursormove', () => { + if (this._newLineFeed) { + this._onCheckShell.fire(); + } + }); + + // Fire a new check for the shell when any key is pressed. + this._xterm.on('keypress', () => this._onCheckShell.fire()); + }); } private checkShell(): void { @@ -110,7 +115,7 @@ export class WindowsShellHelper { return this._currentRequest; } this._currentRequest = new TPromise(resolve => { - windowsProcessTree(this._rootProcessId, (tree) => { + windowsProcessTree.getProcessTree(this._rootProcessId, (tree) => { const name = this.traverseTree(tree); this._currentRequest = null; resolve(name); @@ -118,4 +123,4 @@ export class WindowsShellHelper { }); return this._currentRequest; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalColorRegistry.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalColorRegistry.test.ts index 6c312a8fb1..48bf35dfc6 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalColorRegistry.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalColorRegistry.test.ts @@ -3,18 +3,16 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as assert from 'assert'; import { Extensions as ThemeingExtensions, IColorRegistry, ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ansiColorIdentifiers, registerColors } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; +import { ansiColorIdentifiers, registerColors } from 'vs/workbench/parts/terminal/common/terminalColorRegistry'; import { ITheme, ThemeType } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; registerColors(); -let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); +let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); function getMockTheme(type: ThemeType): ITheme { let theme = { selector: '', diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index b89e95fbb2..5c16f9af8d 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -3,12 +3,10 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as assert from 'assert'; import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { isFedora } from 'vs/workbench/parts/terminal/electron-browser/terminal'; +import { isFedora } from 'vs/workbench/parts/terminal/node/terminal'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; suite('Workbench - TerminalConfigHelper', () => { diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts deleted file mode 100644 index 2012a69123..0000000000 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts +++ /dev/null @@ -1,215 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 assert from 'assert'; -import * as os from 'os'; -import * as platform from 'vs/base/common/platform'; -import Uri from 'vs/base/common/uri'; -import { IStringDictionary } from 'vs/base/common/collections'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; -import { IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; -import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; -import { TestNotificationService, TestContextService, TestHistoryService } from 'vs/workbench/test/workbenchTestServices'; -import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { ILogService, NullLogService } from 'vs/platform/log/common/log'; - -class TestTerminalInstance extends TerminalInstance { - - public _getCwd(shell: IShellLaunchConfig, root: Uri): string { - return super._getCwd(shell, root); - } - - protected _createProcess(): void { } - protected _createXterm(): TPromise { return TPromise.as(void 0); } -} - -suite('Workbench - TerminalInstance', () => { - - let instantiationService: TestInstantiationService; - - setup(() => { - instantiationService = new TestInstantiationService(); - instantiationService.stub(INotificationService, new TestNotificationService()); - instantiationService.stub(IHistoryService, new TestHistoryService()); - }); - - test('createTerminalEnv', function () { - const shell1 = { - executable: '/bin/foosh', - args: ['-bar', 'baz'] - }; - const parentEnv1: IStringDictionary = { - ok: true - } as any; - const env1 = TerminalInstance.createTerminalEnv(parentEnv1, shell1, '/foo', 'en-au'); - assert.ok(env1['ok'], 'Parent environment is copied'); - assert.deepStrictEqual(parentEnv1, { ok: true }, 'Parent environment is unchanged'); - assert.equal(env1['PTYPID'], process.pid.toString(), 'PTYPID is equal to the current PID'); - assert.equal(env1['PTYSHELL'], '/bin/foosh', 'PTYSHELL is equal to the provided shell'); - assert.equal(env1['PTYSHELLARG0'], '-bar', 'PTYSHELLARG0 is equal to the first shell argument'); - assert.equal(env1['PTYSHELLARG1'], 'baz', 'PTYSHELLARG1 is equal to the first shell argument'); - assert.ok(!('PTYSHELLARG2' in env1), 'PTYSHELLARG2 is unset'); - assert.equal(env1['PTYCWD'], '/foo', 'PTYCWD is equal to requested cwd'); - assert.equal(env1['LANG'], 'en_AU.UTF-8', 'LANG is equal to the requested locale with UTF-8'); - - const shell2: IShellLaunchConfig = { - executable: '/bin/foosh', - args: [] - }; - const parentEnv2: IStringDictionary = { - LANG: 'en_US.UTF-8' - }; - const env2 = TerminalInstance.createTerminalEnv(parentEnv2, shell2, '/foo', 'en-au'); - assert.ok(!('PTYSHELLARG0' in env2), 'PTYSHELLARG0 is unset'); - assert.equal(env2['PTYCWD'], '/foo', 'PTYCWD is equal to /foo'); - assert.equal(env2['LANG'], 'en_AU.UTF-8', 'LANG is equal to the requested locale with UTF-8'); - - const env3 = TerminalInstance.createTerminalEnv(parentEnv1, shell1, '/', null); - assert.equal(env3['LANG'], 'en_US.UTF-8', 'LANG is equal to en_US.UTF-8 as fallback.'); // More info on issue #14586 - - const env4 = TerminalInstance.createTerminalEnv(parentEnv2, shell1, '/', null); - assert.equal(env4['LANG'], 'en_US.UTF-8', 'LANG is equal to the parent environment\'s LANG'); - }); - - suite('mergeEnvironments', () => { - test('should add keys', () => { - const parent = { - a: 'b' - }; - const other = { - c: 'd' - }; - TerminalInstance.mergeEnvironments(parent, other); - assert.deepEqual(parent, { - a: 'b', - c: 'd' - }); - }); - - test('should add keys ignoring case on Windows', () => { - if (!platform.isWindows) { - return; - } - const parent = { - a: 'b' - }; - const other = { - A: 'c' - }; - TerminalInstance.mergeEnvironments(parent, other); - assert.deepEqual(parent, { - a: 'c' - }); - }); - - test('null values should delete keys from the parent env', () => { - const parent = { - a: 'b', - c: 'd' - }; - const other: IStringDictionary = { - a: null - }; - TerminalInstance.mergeEnvironments(parent, other); - assert.deepEqual(parent, { - c: 'd' - }); - }); - - test('null values should delete keys from the parent env ignoring case on Windows', () => { - if (!platform.isWindows) { - return; - } - const parent = { - a: 'b', - c: 'd' - }; - const other: IStringDictionary = { - A: null - }; - TerminalInstance.mergeEnvironments(parent, other); - assert.deepEqual(parent, { - c: 'd' - }); - }); - }); - - suite('_getCwd', () => { - let instance: TestTerminalInstance; - let instantiationService: TestInstantiationService; - let configHelper: { config: { cwd: string } }; - - setup(() => { - let contextKeyService = new MockContextKeyService(); - let keybindingService = new MockKeybindingService(); - let terminalFocusContextKey = contextKeyService.createKey('test', false); - instantiationService = new TestInstantiationService(); - instantiationService.stub(IConfigurationService, new TestConfigurationService()); - instantiationService.stub(INotificationService, new TestNotificationService()); - instantiationService.stub(IWorkspaceContextService, new TestContextService()); - instantiationService.stub(IKeybindingService, keybindingService); - instantiationService.stub(IContextKeyService, contextKeyService); - instantiationService.stub(IHistoryService, new TestHistoryService()); - instantiationService.stub(ILogService, new NullLogService()); - configHelper = { - config: { - cwd: null - } - }; - instance = instantiationService.createInstance(TestTerminalInstance, terminalFocusContextKey, configHelper, null, null); - }); - - // This helper checks the paths in a cross-platform friendly manner - function assertPathsMatch(a: string, b: string): void { - assert.equal(Uri.file(a).fsPath, Uri.file(b).fsPath); - } - - test('should default to os.homedir() for an empty workspace', () => { - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, null), os.homedir()); - }); - - test('should use to the workspace if it exists', () => { - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, Uri.file('/foo')), '/foo'); - }); - - test('should use an absolute custom cwd as is', () => { - configHelper.config.cwd = '/foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, null), '/foo'); - }); - - test('should normalize a relative custom cwd against the workspace path', () => { - configHelper.config.cwd = 'foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, Uri.file('/bar')), '/bar/foo'); - configHelper.config.cwd = './foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, Uri.file('/bar')), '/bar/foo'); - configHelper.config.cwd = '../foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, Uri.file('/bar'), ), '/foo'); - }); - - test('should fall back for relative a custom cwd that doesn\'t have a workspace', () => { - configHelper.config.cwd = 'foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, null), os.homedir()); - configHelper.config.cwd = './foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, null), os.homedir()); - configHelper.config.cwd = '../foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [] }, null), os.homedir()); - }); - - test('should ignore custom cwd when told to ignore', () => { - configHelper.config.cwd = '/foo'; - assertPathsMatch(instance._getCwd({ executable: null, args: [], ignoreConfigurationCwd: true }, Uri.file('/bar')), '/bar'); - }); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts index d004cba6e1..6035fe11d4 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -3,8 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as assert from 'assert'; import { Platform } from 'vs/base/common/platform'; import { TerminalLinkHandler, LineColumnInfo } from 'vs/workbench/parts/terminal/electron-browser/terminalLinkHandler'; diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalPanel.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalPanel.test.ts deleted file mode 100644 index 4292840420..0000000000 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalPanel.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 assert from 'assert'; -import { TerminalPanel } from 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; -import * as platform from 'vs/base/common/platform'; - -suite('Workbench - TerminalPanel', () => { - test('preparePathForTerminal', function () { - if (platform.isWindows) { - assert.equal(TerminalPanel.preparePathForTerminal('C:\\foo'), 'C:\\foo'); - assert.equal(TerminalPanel.preparePathForTerminal('C:\\foo bar'), '"C:\\foo bar"'); - return; - } - assert.equal(TerminalPanel.preparePathForTerminal('/a/\\foo bar"\'? ;\'?? :'), '/a/\\\\foo\\ bar\\"\\\'\\?\\ \\;\\\'\\?\\?\\ \\ \\:'); - assert.equal(TerminalPanel.preparePathForTerminal('/\\\'"?:;!*(){}[]'), '/\\\\\\\'\\"\\?\\:\\;\\!\\*\\(\\)\\{\\}\\[\\]'); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/test/node/terminalCommandTracker.test.ts b/src/vs/workbench/parts/terminal/test/node/terminalCommandTracker.test.ts new file mode 100644 index 0000000000..bbd9877126 --- /dev/null +++ b/src/vs/workbench/parts/terminal/test/node/terminalCommandTracker.test.ts @@ -0,0 +1,114 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { Terminal } from 'vscode-xterm'; +import { TerminalCommandTracker } from 'vs/workbench/parts/terminal/node/terminalCommandTracker'; + +interface TestTerminal extends Terminal { + writeBuffer: string[]; + _innerWrite(): void; +} + +function syncWrite(term: TestTerminal, data: string): void { + // Terminal.write is asynchronous + term.writeBuffer.push(data); + term._innerWrite(); +} + +const ROWS = 10; +const COLS = 10; + +suite('Workbench - TerminalCommandTracker', () => { + let xterm: TestTerminal; + let commandTracker: TerminalCommandTracker; + + setup(() => { + xterm = (new Terminal({ + cols: COLS, + rows: ROWS + })); + // Fill initial viewport + for (let i = 0; i < ROWS - 1; i++) { + syncWrite(xterm, `${i}\n`); + } + commandTracker = new TerminalCommandTracker(xterm); + }); + + suite('Command tracking', () => { + test('should track commands when the prompt is of sufficient size', () => { + assert.equal(xterm.markers.length, 0); + syncWrite(xterm, '\x1b[3G'); // Move cursor to column 3 + xterm.emit('key', '\x0d'); + assert.equal(xterm.markers.length, 1); + }); + test('should not track commands when the prompt is too small', () => { + assert.equal(xterm.markers.length, 0); + syncWrite(xterm, '\x1b[2G'); // Move cursor to column 2 + xterm.emit('key', '\x0d'); + assert.equal(xterm.markers.length, 0); + }); + }); + + suite('Commands', () => { + test('should scroll to the next and previous commands', () => { + syncWrite(xterm, '\x1b[3G'); // Move cursor to column 3 + xterm.emit('key', '\x0d'); // Mark line #10 + assert.equal(xterm.markers[0].line, 9); + + for (let i = 0; i < 20; i++) { + syncWrite(xterm, `\r\n`); + } + assert.equal(xterm.buffer.ybase, 20); + assert.equal(xterm.buffer.ydisp, 20); + + // Scroll to marker + commandTracker.scrollToPreviousCommand(); + assert.equal(xterm.buffer.ydisp, 9); + + // Scroll to top boundary + commandTracker.scrollToPreviousCommand(); + assert.equal(xterm.buffer.ydisp, 0); + + // Scroll to marker + commandTracker.scrollToNextCommand(); + assert.equal(xterm.buffer.ydisp, 9); + + // Scroll to bottom boundary + commandTracker.scrollToNextCommand(); + assert.equal(xterm.buffer.ydisp, 20); + }); + // test('should select to the next and previous commands', () => { + // (window).matchMedia = () => { + // return { addListener: () => {} } + // }; + // xterm.open(document.createElement('div')); + + // syncWrite(xterm, '\r0'); + // syncWrite(xterm, '\n\r1'); + // syncWrite(xterm, '\x1b[3G'); // Move cursor to column 3 + // xterm.emit('key', '\x0d'); // Mark line + // assert.equal(xterm.markers[0].line, 10); + // syncWrite(xterm, '\n\r2'); + // syncWrite(xterm, '\x1b[3G'); // Move cursor to column 3 + // xterm.emit('key', '\x0d'); // Mark line + // assert.equal(xterm.markers[1].line, 11); + // syncWrite(xterm, '\n\r3'); + + // assert.equal(xterm.buffer.ybase, 3); + // assert.equal(xterm.buffer.ydisp, 3); + + // assert.equal(xterm.getSelection(), ''); + // commandTracker.selectToPreviousCommand(); + // assert.equal(xterm.getSelection(), '2'); + // commandTracker.selectToPreviousCommand(); + // assert.equal(xterm.getSelection(), '1\n2'); + // commandTracker.selectToNextCommand(); + // assert.equal(xterm.getSelection(), '2'); + // commandTracker.selectToNextCommand(); + // assert.equal(xterm.getSelection(), '\n'); + // }); + }); +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/test/node/terminalEnvironment.test.ts b/src/vs/workbench/parts/terminal/test/node/terminalEnvironment.test.ts new file mode 100644 index 0000000000..a8e588ee95 --- /dev/null +++ b/src/vs/workbench/parts/terminal/test/node/terminalEnvironment.test.ts @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as os from 'os'; +import * as platform from 'vs/base/common/platform'; +import * as terminalEnvironment from 'vs/workbench/parts/terminal/node/terminalEnvironment'; +import Uri from 'vs/base/common/uri'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { IShellLaunchConfig, ITerminalConfigHelper } from 'vs/workbench/parts/terminal/common/terminal'; + +suite('Workbench - TerminalEnvironment', () => { + test('createTerminalEnv', function () { + const shell1 = { + executable: '/bin/foosh', + args: ['-bar', 'baz'] + }; + const parentEnv1: IStringDictionary = { + ok: true + } as any; + const env1 = terminalEnvironment.createTerminalEnv(parentEnv1, shell1, '/foo', 'en-au'); + assert.ok(env1['ok'], 'Parent environment is copied'); + assert.deepStrictEqual(parentEnv1, { ok: true }, 'Parent environment is unchanged'); + assert.equal(env1['PTYPID'], process.pid.toString(), 'PTYPID is equal to the current PID'); + assert.equal(env1['PTYSHELL'], '/bin/foosh', 'PTYSHELL is equal to the provided shell'); + assert.equal(env1['PTYSHELLARG0'], '-bar', 'PTYSHELLARG0 is equal to the first shell argument'); + assert.equal(env1['PTYSHELLARG1'], 'baz', 'PTYSHELLARG1 is equal to the first shell argument'); + assert.ok(!('PTYSHELLARG2' in env1), 'PTYSHELLARG2 is unset'); + assert.equal(env1['PTYCWD'], '/foo', 'PTYCWD is equal to requested cwd'); + assert.equal(env1['LANG'], 'en_AU.UTF-8', 'LANG is equal to the requested locale with UTF-8'); + + const shell2: IShellLaunchConfig = { + executable: '/bin/foosh', + args: [] + }; + const parentEnv2: IStringDictionary = { + LANG: 'en_US.UTF-8' + }; + const env2 = terminalEnvironment.createTerminalEnv(parentEnv2, shell2, '/foo', 'en-au'); + assert.ok(!('PTYSHELLARG0' in env2), 'PTYSHELLARG0 is unset'); + assert.equal(env2['PTYCWD'], '/foo', 'PTYCWD is equal to /foo'); + assert.equal(env2['LANG'], 'en_AU.UTF-8', 'LANG is equal to the requested locale with UTF-8'); + + const env3 = terminalEnvironment.createTerminalEnv(parentEnv1, shell1, '/', null); + assert.equal(env3['LANG'], 'en_US.UTF-8', 'LANG is equal to en_US.UTF-8 as fallback.'); // More info on issue #14586 + + const env4 = terminalEnvironment.createTerminalEnv(parentEnv2, shell1, '/', null); + assert.equal(env4['LANG'], 'en_US.UTF-8', 'LANG is equal to the parent environment\'s LANG'); + }); + + suite('mergeEnvironments', () => { + test('should add keys', () => { + const parent = { + a: 'b' + }; + const other = { + c: 'd' + }; + terminalEnvironment.mergeEnvironments(parent, other); + assert.deepEqual(parent, { + a: 'b', + c: 'd' + }); + }); + + test('should add keys ignoring case on Windows', () => { + if (!platform.isWindows) { + return; + } + const parent = { + a: 'b' + }; + const other = { + A: 'c' + }; + terminalEnvironment.mergeEnvironments(parent, other); + assert.deepEqual(parent, { + a: 'c' + }); + }); + + test('null values should delete keys from the parent env', () => { + const parent = { + a: 'b', + c: 'd' + }; + const other: IStringDictionary = { + a: null + }; + terminalEnvironment.mergeEnvironments(parent, other); + assert.deepEqual(parent, { + c: 'd' + }); + }); + + test('null values should delete keys from the parent env ignoring case on Windows', () => { + if (!platform.isWindows) { + return; + } + const parent = { + a: 'b', + c: 'd' + }; + const other: IStringDictionary = { + A: null + }; + terminalEnvironment.mergeEnvironments(parent, other); + assert.deepEqual(parent, { + c: 'd' + }); + }); + }); + + suite('getCwd', () => { + let configHelper: ITerminalConfigHelper; + + setup(() => { + configHelper = { + config: { + cwd: null + } + }; + }); + + // This helper checks the paths in a cross-platform friendly manner + function assertPathsMatch(a: string, b: string): void { + assert.equal(Uri.file(a).fsPath, Uri.file(b).fsPath); + } + + test('should default to os.homedir() for an empty workspace', () => { + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, null, configHelper), os.homedir()); + }); + + test('should use to the workspace if it exists', () => { + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, Uri.file('/foo'), configHelper), '/foo'); + }); + + test('should use an absolute custom cwd as is', () => { + configHelper.config.cwd = '/foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, null, configHelper), '/foo'); + }); + + test('should normalize a relative custom cwd against the workspace path', () => { + configHelper.config.cwd = 'foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, Uri.file('/bar'), configHelper), '/bar/foo'); + configHelper.config.cwd = './foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, Uri.file('/bar'), configHelper), '/bar/foo'); + configHelper.config.cwd = '../foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, Uri.file('/bar'), configHelper), '/foo'); + }); + + test('should fall back for relative a custom cwd that doesn\'t have a workspace', () => { + configHelper.config.cwd = 'foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, null, configHelper), os.homedir()); + configHelper.config.cwd = './foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, null, configHelper), os.homedir()); + configHelper.config.cwd = '../foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [] }, null, configHelper), os.homedir()); + }); + + test('should ignore custom cwd when told to ignore', () => { + configHelper.config.cwd = '/foo'; + assertPathsMatch(terminalEnvironment.getCwd({ executable: null, args: [], ignoreConfigurationCwd: true }, Uri.file('/bar'), configHelper), '/bar'); + }); + }); + + test('preparePathForTerminal', function () { + if (platform.isWindows) { + assert.equal(terminalEnvironment.preparePathForTerminal('C:\\foo'), 'C:\\foo'); + assert.equal(terminalEnvironment.preparePathForTerminal('C:\\foo bar'), '"C:\\foo bar"'); + return; + } + assert.equal(terminalEnvironment.preparePathForTerminal('/a/\\foo bar"\'? ;\'?? :'), '/a/\\\\foo\\ bar\\"\\\'\\?\\ \\;\\\'\\?\\?\\ \\ \\:'); + assert.equal(terminalEnvironment.preparePathForTerminal('/\\\'"?:;!*(){}[]'), '/\\\\\\\'\\"\\?\\:\\;\\!\\*\\(\\)\\{\\}\\[\\]'); + }); +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts index 512eebef4c..f3d8179840 100644 --- a/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts +++ b/src/vs/workbench/parts/themes/electron-browser/themes.contribution.ts @@ -78,9 +78,9 @@ export class SelectColorThemeAction extends Action { return this.quickOpenService.pick(picks, { placeHolder, autoFocus: { autoFocusIndex } }) .then( - theme => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0), - null, - theme => delayer.trigger(() => selectTheme(theme, false)) + theme => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0), + null, + theme => delayer.trigger(() => selectTheme(theme, false)) ); }); } @@ -137,9 +137,9 @@ class SelectIconThemeAction extends Action { return this.quickOpenService.pick(picks, { placeHolder, autoFocus: { autoFocusIndex } }) .then( - theme => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0), - null, - theme => delayer.trigger(() => selectTheme(theme, false)) + theme => delayer.trigger(() => selectTheme(theme || currentTheme, true), 0), + null, + theme => delayer.trigger(() => selectTheme(theme, false)) ); }); } @@ -187,7 +187,7 @@ class GenerateColorThemeAction extends Action { run(): TPromise { let theme = this.themeService.getColorTheme(); - let colorRegistry = Registry.as(ColorRegistryExtensions.ColorContribution); + let colorRegistry = Registry.as(ColorRegistryExtensions.ColorContribution); let resultingColors = {}; colorRegistry.getColors().map(c => { let color = theme.getColor(c.id, false); diff --git a/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts b/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts index e83cf02f52..f6bd8c7fee 100644 --- a/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts +++ b/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts @@ -6,10 +6,10 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import URI from 'vs/base/common/uri'; import { IModeService } from 'vs/editor/common/services/modeService'; -import pfs = require('vs/base/node/pfs'); +import * as pfs from 'vs/base/node/pfs'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; diff --git a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts b/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts deleted file mode 100644 index 434d7f3ff0..0000000000 --- a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts +++ /dev/null @@ -1,80 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 nls from 'vs/nls'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences'; -import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; -import { Severity } from 'vs/platform/notification/common/notification'; - -class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution { - - private static readonly storageKey = 'workspace.settings.unsupported.warning'; - private toDispose: IDisposable[] = []; - private isUntrusted = false; - - constructor( - @ILifecycleService lifecycleService: ILifecycleService, - @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, - @IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService, - @IPreferencesService private preferencesService: IPreferencesService, - @IChoiceService private choiceService: IChoiceService, - @IStorageService private storageService: IStorageService - ) { - lifecycleService.onShutdown(this.dispose, this); - this.toDispose.push(this.workspaceConfigurationService.onDidChangeConfiguration(e => this.checkWorkspaceSettings())); - this.toDispose.push(workspaceContextService.onDidChangeWorkspaceFolders(e => this.checkWorkspaceSettings())); - } - - public dispose(): void { - this.toDispose = dispose(this.toDispose); - } - - private checkWorkspaceSettings(): void { - if (this.isUntrusted) { - return; - } - - const configurationKeys = this.workspaceConfigurationService.getUnsupportedWorkspaceKeys(); - this.isUntrusted = configurationKeys.length > 0; - if (this.isUntrusted && !this.hasShownWarning()) { - this.showWarning(configurationKeys); - } - } - - private hasShownWarning(): boolean { - return this.storageService.getBoolean(UnsupportedWorkspaceSettingsContribution.storageKey, StorageScope.WORKSPACE, false); - } - - private rememberWarningWasShown(): void { - this.storageService.store(UnsupportedWorkspaceSettingsContribution.storageKey, true, StorageScope.WORKSPACE); - } - - private showWarning(unsupportedKeys: string[]): void { - const choices: Choice[] = [nls.localize('openWorkspaceSettings', 'Open Workspace Settings'), { label: nls.localize('dontShowAgain', 'Don\'t Show Again') }]; - this.choiceService.choose(Severity.Warning, nls.localize('unsupportedWorkspaceSettings', 'This Workspace contains settings that can only be set in User Settings ({0}). Click [here]({1}) to learn more.', unsupportedKeys.join(', '), 'https://go.microsoft.com/fwlink/?linkid=839878'), choices).then(choice => { - switch (choice) { - case 0 /* Open Workspace Settings */: - this.rememberWarningWasShown(); - this.preferencesService.openWorkspaceSettings(); - break; - case 1 /* Never show again */: - this.rememberWarningWasShown(); - break; - } - }); - } -} - -const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); -workbenchRegistry.registerWorkbenchContribution(UnsupportedWorkspaceSettingsContribution, LifecyclePhase.Running); diff --git a/src/vs/workbench/parts/update/electron-browser/media/update.svg b/src/vs/workbench/parts/update/electron-browser/media/update.svg index 3dec2ba50f..c97bb48bdc 100644 --- a/src/vs/workbench/parts/update/electron-browser/media/update.svg +++ b/src/vs/workbench/parts/update/electron-browser/media/update.svg @@ -1 +1 @@ - \ No newline at end of file +configure \ No newline at end of file diff --git a/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts b/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts index fc9fef2ae5..c1ea72c611 100644 --- a/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts +++ b/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts @@ -5,29 +5,29 @@ 'use strict'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { marked } from 'vs/base/common/marked/marked'; -import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import { Builder } from 'vs/base/browser/builder'; -import { append, $ } from 'vs/base/browser/dom'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { ReleaseNotesInput } from './releaseNotesInput'; -import { EditorOptions } from 'vs/workbench/common/editor'; -import { Webview } from 'vs/workbench/parts/html/browser/webview'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IModeService } from 'vs/editor/common/services/modeService'; -import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; -import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; -import { WebviewEditor } from 'vs/workbench/parts/html/browser/webviewEditor'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IMode, TokenizationRegistry } from 'vs/editor/common/modes'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { addGAParameters } from 'vs/platform/telemetry/node/telemetryNodeUtils'; +import { marked } from 'vs/base/common/marked/marked'; +import { OS } from 'vs/base/common/platform'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { asText } from 'vs/base/node/request'; +import { IMode, TokenizationRegistry } from 'vs/editor/common/modes'; import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization'; +import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; +import { IModeService } from 'vs/editor/common/services/modeService'; +import * as nls from 'vs/nls'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { IRequestService } from 'vs/platform/request/node/request'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { addGAParameters } from 'vs/platform/telemetry/node/telemetryNodeUtils'; +import { IWebviewEditorService } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; +import { Position } from 'vs/platform/editor/common/editor'; +import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput'; function renderBody( body: string, @@ -47,103 +47,111 @@ function renderBody( `; } -export class ReleaseNotesEditor extends WebviewEditor { +export class ReleaseNotesManager { - static readonly ID: string = 'workbench.editor.releaseNotes'; + private _releaseNotesCache: { [version: string]: TPromise; } = Object.create(null); - private contentDisposables: IDisposable[] = []; - private scrollYPercentage: number = 0; + private _currentReleaseNotes: WebviewEditorInput | undefined = undefined; - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService storageService: IStorageService, - @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService protected readonly themeService: IThemeService, - @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IOpenerService private readonly openerService: IOpenerService, - @IModeService private readonly modeService: IModeService, - @IPartService private readonly partService: IPartService, - @IContextViewService private readonly _contextViewService: IContextViewService - ) { - super(ReleaseNotesEditor.ID, telemetryService, themeService, storageService, contextKeyService); - } + public constructor( + @IEnvironmentService private readonly _environmentService: IEnvironmentService, + @IKeybindingService private readonly _keybindingService: IKeybindingService, + @IModeService private readonly _modeService: IModeService, + @IOpenerService private readonly _openerService: IOpenerService, + @IRequestService private readonly _requestService: IRequestService, + @ITelemetryService private readonly _telemetryService: ITelemetryService, + @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, + @IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService, + ) { } - createEditor(parent: Builder): void { - const container = parent.getHTMLElement(); - this.content = append(container, $('.release-notes', { 'style': 'height: 100%; position: relative; overflow: hidden;' })); - } + public async show( + accessor: ServicesAccessor, + version: string + ): TPromise { + const releaseNoteText = await this.loadReleaseNotes(version); + const html = await this.renderBody(releaseNoteText); + const title = nls.localize('releaseNotesInputName', "Release Notes: {0}", version); - async setInput(input: ReleaseNotesInput, options: EditorOptions): TPromise { - if (this.input && this.input.matches(input)) { - return undefined; + const activeEditor = this._editorService.getActiveEditor(); + if (this._currentReleaseNotes) { + this._currentReleaseNotes.setName(title); + this._currentReleaseNotes.html = html; + this._webviewEditorService.revealWebview(this._currentReleaseNotes, activeEditor ? activeEditor.position : undefined); + } else { + this._currentReleaseNotes = this._webviewEditorService.createWebview( + 'releaseNotes', + title, + activeEditor ? activeEditor.position : Position.ONE, + { tryRestoreScrollPosition: true, enableFindWidget: true }, + undefined, { + onDidClickLink: uri => this.onDidClickLink(uri), + onDispose: () => { this._currentReleaseNotes = undefined; } + }); + + this._currentReleaseNotes.html = html; } - const { text } = input; + return true; + } - this.contentDisposables = dispose(this.contentDisposables); - this.content.innerHTML = ''; - - await super.setInput(input, options); - - const body = await this.renderBody(text); - this._webview = new Webview( - this.content, - this.partService.getContainer(Parts.EDITOR_PART), - this.themeService, - this.environmentService, - this._contextViewService, - this.contextKey, - this.findInputFocusContextKey, - {}); - - if (this.input && this.input instanceof ReleaseNotesInput) { - const state = this.loadViewState(this.input.version); - if (state) { - this._webview.initialScrollProgress = state.scrollYPercentage; - } + private loadReleaseNotes( + version: string + ): TPromise { + const match = /^(\d+\.\d+)\./.exec(version); + if (!match) { + return TPromise.wrapError(new Error('not found')); } - this._webview.contents = body; + const versionLabel = match[1].replace(/\./g, '_'); + const baseUrl = 'https://code.visualstudio.com/raw'; + const url = `${baseUrl}/v${versionLabel}.md`; + const unassigned = nls.localize('unassigned', "unassigned"); - this._webview.onDidClickLink(link => { - addGAParameters(this.telemetryService, this.environmentService, link, 'ReleaseNotes') - .then(updated => this.openerService.open(updated)) - .then(null, onUnexpectedError); - }, null, this.contentDisposables); - this._webview.onDidScroll(event => { - this.scrollYPercentage = event.scrollYPercentage; - }, null, this.contentDisposables); - this.contentDisposables.push(this._webview); - this.contentDisposables.push(toDisposable(() => this._webview = null)); - } + const patchKeybindings = (text: string): string => { + const kb = (match: string, kb: string) => { + const keybinding = this._keybindingService.lookupKeybinding(kb); - dispose(): void { - this.contentDisposables = dispose(this.contentDisposables); - super.dispose(); - } + if (!keybinding) { + return unassigned; + } - protected getViewState() { - return { - scrollYPercentage: this.scrollYPercentage + return keybinding.getLabel(); + }; + + const kbstyle = (match: string, kb: string) => { + const keybinding = KeybindingIO.readKeybinding(kb, OS); + + if (!keybinding) { + return unassigned; + } + + const resolvedKeybindings = this._keybindingService.resolveKeybinding(keybinding); + + if (resolvedKeybindings.length === 0) { + return unassigned; + } + + return resolvedKeybindings[0].getLabel(); + }; + + return text + .replace(/kb\(([a-z.\d\-]+)\)/gi, kb) + .replace(/kbstyle\(([^\)]+)\)/gi, kbstyle); }; + + if (!this._releaseNotesCache[version]) { + this._releaseNotesCache[version] = this._requestService.request({ url }) + .then(asText) + .then(text => patchKeybindings(text)); + } + + return this._releaseNotesCache[version]; } - public clearInput(): void { - if (this.input instanceof ReleaseNotesInput) { - this.saveViewState(this.input.version, { - scrollYPercentage: this.scrollYPercentage - }); - } - super.clearInput(); - } - - public shutdown(): void { - if (this.input instanceof ReleaseNotesInput) { - this.saveViewState(this.input.version, { - scrollYPercentage: this.scrollYPercentage - }); - } - super.shutdown(); + private onDidClickLink(uri: URI) { + addGAParameters(this._telemetryService, this._environmentService, uri, 'ReleaseNotes') + .then(updated => this._openerService.open(updated)) + .then(null, onUnexpectedError); } private async renderBody(text: string) { @@ -162,8 +170,8 @@ export class ReleaseNotesEditor extends WebviewEditor { const result: TPromise[] = []; const renderer = new marked.Renderer(); renderer.code = (code, lang) => { - const modeId = this.modeService.getModeIdForLanguageName(lang); - result.push(this.modeService.getOrCreateMode(modeId)); + const modeId = this._modeService.getModeIdForLanguageName(lang); + result.push(this._modeService.getOrCreateMode(modeId)); return ''; }; @@ -171,7 +179,7 @@ export class ReleaseNotesEditor extends WebviewEditor { await TPromise.join(result); renderer.code = (code, lang) => { - const modeId = this.modeService.getModeIdForLanguageName(lang); + const modeId = this._modeService.getModeIdForLanguageName(lang); return `${tokenizeToString(code, modeId)}`; }; return renderer; diff --git a/src/vs/workbench/parts/update/electron-browser/releaseNotesInput.ts b/src/vs/workbench/parts/update/electron-browser/releaseNotesInput.ts deleted file mode 100644 index 6903048799..0000000000 --- a/src/vs/workbench/parts/update/electron-browser/releaseNotesInput.ts +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { localize } from 'vs/nls'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { EditorInput } from 'vs/workbench/common/editor'; -import URI from 'vs/base/common/uri'; - -export class ReleaseNotesInput extends EditorInput { - - static readonly ID = 'workbench.releaseNotes.input'; - - get version(): string { return this._version; } - get text(): string { return this._text; } - - constructor(private _version: string, private _text: string) { - super(); - } - - getResource(): URI { - return URI.from({ scheme: 'release-notes', path: `${this._version}.release-notes` }); - } - - getTypeId(): string { - return ReleaseNotesInput.ID; - } - - getName(): string { - return localize('releaseNotesInputName', "Release Notes: {0}", this.version); - } - - matches(other: any): boolean { - if (!(other instanceof ReleaseNotesInput)) { - return false; - } - - const otherInput = other as ReleaseNotesInput; - return this.version === otherInput.version; - } - - resolve(refresh?: boolean): TPromise { - return TPromise.as(null); - } - - supportsSplitEditor(): boolean { - return false; - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts index a6566303e4..54848b51b0 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts @@ -5,20 +5,15 @@ 'use strict'; -import * as nls from 'vs/nls'; import 'vs/css!./media/update.contribution'; import 'vs/platform/update/node/update.config.contribution'; import * as platform from 'vs/base/common/platform'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { ReleaseNotesEditor } from 'vs/workbench/parts/update/electron-browser/releaseNotesEditor'; -import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput'; import { IGlobalActivityRegistry, GlobalActivityExtensions } from 'vs/workbench/common/activity'; -import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { ShowCurrentReleaseNotesAction, ProductContribution, UpdateContribution, Win3264BitContribution } from './update'; -import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; Registry.as(WorkbenchExtensions.Workbench) @@ -33,14 +28,5 @@ Registry.as(GlobalActivityExtensions) .registerActivity(UpdateContribution); // Editor -const editorDescriptor = new EditorDescriptor( - ReleaseNotesEditor, - ReleaseNotesEditor.ID, - nls.localize('release notes', "Release notes") -); - -Registry.as(EditorExtensions.Editors) - .registerEditor(editorDescriptor, [new SyncDescriptor(ReleaseNotesInput)]); - Registry.as(ActionExtensions.WorkbenchActions) .registerWorkbenchAction(new SyncActionDescriptor(ShowCurrentReleaseNotesAction, ShowCurrentReleaseNotesAction.ID, ShowCurrentReleaseNotesAction.LABEL), 'Show Release Notes'); diff --git a/src/vs/workbench/parts/update/electron-browser/update.ts b/src/vs/workbench/parts/update/electron-browser/update.ts index bef451ed3d..135c93f1a9 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.ts @@ -5,7 +5,7 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, Action } from 'vs/base/common/actions'; @@ -16,88 +16,29 @@ import product from 'vs/platform/node/product'; import URI from 'vs/base/common/uri'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IActivityService, NumberBadge, IBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; -import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IGlobalActivity } from 'vs/workbench/common/activity'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { asText } from 'vs/base/node/request'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update'; import * as semver from 'semver'; -import { OS } from 'vs/base/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IWindowService } from 'vs/platform/windows/common/windows'; +import { ReleaseNotesManager } from './releaseNotesEditor'; +import { isWindows } from 'vs/base/common/platform'; -const NotNowAction = new Action( - 'update.later', - nls.localize('later', "Later"), - null, - true, - () => TPromise.as(true) -); +let releaseNotesManager: ReleaseNotesManager | undefined = undefined; -const releaseNotesCache: { [version: string]: TPromise; } = Object.create(null); - -export function loadReleaseNotes(accessor: ServicesAccessor, version: string): TPromise { - const requestService = accessor.get(IRequestService); - const keybindingService = accessor.get(IKeybindingService); - const match = /^(\d+\.\d+)\./.exec(version); - - if (!match) { - return TPromise.wrapError(new Error('not found')); +function showReleaseNotes(instantiationService: IInstantiationService, version: string) { + if (!releaseNotesManager) { + releaseNotesManager = instantiationService.createInstance(ReleaseNotesManager); } - const versionLabel = match[1].replace(/\./g, '_'); - const baseUrl = 'https://code.visualstudio.com/raw'; - const url = `${baseUrl}/v${versionLabel}.md`; - const unassigned = nls.localize('unassigned', "unassigned"); - - const patchKeybindings = (text: string): string => { - const kb = (match: string, kb: string) => { - const keybinding = keybindingService.lookupKeybinding(kb); - - if (!keybinding) { - return unassigned; - } - - return keybinding.getLabel(); - }; - - const kbstyle = (match: string, kb: string) => { - const keybinding = KeybindingIO.readKeybinding(kb, OS); - - if (!keybinding) { - return unassigned; - } - - const resolvedKeybindings = keybindingService.resolveKeybinding(keybinding); - - if (resolvedKeybindings.length === 0) { - return unassigned; - } - - return resolvedKeybindings[0].getLabel(); - }; - - return text - .replace(/kb\(([a-z.\d\-]+)\)/gi, kb) - .replace(/kbstyle\(([^\)]+)\)/gi, kbstyle); - }; - - if (!releaseNotesCache[version]) { - releaseNotesCache[version] = requestService.request({ url }) - .then(asText) - .then(text => patchKeybindings(text)); - } - - return releaseNotesCache[version]; + return instantiationService.invokeFunction(accessor => releaseNotesManager.show(accessor, version)); } export class OpenLatestReleaseNotesInBrowserAction extends Action { @@ -120,7 +61,6 @@ export abstract class AbstractShowReleaseNotesAction extends Action { id: string, label: string, private version: string, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IInstantiationService private instantiationService: IInstantiationService ) { super(id, label, null, true); @@ -133,9 +73,7 @@ export abstract class AbstractShowReleaseNotesAction extends Action { this.enabled = false; - return this.instantiationService.invokeFunction(loadReleaseNotes, this.version) - .then(text => this.editorService.openEditor(this.instantiationService.createInstance(ReleaseNotesInput, this.version, text), { pinned: true })) - .then(() => true) + return showReleaseNotes(this.instantiationService, this.version) .then(null, () => { const action = this.instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction); return action.run().then(() => false); @@ -147,10 +85,9 @@ export class ShowReleaseNotesAction extends AbstractShowReleaseNotesAction { constructor( version: string, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IInstantiationService instantiationService: IInstantiationService ) { - super('update.showReleaseNotes', nls.localize('releaseNotes', "Release Notes"), version, editorService, instantiationService); + super('update.showReleaseNotes', nls.localize('releaseNotes', "Release Notes"), version, instantiationService); } } @@ -162,10 +99,9 @@ export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesActio constructor( id = ShowCurrentReleaseNotesAction.ID, label = ShowCurrentReleaseNotesAction.LABEL, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IInstantiationService instantiationService: IInstantiationService ) { - super(id, label, pkg.version, editorService, instantiationService); + super(id, label, pkg.version, instantiationService); } } @@ -178,7 +114,8 @@ export class ProductContribution implements IWorkbenchContribution { @IInstantiationService instantiationService: IInstantiationService, @INotificationService notificationService: INotificationService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IEnvironmentService environmentService: IEnvironmentService + @IEnvironmentService environmentService: IEnvironmentService, + @IOpenerService openerService: IOpenerService ) { // {{SQL CARBON EDIT}} /* @@ -186,23 +123,25 @@ export class ProductContribution implements IWorkbenchContribution { // was there an update? if so, open release notes if (!environmentService.skipReleaseNotes && product.releaseNotesUrl && lastVersion && pkg.version !== lastVersion) { - instantiationService.invokeFunction(loadReleaseNotes, pkg.version).then( - text => editorService.openEditor(instantiationService.createInstance(ReleaseNotesInput, pkg.version, text), { pinned: true }), - () => { - notificationService.notify({ - severity: severity.Info, - message: nls.localize('read the release notes', "Welcome to {0} v{1}! Would you like to read the Release Notes?", product.nameLong, pkg.version), - actions: { primary: [instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction)] } - }); + showReleaseNotes(instantiationService, pkg.version) + .then(undefined, () => { + notificationService.prompt( + severity.Info, + nls.localize('read the release notes', "Welcome to {0} v{1}! Would you like to read the Release Notes?", product.nameLong, pkg.version), + [{ + label: nls.localize('releaseNotes', "Release Notes"), + run: () => { + const uri = URI.parse(product.releaseNotesUrl); + openerService.open(uri); + } + }] + ); }); } // should we show the new license? if (product.licenseUrl && lastVersion && semver.satisfies(lastVersion, '<1.0.0') && semver.satisfies(pkg.version, '>=1.0.0')) { - notificationService.notify({ - severity: severity.Info, - message: nls.localize('licenseChanged', "Our license terms have changed, please click [here]({0}) to go through them.", product.licenseUrl), - }); + notificationService.info(nls.localize('licenseChanged', "Our license terms have changed, please click [here]({0}) to go through them.", product.licenseUrl)); } storageService.store(ProductContribution.KEY, pkg.version, StorageScope.GLOBAL); @@ -241,7 +180,7 @@ export class Win3264BitContribution implements IWorkbenchContribution { constructor( @IStorageService storageService: IStorageService, @IInstantiationService instantiationService: IInstantiationService, - @INotificationService private notificationService: INotificationService, + @INotificationService notificationService: INotificationService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IEnvironmentService environmentService: IEnvironmentService ) { @@ -259,11 +198,18 @@ export class Win3264BitContribution implements IWorkbenchContribution { ? Win3264BitContribution.INSIDER_URL : Win3264BitContribution.URL; - this.notificationService.notify({ - severity: severity.Info, - message: nls.localize('64bitisavailable', "{0} for 64-bit Windows is now available! Click [here]({1}) to learn more.", product.nameShort, url), - actions: { secondary: [neverShowAgain.action] } - }); + notificationService.prompt( + severity.Info, + nls.localize('64bitisavailable', "{0} for 64-bit Windows is now available! Click [here]({1}) to learn more.", product.nameShort, url), + [{ + label: nls.localize('neveragain', "Don't Show Again"), + isSecondary: true, + run: () => { + neverShowAgain.action.run(); + neverShowAgain.action.dispose(); + } + }] + ); } } @@ -281,7 +227,7 @@ class CommandAction extends Action { export class UpdateContribution implements IGlobalActivity { private static readonly showCommandsId = 'workbench.action.showCommands'; - private static readonly openSettingsId = 'workbench.action.openGlobalSettings'; + private static readonly openSettingsId = 'workbench.action.openSettings'; private static readonly openKeybindingsId = 'workbench.action.openGlobalKeybindings'; private static readonly openUserSnippets = 'workbench.action.openSnippets'; private static readonly selectColorThemeId = 'workbench.action.selectTheme'; @@ -301,7 +247,7 @@ export class UpdateContribution implements IGlobalActivity { @ICommandService private commandService: ICommandService, @IInstantiationService private instantiationService: IInstantiationService, @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService, + @IDialogService private dialogService: IDialogService, @IUpdateService private updateService: IUpdateService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IActivityService private activityService: IActivityService, @@ -375,12 +321,10 @@ export class UpdateContribution implements IGlobalActivity { } private onUpdateNotAvailable(): void { - this.choiceService.choose( + this.dialogService.show( severity.Info, nls.localize('noUpdatesAvailable', "There are currently no updates available."), - [nls.localize('ok', "OK")], - 0, - true + [nls.localize('ok', "OK")] ); } @@ -390,15 +334,24 @@ export class UpdateContribution implements IGlobalActivity { return; } - const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); - const downloadAction = new Action('update.downloadNow', nls.localize('download now', "Download Now"), null, true, () => - this.updateService.downloadUpdate()); - - this.notificationService.notify({ - severity: severity.Info, - message: nls.localize('thereIsUpdateAvailable', "There is an available update."), - actions: { primary: [downloadAction, NotNowAction, releaseNotesAction] } - }); + this.notificationService.prompt( + severity.Info, + nls.localize('thereIsUpdateAvailable', "There is an available update."), + [{ + label: nls.localize('download now', "Download Now"), + run: () => this.updateService.downloadUpdate() + }, { + label: nls.localize('later', "Later"), + run: () => { } + }, { + label: nls.localize('releaseNotes', "Release Notes"), + run: () => { + const action = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + action.run(); + action.dispose(); + } + }] + ); } // windows fast updates @@ -407,15 +360,24 @@ export class UpdateContribution implements IGlobalActivity { return; } - const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); - const installUpdateAction = new Action('update.applyUpdate', nls.localize('installUpdate', "Install Update"), undefined, true, () => - this.updateService.applyUpdate()); - - this.notificationService.notify({ - severity: severity.Info, - message: nls.localize('updateAvailable', "There's an available update: {0} {1}", product.nameLong, update.productVersion), - actions: { primary: [installUpdateAction, NotNowAction, releaseNotesAction] } - }); + this.notificationService.prompt( + severity.Info, + nls.localize('updateAvailable', "There's an update available: {0} {1}", product.nameLong, update.productVersion), + [{ + label: nls.localize('installUpdate', "Install Update"), + run: () => this.updateService.applyUpdate() + }, { + label: nls.localize('later', "Later"), + run: () => { } + }, { + label: nls.localize('releaseNotes', "Release Notes"), + run: () => { + const action = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + action.run(); + action.dispose(); + } + }] + ); } // windows fast updates @@ -426,28 +388,44 @@ export class UpdateContribution implements IGlobalActivity { return; } - this.notificationService.notify({ - severity: severity.Info, - message: nls.localize('updateInstalling', "{0} {1} is being installed in the background, we'll let you know when it's done.", product.nameLong, update.productVersion), - actions: { secondary: [neverShowAgain.action] } - }); + this.notificationService.prompt( + severity.Info, + nls.localize('updateInstalling', "{0} {1} is being installed in the background, we'll let you know when it's done.", product.nameLong, update.productVersion), + [{ + label: nls.localize('neveragain', "Don't Show Again"), + isSecondary: true, + run: () => { + neverShowAgain.action.run(); + neverShowAgain.action.dispose(); + } + }] + ); } // windows and mac private onUpdateReady(update: IUpdate): void { - if (!this.shouldShowNotification()) { + if (!isWindows && !this.shouldShowNotification()) { return; } - const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); - const applyUpdateAction = new Action('update.applyUpdate', nls.localize('updateNow', "Update Now"), undefined, true, () => - this.updateService.quitAndInstall()); - - this.notificationService.notify({ - severity: severity.Info, - message: nls.localize('updateAvailableAfterRestart', "{0} will be updated after it restarts.", product.nameLong), - actions: { primary: [applyUpdateAction, NotNowAction, releaseNotesAction] } - }); + this.notificationService.prompt( + severity.Info, + nls.localize('updateAvailableAfterRestart', "Restart {0} to apply the latest update.", product.nameLong), + [{ + label: nls.localize('updateNow', "Update Now"), + run: () => this.updateService.quitAndInstall() + }, { + label: nls.localize('later', "Later"), + run: () => { } + }, { + label: nls.localize('releaseNotes', "Release Notes"), + run: () => { + const action = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + action.run(); + action.dispose(); + } + }] + ); } private shouldShowNotification(): boolean { diff --git a/src/vs/workbench/parts/url/electron-browser/url.contribution.ts b/src/vs/workbench/parts/url/electron-browser/url.contribution.ts new file mode 100644 index 0000000000..221289f355 --- /dev/null +++ b/src/vs/workbench/parts/url/electron-browser/url.contribution.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; +import { IURLService } from 'vs/platform/url/common/url'; +import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Action } from 'vs/base/common/actions'; + +export class OpenUrlAction extends Action { + + static readonly ID = 'workbench.action.url.openUrl'; + static readonly LABEL = localize('openUrl', "Open URL"); + + constructor( + id: string, + label: string, + @IURLService private urlService: IURLService, + @IQuickOpenService private quickOpenService: IQuickOpenService, + ) { + super(id, label); + } + + async run(): TPromise { + const input = await this.quickOpenService.input({ prompt: 'URL to open' }); + const uri = URI.parse(input); + + this.urlService.open(uri); + } +} + +Registry.as(ActionExtensions.WorkbenchActions) + .registerWorkbenchAction(new SyncActionDescriptor(OpenUrlAction, OpenUrlAction.ID, OpenUrlAction.LABEL), 'OpenUrl', localize('developer', "Developer")); \ No newline at end of file diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 3b589e8c42..a0227568d1 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -21,7 +21,7 @@ import { OpenRecentAction } from 'vs/workbench/electron-browser/actions'; import { GlobalNewUntitledFileAction } from 'vs/workbench/parts/files/electron-browser/fileActions'; import { OpenFolderAction, OpenFileFolderAction, OpenFileAction } from 'vs/workbench/browser/actions/workspaceActions'; import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler'; -import { Parts, IPartService, Dimension } from 'vs/workbench/services/part/common/partService'; +import { Parts, IPartService, IDimension } from 'vs/workbench/services/part/common/partService'; import { StartAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { FindInFilesActionId } from 'vs/workbench/parts/search/common/constants'; import { ToggleTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; @@ -195,7 +195,7 @@ export class WatermarkContribution implements IWorkbenchContribution { update(); this.watermark.build(container.firstElementChild as HTMLElement, 0); this.toDispose.push(this.keybindingService.onDidUpdateKeybindings(update)); - this.toDispose.push(this.partService.onEditorLayout(({ height }: Dimension) => { + this.toDispose.push(this.partService.onEditorLayout(({ height }: IDimension) => { container.classList[height <= 478 ? 'add' : 'remove']('max-height-478px'); })); } diff --git a/src/vs/workbench/parts/html/browser/webviewEditor.ts b/src/vs/workbench/parts/webview/electron-browser/baseWebviewEditor.ts similarity index 78% rename from src/vs/workbench/parts/html/browser/webviewEditor.ts rename to src/vs/workbench/parts/webview/electron-browser/baseWebviewEditor.ts index 6abb2e971a..02c4951ffd 100644 --- a/src/vs/workbench/parts/html/browser/webviewEditor.ts +++ b/src/vs/workbench/parts/webview/electron-browser/baseWebviewEditor.ts @@ -3,16 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Dimension } from 'vs/base/browser/dom'; +import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { BaseWebviewEditor } from 'vs/workbench/browser/parts/editor/webviewEditor'; -import { IStorageService } from 'vs/platform/storage/common/storage'; - -import { IContextKey, RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; - -import { Webview } from './webview'; -import { Builder } from 'vs/base/browser/builder'; -import { Dimension } from 'vs/workbench/services/part/common/partService'; +import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; +import { WebviewElement } from './webviewElement'; /** A context key that is set when a webview editor has focus. */ export const KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS = new RawContextKey('webviewEditorFocus', false); @@ -21,14 +17,13 @@ export const KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED = new Ra /** A context key that is set when the find widget in a webview is visible. */ export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE = new RawContextKey('webviewFindWidgetVisible', false); + /** * This class is only intended to be subclassed and not instantiated. */ -export abstract class WebviewEditor extends BaseWebviewEditor { +export abstract class BaseWebviewEditor extends BaseEditor { - protected _webviewFocusContextKey: IContextKey; - protected _webview: Webview; - protected content: HTMLElement; + protected _webview: WebviewElement | undefined; protected contextKey: IContextKey; protected findWidgetVisible: IContextKey; protected findInputFocusContextKey: IContextKey; @@ -37,10 +32,9 @@ export abstract class WebviewEditor extends BaseWebviewEditor { id: string, telemetryService: ITelemetryService, themeService: IThemeService, - storageService: IStorageService, contextKeyService: IContextKeyService, ) { - super(id, telemetryService, themeService, storageService); + super(id, telemetryService, themeService); if (contextKeyService) { this.contextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS.bindTo(contextKeyService); this.findInputFocusContextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED.bindTo(contextKeyService); @@ -95,7 +89,4 @@ export abstract class WebviewEditor extends BaseWebviewEditor { this._webview.focus(); } } - - protected abstract createEditor(parent: Builder): void; } - diff --git a/src/vs/workbench/parts/html/browser/webview-pre.js b/src/vs/workbench/parts/webview/electron-browser/webview-pre.js similarity index 86% rename from src/vs/workbench/parts/html/browser/webview-pre.js rename to src/vs/workbench/parts/webview/electron-browser/webview-pre.js index 529e48cd9a..5166e6e623 100644 --- a/src/vs/workbench/parts/html/browser/webview-pre.js +++ b/src/vs/workbench/parts/webview/electron-browser/webview-pre.js @@ -6,8 +6,30 @@ (function () { 'use strict'; + // @ts-ignore const ipcRenderer = require('electron').ipcRenderer; + + const registerVscodeResourceScheme = (function () { + let hasRegistered = false; + return () => { + if (hasRegistered) { + return; + } + + hasRegistered = true; + + // @ts-ignore + require('electron').webFrame.registerURLSchemeAsPrivileged('vscode-resource', { + secure: true, + bypassCSP: false, + allowServiceWorkers: false, + supportFetchAPI: true, + corsEnabled: true + }); + }; + }()); + // state var firstLoad = true; var loadTimeout; @@ -26,18 +48,12 @@ body.classList.add(initData.activeTheme); } - /** - * @return {HTMLIFrameElement} - */ function getActiveFrame() { - return document.getElementById('active-frame'); + return /** @type {HTMLIFrameElement} */ (document.getElementById('active-frame')); } - /** - * @return {HTMLIFrameElement} - */ function getPendingFrame() { - return document.getElementById('pending-frame'); + return /** @type {HTMLIFrameElement} */ (document.getElementById('pending-frame')); } /** @@ -138,6 +154,10 @@ const options = data.options; enableWrappedPostMessage = options && options.enableWrappedPostMessage; + if (enableWrappedPostMessage) { + registerVscodeResourceScheme(); + } + const text = data.contents; const newDocument = new DOMParser().parseFromString(text, 'text/html'); @@ -154,6 +174,38 @@ newDocument.head.appendChild(baseElement); } + // apply default script + if (enableWrappedPostMessage) { + const defaultScript = newDocument.createElement('script'); + defaultScript.textContent = ` + const acquireVsCodeApi = (function() { + const originalPostMessage = window.parent.postMessage.bind(window.parent); + let acquired = false; + + return () => { + if (acquired) { + throw new Error('An instance of the VS Code API has already been acquired'); + } + acquired = true; + return Object.freeze({ + postMessage: function(msg) { + return originalPostMessage(msg, '*'); + } + }); + }; + })(); + delete window.parent; + delete window.top; + delete window.frameElement; + `; + + if (newDocument.head.hasChildNodes()) { + newDocument.head.insertBefore(defaultScript, newDocument.head.firstChild); + } else { + newDocument.head.appendChild(defaultScript); + } + } + // apply default styles const defaultStyles = newDocument.createElement('style'); defaultStyles.id = '_defaultStyles'; diff --git a/src/vs/workbench/parts/html/browser/webview.contribution.ts b/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts similarity index 50% rename from src/vs/workbench/parts/html/browser/webview.contribution.ts rename to src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts index 66acb47040..591b6df9fe 100644 --- a/src/vs/workbench/parts/html/browser/webview.contribution.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts @@ -3,27 +3,49 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; -import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; -import { ContextKeyExpr, } from 'vs/platform/contextkey/common/contextkey'; -import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; - -import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE } from './webviewEditor'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { localize } from 'vs/nls'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ShowWebViewEditorFindWidgetAction, ShowWebViewEditorFindTermCommand, HideWebViewEditorFindCommand, OpenWebviewDeveloperToolsAction, ReloadWebviewAction } from './webviewCommands'; +import { EditorDescriptor, Extensions as EditorExtensions, IEditorRegistry } from 'vs/workbench/browser/editor'; +import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; +import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { WebviewEditorInputFactory } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory'; +import { KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE } from './baseWebviewEditor'; +import { HideWebViewEditorFindCommand, OpenWebviewDeveloperToolsAction, ReloadWebviewAction, ShowWebViewEditorFindTermCommand, ShowWebViewEditorFindWidgetCommand } from './webviewCommands'; +import { WebviewEditor } from './webviewEditor'; +import { WebviewEditorInput } from './webviewEditorInput'; +import { IWebviewEditorService, WebviewEditorService } from './webviewEditorService'; + +(Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( + WebviewEditor, + WebviewEditor.ID, + localize('webview.editor.label', "webview editor")), + [new SyncDescriptor(WebviewEditorInput)]); + +Registry.as(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory( + WebviewEditorInputFactory.ID, + WebviewEditorInputFactory); + +registerSingleton(IWebviewEditorService, WebviewEditorService); -const category = 'Webview'; -const webviewDeveloperCategory = nls.localize('developer', "Developer"); +const webviewDeveloperCategory = localize('developer', "Developer"); -const actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); +const actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowWebViewEditorFindWidgetAction, ShowWebViewEditorFindWidgetAction.ID, ShowWebViewEditorFindWidgetAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.KEY_F -}, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS), - 'Webview: Focus Find Widget', category); +const showNextFindWdigetCommand = new ShowWebViewEditorFindWidgetCommand({ + id: ShowWebViewEditorFindWidgetCommand.ID, + precondition: KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, + kbOpts: { + primary: KeyMod.CtrlCmd | KeyCode.KEY_F + } +}); +KeybindingsRegistry.registerCommandAndKeybindingRule(showNextFindWdigetCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib())); const showNextFindTermCommand = new ShowWebViewEditorFindTermCommand({ @@ -46,7 +68,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule(showPreviousFindTermCommand const hideCommand = new HideWebViewEditorFindCommand({ - id: 'editor.action.webvieweditor.hideFind', + id: HideWebViewEditorFindCommand.ID, precondition: ContextKeyExpr.and( KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE), diff --git a/src/vs/workbench/parts/html/browser/webview.html b/src/vs/workbench/parts/webview/electron-browser/webview.html similarity index 100% rename from src/vs/workbench/parts/html/browser/webview.html rename to src/vs/workbench/parts/webview/electron-browser/webview.html diff --git a/src/vs/workbench/parts/html/browser/webviewCommands.ts b/src/vs/workbench/parts/webview/electron-browser/webviewCommands.ts similarity index 61% rename from src/vs/workbench/parts/html/browser/webviewCommands.ts rename to src/vs/workbench/parts/webview/electron-browser/webviewCommands.ts index 0ec9e203de..2807378f0b 100644 --- a/src/vs/workbench/parts/html/browser/webviewCommands.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webviewCommands.ts @@ -3,68 +3,45 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; - -import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { Command, ICommandOptions } from 'vs/editor/browser/editorExtensions'; -import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Action } from 'vs/base/common/actions'; import { TPromise } from 'vs/base/common/winjs.base'; -import { WebviewEditor } from './webviewEditor'; +import { Command, ICommandOptions } from 'vs/editor/browser/editorExtensions'; +import * as nls from 'vs/nls'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { BaseWebviewEditor } from './baseWebviewEditor'; -export class ShowWebViewEditorFindWidgetAction extends Action { +export class ShowWebViewEditorFindWidgetCommand extends Command { public static readonly ID = 'editor.action.webvieweditor.showFind'; - public static readonly LABEL = nls.localize('editor.action.webvieweditor.showFind', "Focus Find Widget"); - public constructor( - id: string, - label: string, - @IWorkbenchEditorService private workbenchEditorService: IWorkbenchEditorService - ) { - super(id, label); - } - - public run(): TPromise { - const webViewEditor = this.getWebViewEditor(); + public runCommand(accessor: ServicesAccessor, args: any): void { + const webViewEditor = getActiveWebviewEditor(accessor); if (webViewEditor) { webViewEditor.showFind(); } - return null; - } - - private getWebViewEditor(): WebviewEditor { - const activeEditor = this.workbenchEditorService.getActiveEditor() as WebviewEditor; - if (activeEditor.isWebviewEditor) { - return activeEditor; - } - return null; } } export class HideWebViewEditorFindCommand extends Command { + public static readonly ID = 'editor.action.webvieweditor.hideFind'; + public runCommand(accessor: ServicesAccessor, args: any): void { - const webViewEditor = this.getWebViewEditor(accessor); + const webViewEditor = getActiveWebviewEditor(accessor); if (webViewEditor) { webViewEditor.hideFind(); } } - - private getWebViewEditor(accessor: ServicesAccessor): WebviewEditor { - const activeEditor = accessor.get(IWorkbenchEditorService).getActiveEditor() as WebviewEditor; - if (activeEditor.isWebviewEditor) { - return activeEditor; - } - return null; - } } export class ShowWebViewEditorFindTermCommand extends Command { + public static readonly Id = 'editor.action.webvieweditor.showPreviousFindTerm'; + constructor(opts: ICommandOptions, private _next: boolean) { super(opts); } public runCommand(accessor: ServicesAccessor, args: any): void { - const webViewEditor = this.getWebViewEditor(accessor); + const webViewEditor = getActiveWebviewEditor(accessor); if (webViewEditor) { if (this._next) { webViewEditor.showNextFindTerm(); @@ -73,20 +50,11 @@ export class ShowWebViewEditorFindTermCommand extends Command { } } } - - private getWebViewEditor(accessor: ServicesAccessor): WebviewEditor { - const activeEditor = accessor.get(IWorkbenchEditorService).getActiveEditor() as WebviewEditor; - if (activeEditor.isWebviewEditor) { - return activeEditor; - } - return null; - } } - export class OpenWebviewDeveloperToolsAction extends Action { static readonly ID = 'workbench.action.webview.openDeveloperTools'; - static LABEL = nls.localize('openToolsLabel', "Open Webview Developer Tools"); + static readonly LABEL = nls.localize('openToolsLabel', "Open Webview Developer Tools"); public constructor( id: string, @@ -108,10 +76,9 @@ export class OpenWebviewDeveloperToolsAction extends Action { } } - export class ReloadWebviewAction extends Action { static readonly ID = 'workbench.action.webview.reloadWebviewAction'; - static LABEL = nls.localize('refreshWebviewLabel', "Reload Webviews"); + static readonly LABEL = nls.localize('refreshWebviewLabel', "Reload Webviews"); public constructor( id: string, @@ -130,7 +97,13 @@ export class ReloadWebviewAction extends Action { private getVisibleWebviews() { return this.workbenchEditorService.getVisibleEditors() - .filter(c => c && (c as any).isWebviewEditor) - .map(e => e as WebviewEditor); + .filter(editor => editor && (editor as BaseWebviewEditor).isWebviewEditor) + .map(editor => editor as BaseWebviewEditor); } +} + +function getActiveWebviewEditor(accessor: ServicesAccessor): BaseWebviewEditor | null { + const workbenchEditorService = accessor.get(IWorkbenchEditorService); + const activeEditor = workbenchEditorService.getActiveEditor() as BaseWebviewEditor; + return activeEditor.isWebviewEditor ? activeEditor : null; } \ No newline at end of file diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewEditor.ts b/src/vs/workbench/parts/webview/electron-browser/webviewEditor.ts new file mode 100644 index 0000000000..c22516bca8 --- /dev/null +++ b/src/vs/workbench/parts/webview/electron-browser/webviewEditor.ts @@ -0,0 +1,242 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as DOM from 'vs/base/browser/dom'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { Position } from 'vs/platform/editor/common/editor'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { EditorOptions } from 'vs/workbench/common/editor'; +import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput'; +import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; +import { BaseWebviewEditor, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE } from './baseWebviewEditor'; +import { WebviewElement } from './webviewElement'; + +export class WebviewEditor extends BaseWebviewEditor { + + public static readonly ID = 'WebviewEditor'; + + private editorFrame: HTMLElement; + private content: HTMLElement; + private webviewContent: HTMLElement | undefined; + + private _webviewFocusTracker?: DOM.IFocusTracker; + private _webviewFocusListenerDisposable?: IDisposable; + + private readonly _onDidFocusWebview = new Emitter(); + + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IThemeService themeService: IThemeService, + @IContextKeyService private _contextKeyService: IContextKeyService, + @IPartService private readonly _partService: IPartService, + @IContextViewService private readonly _contextViewService: IContextViewService, + @IEnvironmentService private readonly _environmentService: IEnvironmentService, + @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService + ) { + super(WebviewEditor.ID, telemetryService, themeService, _contextKeyService); + } + + protected createEditor(parent: HTMLElement): void { + this.editorFrame = parent; + this.content = document.createElement('div'); + parent.appendChild(this.content); + } + + private doUpdateContainer() { + const webviewContainer = this.input && (this.input as WebviewEditorInput).container; + if (webviewContainer && webviewContainer.parentElement) { + const frameRect = this.editorFrame.getBoundingClientRect(); + const containerRect = webviewContainer.parentElement.getBoundingClientRect(); + + webviewContainer.style.position = 'absolute'; + webviewContainer.style.top = `${frameRect.top - containerRect.top}px`; + webviewContainer.style.left = `${frameRect.left - containerRect.left}px`; + webviewContainer.style.width = `${frameRect.width}px`; + webviewContainer.style.height = `${frameRect.height}px`; + } + } + + public layout(dimension: DOM.Dimension): void { + if (this._webview) { + this.doUpdateContainer(); + } + super.layout(dimension); + } + + public dispose(): void { + // Let the editor input dispose of the webview. + this._webview = undefined; + this.webviewContent = undefined; + + this._onDidFocusWebview.dispose(); + + if (this._webviewFocusTracker) { + this._webviewFocusTracker.dispose(); + } + + if (this._webviewFocusListenerDisposable) { + this._webviewFocusListenerDisposable.dispose(); + } + + super.dispose(); + } + + public sendMessage(data: any): void { + if (this._webview) { + this._webview.sendMessage(data); + } + } + + public get onDidFocus(): Event { + return this._onDidFocusWebview.event; + } + + protected setEditorVisible(visible: boolean, position?: Position): void { + if (this.input && this.input instanceof WebviewEditorInput) { + if (visible) { + this.input.claimWebview(this); + } else { + this.input.releaseWebview(this); + } + + this.updateWebview(this.input as WebviewEditorInput); + } + + if (this.webviewContent) { + if (visible) { + this.webviewContent.style.visibility = 'visible'; + this.doUpdateContainer(); + } else { + this.webviewContent.style.visibility = 'hidden'; + } + } + + super.setEditorVisible(visible, position); + } + + public clearInput() { + if (this.input && this.input instanceof WebviewEditorInput) { + this.input.releaseWebview(this); + } + + this._webview = undefined; + this.webviewContent = undefined; + + super.clearInput(); + } + + async setInput(input: WebviewEditorInput, options: EditorOptions): TPromise { + if (this.input && this.input.matches(input)) { + return undefined; + } + + if (this.input) { + (this.input as WebviewEditorInput).releaseWebview(this); + this._webview = undefined; + this.webviewContent = undefined; + } + await super.setInput(input, options); + + await input.resolve(); + await input.updatePosition(this.position); + this.updateWebview(input); + } + + private updateWebview(input: WebviewEditorInput) { + const webview = this.getWebview(input); + input.claimWebview(this); + webview.options = { + allowScripts: input.options.enableScripts, + allowSvgs: true, + enableWrappedPostMessage: true, + useSameOriginForRoot: false, + localResourceRoots: input.options.localResourceRoots || this.getDefaultLocalResourceRoots() + }; + input.html = input.html; + + if (this.webviewContent) { + this.webviewContent.style.visibility = 'visible'; + } + + this.doUpdateContainer(); + } + + private getDefaultLocalResourceRoots(): URI[] { + const rootPaths = this._contextService.getWorkspace().folders.map(x => x.uri); + if ((this.input as WebviewEditorInput).extensionFolderPath) { + rootPaths.push((this.input as WebviewEditorInput).extensionFolderPath); + } + return rootPaths; + } + + private getWebview(input: WebviewEditorInput): WebviewElement { + if (this._webview) { + return this._webview; + } + + this.webviewContent = input.container; + + this.trackFocus(); + + const existing = input.webview; + if (existing) { + this._webview = existing; + return existing; + } + + if (input.options.enableFindWidget) { + this._contextKeyService = this._contextKeyService.createScoped(this.webviewContent); + this.contextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS.bindTo(this._contextKeyService); + this.findInputFocusContextKey = KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED.bindTo(this._contextKeyService); + this.findWidgetVisible = KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE.bindTo(this._contextKeyService); + } + + this._webview = new WebviewElement( + this._partService.getContainer(Parts.EDITOR_PART), + this.themeService, + this._environmentService, + this._contextViewService, + this.contextKey, + this.findInputFocusContextKey, + { + enableWrappedPostMessage: true, + useSameOriginForRoot: false + }); + this._webview.mountTo(this.webviewContent); + input.webview = this._webview; + + if (input.options.tryRestoreScrollPosition) { + this._webview.initialScrollProgress = input.scrollYPercentage; + } + + this.content.setAttribute('aria-flowto', this.webviewContent.id); + + this.doUpdateContainer(); + return this._webview; + } + + private trackFocus() { + if (this._webviewFocusTracker) { + this._webviewFocusTracker.dispose(); + } + if (this._webviewFocusListenerDisposable) { + this._webviewFocusListenerDisposable.dispose(); + } + + this._webviewFocusTracker = DOM.trackFocus(this.webviewContent); + this._webviewFocusListenerDisposable = this._webviewFocusTracker.onDidFocus(() => { + this._onDidFocusWebview.fire(); + }); + } +} + diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewEditorInput.ts b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInput.ts new file mode 100644 index 0000000000..a8de52c4f1 --- /dev/null +++ b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInput.ts @@ -0,0 +1,230 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IEditorInput, IEditorModel, Position } from 'vs/platform/editor/common/editor'; +import { EditorInput, EditorModel } from 'vs/workbench/common/editor'; +import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; +import { WebviewEvents, WebviewInputOptions, WebviewReviver } from './webviewEditorService'; +import { WebviewElement } from './webviewElement'; + + +export class WebviewEditorInput extends EditorInput { + private static handlePool = 0; + + public static readonly typeId = 'workbench.editors.webviewInput'; + + private _name: string; + private _options: WebviewInputOptions; + private _html: string = ''; + private _currentWebviewHtml: string = ''; + public _events: WebviewEvents | undefined; + private _container: HTMLElement; + private _webview: WebviewElement | undefined; + private _webviewOwner: any; + private _webviewDisposables: IDisposable[] = []; + private _position?: Position; + private _scrollYPercentage: number = 0; + private _state: any; + + private _revived: boolean = false; + + public readonly extensionFolderPath: URI | undefined; + + constructor( + public readonly viewType: string, + name: string, + options: WebviewInputOptions, + state: any, + events: WebviewEvents, + extensionFolderPath: string | undefined, + public readonly reviver: WebviewReviver | undefined, + @IPartService private readonly _partService: IPartService, + ) { + super(); + this._name = name; + this._options = options; + this._events = events; + this._state = state; + + if (extensionFolderPath) { + this.extensionFolderPath = URI.file(extensionFolderPath); + } + } + + public getTypeId(): string { + return WebviewEditorInput.typeId; + } + + public dispose() { + this.disposeWebview(); + + if (this._container) { + this._container.remove(); + this._container = undefined; + } + + if (this._events) { + this._events.onDispose(); + this._events = undefined; + } + + super.dispose(); + } + + public getResource(): URI { + return null; + } + + public getName(): string { + return this._name; + } + + public getTitle() { + return this.getName(); + } + + public getDescription(): string { + return null; + } + + public setName(value: string): void { + this._name = value; + this._onDidChangeLabel.fire(); + } + + matches(other: IEditorInput): boolean { + return other && other === this; + } + + public get position(): Position | undefined { + return this._position; + } + + public get html(): string { + return this._html; + } + + public set html(value: string) { + if (value === this._currentWebviewHtml) { + return; + } + + this._html = value; + + if (this._webview) { + this._webview.contents = value; + this._currentWebviewHtml = value; + } + } + + public get state(): any { + return this._state; + } + + public set state(value: any) { + this._state = value; + } + + public get options(): WebviewInputOptions { + return this._options; + } + + public set options(value: WebviewInputOptions) { + this._options = value; + } + + public resolve(refresh?: boolean): TPromise { + if (this.reviver && !this._revived) { + this._revived = true; + return this.reviver.reviveWebview(this).then(() => new EditorModel()); + } + + return TPromise.as(new EditorModel()); + } + + public supportsSplitEditor() { + return false; + } + + public get container(): HTMLElement { + if (!this._container) { + const id = WebviewEditorInput.handlePool++; + this._container = document.createElement('div'); + this._container.id = `webview-${id}`; + this._partService.getContainer(Parts.EDITOR_PART).appendChild(this._container); + } + return this._container; + } + + public get webview(): WebviewElement | undefined { + return this._webview; + } + + public set webview(value: WebviewElement) { + this._webviewDisposables = dispose(this._webviewDisposables); + + this._webview = value; + + this._webview.onDidClickLink(link => { + if (this._events && this._events.onDidClickLink) { + this._events.onDidClickLink(link, this._options); + } + }, null, this._webviewDisposables); + + this._webview.onMessage(message => { + if (this._events && this._events.onMessage) { + this._events.onMessage(message); + } + }, null, this._webviewDisposables); + + this._webview.onDidScroll(message => { + this._scrollYPercentage = message.scrollYPercentage; + }, null, this._webviewDisposables); + } + + public get scrollYPercentage() { + return this._scrollYPercentage; + } + + public claimWebview(owner: any) { + this._webviewOwner = owner; + } + + public releaseWebview(owner: any) { + if (this._webviewOwner === owner) { + this._webviewOwner = undefined; + if (this._options.retainContextWhenHidden && this._container) { + this._container.style.visibility = 'hidden'; + } else { + this.disposeWebview(); + } + } + } + + public disposeWebview() { + // The input owns the webview and its parent + if (this._webview) { + this._webview.dispose(); + this._webview = undefined; + } + + this._webviewDisposables = dispose(this._webviewDisposables); + + this._webviewOwner = undefined; + + if (this._container) { + this._container.style.visibility = 'hidden'; + } + + this._currentWebviewHtml = ''; + } + + public updatePosition(position: Position): void { + this._position = position; + } +} diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts new file mode 100644 index 0000000000..23285a18d9 --- /dev/null +++ b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts @@ -0,0 +1,57 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IEditorInputFactory } from 'vs/workbench/common/editor'; +import { WebviewEditorInput } from './webviewEditorInput'; +import { IWebviewEditorService, WebviewInputOptions } from './webviewEditorService'; + +interface SerializedWebview { + readonly viewType: string; + readonly title: string; + readonly options: WebviewInputOptions; + readonly extensionFolderPath: string; + readonly state: any; +} + +export class WebviewEditorInputFactory implements IEditorInputFactory { + + public static readonly ID = WebviewEditorInput.typeId; + + public constructor( + @IWebviewEditorService private readonly _webviewService: IWebviewEditorService + ) { } + + public serialize( + input: WebviewEditorInput + ): string { + // Has no state, don't revive + if (!input.state) { + return null; + } + + // Only attempt revival if we may have a reviver + if (!this._webviewService.canRevive(input) && !input.reviver) { + return null; + } + + const data: SerializedWebview = { + viewType: input.viewType, + title: input.getName(), + options: input.options, + extensionFolderPath: input.extensionFolderPath.fsPath, + state: input.state + }; + return JSON.stringify(data); + } + + public deserialize( + instantiationService: IInstantiationService, + serializedEditorInput: string + ): WebviewEditorInput { + const data: SerializedWebview = JSON.parse(serializedEditorInput); + return this._webviewService.reviveWebview(data.viewType, data.title, data.state, data.options, data.extensionFolderPath); + } +} diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewEditorService.ts b/src/vs/workbench/parts/webview/electron-browser/webviewEditorService.ts new file mode 100644 index 0000000000..d9ee615939 --- /dev/null +++ b/src/vs/workbench/parts/webview/electron-browser/webviewEditorService.ts @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Position } from 'vs/platform/editor/common/editor'; +import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; +import * as vscode from 'vscode'; +import { WebviewEditorInput } from './webviewEditorInput'; + +export const IWebviewEditorService = createDecorator('webviewEditorService'); + +export interface IWebviewEditorService { + _serviceBrand: any; + + createWebview( + viewType: string, + title: string, + column: Position, + options: WebviewInputOptions, + extensionFolderPath: string, + events: WebviewEvents + ): WebviewEditorInput; + + reviveWebview( + viewType: string, + title: string, + state: any, + options: WebviewInputOptions, + extensionFolderPath: string + ): WebviewEditorInput; + + revealWebview( + webview: WebviewEditorInput, + column: Position | null + ): void; + + registerReviver( + viewType: string, + reviver: WebviewReviver + ): IDisposable; + + canRevive( + input: WebviewEditorInput + ): boolean; +} + +export interface WebviewReviver { + canRevive( + webview: WebviewEditorInput + ): boolean; + + reviveWebview( + webview: WebviewEditorInput + ): TPromise; +} + +export interface WebviewEvents { + onMessage?(message: any): void; + onDidChangePosition?(newPosition: Position): void; + onDispose?(): void; + onDidClickLink?(link: URI, options: vscode.WebviewOptions): void; +} + +export interface WebviewInputOptions extends vscode.WebviewOptions, vscode.WebviewPanelOptions { + tryRestoreScrollPosition?: boolean; +} + +export class WebviewEditorService implements IWebviewEditorService { + _serviceBrand: any; + + private readonly _revivers = new Map(); + private _awaitingRevival: { input: WebviewEditorInput, resolve: (x: any) => void }[] = []; + + constructor( + @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IEditorGroupService private readonly _editorGroupService: IEditorGroupService, + ) { } + + createWebview( + viewType: string, + title: string, + column: Position, + options: vscode.WebviewOptions, + extensionFolderPath: string, + events: WebviewEvents + ): WebviewEditorInput { + const webviewInput = this._instantiationService.createInstance(WebviewEditorInput, viewType, title, options, {}, events, extensionFolderPath, undefined); + this._editorService.openEditor(webviewInput, { pinned: true }, column); + return webviewInput; + } + + revealWebview( + webview: WebviewEditorInput, + column: Position | null + ): void { + if (!column || webview.position === column) { + this._editorService.openEditor(webview, { preserveFocus: false }, column || webview.position); + } else { + this._editorGroupService.moveEditor(webview, webview.position, column, { preserveFocus: false }); + } + } + + reviveWebview( + viewType: string, + title: string, + state: any, + options: WebviewInputOptions, + extensionFolderPath: string + ): WebviewEditorInput { + const webviewInput = this._instantiationService.createInstance(WebviewEditorInput, viewType, title, options, state, {}, extensionFolderPath, { + canRevive: (webview) => { + return true; + }, + reviveWebview: async (webview: WebviewEditorInput): TPromise => { + const didRevive = await this.tryRevive(webview); + if (didRevive) { + return; + } + // A reviver may not be registered yet. Put into queue and resolve promise when we can revive + let resolve: (value: void) => void; + const promise = new TPromise(r => { resolve = r; }); + this._awaitingRevival.push({ input: webview, resolve }); + return promise; + } + }); + + return webviewInput; + } + + registerReviver( + viewType: string, + reviver: WebviewReviver + ): IDisposable { + if (this._revivers.has(viewType)) { + throw new Error(`Reviver for '${viewType}' already registered`); + } + + this._revivers.set(viewType, reviver); + + // Resolve any pending views + const toRevive = this._awaitingRevival.filter(x => x.input.viewType === viewType); + this._awaitingRevival = this._awaitingRevival.filter(x => x.input.viewType !== viewType); + + for (const input of toRevive) { + reviver.reviveWebview(input.input).then(() => input.resolve(void 0)); + } + + return toDisposable(() => { + this._revivers.delete(viewType); + }); + } + + canRevive( + webview: WebviewEditorInput + ): boolean { + const viewType = webview.viewType; + return this._revivers.has(viewType) && this._revivers.get(viewType).canRevive(webview); + } + + private async tryRevive( + webview: WebviewEditorInput + ): TPromise { + const reviver = this._revivers.get(webview.viewType); + if (!reviver) { + return false; + } + + await reviver.reviveWebview(webview); + return true; + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts similarity index 91% rename from src/vs/workbench/parts/html/browser/webview.ts rename to src/vs/workbench/parts/webview/electron-browser/webviewElement.ts index 6b1d0a79bc..e4304876ef 100644 --- a/src/vs/workbench/parts/html/browser/webview.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts @@ -3,20 +3,18 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import URI from 'vs/base/common/uri'; +import { addClass, addDisposableListener } from 'vs/base/browser/dom'; +import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; -import { addDisposableListener, addClass } from 'vs/base/browser/dom'; -import { editorBackground, editorForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; -import { ITheme, LIGHT, DARK, IThemeService } from 'vs/platform/theme/common/themeService'; -import { WebviewFindWidget } from './webviewFindWidget'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { nativeSep } from 'vs/base/common/paths'; import { startsWith } from 'vs/base/common/strings'; +import URI from 'vs/base/common/uri'; +import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { editorBackground, editorForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; +import { DARK, ITheme, IThemeService, LIGHT } from 'vs/platform/theme/common/themeService'; +import { WebviewFindWidget } from './webviewFindWidget'; export interface WebviewOptions { readonly allowScripts?: boolean; @@ -24,10 +22,10 @@ export interface WebviewOptions { readonly svgWhiteList?: string[]; readonly enableWrappedPostMessage?: boolean; readonly useSameOriginForRoot?: boolean; - readonly localResourceRoots?: URI[]; + readonly localResourceRoots?: ReadonlyArray; } -export class Webview { +export class WebviewElement { private readonly _webview: Electron.WebviewTag; private _ready: Promise; private _disposables: IDisposable[] = []; @@ -37,7 +35,6 @@ export class Webview { private _contents: string = ''; constructor( - private readonly parent: HTMLElement, private readonly _styleElement: Element, private readonly _themeService: IThemeService, private readonly _environmentService: IEnvironmentService, @@ -180,11 +177,11 @@ export class Webview { this.style(this._themeService.getTheme()); this._themeService.onThemeChange(this.style, this, this._disposables); + } - if (parent) { - parent.appendChild(this._webviewFindWidget.getDomNode()); - parent.appendChild(this._webview); - } + public mountTo(parent: HTMLElement) { + parent.appendChild(this._webviewFindWidget.getDomNode()); + parent.appendChild(this._webview); } public notifyFindWidgetFocusChanged(isFocused: boolean) { @@ -205,9 +202,9 @@ export class Webview { if (this._webview.parentElement) { this._webview.parentElement.removeChild(this._webview); - const findWidgetDomNode = this._webviewFindWidget.getDomNode(); - findWidgetDomNode.parentElement.removeChild(findWidgetDomNode); } + + this._webviewFindWidget.dispose(); } private readonly _onDidClickLink = new Emitter(); @@ -294,9 +291,12 @@ export class Webview { } contents.setZoomFactor(factor); + if (!this._webview || !this._webview.parentElement) { + return; + } - const width = this.parent.clientWidth; - const height = this.parent.clientHeight; + const width = this._webview.parentElement.clientWidth; + const height = this._webview.parentElement.clientHeight; contents.setSize({ normal: { width: Math.floor(width * factor), @@ -327,17 +327,7 @@ export class Webview { appRootUri ]); - const extensionPaths = [ - URI.file(this._environmentService.extensionsPath), - appRootUri, - ]; - - if (this._environmentService.extensionDevelopmentPath) { - extensionPaths.push(URI.file(this._environmentService.extensionDevelopmentPath)); - } - registerFileProtocol(contents, 'vscode-extension-resource', () => extensionPaths); - - registerFileProtocol(contents, 'vscode-workspace-resource', () => + registerFileProtocol(contents, 'vscode-resource', () => (this._options.localResourceRoots || []) ); } @@ -432,7 +422,7 @@ namespace ApiThemeClassName { function registerFileProtocol( contents: Electron.WebContents, protocol: string, - getRoots: () => URI[] + getRoots: () => ReadonlyArray ) { contents.session.protocol.registerFileProtocol(protocol, (request, callback: any) => { const requestPath = URI.parse(request.url).path; @@ -442,9 +432,9 @@ function registerFileProtocol( callback({ path: normalizedPath }); return; } - } - callback({ error: 'Cannot load resource outside of protocol root' }); + console.error('Webview: Cannot load resource outside of protocol root'); + callback({ error: -10 /* ACCESS_DENIED: https://cs.chromium.org/chromium/src/net/base/net_error_list.h */ }); }, (error) => { if (error) { console.error('Failed to register protocol ' + protocol); diff --git a/src/vs/workbench/parts/html/browser/webviewFindWidget.ts b/src/vs/workbench/parts/webview/electron-browser/webviewFindWidget.ts similarity index 93% rename from src/vs/workbench/parts/html/browser/webviewFindWidget.ts rename to src/vs/workbench/parts/webview/electron-browser/webviewFindWidget.ts index ed17a23c4f..6223be7a32 100644 --- a/src/vs/workbench/parts/html/browser/webviewFindWidget.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webviewFindWidget.ts @@ -5,13 +5,13 @@ import { SimpleFindWidget } from 'vs/editor/contrib/find/simpleFindWidget'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { Webview } from './webview'; +import { WebviewElement } from './webviewElement'; export class WebviewFindWidget extends SimpleFindWidget { constructor( @IContextViewService contextViewService: IContextViewService, - private readonly webview: Webview + private readonly webview: WebviewElement ) { super(contextViewService); } diff --git a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts index ab0d42f4e7..fcf2632b54 100644 --- a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts @@ -15,6 +15,10 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; // .as(WorkbenchExtensions.Workbench) // .registerWorkbenchContribution(GettingStarted, LifecyclePhase.Running); +Registry + .as(WorkbenchExtensions.Workbench) + .registerWorkbenchContribution(GettingStarted, LifecyclePhase.Running); + Registry .as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(TelemetryOptOut, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.ts b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.ts index dd4e8c66d4..cae96133ad 100644 --- a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.ts +++ b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.ts @@ -25,11 +25,20 @@ export class GettingStarted implements IWorkbenchContribution { ) { this.appName = product.nameLong; - /* do not open a browser when we run an extension or --skip-getting-started is provided */ - if (product.welcomePage && !environmentService.isExtensionDevelopment && !environmentService.skipGettingStarted) { - this.welcomePageURL = product.welcomePage; - this.handleWelcome(); + if (!product.welcomePage) { + return; } + + if (environmentService.skipGettingStarted) { + return; + } + + if (environmentService.isExtensionDevelopment) { + return; + } + + this.welcomePageURL = product.welcomePage; + this.handleWelcome(); } private getUrl(telemetryInfo: ITelemetryInfo): string { diff --git a/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.css b/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.css index 1300605c96..88bfc02238 100644 --- a/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.css +++ b/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.css @@ -97,8 +97,16 @@ left: 45px; } +.monaco-workbench > .welcomeOverlay > .key.notifications { + position: absolute; + bottom: 25px; + right: 16px; +} + .monaco-workbench > .welcomeOverlay > .key.problems > .label, -.monaco-workbench > .welcomeOverlay > .key.problems > .shortcut { +.monaco-workbench > .welcomeOverlay > .key.problems > .shortcut, +.monaco-workbench > .welcomeOverlay > .key.notifications > .label, +.monaco-workbench > .welcomeOverlay > .key.notifications > .shortcut { vertical-align: super; } diff --git a/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.ts b/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.ts index ea1c1ce69a..1b04012d79 100644 --- a/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.ts +++ b/src/vs/workbench/parts/welcome/overlay/browser/welcomeOverlay.ts @@ -91,6 +91,13 @@ const keys: Key[] = [ label: localize('welcomeOverlay.commandPalette', "Find and run all commands"), command: ShowAllCommandsAction.ID }, + { + id: 'notifications', + arrow: '⤵', + arrowLast: true, + label: localize('welcomeOverlay.notifications', "Show notifications"), + command: 'notifications.showList' + } ]; const OVERLAY_VISIBLE = new RawContextKey('interfaceOverviewVisible', false); diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts index 649485981f..01bd686d30 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts @@ -47,7 +47,7 @@ export default () => ` -

    +

    @@ -57,7 +57,7 @@ export default () => ` .replace('{0}', ``) .replace('{1}', `${escape(localize('welcomePage.moreExtensions', "more"))}`)} -
  1. diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css index 3e653236c3..17c61559b7 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css @@ -22,10 +22,19 @@ flex-flow: row; } -.monaco-workbench > .part.editor > .content .welcomePage .row * { - min-width: 0; - white-space: nowrap; - text-overflow: ellipsis; +.monaco-workbench > .part.editor > .content .welcomePage .row .section { + overflow: hidden; +} + +.monaco-workbench > .part.editor > .content .welcomePage .row .splash { + overflow: hidden; +} + +.monaco-workbench > .part.editor > .content .welcomePage .row .commands { + overflow: hidden; +} + +.monaco-workbench > .part.editor > .content .welcomePage .row .commands ul { overflow: hidden; } @@ -95,6 +104,13 @@ padding: 0; } +.monaco-workbench > .part.editor > .content .welcomePage .splash li { + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .monaco-workbench > .part.editor > .content .welcomePage.emptyRecent .splash .recent .list { display: none; } @@ -109,22 +125,19 @@ margin-top: 5px; } -.monaco-workbench > .part.editor > .content .welcomePage .splash .recent li { - min-width: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} .monaco-workbench > .part.editor > .content .welcomePage .splash .recent .path { padding-left: 1em; } .monaco-workbench > .part.editor > .content .welcomePage .splash .title, .monaco-workbench > .part.editor > .content .welcomePage .splash .showOnStartup { + min-width: 0; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } -.monaco-workbench > .part.editor > .content .welcomePage .splash .showOnStartup input[type=checkbox] { +.monaco-workbench > .part.editor > .content .welcomePage .splash .showOnStartup > .checkbox { vertical-align: bottom; } @@ -150,6 +163,10 @@ .monaco-workbench > .part.editor > .content .welcomePage .commands li button > span { display: inline-block; width:100%; + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .monaco-workbench > .part.editor > .content .welcomePage .commands li button h3 { @@ -157,6 +174,10 @@ font-size: 1em; margin: 0; margin-bottom: .25em; + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .monaco-workbench > .part.editor > .content .welcomePage .commands li button { diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index 0dc068486d..a01f71ea8a 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -39,7 +39,6 @@ import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifi import { IEditorInputFactory, EditorInput } from 'vs/workbench/common/editor'; import { getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; used(); @@ -227,7 +226,6 @@ class WelcomePage { @IConfigurationService private configurationService: IConfigurationService, @IEnvironmentService private environmentService: IEnvironmentService, @INotificationService private notificationService: INotificationService, - @IChoiceService private choiceService: IChoiceService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService, @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @@ -416,31 +414,32 @@ class WelcomePage { this.notificationService.info(strings.alreadyInstalled.replace('{0}', extensionSuggestion.name)); return; } - const foundAndInstalled = installedExtension ? TPromise.as(installedExtension.identifier) : this.extensionGalleryService.query({ names: [extensionSuggestion.id], source: telemetryFrom }) + const foundAndInstalled = installedExtension ? TPromise.as(installedExtension.local) : this.extensionGalleryService.query({ names: [extensionSuggestion.id], source: telemetryFrom }) .then(result => { const [extension] = result.firstPage; if (!extension) { return null; } return this.extensionManagementService.installFromGallery(extension) - .then(() => { + .then(local => { // TODO: Do this as part of the install to avoid multiple events. - return this.extensionEnablementService.setEnablement(extension.identifier, EnablementState.Disabled); - }).then(() => { - return extension.identifier; + return this.extensionEnablementService.setEnablement(local, EnablementState.Disabled).then(() => local); }); }); - this.choiceService.choose(Severity.Info, strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name), [localize('ok', "OK"), localize('details', "Details")]).then(choice => { - switch (choice) { - case 0 /* OK */: + this.notificationService.prompt( + Severity.Info, + strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name), + [{ + label: localize('ok', "OK"), + run: () => { const messageDelay = TPromise.timeout(300); messageDelay.then(() => { this.notificationService.info(strings.installing.replace('{0}', extensionSuggestion.name)); }); TPromise.join(extensionSuggestion.isKeymap ? extensions.filter(extension => isKeymapExtension(this.tipsService, extension) && extension.globallyEnabled) .map(extension => { - return this.extensionEnablementService.setEnablement(extension.identifier, EnablementState.Disabled); + return this.extensionEnablementService.setEnablement(extension.local, EnablementState.Disabled); }) : []).then(() => { return foundAndInstalled.then(foundExtension => { messageDelay.cancel(); @@ -495,8 +494,10 @@ class WelcomePage { }); this.notificationService.error(err); }); - break; - case 1 /* Details */: + } + }, { + label: localize('details', "Details"), + run: () => { /* __GDPR__FRAGMENT__ "WelcomePageDetails-1" : { "from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, @@ -510,9 +511,9 @@ class WelcomePage { this.extensionsWorkbenchService.queryGallery({ names: [extensionSuggestion.id] }) .then(result => this.extensionsWorkbenchService.open(result.firstPage[0])) .then(null, onUnexpectedError); - break; - } - }); + } + }] + ); }).then(null, err => { /* __GDPR__FRAGMENT__ "WelcomePageInstalled-6" : { diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/editor/vs_code_editor_walkthrough.md b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/editor/vs_code_editor_walkthrough.md index 946f83b6af..d58daa2668 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/editor/vs_code_editor_walkthrough.md +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/editor/vs_code_editor_walkthrough.md @@ -161,7 +161,7 @@ You can greatly accelerate your editing through the use of snippets. Simply sta ### Emmet -Emmet takes the snippets idea to a whole new level: you can type CSS-like expressions that can be dynamically parsed, and produce output depending on what you type in the abbreviation. To use Emmet simply run the command `Emmet: Expand Abbreviation` with the cursor at the end of a valid Emmet abbreviation or snippet and the expansion will occur. +Emmet takes the snippets idea to a whole new level: you can type CSS-like expressions that can be dynamically parsed, and produce output depending on what you type in the abbreviation. Try it by selecting `Emmet: Expand Abbreviation` from the `Edit` menu with the cursor at the end of a valid Emmet abbreviation or snippet and the expansion will occur. ```html ul>li.item$*5 diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution.ts b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution.ts index 3b05b822df..d609c5db92 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution.ts @@ -28,12 +28,12 @@ Registry.as(EditorExtensions.Editors) WalkThroughPart.ID, localize('walkThrough.editor.label', "Interactive Playground"), ), - [new SyncDescriptor(WalkThroughInput)]); + [new SyncDescriptor(WalkThroughInput)]); Registry.as(Extensions.WorkbenchActions) .registerWorkbenchAction( - new SyncActionDescriptor(EditorWalkThroughAction, EditorWalkThroughAction.ID, EditorWalkThroughAction.LABEL), - 'Help: Interactive Playground', localize('help', "Help")); + new SyncActionDescriptor(EditorWalkThroughAction, EditorWalkThroughAction.ID, EditorWalkThroughAction.LABEL), + 'Help: Interactive Playground', localize('help', "Help")); Registry.as(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(EditorWalkThroughInputFactory.ID, EditorWalkThroughInputFactory); @@ -44,13 +44,13 @@ Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(WalkThroughSnippetContentProvider, LifecyclePhase.Starting); Registry.as(Extensions.WorkbenchActions) - .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughArrowUpAction, WalkThroughArrowUpAction.ID, WalkThroughArrowUpAction.LABEL, { primary: KeyCode.UpArrow }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.textFocus.toNegated())), 'Interactive Playground: Scroll Up (Line)', localize('interactivePlayground', "Interactive Playground")); + .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughArrowUpAction, WalkThroughArrowUpAction.ID, WalkThroughArrowUpAction.LABEL, { primary: KeyCode.UpArrow }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.editorTextFocus.toNegated())), 'Interactive Playground: Scroll Up (Line)', localize('interactivePlayground', "Interactive Playground")); Registry.as(Extensions.WorkbenchActions) - .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughArrowDownAction, WalkThroughArrowDownAction.ID, WalkThroughArrowDownAction.LABEL, { primary: KeyCode.DownArrow }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.textFocus.toNegated())), 'Interactive Playground: Scroll Down (Line)', localize('interactivePlayground', "Interactive Playground")); + .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughArrowDownAction, WalkThroughArrowDownAction.ID, WalkThroughArrowDownAction.LABEL, { primary: KeyCode.DownArrow }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.editorTextFocus.toNegated())), 'Interactive Playground: Scroll Down (Line)', localize('interactivePlayground', "Interactive Playground")); Registry.as(Extensions.WorkbenchActions) - .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughPageUpAction, WalkThroughPageUpAction.ID, WalkThroughPageUpAction.LABEL, { primary: KeyCode.PageUp }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.textFocus.toNegated())), 'Interactive Playground: Scroll Up (Page)', localize('interactivePlayground', "Interactive Playground")); + .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughPageUpAction, WalkThroughPageUpAction.ID, WalkThroughPageUpAction.LABEL, { primary: KeyCode.PageUp }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.editorTextFocus.toNegated())), 'Interactive Playground: Scroll Up (Page)', localize('interactivePlayground', "Interactive Playground")); Registry.as(Extensions.WorkbenchActions) - .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughPageDownAction, WalkThroughPageDownAction.ID, WalkThroughPageDownAction.LABEL, { primary: KeyCode.PageDown }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.textFocus.toNegated())), 'Interactive Playground: Scroll Down (Page)', localize('interactivePlayground', "Interactive Playground")); + .registerWorkbenchAction(new SyncActionDescriptor(WalkThroughPageDownAction, WalkThroughPageDownAction.ID, WalkThroughPageDownAction.LABEL, { primary: KeyCode.PageDown }, ContextKeyExpr.and(WALK_THROUGH_FOCUS, EditorContextKeys.editorTextFocus.toNegated())), 'Interactive Playground: Scroll Down (Page)', localize('interactivePlayground', "Interactive Playground")); diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.css b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.css index 1b8e588c30..b110f0c590 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.css +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.css @@ -8,7 +8,6 @@ padding: 10px 20px; line-height: 22px; user-select: initial; - -webkit-user-select: initial; } .monaco-workbench > .part.editor > .content .walkThroughContent img { diff --git a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts index 57d7eace53..4062de3b7c 100644 --- a/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts +++ b/src/vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts @@ -11,9 +11,8 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { $, Dimension, Builder } from 'vs/base/browser/builder'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { EditorOptions } from 'vs/workbench/common/editor'; +import { EditorOptions, EditorViewStateMemento } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { WalkThroughInput } from 'vs/workbench/parts/welcome/walkThrough/node/walkThroughInput'; @@ -40,6 +39,7 @@ import { UILabelProvider } from 'vs/base/common/keybindingLabels'; import { OS, OperatingSystem } from 'vs/base/common/platform'; import { deepClone } from 'vs/base/common/objects'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { Dimension, size } from 'vs/base/browser/dom'; export const WALK_THROUGH_FOCUS = new RawContextKey('interactivePlaygroundFocus', false); @@ -55,12 +55,6 @@ interface IWalkThroughEditorViewState { viewState: IViewState; } -interface IWalkThroughEditorViewStates { - 0?: IWalkThroughEditorViewState; - 1?: IWalkThroughEditorViewState; - 2?: IWalkThroughEditorViewState; -} - class WalkThroughCodeEditor extends CodeEditor { constructor( @@ -71,9 +65,10 @@ class WalkThroughCodeEditor extends CodeEditor { @ICodeEditorService codeEditorService: ICodeEditorService, @ICommandService commandService: ICommandService, @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @INotificationService notificationService: INotificationService, ) { - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService); + super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService); } getTelemetryData() { @@ -91,26 +86,26 @@ export class WalkThroughPart extends BaseEditor { private scrollbar: DomScrollableElement; private editorFocus: IContextKey; private size: Dimension; + private editorViewStateMemento: EditorViewStateMemento; constructor( @ITelemetryService telemetryService: ITelemetryService, + @IThemeService themeService: IThemeService, + @IModelService modelService: IModelService, @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService protected themeService: IThemeService, @IOpenerService private openerService: IOpenerService, - @IModelService protected modelService: IModelService, @IKeybindingService private keybindingService: IKeybindingService, - @IStorageService private storageService: IStorageService, + @IStorageService storageService: IStorageService, @IContextKeyService private contextKeyService: IContextKeyService, @IConfigurationService private configurationService: IConfigurationService, @INotificationService private notificationService: INotificationService ) { super(WalkThroughPart.ID, telemetryService, themeService); this.editorFocus = WALK_THROUGH_FOCUS.bindTo(this.contextKeyService); + this.editorViewStateMemento = new EditorViewStateMemento(this.getMemento(storageService, Scope.WORKSPACE), WALK_THROUGH_EDITOR_VIEW_STATE_PREFERENCE_KEY); } - createEditor(parent: Builder): void { - const container = parent.getHTMLElement(); - + createEditor(container: HTMLElement): void { this.content = document.createElement('div'); this.content.tabIndex = 0; this.content.style.outlineStyle = 'none'; @@ -214,9 +209,9 @@ export class WalkThroughPart extends BaseEditor { return uri.with({ query: JSON.stringify(query) }); } - layout(size: Dimension): void { - this.size = size; - $(this.content).style({ height: `${size.height}px`, width: `${size.width}px` }); + layout(dimension: Dimension): void { + this.size = dimension; + size(this.content, dimension.width, dimension.height); this.updateSizeClasses(); this.contentDisposables.forEach(disposable => { if (disposable instanceof CodeEditor) { @@ -281,7 +276,7 @@ export class WalkThroughPart extends BaseEditor { } if (this.input instanceof WalkThroughInput) { - this.saveTextEditorViewState(this.input.getResource()); + this.saveTextEditorViewState(this.input); } this.contentDisposables = dispose(this.contentDisposables); @@ -302,7 +297,7 @@ export class WalkThroughPart extends BaseEditor { input.onReady(this.content.firstElementChild as HTMLElement); } this.scrollbar.scanDomNode(); - this.loadTextEditorViewState(input.getResource()); + this.loadTextEditorViewState(input); this.updatedScrollPosition(); return; } @@ -328,7 +323,7 @@ export class WalkThroughPart extends BaseEditor { /* __GDPR__FRAGMENT__ "EditorTelemetryData" : { "target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ const telemetryData = { @@ -383,7 +378,7 @@ export class WalkThroughPart extends BaseEditor { "walkThroughSnippetInteraction" : { "from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('walkThroughSnippetInteraction', { @@ -397,7 +392,7 @@ export class WalkThroughPart extends BaseEditor { "walkThroughSnippetInteraction" : { "from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('walkThroughSnippetInteraction', { @@ -411,7 +406,7 @@ export class WalkThroughPart extends BaseEditor { "walkThroughSnippetInteraction" : { "from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "snippet": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('walkThroughSnippetInteraction', { @@ -432,7 +427,7 @@ export class WalkThroughPart extends BaseEditor { input.onReady(innerContent); } this.scrollbar.scanDomNode(); - this.loadTextEditorViewState(input.getResource()); + this.loadTextEditorViewState(input); this.updatedScrollPosition(); }); } @@ -496,61 +491,46 @@ export class WalkThroughPart extends BaseEditor { }); } - private saveTextEditorViewState(resource: URI): void { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - let editorViewStateMemento: { [key: string]: { [position: number]: IWalkThroughEditorViewState } } = memento[WALK_THROUGH_EDITOR_VIEW_STATE_PREFERENCE_KEY]; - if (!editorViewStateMemento) { - editorViewStateMemento = Object.create(null); - memento[WALK_THROUGH_EDITOR_VIEW_STATE_PREFERENCE_KEY] = editorViewStateMemento; - } - + private saveTextEditorViewState(input: WalkThroughInput): void { const scrollPosition = this.scrollbar.getScrollPosition(); - const editorViewState: IWalkThroughEditorViewState = { + + this.editorViewStateMemento.saveState(input, this.position, { viewState: { scrollTop: scrollPosition.scrollTop, scrollLeft: scrollPosition.scrollLeft } - }; - - let fileViewState = editorViewStateMemento[resource.toString()]; - if (!fileViewState) { - fileViewState = Object.create(null); - editorViewStateMemento[resource.toString()] = fileViewState; - } - - if (typeof this.position === 'number') { - fileViewState[this.position] = editorViewState; - } + }); } - private loadTextEditorViewState(resource: URI) { - const memento = this.getMemento(this.storageService, Scope.WORKSPACE); - const editorViewStateMemento: { [key: string]: IWalkThroughEditorViewStates } = memento[WALK_THROUGH_EDITOR_VIEW_STATE_PREFERENCE_KEY]; - if (editorViewStateMemento) { - const fileViewState = editorViewStateMemento[resource.toString()]; - if (fileViewState) { - const state = fileViewState[this.position]; - if (state) { - this.scrollbar.setScrollPosition(state.viewState); - } - } + private loadTextEditorViewState(input: WalkThroughInput) { + const state = this.editorViewStateMemento.loadState(input, this.position); + if (state) { + this.scrollbar.setScrollPosition(state.viewState); } } public clearInput(): void { if (this.input instanceof WalkThroughInput) { - this.saveTextEditorViewState(this.input.getResource()); + this.saveTextEditorViewState(this.input); } super.clearInput(); } public shutdown(): void { if (this.input instanceof WalkThroughInput) { - this.saveTextEditorViewState(this.input.getResource()); + this.saveTextEditorViewState(this.input); } super.shutdown(); } + protected saveMemento(): void { + + // ensure to first save our view state memento + this.editorViewStateMemento.save(); + + super.saveMemento(); + } + dispose(): void { this.editorFocus.reset(); this.contentDisposables = dispose(this.contentDisposables); diff --git a/src/vs/workbench/services/actions/test/common/menuService.test.ts b/src/vs/workbench/services/actions/test/common/menuService.test.ts index 0ae71806a1..707627acea 100644 --- a/src/vs/workbench/services/actions/test/common/menuService.test.ts +++ b/src/vs/workbench/services/actions/test/common/menuService.test.ts @@ -13,7 +13,7 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { TPromise } from 'vs/base/common/winjs.base'; import { ExtensionPointContribution, IExtensionDescription, IExtensionsStatus, IExtensionService, ProfileSession } from 'vs/workbench/services/extensions/common/extensions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; // --- service instances diff --git a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts similarity index 72% rename from src/vs/workbench/services/backup/test/node/backupFileService.test.ts rename to src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts index e566130f05..1e1b1441fa 100644 --- a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts @@ -7,17 +7,17 @@ import * as assert from 'assert'; import * as platform from 'vs/base/common/platform'; -import crypto = require('crypto'); -import os = require('os'); -import fs = require('fs'); -import path = require('path'); -import extfs = require('vs/base/node/extfs'); -import pfs = require('vs/base/node/pfs'); +import * as crypto from 'crypto'; +import * as os from 'os'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as pfs from 'vs/base/node/pfs'; import Uri from 'vs/base/common/uri'; import { BackupFileService, BackupFilesModel } from 'vs/workbench/services/backup/node/backupFileService'; -import { FileService } from 'vs/workbench/services/files/node/fileService'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; import { TextModel, createTextBufferFactory } from 'vs/editor/common/model/textModel'; -import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices'; +import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { DefaultEndOfLine } from 'vs/editor/common/model'; @@ -39,7 +39,7 @@ const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', crypto.cre class TestBackupFileService extends BackupFileService { constructor(workspace: Uri, backupHome: string, workspacesJsonPath: string) { - const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, workspace.fsPath, toWorkspaceFolders([{ path: workspace.fsPath }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), { disableWatcher: true }); + const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, workspace.fsPath, toWorkspaceFolders([{ path: workspace.fsPath }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true }); super(workspaceBackupPath, fileService); } @@ -52,21 +52,19 @@ class TestBackupFileService extends BackupFileService { suite('BackupFileService', () => { let service: TestBackupFileService; - setup(done => { + setup(() => { service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath); // Delete any existing backups completely and then re-create it. - extfs.del(backupHome, os.tmpdir(), () => { - pfs.mkdirp(backupHome).then(() => { - pfs.writeFile(workspacesJsonPath, '').then(() => { - done(); - }); + return pfs.del(backupHome, os.tmpdir()).then(() => { + return pfs.mkdirp(backupHome).then(() => { + return pfs.writeFile(workspacesJsonPath, ''); }); }); }); - teardown(done => { - extfs.del(backupHome, os.tmpdir(), done); + teardown(() => { + return pfs.del(backupHome, os.tmpdir()); }); suite('getBackupResource', () => { @@ -90,16 +88,15 @@ suite('BackupFileService', () => { }); suite('loadBackupResource', () => { - test('should return whether a backup resource exists', done => { - pfs.mkdirp(path.dirname(fooBackupPath)).then(() => { + test('should return whether a backup resource exists', () => { + return pfs.mkdirp(path.dirname(fooBackupPath)).then(() => { fs.writeFileSync(fooBackupPath, 'foo'); service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath); - service.loadBackupResource(fooFile).then(resource => { + return service.loadBackupResource(fooFile).then(resource => { assert.ok(resource); assert.equal(path.basename(resource.fsPath), path.basename(fooBackupPath)); return service.hasBackups().then(hasBackups => { assert.ok(hasBackups); - done(); }); }); }); @@ -107,165 +104,151 @@ suite('BackupFileService', () => { }); suite('backupResource', () => { - test('text file', function (done: () => void) { - service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('text file', function () { + return service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); - done(); }); }); - test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('untitled file', function () { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); assert.equal(fs.existsSync(untitledBackupPath), true); assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\ntest`); - done(); }); }); - test('text file (ITextSnapshot)', function (done: () => void) { + test('text file (ITextSnapshot)', function () { const model = TextModel.createFromString('test'); - service.backupResource(fooFile, model.createSnapshot()).then(() => { + return service.backupResource(fooFile, model.createSnapshot()).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); model.dispose(); - done(); }); }); - test('untitled file (ITextSnapshot)', function (done: () => void) { + test('untitled file (ITextSnapshot)', function () { const model = TextModel.createFromString('test'); - service.backupResource(untitledFile, model.createSnapshot()).then(() => { + return service.backupResource(untitledFile, model.createSnapshot()).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); assert.equal(fs.existsSync(untitledBackupPath), true); assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\ntest`); model.dispose(); - done(); }); }); - test('text file (large file, ITextSnapshot)', function (done: () => void) { + test('text file (large file, ITextSnapshot)', function () { const largeString = (new Array(10 * 1024)).join('Large String\n'); const model = TextModel.createFromString(largeString); - service.backupResource(fooFile, model.createSnapshot()).then(() => { + return service.backupResource(fooFile, model.createSnapshot()).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\n${largeString}`); model.dispose(); - done(); }); }); - test('untitled file (large file, ITextSnapshot)', function (done: () => void) { + test('untitled file (large file, ITextSnapshot)', function () { const largeString = (new Array(10 * 1024)).join('Large String\n'); const model = TextModel.createFromString(largeString); - service.backupResource(untitledFile, model.createSnapshot()).then(() => { + return service.backupResource(untitledFile, model.createSnapshot()).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); assert.equal(fs.existsSync(untitledBackupPath), true); assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\n${largeString}`); model.dispose(); - done(); }); }); }); suite('discardResourceBackup', () => { - test('text file', function (done: () => void) { - service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('text file', function () { + return service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); - service.discardResourceBackup(fooFile).then(() => { + return service.discardResourceBackup(fooFile).then(() => { assert.equal(fs.existsSync(fooBackupPath), false); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 0); - done(); }); }); }); - test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('untitled file', function () { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); - service.discardResourceBackup(untitledFile).then(() => { + return service.discardResourceBackup(untitledFile).then(() => { assert.equal(fs.existsSync(untitledBackupPath), false); assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 0); - done(); }); }); }); }); suite('discardAllWorkspaceBackups', () => { - test('text file', function (done: () => void) { - service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('text file', function () { + return service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); - service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + return service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 2); - service.discardAllWorkspaceBackups().then(() => { + return service.discardAllWorkspaceBackups().then(() => { assert.equal(fs.existsSync(fooBackupPath), false); assert.equal(fs.existsSync(barBackupPath), false); assert.equal(fs.existsSync(path.join(workspaceBackupPath, 'file')), false); - done(); }); }); }); }); - test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('untitled file', function () { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); - service.discardAllWorkspaceBackups().then(() => { + return service.discardAllWorkspaceBackups().then(() => { assert.equal(fs.existsSync(untitledBackupPath), false); assert.equal(fs.existsSync(path.join(workspaceBackupPath, 'untitled')), false); - done(); }); }); }); - test('should disable further backups', function (done: () => void) { - service.discardAllWorkspaceBackups().then(() => { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + test('should disable further backups', function () { + return service.discardAllWorkspaceBackups().then(() => { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.existsSync(workspaceBackupPath), false); - done(); }); }); }); }); suite('getWorkspaceFileBackups', () => { - test('("file") - text file', done => { - service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { - service.getWorkspaceFileBackups().then(textFiles => { + test('("file") - text file', () => { + return service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + return service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [fooFile.fsPath]); - service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { - service.getWorkspaceFileBackups().then(textFiles => { + return service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + return service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [fooFile.fsPath, barFile.fsPath]); - done(); }); }); }); }); }); - test('("file") - untitled file', done => { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { - service.getWorkspaceFileBackups().then(textFiles => { + test('("file") - untitled file', () => { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + return service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [untitledFile.fsPath]); - done(); }); }); }); - test('("untitled") - untitled file', done => { - service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { - service.getWorkspaceFileBackups().then(textFiles => { + test('("untitled") - untitled file', () => { + return service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + return service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), ['Untitled-1']); - done(); }); }); }); @@ -346,16 +329,14 @@ suite('BackupFilesModel', () => { assert.equal(model.has(resource4), true); }); - test('resolve', (done) => { - pfs.mkdirp(path.dirname(fooBackupPath)).then(() => { + test('resolve', () => { + return pfs.mkdirp(path.dirname(fooBackupPath)).then(() => { fs.writeFileSync(fooBackupPath, 'foo'); const model = new BackupFilesModel(); - model.resolve(workspaceBackupPath).then(model => { + return model.resolve(workspaceBackupPath).then(model => { assert.equal(model.has(Uri.file(fooBackupPath)), true); - - done(); }); }); }); diff --git a/src/vs/workbench/services/commands/common/commandService.ts b/src/vs/workbench/services/commands/common/commandService.ts index 1e3bffd8f8..cc66214564 100644 --- a/src/vs/workbench/services/commands/common/commandService.ts +++ b/src/vs/workbench/services/commands/common/commandService.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService, ICommandEvent, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; @@ -18,7 +18,7 @@ export class CommandService extends Disposable implements ICommandService { private _extensionHostIsReady: boolean = false; - private _onWillExecuteCommand: Emitter = this._register(new Emitter()); + private readonly _onWillExecuteCommand: Emitter = this._register(new Emitter()); public readonly onWillExecuteCommand: Event = this._onWillExecuteCommand.event; constructor( diff --git a/src/vs/workbench/services/commands/test/common/commandService.test.ts b/src/vs/workbench/services/commands/test/common/commandService.test.ts index 4e445e035a..c10a44343b 100644 --- a/src/vs/workbench/services/commands/test/common/commandService.test.ts +++ b/src/vs/workbench/services/commands/test/common/commandService.test.ts @@ -12,7 +12,7 @@ import { CommandService } from 'vs/workbench/services/commands/common/commandSer import { IExtensionService, ExtensionPointContribution, IExtensionDescription, ProfileSession } from 'vs/workbench/services/extensions/common/extensions'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { NullLogService } from 'vs/platform/log/common/log'; class SimpleExtensionService implements IExtensionService { diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index b19af0673e..de9ce19f14 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -14,10 +14,6 @@ export const FOLDER_SETTINGS_PATH = `${FOLDER_CONFIG_FOLDER_NAME}/${FOLDER_SETTI export const IWorkspaceConfigurationService = createDecorator('configurationService'); export interface IWorkspaceConfigurationService extends IConfigurationService { - /** - * Returns untrusted configuration keys for the current workspace. - */ - getUnsupportedWorkspaceKeys(): string[]; } export const defaultSettingsSchemaId = 'vscode://schemas/settings/default'; @@ -30,5 +26,5 @@ export const TASKS_CONFIGURATION_KEY = 'tasks'; export const LAUNCH_CONFIGURATION_KEY = 'launch'; export const WORKSPACE_STANDALONE_CONFIGURATIONS = Object.create(null); -WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/tasks.json`; -WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/launch.json`; +WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/${TASKS_CONFIGURATION_KEY}.json`; +WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/${LAUNCH_CONFIGURATION_KEY}.json`; diff --git a/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts index c1d6c27c8c..b939ab4df5 100644 --- a/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts +++ b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts @@ -32,13 +32,15 @@ const configurationEntrySchema: IJSONSchema = { type: 'object', properties: { isExecutable: { - type: 'boolean' + type: 'boolean', + deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `application` value.' }, scope: { type: 'string', - enum: ['window', 'resource'], + enum: ['application', 'window', 'resource'], default: 'window', enumDescriptions: [ + nls.localize('scope.application.description', "Application specific configuration, which can be configured only in User settings."), nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."), nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.") ], @@ -130,7 +132,17 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten for (let key in properties) { const message = validateProperty(key); const propertyConfiguration = configuration.properties[key]; - propertyConfiguration.scope = propertyConfiguration.scope && propertyConfiguration.scope.toString() === 'resource' ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW; + if (propertyConfiguration.scope) { + if (propertyConfiguration.scope.toString() === 'application') { + propertyConfiguration.scope = ConfigurationScope.APPLICATION; + } else if (propertyConfiguration.scope.toString() === 'resource') { + propertyConfiguration.scope = ConfigurationScope.RESOURCE; + } else { + propertyConfiguration.scope = ConfigurationScope.WINDOW; + } + } else { + propertyConfiguration.scope = ConfigurationScope.WINDOW; + } propertyConfiguration.notMultiRootAdopted = !(extension.description.isBuiltin || (Array.isArray(extension.description.keywords) && extension.description.keywords.indexOf('multi-root ready') !== -1)); if (message) { extension.collector.warn(message); diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 8017db9676..90104ae7f2 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -5,30 +5,15 @@ 'use strict'; import { equals } from 'vs/base/common/objects'; -import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel, IConfigurationOverrides, IOverrides } from 'vs/platform/configuration/common/configuration'; +import { compare, toValuesTree, IConfigurationChangeEvent, ConfigurationTarget, IConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { Configuration as BaseConfiguration, ConfigurationModelParser, ConfigurationChangeEvent, ConfigurationModel, AbstractConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, IConfigurationPropertySchema, Extensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { Workspace } from 'vs/platform/workspace/common/workspace'; -import { StrictResourceMap } from 'vs/base/common/map'; +import { ResourceMap } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; -export class SettingsModel extends ConfigurationModel { - - private _unsupportedKeys: string[]; - - constructor(contents: any, keys: string[], overrides: IOverrides[], unsupportedKeys: string[]) { - super(contents, keys, overrides); - this._unsupportedKeys = unsupportedKeys; - } - - public get unsupportedKeys(): string[] { - return this._unsupportedKeys; - } - -} - export class WorkspaceConfigurationModelParser extends ConfigurationModelParser { private _folders: IStoredWorkspaceFolder[] = []; @@ -37,7 +22,7 @@ export class WorkspaceConfigurationModelParser extends ConfigurationModelParser constructor(name: string) { super(name); - this._settingsModelParser = new FolderSettingsModelParser(name); + this._settingsModelParser = new FolderSettingsModelParser(name, [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]); this._launchModel = new ConfigurationModel(); } @@ -45,8 +30,8 @@ export class WorkspaceConfigurationModelParser extends ConfigurationModelParser return this._folders; } - get settingsModel(): SettingsModel { - return this._settingsModelParser.settingsModel; + get settingsModel(): ConfigurationModel { + return this._settingsModelParser.configurationModel; } get launchModel(): ConfigurationModel { @@ -96,9 +81,9 @@ export class StandaloneConfigurationModelParser extends ConfigurationModelParser export class FolderSettingsModelParser extends ConfigurationModelParser { private _raw: any; - private _settingsModel: SettingsModel; + private _settingsModel: ConfigurationModel; - constructor(name: string, private configurationScope?: ConfigurationScope) { + constructor(name: string, private scopes: ConfigurationScope[]) { super(name); } @@ -108,11 +93,7 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } get configurationModel(): ConfigurationModel { - return this._settingsModel || new SettingsModel({}, [], [], []); - } - - get settingsModel(): SettingsModel { - return this.configurationModel; + return this._settingsModel || new ConfigurationModel(); } reprocess(): void { @@ -120,34 +101,22 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } private parseWorkspaceSettings(rawSettings: any): void { - const unsupportedKeys = []; const rawWorkspaceSettings = {}; const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); for (let key in rawSettings) { - if (this.isNotExecutable(key, configurationProperties)) { - if (this.configurationScope === void 0 || this.getScope(key, configurationProperties) === this.configurationScope) { - rawWorkspaceSettings[key] = rawSettings[key]; - } - } else { - unsupportedKeys.push(key); + const scope = this.getScope(key, configurationProperties); + if (this.scopes.indexOf(scope) !== -1) { + rawWorkspaceSettings[key] = rawSettings[key]; } } const configurationModel = this.parseRaw(rawWorkspaceSettings); - this._settingsModel = new SettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys); + this._settingsModel = new ConfigurationModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides); } private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope { const propertySchema = configurationProperties[key]; return propertySchema ? propertySchema.scope : ConfigurationScope.WINDOW; } - - private isNotExecutable(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): boolean { - const propertySchema = configurationProperties[key]; - if (!propertySchema) { - return true; // Unknown propertis are ignored from checks - } - return !propertySchema.isExecutable; - } } export class Configuration extends BaseConfiguration { @@ -156,9 +125,9 @@ export class Configuration extends BaseConfiguration { defaults: ConfigurationModel, user: ConfigurationModel, workspaceConfiguration: ConfigurationModel, - folders: StrictResourceMap, + folders: ResourceMap, memoryConfiguration: ConfigurationModel, - memoryConfigurationByResource: StrictResourceMap, + memoryConfigurationByResource: ResourceMap, private readonly _workspace: Workspace) { super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource); } @@ -266,8 +235,8 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange return this._changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap { - return new StrictResourceMap(); + get changedConfigurationByResource(): ResourceMap { + return new ResourceMap(); } get affectedKeys(): string[] { @@ -287,7 +256,7 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv return this.configurationChangeEvent.changedConfiguration; } - get changedConfigurationByResource(): StrictResourceMap { + get changedConfigurationByResource(): ResourceMap { return this.configurationChangeEvent.changedConfigurationByResource; } @@ -317,4 +286,4 @@ export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEv return false; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 789e73c16e..0e640013fb 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -4,74 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import URI from 'vs/base/common/uri'; +import { createHash } from 'crypto'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; -import { readFile } from 'vs/base/node/pfs'; +import { Event, Emitter } from 'vs/base/common/event'; +import * as pfs from 'vs/base/node/pfs'; import * as errors from 'vs/base/common/errors'; import * as collections from 'vs/base/common/collections'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; +import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; -import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels'; +import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels'; -import { WORKSPACE_STANDALONE_CONFIGURATIONS, FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; +import { FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import * as extfs from 'vs/base/node/extfs'; import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; -import { WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { relative } from 'path'; import { equals } from 'vs/base/common/objects'; - -// node.hs helper functions - -interface IStat { - resource: URI; - isDirectory?: boolean; - children?: { resource: URI; }[]; -} - -interface IContent { - resource: URI; - value: string; -} - -function resolveContents(resources: URI[]): TPromise { - const contents: IContent[] = []; - - return TPromise.join(resources.map(resource => { - return resolveContent(resource).then(content => { - contents.push(content); - }); - })).then(() => contents); -} - -function resolveContent(resource: URI): TPromise { - return readFile(resource.fsPath).then(contents => ({ resource, value: contents.toString() })); -} - -function resolveStat(resource: URI): TPromise { - return new TPromise((c, e) => { - extfs.readdir(resource.fsPath, (error, children) => { - if (error) { - if ((error).code === 'ENOTDIR') { - c({ resource }); - } else { - e(error); - } - } else { - c({ - resource, - isDirectory: true, - children: children.map(child => { return { resource: URI.file(paths.join(resource.fsPath, child)) }; }) - }); - } - }); - }); -} +import { Schemas } from 'vs/base/common/network'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IConfigurationModel } from 'vs/platform/configuration/common/configuration'; export class WorkspaceConfiguration extends Disposable { @@ -79,7 +36,7 @@ export class WorkspaceConfiguration extends Disposable { private _workspaceConfigurationWatcher: ConfigWatcher; private _workspaceConfigurationWatcherDisposables: IDisposable[] = []; - private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); + private readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : ''); @@ -135,10 +92,6 @@ export class WorkspaceConfiguration extends Disposable { return this._cache; } - getUnsupportedKeys(): string[] { - return this._workspaceConfigurationModelParser.settingsModel.unsupportedKeys; - } - reprocessWorkspaceSettings(): ConfigurationModel { this._workspaceConfigurationModelParser.reprocessWorkspaceSettings(); this.consolidate(); @@ -170,108 +123,201 @@ export class WorkspaceConfiguration extends Disposable { } } -export class FolderConfiguration extends Disposable { +function isFolderConfigurationFile(resource: URI): boolean { + const name = paths.basename(resource.path); + return [`${FOLDER_SETTINGS_NAME}.json`, `${TASKS_CONFIGURATION_KEY}.json`, `${LAUNCH_CONFIGURATION_KEY}.json`].some(p => p === name);// only workspace config files +} - private static readonly RELOAD_CONFIGURATION_DELAY = 50; +export interface IFolderConfiguration { + readonly onDidChange: Event; + readonly loaded: boolean; + loadConfiguration(): TPromise; + reprocess(): ConfigurationModel; + dispose(): void; +} - private bulkFetchFromWorkspacePromise: TPromise; - private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise }; +export abstract class AbstractFolderConfiguration extends Disposable implements IFolderConfiguration { private _folderSettingsModelParser: FolderSettingsModelParser; - private _standAloneConfigurations: ConfigurationModel[] = []; - private _cache: ConfigurationModel = new ConfigurationModel(); + private _standAloneConfigurations: ConfigurationModel[]; + private _cache: ConfigurationModel; + private _loaded: boolean = false; - private reloadConfigurationScheduler: RunOnceScheduler; - private reloadConfigurationEventEmitter: Emitter = new Emitter(); + protected readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; - constructor(private folder: URI, private configFolderRelativePath: string, workbenchState: WorkbenchState) { + constructor(protected readonly folder: URI, workbenchState: WorkbenchState, from?: AbstractFolderConfiguration) { super(); - this._folderSettingsModelParser = new FolderSettingsModelParser(FOLDER_SETTINGS_PATH, WorkbenchState.WORKSPACE === workbenchState ? ConfigurationScope.RESOURCE : void 0); - this.workspaceFilePathToConfiguration = Object.create(null); - this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.loadConfiguration().then(configuration => this.reloadConfigurationEventEmitter.fire(configuration), errors.onUnexpectedError), FolderConfiguration.RELOAD_CONFIGURATION_DELAY)); + this._folderSettingsModelParser = from ? from._folderSettingsModelParser : new FolderSettingsModelParser(FOLDER_SETTINGS_PATH, WorkbenchState.WORKSPACE === workbenchState ? [ConfigurationScope.RESOURCE] : [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]); + this._standAloneConfigurations = from ? from._standAloneConfigurations : []; + this._cache = from ? from._cache : new ConfigurationModel(); + } + + get loaded(): boolean { + return this._loaded; } loadConfiguration(): TPromise { - // Load workspace locals - return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => { - this._standAloneConfigurations = Object.keys(workspaceConfigFiles).filter(key => key !== FOLDER_SETTINGS_PATH).map(key => workspaceConfigFiles[key].configurationModel); - // Consolidate (support *.json files in the workspace settings folder) - this.consolidate(); - return this._cache; - }); + return this.loadFolderConfigurationContents() + .then((contents) => { + + // reset + this._standAloneConfigurations = []; + this._folderSettingsModelParser.parse(''); + + // parse + this.parseContents(contents); + + // Consolidate (support *.json files in the workspace settings folder) + this.consolidate(); + + this._loaded = true; + return this._cache; + }); } reprocess(): ConfigurationModel { - const oldContents = this._folderSettingsModelParser.settingsModel.contents; + const oldContents = this._folderSettingsModelParser.configurationModel.contents; this._folderSettingsModelParser.reprocess(); - if (!equals(oldContents, this._folderSettingsModelParser.settingsModel.contents)) { + if (!equals(oldContents, this._folderSettingsModelParser.configurationModel.contents)) { this.consolidate(); } return this._cache; } - getUnsupportedKeys(): string[] { - return this._folderSettingsModelParser.settingsModel.unsupportedKeys; - } - private consolidate(): void { - this._cache = this._folderSettingsModelParser.settingsModel.merge(...this._standAloneConfigurations); + this._cache = this._folderSettingsModelParser.configurationModel.merge(...this._standAloneConfigurations); } - private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModelParser }> { - // once: when invoked for the first time we fetch json files that contribute settings - if (!this.bulkFetchFromWorkspacePromise) { - this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.configFolderRelativePath)).then(stat => { - if (!stat.isDirectory) { - return TPromise.as([]); + private parseContents(contents: { resource: URI, value: string }[]): void { + for (const content of contents) { + const name = paths.basename(content.resource.path); + if (name === `${FOLDER_SETTINGS_NAME}.json`) { + this._folderSettingsModelParser.parse(content.value); + } else { + const matches = /([^\.]*)*\.json/.exec(name); + if (matches && matches[1]) { + const standAloneConfigurationModelParser = new StandaloneConfigurationModelParser(content.resource.toString(), matches[1]); + standAloneConfigurationModelParser.parse(content.value); + this._standAloneConfigurations.push(standAloneConfigurationModelParser.configurationModel); } + } + } + } - return resolveContents(stat.children.filter(stat => { - const isJson = paths.extname(stat.resource.fsPath) === '.json'; - if (!isJson) { - return false; // only JSON files + protected abstract loadFolderConfigurationContents(): TPromise<{ resource: URI, value: string }[]>; +} + +export class NodeBasedFolderConfiguration extends AbstractFolderConfiguration { + + private readonly folderConfigurationPath: URI; + + constructor(folder: URI, configFolderRelativePath: string, workbenchState: WorkbenchState) { + super(folder, workbenchState); + this.folderConfigurationPath = URI.file(paths.join(this.folder.fsPath, configFolderRelativePath)); + } + + protected loadFolderConfigurationContents(): TPromise<{ resource: URI, value: string }[]> { + return this.resolveStat(this.folderConfigurationPath).then(stat => { + if (!stat.isDirectory) { + return TPromise.as([]); + } + return this.resolveContents(stat.children.filter(stat => isFolderConfigurationFile(stat.resource)) + .map(stat => stat.resource)); + }, err => [] /* never fail this call */) + .then(null, errors.onUnexpectedError); + } + + private resolveContents(resources: URI[]): TPromise<{ resource: URI, value: string }[]> { + return TPromise.join(resources.map(resource => + pfs.readFile(resource.fsPath) + .then(contents => ({ resource, value: contents.toString() })))); + } + + private resolveStat(resource: URI): TPromise<{ resource: URI, isDirectory?: boolean, children?: { resource: URI; }[] }> { + return new TPromise<{ resource: URI, isDirectory?: boolean, children?: { resource: URI; }[] }>((c, e) => { + extfs.readdir(resource.fsPath, (error, children) => { + if (error) { + if ((error).code === 'ENOTDIR') { + c({ resource }); + } else { + e(error); } + } else { + c({ + resource, + isDirectory: true, + children: children.map(child => { return { resource: URI.file(paths.join(resource.fsPath, child)) }; }) + }); + } + }); + }); + } +} - return this.isWorkspaceConfigurationFile(this.toFolderRelativePath(stat.resource)); // only workspace config files - }).map(stat => stat.resource)); - }, err => [] /* never fail this call */) - .then((contents: IContent[]) => { - contents.forEach(content => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(content.resource)] = TPromise.as(this.createConfigurationModelParser(content))); - }, errors.onUnexpectedError); +export class FileServiceBasedFolderConfiguration extends AbstractFolderConfiguration { + + private bulkContentFetchromise: TPromise; + private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise }; + private reloadConfigurationScheduler: RunOnceScheduler; + private readonly folderConfigurationPath: URI; + + constructor(folder: URI, private configFolderRelativePath: string, workbenchState: WorkbenchState, private fileService: IFileService, from?: AbstractFolderConfiguration) { + super(folder, workbenchState, from); + this.folderConfigurationPath = folder.with({ path: paths.join(this.folder.path, configFolderRelativePath) }); + this.workspaceFilePathToConfiguration = Object.create(null); + this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50)); + this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e))); + } + + protected loadFolderConfigurationContents(): TPromise<{ resource: URI, value: string }[]> { + // once: when invoked for the first time we fetch json files that contribute settings + if (!this.bulkContentFetchromise) { + this.bulkContentFetchromise = this.fileService.resolveFile(this.folderConfigurationPath) + .then(stat => { + if (stat.isDirectory && stat.children) { + stat.children + .filter(child => isFolderConfigurationFile(child.resource)) + .forEach(child => this.workspaceFilePathToConfiguration[this.toFolderRelativePath(child.resource)] = this.fileService.resolveContent(child.resource).then(null, errors.onUnexpectedError)); + } + }).then(null, err => [] /* never fail this call */); } // on change: join on *all* configuration file promises so that we can merge them into a single configuration object. this // happens whenever a config file changes, is deleted, or added - return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration)); + return this.bulkContentFetchromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration).then(result => collections.values(result))); } - public handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { + private handleWorkspaceFileEvents(event: FileChangesEvent): void { const events = event.changes; let affectedByChanges = false; // Find changes that affect workspace configuration files for (let i = 0, len = events.length; i < len; i++) { + const resource = events[i].resource; - const isJson = paths.extname(resource.fsPath) === '.json'; - const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && paths.isEqual(paths.basename(resource.fsPath), this.configFolderRelativePath)); + const basename = paths.basename(resource.path); + const isJson = paths.extname(basename) === '.json'; + const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && basename === this.configFolderRelativePath); + if (!isJson && !isDeletedSettingsFolder) { continue; // only JSON files or the actual settings folder } - const workspacePath = this.toFolderRelativePath(resource); - if (!workspacePath) { - continue; // event is not inside workspace + const folderRelativePath = this.toFolderRelativePath(resource); + if (!folderRelativePath) { + continue; // event is not inside folder } // Handle case where ".vscode" got deleted - if (workspacePath === this.configFolderRelativePath && events[i].type === FileChangeType.DELETED) { + if (isDeletedSettingsFolder) { this.workspaceFilePathToConfiguration = Object.create(null); affectedByChanges = true; } // only valid workspace config files - if (!this.isWorkspaceConfigurationFile(workspacePath)) { + if (!isFolderConfigurationFile(resource)) { continue; } @@ -279,72 +325,176 @@ export class FolderConfiguration extends Disposable { // remove promises for delete events switch (events[i].type) { case FileChangeType.DELETED: - affectedByChanges = collections.remove(this.workspaceFilePathToConfiguration, workspacePath); + affectedByChanges = collections.remove(this.workspaceFilePathToConfiguration, folderRelativePath); break; case FileChangeType.UPDATED: case FileChangeType.ADDED: - this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigurationModelParser(content), errors.onUnexpectedError); + this.workspaceFilePathToConfiguration[folderRelativePath] = this.fileService.resolveContent(resource).then(null, errors.onUnexpectedError); affectedByChanges = true; } } - if (!affectedByChanges) { - return TPromise.as(null); + if (affectedByChanges) { + this.reloadConfigurationScheduler.schedule(); } + } - return new TPromise((c, e) => { - let disposable = this.reloadConfigurationEventEmitter.event(configuration => { - disposable.dispose(); - c(configuration); - }); - // trigger reload of the configuration if we are affected by changes - if (!this.reloadConfigurationScheduler.isScheduled()) { - this.reloadConfigurationScheduler.schedule(); + private toFolderRelativePath(resource: URI): string { + if (resource.scheme === Schemas.file) { + if (paths.isEqualOrParent(resource.fsPath, this.folderConfigurationPath.fsPath, !isLinux /* ignorecase */)) { + return paths.normalize(relative(this.folderConfigurationPath.fsPath, resource.fsPath)); } + } else { + if (paths.isEqualOrParent(resource.path, this.folderConfigurationPath.path, true /* ignorecase */)) { + return paths.normalize(relative(this.folderConfigurationPath.path, resource.path)); + } + } + return null; + } +} + +export class CachedFolderConfiguration extends Disposable implements IFolderConfiguration { + + private readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; + + private readonly cachedFolderPath: string; + private readonly cachedConfigurationPath: string; + private configurationModel: ConfigurationModel; + + loaded: boolean = false; + + constructor( + folder: URI, + configFolderRelativePath: string, + environmentService: IEnvironmentService) { + super(); + this.cachedFolderPath = paths.join(environmentService.appSettingsHome, createHash('md5').update(paths.join(folder.path, configFolderRelativePath)).digest('hex')); + this.cachedConfigurationPath = paths.join(this.cachedFolderPath, 'configuration.json'); + this.configurationModel = new ConfigurationModel(); + } + + loadConfiguration(): TPromise { + return pfs.readFile(this.cachedConfigurationPath) + .then(contents => { + const parsed: IConfigurationModel = JSON.parse(contents.toString()); + this.configurationModel = new ConfigurationModel(parsed.contents, parsed.keys, parsed.overrides); + this.loaded = true; + return this.configurationModel; + }, () => this.configurationModel); + } + + updateConfiguration(configurationModel: ConfigurationModel): TPromise { + const raw = JSON.stringify(configurationModel.toJSON()); + return this.createCachedFolder().then(created => { + if (created) { + return configurationModel.keys.length ? pfs.writeFile(this.cachedConfigurationPath, raw) : pfs.rimraf(this.cachedFolderPath); + } + return null; }); } - private createConfigurationModelParser(content: IContent): ConfigurationModelParser { - const path = this.toFolderRelativePath(content.resource); - if (path === FOLDER_SETTINGS_PATH) { - this._folderSettingsModelParser.parse(content.value); - return this._folderSettingsModelParser; - } else { - const matches = /\/([^\.]*)*\.json/.exec(path); - if (matches && matches[1]) { - const standAloneConfigurationModelParser = new StandaloneConfigurationModelParser(content.resource.toString(), matches[1]); - standAloneConfigurationModelParser.parse(content.value); - return standAloneConfigurationModelParser; + reprocess(): ConfigurationModel { + return this.configurationModel; + } + + getUnsupportedKeys(): string[] { + return []; + } + + private createCachedFolder(): TPromise { + return pfs.exists(this.cachedFolderPath) + .then(null, () => false) + .then(exists => exists ? exists : pfs.mkdirp(this.cachedFolderPath).then(() => true, () => false)); + } +} + +export class FolderConfiguration extends Disposable implements IFolderConfiguration { + + protected readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; + + private folderConfiguration: IFolderConfiguration; + private cachedFolderConfiguration: CachedFolderConfiguration; + private _loaded: boolean = false; + + constructor( + readonly workspaceFolder: IWorkspaceFolder, + private readonly configFolderRelativePath: string, + private readonly workbenchState: WorkbenchState, + private environmentService: IEnvironmentService, + fileService?: IFileService + ) { + super(); + + this.cachedFolderConfiguration = new CachedFolderConfiguration(this.workspaceFolder.uri, this.configFolderRelativePath, this.environmentService); + this.folderConfiguration = this.cachedFolderConfiguration; + if (fileService) { + this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.workspaceFolder.uri, this.configFolderRelativePath, this.workbenchState, fileService); + } else if (this.workspaceFolder.uri.scheme === Schemas.file) { + this.folderConfiguration = new NodeBasedFolderConfiguration(this.workspaceFolder.uri, this.configFolderRelativePath, this.workbenchState); + } + this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); + } + + loadConfiguration(): TPromise { + return this.folderConfiguration.loadConfiguration() + .then(model => { + this._loaded = this.folderConfiguration.loaded; + return model; + }); + } + + reprocess(): ConfigurationModel { + return this.folderConfiguration.reprocess(); + } + + get loaded(): boolean { + return this._loaded; + } + + adopt(fileService: IFileService): TPromise { + if (fileService) { + if (this.folderConfiguration instanceof CachedFolderConfiguration) { + return this.adoptFromCachedConfiguration(fileService); + } + + if (this.folderConfiguration instanceof NodeBasedFolderConfiguration) { + return this.adoptFromNodeBasedConfiguration(fileService); } } - return new ConfigurationModelParser(null); + return TPromise.as(false); } - private isWorkspaceConfigurationFile(folderRelativePath: string): boolean { - return [FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY], WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY]].some(p => p === folderRelativePath); + private adoptFromCachedConfiguration(fileService: IFileService): TPromise { + const folderConfiguration = new FileServiceBasedFolderConfiguration(this.workspaceFolder.uri, this.configFolderRelativePath, this.workbenchState, fileService); + return folderConfiguration.loadConfiguration() + .then(() => { + this.folderConfiguration = folderConfiguration; + this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); + this.updateCache(); + return true; + }); } - private toResource(folderRelativePath: string): URI { - if (typeof folderRelativePath === 'string') { - return URI.file(paths.join(this.folder.fsPath, folderRelativePath)); + private adoptFromNodeBasedConfiguration(fileService: IFileService): TPromise { + const oldFolderConfiguration = this.folderConfiguration; + this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.workspaceFolder.uri, this.configFolderRelativePath, this.workbenchState, fileService, oldFolderConfiguration); + oldFolderConfiguration.dispose(); + this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange())); + return TPromise.as(false); + } + + private onDidFolderConfigurationChange(): void { + this.updateCache(); + this._onDidChange.fire(); + } + + private updateCache(): TPromise { + if (this.workspaceFolder.uri.scheme !== Schemas.file && this.folderConfiguration instanceof FileServiceBasedFolderConfiguration) { + return this.folderConfiguration.loadConfiguration() + .then(configurationModel => this.cachedFolderConfiguration.updateConfiguration(configurationModel)); } - - return null; - } - - private toFolderRelativePath(resource: URI, toOSPath?: boolean): string { - if (this.contains(resource)) { - return paths.normalize(relative(this.folder.fsPath, resource.fsPath), toOSPath); - } - - return null; - } - - private contains(resource: URI): boolean { - if (resource) { - return paths.isEqualOrParent(resource.fsPath, this.folder.fsPath, !isLinux /* ignorecase */); - } - - return false; + return TPromise.as(null); } } \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index e9009f7c6e..299ae47552 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -30,7 +30,6 @@ import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as Config import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextModel } from 'vs/editor/common/model'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; export enum ConfigurationEditingErrorCode { @@ -40,6 +39,11 @@ export enum ConfigurationEditingErrorCode { */ ERROR_UNKNOWN_KEY, + /** + * Error when trying to write an application setting into workspace settings. + */ + ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION, + /** * Error when trying to write an invalid folder configuration key to folder settings. */ @@ -127,7 +131,6 @@ export class ConfigurationEditingService { @IFileService private fileService: IFileService, @ITextModelService private textModelResolverService: ITextModelService, @ITextFileService private textFileService: ITextFileService, - @IChoiceService private choiceService: IChoiceService, @INotificationService private notificationService: INotificationService, @ICommandService private commandService: ICommandService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService @@ -139,12 +142,12 @@ export class ConfigurationEditingService { const operation = this.getConfigurationEditOperation(target, value, options.scopes || {}); return this.queue.queue(() => this.doWriteConfiguration(operation, options) // queue up writes to prevent race conditions .then(() => null, - error => { - if (!options.donotNotifyError) { - this.onError(error, operation, options.scopes); - } - return TPromise.wrapError(error); - })); + error => { + if (!options.donotNotifyError) { + this.onError(error, operation, options.scopes); + } + return TPromise.wrapError(error); + })); } private doWriteConfiguration(operation: IConfigurationEditOperation, options: ConfigurationEditingOptions): TPromise { @@ -194,19 +197,19 @@ export class ConfigurationEditingService { : operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration") : null; if (openStandAloneConfigurationActionLabel) { - this.choiceService.choose(Severity.Error, error.message, [openStandAloneConfigurationActionLabel]) - .then(option => { - if (option === 0) { - this.openFile(operation.resource); - } - }); + this.notificationService.prompt(Severity.Error, error.message, + [{ + label: openStandAloneConfigurationActionLabel, + run: () => this.openFile(operation.resource) + }] + ); } else { - this.choiceService.choose(Severity.Error, error.message, [nls.localize('open', "Open Settings")]) - .then(option => { - if (option === 0) { - this.openSettings(operation); - } - }); + this.notificationService.prompt(Severity.Error, error.message, + [{ + label: nls.localize('open', "Open Settings"), + run: () => this.openSettings(operation) + }] + ); } } @@ -215,30 +218,30 @@ export class ConfigurationEditingService { : operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration") : null; if (openStandAloneConfigurationActionLabel) { - this.choiceService.choose(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), openStandAloneConfigurationActionLabel]) - .then(option => { - switch (option) { - case 0 /* Save & Retry */: - const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey; - this.writeConfiguration(operation.target, { key, value: operation.value }, { force: true, scopes }); - break; - case 1 /* Open Config */: - this.openFile(operation.resource); - break; + this.notificationService.prompt(Severity.Error, error.message, + [{ + label: nls.localize('saveAndRetry', "Save and Retry"), + run: () => { + const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey; + this.writeConfiguration(operation.target, { key, value: operation.value }, { force: true, scopes }); } - }); + }, + { + label: openStandAloneConfigurationActionLabel, + run: () => this.openFile(operation.resource) + }] + ); } else { - this.choiceService.choose(Severity.Error, error.message, [nls.localize('saveAndRetry', "Save and Retry"), nls.localize('open', "Open Settings")]) - .then(option => { - switch (option) { - case 0 /* Save and Retry */: - this.writeConfiguration(operation.target, { key: operation.key, value: operation.value }, { force: true, scopes }); - break; - case 1 /* Open Settings */: - this.openSettings(operation); - break; - } - }); + this.notificationService.prompt(Severity.Error, error.message, + [{ + label: nls.localize('saveAndRetry', "Save and Retry"), + run: () => this.writeConfiguration(operation.target, { key: operation.key, value: operation.value }, { force: true, scopes }) + }, + { + label: nls.localize('open', "Open Settings"), + run: () => this.openSettings(operation) + }] + ); } } @@ -276,6 +279,7 @@ export class ConfigurationEditingService { // API constraints case ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY: return nls.localize('errorUnknownKey', "Unable to write to {0} because {1} is not a registered configuration.", this.stringifyTarget(target), operation.key); + case ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION: return nls.localize('errorInvalidWorkspaceConfigurationApplication', "Unable to write {0} to Workspace Settings. This setting can be written only into User settings.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_CONFIGURATION: return nls.localize('errorInvalidFolderConfiguration', "Unable to write to Folder Settings because {0} does not support the folder resource scope.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET: return nls.localize('errorInvalidUserTarget', "Unable to write to User Settings because {0} does not support for global scope.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET: return nls.localize('errorInvalidWorkspaceTarget', "Unable to write to Workspace Settings because {0} does not support for workspace scope in a multi folder workspace.", operation.key); @@ -398,6 +402,15 @@ export class ConfigurationEditingService { return this.wrapError(ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED, target, operation); } + if (target === ConfigurationTarget.WORKSPACE) { + if (!operation.workspaceStandAloneConfigurationKey) { + const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); + if (configurationProperties[operation.key].scope === ConfigurationScope.APPLICATION) { + return this.wrapError(ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION, target, operation); + } + } + } + if (target === ConfigurationTarget.WORKSPACE_FOLDER) { if (!operation.resource) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_TARGET, target, operation); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 0f9282e672..163cc1004e 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -8,15 +8,15 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { dirname, basename } from 'path'; import * as assert from 'vs/base/common/assert'; -import Event, { Emitter } from 'vs/base/common/event'; -import { StrictResourceMap } from 'vs/base/common/map'; -import { equals } from 'vs/base/common/objects'; +import { Event, Emitter } from 'vs/base/common/event'; +import { ResourceMap } from 'vs/base/common/map'; +import { equals, deepClone } from 'vs/base/common/objects'; import { Disposable } from 'vs/base/common/lifecycle'; import { Queue } from 'vs/base/common/async'; import { stat, writeFile } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { FileChangesEvent } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; @@ -24,7 +24,7 @@ import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { IWorkspaceConfigurationService, FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationNode, IConfigurationRegistry, Extensions, settingsSchema, resourceSettingsSchema, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationNode, IConfigurationRegistry, Extensions, IConfigurationPropertySchema, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; import { getWorkspaceLabel, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; @@ -37,9 +37,10 @@ import { WorkspaceConfiguration, FolderConfiguration } from 'vs/workbench/servic import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; import { Schemas } from 'vs/base/common/network'; import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces'; -import { distinct } from 'vs/base/common/arrays'; import { UserConfiguration } from 'vs/platform/configuration/node/configuration'; import { getBaseLabel } from 'vs/base/common/labels'; +import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; +import { localize } from 'vs/nls'; export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { @@ -50,7 +51,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private defaultConfiguration: DefaultConfigurationModel; private userConfiguration: UserConfiguration; private workspaceConfiguration: WorkspaceConfiguration; - private cachedFolderConfigs: StrictResourceMap; + private cachedFolderConfigs: ResourceMap; private workspaceEditingQueue: Queue; @@ -66,6 +67,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat protected readonly _onDidChangeWorkbenchState: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event; + private fileService: IFileService; private configurationEditingService: ConfigurationEditingService; private jsonEditingService: JSONEditingService; @@ -236,7 +238,9 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // Workspace Configuration Service Impl getConfigurationData(): IConfigurationData { - return this._configuration.toData(); + const configurationData = this._configuration.toData(); + configurationData.isComplete = this.cachedFolderConfigs.values().every(c => c.loaded); + return configurationData; } getValue(): T; @@ -291,32 +295,31 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this._configuration.keys(); } - getUnsupportedWorkspaceKeys(): string[] { - const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getUnsupportedKeys()]; - for (const folder of this.workspace.folders) { - unsupportedWorkspaceKeys.push(...this.cachedFolderConfigs.get(folder.uri).getUnsupportedKeys()); - } - return distinct(unsupportedWorkspaceKeys); - } - initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { return this.createWorkspace(arg) .then(workspace => this.updateWorkspaceAndInitializeConfiguration(workspace)); } - setInstantiationService(instantiationService: IInstantiationService): void { - this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); - this.jsonEditingService = instantiationService.createInstance(JSONEditingService); + acquireFileService(fileService: IFileService): void { + this.fileService = fileService; + const changedWorkspaceFolders: IWorkspaceFolder[] = []; + TPromise.join(this.cachedFolderConfigs.values() + .map(folderConfiguration => folderConfiguration.adopt(fileService) + .then(result => { + if (result) { + changedWorkspaceFolders.push(folderConfiguration.workspaceFolder); + } + }))) + .then(() => { + for (const workspaceFolder of changedWorkspaceFolders) { + this.onWorkspaceFolderConfigurationChanged(workspaceFolder); + } + }); } - handleWorkspaceFileEvents(event: FileChangesEvent): TPromise { - switch (this.getWorkbenchState()) { - case WorkbenchState.FOLDER: - return this.onSingleFolderFileChanges(event); - case WorkbenchState.WORKSPACE: - return this.onWorkspaceFileChanges(event); - } - return TPromise.as(void 0); + acquireInstantiationService(instantiationService: IInstantiationService): void { + this.configurationEditingService = instantiationService.createInstance(ConfigurationEditingService); + this.jsonEditingService = instantiationService.createInstance(JSONEditingService); } private createWorkspace(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { @@ -438,18 +441,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private loadConfiguration(): TPromise { // reset caches - this.cachedFolderConfigs = new StrictResourceMap(); + this.cachedFolderConfigs = new ResourceMap(); const folders = this.workspace.folders; return this.loadFolderConfigurations(folders) .then((folderConfigurations) => { let workspaceConfiguration = this.getWorkspaceConfigurationModel(folderConfigurations); - const folderConfigurationModels = new StrictResourceMap(); + const folderConfigurationModels = new ResourceMap(); folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration)); const currentConfiguration = this._configuration; - this._configuration = new Configuration(this.defaultConfiguration, this.userConfiguration.configurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new StrictResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null + this._configuration = new Configuration(this.defaultConfiguration, this.userConfiguration.configurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new ResourceMap(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null if (currentConfiguration) { const changedKeys = this._configuration.compare(currentConfiguration); @@ -489,15 +492,29 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private registerConfigurationSchemas(): void { if (this.workspace) { const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); - jsonRegistry.registerSchema(defaultSettingsSchemaId, settingsSchema); - jsonRegistry.registerSchema(userSettingsSchemaId, settingsSchema); + const convertToNotSuggestedProperties = (properties: IJSONSchemaMap, errorMessage: string): IJSONSchemaMap => { + return Object.keys(properties).reduce((result: IJSONSchemaMap, property) => { + result[property] = deepClone(properties[property]); + result[property].deprecationMessage = errorMessage; + return result; + }, {}); + }; + + const allSettingsSchema: IJSONSchema = { properties: allSettings.properties, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + const unsupportedApplicationSettings = convertToNotSuggestedProperties(applicationSettings.properties, localize('unsupportedApplicationSetting', "This setting can be applied only in User Settings")); + const workspaceSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...windowSettings.properties, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + + jsonRegistry.registerSchema(defaultSettingsSchemaId, allSettingsSchema); + jsonRegistry.registerSchema(userSettingsSchemaId, allSettingsSchema); if (WorkbenchState.WORKSPACE === this.getWorkbenchState()) { - jsonRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); - jsonRegistry.registerSchema(folderSettingsSchemaId, resourceSettingsSchema); + const unsupportedWindowSettings = convertToNotSuggestedProperties(windowSettings.properties, localize('unsupportedWindowSetting', "This setting cannot be applied now. It will be applied when you open this folder directly.")); + const folderSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...unsupportedWindowSettings, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + jsonRegistry.registerSchema(workspaceSettingsSchemaId, workspaceSettingsSchema); + jsonRegistry.registerSchema(folderSettingsSchemaId, folderSettingsSchema); } else { - jsonRegistry.registerSchema(workspaceSettingsSchemaId, settingsSchema); - jsonRegistry.registerSchema(folderSettingsSchemaId, settingsSchema); + jsonRegistry.registerSchema(workspaceSettingsSchemaId, workspaceSettingsSchema); + jsonRegistry.registerSchema(folderSettingsSchemaId, workspaceSettingsSchema); } } } @@ -526,33 +543,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return TPromise.as(null); } - private onWorkspaceFileChanges(event: FileChangesEvent): TPromise { - return TPromise.join(this.workspace.folders.map(folder => - // handle file event for each folder - this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event) - // Update folder configuration if handled - .then(folderConfiguration => folderConfiguration ? this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration) : new ConfigurationChangeEvent())) - ).then(changeEvents => { - const consolidateChangeEvent = changeEvents.reduce((consolidated, e) => consolidated.change(e), new ConfigurationChangeEvent()); - this.triggerConfigurationChange(consolidateChangeEvent, ConfigurationTarget.WORKSPACE_FOLDER); - }); - } - - private onSingleFolderFileChanges(event: FileChangesEvent): TPromise { - const folder = this.workspace.folders[0]; - return this.cachedFolderConfigs.get(folder.uri).handleWorkspaceFileEvents(event) - .then(folderConfiguration => { - if (folderConfiguration) { - // File change handled - this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration); - const workspaceChangedKeys = this._configuration.compareAndUpdateWorkspaceConfiguration(folderConfiguration); - this.triggerConfigurationChange(workspaceChangedKeys, ConfigurationTarget.WORKSPACE); - } - }); - } - private onWorkspaceFolderConfigurationChanged(folder: IWorkspaceFolder, key?: string): TPromise { - this.disposeFolderConfiguration(folder); return this.loadFolderConfigurations([folder]) .then(([folderConfiguration]) => { const folderChangedKeys = this._configuration.compareAndUpdateFolderConfiguration(folder.uri, folderConfiguration); @@ -571,6 +562,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // Remove the configurations of deleted folders for (const key of this.cachedFolderConfigs.keys()) { if (!this.workspace.folders.filter(folder => folder.uri.toString() === key.toString())[0]) { + const folderConfiguration = this.cachedFolderConfigs.get(key); + folderConfiguration.dispose(); this.cachedFolderConfigs.delete(key); changeEvent = changeEvent.change(this._configuration.compareAndDeleteFolderConfiguration(key)); } @@ -591,8 +584,12 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private loadFolderConfigurations(folders: IWorkspaceFolder[]): TPromise { return TPromise.join([...folders.map(folder => { - const folderConfiguration = new FolderConfiguration(folder.uri, this.workspaceSettingsRootFolder, this.getWorkbenchState()); - this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration)); + let folderConfiguration = this.cachedFolderConfigs.get(folder.uri); + if (!folderConfiguration) { + folderConfiguration = new FolderConfiguration(folder, this.workspaceSettingsRootFolder, this.getWorkbenchState(), this.environmentService, this.fileService); + this._register(folderConfiguration.onDidChange(() => this.onWorkspaceFolderConfigurationChanged(folder))); + this.cachedFolderConfigs.set(folder.uri, this._register(folderConfiguration)); + } return folderConfiguration.loadConfiguration(); })]); } @@ -679,13 +676,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return path1 === path2; } - - private disposeFolderConfiguration(folder: IWorkspaceFolder): void { - const folderConfiguration = this.cachedFolderConfigs.get(folder.uri); - if (folderConfiguration) { - folderConfiguration.dispose(); - } - } } interface IExportedConfigurationNode { diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index 417cb077b4..b72e5e21a1 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -13,12 +13,12 @@ import URI from 'vs/base/common/uri'; import { ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { StrictResourceMap } from 'vs/base/common/map'; +import { ResourceMap } from 'vs/base/common/map'; suite('FolderSettingsModelParser', () => { suiteSetup(() => { - const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': 'FolderSettingsModelParser_1', 'type': 'object', @@ -32,47 +32,47 @@ suite('FolderSettingsModelParser', () => { 'default': 'isSet', scope: ConfigurationScope.RESOURCE }, - 'FolderSettingsModelParser.executable': { + 'FolderSettingsModelParser.application': { 'type': 'string', 'default': 'isSet', - isExecutable: true + scope: ConfigurationScope.APPLICATION } } }); }); test('parse all folder settings', () => { - const testObject = new FolderSettingsModelParser('settings'); + const testObject = new FolderSettingsModelParser('settings', [ConfigurationScope.RESOURCE, ConfigurationScope.WINDOW]); - testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.executable': 'executable' })); + testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'executable' })); assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'window': 'window', 'resource': 'resource' } }); }); test('parse resource folder settings', () => { - const testObject = new FolderSettingsModelParser('settings', ConfigurationScope.RESOURCE); + const testObject = new FolderSettingsModelParser('settings', [ConfigurationScope.RESOURCE]); - testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.executable': 'executable' })); + testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'executable' })); assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource' } }); }); - test('reprocess folder settings excludes executable', () => { - const testObject = new FolderSettingsModelParser('settings'); + test('reprocess folder settings excludes application setting', () => { + const testObject = new FolderSettingsModelParser('settings', [ConfigurationScope.RESOURCE, ConfigurationScope.WINDOW]); - testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.anotherExecutable': 'executable' })); + testObject.parse(JSON.stringify({ 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.anotherApplicationSetting': 'executable' })); - assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource', 'anotherExecutable': 'executable' } }); + assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource', 'anotherApplicationSetting': 'executable' } }); - const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': 'FolderSettingsModelParser_2', 'type': 'object', 'properties': { - 'FolderSettingsModelParser.anotherExecutable': { + 'FolderSettingsModelParser.anotherApplicationSetting': { 'type': 'string', 'default': 'isSet', - isExecutable: true + scope: ConfigurationScope.APPLICATION } } }); @@ -194,7 +194,7 @@ suite('AllKeysConfigurationChangeEvent', () => { test('changeEvent affects keys for any resource', () => { const configuraiton = new Configuration(new ConfigurationModel({}, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']), - new ConfigurationModel(), new ConfigurationModel(), new StrictResourceMap(), new ConfigurationModel(), new StrictResourceMap(), null); + new ConfigurationModel(), new ConfigurationModel(), new ResourceMap(), new ConfigurationModel(), new ResourceMap(), null); let testObject = new AllKeysConfigurationChangeEvent(configuraiton, ConfigurationTarget.USER, null); assert.deepEqual(testObject.affectedKeys, ['window.title', 'window.zoomLevel', 'window.restoreFullscreen', 'workbench.editor.enablePreview', 'window.restoreWindows']); @@ -234,4 +234,4 @@ suite('AllKeysConfigurationChangeEvent', () => { assert.ok(!testObject.affectsConfiguration('files')); assert.ok(!testObject.affectsConfiguration('files', URI.file('file1'))); }); -}); \ No newline at end of file +}); diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts similarity index 87% rename from src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts rename to src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index 8f7b6a2a1e..07a2857a2d 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -6,10 +6,10 @@ 'use strict'; import * as sinon from 'sinon'; -import assert = require('assert'); -import os = require('os'); -import path = require('path'); -import fs = require('fs'); +import * as assert from 'assert'; +import * as os from 'os'; +import * as path from 'path'; +import * as fs from 'fs'; import * as json from 'vs/base/common/json'; import { TPromise } from 'vs/base/common/winjs.base'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -17,12 +17,13 @@ import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/ import { parseArgs } from 'vs/platform/environment/node/argv'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService, TestLifecycleService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices'; -import uuid = require('vs/base/common/uuid'); +import * as extfs from 'vs/base/node/extfs'; +import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; -import { FileService } from 'vs/workbench/services/files/node/fileService'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { IFileService } from 'vs/platform/files/common/files'; import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration'; @@ -34,7 +35,9 @@ import { TextModelResolverService } from 'vs/workbench/services/textmodelResolve import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { mkdirp } from 'vs/base/node/pfs'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { CommandService } from 'vs/workbench/services/commands/common/commandService'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -55,7 +58,7 @@ suite('ConfigurationEditingService', () => { let workspaceSettingsDir; suiteSetup(() => { - const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ 'id': '_test', 'type': 'object', @@ -103,9 +106,10 @@ suite('ConfigurationEditingService', () => { instantiationService.stub(IWorkspaceContextService, workspaceService); return workspaceService.initialize(noWorkspace ? {} as IWindowConfiguration : workspaceDir).then(() => { instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(IFileService, new FileService(workspaceService, TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), { disableWatcher: true })); + instantiationService.stub(IFileService, new FileService(workspaceService, TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true })); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + instantiationService.stub(ICommandService, CommandService); testObject = instantiationService.createInstance(ConfigurationEditingService); }); } @@ -138,34 +142,34 @@ suite('ConfigurationEditingService', () => { test('errors cases - invalid key', () => { return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' }) .then(() => assert.fail('Should fail with ERROR_UNKNOWN_KEY'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY)); + (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY)); }); test('errors cases - invalid target', () => { return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' }) .then(() => assert.fail('Should fail with ERROR_INVALID_TARGET'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET)); + (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET)); }); test('errors cases - no workspace', () => { return setUpServices(true) .then(() => testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' })) .then(() => assert.fail('Should fail with ERROR_NO_WORKSPACE_OPENED'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED)); + (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED)); }); test('errors cases - invalid configuration', () => { fs.writeFileSync(globalSettingsFile, ',,,,,,,,,,,,,,'); return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) .then(() => assert.fail('Should fail with ERROR_INVALID_CONFIGURATION'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION)); + (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION)); }); test('errors cases - dirty', () => { instantiationService.stub(ITextFileService, 'isDirty', true); return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }) .then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'), - (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY)); + (error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY)); }); test('dirty error is not thrown if not asked to save', () => { @@ -177,13 +181,13 @@ suite('ConfigurationEditingService', () => { test('do not notify error', () => { instantiationService.stub(ITextFileService, 'isDirty', true); const target = sinon.stub(); - instantiationService.stubPromise(IChoiceService, 'choose', target); + instantiationService.stub(INotificationService, { prompt: target, _serviceBrand: null, notify: null, error: null, info: null, warn: null }); return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true }) .then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'), - (error: ConfigurationEditingError) => { - assert.equal(false, target.calledOnce); - assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY); - }); + (error: ConfigurationEditingError) => { + assert.equal(false, target.calledOnce); + assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY); + }); }); test('write one setting - empty file', () => { diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts similarity index 87% rename from src/vs/workbench/services/configuration/test/node/configurationService.test.ts rename to src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 9ae1c4617a..4adb45f640 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -16,16 +16,17 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { parseArgs } from 'vs/platform/environment/node/argv'; -import extfs = require('vs/base/node/extfs'); -import uuid = require('vs/base/common/uuid'); +import * as pfs from 'vs/base/node/pfs'; +import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService'; import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService'; -import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget, IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; -import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService, TestLifecycleService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices'; -import { FileService } from 'vs/workbench/services/files/node/fileService'; +import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -34,7 +35,6 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { mkdirp } from 'vs/base/node/pfs'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -55,7 +55,7 @@ function setUpFolder(folderName: string, parentDir: string): TPromise { const folderDir = path.join(parentDir, folderName); // {{SQL CARBON EDIT}} const workspaceSettingsDir = path.join(folderDir, '.sqlops'); - return mkdirp(workspaceSettingsDir, 493).then(() => folderDir); + return pfs.mkdirp(workspaceSettingsDir, 493).then(() => folderDir); } function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, configPath: string }> { @@ -63,7 +63,7 @@ function setUpWorkspace(folders: string[]): TPromise<{ parentDir: string, config const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); - return mkdirp(parentDir, 493) + return pfs.mkdirp(parentDir, 493) .then(() => { const configPath = path.join(parentDir, 'vsctests.code-workspace'); const workspace = { folders: folders.map(path => ({ path })) }; diff --git a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts index 6085a7e3bf..157b418add 100644 --- a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts @@ -16,6 +16,6 @@ export interface IConfigurationResolverService { resolve(root: IWorkspaceFolder, value: string): string; resolve(root: IWorkspaceFolder, value: string[]): string[]; resolve(root: IWorkspaceFolder, value: IStringDictionary): IStringDictionary; - resolveAny(root: IWorkspaceFolder, value: T): T; - resolveInteractiveVariables(configuration: any, interactiveVariablesMap: { [key: string]: string }): TPromise; + resolveAny(root: IWorkspaceFolder, value: T, commandMapping?: IStringDictionary): T; + executeCommandVariables(value: any, variables: IStringDictionary): TPromise>; } diff --git a/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts index 9c664f6a69..75a3f239a4 100644 --- a/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts @@ -3,10 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import uri from 'vs/base/common/uri'; import * as paths from 'vs/base/common/paths'; -import * as types from 'vs/base/common/types'; +import { Schemas } from 'vs/base/common/network'; import { TPromise } from 'vs/base/common/winjs.base'; import { sequence } from 'vs/base/common/async'; +import { toResource } from 'vs/workbench/common/editor'; import { IStringDictionary } from 'vs/base/common/collections'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -14,159 +16,11 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { toResource } from 'vs/workbench/common/editor'; -import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { IProcessEnvironment } from 'vs/base/common/platform'; +import { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { relative } from 'path'; -import { IProcessEnvironment, isWindows } from 'vs/base/common/platform'; -import { normalizeDriveLetter } from 'vs/base/common/labels'; -import { Schemas } from 'vs/base/common/network'; +import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; -class VariableResolver { - static VARIABLE_REGEXP = /\$\{(.*?)\}/g; - private envVariables: IProcessEnvironment; - - constructor( - envVariables: IProcessEnvironment, - private configurationService: IConfigurationService, - private editorService: IWorkbenchEditorService, - private environmentService: IEnvironmentService, - private workspaceContextService: IWorkspaceContextService - ) { - if (isWindows) { - this.envVariables = Object.create(null); - Object.keys(envVariables).forEach(key => { - this.envVariables[key.toLowerCase()] = envVariables[key]; - }); - } else { - this.envVariables = envVariables; - } - } - - resolve(context: IWorkspaceFolder, value: string): string { - const filePath = this.getFilePath(); - return value.replace(VariableResolver.VARIABLE_REGEXP, (match: string, variable: string) => { - const parts = variable.split(':'); - let sufix: string; - if (parts && parts.length > 1) { - variable = parts[0]; - sufix = parts[1]; - } - - switch (variable) { - case 'env': { - if (sufix) { - if (isWindows) { - sufix = sufix.toLowerCase(); - } - - const env = this.envVariables[sufix]; - if (types.isString(env)) { - return env; - } - } - } - case 'config': { - if (sufix) { - const config = this.configurationService.getValue(sufix, context ? { resource: context.uri } : undefined); - if (!types.isUndefinedOrNull(config) && !types.isObject(config)) { - return config; - } - } - } - default: { - if (sufix) { - const folder = this.workspaceContextService.getWorkspace().folders.filter(f => f.name === sufix).pop(); - if (folder) { - context = folder; - } - } - - switch (variable) { - case 'workspaceRoot': - case 'workspaceFolder': - return context ? normalizeDriveLetter(context.uri.fsPath) : match; - case 'cwd': - return context ? normalizeDriveLetter(context.uri.fsPath) : process.cwd(); - case 'workspaceRootFolderName': - case 'workspaceFolderBasename': - return context ? paths.basename(context.uri.fsPath) : match; - case 'lineNumber': - return this.getLineNumber() || match; - case 'selectedText': - return this.getSelectedText() || match; - case 'file': - return filePath || match; - case 'relativeFile': - return context ? paths.normalize(relative(context.uri.fsPath, filePath)) : filePath || match; - case 'fileDirname': - return filePath ? paths.dirname(filePath) : match; - case 'fileExtname': - return filePath ? paths.extname(filePath) : match; - case 'fileBasename': - return filePath ? paths.basename(filePath) : match; - case 'fileBasenameNoExtension': { - if (!filePath) { - return match; - } - - const basename = paths.basename(filePath); - return basename.slice(0, basename.length - paths.extname(basename).length); - } - case 'execPath': - return this.environmentService.execPath; - - default: - return match; - } - } - } - }); - } - - private getSelectedText(): string { - const activeEditor = this.editorService.getActiveEditor(); - if (activeEditor) { - const editorControl = (activeEditor.getControl()); - if (editorControl) { - const editorModel = editorControl.getModel(); - const editorSelection = editorControl.getSelection(); - if (editorModel && editorSelection) { - return editorModel.getValueInRange(editorSelection); - } - } - } - - return undefined; - } - - private getFilePath(): string { - let input = this.editorService.getActiveEditorInput(); - if (input instanceof DiffEditorInput) { - input = input.modifiedInput; - } - - const fileResource = toResource(input, { filter: Schemas.file }); - if (!fileResource) { - return undefined; - } - - return paths.normalize(fileResource.fsPath, true); - } - - private getLineNumber(): string { - const activeEditor = this.editorService.getActiveEditor(); - if (activeEditor) { - const editorControl = (activeEditor.getControl()); - if (editorControl) { - const lineNumber = editorControl.getSelection().positionLineNumber; - return String(lineNumber); - } - } - - return undefined; - } -} export class ConfigurationResolverService implements IConfigurationResolverService { _serviceBrand: any; @@ -180,78 +34,112 @@ export class ConfigurationResolverService implements IConfigurationResolverServi @ICommandService private commandService: ICommandService, @IWorkspaceContextService workspaceContextService: IWorkspaceContextService ) { - this.resolver = new VariableResolver(envVariables, configurationService, editorService, environmentService, workspaceContextService); + this.resolver = new VariableResolver({ + getFolderUri: (folderName: string): uri => { + const folder = workspaceContextService.getWorkspace().folders.filter(f => f.name === folderName).pop(); + return folder ? folder.uri : undefined; + }, + getWorkspaceFolderCount: (): number => { + return workspaceContextService.getWorkspace().folders.length; + }, + getConfigurationValue: (folderUri: uri, suffix: string) => { + return configurationService.getValue(suffix, folderUri ? { resource: folderUri } : undefined); + }, + getExecPath: () => { + return environmentService['execPath']; + }, + getFilePath: (): string | undefined => { + let input = editorService.getActiveEditorInput(); + if (input instanceof DiffEditorInput) { + input = input.modifiedInput; + } + const fileResource = toResource(input, { filter: Schemas.file }); + if (!fileResource) { + return undefined; + } + return paths.normalize(fileResource.fsPath, true); + }, + getSelectedText: (): string | undefined => { + const activeEditor = editorService.getActiveEditor(); + if (activeEditor) { + const editorControl = (activeEditor.getControl()); + if (editorControl) { + const editorModel = editorControl.getModel(); + const editorSelection = editorControl.getSelection(); + if (editorModel && editorSelection) { + return editorModel.getValueInRange(editorSelection); + } + } + } + return undefined; + }, + getLineNumber: (): string => { + const activeEditor = editorService.getActiveEditor(); + if (activeEditor) { + const editorControl = (activeEditor.getControl()); + if (editorControl) { + const lineNumber = editorControl.getSelection().positionLineNumber; + return String(lineNumber); + } + } + return undefined; + } + }, envVariables); } public resolve(root: IWorkspaceFolder, value: string): string; public resolve(root: IWorkspaceFolder, value: string[]): string[]; public resolve(root: IWorkspaceFolder, value: IStringDictionary): IStringDictionary; public resolve(root: IWorkspaceFolder, value: any): any { - if (types.isString(value)) { - return this.resolver.resolve(root, value); - } else if (types.isArray(value)) { - return value.map(s => this.resolver.resolve(root, s)); - } else if (types.isObject(value)) { - let result: IStringDictionary | string[]> = Object.create(null); - Object.keys(value).forEach(key => { - result[key] = this.resolve(root, value[key]); - }); - - return result; - } - return value; + return this.resolver.resolveAny(root ? root.uri : undefined, value); } - public resolveAny(root: IWorkspaceFolder, value: any): any { - if (types.isString(value)) { - return this.resolver.resolve(root, value); - } else if (types.isArray(value)) { - return value.map(s => this.resolveAny(root, s)); - } else if (types.isObject(value)) { - let result: IStringDictionary | string[]> = Object.create(null); - Object.keys(value).forEach(key => { - result[key] = this.resolveAny(root, value[key]); - }); - - return result; - } - return value; + public resolveAny(root: IWorkspaceFolder, value: any, commandValueMapping?: IStringDictionary): any { + return this.resolver.resolveAny(root ? root.uri : undefined, value, commandValueMapping); } /** - * Resolve all interactive variables in configuration #6569 + * Finds and executes all command variables (see #6569) */ - public resolveInteractiveVariables(configuration: any, interactiveVariablesMap: { [key: string]: string }): TPromise { + public executeCommandVariables(configuration: any, variableToCommandMap: IStringDictionary): TPromise> { + if (!configuration) { return TPromise.as(null); } - // We need a map from interactive variables to keys because we only want to trigger an command once per key - - // even though it might occur multiple times in configuration #7026. - const interactiveVariablesToSubstitutes: { [interactiveVariable: string]: { object: any, key: string }[] } = Object.create(null); - const findInteractiveVariables = (object: any) => { + // use an array to preserve order of first appearance + const commands: string[] = []; + + const cmd_var = /\${command:(.*?)}/g; + + const findCommandVariables = (object: any) => { Object.keys(object).forEach(key => { - if (object[key] && typeof object[key] === 'object') { - findInteractiveVariables(object[key]); - } else if (typeof object[key] === 'string') { - const matches = /\${command:(.+)}/.exec(object[key]); - if (matches && matches.length === 2) { - const interactiveVariable = matches[1]; - if (!interactiveVariablesToSubstitutes[interactiveVariable]) { - interactiveVariablesToSubstitutes[interactiveVariable] = []; + const value = object[key]; + if (value && typeof value === 'object') { + findCommandVariables(value); + } else if (typeof value === 'string') { + let matches; + while ((matches = cmd_var.exec(value)) !== null) { + if (matches.length === 2) { + const command = matches[1]; + if (commands.indexOf(command) < 0) { + commands.push(command); + } } - interactiveVariablesToSubstitutes[interactiveVariable].push({ object, key }); } } }); }; - findInteractiveVariables(configuration); - let substitionCanceled = false; - const factory: { (): TPromise }[] = Object.keys(interactiveVariablesToSubstitutes).map(interactiveVariable => { + findCommandVariables(configuration); + + let cancelled = false; + const commandValueMapping: IStringDictionary = Object.create(null); + + const factory: { (): TPromise }[] = commands.map(interactiveVariable => { return () => { - let commandId: string = null; - commandId = interactiveVariablesMap ? interactiveVariablesMap[interactiveVariable] : null; + + let commandId = variableToCommandMap ? variableToCommandMap[interactiveVariable] : null; if (!commandId) { // Just launch any command if the interactive variable is not contributed by the adapter #12735 commandId = interactiveVariable; @@ -259,18 +147,14 @@ export class ConfigurationResolverService implements IConfigurationResolverServi return this.commandService.executeCommand(commandId, configuration).then(result => { if (result) { - interactiveVariablesToSubstitutes[interactiveVariable].forEach(substitute => { - if (substitute.object[substitute.key].indexOf(`\${command:${interactiveVariable}}`) >= 0) { - substitute.object[substitute.key] = substitute.object[substitute.key].replace(`\${command:${interactiveVariable}}`, result); - } - }); + commandValueMapping[interactiveVariable] = result; } else { - substitionCanceled = true; + cancelled = true; } }); }; }); - return sequence(factory).then(() => substitionCanceled ? null : configuration); + return sequence(factory).then(() => cancelled ? null : commandValueMapping); } } diff --git a/src/vs/workbench/services/configurationResolver/node/variableResolver.ts b/src/vs/workbench/services/configurationResolver/node/variableResolver.ts new file mode 100644 index 0000000000..ce13951a4f --- /dev/null +++ b/src/vs/workbench/services/configurationResolver/node/variableResolver.ts @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as paths from 'vs/base/common/paths'; +import * as types from 'vs/base/common/types'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { relative } from 'path'; +import { IProcessEnvironment, isWindows } from 'vs/base/common/platform'; +import { normalizeDriveLetter } from 'vs/base/common/labels'; +import { localize } from 'vs/nls'; +import uri from 'vs/base/common/uri'; + +export interface IVariableAccessor { + getFolderUri(folderName: string): uri | undefined; + getWorkspaceFolderCount(): number; + getConfigurationValue(folderUri: uri, section: string): string | undefined; + getExecPath(): string | undefined; + getFilePath(): string | undefined; + getSelectedText(): string | undefined; + getLineNumber(): string; +} + +export class VariableResolver { + + static VARIABLE_REGEXP = /\$\{(.*?)\}/g; + + private envVariables: IProcessEnvironment; + + constructor( + private accessor: IVariableAccessor, + envVariables: IProcessEnvironment + ) { + if (isWindows) { + this.envVariables = Object.create(null); + Object.keys(envVariables).forEach(key => { + this.envVariables[key.toLowerCase()] = envVariables[key]; + }); + } else { + this.envVariables = envVariables; + } + } + + resolveAny(folderUri: uri, value: any, commandValueMapping?: IStringDictionary): any { + if (types.isString(value)) { + return this.resolve(folderUri, value, commandValueMapping); + } else if (types.isArray(value)) { + return value.map(s => this.resolveAny(folderUri, s, commandValueMapping)); + } else if (types.isObject(value)) { + let result: IStringDictionary | string[]> = Object.create(null); + Object.keys(value).forEach(key => { + result[key] = this.resolveAny(folderUri, value[key], commandValueMapping); + }); + return result; + } + return value; + } + + resolve(folderUri: uri, value: string, commandValueMapping: IStringDictionary): string { + + const filePath = this.accessor.getFilePath(); + + return value.replace(VariableResolver.VARIABLE_REGEXP, (match: string, variable: string) => { + + let argument: string; + const parts = variable.split(':'); + if (parts && parts.length > 1) { + variable = parts[0]; + argument = parts[1]; + } + + switch (variable) { + + case 'env': + if (argument) { + if (isWindows) { + argument = argument.toLowerCase(); + } + const env = this.envVariables[argument]; + if (types.isString(env)) { + return env; + } + // For `env` we should do the same as a normal shell does - evaluates missing envs to an empty string #46436 + return ''; + } + throw new Error(localize('missingEnvVarName', "'{0}' can not be resolved because no environment variable name is given.", match)); + + case 'config': + if (argument) { + const config = this.accessor.getConfigurationValue(folderUri, argument); + if (types.isUndefinedOrNull(config)) { + throw new Error(localize('configNotFound', "'{0}' can not be resolved because setting '{1}' not found.", match, argument)); + } + if (types.isObject(config)) { + throw new Error(localize('configNoString', "'{0}' can not be resolved because '{1}' is a structured value.", match, argument)); + } + return config; + } + throw new Error(localize('missingConfigName', "'{0}' can not be resolved because no settings name is given.", match)); + + case 'command': + if (argument && commandValueMapping) { + const v = commandValueMapping[argument]; + if (typeof v === 'string') { + return v; + } + throw new Error(localize('noValueForCommand', "'{0}' can not be resolved because the command has no value.", match)); + } + return match; + + default: { + + // common error handling for all variables that require an open folder and accept a folder name argument + switch (variable) { + case 'workspaceRoot': + case 'workspaceFolder': + case 'workspaceRootFolderName': + case 'workspaceFolderBasename': + case 'relativeFile': + if (argument) { + const folder = this.accessor.getFolderUri(argument); + if (folder) { + folderUri = folder; + } else { + throw new Error(localize('canNotFindFolder', "'{0}' can not be resolved. No such folder '{1}'.", match, argument)); + } + } + if (!folderUri) { + if (this.accessor.getWorkspaceFolderCount() > 1) { + throw new Error(localize('canNotResolveWorkspaceFolderMultiRoot', "'{0}' can not be resolved in a multi folder workspace. Scope this variable using ':' and a workspace folder name.", match)); + } + throw new Error(localize('canNotResolveWorkspaceFolder', "'{0}' can not be resolved. Please open a folder.", match)); + } + break; + default: + break; + } + + // common error handling for all variables that require an open file + switch (variable) { + case 'file': + case 'relativeFile': + case 'fileDirname': + case 'fileExtname': + case 'fileBasename': + case 'fileBasenameNoExtension': + if (!filePath) { + throw new Error(localize('canNotResolveFile', "'{0}' can not be resolved. Please open an editor.", match)); + } + break; + default: + break; + } + + switch (variable) { + case 'workspaceRoot': + case 'workspaceFolder': + return normalizeDriveLetter(folderUri.fsPath); + + case 'cwd': + return folderUri ? normalizeDriveLetter(folderUri.fsPath) : process.cwd(); + + case 'workspaceRootFolderName': + case 'workspaceFolderBasename': + return paths.basename(folderUri.fsPath); + + case 'lineNumber': + const lineNumber = this.accessor.getLineNumber(); + if (lineNumber) { + return lineNumber; + } + throw new Error(localize('canNotResolveLineNumber', "'{0}' can not be resolved. Make sure to have a line selected in the active editor.", match)); + + case 'selectedText': + const selectedText = this.accessor.getSelectedText(); + if (selectedText) { + return selectedText; + } + throw new Error(localize('canNotResolveSelectedText', "'{0}' can not be resolved. Make sure to have some text selected in the active editor.", match)); + + case 'file': + return filePath; + + case 'relativeFile': + if (folderUri) { + return paths.normalize(relative(folderUri.fsPath, filePath)); + } + return filePath; + + case 'fileDirname': + return paths.dirname(filePath); + + case 'fileExtname': + return paths.extname(filePath); + + case 'fileBasename': + return paths.basename(filePath); + + case 'fileBasenameNoExtension': + const basename = paths.basename(filePath); + return basename.slice(0, basename.length - paths.extname(basename).length); + + case 'execPath': + const ep = this.accessor.getExecPath(); + if (ep) { + return ep; + } + return match; + + default: + return match; + } + } + } + }); + } +} diff --git a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts index 17e06b0ed9..62e9ecb904 100644 --- a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts @@ -3,9 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import assert = require('assert'); +import * as assert from 'assert'; import uri from 'vs/base/common/uri'; -import platform = require('vs/base/common/platform'); +import * as platform from 'vs/base/common/platform'; import { TPromise } from 'vs/base/common/winjs.base'; import { IConfigurationService, getConfigurationValue, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -86,7 +86,7 @@ suite('Configuration Resolver Service', () => { if (platform.isWindows) { assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - Value for key1'); } else { - assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - ${env:Key1}'); + assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - '); } }); @@ -196,18 +196,6 @@ suite('Configuration Resolver Service', () => { assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz'); }); - test('configuration should not evaluate Javascript', () => { - let configurationService: IConfigurationService; - configurationService = new MockConfigurationService({ - editor: { - abc: 'foo' - } - }); - - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc ${config:editor[\'abc\'.substr(0)]} xyz'); - }); - test('uses original variable as fallback', () => { let configurationService: IConfigurationService; configurationService = new MockConfigurationService({ @@ -215,10 +203,8 @@ suite('Configuration Resolver Service', () => { }); let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); - assert.strictEqual(service.resolve(workspace, 'abc ${invalidVariable} xyz'), 'abc ${invalidVariable} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${env:invalidVariable} xyz'), 'abc ${env:invalidVariable} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc.def} xyz'), 'abc ${config:editor.abc.def} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:panel.abc} xyz'), 'abc ${config:panel.abc} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${unknownVariable} xyz'), 'abc ${unknownVariable} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${env:unknownVariable} xyz'), 'abc xyz'); }); test('configuration variables with invalid accessor', () => { @@ -230,9 +216,14 @@ suite('Configuration Resolver Service', () => { }); let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); - assert.strictEqual(service.resolve(workspace, 'abc ${config:} xyz'), 'abc ${config:} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz'), 'abc ${config:editor..fontFamily} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.none.none2} xyz'), 'abc ${config:editor.none.none2} xyz'); + + assert.throws(() => service.resolve(workspace, 'abc ${env} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${env:} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${config} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${config:} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${config:editor} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz')); + assert.throws(() => service.resolve(workspace, 'abc ${config:editor.none.none2} xyz')); }); test('interactive variable simple', () => { @@ -249,8 +240,11 @@ suite('Configuration Resolver Service', () => { interactiveVariables['interactiveVariable1'] = 'command1'; interactiveVariables['interactiveVariable2'] = 'command2'; - configurationResolverService.resolveInteractiveVariables(configuration, interactiveVariables).then(resolved => { - assert.deepEqual(resolved, { + configurationResolverService.executeCommandVariables(configuration, interactiveVariables).then(mapping => { + + const result = configurationResolverService.resolveAny(undefined, configuration, mapping); + + assert.deepEqual(result, { 'name': 'Attach to Process', 'type': 'node', 'request': 'attach', @@ -281,8 +275,11 @@ suite('Configuration Resolver Service', () => { interactiveVariables['interactiveVariable1'] = 'command1'; interactiveVariables['interactiveVariable2'] = 'command2'; - configurationResolverService.resolveInteractiveVariables(configuration, interactiveVariables).then(resolved => { - assert.deepEqual(resolved, { + configurationResolverService.executeCommandVariables(configuration, interactiveVariables).then(mapping => { + + const result = configurationResolverService.resolveAny(undefined, configuration, mapping); + + assert.deepEqual(result, { 'name': 'Attach to Process', 'type': 'node', 'request': 'attach', diff --git a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts index ddc9d41b83..e6a7a169eb 100644 --- a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts @@ -8,14 +8,14 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; -import dom = require('vs/base/browser/dom'); +import * as dom from 'vs/base/browser/dom'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { remote, webFrame } from 'electron'; import { unmnemonicLabel } from 'vs/base/common/labels'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IContextMenuDelegate, ContextSubMenu, IEvent } from 'vs/base/browser/contextmenu'; diff --git a/src/vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts b/src/vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts index 9e208c7888..a7dbdcf30f 100644 --- a/src/vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts +++ b/src/vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import { assign, deepClone } from 'vs/base/common/objects'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -27,7 +27,7 @@ export interface ICrashReporterConfig { enableCrashReporter: boolean; } -const configurationRegistry = Registry.as(Extensions.Configuration); +const configurationRegistry = Registry.as(Extensions.Configuration); configurationRegistry.registerConfiguration({ 'id': TELEMETRY_SECTION_ID, 'order': 110, @@ -119,7 +119,7 @@ export class CrashReporterService implements ICrashReporterService { // Experimental crash reporting support for child processes on Mac only for now if (this.isEnabled && isMacintosh) { const childProcessOptions = deepClone(this.options); - childProcessOptions.extra.processName = name; + (childProcessOptions.extra).processName = name; childProcessOptions.crashesDirectory = os.tmpdir(); return childProcessOptions; diff --git a/src/vs/workbench/services/decorations/browser/decorations.ts b/src/vs/workbench/services/decorations/browser/decorations.ts index c73c916eb0..f12c9864b6 100644 --- a/src/vs/workbench/services/decorations/browser/decorations.ts +++ b/src/vs/workbench/services/decorations/browser/decorations.ts @@ -6,9 +6,10 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import URI from 'vs/base/common/uri'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { TPromise } from 'vs/base/common/winjs.base'; export const IDecorationsService = createDecorator('IFileDecorationsService'); @@ -31,7 +32,7 @@ export interface IDecoration { export interface IDecorationsProvider { readonly label: string; readonly onDidChange: Event; - provideDecorations(uri: URI): IDecorationData | Thenable; + provideDecorations(uri: URI): IDecorationData | TPromise; } export interface IResourceDecorationChangeEvent { diff --git a/src/vs/workbench/services/decorations/browser/decorationsService.ts b/src/vs/workbench/services/decorations/browser/decorationsService.ts index c27b22406f..25bd3eeb53 100644 --- a/src/vs/workbench/services/decorations/browser/decorationsService.ts +++ b/src/vs/workbench/services/decorations/browser/decorationsService.ts @@ -5,7 +5,7 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import Event, { Emitter, debounceEvent, anyEvent } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent, anyEvent } from 'vs/base/common/event'; import { IDecorationsService, IDecoration, IResourceDecorationChangeEvent, IDecorationsProvider, IDecorationData } from './decorations'; import { TernarySearchTree } from 'vs/base/common/map'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -17,6 +17,8 @@ import { IdGenerator } from 'vs/base/common/idGenerator'; import { IIterator } from 'vs/base/common/iterator'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { localize } from 'vs/nls'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { isPromiseCanceledError } from 'vs/base/common/errors'; class DecorationRule { @@ -229,7 +231,7 @@ class FileDecorationChangeEvent implements IResourceDecorationChangeEvent { class DecorationProviderWrapper { - readonly data = TernarySearchTree.forPaths | IDecorationData>(); + readonly data = TernarySearchTree.forPaths | IDecorationData>(); private readonly _dispoable: IDisposable; constructor( @@ -245,6 +247,9 @@ class DecorationProviderWrapper { } else { // selective changes -> drop for resource, fetch again, send event + // perf: the map stores thenables, decorations, or `null`-markers. + // we make us of that and ignore all uris in which we have never + // been interested. for (const uri of uris) { this._fetchData(uri); } @@ -295,6 +300,13 @@ class DecorationProviderWrapper { private _fetchData(uri: URI): IDecorationData { + // check for pending request and cancel it + const pendingRequest = this.data.get(uri.toString()); + if (TPromise.is(pendingRequest)) { + pendingRequest.cancel(); + this.data.delete(uri.toString()); + } + const dataOrThenable = this._provider.provideDecorations(uri); if (!isThenable(dataOrThenable)) { // sync -> we have a result now @@ -302,10 +314,17 @@ class DecorationProviderWrapper { } else { // async -> we have a result soon - const request = Promise.resolve(dataOrThenable) - .then(data => this._keepItem(uri, data)) - .catch(_ => this.data.delete(uri.toString())); + const request = TPromise.wrap(dataOrThenable).then(data => { + if (this.data.get(uri.toString()) === request) { + this._keepItem(uri, data); + } + }, err => { + if (!isPromiseCanceledError(err) && this.data.get(uri.toString()) === request) { + this.data.delete(uri.toString()); + } + }); + // {{ SQL CARBON EDIT }} - Add type assertion to fix build break this.data.set(uri.toString(), request); return undefined; } @@ -363,6 +382,8 @@ export class FileDecorationsService implements IDecorationsService { dispose(): void { dispose(this._disposables); + dispose(this._onDidChangeDecorations); + dispose(this._onDidChangeDecorationsDelayed); } registerDecorationsProvider(provider: IDecorationsProvider): IDisposable { diff --git a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts index af8562438e..63e4b6801b 100644 --- a/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts +++ b/src/vs/workbench/services/decorations/test/browser/decorationsService.test.ts @@ -9,8 +9,9 @@ import * as assert from 'assert'; import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService'; import { IDecorationsProvider, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; import URI from 'vs/base/common/uri'; -import Event, { toPromise } from 'vs/base/common/event'; +import { Event, toPromise, Emitter } from 'vs/base/common/event'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; +import { TPromise } from 'vs/base/common/winjs.base'; suite('DecorationsService', function () { @@ -33,7 +34,7 @@ suite('DecorationsService', function () { readonly onDidChange: Event = Event.None; provideDecorations(uri: URI) { callCounter += 1; - return new Promise(resolve => { + return new TPromise(resolve => { setTimeout(() => resolve({ color: 'someBlue', tooltip: 'T' @@ -75,7 +76,7 @@ suite('DecorationsService', function () { assert.equal(callCounter, 1); }); - test('Clear decorations on provider dispose', function () { + test('Clear decorations on provider dispose', async function () { let uri = URI.parse('foo:bar'); let callCounter = 0; @@ -94,13 +95,14 @@ suite('DecorationsService', function () { // un-register -> ensure good event let didSeeEvent = false; - service.onDidChangeDecorations(e => { + let p = toPromise(service.onDidChangeDecorations).then(e => { assert.equal(e.affectsResource(uri), true); assert.deepEqual(service.getDecoration(uri, false), undefined); assert.equal(callCounter, 1); didSeeEvent = true; }); reg.dispose(); + await p; assert.equal(didSeeEvent, true); }); @@ -168,4 +170,42 @@ suite('DecorationsService', function () { reg.dispose(); }); + + test('Decorations not showing up for second root folder #48502', async function () { + + let cancelCount = 0; + let callCount = 0; + + let provider = new class implements IDecorationsProvider { + + _onDidChange = new Emitter(); + onDidChange: Event = this._onDidChange.event; + + label: string = 'foo'; + + provideDecorations(uri): TPromise { + return new TPromise(resolve => { + callCount += 1; + setTimeout(() => { + resolve({ letter: 'foo' }); + }, 10); + }, () => { + cancelCount += 1; + }); + } + }; + + let reg = service.registerDecorationsProvider(provider); + + const uri = URI.parse('foo://bar'); + service.getDecoration(uri, false); + + provider._onDidChange.fire([uri]); + service.getDecoration(uri, false); + + assert.equal(cancelCount, 1); + assert.equal(callCount, 2); + + reg.dispose(); + }); }); diff --git a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts new file mode 100644 index 0000000000..0365d1ca50 --- /dev/null +++ b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts @@ -0,0 +1,144 @@ +/*--------------------------------------------------------------------------------------------- + * 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 nls from 'vs/nls'; +import product from 'vs/platform/node/product'; +import { TPromise } from 'vs/base/common/winjs.base'; +import Severity from 'vs/base/common/severity'; +import { isLinux, isWindows } from 'vs/base/common/platform'; +import { IWindowService } from 'vs/platform/windows/common/windows'; +import { mnemonicButtonLabel } from 'vs/base/common/labels'; +import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions } from 'vs/platform/dialogs/common/dialogs'; + +interface IMassagedMessageBoxOptions { + + /** + * OS massaged message box options. + */ + options: Electron.MessageBoxOptions; + + /** + * Since the massaged result of the message box options potentially + * changes the order of buttons, we have to keep a map of these + * changes so that we can still return the correct index to the caller. + */ + buttonIndexMap: number[]; +} + +export class DialogService implements IDialogService { + + public _serviceBrand: any; + + constructor( + @IWindowService private windowService: IWindowService + ) { + } + + public confirm(confirmation: IConfirmation): TPromise { + const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation)); + + return this.windowService.showMessageBox(options).then(result => { + return { + confirmed: buttonIndexMap[result.button] === 0 ? true : false, + checkboxChecked: result.checkboxChecked + } as IConfirmationResult; + }); + } + + private getConfirmOptions(confirmation: IConfirmation): Electron.MessageBoxOptions { + const buttons: string[] = []; + if (confirmation.primaryButton) { + buttons.push(confirmation.primaryButton); + } else { + buttons.push(nls.localize({ key: 'yesButton', comment: ['&& denotes a mnemonic'] }, "&&Yes")); + } + + if (confirmation.secondaryButton) { + buttons.push(confirmation.secondaryButton); + } else if (typeof confirmation.secondaryButton === 'undefined') { + buttons.push(nls.localize('cancelButton', "Cancel")); + } + + const opts: Electron.MessageBoxOptions = { + title: confirmation.title, + message: confirmation.message, + buttons, + cancelId: 1 + }; + + if (confirmation.detail) { + opts.detail = confirmation.detail; + } + + if (confirmation.type) { + opts.type = confirmation.type; + } + + if (confirmation.checkbox) { + opts.checkboxLabel = confirmation.checkbox.label; + opts.checkboxChecked = confirmation.checkbox.checked; + } + + return opts; + } + + public show(severity: Severity, message: string, buttons: string[], dialogOptions?: IDialogOptions): TPromise { + const { options, buttonIndexMap } = this.massageMessageBoxOptions({ + message, + buttons, + type: (severity === Severity.Info) ? 'question' : (severity === Severity.Error) ? 'error' : (severity === Severity.Warning) ? 'warning' : 'none', + cancelId: dialogOptions ? dialogOptions.cancelId : void 0, + detail: dialogOptions ? dialogOptions.detail : void 0 + }); + + return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button]); + } + + private massageMessageBoxOptions(options: Electron.MessageBoxOptions): IMassagedMessageBoxOptions { + let buttonIndexMap = options.buttons.map((button, index) => index); + let buttons = options.buttons.map(button => mnemonicButtonLabel(button)); + let cancelId = options.cancelId; + + // Linux: order of buttons is reverse + // macOS: also reverse, but the OS handles this for us! + if (isLinux) { + buttons = buttons.reverse(); + buttonIndexMap = buttonIndexMap.reverse(); + } + + // Default Button (always first one) + options.defaultId = buttonIndexMap[0]; + + // Cancel Button + if (typeof cancelId === 'number') { + + // Ensure the cancelId is the correct one from our mapping + cancelId = buttonIndexMap[cancelId]; + + // macOS/Linux: the cancel button should always be to the left of the primary action + // if we see more than 2 buttons, move the cancel one to the left of the primary + if (!isWindows && buttons.length > 2 && cancelId !== 1) { + const cancelButton = buttons[cancelId]; + buttons.splice(cancelId, 1); + buttons.splice(1, 0, cancelButton); + + const cancelButtonIndex = buttonIndexMap[cancelId]; + buttonIndexMap.splice(cancelId, 1); + buttonIndexMap.splice(1, 0, cancelButtonIndex); + + cancelId = 1; + } + } + + options.buttons = buttons; + options.cancelId = cancelId; + options.noLink = true; + options.title = options.title || product.nameLong; + + return { options, buttonIndexMap }; + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/dialogs/electron-browser/dialogs.ts b/src/vs/workbench/services/dialogs/electron-browser/dialogs.ts deleted file mode 100644 index 24c9d2b788..0000000000 --- a/src/vs/workbench/services/dialogs/electron-browser/dialogs.ts +++ /dev/null @@ -1,241 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 nls = require('vs/nls'); -import product from 'vs/platform/node/product'; -import { TPromise } from 'vs/base/common/winjs.base'; -import Severity from 'vs/base/common/severity'; -import { isLinux, isMacintosh } from 'vs/base/common/platform'; -import { Action } from 'vs/base/common/actions'; -import { IWindowService } from 'vs/platform/windows/common/windows'; -import { mnemonicButtonLabel } from 'vs/base/common/labels'; -import { IConfirmationService, IChoiceService, IConfirmation, IConfirmationResult, Choice } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotificationHandle, INotificationActions } from 'vs/platform/notification/common/notification'; -import { once } from 'vs/base/common/event'; -import URI from 'vs/base/common/uri'; -import { basename } from 'vs/base/common/paths'; - -interface IMassagedMessageBoxOptions { - - /** - * OS massaged message box options. - */ - options: Electron.MessageBoxOptions; - - /** - * Since the massaged result of the message box options potentially - * changes the order of buttons, we have to keep a map of these - * changes so that we can still return the correct index to the caller. - */ - buttonIndexMap: number[]; -} - -export class DialogService implements IChoiceService, IConfirmationService { - - public _serviceBrand: any; - - constructor( - @IWindowService private windowService: IWindowService, - @INotificationService private notificationService: INotificationService - ) { - } - - public confirmWithCheckbox(confirmation: IConfirmation): TPromise { - const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation)); - - return this.windowService.showMessageBox(options).then(result => { - return { - confirmed: buttonIndexMap[result.button] === 0 ? true : false, - checkboxChecked: result.checkboxChecked - } as IConfirmationResult; - }); - } - - public confirm(confirmation: IConfirmation): TPromise { - const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation)); - - return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button] === 0 ? true : false); - } - - private getConfirmOptions(confirmation: IConfirmation): Electron.MessageBoxOptions { - const buttons: string[] = []; - if (confirmation.primaryButton) { - buttons.push(confirmation.primaryButton); - } else { - buttons.push(nls.localize({ key: 'yesButton', comment: ['&& denotes a mnemonic'] }, "&&Yes")); - } - - if (confirmation.secondaryButton) { - buttons.push(confirmation.secondaryButton); - } else if (typeof confirmation.secondaryButton === 'undefined') { - buttons.push(nls.localize('cancelButton', "Cancel")); - } - - const opts: Electron.MessageBoxOptions = { - title: confirmation.title, - message: confirmation.message, - buttons, - defaultId: 0, - cancelId: 1 - }; - - if (confirmation.detail) { - opts.detail = confirmation.detail; - } - - if (confirmation.type) { - opts.type = confirmation.type; - } - - if (confirmation.checkbox) { - opts.checkboxLabel = confirmation.checkbox.label; - opts.checkboxChecked = confirmation.checkbox.checked; - } - - return opts; - } - - public choose(severity: Severity, message: string, choices: Choice[], cancelId?: number, modal: boolean = false): TPromise { - if (modal) { - return this.doChooseWithDialog(severity, message, choices, cancelId); - } - - return this.doChooseWithNotification(severity, message, choices); - } - - private doChooseWithDialog(severity: Severity, message: string, choices: Choice[], cancelId?: number): TPromise { - const type: 'none' | 'info' | 'error' | 'question' | 'warning' = severity === Severity.Info ? 'question' : severity === Severity.Error ? 'error' : severity === Severity.Warning ? 'warning' : 'none'; - - const stringChoices: string[] = []; - choices.forEach(choice => { - if (typeof choice === 'string') { - stringChoices.push(choice); - } else { - stringChoices.push(choice.label); - } - }); - - const { options, buttonIndexMap } = this.massageMessageBoxOptions({ message, buttons: stringChoices, type, cancelId }); - - return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button]); - } - - private doChooseWithNotification(severity: Severity, message: string, choices: Choice[]): TPromise { - let handle: INotificationHandle; - - const promise = new TPromise((c, e) => { - - // Complete promise with index of action that was picked - const callback = (index: number, closeNotification: boolean) => () => { - c(index); - - if (closeNotification) { - handle.close(); - } - - return TPromise.as(void 0); - }; - - // Convert choices into primary/secondary actions - const actions: INotificationActions = { - primary: [], - secondary: [] - }; - - choices.forEach((choice, index) => { - let isPrimary = true; - let label: string; - let closeNotification = false; - - if (typeof choice === 'string') { - label = choice; - } else { - isPrimary = false; - label = choice.label; - closeNotification = !choice.keepOpen; - } - - const action = new Action(`workbench.dialog.choice.${index}`, label, null, true, callback(index, closeNotification)); - if (isPrimary) { - actions.primary.push(action); - } else { - actions.secondary.push(action); - } - }); - - // Show notification with actions - handle = this.notificationService.notify({ severity, message, actions }); - - // Cancel promise when notification gets disposed - once(handle.onDidClose)(() => promise.cancel()); - - }, () => handle.close()); - - return promise; - } - - private massageMessageBoxOptions(options: Electron.MessageBoxOptions): IMassagedMessageBoxOptions { - let buttonIndexMap = options.buttons.map((button, index) => index); - - options.buttons = options.buttons.map(button => mnemonicButtonLabel(button)); - - // Linux: order of buttons is reverse - // macOS: also reverse, but the OS handles this for us! - if (isLinux) { - options.buttons = options.buttons.reverse(); - buttonIndexMap = buttonIndexMap.reverse(); - } - - // Default Button - if (options.defaultId !== void 0) { - options.defaultId = buttonIndexMap[options.defaultId]; - } else if (isLinux) { - options.defaultId = buttonIndexMap[0]; - } - - // Cancel Button - if (options.cancelId !== void 0) { - - // macOS: the cancel button should always be to the left of the primary action - // if we see more than 2 buttons, move the cancel one to the left of the primary - if (isMacintosh && options.buttons.length > 2 && options.cancelId !== 1) { - const cancelButton = options.buttons[options.cancelId]; - options.buttons.splice(options.cancelId, 1); - options.buttons.splice(1, 0, cancelButton); - - const cancelButtonIndex = buttonIndexMap[options.cancelId]; - buttonIndexMap.splice(cancelButtonIndex, 1); - buttonIndexMap.splice(1, 0, cancelButtonIndex); - } - - options.cancelId = buttonIndexMap[options.cancelId]; - } - - options.noLink = true; - options.title = options.title || product.nameLong; - - return { options, buttonIndexMap }; - } -} - -const MAX_CONFIRM_FILES = 10; -export function getConfirmMessage(start: string, resourcesToConfirm: URI[]): string { - const message = [start]; - message.push(''); - message.push(...resourcesToConfirm.slice(0, MAX_CONFIRM_FILES).map(r => basename(r.fsPath))); - - if (resourcesToConfirm.length > MAX_CONFIRM_FILES) { - if (resourcesToConfirm.length - MAX_CONFIRM_FILES === 1) { - message.push(nls.localize('moreFile', "...1 additional file not shown")); - } else { - message.push(nls.localize('moreFiles', "...{0} additional files not shown", resourcesToConfirm.length - MAX_CONFIRM_FILES)); - } - } - - message.push(''); - return message.join('\n'); -} \ No newline at end of file diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 0b8fa9cc0b..eab427337f 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -16,7 +16,7 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { getPathLabel } from 'vs/base/common/labels'; import { ResourceMap } from 'vs/base/common/map'; import { once } from 'vs/base/common/event'; diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index f30f1939a2..f1ef6c0d65 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import paths = require('vs/base/common/paths'); +import * as paths from 'vs/base/common/paths'; import { Position, IEditor, IEditorInput } from 'vs/platform/editor/common/editor'; import URI from 'vs/base/common/uri'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 721239dfec..38204d117f 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -8,7 +8,7 @@ import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export interface IExtensionDescription { readonly id: string; diff --git a/src/vs/workbench/services/extensions/common/extensionsRegistry.ts b/src/vs/workbench/services/extensions/common/extensionsRegistry.ts index 67b98d95b1..ce22adaab2 100644 --- a/src/vs/workbench/services/extensions/common/extensionsRegistry.ts +++ b/src/vs/workbench/services/extensions/common/extensionsRegistry.ts @@ -14,7 +14,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { EXTENSION_IDENTIFIER_PATTERN } from 'vs/platform/extensionManagement/common/extensionManagement'; const hasOwnProperty = Object.hasOwnProperty; -const schemaRegistry = Registry.as(Extensions.JSONContribution); +const schemaRegistry = Registry.as(Extensions.JSONContribution); export class ExtensionMessageCollector { @@ -125,12 +125,12 @@ const schema: IJSONSchema = { properties: { engines: { type: 'object', - + description: nls.localize('vscode.extension.engines', "Engine compatibility."), properties: { 'vscode': { type: 'string', description: nls.localize('vscode.extension.engines.vscode', 'For VS Code extensions, specifies the VS Code version that the extension is compatible with. Cannot be *. For example: ^0.10.5 indicates compatibility with a minimum VS Code version of 0.10.5.'), - default: '^0.10.0', + default: '^1.22.0', } } }, @@ -147,8 +147,15 @@ const schema: IJSONSchema = { type: 'array', uniqueItems: true, items: { - type: 'string', - enum: ['Languages', 'Snippets', 'Linters', 'Themes', 'Debuggers', 'Other', 'Keymaps', 'Formatters', 'Extension Packs', 'SCM Providers', 'Azure', 'Language Packs'] + oneOf: [{ + type: 'string', + enum: ['Programming Languages', 'Snippets', 'Linters', 'Themes', 'Debuggers', 'Other', 'Keymaps', 'Formatters', 'Extension Packs', 'SCM Providers', 'Azure', 'Language Packs'], + }, + { + type: 'string', + const: 'Languages', + deprecationMessage: nls.localize('vscode.extension.category.languages.deprecated', 'Use \'Programming Languages\' instead'), + }] } }, galleryBanner: { @@ -219,6 +226,11 @@ const schema: IJSONSchema = { body: 'onView:${5:viewId}', description: nls.localize('vscode.extension.activationEvents.onView', 'An activation event emitted whenever the specified view is expanded.'), }, + { + label: 'onUri', + body: 'onUri', + description: nls.localize('vscode.extension.activationEvents.onUri', 'An activation event emitted whenever a system-wide Uri directed towards this extension is open.'), + }, { label: '*', description: nls.localize('vscode.extension.activationEvents.star', 'An activation event emitted on VS Code startup. To ensure a great end user experience, please use this activation event in your extension only when no other activation events combination works in your use-case.'), @@ -249,6 +261,25 @@ const schema: IJSONSchema = { } } }, + markdown: { + type: 'string', + description: nls.localize('vscode.extension.markdown', "Controls the Markdown rendering engine used in the Marketplace. Either github (default) or standard."), + enum: ['github', 'standard'], + default: 'github' + }, + qna: { + default: 'marketplace', + description: nls.localize('vscode.extension.qna', "Controls the Q&A link in the Marketplace. Set to marketplace to enable the default Marketplace Q & A site. Set to a string to provide the URL of a custom Q & A site. Set to false to disable Q & A altogether."), + anyOf: [ + { + type: ['string', 'boolean'], + enum: ['marketplace', false] + }, + { + type: 'string' + } + ] + }, extensionDependencies: { description: nls.localize('vscode.extension.extensionDependencies', 'Dependencies to other extensions. The identifier of an extension is always ${publisher}.${name}. For example: vscode.csharp.'), type: 'array', diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 16175a2c78..50c9079bea 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -23,7 +23,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { generateRandomPipeName, Protocol } from 'vs/base/parts/ipc/node/ipc.net'; import { createServer, Server, Socket } from 'net'; -import Event, { Emitter, debounceEvent, mapEvent, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent, mapEvent, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event'; import { IInitData, IWorkspaceData, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; @@ -36,11 +36,10 @@ import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console'; import { getScopes } from 'vs/platform/configuration/common/configurationRegistry'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; export class ExtensionHostProcessWorker { - private _onCrashed: Emitter<[number, string]> = new Emitter<[number, string]>(); + private readonly _onCrashed: Emitter<[number, string]> = new Emitter<[number, string]>(); public readonly onCrashed: Event<[number, string]> = this._onCrashed.event; private readonly _toDispose: IDisposable[]; @@ -73,7 +72,6 @@ export class ExtensionHostProcessWorker { @IWorkspaceConfigurationService private readonly _configurationService: IWorkspaceConfigurationService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @ICrashReporterService private readonly _crashReporterService: ICrashReporterService, - @IChoiceService private readonly _choiceService: IChoiceService, @ILogService private readonly _logService: ILogService ) { // handle extension host lifecycle a bit special when we know we are developing an extension that runs inside @@ -143,7 +141,6 @@ export class ExtensionHostProcessWorker { AMD_ENTRYPOINT: 'vs/workbench/node/extensionHostProcess', PIPE_LOGGING: 'true', VERBOSE_LOGGING: true, - VSCODE_WINDOW_ID: String(this._windowService.getCurrentWindowId()), VSCODE_IPC_HOOK_EXTHOST: pipeName, VSCODE_HANDLES_UNCAUGHT_ERRORS: true, VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || product.quality !== 'stable' || this._environmentService.verbose) @@ -238,11 +235,12 @@ export class ExtensionHostProcessWorker { ? nls.localize('extensionHostProcess.startupFailDebug', "Extension host did not start in 10 seconds, it might be stopped on the first line and needs a debugger to continue.") : nls.localize('extensionHostProcess.startupFail', "Extension host did not start in 10 seconds, that might be a problem."); - this._choiceService.choose(Severity.Warning, msg, [nls.localize('reloadWindow', "Reload Window")]).then(choice => { - if (choice === 0) { - this._windowService.reloadWindow(); - } - }); + this._notificationService.prompt(Severity.Warning, msg, + [{ + label: nls.localize('reloadWindow', "Reload Window"), + run: () => this._windowService.reloadWindow() + }] + ); }, 10000); } @@ -372,22 +370,17 @@ export class ExtensionHostProcessWorker { appRoot: this._environmentService.appRoot, appSettingsHome: this._environmentService.appSettingsHome, disableExtensions: this._environmentService.disableExtensions, - userExtensionsHome: this._environmentService.extensionsPath, extensionDevelopmentPath: this._environmentService.extensionDevelopmentPath, - extensionTestsPath: this._environmentService.extensionTestsPath, - // globally disable proposed api when built and not insiders developing extensions - enableProposedApiForAll: !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0), - enableProposedApiFor: this._environmentService.args['enable-proposed-api'] || [] + extensionTestsPath: this._environmentService.extensionTestsPath }, workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace(), extensions: extensionDescriptions, // Send configurations scopes only in development mode. configuration: !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment ? { ...configurationData, configurationScopes: getScopes() } : configurationData, telemetryInfo, - args: this._environmentService.args, - execPath: this._environmentService.execPath, windowId: this._windowService.getCurrentWindowId(), - logLevel: this._logService.getLevel() + logLevel: this._logService.getLevel(), + logsPath: this._environmentService.logsPath }; return r; }); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index edc8fe1c05..a5c7e0b53a 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -17,8 +17,8 @@ import * as platform from 'vs/base/common/platform'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; import { IMessage, IExtensionDescription, IExtensionsStatus, IExtensionService, ExtensionPointContribution, ActivationTimes, ProfileSession } from 'vs/workbench/services/extensions/common/extensions'; import { USER_MANIFEST_CACHE_FILE, BUILTIN_MANIFEST_CACHE_FILE, MANIFEST_CACHE_FOLDER } from 'vs/platform/extensions/common/extensions'; -import { IExtensionEnablementService, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { areSameExtensions, BetterMergeId, BetterMergeDisabledNowKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { IExtensionEnablementService, IExtensionIdentifier, EnablementState, IExtensionManagementService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { areSameExtensions, BetterMergeId, BetterMergeDisabledNowKey, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionsRegistry, ExtensionPoint, IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ExtensionScanner, ILog, ExtensionScannerInput, IExtensionResolver, IExtensionReference, Translations } from 'vs/workbench/services/extensions/node/extensionPoints'; import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; @@ -35,13 +35,13 @@ import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { mark, time } from 'vs/base/common/performance'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { Barrier } from 'vs/base/common/async'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler'; import product from 'vs/platform/node/product'; import * as strings from 'vs/base/common/strings'; import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { isFalsyOrEmpty } from 'vs/base/common/arrays'; let _SystemExtensionsRoot: string = null; function getSystemExtensionsRoot(): string { @@ -111,10 +111,160 @@ function messageWithSource2(source: string, message: string): string { const hasOwnProperty = Object.hasOwnProperty; const NO_OP_VOID_PROMISE = TPromise.wrap(void 0); +export class ExtensionHostProcessManager extends Disposable { + + public readonly onDidCrash: Event<[number, string]>; + + /** + * A map of already activated events to speed things up if the same activation event is triggered multiple times. + */ + private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; }; + private readonly _extensionHostProcessActivationTimes: { [id: string]: ActivationTimes; }; + private readonly _extensionHostExtensionRuntimeErrors: { [id: string]: Error[]; }; + private _extensionHostProcessRPCProtocol: RPCProtocol; + private readonly _extensionHostProcessCustomers: IDisposable[]; + private readonly _extensionHostProcessWorker: ExtensionHostProcessWorker; + /** + * winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object. + */ + private readonly _extensionHostProcessProxy: TPromise<{ value: ExtHostExtensionServiceShape; }>; + + constructor( + extensionHostProcessWorker: ExtensionHostProcessWorker, + initialActivationEvents: string[], + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IEnvironmentService private readonly _environmentService: IEnvironmentService, + ) { + super(); + this._extensionHostProcessFinishedActivateEvents = Object.create(null); + this._extensionHostProcessActivationTimes = Object.create(null); + this._extensionHostExtensionRuntimeErrors = Object.create(null); + this._extensionHostProcessRPCProtocol = null; + this._extensionHostProcessCustomers = []; + this._extensionHostProcessProxy = null; + + this._extensionHostProcessWorker = extensionHostProcessWorker; + this.onDidCrash = this._extensionHostProcessWorker.onCrashed; + this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then( + (protocol) => { + return { value: this._createExtensionHostCustomers(protocol) }; + }, + (err) => { + console.error('Error received from starting extension host'); + console.error(err); + return null; + } + ); + this._extensionHostProcessProxy.then(() => { + initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent)); + }); + } + + public dispose(): void { + if (this._extensionHostProcessWorker) { + this._extensionHostProcessWorker.dispose(); + } + if (this._extensionHostProcessRPCProtocol) { + this._extensionHostProcessRPCProtocol.dispose(); + } + for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) { + const customer = this._extensionHostProcessCustomers[i]; + try { + customer.dispose(); + } catch (err) { + errors.onUnexpectedError(err); + } + } + + super.dispose(); + } + + public getActivatedExtensionIds(): string[] { + return Object.keys(this._extensionHostProcessActivationTimes); + } + + public getActivationTimes(): { [id: string]: ActivationTimes; } { + return this._extensionHostProcessActivationTimes; + } + + public getRuntimeErrors(): { [id: string]: Error[]; } { + return this._extensionHostExtensionRuntimeErrors; + } + + public canProfileExtensionHost(): boolean { + return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort()); + } + + private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape { + + if (logExtensionHostCommunication || this._environmentService.logExtensionHostCommunication) { + protocol = asLoggingProtocol(protocol); + } + + this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol); + const extHostContext: IExtHostContext = this._extensionHostProcessRPCProtocol; + + // Named customers + const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers(); + for (let i = 0, len = namedCustomers.length; i < len; i++) { + const [id, ctor] = namedCustomers[i]; + const instance = this._instantiationService.createInstance(ctor, extHostContext); + this._extensionHostProcessCustomers.push(instance); + this._extensionHostProcessRPCProtocol.set(id, instance); + } + + // Customers + const customers = ExtHostCustomersRegistry.getCustomers(); + for (let i = 0, len = customers.length; i < len; i++) { + const ctor = customers[i]; + const instance = this._instantiationService.createInstance(ctor, extHostContext); + this._extensionHostProcessCustomers.push(instance); + } + + // Check that no named customers are missing + const expected: ProxyIdentifier[] = Object.keys(MainContext).map((key) => MainContext[key]); + this._extensionHostProcessRPCProtocol.assertRegistered(expected); + + return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService); + } + + public activateByEvent(activationEvent: string): TPromise { + if (this._extensionHostProcessFinishedActivateEvents[activationEvent] || !this._extensionHostProcessProxy) { + return NO_OP_VOID_PROMISE; + } + return this._extensionHostProcessProxy.then((proxy) => { + return proxy.value.$activateByEvent(activationEvent); + }).then(() => { + this._extensionHostProcessFinishedActivateEvents[activationEvent] = true; + }); + } + + public startExtensionHostProfile(): TPromise { + if (this._extensionHostProcessWorker) { + let port = this._extensionHostProcessWorker.getInspectPort(); + if (port) { + return this._instantiationService.createInstance(ExtensionHostProfiler, port).start(); + } + } + throw new Error('Extension host not running or no inspect port available'); + } + + public onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void { + this._extensionHostProcessActivationTimes[extensionId] = new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent); + } + + public onExtensionRuntimeError(extensionId: string, err: Error): void { + if (!this._extensionHostExtensionRuntimeErrors[extensionId]) { + this._extensionHostExtensionRuntimeErrors[extensionId] = []; + } + this._extensionHostExtensionRuntimeErrors[extensionId].push(err); + } +} + export class ExtensionService extends Disposable implements IExtensionService { public _serviceBrand: any; - private _onDidRegisterExtensions: Emitter; + private readonly _onDidRegisterExtensions: Emitter; private _registry: ExtensionDescriptionRegistry; private readonly _installedExtensionsReady: Barrier; @@ -126,31 +276,18 @@ export class ExtensionService extends Disposable implements IExtensionService { public readonly onDidChangeExtensionsStatus: Event = this._onDidChangeExtensionsStatus.event; // --- Members used per extension host process - - /** - * A map of already activated events to speed things up if the same activation event is triggered multiple times. - */ - private _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; }; - private _extensionHostProcessActivationTimes: { [id: string]: ActivationTimes; }; - private _extensionHostExtensionRuntimeErrors: { [id: string]: Error[]; }; - private _extensionHostProcessWorker: ExtensionHostProcessWorker; - private _extensionHostProcessRPCProtocol: RPCProtocol; - private _extensionHostProcessCustomers: IDisposable[]; - /** - * winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object. - */ - private _extensionHostProcessProxy: TPromise<{ value: ExtHostExtensionServiceShape; }>; + private _extensionHostProcessManager: ExtensionHostProcessManager; constructor( @IInstantiationService private readonly _instantiationService: IInstantiationService, @INotificationService private readonly _notificationService: INotificationService, - @IChoiceService private readonly _choiceService: IChoiceService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @IExtensionEnablementService private readonly _extensionEnablementService: IExtensionEnablementService, @IStorageService private readonly _storageService: IStorageService, @IWindowService private readonly _windowService: IWindowService, - @ILifecycleService lifecycleService: ILifecycleService + @ILifecycleService lifecycleService: ILifecycleService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService ) { super(); this._registry = null; @@ -161,15 +298,12 @@ export class ExtensionService extends Disposable implements IExtensionService { this._onDidRegisterExtensions = new Emitter(); - this._extensionHostProcessFinishedActivateEvents = Object.create(null); - this._extensionHostProcessActivationTimes = Object.create(null); - this._extensionHostExtensionRuntimeErrors = Object.create(null); - this._extensionHostProcessWorker = null; - this._extensionHostProcessRPCProtocol = null; - this._extensionHostProcessCustomers = []; - this._extensionHostProcessProxy = null; - + this._extensionHostProcessManager = null; this.startDelayed(lifecycleService); + + if (this._environmentService.disableExtensions) { + this._notificationService.info(nls.localize('extensionsDisabled', "All extensions are disabled.")); + } } private startDelayed(lifecycleService: ILifecycleService): void { @@ -223,51 +357,25 @@ export class ExtensionService extends Disposable implements IExtensionService { } private _stopExtensionHostProcess(): void { - const previouslyActivatedExtensionIds = Object.keys(this._extensionHostProcessActivationTimes); + let previouslyActivatedExtensionIds: string[] = []; - this._extensionHostProcessFinishedActivateEvents = Object.create(null); - this._extensionHostProcessActivationTimes = Object.create(null); - this._extensionHostExtensionRuntimeErrors = Object.create(null); - if (this._extensionHostProcessWorker) { - this._extensionHostProcessWorker.dispose(); - this._extensionHostProcessWorker = null; + if (this._extensionHostProcessManager) { + previouslyActivatedExtensionIds = this._extensionHostProcessManager.getActivatedExtensionIds(); + this._extensionHostProcessManager.dispose(); + this._extensionHostProcessManager = null; } - if (this._extensionHostProcessRPCProtocol) { - this._extensionHostProcessRPCProtocol.dispose(); - this._extensionHostProcessRPCProtocol = null; - } - for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) { - const customer = this._extensionHostProcessCustomers[i]; - try { - customer.dispose(); - } catch (err) { - errors.onUnexpectedError(err); - } - } - this._extensionHostProcessCustomers = []; - this._extensionHostProcessProxy = null; - this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds); + if (previouslyActivatedExtensionIds.length > 0) { + this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds); + } } private _startExtensionHostProcess(initialActivationEvents: string[]): void { this._stopExtensionHostProcess(); - this._extensionHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, this); - this._extensionHostProcessWorker.onCrashed(([code, signal]) => this._onExtensionHostCrashed(code, signal)); - this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then( - (protocol) => { - return { value: this._createExtensionHostCustomers(protocol) }; - }, - (err) => { - console.error('Error received from starting extension host'); - console.error(err); - return null; - } - ); - this._extensionHostProcessProxy.then(() => { - initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent)); - }); + const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, this); + this._extensionHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, extHostProcessWorker, initialActivationEvents); + this._extensionHostProcessManager.onDidCrash(([code, signal]) => this._onExtensionHostCrashed(code, signal)); } private _onExtensionHostCrashed(code: number, signal: string): void { @@ -279,49 +387,16 @@ export class ExtensionService extends Disposable implements IExtensionService { message = nls.localize('extensionHostProcess.unresponsiveCrash', "Extension host terminated because it was not responsive."); } - this._choiceService.choose(Severity.Error, message, [nls.localize('devTools', "Developer Tools"), nls.localize('restart', "Restart Extension Host")]).then(choice => { - switch (choice) { - case 0 /* Open Dev Tools */: - this._windowService.openDevTools(); - break; - case 1 /* Restart Extension Host */: - this._startExtensionHostProcess(Object.keys(this._allRequestedActivateEvents)); - break; - } - }); - } - - private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape { - - if (logExtensionHostCommunication || this._environmentService.logExtensionHostCommunication) { - protocol = asLoggingProtocol(protocol); - } - - this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol); - const extHostContext: IExtHostContext = this._extensionHostProcessRPCProtocol; - - // Named customers - const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers(); - for (let i = 0, len = namedCustomers.length; i < len; i++) { - const [id, ctor] = namedCustomers[i]; - const instance = this._instantiationService.createInstance(ctor, extHostContext); - this._extensionHostProcessCustomers.push(instance); - this._extensionHostProcessRPCProtocol.set(id, instance); - } - - // Customers - const customers = ExtHostCustomersRegistry.getCustomers(); - for (let i = 0, len = customers.length; i < len; i++) { - const ctor = customers[i]; - const instance = this._instantiationService.createInstance(ctor, extHostContext); - this._extensionHostProcessCustomers.push(instance); - } - - // Check that no named customers are missing - const expected: ProxyIdentifier[] = Object.keys(MainContext).map((key) => MainContext[key]); - this._extensionHostProcessRPCProtocol.assertRegistered(expected); - - return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService); + this._notificationService.prompt(Severity.Error, message, + [{ + label: nls.localize('devTools', "Open Developer Tools"), + run: () => this._windowService.openDevTools() + }, + { + label: nls.localize('restart', "Restart Extension Host"), + run: () => this._startExtensionHostProcess(Object.keys(this._allRequestedActivateEvents)) + }] + ); } // ---- begin IExtensionService @@ -349,15 +424,11 @@ export class ExtensionService extends Disposable implements IExtensionService { } } - protected _activateByEvent(activationEvent: string): TPromise { - if (this._extensionHostProcessFinishedActivateEvents[activationEvent] || !this._extensionHostProcessProxy) { - return NO_OP_VOID_PROMISE; + private _activateByEvent(activationEvent: string): TPromise { + if (this._extensionHostProcessManager) { + return this._extensionHostProcessManager.activateByEvent(activationEvent); } - return this._extensionHostProcessProxy.then((proxy) => { - return proxy.value.$activateByEvent(activationEvent); - }).then(() => { - this._extensionHostProcessFinishedActivateEvents[activationEvent] = true; - }); + return NO_OP_VOID_PROMISE; } public whenInstalledExtensionsRegistered(): TPromise { @@ -388,6 +459,9 @@ export class ExtensionService extends Disposable implements IExtensionService { } public getExtensionsStatus(): { [id: string]: IExtensionsStatus; } { + const activationTimes = this._extensionHostProcessManager ? this._extensionHostProcessManager.getActivationTimes() : {}; + const runtimeErrors = this._extensionHostProcessManager ? this._extensionHostProcessManager.getRuntimeErrors() : {}; + let result: { [id: string]: IExtensionsStatus; } = Object.create(null); if (this._registry) { const extensions = this._registry.getAllExtensionDescriptions(); @@ -396,8 +470,8 @@ export class ExtensionService extends Disposable implements IExtensionService { const id = extension.id; result[id] = { messages: this._extensionsMessages[id], - activationTimes: this._extensionHostProcessActivationTimes[id], - runtimeErrors: this._extensionHostExtensionRuntimeErrors[id], + activationTimes: activationTimes[id], + runtimeErrors: runtimeErrors[id], }; } } @@ -405,15 +479,15 @@ export class ExtensionService extends Disposable implements IExtensionService { } public canProfileExtensionHost(): boolean { - return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort()); + if (this._extensionHostProcessManager) { + return this._extensionHostProcessManager.canProfileExtensionHost(); + } + return false; } public startExtensionHostProfile(): TPromise { - if (this._extensionHostProcessWorker) { - let port = this._extensionHostProcessWorker.getInspectPort(); - if (port) { - return this._instantiationService.createInstance(ExtensionHostProfiler, port).start(); - } + if (this._extensionHostProcessManager) { + return this._extensionHostProcessManager.startExtensionHostProfile(); } throw new Error('Extension host not running or no inspect port available'); } @@ -424,7 +498,7 @@ export class ExtensionService extends Disposable implements IExtensionService { private _scanAndHandleExtensions(): void { - this._getRuntimeExtension() + this._getRuntimeExtensions() .then(runtimeExtensons => { this._registry = new ExtensionDescriptionRegistry(runtimeExtensons); @@ -449,14 +523,13 @@ export class ExtensionService extends Disposable implements IExtensionService { }); } - private _getRuntimeExtension(): TPromise { + private _getRuntimeExtensions(): TPromise { const log = new Logger((severity, source, message) => { this._logOrShowMessage(severity, this._isDev ? messageWithSource2(source, message) : message); }); - return ExtensionService._scanInstalledExtensions(this._windowService, this._choiceService, this._environmentService, log) + return ExtensionService._scanInstalledExtensions(this._windowService, this._notificationService, this._environmentService, log) .then(({ system, user, development }) => { - this._extensionEnablementService.migrateToIdentifiers(user); // TODO: @sandy Remove it after couple of milestones return this._extensionEnablementService.getDisabledExtensions() .then(disabledExtensions => { let result: { [extensionId: string]: IExtensionDescription; } = {}; @@ -501,7 +574,11 @@ export class ExtensionService extends Disposable implements IExtensionService { }); if (extensionsToDisable.length) { - return TPromise.join(extensionsToDisable.map(e => this._extensionEnablementService.setEnablement(e, EnablementState.Disabled))) + return this.extensionManagementService.getInstalled(LocalExtensionType.User) + .then(installed => { + const toDisable = installed.filter(i => extensionsToDisable.some(e => areSameExtensions({ id: getGalleryExtensionIdFromLocal(i) }, e))); + return TPromise.join(toDisable.map(e => this._extensionEnablementService.setEnablement(e, EnablementState.Disabled))); + }) .then(() => { this._storageService.store(BetterMergeDisabledNowKey, true); return runtimeExtensions; @@ -510,7 +587,36 @@ export class ExtensionService extends Disposable implements IExtensionService { return runtimeExtensions; } }); - }); + }).then(extensions => this._updateEnableProposedApi(extensions)); + } + + private _updateEnableProposedApi(extensions: IExtensionDescription[]): IExtensionDescription[] { + const enableProposedApiForAll = !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0); + const enableProposedApiFor = this._environmentService.args['enable-proposed-api'] || []; + for (const extension of extensions) { + if (!isFalsyOrEmpty(product.extensionAllowedProposedApi) + && product.extensionAllowedProposedApi.indexOf(extension.id) >= 0 + ) { + // fast lane -> proposed api is available to all extensions + // that are listed in product.json-files + extension.enableProposedApi = true; + + } else if (extension.enableProposedApi && !extension.isBuiltin) { + if ( + !enableProposedApiForAll && + enableProposedApiFor.indexOf(extension.id) < 0 + ) { + extension.enableProposedApi = false; + console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`); + + } else { + // proposed api is available when developing or when an extension was explicitly + // spelled out via a command line argument + console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`); + } + } + } + return extensions; } private _handleExtensionPointMessage(msg: IMessage) { @@ -531,7 +637,7 @@ export class ExtensionService extends Disposable implements IExtensionService { const { type, extensionId, extensionPointId, message } = msg; /* __GDPR__ "extensionsMessage" : { - "type" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "type" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "extensionId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "extensionPointId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "message": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } @@ -543,7 +649,7 @@ export class ExtensionService extends Disposable implements IExtensionService { } } - private static async _validateExtensionsCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise { + private static async _validateExtensionsCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise { const cacheFolder = path.join(environmentService.userDataPath, MANIFEST_CACHE_FOLDER); const cacheFile = path.join(cacheFolder, cacheKey); @@ -568,11 +674,14 @@ export class ExtensionService extends Disposable implements IExtensionService { console.error(err); } - choiceService.choose(Severity.Error, nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."), [nls.localize('reloadWindow', "Reload Window")]).then(choice => { - if (choice === 0) { - windowService.reloadWindow(); - } - }); + notificationService.prompt( + Severity.Error, + nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."), + [{ + label: nls.localize('reloadWindow', "Reload Window"), + run: () => windowService.reloadWindow() + }] + ); } private static async _readExtensionCache(environmentService: IEnvironmentService, cacheKey: string): TPromise { @@ -606,7 +715,7 @@ export class ExtensionService extends Disposable implements IExtensionService { } } - private static async _scanExtensionsWithCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise { + private static async _scanExtensionsWithCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise { if (input.devMode) { // Do not cache when running out of sources... return ExtensionScanner.scanExtensions(input, log); @@ -624,7 +733,7 @@ export class ExtensionService extends Disposable implements IExtensionService { // Validate the cache asynchronously after 5s setTimeout(async () => { try { - await this._validateExtensionsCache(windowService, choiceService, environmentService, cacheKey, input); + await this._validateExtensionsCache(windowService, notificationService, environmentService, cacheKey, input); } catch (err) { errors.onUnexpectedError(err); } @@ -646,7 +755,7 @@ export class ExtensionService extends Disposable implements IExtensionService { return result; } - private static _scanInstalledExtensions(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> { + private static _scanInstalledExtensions(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> { const translationConfig: TPromise = platform.translationsConfigFile ? pfs.readFile(platform.translationsConfigFile, 'utf8').then((content) => { @@ -668,7 +777,7 @@ export class ExtensionService extends Disposable implements IExtensionService { const builtinExtensions = this._scanExtensionsWithCache( windowService, - choiceService, + notificationService, environmentService, BUILTIN_MANIFEST_CACHE_FILE, new ExtensionScannerInput(version, commit, locale, devMode, getSystemExtensionsRoot(), true, translations), @@ -722,7 +831,7 @@ export class ExtensionService extends Disposable implements IExtensionService { ? TPromise.as([]) : this._scanExtensionsWithCache( windowService, - choiceService, + notificationService, environmentService, USER_MANIFEST_CACHE_FILE, new ExtensionScannerInput(version, commit, locale, devMode, environmentService.extensionsPath, false, translations), @@ -798,15 +907,12 @@ export class ExtensionService extends Disposable implements IExtensionService { } public _onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void { - this._extensionHostProcessActivationTimes[extensionId] = new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent); + this._extensionHostProcessManager.onExtensionActivated(extensionId, startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent); this._onDidChangeExtensionsStatus.fire([extensionId]); } public _onExtensionRuntimeError(extensionId: string, err: Error): void { - if (!this._extensionHostExtensionRuntimeErrors[extensionId]) { - this._extensionHostExtensionRuntimeErrors[extensionId] = []; - } - this._extensionHostExtensionRuntimeErrors[extensionId].push(err); + this._extensionHostProcessManager.onExtensionRuntimeError(extensionId, err); this._onDidChangeExtensionsStatus.fire([extensionId]); } diff --git a/src/vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts b/src/vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts index 6830265599..d126113c6b 100644 --- a/src/vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts +++ b/src/vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts @@ -33,6 +33,12 @@ export class ExtensionDescriptionRegistry { if (Array.isArray(extensionDescription.activationEvents)) { for (let j = 0, lenJ = extensionDescription.activationEvents.length; j < lenJ; j++) { let activationEvent = extensionDescription.activationEvents[j]; + + // TODO@joao: there's no easy way to contribute this + if (activationEvent === 'onUri') { + activationEvent = `onUri:${extensionDescription.id}`; + } + this._activationMap[activationEvent] = this._activationMap[activationEvent] || []; this._activationMap[activationEvent].push(extensionDescription); } diff --git a/src/vs/workbench/services/extensions/node/extensionPoints.ts b/src/vs/workbench/services/extensions/node/extensionPoints.ts index 07ca377401..6d0ed429aa 100644 --- a/src/vs/workbench/services/extensions/node/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/node/extensionPoints.ts @@ -496,7 +496,7 @@ export class ExtensionScanner { /** * Read the extension defined in `absoluteFolderPath` */ - private static scanExtension(version: string, log: ILog, absoluteFolderPath: string, isBuiltin: boolean, nlsConfig: NlsConfiguration): TPromise { + public static scanExtension(version: string, log: ILog, absoluteFolderPath: string, isBuiltin: boolean, nlsConfig: NlsConfiguration): TPromise { absoluteFolderPath = normalize(absoluteFolderPath); let parser = new ExtensionManifestParser(version, log, absoluteFolderPath, isBuiltin); @@ -550,11 +550,13 @@ export class ExtensionScanner { const gallery: IExtensionReference[] = []; refs.forEach(ref => { - const { id, version } = getIdAndVersionFromLocalExtensionId(ref.name); - if (!id || !version) { - nonGallery.push(ref); - } else { - gallery.push(ref); + if (ref.name.indexOf('.') !== 0) { // Do not consider user extension folder starting with `.` + const { id, version } = getIdAndVersionFromLocalExtensionId(ref.name); + if (!id || !version) { + nonGallery.push(ref); + } else { + gallery.push(ref); + } } }); refs = [...nonGallery, ...gallery]; diff --git a/src/vs/workbench/services/extensions/node/rpcProtocol.ts b/src/vs/workbench/services/extensions/node/rpcProtocol.ts index 9f90a6feb3..0399f6528c 100644 --- a/src/vs/workbench/services/extensions/node/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/node/rpcProtocol.ts @@ -10,11 +10,88 @@ import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise'; import { ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { CharCode } from 'vs/base/common/charCode'; +import URI, { UriComponents } from 'vs/base/common/uri'; +import { MarshalledObject } from 'vs/base/common/marshalling'; declare var Proxy: any; // TODO@TypeScript +export interface IURITransformer { + transformIncoming(uri: UriComponents): UriComponents; + transformOutgoing(uri: URI): URI; +} + +function _transformOutgoingURIs(obj: any, transformer: IURITransformer, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + if (obj instanceof URI) { + return transformer.transformOutgoing(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformOutgoingURIs(obj[key], transformer, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +function transformOutgoingURIs(obj: any, transformer: IURITransformer): any { + const result = _transformOutgoingURIs(obj, transformer, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + +function _transformIncomingURIs(obj: any, transformer: IURITransformer, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + + if ((obj).$mid === 1) { + return transformer.transformIncoming(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformIncomingURIs(obj[key], transformer, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +function transformIncomingURIs(obj: any, transformer: IURITransformer): any { + const result = _transformIncomingURIs(obj, transformer, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + export class RPCProtocol implements IRPCProtocol { + private readonly _uriTransformer: IURITransformer; private _isDisposed: boolean; private readonly _locals: { [id: string]: any; }; private readonly _proxies: { [id: string]: any; }; @@ -23,7 +100,8 @@ export class RPCProtocol implements IRPCProtocol { private readonly _pendingRPCReplies: { [msgId: string]: LazyPromise; }; private readonly _multiplexor: RPCMultiplexer; - constructor(protocol: IMessagePassingProtocol) { + constructor(protocol: IMessagePassingProtocol, transformer: IURITransformer = null) { + this._uriTransformer = transformer; this._isDisposed = false; this._locals = Object.create(null); this._proxies = Object.create(null); @@ -43,6 +121,13 @@ export class RPCProtocol implements IRPCProtocol { }); } + public transformIncomingURIs(obj: T): T { + if (!this._uriTransformer) { + return obj; + } + return transformIncomingURIs(obj, this._uriTransformer); + } + public getProxy(identifier: ProxyIdentifier): T { if (!this._proxies[identifier.id]) { this._proxies[identifier.id] = this._createProxy(identifier.id); @@ -84,6 +169,9 @@ export class RPCProtocol implements IRPCProtocol { } let msg = JSON.parse(rawmsg); + if (this._uriTransformer) { + msg = transformIncomingURIs(msg, this._uriTransformer); + } switch (msg.type) { case MessageType.Request: @@ -109,6 +197,9 @@ export class RPCProtocol implements IRPCProtocol { this._invokedHandlers[callId].then((r) => { delete this._invokedHandlers[callId]; + if (this._uriTransformer) { + r = transformOutgoingURIs(r, this._uriTransformer); + } this._multiplexor.send(MessageFactory.replyOK(callId, r)); }, (err) => { delete this._invokedHandlers[callId]; @@ -185,6 +276,9 @@ export class RPCProtocol implements IRPCProtocol { }); this._pendingRPCReplies[callId] = result; + if (this._uriTransformer) { + args = transformOutgoingURIs(args, this._uriTransformer); + } this._multiplexor.send(MessageFactory.request(callId, proxyId, methodName, args)); return result; } diff --git a/src/vs/workbench/services/files/electron-browser/encoding.ts b/src/vs/workbench/services/files/electron-browser/encoding.ts new file mode 100644 index 0000000000..4c1e209906 --- /dev/null +++ b/src/vs/workbench/services/files/electron-browser/encoding.ts @@ -0,0 +1,146 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; +import * as encoding from 'vs/base/node/encoding'; +import uri from 'vs/base/common/uri'; +import { IResolveContentOptions, isParent, IResourceEncodings } from 'vs/platform/files/common/files'; +import { isLinux } from 'vs/base/common/platform'; +import { join, extname } from 'path'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; + +export interface IEncodingOverride { + parent?: uri; + extension?: string; + encoding: string; +} + +// TODO@Ben debt - encodings should move one layer up from the file service into the text file +// service and then ideally be passed in as option to the file service +// the file service should talk about string | Buffer for reading and writing and only convert +// to strings if a encoding is provided +export class ResourceEncodings implements IResourceEncodings { + private encodingOverride: IEncodingOverride[]; + private toDispose: IDisposable[]; + + constructor( + private textResourceConfigurationService: ITextResourceConfigurationService, + private environmentService: IEnvironmentService, + private contextService: IWorkspaceContextService, + encodingOverride?: IEncodingOverride[] + ) { + this.encodingOverride = encodingOverride || this.getEncodingOverrides(); + this.toDispose = []; + + this.registerListeners(); + } + + private registerListeners(): void { + + // Workspace Folder Change + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => { + this.encodingOverride = this.getEncodingOverrides(); + })); + } + + public getReadEncoding(resource: uri, options: IResolveContentOptions, detected: encoding.IDetectedEncodingResult): string { + let preferredEncoding: string; + + // Encoding passed in as option + if (options && options.encoding) { + if (detected.encoding === encoding.UTF8 && options.encoding === encoding.UTF8) { + preferredEncoding = encoding.UTF8_with_bom; // indicate the file has BOM if we are to resolve with UTF 8 + } else { + preferredEncoding = options.encoding; // give passed in encoding highest priority + } + } + + // Encoding detected + else if (detected.encoding) { + if (detected.encoding === encoding.UTF8) { + preferredEncoding = encoding.UTF8_with_bom; // if we detected UTF-8, it can only be because of a BOM + } else { + preferredEncoding = detected.encoding; + } + } + + // Encoding configured + else if (this.textResourceConfigurationService.getValue(resource, 'files.encoding') === encoding.UTF8_with_bom) { + preferredEncoding = encoding.UTF8; // if we did not detect UTF 8 BOM before, this can only be UTF 8 then + } + + return this.getEncodingForResource(resource, preferredEncoding); + } + + public getWriteEncoding(resource: uri, preferredEncoding?: string): string { + return this.getEncodingForResource(resource, preferredEncoding); + } + + private getEncodingForResource(resource: uri, preferredEncoding?: string): string { + let fileEncoding: string; + + const override = this.getEncodingOverride(resource); + if (override) { + fileEncoding = override; // encoding override always wins + } else if (preferredEncoding) { + fileEncoding = preferredEncoding; // preferred encoding comes second + } else { + fileEncoding = this.textResourceConfigurationService.getValue(resource, 'files.encoding'); // and last we check for settings + } + + if (!fileEncoding || !encoding.encodingExists(fileEncoding)) { + fileEncoding = encoding.UTF8; // the default is UTF 8 + } + + return fileEncoding; + } + + private getEncodingOverrides(): IEncodingOverride[] { + const encodingOverride: IEncodingOverride[] = []; + + // Global settings + encodingOverride.push({ parent: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); + + // Workspace files + encodingOverride.push({ extension: WORKSPACE_EXTENSION, encoding: encoding.UTF8 }); + + // Folder Settings + this.contextService.getWorkspace().folders.forEach(folder => { + // {{SQL CARBON EDIT}} + encodingOverride.push({ parent: uri.file(join(folder.uri.fsPath, '.sqlops')), encoding: encoding.UTF8 }); + }); + + return encodingOverride; + } + + private getEncodingOverride(resource: uri): string { + if (resource && this.encodingOverride && this.encodingOverride.length) { + for (let i = 0; i < this.encodingOverride.length; i++) { + const override = this.encodingOverride[i]; + + // check if the resource is child of encoding override path + if (override.parent && isParent(resource.fsPath, override.parent.fsPath, !isLinux /* ignorecase */)) { + return override.encoding; + } + + // check if the resource extension is equal to encoding override + if (override.extension && extname(resource.fsPath) === `.${override.extension}`) { + return override.encoding; + } + } + } + + return null; + } + + public dispose(): void { + this.toDispose = dispose(this.toDispose); + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 9897c7b93a..2f7e63410d 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -2,92 +2,197 @@ * 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 nls = require('vs/nls'); +import * as paths from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as crypto from 'crypto'; +import * as assert from 'assert'; +import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, FileChangesEvent, ICreateFileOptions, IContentData, ITextSnapshot, IFilesConfiguration, IFileSystemProviderRegistrationEvent, IFileSystemProvider } from 'vs/platform/files/common/files'; +import { MAX_FILE_SIZE, MAX_HEAP_SIZE } from 'vs/platform/files/node/files'; +import { isEqualOrParent } from 'vs/base/common/paths'; +import { ResourceMap } from 'vs/base/common/map'; +import * as arrays from 'vs/base/common/arrays'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import paths = require('vs/base/common/paths'); -import encoding = require('vs/base/node/encoding'); -import errors = require('vs/base/common/errors'); +import * as objects from 'vs/base/common/objects'; +import * as extfs from 'vs/base/node/extfs'; +import { nfcall, ThrottledDelayer, asWinJsPromise } from 'vs/base/common/async'; import uri from 'vs/base/common/uri'; -import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent, ICreateFileOptions, ITextSnapshot } from 'vs/platform/files/common/files'; -import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; -import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import Event, { Emitter } from 'vs/base/common/event'; -import { shell } from 'electron'; +import * as nls from 'vs/nls'; +import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; +import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import * as pfs from 'vs/base/node/pfs'; +import * as encoding from 'vs/base/node/encoding'; +import * as flow from 'vs/base/node/flow'; +import { FileWatcher as UnixWatcherService } from 'vs/workbench/services/files/node/watcher/unix/watcherService'; +import { FileWatcher as WindowsWatcherService } from 'vs/workbench/services/files/node/watcher/win32/watcherService'; +import { toFileChangesEvent, normalize, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common'; +import { Event, Emitter } from 'vs/base/common/event'; +import { FileWatcher as NsfwWatcherService } from 'vs/workbench/services/files/node/watcher/nsfw/watcherService'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; -import { isMacintosh, isWindows } from 'vs/base/common/platform'; -import product from 'vs/platform/node/product'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; +import { getBaseLabel } from 'vs/base/common/labels'; import { Schemas } from 'vs/base/common/network'; -import { Severity } from 'vs/platform/notification/common/notification'; -import { IChoiceService, Choice } from 'vs/platform/dialogs/common/dialogs'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { onUnexpectedError } from 'vs/base/common/errors'; +import product from 'vs/platform/node/product'; +import { IEncodingOverride, ResourceEncodings } from 'vs/workbench/services/files/electron-browser/encoding'; +import { createReadableOfSnapshot } from 'vs/workbench/services/files/electron-browser/streams'; + +class BufferPool { + + static _64K = new BufferPool(64 * 1024, 5); + + constructor( + readonly bufferSize: number, + private readonly _capacity: number, + private readonly _free: Buffer[] = [], + ) { } + + acquire(): Buffer { + if (this._free.length === 0) { + return Buffer.allocUnsafe(this.bufferSize); + } else { + return this._free.shift(); + } + } + + release(buf: Buffer): void { + if (this._free.length <= this._capacity) { + this._free.push(buf); + } + } +} + +export interface IFileServiceTestOptions { + disableWatcher?: boolean; + encodingOverride?: IEncodingOverride[]; +} export class FileService implements IFileService { public _serviceBrand: any; - // If we run with .NET framework < 4.5, we need to detect this error to inform the user + private static readonly FS_EVENT_DELAY = 50; // aggregate and only emit events when changes have stopped for this duration (in ms) + private static readonly FS_REWATCH_DELAY = 300; // delay to rewatch a file that was renamed or deleted (in ms) + private static readonly NET_VERSION_ERROR = 'System.MissingMethodException'; private static readonly NET_VERSION_ERROR_IGNORE_KEY = 'ignoreNetVersionError'; private static readonly ENOSPC_ERROR = 'ENOSPC'; private static readonly ENOSPC_ERROR_IGNORE_KEY = 'ignoreEnospcError'; - private raw: NodeFileService; + protected readonly _onFileChanges: Emitter; + protected readonly _onAfterOperation: Emitter; + protected readonly _onDidChangeFileSystemProviderRegistrations = new Emitter(); - private toUnbind: IDisposable[]; + protected toDispose: IDisposable[]; - protected _onFileChanges: Emitter; - protected _onAfterOperation: Emitter; + private activeWorkspaceFileChangeWatcher: IDisposable; + private activeFileChangesWatchers: ResourceMap; + private fileChangesWatchDelayer: ThrottledDelayer; + private undeliveredRawFileChangesEvents: IRawFileChange[]; + + private _encoding: ResourceEncodings; constructor( - @IConfigurationService private configurationService: IConfigurationService, - @IWorkspaceContextService private contextService: IWorkspaceContextService, - @IEnvironmentService private environmentService: IEnvironmentService, - @ILifecycleService private lifecycleService: ILifecycleService, - @IChoiceService private choiceService: IChoiceService, - @IStorageService private storageService: IStorageService, - @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService + private contextService: IWorkspaceContextService, + private environmentService: IEnvironmentService, + private textResourceConfigurationService: ITextResourceConfigurationService, + private configurationService: IConfigurationService, + private lifecycleService: ILifecycleService, + private storageService: IStorageService, + private notificationService: INotificationService, + private options: IFileServiceTestOptions = Object.create(null) ) { - this.toUnbind = []; + this.toDispose = []; this._onFileChanges = new Emitter(); - this.toUnbind.push(this._onFileChanges); + this.toDispose.push(this._onFileChanges); this._onAfterOperation = new Emitter(); - this.toUnbind.push(this._onAfterOperation); + this.toDispose.push(this._onAfterOperation); - const configuration = this.configurationService.getValue(); + this.activeFileChangesWatchers = new ResourceMap(); + this.fileChangesWatchDelayer = new ThrottledDelayer(FileService.FS_EVENT_DELAY); + this.undeliveredRawFileChangesEvents = []; - let watcherIgnoredPatterns: string[] = []; - if (configuration.files && configuration.files.watcherExclude) { - watcherIgnoredPatterns = Object.keys(configuration.files.watcherExclude).filter(k => !!configuration.files.watcherExclude[k]); + this._encoding = new ResourceEncodings(textResourceConfigurationService, environmentService, contextService, this.options.encodingOverride); + + this.registerListeners(); + } + + public get encoding(): ResourceEncodings { + return this._encoding; + } + + private registerListeners(): void { + + // Wait until we are fully running before starting file watchers + this.lifecycleService.when(LifecyclePhase.Running).then(() => { + this.setupFileWatching(); + }); + + // Workbench State Change + this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => { + if (this.lifecycleService.phase >= LifecyclePhase.Running) { + this.setupFileWatching(); + } + })); + + // Lifecycle + this.lifecycleService.onShutdown(this.dispose, this); + } + + private handleError(error: string | Error): void { + const msg = error ? error.toString() : void 0; + if (!msg) { + return; } - // build config - const fileServiceConfig: IFileServiceOptions = { - errorLogger: (msg: string) => this.onFileServiceError(msg), - encodingOverride: this.getEncodingOverrides(), - watcherIgnoredPatterns, - verboseLogging: environmentService.verbose, - useExperimentalFileWatcher: configuration.files.useExperimentalFileWatcher, - elevationSupport: { - cliPath: this.environmentService.cliPath, - promptTitle: this.environmentService.appNameLong, - promptIcnsPath: (isMacintosh && this.environmentService.isBuilt) ? paths.join(paths.dirname(this.environmentService.appRoot), `${product.nameShort}.icns`) : void 0 - } - }; + // Forward to unexpected error handler + onUnexpectedError(msg); - // create service - this.raw = new NodeFileService(contextService, environmentService, textResourceConfigurationService, configurationService, lifecycleService, fileServiceConfig); + // Detect if we run < .NET Framework 4.5 (TODO@ben remove with new watcher impl) + if (msg.indexOf(FileService.NET_VERSION_ERROR) >= 0 && !this.storageService.getBoolean(FileService.NET_VERSION_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) { + this.notificationService.prompt( + Severity.Warning, + nls.localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."), + [{ + label: nls.localize('installNet', "Download .NET Framework 4.5"), + run: () => window.open('https://go.microsoft.com/fwlink/?LinkId=786533') + }, + { + label: nls.localize('neverShowAgain', "Don't Show Again"), + isSecondary: true, + run: () => this.storageService.store(FileService.NET_VERSION_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE) + }] + ); + } - // Listeners - this.registerListeners(); + // Detect if we run into ENOSPC issues + if (msg.indexOf(FileService.ENOSPC_ERROR) >= 0 && !this.storageService.getBoolean(FileService.ENOSPC_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) { + this.notificationService.prompt( + Severity.Warning, + nls.localize('enospcError', "{0} is unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue.", product.nameLong), + [{ + label: nls.localize('learnMore', "Instructions"), + run: () => window.open('https://go.microsoft.com/fwlink/?linkid=867693') + }, + { + label: nls.localize('neverShowAgain', "Don't Show Again"), + isSecondary: true, + run: () => this.storageService.store(FileService.ENOSPC_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE) + }] + ); + } } public get onFileChanges(): Event { @@ -98,193 +203,1038 @@ export class FileService implements IFileService { return this._onAfterOperation.event; } - private onFileServiceError(error: string | Error): void { - const msg = error ? error.toString() : void 0; - if (!msg) { + private setupFileWatching(): void { + + // dispose old if any + if (this.activeWorkspaceFileChangeWatcher) { + this.activeWorkspaceFileChangeWatcher.dispose(); + } + + // Return if not aplicable + const workbenchState = this.contextService.getWorkbenchState(); + if (workbenchState === WorkbenchState.EMPTY || this.options.disableWatcher) { return; } - // Forward to unexpected error handler - errors.onUnexpectedError(msg); - - // Detect if we run < .NET Framework 4.5 (TODO@ben remove with new watcher impl) - if (msg.indexOf(FileService.NET_VERSION_ERROR) >= 0 && !this.storageService.getBoolean(FileService.NET_VERSION_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) { - const choices: Choice[] = [nls.localize('installNet', "Download .NET Framework 4.5"), { label: nls.localize('neverShowAgain', "Don't Show Again") }]; - this.choiceService.choose(Severity.Warning, nls.localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."), choices).then(choice => { - switch (choice) { - case 0 /* Read More */: - window.open('https://go.microsoft.com/fwlink/?LinkId=786533'); - break; - case 1 /* Never show again */: - this.storageService.store(FileService.NET_VERSION_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE); - break; - } - }); + // new watcher: use it if setting tells us so or we run in multi-root environment + const configuration = this.configurationService.getValue(); + if ((configuration.files && configuration.files.useExperimentalFileWatcher) || workbenchState === WorkbenchState.WORKSPACE) { + const multiRootWatcher = new NsfwWatcherService(this.contextService, this.configurationService, e => this._onFileChanges.fire(e), err => this.handleError(err), this.environmentService.verbose); + this.activeWorkspaceFileChangeWatcher = toDisposable(multiRootWatcher.startWatching()); } - // Detect if we run into ENOSPC issues - if (msg.indexOf(FileService.ENOSPC_ERROR) >= 0 && !this.storageService.getBoolean(FileService.ENOSPC_ERROR_IGNORE_KEY, StorageScope.WORKSPACE)) { - const choices: Choice[] = [nls.localize('learnMore', "Instructions"), { label: nls.localize('neverShowAgain', "Don't Show Again") }]; - this.choiceService.choose(Severity.Warning, nls.localize('enospcError', "{0} is running out of file handles. Please follow the instructions link to resolve this issue.", product.nameLong), choices).then(choice => { - switch (choice) { - case 0 /* Read More */: - window.open('https://go.microsoft.com/fwlink/?linkid=867693'); - break; - case 1 /* Never show again */: - this.storageService.store(FileService.ENOSPC_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE); - break; - } - }); + // legacy watcher + else { + let watcherIgnoredPatterns: string[] = []; + if (configuration.files && configuration.files.watcherExclude) { + watcherIgnoredPatterns = Object.keys(configuration.files.watcherExclude).filter(k => !!configuration.files.watcherExclude[k]); + } + + if (isWindows) { + const legacyWindowsWatcher = new WindowsWatcherService(this.contextService, watcherIgnoredPatterns, e => this._onFileChanges.fire(e), err => this.handleError(err), this.environmentService.verbose); + this.activeWorkspaceFileChangeWatcher = toDisposable(legacyWindowsWatcher.startWatching()); + } else { + const legacyUnixWatcher = new UnixWatcherService(this.contextService, watcherIgnoredPatterns, e => this._onFileChanges.fire(e), err => this.handleError(err), this.environmentService.verbose); + this.activeWorkspaceFileChangeWatcher = toDisposable(legacyUnixWatcher.startWatching()); + } } } - private registerListeners(): void { + public readonly onDidChangeFileSystemProviderRegistrations: Event = this._onDidChangeFileSystemProviderRegistrations.event; - // File events - this.toUnbind.push(this.raw.onFileChanges(e => this._onFileChanges.fire(e))); - this.toUnbind.push(this.raw.onAfterOperation(e => this._onAfterOperation.fire(e))); - - // Config changes - this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationChange(e))); - - // Root changes - this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); - - // Lifecycle - this.lifecycleService.onShutdown(this.dispose, this); + public registerProvider(scheme: string, provider: IFileSystemProvider): IDisposable { + throw new Error('not implemented'); } - private onDidChangeWorkspaceFolders(): void { - this.updateOptions({ encodingOverride: this.getEncodingOverrides() }); - } - - private getEncodingOverrides(): IEncodingOverride[] { - const encodingOverride: IEncodingOverride[] = []; - encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - this.contextService.getWorkspace().folders.forEach(folder => { - // {{SQL CARBON EDIT}} - encodingOverride.push({ resource: uri.file(paths.join(folder.uri.fsPath, '.sqlops')), encoding: encoding.UTF8 }); - }); - - return encodingOverride; - } - - private onConfigurationChange(event: IConfigurationChangeEvent): void { - if (event.affectsConfiguration('files.useExperimentalFileWatcher')) { - this.updateOptions({ useExperimentalFileWatcher: this.configurationService.getValue('files.useExperimentalFileWatcher') }); - } - } - - public updateOptions(options: object): void { - this.raw.updateOptions(options); + public canHandleResource(resource: uri): boolean { + return resource.scheme === Schemas.file; } public resolveFile(resource: uri, options?: IResolveFileOptions): TPromise { - return this.raw.resolveFile(resource, options); + return this.resolve(resource, options); } public resolveFiles(toResolve: { resource: uri, options?: IResolveFileOptions }[]): TPromise { - return this.raw.resolveFiles(toResolve); + return TPromise.join(toResolve.map(resourceAndOptions => this.resolve(resourceAndOptions.resource, resourceAndOptions.options) + .then(stat => ({ stat, success: true }), error => ({ stat: void 0, success: false })))); } public existsFile(resource: uri): TPromise { - return this.raw.existsFile(resource); + return this.resolveFile(resource).then(() => true, () => false); } public resolveContent(resource: uri, options?: IResolveContentOptions): TPromise { - return this.raw.resolveContent(resource, options); + return this.resolveStreamContent(resource, options).then(streamContent => { + return new TPromise((resolve, reject) => { + + const result: IContent = { + resource: streamContent.resource, + name: streamContent.name, + mtime: streamContent.mtime, + etag: streamContent.etag, + encoding: streamContent.encoding, + value: '' + }; + + streamContent.value.on('data', chunk => result.value += chunk); + streamContent.value.on('error', err => reject(err)); + streamContent.value.on('end', _ => resolve(result)); + + return result; + }); + }); } public resolveStreamContent(resource: uri, options?: IResolveContentOptions): TPromise { - return this.raw.resolveStreamContent(resource, options); + + // Guard early against attempts to resolve an invalid file path + if (resource.scheme !== Schemas.file || !resource.fsPath) { + return TPromise.wrapError(new FileOperationError( + nls.localize('fileInvalidPath', "Invalid file resource ({0})", resource.toString(true)), + FileOperationResult.FILE_INVALID_PATH, + options + )); + } + + const result: IStreamContent = { + resource: void 0, + name: void 0, + mtime: void 0, + etag: void 0, + encoding: void 0, + value: void 0 + }; + + const contentResolverTokenSource = new CancellationTokenSource(); + + const onStatError = (error: Error) => { + + // error: stop reading the file the stat and content resolve call + // usually race, mostly likely the stat call will win and cancel + // the content call + contentResolverTokenSource.cancel(); + + // forward error + return TPromise.wrapError(error); + }; + + const statsPromise = this.resolveFile(resource).then(stat => { + result.resource = stat.resource; + result.name = stat.name; + result.mtime = stat.mtime; + result.etag = stat.etag; + + // Return early if resource is a directory + if (stat.isDirectory) { + return onStatError(new FileOperationError( + nls.localize('fileIsDirectoryError', "File is directory"), + FileOperationResult.FILE_IS_DIRECTORY, + options + )); + } + + // Return early if file not modified since + if (options && options.etag && options.etag === stat.etag) { + return onStatError(new FileOperationError( + nls.localize('fileNotModifiedError', "File not modified since"), + FileOperationResult.FILE_NOT_MODIFIED_SINCE, + options + )); + } + + // Return early if file is too large to load + if (typeof stat.size === 'number') { + if (stat.size > Math.max(this.environmentService.args['max-memory'] * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { + return onStatError(new FileOperationError( + nls.localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart VS Code and allow it to use more memory"), + FileOperationResult.FILE_EXCEED_MEMORY_LIMIT + )); + } + + if (stat.size > MAX_FILE_SIZE) { + return onStatError(new FileOperationError( + nls.localize('fileTooLargeError', "File too large to open"), + FileOperationResult.FILE_TOO_LARGE + )); + } + } + + return void 0; + }, err => { + + // Wrap file not found errors + if (err.code === 'ENOENT') { + return onStatError(new FileOperationError( + nls.localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), + FileOperationResult.FILE_NOT_FOUND, + options + )); + } + + return onStatError(err); + }); + + let completePromise: Thenable; + + // await the stat iff we already have an etag so that we compare the + // etag from the stat before we actually read the file again. + if (options && options.etag) { + completePromise = statsPromise.then(() => { + return this.fillInContents(result, resource, options, contentResolverTokenSource.token); // Waterfall -> only now resolve the contents + }); + } + + // a fresh load without a previous etag which means we can resolve the file stat + // and the content at the same time, avoiding the waterfall. + else { + completePromise = Promise.all([statsPromise, this.fillInContents(result, resource, options, contentResolverTokenSource.token)]); + } + + return TPromise.wrap(completePromise).then(() => { + contentResolverTokenSource.dispose(); + + return result; + }); } - public updateContent(resource: uri, value: string | ITextSnapshot, options?: IUpdateContentOptions): TPromise { - return this.raw.updateContent(resource, value, options); + private fillInContents(content: IStreamContent, resource: uri, options: IResolveContentOptions, token: CancellationToken): Thenable { + return this.resolveFileData(resource, options, token).then(data => { + content.encoding = data.encoding; + content.value = data.stream; + }); } - public moveFile(source: uri, target: uri, overwrite?: boolean): TPromise { - return this.raw.moveFile(source, target, overwrite); + private resolveFileData(resource: uri, options: IResolveContentOptions, token: CancellationToken): Thenable { + + const chunkBuffer = BufferPool._64K.acquire(); + + const result: IContentData = { + encoding: void 0, + stream: void 0 + }; + + return new Promise((resolve, reject) => { + fs.open(this.toAbsolutePath(resource), 'r', (err, fd) => { + if (err) { + if (err.code === 'ENOENT') { + // Wrap file not found errors + err = new FileOperationError( + nls.localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), + FileOperationResult.FILE_NOT_FOUND, + options + ); + } + + return reject(err); + } + + let decoder: NodeJS.ReadWriteStream; + let totalBytesRead = 0; + + const finish = (err?: any) => { + + if (err) { + if (err.code === 'EISDIR') { + // Wrap EISDIR errors (fs.open on a directory works, but you cannot read from it) + err = new FileOperationError( + nls.localize('fileIsDirectoryError', "File is directory"), + FileOperationResult.FILE_IS_DIRECTORY, + options + ); + } + if (decoder) { + // If the decoder already started, we have to emit the error through it as + // event because the promise is already resolved! + decoder.emit('error', err); + } else { + reject(err); + } + } + if (decoder) { + decoder.end(); + } + + // return the shared buffer + BufferPool._64K.release(chunkBuffer); + + if (fd) { + fs.close(fd, err => { + if (err) { + this.handleError(`resolveFileData#close(): ${err.toString()}`); + } + }); + } + }; + + const handleChunk = (bytesRead: number) => { + if (token.isCancellationRequested) { + // cancellation -> finish + finish(new Error('cancelled')); + } else if (bytesRead === 0) { + // no more data -> finish + finish(); + } else if (bytesRead < chunkBuffer.length) { + // write the sub-part of data we received -> repeat + decoder.write(chunkBuffer.slice(0, bytesRead), readChunk); + } else { + // write all data we received -> repeat + decoder.write(chunkBuffer, readChunk); + } + }; + + let currentPosition: number = (options && options.position) || null; + + const readChunk = () => { + fs.read(fd, chunkBuffer, 0, chunkBuffer.length, currentPosition, (err, bytesRead) => { + totalBytesRead += bytesRead; + + if (typeof currentPosition === 'number') { + // if we received a position argument as option we need to ensure that + // we advance the position by the number of bytesread + currentPosition += bytesRead; + } + + if (totalBytesRead > Math.max(this.environmentService.args['max-memory'] * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { + finish(new FileOperationError( + nls.localize('fileTooLargeForHeapError', "To open a file of this size, you need to restart VS Code and allow it to use more memory"), + FileOperationResult.FILE_EXCEED_MEMORY_LIMIT + )); + } + + if (totalBytesRead > MAX_FILE_SIZE) { + // stop when reading too much + finish(new FileOperationError( + nls.localize('fileTooLargeError', "File too large to open"), + FileOperationResult.FILE_TOO_LARGE, + options + )); + } else if (err) { + // some error happened + finish(err); + + } else if (decoder) { + // pass on to decoder + handleChunk(bytesRead); + + } else { + // when receiving the first chunk of data we need to create the + // decoding stream which is then used to drive the string stream. + const autoGuessEncoding = (options && options.autoGuessEncoding) || this.textResourceConfigurationService.getValue(resource, 'files.autoGuessEncoding'); + TPromise.as(encoding.detectEncodingFromBuffer( + { buffer: chunkBuffer, bytesRead }, + autoGuessEncoding + )).then(detected => { + + if (options && options.acceptTextOnly && detected.seemsBinary) { + // Return error early if client only accepts text and this is not text + finish(new FileOperationError( + nls.localize('fileBinaryError', "File seems to be binary and cannot be opened as text"), + FileOperationResult.FILE_IS_BINARY, + options + )); + + } else { + result.encoding = this._encoding.getReadEncoding(resource, options, detected); + result.stream = decoder = encoding.decodeStream(result.encoding); + resolve(result); + handleChunk(bytesRead); + } + + }).then(void 0, err => { + // failed to get encoding + finish(err); + }); + } + }); + }; + + // start reading + readChunk(); + }); + }); } - public copyFile(source: uri, target: uri, overwrite?: boolean): TPromise { - return this.raw.copyFile(source, target, overwrite); + public updateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { + if (options.writeElevated) { + return this.doUpdateContentElevated(resource, value, options); + } + + return this.doUpdateContent(resource, value, options); } - public createFile(resource: uri, content?: string, options?: ICreateFileOptions): TPromise { - return this.raw.createFile(resource, content, options); + private doUpdateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { + const absolutePath = this.toAbsolutePath(resource); + + // 1.) check file for writing + return this.checkFileBeforeWriting(absolutePath, options).then(exists => { + let createParentsPromise: TPromise; + if (exists) { + createParentsPromise = TPromise.as(null); + } else { + createParentsPromise = pfs.mkdirp(paths.dirname(absolutePath)); + } + + // 2.) create parents as needed + return createParentsPromise.then(() => { + const encodingToWrite = this._encoding.getWriteEncoding(resource, options.encoding); + let addBomPromise: TPromise = TPromise.as(false); + + // UTF_16 BE and LE as well as UTF_8 with BOM always have a BOM + if (encodingToWrite === encoding.UTF16be || encodingToWrite === encoding.UTF16le || encodingToWrite === encoding.UTF8_with_bom) { + addBomPromise = TPromise.as(true); + } + + // Existing UTF-8 file: check for options regarding BOM + else if (exists && encodingToWrite === encoding.UTF8) { + if (options.overwriteEncoding) { + addBomPromise = TPromise.as(false); // if we are to overwrite the encoding, we do not preserve it if found + } else { + addBomPromise = encoding.detectEncodingByBOM(absolutePath).then(enc => enc === encoding.UTF8); // otherwise preserve it if found + } + } + + // 3.) check to add UTF BOM + return addBomPromise.then(addBom => { + + // 4.) set contents and resolve + return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite).then(void 0, error => { + if (!exists || error.code !== 'EPERM' || !isWindows) { + return TPromise.wrapError(error); + } + + // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file + // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows + // (see https://github.com/Microsoft/vscode/issues/931) + + // 5.) truncate + return pfs.truncate(absolutePath, 0).then(() => { + + // 6.) set contents (this time with r+ mode) and resolve again + return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite, { flag: 'r+' }); + }); + }); + }); + }); + }).then(null, error => { + if (error.code === 'EACCES' || error.code === 'EPERM') { + return TPromise.wrapError(new FileOperationError( + nls.localize('filePermission', "Permission denied writing to file ({0})", resource.toString(true)), + FileOperationResult.FILE_PERMISSION_DENIED, + options + )); + } + + return TPromise.wrapError(error); + }); + } + + private doSetContentsAndResolve(resource: uri, absolutePath: string, value: string | ITextSnapshot, addBOM: boolean, encodingToWrite: string, options?: { mode?: number; flag?: string; }): TPromise { + let writeFilePromise: TPromise; + + // Configure encoding related options as needed + const writeFileOptions: extfs.IWriteFileOptions = options ? options : Object.create(null); + if (addBOM || encodingToWrite !== encoding.UTF8) { + writeFileOptions.encoding = { + charset: encodingToWrite, + addBOM + }; + } + + if (typeof value === 'string') { + writeFilePromise = pfs.writeFile(absolutePath, value, writeFileOptions); + } else { + writeFilePromise = pfs.writeFile(absolutePath, createReadableOfSnapshot(value), writeFileOptions); + } + + // set contents + return writeFilePromise.then(() => { + + // resolve + return this.resolve(resource); + }); + } + + private doUpdateContentElevated(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { + const absolutePath = this.toAbsolutePath(resource); + + // 1.) check file for writing + return this.checkFileBeforeWriting(absolutePath, options, options.overwriteReadonly /* ignore readonly if we overwrite readonly, this is handled via sudo later */).then(exists => { + const writeOptions: IUpdateContentOptions = objects.assign(Object.create(null), options); + writeOptions.writeElevated = false; + writeOptions.encoding = this._encoding.getWriteEncoding(resource, options.encoding); + + // 2.) write to a temporary file to be able to copy over later + const tmpPath = paths.join(os.tmpdir(), `code-elevated-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6)}`); + return this.updateContent(uri.file(tmpPath), value, writeOptions).then(() => { + + // 3.) invoke our CLI as super user + return (import('sudo-prompt')).then(sudoPrompt => { + return new TPromise((c, e) => { + const promptOptions = { + name: this.environmentService.appNameLong.replace('-', ''), + icns: (isMacintosh && this.environmentService.isBuilt) ? paths.join(paths.dirname(this.environmentService.appRoot), `${product.nameShort}.icns`) : void 0 + }; + + const sudoCommand: string[] = [`"${this.environmentService.cliPath}"`]; + if (options.overwriteReadonly) { + sudoCommand.push('--file-chmod'); + } + sudoCommand.push('--file-write', `"${tmpPath}"`, `"${absolutePath}"`); + + sudoPrompt.exec(sudoCommand.join(' '), promptOptions, (error: string, stdout: string, stderr: string) => { + if (error || stderr) { + e(error || stderr); + } else { + c(void 0); + } + }); + }); + }).then(() => { + + // 3.) delete temp file + return pfs.del(tmpPath, os.tmpdir()).then(() => { + + // 4.) resolve again + return this.resolve(resource); + }); + }); + }); + }).then(null, error => { + if (this.environmentService.verbose) { + this.handleError(`Unable to write to file '${resource.toString(true)}' as elevated user (${error})`); + } + + if (!FileOperationError.isFileOperationError(error)) { + error = new FileOperationError( + nls.localize('filePermission', "Permission denied writing to file ({0})", resource.toString(true)), + FileOperationResult.FILE_PERMISSION_DENIED, + options + ); + } + + return TPromise.wrapError(error); + }); + } + + public createFile(resource: uri, content: string = '', options: ICreateFileOptions = Object.create(null)): TPromise { + const absolutePath = this.toAbsolutePath(resource); + + let checkFilePromise: TPromise; + if (options.overwrite) { + checkFilePromise = TPromise.as(false); + } else { + checkFilePromise = pfs.exists(absolutePath); + } + + // Check file exists + return checkFilePromise.then(exists => { + if (exists && !options.overwrite) { + return TPromise.wrapError(new FileOperationError( + nls.localize('fileExists', "File to create already exists ({0})", resource.toString(true)), + FileOperationResult.FILE_MODIFIED_SINCE, + options + )); + } + + // Create file + return this.updateContent(resource, content).then(result => { + + // Events + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); + + return result; + }); + }); } public createFolder(resource: uri): TPromise { - return this.raw.createFolder(resource); + + // 1.) Create folder + const absolutePath = this.toAbsolutePath(resource); + return pfs.mkdirp(absolutePath).then(() => { + + // 2.) Resolve + return this.resolve(resource).then(result => { + + // Events + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); + + return result; + }); + }); } - public touchFile(resource: uri): TPromise { - return this.raw.touchFile(resource); + private checkFileBeforeWriting(absolutePath: string, options: IUpdateContentOptions = Object.create(null), ignoreReadonly?: boolean): TPromise { + return pfs.exists(absolutePath).then(exists => { + if (exists) { + return pfs.stat(absolutePath).then(stat => { + if (stat.isDirectory()) { + return TPromise.wrapError(new Error('Expected file is actually a directory')); + } + + // Dirty write prevention: if the file on disk has been changed and does not match our expected + // mtime and etag, we bail out to prevent dirty writing. + // + // First, we check for a mtime that is in the future before we do more checks. The assumption is + // that only the mtime is an indicator for a file that has changd on disk. + // + // Second, if the mtime has advanced, we compare the size of the file on disk with our previous + // one using the etag() function. Relying only on the mtime check has prooven to produce false + // positives due to file system weirdness (especially around remote file systems). As such, the + // check for size is a weaker check because it can return a false negative if the file has changed + // but to the same length. This is a compromise we take to avoid having to produce checksums of + // the file content for comparison which would be much slower to compute. + if (typeof options.mtime === 'number' && typeof options.etag === 'string' && options.mtime < stat.mtime.getTime() && options.etag !== etag(stat.size, options.mtime)) { + return TPromise.wrapError(new FileOperationError(nls.localize('fileModifiedError', "File Modified Since"), FileOperationResult.FILE_MODIFIED_SINCE, options)); + } + + // Throw if file is readonly and we are not instructed to overwrite + if (!ignoreReadonly && !(stat.mode & 128) /* readonly */) { + if (!options.overwriteReadonly) { + return this.readOnlyError(options); + } + + // Try to change mode to writeable + let mode = stat.mode; + mode = mode | 128; + return pfs.chmod(absolutePath, mode).then(() => { + + // Make sure to check the mode again, it could have failed + return pfs.stat(absolutePath).then(stat => { + if (!(stat.mode & 128) /* readonly */) { + return this.readOnlyError(options); + } + + return exists; + }); + }); + } + + return TPromise.as(exists); + }); + } + + return TPromise.as(exists); + }); + } + + private readOnlyError(options: IUpdateContentOptions): TPromise { + return TPromise.wrapError(new FileOperationError( + nls.localize('fileReadOnlyError', "File is Read Only"), + FileOperationResult.FILE_READ_ONLY, + options + )); } public rename(resource: uri, newName: string): TPromise { - return this.raw.rename(resource, newName); + const newPath = paths.join(paths.dirname(resource.fsPath), newName); + + return this.moveFile(resource, uri.file(newPath)); + } + + public moveFile(source: uri, target: uri, overwrite?: boolean): TPromise { + return this.moveOrCopyFile(source, target, false, overwrite); + } + + public copyFile(source: uri, target: uri, overwrite?: boolean): TPromise { + return this.moveOrCopyFile(source, target, true, overwrite); + } + + private moveOrCopyFile(source: uri, target: uri, keepCopy: boolean, overwrite: boolean): TPromise { + const sourcePath = this.toAbsolutePath(source); + const targetPath = this.toAbsolutePath(target); + + // 1.) move / copy + return this.doMoveOrCopyFile(sourcePath, targetPath, keepCopy, overwrite).then(() => { + + // 2.) resolve + return this.resolve(target).then(result => { + + // Events + this._onAfterOperation.fire(new FileOperationEvent(source, keepCopy ? FileOperation.COPY : FileOperation.MOVE, result)); + + return result; + }); + }); + } + + private doMoveOrCopyFile(sourcePath: string, targetPath: string, keepCopy: boolean, overwrite: boolean): TPromise { + + // 1.) validate operation + if (isParent(targetPath, sourcePath, !isLinux)) { + return TPromise.wrapError(new Error('Unable to move/copy when source path is parent of target path')); + } + + // 2.) check if target exists + return pfs.exists(targetPath).then(exists => { + const isCaseRename = sourcePath.toLowerCase() === targetPath.toLowerCase(); + const isSameFile = sourcePath === targetPath; + + // Return early with conflict if target exists and we are not told to overwrite + if (exists && !isCaseRename && !overwrite) { + return TPromise.wrapError(new FileOperationError(nls.localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), FileOperationResult.FILE_MOVE_CONFLICT)); + } + + // 3.) make sure target is deleted before we move/copy unless this is a case rename of the same file + let deleteTargetPromise = TPromise.wrap(void 0); + if (exists && !isCaseRename) { + if (isEqualOrParent(sourcePath, targetPath, !isLinux /* ignorecase */)) { + return TPromise.wrapError(new Error(nls.localize('unableToMoveCopyError', "Unable to move/copy. File would replace folder it is contained in."))); // catch this corner case! + } + + deleteTargetPromise = this.del(uri.file(targetPath)); + } + + return deleteTargetPromise.then(() => { + + // 4.) make sure parents exists + return pfs.mkdirp(paths.dirname(targetPath)).then(() => { + + // 4.) copy/move + if (isSameFile) { + return TPromise.wrap(null); + } else if (keepCopy) { + return nfcall(extfs.copy, sourcePath, targetPath); + } else { + return nfcall(extfs.mv, sourcePath, targetPath); + } + }).then(() => exists); + }); + }); } public del(resource: uri, useTrash?: boolean): TPromise { if (useTrash) { - return this.doMoveItemToTrash(resource); + return asWinJsPromise(() => this.doMoveItemToTrash(resource)); } - return this.raw.del(resource); + return this.doDelete(resource); } - private doMoveItemToTrash(resource: uri): TPromise { + private doMoveItemToTrash(resource: uri): Promise { const absolutePath = resource.fsPath; - const result = shell.moveItemToTrash(absolutePath); - if (!result) { - return TPromise.wrapError(new Error(isWindows ? nls.localize('binFailed', "Failed to move '{0}' to the recycle bin", paths.basename(absolutePath)) : nls.localize('trashFailed', "Failed to move '{0}' to the trash", paths.basename(absolutePath)))); - } - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE)); + return (import('electron')).then(electron => { // workaround for https://github.com/Microsoft/vscode/issues/48205 + const result = electron.shell.moveItemToTrash(absolutePath); + if (!result) { + return TPromise.wrapError(new Error(isWindows ? nls.localize('binFailed', "Failed to move '{0}' to the recycle bin", paths.basename(absolutePath)) : nls.localize('trashFailed', "Failed to move '{0}' to the trash", paths.basename(absolutePath)))); + } - return TPromise.as(null); + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE)); + + return TPromise.wrap(null); + }); } - public importFile(source: uri, targetFolder: uri): TPromise { - return this.raw.importFile(source, targetFolder).then((result) => { - return { - isNew: result && result.isNew, - stat: result && result.stat - }; + private doDelete(resource: uri): TPromise { + const absolutePath = this.toAbsolutePath(resource); + + return pfs.del(absolutePath, os.tmpdir()).then(() => { + + // Events + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE)); + }); + } + + // Helpers + + private toAbsolutePath(arg1: uri | IFileStat): string { + let resource: uri; + if (arg1 instanceof uri) { + resource = arg1; + } else { + resource = (arg1).resource; + } + + assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource: ${resource}`); + + return paths.normalize(resource.fsPath); + } + + private resolve(resource: uri, options: IResolveFileOptions = Object.create(null)): TPromise { + return this.toStatResolver(resource).then(model => model.resolve(options)); + } + + private toStatResolver(resource: uri): TPromise { + const absolutePath = this.toAbsolutePath(resource); + + return pfs.statLink(absolutePath).then(({ isSymbolicLink, stat }) => { + return new StatResolver(resource, isSymbolicLink, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.environmentService.verbose ? err => this.handleError(err) : void 0); }); } public watchFileChanges(resource: uri): void { - if (!resource) { - return; + assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource for watching: ${resource}`); + + // Create or get watcher for provided path + let watcher = this.activeFileChangesWatchers.get(resource); + if (!watcher) { + const fsPath = resource.fsPath; + const fsName = paths.basename(resource.fsPath); + + watcher = extfs.watch(fsPath, (eventType: string, filename: string) => { + const renamedOrDeleted = ((filename && filename !== fsName) || eventType === 'rename'); + + // The file was either deleted or renamed. Many tools apply changes to files in an + // atomic way ("Atomic Save") by first renaming the file to a temporary name and then + // renaming it back to the original name. Our watcher will detect this as a rename + // and then stops to work on Mac and Linux because the watcher is applied to the + // inode and not the name. The fix is to detect this case and trying to watch the file + // again after a certain delay. + // In addition, we send out a delete event if after a timeout we detect that the file + // does indeed not exist anymore. + if (renamedOrDeleted) { + + // Very important to dispose the watcher which now points to a stale inode + this.unwatchFileChanges(resource); + + // Wait a bit and try to install watcher again, assuming that the file was renamed quickly ("Atomic Save") + setTimeout(() => { + this.existsFile(resource).done(exists => { + + // File still exists, so reapply the watcher + if (exists) { + this.watchFileChanges(resource); + } + + // File seems to be really gone, so emit a deleted event + else { + this.onRawFileChange({ + type: FileChangeType.DELETED, + path: fsPath + }); + } + }); + }, FileService.FS_REWATCH_DELAY); + } + + // Handle raw file change + this.onRawFileChange({ + type: FileChangeType.UPDATED, + path: fsPath + }); + }, (error: string) => this.handleError(error)); + + if (watcher) { + this.activeFileChangesWatchers.set(resource, watcher); + } + } + } + + private onRawFileChange(event: IRawFileChange): void { + + // add to bucket of undelivered events + this.undeliveredRawFileChangesEvents.push(event); + + if (this.environmentService.verbose) { + console.log('%c[node.js Watcher]%c', 'color: green', 'color: black', event.type === FileChangeType.ADDED ? '[ADDED]' : event.type === FileChangeType.DELETED ? '[DELETED]' : '[CHANGED]', event.path); } - if (resource.scheme !== Schemas.file) { - return; // only support files - } + // handle emit through delayer to accommodate for bulk changes + this.fileChangesWatchDelayer.trigger(() => { + const buffer = this.undeliveredRawFileChangesEvents; + this.undeliveredRawFileChangesEvents = []; - // return early if the resource is inside the workspace for which we have another watcher in place - if (this.contextService.isInsideWorkspace(resource)) { - return; - } + // Normalize + const normalizedEvents = normalize(buffer); - this.raw.watchFileChanges(resource); + // Logging + if (this.environmentService.verbose) { + normalizedEvents.forEach(r => { + console.log('%c[node.js Watcher]%c >> normalized', 'color: green', 'color: black', r.type === FileChangeType.ADDED ? '[ADDED]' : r.type === FileChangeType.DELETED ? '[DELETED]' : '[CHANGED]', r.path); + }); + } + + // Emit + this._onFileChanges.fire(toFileChangesEvent(normalizedEvents)); + + return TPromise.as(null); + }); } public unwatchFileChanges(resource: uri): void { - this.raw.unwatchFileChanges(resource); - } - - public getEncoding(resource: uri, preferredEncoding?: string): string { - return this.raw.getEncoding(resource, preferredEncoding); + const watcher = this.activeFileChangesWatchers.get(resource); + if (watcher) { + watcher.close(); + this.activeFileChangesWatchers.delete(resource); + } } public dispose(): void { - this.toUnbind = dispose(this.toUnbind); + this.toDispose = dispose(this.toDispose); - // Dispose service - this.raw.dispose(); + if (this.activeWorkspaceFileChangeWatcher) { + this.activeWorkspaceFileChangeWatcher.dispose(); + this.activeWorkspaceFileChangeWatcher = null; + } + + this.activeFileChangesWatchers.forEach(watcher => watcher.close()); + this.activeFileChangesWatchers.clear(); + } +} + +function etag(stat: fs.Stats): string; +function etag(size: number, mtime: number): string; +function etag(arg1: any, arg2?: any): string { + let size: number; + let mtime: number; + if (typeof arg2 === 'number') { + size = arg1; + mtime = arg2; + } else { + size = (arg1).size; + mtime = (arg1).mtime.getTime(); + } + + return `"${crypto.createHash('sha1').update(String(size) + String(mtime)).digest('hex')}"`; +} + +export class StatResolver { + private name: string; + private etag: string; + + constructor( + private resource: uri, + private isSymbolicLink: boolean, + private isDirectory: boolean, + private mtime: number, + private size: number, + private errorLogger?: (error: Error | string) => void + ) { + assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource: ${resource}`); + + this.name = getBaseLabel(resource); + this.etag = etag(size, mtime); + } + + public resolve(options: IResolveFileOptions): TPromise { + + // General Data + const fileStat: IFileStat = { + resource: this.resource, + isDirectory: this.isDirectory, + isSymbolicLink: this.isSymbolicLink, + name: this.name, + etag: this.etag, + size: this.size, + mtime: this.mtime + }; + + // File Specific Data + if (!this.isDirectory) { + return TPromise.as(fileStat); + } + + // Directory Specific Data + else { + + // Convert the paths from options.resolveTo to absolute paths + let absoluteTargetPaths: string[] = null; + if (options && options.resolveTo) { + absoluteTargetPaths = []; + options.resolveTo.forEach(resource => { + absoluteTargetPaths.push(resource.fsPath); + }); + } + + return new TPromise((c, e) => { + + // Load children + this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, options && options.resolveSingleChildDescendants, children => { + children = arrays.coalesce(children); // we don't want those null children (could be permission denied when reading a child) + fileStat.children = children || []; + + c(fileStat); + }); + }); + } + } + + private resolveChildren(absolutePath: string, absoluteTargetPaths: string[], resolveSingleChildDescendants: boolean, callback: (children: IFileStat[]) => void): void { + extfs.readdir(absolutePath, (error: Error, files: string[]) => { + if (error) { + if (this.errorLogger) { + this.errorLogger(error); + } + + return callback(null); // return - we might not have permissions to read the folder + } + + // for each file in the folder + flow.parallel(files, (file: string, clb: (error: Error, children: IFileStat) => void) => { + const fileResource = uri.file(paths.resolve(absolutePath, file)); + let fileStat: fs.Stats; + let isSymbolicLink = false; + const $this = this; + + flow.sequence( + function onError(error: Error): void { + if ($this.errorLogger) { + $this.errorLogger(error); + } + + clb(null, null); // return - we might not have permissions to read the folder or stat the file + }, + + function stat(this: any): void { + extfs.statLink(fileResource.fsPath, this); + }, + + function countChildren(this: any, statAndLink: extfs.IStatAndLink): void { + fileStat = statAndLink.stat; + isSymbolicLink = statAndLink.isSymbolicLink; + + if (fileStat.isDirectory()) { + extfs.readdir(fileResource.fsPath, (error, result) => { + this(null, result ? result.length : 0); + }); + } else { + this(null, 0); + } + }, + + function resolve(childCount: number): void { + const childStat: IFileStat = { + resource: fileResource, + isDirectory: fileStat.isDirectory(), + isSymbolicLink, + name: file, + mtime: fileStat.mtime.getTime(), + etag: etag(fileStat), + size: fileStat.size + }; + + // Return early for files + if (!fileStat.isDirectory()) { + return clb(null, childStat); + } + + // Handle Folder + let resolveFolderChildren = false; + if (files.length === 1 && resolveSingleChildDescendants) { + resolveFolderChildren = true; + } else if (childCount > 0 && absoluteTargetPaths && absoluteTargetPaths.some(targetPath => isEqualOrParent(targetPath, fileResource.fsPath, !isLinux /* ignorecase */))) { + resolveFolderChildren = true; + } + + // Continue resolving children based on condition + if (resolveFolderChildren) { + $this.resolveChildren(fileResource.fsPath, absoluteTargetPaths, resolveSingleChildDescendants, children => { + children = arrays.coalesce(children); // we don't want those null children + childStat.children = children || []; + + clb(null, childStat); + }); + } + + // Otherwise return result + else { + clb(null, childStat); + } + }); + }, (errors, result) => { + callback(result); + }); + }); } } diff --git a/src/vs/workbench/services/files/electron-browser/remoteFileService.ts b/src/vs/workbench/services/files/electron-browser/remoteFileService.ts index 75bd8223b9..c496d58075 100644 --- a/src/vs/workbench/services/files/electron-browser/remoteFileService.ts +++ b/src/vs/workbench/services/files/electron-browser/remoteFileService.ts @@ -4,51 +4,62 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; -import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; -import { IContent, IStreamContent, IFileStat, IResolveContentOptions, IUpdateContentOptions, IResolveFileOptions, IResolveFileResult, FileOperationEvent, FileOperation, IFileSystemProvider, IStat, FileType, IImportResult, FileChangesEvent, ICreateFileOptions, FileOperationError, FileOperationResult, ITextSnapshot, snapshotToString } from 'vs/platform/files/common/files'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { basename, join } from 'path'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { isFalsyOrEmpty, distinct } from 'vs/base/common/arrays'; +import { posix } from 'path'; +import { flatten, isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { TernarySearchTree, keys } from 'vs/base/common/map'; import { Schemas } from 'vs/base/common/network'; -import { Progress } from 'vs/platform/progress/common/progress'; -import { decodeStream, encode, UTF8, UTF8_with_bom } from 'vs/base/node/encoding'; -import { TernarySearchTree } from 'vs/base/common/map'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IStorageService } from 'vs/platform/storage/common/storage'; +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IDecodeStreamOptions, toDecodeStream, encodeStream } from 'vs/base/node/encoding'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { maxBufferLen, detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; -import { MIME_BINARY } from 'vs/base/common/mime'; import { localize } from 'vs/nls'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { FileChangesEvent, FileOperation, FileOperationError, FileOperationEvent, FileOperationResult, FileWriteOptions, FileSystemProviderCapabilities, IContent, ICreateFileOptions, IFileStat, IFileSystemProvider, IFilesConfiguration, IResolveContentOptions, IResolveFileOptions, IResolveFileResult, IStat, IStreamContent, ITextSnapshot, IUpdateContentOptions, StringSnapshot, IWatchOptions, FileType } from 'vs/platform/files/common/files'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; +import { createReadableOfProvider, createReadableOfSnapshot, createWritableOfProvider } from 'vs/workbench/services/files/electron-browser/streams'; + +class TypeOnlyStat implements IStat { + + constructor(readonly type: FileType) { + // + } + + // todo@remote -> make a getter and warn when + // being used in development. + mtime: number = 0; + ctime: number = 0; + size: number = 0; +} function toIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], recurse?: (tuple: [URI, IStat]) => boolean): TPromise { const [resource, stat] = tuple; const fileStat: IFileStat = { - isDirectory: false, - isSymbolicLink: stat.type === FileType.Symlink, - resource: resource, - name: basename(resource.path), + resource, + name: posix.basename(resource.path), + isDirectory: (stat.type & FileType.Directory) !== 0, + isSymbolicLink: (stat.type & FileType.SymbolicLink) !== 0, mtime: stat.mtime, size: stat.size, etag: stat.mtime.toString(29) + stat.size.toString(31), }; - if (stat.type === FileType.Dir) { - fileStat.isDirectory = true; - + if (fileStat.isDirectory) { if (recurse && recurse([resource, stat])) { // dir -> resolve return provider.readdir(resource).then(entries => { - fileStat.isDirectory = true; - // resolve children if requested - return TPromise.join(entries.map(stat => toIFileStat(provider, stat, recurse))).then(children => { + return TPromise.join(entries.map(tuple => { + const [name, type] = tuple; + const childResource = resource.with({ path: posix.join(resource.path, name) }); + return toIFileStat(provider, [childResource, new TypeOnlyStat(type)], recurse); + })).then(children => { fileStat.children = children; return fileStat; }); @@ -74,66 +85,183 @@ export function toDeepIFileStat(provider: IFileSystemProvider, tuple: [URI, ISta }); } +class WorkspaceWatchLogic { + + private _disposables: IDisposable[] = []; + private _watches = new Map(); + + constructor( + private _fileService: RemoteFileService, + @IConfigurationService private _configurationService: IConfigurationService, + @IWorkspaceContextService private _contextService: IWorkspaceContextService, + ) { + this._refresh(); + + this._disposables.push(this._contextService.onDidChangeWorkspaceFolders(e => { + for (const removed of e.removed) { + this._unwatchWorkspace(removed.uri); + } + for (const added of e.added) { + this._watchWorkspace(added.uri); + } + })); + this._disposables.push(this._contextService.onDidChangeWorkbenchState(e => { + this._refresh(); + })); + this._disposables.push(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('files.watcherExclude')) { + this._refresh(); + } + })); + } + + dispose(): void { + this._unwatchWorkspaces(); + this._disposables = dispose(this._disposables); + } + + private _refresh(): void { + this._unwatchWorkspaces(); + for (const folder of this._contextService.getWorkspace().folders) { + if (folder.uri.scheme !== Schemas.file) { + this._watchWorkspace(folder.uri); + } + } + } + + private _watchWorkspace(resource: URI) { + let excludes: string[] = []; + let config = this._configurationService.getValue({ resource }); + if (config.files && config.files.watcherExclude) { + for (const key in config.files.watcherExclude) { + if (config.files.watcherExclude[key] === true) { + excludes.push(key); + } + } + } + this._watches.set(resource.toString(), resource); + this._fileService.watchFileChanges(resource, { recursive: true, excludes }); + } + + private _unwatchWorkspace(resource: URI) { + if (this._watches.has(resource.toString())) { + this._fileService.unwatchFileChanges(resource); + this._watches.delete(resource.toString()); + } + } + + private _unwatchWorkspaces() { + this._watches.forEach(uri => this._fileService.unwatchFileChanges(uri)); + this._watches.clear(); + } +} + export class RemoteFileService extends FileService { - private readonly _provider = new Map(); - private _supportedSchemes: string[]; + private readonly _provider: Map; + private readonly _lastKnownSchemes: string[]; constructor( @IExtensionService private readonly _extensionService: IExtensionService, @IStorageService private readonly _storageService: IStorageService, + @IEnvironmentService private readonly _environmentService: IEnvironmentService, @IConfigurationService configurationService: IConfigurationService, @IWorkspaceContextService contextService: IWorkspaceContextService, - @IEnvironmentService environmentService: IEnvironmentService, @ILifecycleService lifecycleService: ILifecycleService, - @IChoiceService choiceService: IChoiceService, + @INotificationService notificationService: INotificationService, @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService, ) { super( - configurationService, contextService, - environmentService, - lifecycleService, - choiceService, - _storageService, + _environmentService, textResourceConfigurationService, + configurationService, + lifecycleService, + _storageService, + notificationService ); - this._supportedSchemes = JSON.parse(this._storageService.get('remote_schemes', undefined, '[]')); + this._provider = new Map(); + this._lastKnownSchemes = JSON.parse(this._storageService.get('remote_schemes', undefined, '[]')); + this.toDispose.push(new WorkspaceWatchLogic(this, configurationService, contextService)); } - registerProvider(authority: string, provider: IFileSystemProvider): IDisposable { - if (this._provider.has(authority)) { - throw new Error(); + registerProvider(scheme: string, provider: IFileSystemProvider): IDisposable { + if (this._provider.has(scheme)) { + throw new Error('a provider for that scheme is already registered'); } - this._supportedSchemes.push(authority); - this._storageService.store('remote_schemes', JSON.stringify(distinct(this._supportedSchemes))); + this._provider.set(scheme, provider); + this._onDidChangeFileSystemProviderRegistrations.fire({ added: true, scheme, provider }); + this._storageService.store('remote_schemes', JSON.stringify(keys(this._provider))); - this._provider.set(authority, provider); - const reg = provider.onDidChange(changes => { + const reg = provider.onDidChangeFile(changes => { // forward change events this._onFileChanges.fire(new FileChangesEvent(changes)); }); return { dispose: () => { - this._provider.delete(authority); + this._onDidChangeFileSystemProviderRegistrations.fire({ added: false, scheme, provider }); + this._provider.delete(scheme); reg.dispose(); } }; } canHandleResource(resource: URI): boolean { - return resource.scheme === Schemas.file - || this._provider.has(resource.scheme) - // TODO@remote - || this._supportedSchemes.indexOf(resource.scheme) >= 0; + if (resource.scheme === Schemas.file || this._provider.has(resource.scheme)) { + return true; + } + // TODO@remote + // this needs to go, but this already went viral + // https://github.com/Microsoft/vscode/issues/48275 + if (this._lastKnownSchemes.indexOf(resource.scheme) < 0) { + return false; + } + if (!this._environmentService.isBuilt) { + console.warn('[remote] cache information required for ' + resource.toString()); + } + return true; + } + + private _tryParseFileOperationResult(err: any): FileOperationResult { + if (!(err instanceof Error)) { + return undefined; + } + let match = /^(.+) \(FileSystemError\)$/.exec(err.name); + if (!match) { + return undefined; + } + let res: FileOperationResult; + switch (match[1]) { + case 'EntryNotFound': + res = FileOperationResult.FILE_NOT_FOUND; + break; + case 'EntryIsADirectory': + res = FileOperationResult.FILE_IS_DIRECTORY; + break; + case 'NoPermissions': + res = FileOperationResult.FILE_PERMISSION_DENIED; + break; + case 'EntryExists': + res = FileOperationResult.FILE_MOVE_CONFLICT; + break; + case 'EntryNotADirectory': + default: + // todo + res = undefined; + break; + } + return res; } // --- stat private _withProvider(resource: URI): TPromise { - return this._extensionService.activateByEvent('onFileSystemAccess:' + resource.scheme).then(() => { + return TPromise.join([ + this._extensionService.activateByEvent('onFileSystem:' + resource.scheme), + this._extensionService.activateByEvent('onFileSystemAccess:' + resource.scheme) // todo@remote -> remove + ]).then(() => { const provider = this._provider.get(resource.scheme); if (!provider) { const err = new Error(); @@ -159,7 +287,10 @@ export class RemoteFileService extends FileService { } else { return this._doResolveFiles([{ resource, options }]).then(data => { if (data.length !== 1 || !data[0].success) { - throw new Error(`ENOENT, ${resource}`); + throw new FileOperationError( + localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), + FileOperationResult.FILE_NOT_FOUND + ); } else { return data[0].stat; } @@ -188,9 +319,7 @@ export class RemoteFileService extends FileService { promises.push(this._doResolveFiles(group)); } } - return TPromise.join(promises).then(data => { - return [].concat(...data); - }); + return TPromise.join(promises).then(data => flatten(data)); } private _doResolveFiles(toResolve: { resource: URI; options?: IResolveFileOptions; }[]): TPromise { @@ -215,7 +344,7 @@ export class RemoteFileService extends FileService { if (resource.scheme === Schemas.file) { return super.resolveContent(resource, options); } else { - return this._doResolveContent(resource, options).then(RemoteFileService._asContent); + return this._readFile(resource, options).then(RemoteFileService._asContent); } } @@ -223,11 +352,11 @@ export class RemoteFileService extends FileService { if (resource.scheme === Schemas.file) { return super.resolveStreamContent(resource, options); } else { - return this._doResolveContent(resource, options); + return this._readFile(resource, options); } } - private _doResolveContent(resource: URI, options: IResolveContentOptions = Object.create(null)): TPromise { + private _readFile(resource: URI, options: IResolveContentOptions = Object.create(null)): TPromise { return this._withProvider(resource).then(provider => { return this.resolveFile(resource).then(fileStat => { @@ -249,20 +378,18 @@ export class RemoteFileService extends FileService { ); } - const guessEncoding = options.autoGuessEncoding; - const count = maxBufferLen(options); - const chunks: Buffer[] = []; + const decodeStreamOpts: IDecodeStreamOptions = { + guessEncoding: options.autoGuessEncoding, + overwriteEncoding: detected => { + return this.encoding.getReadEncoding(resource, options, { encoding: detected, seemsBinary: false }); + } + }; - return provider.read( - resource, - 0, count, - new Progress(chunk => chunks.push(chunk)) - ).then(bytesRead => { - // send to bla - return detectMimeAndEncodingFromBuffer({ bytesRead, buffer: Buffer.concat(chunks) }, guessEncoding); + const readable = createReadableOfProvider(provider, resource, options.position || 0); - }).then(detected => { - if (options.acceptTextOnly && detected.mimes.indexOf(MIME_BINARY) >= 0) { + return toDecodeStream(readable, decodeStreamOpts).then(data => { + + if (options.acceptTextOnly && data.detected.seemsBinary) { return TPromise.wrapError(new FileOperationError( localize('fileBinaryError', "File seems to be binary and cannot be opened as text"), FileOperationResult.FILE_IS_BINARY, @@ -270,53 +397,9 @@ export class RemoteFileService extends FileService { )); } - let preferredEncoding: string; - if (options && options.encoding) { - if (detected.encoding === UTF8 && options.encoding === UTF8) { - preferredEncoding = UTF8_with_bom; // indicate the file has BOM if we are to resolve with UTF 8 - } else { - preferredEncoding = options.encoding; // give passed in encoding highest priority - } - } else if (detected.encoding) { - if (detected.encoding === UTF8) { - preferredEncoding = UTF8_with_bom; // if we detected UTF-8, it can only be because of a BOM - } else { - preferredEncoding = detected.encoding; - } - // todo@remote - encoding logic should not be kept - // hostage inside the node file service - // } else if (super.configuredEncoding(resource) === UTF8_with_bom) { - } else { - preferredEncoding = UTF8; // if we did not detect UTF 8 BOM before, this can only be UTF 8 then - } - - // const encoding = this.getEncoding(resource); - const stream = decodeStream(preferredEncoding); - - // start with what we have already read - // and have a new stream to read the rest - let offset = 0; - for (const chunk of chunks) { - stream.write(chunk); - offset += chunk.length; - } - if (offset < count) { - // we didn't read enough the first time which means - // that we are done - stream.end(); - } else { - // there is more to read - provider.read(resource, offset, -1, new Progress(chunk => stream.write(chunk))).then(() => { - stream.end(); - }, err => { - stream.emit('error', err); - stream.end(); - }); - } - - return { - encoding: preferredEncoding, - value: stream, + return { + encoding: data.detected.encoding, + value: data.stream, resource: fileStat.resource, name: fileStat.name, etag: fileStat.etag, @@ -329,25 +412,46 @@ export class RemoteFileService extends FileService { // --- saving + private static async _mkdirp(provider: IFileSystemProvider, directory: URI): Promise { + + let basenames: string[] = []; + while (directory.path !== '/') { + try { + let stat = await provider.stat(directory); + if ((stat.type & FileType.Directory) === 0) { + throw new Error(`${directory.toString()} is not a directory`); + } + break; // we have hit a directory -> good + } catch (e) { + // ENOENT + basenames.push(posix.basename(directory.path)); + directory = directory.with({ path: posix.dirname(directory.path) }); + } + } + for (let i = basenames.length - 1; i >= 0; i--) { + directory = directory.with({ path: posix.join(directory.path, basenames[i]) }); + await provider.mkdir(directory); + } + } + createFile(resource: URI, content?: string, options?: ICreateFileOptions): TPromise { if (resource.scheme === Schemas.file) { return super.createFile(resource, content, options); } else { + return this._withProvider(resource).then(provider => { - let prepare = options && !options.overwrite - ? this.existsFile(resource) - : TPromise.as(false); - - - return prepare.then(exists => { - if (exists && options && !options.overwrite) { - return TPromise.wrapError(new FileOperationError('EEXIST', FileOperationResult.FILE_MODIFIED_SINCE, options)); - } - return this._doUpdateContent(provider, resource, content || '', {}); - }).then(fileStat => { - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat)); - return fileStat; + return RemoteFileService._mkdirp(provider, resource.with({ path: posix.dirname(resource.path) })).then(() => { + const encoding = this.encoding.getWriteEncoding(resource); + return this._writeFile(provider, resource, new StringSnapshot(content), encoding, { create: true, overwrite: Boolean(options && options.overwrite) }); }); + + }).then(fileStat => { + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat)); + return fileStat; + }, err => { + const message = localize('err.create', "Failed to create file {0}", resource.toString(false)); + const result = this._tryParseFileOperationResult(err); + throw new FileOperationError(message, result, options); }); } } @@ -357,15 +461,24 @@ export class RemoteFileService extends FileService { return super.updateContent(resource, value, options); } else { return this._withProvider(resource).then(provider => { - return this._doUpdateContent(provider, resource, value, options || {}); + return RemoteFileService._mkdirp(provider, resource.with({ path: posix.dirname(resource.path) })).then(() => { + const snapshot = typeof value === 'string' ? new StringSnapshot(value) : value; + return this._writeFile(provider, resource, snapshot, options && options.encoding, { create: true, overwrite: true }); + }); }); } } - private _doUpdateContent(provider: IFileSystemProvider, resource: URI, content: string | ITextSnapshot, options: IUpdateContentOptions): TPromise { - const encoding = this.getEncoding(resource, options.encoding); - // TODO@Joh support streaming API for remote file system writes - return provider.write(resource, encode(typeof content === 'string' ? content : snapshotToString(content), encoding)).then(() => { + private _writeFile(provider: IFileSystemProvider, resource: URI, snapshot: ITextSnapshot, preferredEncoding: string, options: FileWriteOptions): TPromise { + const readable = createReadableOfSnapshot(snapshot); + const encoding = this.encoding.getWriteEncoding(resource, preferredEncoding); + const encoder = encodeStream(encoding); + const target = createWritableOfProvider(provider, resource, options); + return new TPromise((resolve, reject) => { + readable.pipe(encoder).pipe(target); + target.once('error', err => reject(err)); + target.once('finish', _ => resolve(void 0)); + }).then(_ => { return this.resolveFile(resource); }); } @@ -393,9 +506,7 @@ export class RemoteFileService extends FileService { return super.del(resource, useTrash); } else { return this._withProvider(resource).then(provider => { - return provider.stat(resource).then(stat => { - return stat.type === FileType.Dir ? provider.rmdir(resource) : provider.unlink(resource); - }).then(() => { + return provider.delete(resource).then(() => { this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE)); }); }); @@ -407,8 +518,10 @@ export class RemoteFileService extends FileService { return super.createFolder(resource); } else { return this._withProvider(resource).then(provider => { - return provider.mkdir(resource).then(stat => { - return toIFileStat(provider, [resource, stat]); + return RemoteFileService._mkdirp(provider, resource.with({ path: posix.dirname(resource.path) })).then(() => { + return provider.mkdir(resource).then(() => { + return this.resolveFile(resource); + }); }); }).then(fileStat => { this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat)); @@ -421,7 +534,7 @@ export class RemoteFileService extends FileService { if (resource.scheme === Schemas.file) { return super.rename(resource, newName); } else { - const target = resource.with({ path: join(resource.path, '..', newName) }); + const target = resource.with({ path: posix.join(resource.path, '..', newName) }); return this._doMoveWithInScheme(resource, target, false); } } @@ -443,11 +556,17 @@ export class RemoteFileService extends FileService { : TPromise.as(null); return prepare.then(() => this._withProvider(source)).then(provider => { - return provider.move(source, target).then(stat => { - return toIFileStat(provider, [target, stat]); + return provider.rename(source, target, { overwrite }).then(() => { + return this.resolveFile(target); }).then(fileStat => { this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.MOVE, fileStat)); return fileStat; + }, err => { + const result = this._tryParseFileOperationResult(err); + if (result === FileOperationResult.FILE_MOVE_CONFLICT) { + throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); + } + throw err; }); }); } @@ -463,75 +582,99 @@ export class RemoteFileService extends FileService { }); } - importFile(source: URI, targetFolder: URI): TPromise { - if (source.scheme === targetFolder.scheme && source.scheme === Schemas.file) { - return super.importFile(source, targetFolder); - } else { - const target = targetFolder.with({ path: join(targetFolder.path, basename(source.path)) }); - return this.copyFile(source, target, false).then(stat => ({ stat, isNew: false })); - } - } - copyFile(source: URI, target: URI, overwrite?: boolean): TPromise { if (source.scheme === target.scheme && source.scheme === Schemas.file) { return super.copyFile(source, target, overwrite); } - const prepare = overwrite - ? this.del(target).then(undefined, err => { /*ignore*/ }) - : TPromise.as(null); + return this._withProvider(target).then(provider => { - return prepare.then(() => { - // todo@ben, can only copy text files - // https://github.com/Microsoft/vscode/issues/41543 - return this.resolveContent(source, { acceptTextOnly: true }).then(content => { - return this._withProvider(target).then(provider => { - return this._doUpdateContent(provider, target, content.value, { encoding: content.encoding }).then(fileStat => { - this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); - return fileStat; - }); + if (source.scheme === target.scheme && (provider.capabilities & FileSystemProviderCapabilities.FileFolderCopy)) { + // good: provider supports copy withing scheme + return provider.copy(source, target, { overwrite }).then(() => { + return this.resolveFile(target); + }).then(fileStat => { + this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); + return fileStat; }, err => { - if (err instanceof Error && err.name === 'ENOPRO') { - // file scheme - return super.updateContent(target, content.value, { encoding: content.encoding }); - } else { - return TPromise.wrapError(err); + const result = this._tryParseFileOperationResult(err); + if (result === FileOperationResult.FILE_MOVE_CONFLICT) { + throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); } + throw err; + }); + } + + const prepare = overwrite + ? this.del(target).then(undefined, err => { /*ignore*/ }) + : TPromise.as(null); + + return prepare.then(() => { + // todo@ben, can only copy text files + // https://github.com/Microsoft/vscode/issues/41543 + return this.resolveContent(source, { acceptTextOnly: true }).then(content => { + return this._withProvider(target).then(provider => { + return this._writeFile( + provider, target, + new StringSnapshot(content.value), + content.encoding, + { create: true, overwrite } + ).then(fileStat => { + this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat)); + return fileStat; + }); + }, err => { + const result = this._tryParseFileOperationResult(err); + if (result === FileOperationResult.FILE_MOVE_CONFLICT) { + throw new FileOperationError(localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), result); + } else if (err instanceof Error && err.name === 'ENOPRO') { + // file scheme + return super.updateContent(target, content.value, { encoding: content.encoding }); + } else { + return TPromise.wrapError(err); + } + }); }); }); }); - } - touchFile(resource: URI): TPromise { + private _activeWatches = new Map, count: number }>(); + + public watchFileChanges(resource: URI, opts?: IWatchOptions): void { if (resource.scheme === Schemas.file) { - return super.touchFile(resource); - } else { - return this._doTouchFile(resource); + return super.watchFileChanges(resource); } - } - private _doTouchFile(resource: URI): TPromise { - return this._withProvider(resource).then(provider => { - return provider.stat(resource).then(() => { - return provider.utimes(resource, Date.now(), Date.now()); + if (!opts) { + opts = { recursive: false, excludes: [] }; + } + + const key = resource.toString(); + const entry = this._activeWatches.get(key); + if (entry) { + entry.count += 1; + return; + } + + this._activeWatches.set(key, { + count: 1, + unwatch: this._withProvider(resource).then(provider => { + return provider.watch(resource, opts); }, err => { - return provider.write(resource, new Uint8Array(0)); - }).then(() => { - return this.resolveFile(resource); - }); + return { dispose() { } }; + }) }); } - // TODO@Joh - file watching on demand! - public watchFileChanges(resource: URI): void { - if (resource.scheme === Schemas.file) { - super.watchFileChanges(resource); - } - } public unwatchFileChanges(resource: URI): void { if (resource.scheme === Schemas.file) { - super.unwatchFileChanges(resource); + return super.unwatchFileChanges(resource); + } + let entry = this._activeWatches.get(resource.toString()); + if (entry && --entry.count === 0) { + entry.unwatch.then(dispose); + this._activeWatches.delete(resource.toString()); } } } diff --git a/src/vs/workbench/services/files/electron-browser/streams.ts b/src/vs/workbench/services/files/electron-browser/streams.ts new file mode 100644 index 0000000000..2979cd728e --- /dev/null +++ b/src/vs/workbench/services/files/electron-browser/streams.ts @@ -0,0 +1,168 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { Readable, Writable } from 'stream'; +import { UTF8 } from 'vs/base/node/encoding'; +import URI from 'vs/base/common/uri'; +import { IFileSystemProvider, ITextSnapshot, FileSystemProviderCapabilities, FileWriteOptions } from 'vs/platform/files/common/files'; +import { illegalArgument } from 'vs/base/common/errors'; + +export function createWritableOfProvider(provider: IFileSystemProvider, resource: URI, opts: FileWriteOptions): Writable { + if (provider.capabilities & FileSystemProviderCapabilities.FileOpenReadWriteClose) { + return createWritable(provider, resource, opts); + } else if (provider.capabilities & FileSystemProviderCapabilities.FileReadWrite) { + return createSimpleWritable(provider, resource, opts); + } else { + throw illegalArgument(); + } +} + +function createSimpleWritable(provider: IFileSystemProvider, resource: URI, opts: FileWriteOptions): Writable { + return new class extends Writable { + _chunks: Buffer[] = []; + constructor(opts?) { + super(opts); + } + _write(chunk: Buffer, encoding: string, callback: Function) { + this._chunks.push(chunk); + callback(null); + } + end() { + // todo@joh - end might have another chunk... + provider.writeFile(resource, Buffer.concat(this._chunks), opts).then(_ => { + super.end(); + }, err => { + this.emit('error', err); + }); + } + }; +} + +function createWritable(provider: IFileSystemProvider, resource: URI, opts: FileWriteOptions): Writable { + return new class extends Writable { + _fd: number; + _pos: number; + constructor(opts?) { + super(opts); + } + async _write(chunk: Buffer, encoding, callback: Function) { + try { + if (typeof this._fd !== 'number') { + this._fd = await provider.open(resource); + } + let bytesWritten = await provider.write(this._fd, this._pos, chunk, 0, chunk.length); + this._pos += bytesWritten; + callback(); + } catch (err) { + callback(err); + } + } + end() { + provider.close(this._fd).then(_ => { + super.end(); + }, err => { + this.emit('error', err); + }); + } + }; +} + +export function createReadableOfProvider(provider: IFileSystemProvider, resource: URI, position: number): Readable { + if (provider.capabilities & FileSystemProviderCapabilities.FileOpenReadWriteClose) { + return createReadable(provider, resource, position); + } else if (provider.capabilities & FileSystemProviderCapabilities.FileReadWrite) { + return createSimpleReadable(provider, resource, position); + } else { + throw illegalArgument(); + } +} + +function createReadable(provider: IFileSystemProvider, resource: URI, position: number): Readable { + return new class extends Readable { + _fd: number; + _pos: number = position; + _reading: boolean = false; + constructor(opts?) { + super(opts); + this.once('close', _ => this._final()); + } + async _read(size?: number) { + if (this._reading) { + return; + } + this._reading = true; + try { + if (typeof this._fd !== 'number') { + this._fd = await provider.open(resource); + } + let buffer = Buffer.allocUnsafe(64 * 1024); + while (this._reading) { + let bytesRead = await provider.read(this._fd, this._pos, buffer, 0, buffer.length); + if (bytesRead === 0) { + this._reading = false; + this.push(null); + } + else { + this._reading = this.push(buffer.slice(0, bytesRead)); + this._pos += bytesRead; + } + } + } + catch (err) { + // + this.emit('error', err); + } + } + async _final() { + if (typeof this._fd === 'number') { + await provider.close(this._fd); + } + } + }; +} + +function createSimpleReadable(provider: IFileSystemProvider, resource: URI, position: number): Readable { + return new class extends Readable { + _readOperation: Thenable; + _read(size?: number): void { + if (this._readOperation) { + return; + } + this._readOperation = provider.readFile(resource).then(data => { + this.push(data.slice(position)); + this.push(null); + }, err => { + this.emit('error', err); + this.push(null); + }); + } + }; +} + +export function createReadableOfSnapshot(snapshot: ITextSnapshot): Readable { + return new Readable({ + read: function () { + try { + let chunk: string; + let canPush = true; + + // Push all chunks as long as we can push and as long as + // the underlying snapshot returns strings to us + while (canPush && typeof (chunk = snapshot.read()) === 'string') { + canPush = this.push(chunk); + } + + // Signal EOS by pushing NULL + if (typeof chunk !== 'string') { + this.push(null); + } + } catch (error) { + this.emit('error', error); + } + }, + encoding: UTF8 // very important, so that strings are passed around and not buffers! + }); +} diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts deleted file mode 100644 index b2841d2a0a..0000000000 --- a/src/vs/workbench/services/files/node/fileService.ts +++ /dev/null @@ -1,1296 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 paths = require('path'); -import fs = require('fs'); -import os = require('os'); -import crypto = require('crypto'); -import assert = require('assert'); -import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData, ITextSnapshot } from 'vs/platform/files/common/files'; -import { MAX_FILE_SIZE, MAX_HEAP_SIZE } from 'vs/platform/files/node/files'; -import { isEqualOrParent } from 'vs/base/common/paths'; -import { ResourceMap } from 'vs/base/common/map'; -import arrays = require('vs/base/common/arrays'); -import baseMime = require('vs/base/common/mime'); -import { TPromise } from 'vs/base/common/winjs.base'; -import objects = require('vs/base/common/objects'); -import extfs = require('vs/base/node/extfs'); -import { nfcall, ThrottledDelayer } from 'vs/base/common/async'; -import uri from 'vs/base/common/uri'; -import nls = require('vs/nls'); -import { isWindows, isLinux } from 'vs/base/common/platform'; -import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import pfs = require('vs/base/node/pfs'); -import encoding = require('vs/base/node/encoding'); -import { detectMimeAndEncodingFromBuffer, IMimeAndEncoding } from 'vs/base/node/mime'; -import flow = require('vs/base/node/flow'); -import { FileWatcher as UnixWatcherService } from 'vs/workbench/services/files/node/watcher/unix/watcherService'; -import { FileWatcher as WindowsWatcherService } from 'vs/workbench/services/files/node/watcher/win32/watcherService'; -import { toFileChangesEvent, normalize, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common'; -import Event, { Emitter } from 'vs/base/common/event'; -import { FileWatcher as NsfwWatcherService } from 'vs/workbench/services/files/node/watcher/nsfw/watcherService'; -import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { getBaseLabel } from 'vs/base/common/labels'; -import { assign } from 'vs/base/common/objects'; -import { Readable } from 'stream'; -import { IWriteFileOptions, IStatAndLink } from 'vs/base/node/extfs'; -import { Schemas } from 'vs/base/common/network'; - -export interface IEncodingOverride { - resource: uri; - encoding: string; -} - -export interface IFileServiceOptions { - tmpDir?: string; - errorLogger?: (msg: string) => void; - encodingOverride?: IEncodingOverride[]; - watcherIgnoredPatterns?: string[]; - disableWatcher?: boolean; - verboseLogging?: boolean; - useExperimentalFileWatcher?: boolean; - writeElevated?: (source: string, target: string) => TPromise; - elevationSupport?: { - cliPath: string; - promptTitle: string; - promptIcnsPath?: string; - }; -} - -function etag(stat: fs.Stats): string; -function etag(size: number, mtime: number): string; -function etag(arg1: any, arg2?: any): string { - let size: number; - let mtime: number; - if (typeof arg2 === 'number') { - size = arg1; - mtime = arg2; - } else { - size = (arg1).size; - mtime = (arg1).mtime.getTime(); - } - - return `"${crypto.createHash('sha1').update(String(size) + String(mtime)).digest('hex')}"`; -} - -class BufferPool { - - static _64K = new BufferPool(64 * 1024, 5); - - constructor( - readonly bufferSize: number, - private readonly _capacity: number, - private readonly _free: Buffer[] = [], - ) { - // - } - - acquire(): Buffer { - if (this._free.length === 0) { - return Buffer.allocUnsafe(this.bufferSize); - } else { - return this._free.shift(); - } - } - - release(buf: Buffer): void { - if (this._free.length <= this._capacity) { - this._free.push(buf); - } - } -} - -export class FileService implements IFileService { - - public _serviceBrand: any; - - private static readonly FS_EVENT_DELAY = 50; // aggregate and only emit events when changes have stopped for this duration (in ms) - private static readonly FS_REWATCH_DELAY = 300; // delay to rewatch a file that was renamed or deleted (in ms) - - private tmpPath: string; - private options: IFileServiceOptions; - - private _onFileChanges: Emitter; - private _onAfterOperation: Emitter; - - private toDispose: IDisposable[]; - - private activeFileChangesWatchers: ResourceMap; - private fileChangesWatchDelayer: ThrottledDelayer; - private undeliveredRawFileChangesEvents: IRawFileChange[]; - - private activeWorkspaceFileChangeWatcher: IDisposable; - - constructor( - private contextService: IWorkspaceContextService, - private environmentService: IEnvironmentService, - private textResourceConfigurationService: ITextResourceConfigurationService, - private configurationService: IConfigurationService, - private lifecycleService: ILifecycleService, - options: IFileServiceOptions - ) { - this.toDispose = []; - this.options = options || Object.create(null); - this.tmpPath = this.options.tmpDir || os.tmpdir(); - - this._onFileChanges = new Emitter(); - this.toDispose.push(this._onFileChanges); - - this._onAfterOperation = new Emitter(); - this.toDispose.push(this._onAfterOperation); - - if (!this.options.errorLogger) { - this.options.errorLogger = console.error; - } - - this.activeFileChangesWatchers = new ResourceMap(); - this.fileChangesWatchDelayer = new ThrottledDelayer(FileService.FS_EVENT_DELAY); - this.undeliveredRawFileChangesEvents = []; - - lifecycleService.when(LifecyclePhase.Running).then(() => { - this.setupFileWatching(); // wait until we are fully running before starting file watchers - }); - - this.registerListeners(); - } - - private registerListeners(): void { - this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => { - if (this.lifecycleService.phase >= LifecyclePhase.Running) { - this.setupFileWatching(); - } - })); - } - - public get onFileChanges(): Event { - return this._onFileChanges.event; - } - - public get onAfterOperation(): Event { - return this._onAfterOperation.event; - } - - public updateOptions(options: IFileServiceOptions): void { - if (options) { - objects.mixin(this.options, options); // overwrite current options - } - } - - private setupFileWatching(): void { - - // dispose old if any - if (this.activeWorkspaceFileChangeWatcher) { - this.activeWorkspaceFileChangeWatcher.dispose(); - } - - // Return if not aplicable - const workbenchState = this.contextService.getWorkbenchState(); - if (workbenchState === WorkbenchState.EMPTY || this.options.disableWatcher) { - return; - } - - // new watcher: use it if setting tells us so or we run in multi-root environment - if (this.options.useExperimentalFileWatcher || workbenchState === WorkbenchState.WORKSPACE) { - this.activeWorkspaceFileChangeWatcher = toDisposable(this.setupNsfwWorkspaceWatching().startWatching()); - } - - // old watcher - else { - if (isWindows) { - this.activeWorkspaceFileChangeWatcher = toDisposable(this.setupWin32WorkspaceWatching().startWatching()); - } else { - this.activeWorkspaceFileChangeWatcher = toDisposable(this.setupUnixWorkspaceWatching().startWatching()); - } - } - } - - private setupWin32WorkspaceWatching(): WindowsWatcherService { - return new WindowsWatcherService(this.contextService, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging); - } - - private setupUnixWorkspaceWatching(): UnixWatcherService { - return new UnixWatcherService(this.contextService, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging); - } - - private setupNsfwWorkspaceWatching(): NsfwWatcherService { - return new NsfwWatcherService(this.contextService, this.configurationService, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging); - } - - public resolveFile(resource: uri, options?: IResolveFileOptions): TPromise { - return this.resolve(resource, options); - } - - public resolveFiles(toResolve: { resource: uri, options?: IResolveFileOptions }[]): TPromise { - return TPromise.join(toResolve.map(resourceAndOptions => this.resolve(resourceAndOptions.resource, resourceAndOptions.options) - .then(stat => ({ stat, success: true }), error => ({ stat: void 0, success: false })))); - } - - public existsFile(resource: uri): TPromise { - return this.resolveFile(resource).then(() => true, () => false); - } - - public resolveContent(resource: uri, options?: IResolveContentOptions): TPromise { - return this.resolveStreamContent(resource, options).then(streamContent => { - return new TPromise((resolve, reject) => { - - const result: IContent = { - resource: streamContent.resource, - name: streamContent.name, - mtime: streamContent.mtime, - etag: streamContent.etag, - encoding: streamContent.encoding, - value: '' - }; - - streamContent.value.on('data', chunk => result.value += chunk); - streamContent.value.on('error', err => reject(err)); - streamContent.value.on('end', _ => resolve(result)); - - return result; - }); - }); - } - - public resolveStreamContent(resource: uri, options?: IResolveContentOptions): TPromise { - - // Guard early against attempts to resolve an invalid file path - if (resource.scheme !== Schemas.file || !resource.fsPath) { - return TPromise.wrapError(new FileOperationError( - nls.localize('fileInvalidPath', "Invalid file resource ({0})", resource.toString(true)), - FileOperationResult.FILE_INVALID_PATH, - options - )); - } - - const result: IStreamContent = { - resource: void 0, - name: void 0, - mtime: void 0, - etag: void 0, - encoding: void 0, - value: void 0 - }; - - const contentResolverToken = new CancellationTokenSource(); - - const onStatError = (error: Error) => { - - // error: stop reading the file the stat and content resolve call - // usually race, mostly likely the stat call will win and cancel - // the content call - contentResolverToken.cancel(); - - // forward error - return TPromise.wrapError(error); - }; - - const statsPromise = this.resolveFile(resource).then(stat => { - result.resource = stat.resource; - result.name = stat.name; - result.mtime = stat.mtime; - result.etag = stat.etag; - - // Return early if resource is a directory - if (stat.isDirectory) { - return onStatError(new FileOperationError( - nls.localize('fileIsDirectoryError', "File is directory"), - FileOperationResult.FILE_IS_DIRECTORY, - options - )); - } - - // Return early if file not modified since - if (options && options.etag && options.etag === stat.etag) { - return onStatError(new FileOperationError( - nls.localize('fileNotModifiedError', "File not modified since"), - FileOperationResult.FILE_NOT_MODIFIED_SINCE, - options - )); - } - - // Return early if file is too large to load - if (typeof stat.size === 'number') { - if (stat.size > Math.max(this.environmentService.args['max-memory'] * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { - return onStatError(new FileOperationError( - nls.localize('fileTooLargeForHeapError', "File size exceeds window memory limit, please try to run code --max-memory=NEWSIZE"), - FileOperationResult.FILE_EXCEED_MEMORY_LIMIT - )); - } - - if (stat.size > MAX_FILE_SIZE) { - return onStatError(new FileOperationError( - nls.localize('fileTooLargeError', "File too large to open"), - FileOperationResult.FILE_TOO_LARGE - )); - } - } - - return void 0; - }, err => { - - // Wrap file not found errors - if (err.code === 'ENOENT') { - return onStatError(new FileOperationError( - nls.localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), - FileOperationResult.FILE_NOT_FOUND, - options - )); - } - - return onStatError(err); - }); - - let completePromise: Thenable; - - // await the stat iff we already have an etag so that we compare the - // etag from the stat before we actually read the file again. - if (options && options.etag) { - completePromise = statsPromise.then(() => { - return this.fillInContents(result, resource, options, contentResolverToken.token); // Waterfall -> only now resolve the contents - }); - } - - // a fresh load without a previous etag which means we can resolve the file stat - // and the content at the same time, avoiding the waterfall. - else { - completePromise = Promise.all([statsPromise, this.fillInContents(result, resource, options, contentResolverToken.token)]); - } - - return TPromise.wrap(completePromise).then(() => result); - } - - private fillInContents(content: IStreamContent, resource: uri, options: IResolveContentOptions, token: CancellationToken): Thenable { - return this.resolveFileData(resource, options, token).then(data => { - content.encoding = data.encoding; - content.value = data.stream; - }); - } - - private resolveFileData(resource: uri, options: IResolveContentOptions, token: CancellationToken): Thenable { - - const chunkBuffer = BufferPool._64K.acquire(); - - const result: IContentData = { - encoding: void 0, - stream: void 0 - }; - - return new Promise((resolve, reject) => { - fs.open(this.toAbsolutePath(resource), 'r', (err, fd) => { - if (err) { - if (err.code === 'ENOENT') { - // Wrap file not found errors - err = new FileOperationError( - nls.localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), - FileOperationResult.FILE_NOT_FOUND, - options - ); - } - - return reject(err); - } - - let decoder: NodeJS.ReadWriteStream; - let totalBytesRead = 0; - - const finish = (err?: any) => { - - if (err) { - if (err.code === 'EISDIR') { - // Wrap EISDIR errors (fs.open on a directory works, but you cannot read from it) - err = new FileOperationError( - nls.localize('fileIsDirectoryError', "File is directory"), - FileOperationResult.FILE_IS_DIRECTORY, - options - ); - } - if (decoder) { - // If the decoder already started, we have to emit the error through it as - // event because the promise is already resolved! - decoder.emit('error', err); - } else { - reject(err); - } - } - if (decoder) { - decoder.end(); - } - - // return the shared buffer - BufferPool._64K.release(chunkBuffer); - - if (fd) { - fs.close(fd, err => { - if (err) { - this.options.errorLogger(`resolveFileData#close(): ${err.toString()}`); - } - }); - } - }; - - const handleChunk = (bytesRead: number) => { - if (token.isCancellationRequested) { - // cancellation -> finish - finish(new Error('cancelled')); - } else if (bytesRead === 0) { - // no more data -> finish - finish(); - } else if (bytesRead < chunkBuffer.length) { - // write the sub-part of data we received -> repeat - decoder.write(chunkBuffer.slice(0, bytesRead), readChunk); - } else { - // write all data we received -> repeat - decoder.write(chunkBuffer, readChunk); - } - }; - - let currentPosition: number = (options && options.position) || null; - - const readChunk = () => { - fs.read(fd, chunkBuffer, 0, chunkBuffer.length, currentPosition, (err, bytesRead) => { - totalBytesRead += bytesRead; - - if (typeof currentPosition === 'number') { - // if we received a position argument as option we need to ensure that - // we advance the position by the number of bytesread - currentPosition += bytesRead; - } - - if (totalBytesRead > Math.max(this.environmentService.args['max-memory'] * 1024 * 1024 || 0, MAX_HEAP_SIZE)) { - finish(new FileOperationError( - nls.localize('fileTooLargeForHeapError', "File size exceeds window memory limit, please try to run code --max-memory=NEWSIZE"), - FileOperationResult.FILE_EXCEED_MEMORY_LIMIT - )); - } - - if (totalBytesRead > MAX_FILE_SIZE) { - // stop when reading too much - finish(new FileOperationError( - nls.localize('fileTooLargeError', "File too large to open"), - FileOperationResult.FILE_TOO_LARGE, - options - )); - } else if (err) { - // some error happened - finish(err); - - } else if (decoder) { - // pass on to decoder - handleChunk(bytesRead); - - } else { - // when receiving the first chunk of data we need to create the - // decoding stream which is then used to drive the string stream. - TPromise.as(detectMimeAndEncodingFromBuffer( - { buffer: chunkBuffer, bytesRead }, - options && options.autoGuessEncoding || this.configuredAutoGuessEncoding(resource) - )).then(value => { - - if (options && options.acceptTextOnly && value.mimes.indexOf(baseMime.MIME_BINARY) >= 0) { - // Return error early if client only accepts text and this is not text - finish(new FileOperationError( - nls.localize('fileBinaryError', "File seems to be binary and cannot be opened as text"), - FileOperationResult.FILE_IS_BINARY, - options - )); - - } else { - result.encoding = this.getEncoding(resource, this.getPeferredEncoding(resource, options, value)); - result.stream = decoder = encoding.decodeStream(result.encoding); - resolve(result); - handleChunk(bytesRead); - } - - }).then(void 0, err => { - // failed to get encoding - finish(err); - }); - } - }); - }; - - // start reading - readChunk(); - }); - }); - } - - public updateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { - if (this.options.elevationSupport && options.writeElevated) { - return this.doUpdateContentElevated(resource, value, options); - } - - return this.doUpdateContent(resource, value, options); - } - - private doUpdateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - // 1.) check file - return this.checkFile(absolutePath, options).then(exists => { - let createParentsPromise: TPromise; - if (exists) { - createParentsPromise = TPromise.as(null); - } else { - createParentsPromise = pfs.mkdirp(paths.dirname(absolutePath)); - } - - // 2.) create parents as needed - return createParentsPromise.then(() => { - const encodingToWrite = this.getEncoding(resource, options.encoding); - let addBomPromise: TPromise = TPromise.as(false); - - // UTF_16 BE and LE as well as UTF_8 with BOM always have a BOM - if (encodingToWrite === encoding.UTF16be || encodingToWrite === encoding.UTF16le || encodingToWrite === encoding.UTF8_with_bom) { - addBomPromise = TPromise.as(true); - } - - // Existing UTF-8 file: check for options regarding BOM - else if (exists && encodingToWrite === encoding.UTF8) { - if (options.overwriteEncoding) { - addBomPromise = TPromise.as(false); // if we are to overwrite the encoding, we do not preserve it if found - } else { - addBomPromise = encoding.detectEncodingByBOM(absolutePath).then(enc => enc === encoding.UTF8); // otherwise preserve it if found - } - } - - // 3.) check to add UTF BOM - return addBomPromise.then(addBom => { - - // 4.) set contents and resolve - return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite).then(void 0, error => { - if (!exists || error.code !== 'EPERM' || !isWindows) { - return TPromise.wrapError(error); - } - - // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file - // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows - // (see https://github.com/Microsoft/vscode/issues/931) - - // 5.) truncate - return pfs.truncate(absolutePath, 0).then(() => { - - // 6.) set contents (this time with r+ mode) and resolve again - return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite, { flag: 'r+' }); - }); - }); - }); - }); - }).then(null, error => { - if (error.code === 'EACCES' || error.code === 'EPERM') { - return TPromise.wrapError(new FileOperationError( - nls.localize('filePermission', "Permission denied writing to file ({0})", resource.toString(true)), - FileOperationResult.FILE_PERMISSION_DENIED, - options - )); - } - - return TPromise.wrapError(error); - }); - } - - private doSetContentsAndResolve(resource: uri, absolutePath: string, value: string | ITextSnapshot, addBOM: boolean, encodingToWrite: string, options?: { mode?: number; flag?: string; }): TPromise { - let writeFilePromise: TPromise; - - // Configure encoding related options as needed - const writeFileOptions: IWriteFileOptions = options ? options : Object.create(null); - if (addBOM || encodingToWrite !== encoding.UTF8) { - writeFileOptions.encoding = { - charset: encodingToWrite, - addBOM - }; - } - - if (typeof value === 'string') { - writeFilePromise = pfs.writeFile(absolutePath, value, writeFileOptions); - } else { - writeFilePromise = pfs.writeFile(absolutePath, this.snapshotToReadableStream(value), writeFileOptions); - } - - // set contents - return writeFilePromise.then(() => { - - // resolve - return this.resolve(resource); - }); - } - - private snapshotToReadableStream(snapshot: ITextSnapshot): NodeJS.ReadableStream { - return new Readable({ - read: function () { - try { - let chunk: string; - let canPush = true; - - // Push all chunks as long as we can push and as long as - // the underlying snapshot returns strings to us - while (canPush && typeof (chunk = snapshot.read()) === 'string') { - canPush = this.push(chunk); - } - - // Signal EOS by pushing NULL - if (typeof chunk !== 'string') { - this.push(null); - } - } catch (error) { - this.emit('error', error); - } - }, - encoding: encoding.UTF8 // very important, so that strings are passed around and not buffers! - }); - } - - private doUpdateContentElevated(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - // 1.) check file - return this.checkFile(absolutePath, options, options.overwriteReadonly /* ignore readonly if we overwrite readonly, this is handled via sudo later */).then(exists => { - const writeOptions: IUpdateContentOptions = assign(Object.create(null), options); - writeOptions.writeElevated = false; - writeOptions.encoding = this.getEncoding(resource, options.encoding); - - // 2.) write to a temporary file to be able to copy over later - const tmpPath = paths.join(this.tmpPath, `code-elevated-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6)}`); - return this.updateContent(uri.file(tmpPath), value, writeOptions).then(() => { - - // 3.) invoke our CLI as super user - return (import('sudo-prompt')).then(sudoPrompt => { - return new TPromise((c, e) => { - const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath }; - - const sudoCommand: string[] = [`"${this.options.elevationSupport.cliPath}"`]; - if (options.overwriteReadonly) { - sudoCommand.push('--file-chmod'); - } - sudoCommand.push('--file-write', `"${tmpPath}"`, `"${absolutePath}"`); - - sudoPrompt.exec(sudoCommand.join(' '), promptOptions, (error: string, stdout: string, stderr: string) => { - if (error || stderr) { - e(error || stderr); - } else { - c(void 0); - } - }); - }); - }).then(() => { - - // 3.) delete temp file - return pfs.del(tmpPath, this.tmpPath).then(() => { - - // 4.) resolve again - return this.resolve(resource); - }); - }); - }); - }).then(null, error => { - if (this.options.verboseLogging) { - this.options.errorLogger(`Unable to write to file '${resource.toString(true)}' as elevated user (${error})`); - } - - if (!FileOperationError.isFileOperationError(error)) { - error = new FileOperationError( - nls.localize('filePermission', "Permission denied writing to file ({0})", resource.toString(true)), - FileOperationResult.FILE_PERMISSION_DENIED, - options - ); - } - - return TPromise.wrapError(error); - }); - } - - public createFile(resource: uri, content: string = '', options: ICreateFileOptions = Object.create(null)): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - let checkFilePromise: TPromise; - if (options.overwrite) { - checkFilePromise = TPromise.as(false); - } else { - checkFilePromise = pfs.exists(absolutePath); - } - - // Check file exists - return checkFilePromise.then(exists => { - if (exists && !options.overwrite) { - return TPromise.wrapError(new FileOperationError( - nls.localize('fileExists', "File to create already exists ({0})", resource.toString(true)), - FileOperationResult.FILE_MODIFIED_SINCE, - options - )); - } - - // Create file - return this.updateContent(resource, content).then(result => { - - // Events - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); - - return result; - }); - }); - } - - public createFolder(resource: uri): TPromise { - - // 1.) Create folder - const absolutePath = this.toAbsolutePath(resource); - return pfs.mkdirp(absolutePath).then(() => { - - // 2.) Resolve - return this.resolve(resource).then(result => { - - // Events - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); - - return result; - }); - }); - } - - public touchFile(resource: uri): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - // 1.) check file - return this.checkFile(absolutePath).then(exists => { - let createPromise: TPromise; - if (exists) { - createPromise = TPromise.as(null); - } else { - createPromise = this.createFile(resource); - } - - // 2.) create file as needed - return createPromise.then(() => { - - // 3.) update atime and mtime - return pfs.touch(absolutePath).then(() => { - - // 4.) resolve - return this.resolve(resource); - }); - }); - }); - } - - public rename(resource: uri, newName: string): TPromise { - const newPath = paths.join(paths.dirname(resource.fsPath), newName); - - return this.moveFile(resource, uri.file(newPath)); - } - - public moveFile(source: uri, target: uri, overwrite?: boolean): TPromise { - return this.moveOrCopyFile(source, target, false, overwrite); - } - - public copyFile(source: uri, target: uri, overwrite?: boolean): TPromise { - return this.moveOrCopyFile(source, target, true, overwrite); - } - - private moveOrCopyFile(source: uri, target: uri, keepCopy: boolean, overwrite: boolean): TPromise { - const sourcePath = this.toAbsolutePath(source); - const targetPath = this.toAbsolutePath(target); - - // 1.) move / copy - return this.doMoveOrCopyFile(sourcePath, targetPath, keepCopy, overwrite).then(() => { - - // 2.) resolve - return this.resolve(target).then(result => { - - // Events - this._onAfterOperation.fire(new FileOperationEvent(source, keepCopy ? FileOperation.COPY : FileOperation.MOVE, result)); - - return result; - }); - }); - } - - private doMoveOrCopyFile(sourcePath: string, targetPath: string, keepCopy: boolean, overwrite: boolean): TPromise { - - // 1.) check if target exists - return pfs.exists(targetPath).then(exists => { - const isCaseRename = sourcePath.toLowerCase() === targetPath.toLowerCase(); - const isSameFile = sourcePath === targetPath; - - // Return early with conflict if target exists and we are not told to overwrite - if (exists && !isCaseRename && !overwrite) { - return TPromise.wrapError(new FileOperationError(nls.localize('fileMoveConflict', "Unable to move/copy. File already exists at destination."), FileOperationResult.FILE_MOVE_CONFLICT)); - } - - // 2.) make sure target is deleted before we move/copy unless this is a case rename of the same file - let deleteTargetPromise = TPromise.wrap(void 0); - if (exists && !isCaseRename) { - if (isEqualOrParent(sourcePath, targetPath, !isLinux /* ignorecase */)) { - return TPromise.wrapError(new Error(nls.localize('unableToMoveCopyError', "Unable to move/copy. File would replace folder it is contained in."))); // catch this corner case! - } - - deleteTargetPromise = this.del(uri.file(targetPath)); - } - - return deleteTargetPromise.then(() => { - - // 3.) make sure parents exists - return pfs.mkdirp(paths.dirname(targetPath)).then(() => { - - // 4.) copy/move - if (isSameFile) { - return TPromise.wrap(null); - } else if (keepCopy) { - return nfcall(extfs.copy, sourcePath, targetPath); - } else { - return nfcall(extfs.mv, sourcePath, targetPath); - } - }).then(() => exists); - }); - }); - } - - public importFile(source: uri, targetFolder: uri): TPromise { - const sourcePath = this.toAbsolutePath(source); - const targetResource = uri.file(paths.join(targetFolder.fsPath, paths.basename(source.fsPath))); - const targetPath = this.toAbsolutePath(targetResource); - - // 1.) resolve - return pfs.stat(sourcePath).then(stat => { - if (stat.isDirectory()) { - return TPromise.wrapError(new Error(nls.localize('foldersCopyError', "Folders cannot be copied into the workspace. Please select individual files to copy them."))); // for now we do not allow to import a folder into a workspace - } - - // 2.) copy - return this.doMoveOrCopyFile(sourcePath, targetPath, true, true).then(exists => { - - // 3.) resolve - return this.resolve(targetResource).then(stat => { - - // Events - this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.IMPORT, stat)); - - return { isNew: !exists, stat: stat }; - }); - }); - }); - } - - public del(resource: uri): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - return pfs.del(absolutePath, this.tmpPath).then(() => { - - // Events - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE)); - }); - } - - // Helpers - - private toAbsolutePath(arg1: uri | IFileStat): string { - let resource: uri; - if (arg1 instanceof uri) { - resource = arg1; - } else { - resource = (arg1).resource; - } - - assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource: ${resource}`); - - return paths.normalize(resource.fsPath); - } - - private resolve(resource: uri, options: IResolveFileOptions = Object.create(null)): TPromise { - return this.toStatResolver(resource) - .then(model => model.resolve(options)); - } - - private toStatResolver(resource: uri): TPromise { - const absolutePath = this.toAbsolutePath(resource); - - return pfs.statLink(absolutePath).then(({ isSymbolicLink, stat }) => { - return new StatResolver(resource, isSymbolicLink, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.options.verboseLogging ? this.options.errorLogger : void 0); - }); - } - - private getPeferredEncoding(resource: uri, options: IResolveContentOptions, detected: IMimeAndEncoding): string { - let preferredEncoding: string; - if (options && options.encoding) { - if (detected.encoding === encoding.UTF8 && options.encoding === encoding.UTF8) { - preferredEncoding = encoding.UTF8_with_bom; // indicate the file has BOM if we are to resolve with UTF 8 - } else { - preferredEncoding = options.encoding; // give passed in encoding highest priority - } - } else if (detected.encoding) { - if (detected.encoding === encoding.UTF8) { - preferredEncoding = encoding.UTF8_with_bom; // if we detected UTF-8, it can only be because of a BOM - } else { - preferredEncoding = detected.encoding; - } - } else if (this.configuredEncoding(resource) === encoding.UTF8_with_bom) { - preferredEncoding = encoding.UTF8; // if we did not detect UTF 8 BOM before, this can only be UTF 8 then - } - return preferredEncoding; - } - - public getEncoding(resource: uri, preferredEncoding?: string): string { - let fileEncoding: string; - - const override = this.getEncodingOverride(resource); - if (override) { - fileEncoding = override; - } else if (preferredEncoding) { - fileEncoding = preferredEncoding; - } else { - fileEncoding = this.configuredEncoding(resource); - } - - if (!fileEncoding || !encoding.encodingExists(fileEncoding)) { - fileEncoding = encoding.UTF8; // the default is UTF 8 - } - - return fileEncoding; - } - - private configuredAutoGuessEncoding(resource: uri): boolean { - return this.textResourceConfigurationService.getValue(resource, 'files.autoGuessEncoding'); - } - - private configuredEncoding(resource: uri): string { - return this.textResourceConfigurationService.getValue(resource, 'files.encoding'); - } - - private getEncodingOverride(resource: uri): string { - if (resource && this.options.encodingOverride && this.options.encodingOverride.length) { - for (let i = 0; i < this.options.encodingOverride.length; i++) { - const override = this.options.encodingOverride[i]; - - // check if the resource is a child of the resource with override and use - // the provided encoding in that case - if (isParent(resource.fsPath, override.resource.fsPath, !isLinux /* ignorecase */)) { - return override.encoding; - } - } - } - - return null; - } - - private checkFile(absolutePath: string, options: IUpdateContentOptions = Object.create(null), ignoreReadonly?: boolean): TPromise { - return pfs.exists(absolutePath).then(exists => { - if (exists) { - return pfs.stat(absolutePath).then(stat => { - if (stat.isDirectory()) { - return TPromise.wrapError(new Error('Expected file is actually a directory')); - } - - // Dirty write prevention - if (typeof options.mtime === 'number' && typeof options.etag === 'string' && options.mtime < stat.mtime.getTime()) { - - // Find out if content length has changed - if (options.etag !== etag(stat.size, options.mtime)) { - return TPromise.wrapError(new FileOperationError(nls.localize('fileModifiedError', "File Modified Since"), FileOperationResult.FILE_MODIFIED_SINCE, options)); - } - } - - // Throw if file is readonly and we are not instructed to overwrite - if (!ignoreReadonly && !(stat.mode & 128) /* readonly */) { - if (!options.overwriteReadonly) { - return this.readOnlyError(options); - } - - // Try to change mode to writeable - let mode = stat.mode; - mode = mode | 128; - return pfs.chmod(absolutePath, mode).then(() => { - - // Make sure to check the mode again, it could have failed - return pfs.stat(absolutePath).then(stat => { - if (!(stat.mode & 128) /* readonly */) { - return this.readOnlyError(options); - } - - return exists; - }); - }); - } - - return TPromise.as(exists); - }); - } - - return TPromise.as(exists); - }); - } - - private readOnlyError(options: IUpdateContentOptions): TPromise { - return TPromise.wrapError(new FileOperationError( - nls.localize('fileReadOnlyError', "File is Read Only"), - FileOperationResult.FILE_READ_ONLY, - options - )); - } - - public watchFileChanges(resource: uri): void { - assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource for watching: ${resource}`); - - // Create or get watcher for provided path - let watcher = this.activeFileChangesWatchers.get(resource); - if (!watcher) { - const fsPath = resource.fsPath; - const fsName = paths.basename(resource.fsPath); - - watcher = extfs.watch(fsPath, (eventType: string, filename: string) => { - const renamedOrDeleted = ((filename && filename !== fsName) || eventType === 'rename'); - - // The file was either deleted or renamed. Many tools apply changes to files in an - // atomic way ("Atomic Save") by first renaming the file to a temporary name and then - // renaming it back to the original name. Our watcher will detect this as a rename - // and then stops to work on Mac and Linux because the watcher is applied to the - // inode and not the name. The fix is to detect this case and trying to watch the file - // again after a certain delay. - // In addition, we send out a delete event if after a timeout we detect that the file - // does indeed not exist anymore. - if (renamedOrDeleted) { - - // Very important to dispose the watcher which now points to a stale inode - this.unwatchFileChanges(resource); - - // Wait a bit and try to install watcher again, assuming that the file was renamed quickly ("Atomic Save") - setTimeout(() => { - this.existsFile(resource).done(exists => { - - // File still exists, so reapply the watcher - if (exists) { - this.watchFileChanges(resource); - } - - // File seems to be really gone, so emit a deleted event - else { - this.onRawFileChange({ - type: FileChangeType.DELETED, - path: fsPath - }); - } - }); - }, FileService.FS_REWATCH_DELAY); - } - - // Handle raw file change - this.onRawFileChange({ - type: FileChangeType.UPDATED, - path: fsPath - }); - }, (error: string) => this.options.errorLogger(error)); - - if (watcher) { - this.activeFileChangesWatchers.set(resource, watcher); - } - } - } - - private onRawFileChange(event: IRawFileChange): void { - - // add to bucket of undelivered events - this.undeliveredRawFileChangesEvents.push(event); - - if (this.options.verboseLogging) { - console.log('%c[node.js Watcher]%c', 'color: green', 'color: black', event.type === FileChangeType.ADDED ? '[ADDED]' : event.type === FileChangeType.DELETED ? '[DELETED]' : '[CHANGED]', event.path); - } - - // handle emit through delayer to accommodate for bulk changes - this.fileChangesWatchDelayer.trigger(() => { - const buffer = this.undeliveredRawFileChangesEvents; - this.undeliveredRawFileChangesEvents = []; - - // Normalize - const normalizedEvents = normalize(buffer); - - // Logging - if (this.options.verboseLogging) { - normalizedEvents.forEach(r => { - console.log('%c[node.js Watcher]%c >> normalized', 'color: green', 'color: black', r.type === FileChangeType.ADDED ? '[ADDED]' : r.type === FileChangeType.DELETED ? '[DELETED]' : '[CHANGED]', r.path); - }); - } - - // Emit - this._onFileChanges.fire(toFileChangesEvent(normalizedEvents)); - - return TPromise.as(null); - }); - } - - public unwatchFileChanges(resource: uri): void { - const watcher = this.activeFileChangesWatchers.get(resource); - if (watcher) { - watcher.close(); - this.activeFileChangesWatchers.delete(resource); - } - } - - public dispose(): void { - this.toDispose = dispose(this.toDispose); - - if (this.activeWorkspaceFileChangeWatcher) { - this.activeWorkspaceFileChangeWatcher.dispose(); - this.activeWorkspaceFileChangeWatcher = null; - } - - this.activeFileChangesWatchers.forEach(watcher => watcher.close()); - this.activeFileChangesWatchers.clear(); - } -} - -export class StatResolver { - private name: string; - private etag: string; - - constructor( - private resource: uri, - private isSymbolicLink: boolean, - private isDirectory: boolean, - private mtime: number, - private size: number, - private errorLogger?: (error: Error | string) => void - ) { - assert.ok(resource && resource.scheme === Schemas.file, `Invalid resource: ${resource}`); - - this.name = getBaseLabel(resource); - this.etag = etag(size, mtime); - } - - public resolve(options: IResolveFileOptions): TPromise { - - // General Data - const fileStat: IFileStat = { - resource: this.resource, - isDirectory: this.isDirectory, - isSymbolicLink: this.isSymbolicLink, - name: this.name, - etag: this.etag, - size: this.size, - mtime: this.mtime - }; - - // File Specific Data - if (!this.isDirectory) { - return TPromise.as(fileStat); - } - - // Directory Specific Data - else { - - // Convert the paths from options.resolveTo to absolute paths - let absoluteTargetPaths: string[] = null; - if (options && options.resolveTo) { - absoluteTargetPaths = []; - options.resolveTo.forEach(resource => { - absoluteTargetPaths.push(resource.fsPath); - }); - } - - return new TPromise((c, e) => { - - // Load children - this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, options && options.resolveSingleChildDescendants, children => { - children = arrays.coalesce(children); // we don't want those null children (could be permission denied when reading a child) - fileStat.children = children || []; - - c(fileStat); - }); - }); - } - } - - private resolveChildren(absolutePath: string, absoluteTargetPaths: string[], resolveSingleChildDescendants: boolean, callback: (children: IFileStat[]) => void): void { - extfs.readdir(absolutePath, (error: Error, files: string[]) => { - if (error) { - if (this.errorLogger) { - this.errorLogger(error); - } - - return callback(null); // return - we might not have permissions to read the folder - } - - // for each file in the folder - flow.parallel(files, (file: string, clb: (error: Error, children: IFileStat) => void) => { - const fileResource = uri.file(paths.resolve(absolutePath, file)); - let fileStat: fs.Stats; - let isSymbolicLink = false; - const $this = this; - - flow.sequence( - function onError(error: Error): void { - if ($this.errorLogger) { - $this.errorLogger(error); - } - - clb(null, null); // return - we might not have permissions to read the folder or stat the file - }, - - function stat(this: any): void { - extfs.statLink(fileResource.fsPath, this); - }, - - function countChildren(this: any, statAndLink: IStatAndLink): void { - fileStat = statAndLink.stat; - isSymbolicLink = statAndLink.isSymbolicLink; - - if (fileStat.isDirectory()) { - extfs.readdir(fileResource.fsPath, (error, result) => { - this(null, result ? result.length : 0); - }); - } else { - this(null, 0); - } - }, - - function resolve(childCount: number): void { - const childStat: IFileStat = { - resource: fileResource, - isDirectory: fileStat.isDirectory(), - isSymbolicLink, - name: file, - mtime: fileStat.mtime.getTime(), - etag: etag(fileStat), - size: fileStat.size - }; - - // Return early for files - if (!fileStat.isDirectory()) { - return clb(null, childStat); - } - - // Handle Folder - let resolveFolderChildren = false; - if (files.length === 1 && resolveSingleChildDescendants) { - resolveFolderChildren = true; - } else if (childCount > 0 && absoluteTargetPaths && absoluteTargetPaths.some(targetPath => isEqualOrParent(targetPath, fileResource.fsPath, !isLinux /* ignorecase */))) { - resolveFolderChildren = true; - } - - // Continue resolving children based on condition - if (resolveFolderChildren) { - $this.resolveChildren(fileResource.fsPath, absoluteTargetPaths, resolveSingleChildDescendants, children => { - children = arrays.coalesce(children); // we don't want those null children - childStat.children = children || []; - - clb(null, childStat); - }); - } - - // Otherwise return result - else { - clb(null, childStat); - } - }); - }, (errors, result) => { - callback(result); - }); - }); - } -} diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService.ts b/src/vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService.ts index 16b2afe682..e62d2c54e9 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService.ts @@ -8,7 +8,7 @@ import * as paths from 'vs/base/common/paths'; import * as path from 'path'; import * as platform from 'vs/base/common/platform'; import * as watcher from 'vs/workbench/services/files/node/watcher/common'; -import * as nsfw from 'nsfw'; +import * as nsfw from 'vscode-nsfw'; import { IWatcherService, IWatcherRequest } from 'vs/workbench/services/files/node/watcher/nsfw/watcher'; import { TPromise, ProgressCallback, TValueCallback, ErrorCallback } from 'vs/base/common/winjs.base'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -61,7 +61,7 @@ export class NsfwWatcherService implements IWatcherService { ignored: request.ignored }; - process.on('uncaughtException', e => { + process.on('uncaughtException', (e: Error | string) => { // Specially handle ENOSPC errors that can happen when // the watcher consumes so many file descriptors that diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts b/src/vs/workbench/services/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts index 3760758f43..4c26fbdb14 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts @@ -5,8 +5,8 @@ 'use strict'; -import assert = require('assert'); -import platform = require('vs/base/common/platform'); +import * as assert from 'assert'; +import * as platform from 'vs/base/common/platform'; import { NsfwWatcherService } from 'vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService'; import { IWatcherRequest } from 'vs/workbench/services/files/node/watcher/nsfw/watcher'; diff --git a/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts index dd3ebcc151..a60a5519dc 100644 --- a/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts @@ -5,20 +5,21 @@ 'use strict'; -import chokidar = require('vscode-chokidar'); -import fs = require('fs'); +import * as chokidar from 'vscode-chokidar'; +import * as fs from 'fs'; -import gracefulFs = require('graceful-fs'); +import * as gracefulFs from 'graceful-fs'; gracefulFs.gracefulify(fs); import { TPromise } from 'vs/base/common/winjs.base'; import { FileChangeType } from 'vs/platform/files/common/files'; import { ThrottledDelayer } from 'vs/base/common/async'; -import strings = require('vs/base/common/strings'); +import * as strings from 'vs/base/common/strings'; import { realcaseSync } from 'vs/base/node/extfs'; import { isMacintosh } from 'vs/base/common/platform'; -import watcher = require('vs/workbench/services/files/node/watcher/common'); +import * as watcher from 'vs/workbench/services/files/node/watcher/common'; import { IWatcherRequest, IWatcherService } from 'vs/workbench/services/files/node/watcher/unix/watcher'; +import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; export class ChokidarWatcherService implements IWatcherService { @@ -28,6 +29,7 @@ export class ChokidarWatcherService implements IWatcherService { private spamCheckStartTime: number; private spamWarningLogged: boolean; private enospcErrorLogged: boolean; + private toDispose: IDisposable[] = []; public watch(request: IWatcherRequest): TPromise { const watcherOpts: chokidar.IOptions = { @@ -62,6 +64,11 @@ export class ChokidarWatcherService implements IWatcherService { let undeliveredFileEvents: watcher.IRawFileChange[] = []; const fileEventDelayer = new ThrottledDelayer(ChokidarWatcherService.FS_EVENT_DELAY); + this.toDispose.push(toDisposable(() => { + chokidarWatcher.close(); + fileEventDelayer.cancel(); + })); + return new TPromise((c, e, p) => { chokidarWatcher.on('all', (type: string, path: string) => { if (isMacintosh) { @@ -156,8 +163,12 @@ export class ChokidarWatcherService implements IWatcherService { } }); }, () => { - chokidarWatcher.close(); - fileEventDelayer.cancel(); + this.toDispose = dispose(this.toDispose); }); } + + public stop(): TPromise { + this.toDispose = dispose(this.toDispose); + return TPromise.as(void 0); + } } diff --git a/src/vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts b/src/vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts index 374e037999..6b16fb1208 100644 --- a/src/vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts @@ -5,11 +5,11 @@ 'use strict'; -import cp = require('child_process'); +import * as cp from 'child_process'; import { FileChangeType } from 'vs/platform/files/common/files'; -import decoder = require('vs/base/node/decoder'); -import glob = require('vs/base/common/glob'); +import * as decoder from 'vs/base/node/decoder'; +import * as glob from 'vs/base/common/glob'; import uri from 'vs/base/common/uri'; import { IRawFileChange } from 'vs/workbench/services/files/node/watcher/common'; diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/electron-browser/fileService.test.ts similarity index 63% rename from src/vs/workbench/services/files/test/node/fileService.test.ts rename to src/vs/workbench/services/files/test/electron-browser/fileService.test.ts index 2a7a265402..677f36328c 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/electron-browser/fileService.test.ts @@ -5,51 +5,47 @@ 'use strict'; -import fs = require('fs'); -import path = require('path'); -import os = require('os'); -import assert = require('assert'); +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import * as assert from 'assert'; import { TPromise } from 'vs/base/common/winjs.base'; -import { FileService, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; import { FileOperation, FileOperationEvent, FileChangesEvent, FileOperationResult, FileOperationError } from 'vs/platform/files/common/files'; import uri from 'vs/base/common/uri'; -import uuid = require('vs/base/common/uuid'); -import extfs = require('vs/base/node/extfs'); -import encodingLib = require('vs/base/node/encoding'); -import utils = require('vs/workbench/services/files/test/node/utils'); -import { onError } from 'vs/base/test/common/utils'; -import { TestEnvironmentService, TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService } from 'vs/workbench/test/workbenchTestServices'; +import * as uuid from 'vs/base/common/uuid'; +import * as pfs from 'vs/base/node/pfs'; +import * as encodingLib from 'vs/base/node/encoding'; +import * as utils from 'vs/workbench/services/files/test/electron-browser/utils'; +import { TestEnvironmentService, TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { TextModel } from 'vs/editor/common/model/textModel'; +import { IEncodingOverride } from 'vs/workbench/services/files/electron-browser/encoding'; suite('FileService', () => { let service: FileService; const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'fileservice'); let testDir: string; - setup(function (done) { + setup(function () { const id = uuid.generateUuid(); testDir = path.join(parentDir, id); const sourceDir = require.toUrl('./fixtures/service'); - extfs.copy(sourceDir, testDir, (error) => { - if (error) { - return onError(error, done); - } - - service = new FileService(new TestContextService(new Workspace(testDir, testDir, toWorkspaceFolders([{ path: testDir }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), { disableWatcher: true }); - done(); + return pfs.copy(sourceDir, testDir).then(() => { + service = new FileService(new TestContextService(new Workspace(testDir, testDir, toWorkspaceFolders([{ path: testDir }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true }); }); }); - teardown((done) => { + teardown(() => { service.dispose(); - extfs.del(parentDir, os.tmpdir(), () => { }, done); + return pfs.del(parentDir, os.tmpdir()); }); - test('createFile', function (done: () => void) { + test('createFile', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; @@ -57,7 +53,7 @@ suite('FileService', () => { const contents = 'Hello World'; const resource = uri.file(path.join(testDir, 'test.txt')); - service.createFile(resource, contents).done(s => { + return service.createFile(resource, contents).then(s => { assert.equal(s.name, 'test.txt'); assert.equal(fs.existsSync(s.resource.fsPath), true); assert.equal(fs.readFileSync(s.resource.fsPath), contents); @@ -67,25 +63,21 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.CREATE); assert.equal(event.target.resource.fsPath, resource.fsPath); toDispose.dispose(); - - done(); - }, error => onError(error, done)); + }); }); - test('createFile (does not overwrite by default)', function (done: () => void) { + test('createFile (does not overwrite by default)', function () { const contents = 'Hello World'; const resource = uri.file(path.join(testDir, 'test.txt')); fs.writeFileSync(resource.fsPath, ''); // create file - service.createFile(resource, contents).done(null, error => { + return service.createFile(resource, contents).then(null, error => { assert.ok(error); - - done(); }); }); - test('createFile (allows to overwrite existing)', function (done: () => void) { + test('createFile (allows to overwrite existing)', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; @@ -96,7 +88,7 @@ suite('FileService', () => { fs.writeFileSync(resource.fsPath, ''); // create file - service.createFile(resource, contents, { overwrite: true }).done(s => { + return service.createFile(resource, contents, { overwrite: true }).then(s => { assert.equal(s.name, 'test.txt'); assert.equal(fs.existsSync(s.resource.fsPath), true); assert.equal(fs.readFileSync(s.resource.fsPath), contents); @@ -106,18 +98,16 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.CREATE); assert.equal(event.target.resource.fsPath, resource.fsPath); toDispose.dispose(); - - done(); - }, error => onError(error, done)); + }); }); - test('createFolder', function (done: () => void) { + test('createFolder', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); - service.resolveFile(uri.file(testDir)).done(parent => { + return service.resolveFile(uri.file(testDir)).then(parent => { const resource = uri.file(path.join(parent.resource.fsPath, 'newFolder')); return service.createFolder(resource).then(f => { @@ -130,20 +120,18 @@ suite('FileService', () => { assert.equal(event.target.resource.fsPath, resource.fsPath); assert.equal(event.target.isDirectory, true); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('createFolder: creating multiple folders at once', function (done: () => void) { + test('createFolder: creating multiple folders at once', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const multiFolderPaths = ['a', 'couple', 'of', 'folders']; - service.resolveFile(uri.file(testDir)).done(parent => { + return service.resolveFile(uri.file(testDir)).then(parent => { const resource = uri.file(path.join(parent.resource.fsPath, ...multiFolderPaths)); return service.createFolder(resource).then(f => { @@ -157,62 +145,18 @@ suite('FileService', () => { assert.equal(event.target.resource.fsPath, resource.fsPath); assert.equal(event.target.isDirectory, true); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('touchFile', function (done: () => void) { - service.touchFile(uri.file(path.join(testDir, 'test.txt'))).done(s => { - assert.equal(s.name, 'test.txt'); - assert.equal(fs.existsSync(s.resource.fsPath), true); - assert.equal(fs.readFileSync(s.resource.fsPath).length, 0); - - const stat = fs.statSync(s.resource.fsPath); - - return TPromise.timeout(10).then(() => { - return service.touchFile(s.resource).done(s => { - const statNow = fs.statSync(s.resource.fsPath); - assert.ok(statNow.mtime.getTime() >= stat.mtime.getTime()); // one some OS the resolution seems to be 1s, so we use >= here - assert.equal(statNow.size, stat.size); - - done(); - }); - }); - }, error => onError(error, done)); - }); - - test('touchFile - multi folder', function (done: () => void) { - const multiFolderPaths = ['a', 'couple', 'of', 'folders']; - - service.touchFile(uri.file(path.join(testDir, ...multiFolderPaths, 'test.txt'))).done(s => { - assert.equal(s.name, 'test.txt'); - assert.equal(fs.existsSync(s.resource.fsPath), true); - assert.equal(fs.readFileSync(s.resource.fsPath).length, 0); - - const stat = fs.statSync(s.resource.fsPath); - - return TPromise.timeout(10).then(() => { - return service.touchFile(s.resource).done(s => { - const statNow = fs.statSync(s.resource.fsPath); - assert.ok(statNow.mtime.getTime() >= stat.mtime.getTime()); // one some OS the resolution seems to be 1s, so we use >= here - assert.equal(statNow.size, stat.size); - - done(); - }); - }); - }, error => onError(error, done)); - }); - - test('renameFile', function (done: () => void) { + test('renameFile', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.rename(source.resource, 'other.html').then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -222,13 +166,11 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('renameFile - multi folder', function (done: () => void) { + test('renameFile - multi folder', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; @@ -238,7 +180,7 @@ suite('FileService', () => { const renameToPath = path.join(...multiFolderPaths, 'other.html'); const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.rename(source.resource, renameToPath).then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -248,20 +190,18 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('renameFolder', function (done: () => void) { + test('renameFolder', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'deep')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.rename(source.resource, 'deeper').then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -271,13 +211,11 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); }); }); - test('renameFolder - multi folder', function (done: () => void) { + test('renameFolder - multi folder', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; @@ -287,7 +225,7 @@ suite('FileService', () => { const renameToPath = path.join(...multiFolderPaths); const resource = uri.file(path.join(testDir, 'deep')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.rename(source.resource, renameToPath).then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -297,19 +235,17 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); }); }); - test('renameFile - MIX CASE', function (done: () => void) { + test('renameFile - MIX CASE', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.rename(source.resource, 'INDEX.html').then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(path.basename(renamed.resource.fsPath), 'INDEX.html'); @@ -319,20 +255,18 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('moveFile', function (done: () => void) { + test('moveFile', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.moveFile(source.resource, uri.file(path.join(testDir, 'other.html'))).then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -342,38 +276,50 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('move - FILE_MOVE_CONFLICT', function (done: () => void) { + test('move - source parent of target', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); - service.resolveFile(uri.file(path.join(testDir, 'index.html'))).done(source => { + return service.resolveFile(uri.file(path.join(testDir, 'index.html'))).then(source => { + return service.moveFile(uri.file(testDir), uri.file(path.join(testDir, 'binary.txt'))).then(null, (e: Error) => { + assert.ok(e); + + assert.ok(!event); + toDispose.dispose(); + }); + }); + }); + + test('move - FILE_MOVE_CONFLICT', function () { + let event: FileOperationEvent; + const toDispose = service.onAfterOperation(e => { + event = e; + }); + + return service.resolveFile(uri.file(path.join(testDir, 'index.html'))).then(source => { return service.moveFile(source.resource, uri.file(path.join(testDir, 'binary.txt'))).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_MOVE_CONFLICT); assert.ok(!event); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('moveFile - MIX CASE', function (done: () => void) { + test('moveFile - MIX CASE', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.moveFile(source.resource, uri.file(path.join(testDir, 'INDEX.html'))).then(renamed => { assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.equal(path.basename(renamed.resource.fsPath), 'INDEX.html'); @@ -383,13 +329,11 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.MOVE); assert.equal(event.target.resource.fsPath, renamed.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('moveFile - overwrite folder with file', function (done: () => void) { + test('moveFile - overwrite folder with file', function () { let createEvent: FileOperationEvent; let moveEvent: FileOperationEvent; let deleteEvent: FileOperationEvent; @@ -403,7 +347,7 @@ suite('FileService', () => { } }); - service.resolveFile(uri.file(testDir)).done(parent => { + return service.resolveFile(uri.file(testDir)).then(parent => { const folderResource = uri.file(path.join(parent.resource.fsPath, 'conway.js')); return service.createFolder(folderResource).then(f => { const resource = uri.file(path.join(testDir, 'deep', 'conway.js')); @@ -421,20 +365,18 @@ suite('FileService', () => { assert.equal(deleteEvent.resource.fsPath, folderResource.fsPath); toDispose.dispose(); - - done(); }); }); - }, error => onError(error, done)); + }); }); - test('copyFile', function (done: () => void) { + test('copyFile', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); - service.resolveFile(uri.file(path.join(testDir, 'index.html'))).done(source => { + return service.resolveFile(uri.file(path.join(testDir, 'index.html'))).then(source => { const resource = uri.file(path.join(testDir, 'other.html')); return service.copyFile(source.resource, resource).then(copied => { assert.equal(fs.existsSync(copied.resource.fsPath), true); @@ -445,13 +387,11 @@ suite('FileService', () => { assert.equal(event.operation, FileOperation.COPY); assert.equal(event.target.resource.fsPath, copied.resource.fsPath); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('copyFile - overwrite folder with file', function (done: () => void) { + test('copyFile - overwrite folder with file', function () { let createEvent: FileOperationEvent; let copyEvent: FileOperationEvent; let deleteEvent: FileOperationEvent; @@ -465,7 +405,7 @@ suite('FileService', () => { } }); - service.resolveFile(uri.file(testDir)).done(parent => { + return service.resolveFile(uri.file(testDir)).then(parent => { const folderResource = uri.file(path.join(parent.resource.fsPath, 'conway.js')); return service.createFolder(folderResource).then(f => { const resource = uri.file(path.join(testDir, 'deep', 'conway.js')); @@ -483,112 +423,48 @@ suite('FileService', () => { assert.equal(deleteEvent.resource.fsPath, folderResource.fsPath); toDispose.dispose(); - - done(); }); }); - }, error => onError(error, done)); - }); - - test('importFile', function (done: () => void) { - let event: FileOperationEvent; - const toDispose = service.onAfterOperation(e => { - event = e; }); - - service.resolveFile(uri.file(path.join(testDir, 'deep'))).done(target => { - const resource = uri.file(require.toUrl('./fixtures/service/index.html')); - return service.importFile(resource, target.resource).then(res => { - assert.equal(res.isNew, true); - assert.equal(fs.existsSync(res.stat.resource.fsPath), true); - - assert.ok(event); - assert.equal(event.resource.fsPath, resource.fsPath); - assert.equal(event.operation, FileOperation.IMPORT); - assert.equal(event.target.resource.fsPath, res.stat.resource.fsPath); - toDispose.dispose(); - - done(); - }); - }, error => onError(error, done)); }); - test('importFile - MIX CASE', function (done: () => void) { - service.resolveFile(uri.file(path.join(testDir, 'index.html'))).done(source => { + test('copyFile - MIX CASE', function () { + return service.resolveFile(uri.file(path.join(testDir, 'index.html'))).then(source => { return service.rename(source.resource, 'CONWAY.js').then(renamed => { // index.html => CONWAY.js assert.equal(fs.existsSync(renamed.resource.fsPath), true); assert.ok(fs.readdirSync(testDir).some(f => f === 'CONWAY.js')); - return service.resolveFile(uri.file(path.join(testDir, 'deep', 'conway.js'))).done(source => { - return service.importFile(source.resource, uri.file(testDir)).then(res => { // CONWAY.js => conway.js - assert.equal(fs.existsSync(res.stat.resource.fsPath), true); - assert.ok(fs.readdirSync(testDir).some(f => f === 'conway.js')); + return service.resolveFile(uri.file(path.join(testDir, 'deep', 'conway.js'))).then(source => { + const targetParent = uri.file(testDir); + const target = targetParent.with({ path: path.posix.join(targetParent.path, path.posix.basename(source.resource.path)) }); - done(); + return service.copyFile(source.resource, target, true).then(res => { // CONWAY.js => conway.js + assert.equal(fs.existsSync(res.resource.fsPath), true); + assert.ok(fs.readdirSync(testDir).some(f => f === 'conway.js')); }); }); }); - }, error => onError(error, done)); - }); - - test('importFile - overwrite folder with file', function (done: () => void) { - let createEvent: FileOperationEvent; - let importEvent: FileOperationEvent; - let deleteEvent: FileOperationEvent; - const toDispose = service.onAfterOperation(e => { - if (e.operation === FileOperation.CREATE) { - createEvent = e; - } else if (e.operation === FileOperation.DELETE) { - deleteEvent = e; - } else if (e.operation === FileOperation.IMPORT) { - importEvent = e; - } }); - - service.resolveFile(uri.file(testDir)).done(parent => { - const folderResource = uri.file(path.join(parent.resource.fsPath, 'conway.js')); - return service.createFolder(folderResource).then(f => { - const resource = uri.file(path.join(testDir, 'deep', 'conway.js')); - return service.importFile(resource, uri.file(testDir)).then(res => { - assert.equal(fs.existsSync(res.stat.resource.fsPath), true); - assert.ok(fs.readdirSync(testDir).some(f => f === 'conway.js')); - assert.ok(fs.statSync(res.stat.resource.fsPath).isFile); - - assert.ok(createEvent); - assert.ok(deleteEvent); - assert.ok(importEvent); - - assert.equal(importEvent.resource.fsPath, resource.fsPath); - assert.equal(importEvent.target.resource.fsPath, res.stat.resource.fsPath); - - assert.equal(deleteEvent.resource.fsPath, folderResource.fsPath); - - toDispose.dispose(); - - done(); - }); - }); - }, error => onError(error, done)); }); - test('importFile - same file', function (done: () => void) { - service.resolveFile(uri.file(path.join(testDir, 'index.html'))).done(source => { - return service.importFile(source.resource, uri.file(path.dirname(source.resource.fsPath))).then(imported => { - assert.equal(imported.stat.size, source.size); - - done(); + test('copyFile - same file', function () { + return service.resolveFile(uri.file(path.join(testDir, 'index.html'))).then(source => { + const targetParent = uri.file(path.dirname(source.resource.fsPath)); + const target = targetParent.with({ path: path.posix.join(targetParent.path, path.posix.basename(source.resource.path)) }); + return service.copyFile(source.resource, target, true).then(copied => { + assert.equal(copied.size, source.size); }); - }, error => onError(error, done)); + }); }); - test('deleteFile', function (done: () => void) { + test('deleteFile', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'deep', 'conway.js')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.del(source.resource).then(() => { assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -596,20 +472,18 @@ suite('FileService', () => { assert.equal(event.resource.fsPath, resource.fsPath); assert.equal(event.operation, FileOperation.DELETE); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('deleteFolder', function (done: () => void) { + test('deleteFolder', function () { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { event = e; }); const resource = uri.file(path.join(testDir, 'deep')); - service.resolveFile(resource).done(source => { + return service.resolveFile(resource).then(source => { return service.del(source.resource).then(() => { assert.equal(fs.existsSync(source.resource.fsPath), false); @@ -617,25 +491,21 @@ suite('FileService', () => { assert.equal(event.resource.fsPath, resource.fsPath); assert.equal(event.operation, FileOperation.DELETE); toDispose.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('resolveFile', function (done: () => void) { - service.resolveFile(uri.file(testDir), { resolveTo: [uri.file(path.join(testDir, 'deep'))] }).done(r => { + test('resolveFile', function () { + return service.resolveFile(uri.file(testDir), { resolveTo: [uri.file(path.join(testDir, 'deep'))] }).then(r => { assert.equal(r.children.length, 8); const deep = utils.getByName(r, 'deep'); assert.equal(deep.children.length, 4); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveFiles', function (done: () => void) { - service.resolveFiles([ + test('resolveFiles', function () { + return service.resolveFiles([ { resource: uri.file(testDir), options: { resolveTo: [uri.file(path.join(testDir, 'deep'))] } }, { resource: uri.file(path.join(testDir, 'deep')) } ]).then(res => { @@ -649,43 +519,37 @@ suite('FileService', () => { const r2 = res[1].stat; assert.equal(r2.children.length, 4); assert.equal(r2.name, 'deep'); - - done(); - }, error => onError(error, done)); + }); }); - test('existsFile', function (done: () => void) { - service.existsFile(uri.file(testDir)).then((exists) => { + test('existsFile', function () { + return service.existsFile(uri.file(testDir)).then((exists) => { assert.equal(exists, true); - service.existsFile(uri.file(testDir + 'something')).then((exists) => { + return service.existsFile(uri.file(testDir + 'something')).then((exists) => { assert.equal(exists, false); - - done(); }); - }, error => onError(error, done)); + }); }); - test('updateContent', function (done: () => void) { + test('updateContent', function () { const resource = uri.file(path.join(testDir, 'small.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.equal(c.value, 'Small File'); c.value = 'Updates to the small file'; return service.updateContent(c.resource, c.value).then(c => { assert.equal(fs.readFileSync(resource.fsPath), 'Updates to the small file'); - - done(); }); - }, error => onError(error, done)); + }); }); - test('updateContent (ITextSnapShot)', function (done: () => void) { + test('updateContent (ITextSnapShot)', function () { const resource = uri.file(path.join(testDir, 'small.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.equal(c.value, 'Small File'); const model = TextModel.createFromString('Updates to the small file'); @@ -694,47 +558,41 @@ suite('FileService', () => { assert.equal(fs.readFileSync(resource.fsPath), 'Updates to the small file'); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('updateContent (large file)', function (done: () => void) { + test('updateContent (large file)', function () { const resource = uri.file(path.join(testDir, 'lorem.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { const newValue = c.value + c.value; c.value = newValue; return service.updateContent(c.resource, c.value).then(c => { assert.equal(fs.readFileSync(resource.fsPath), newValue); - - done(); }); - }, error => onError(error, done)); + }); }); - test('updateContent (large file, ITextSnapShot)', function (done: () => void) { + test('updateContent (large file, ITextSnapShot)', function () { const resource = uri.file(path.join(testDir, 'lorem.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { const newValue = c.value + c.value; const model = TextModel.createFromString(newValue); return service.updateContent(c.resource, model.createSnapshot()).then(c => { assert.equal(fs.readFileSync(resource.fsPath), newValue); - - done(); }); - }, error => onError(error, done)); + }); }); - test('updateContent - use encoding (UTF 16 BE)', function (done: () => void) { + test('updateContent - use encoding (UTF 16 BE)', function () { const resource = uri.file(path.join(testDir, 'small.txt')); const encoding = 'utf16be'; - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { c.encoding = encoding; return service.updateContent(c.resource, c.value, { encoding: encoding }).then(c => { @@ -743,19 +601,17 @@ suite('FileService', () => { return service.resolveContent(resource).then(c => { assert.equal(c.encoding, encoding); - - done(); }); }); }); - }, error => onError(error, done)); + }); }); - test('updateContent - use encoding (UTF 16 BE, ITextSnapShot)', function (done: () => void) { + test('updateContent - use encoding (UTF 16 BE, ITextSnapShot)', function () { const resource = uri.file(path.join(testDir, 'small.txt')); const encoding = 'utf16be'; - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { c.encoding = encoding; const model = TextModel.createFromString(c.value); @@ -768,19 +624,17 @@ suite('FileService', () => { assert.equal(c.encoding, encoding); model.dispose(); - - done(); }); }); }); - }, error => onError(error, done)); + }); }); - test('updateContent - encoding preserved (UTF 16 LE)', function (done: () => void) { + test('updateContent - encoding preserved (UTF 16 LE)', function () { const encoding = 'utf16le'; const resource = uri.file(path.join(testDir, 'some_utf16le.css')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.equal(c.encoding, encoding); c.value = 'Some updates'; @@ -791,19 +645,17 @@ suite('FileService', () => { return service.resolveContent(resource).then(c => { assert.equal(c.encoding, encoding); - - done(); }); }); }); - }, error => onError(error, done)); + }); }); - test('updateContent - encoding preserved (UTF 16 LE, ITextSnapShot)', function (done: () => void) { + test('updateContent - encoding preserved (UTF 16 LE, ITextSnapShot)', function () { const encoding = 'utf16le'; const resource = uri.file(path.join(testDir, 'some_utf16le.css')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.equal(c.encoding, encoding); const model = TextModel.createFromString('Some updates'); @@ -816,22 +668,18 @@ suite('FileService', () => { assert.equal(c.encoding, encoding); model.dispose(); - - done(); }); }); }); - }, error => onError(error, done)); + }); }); - test('resolveContent - large file', function (done: () => void) { + test('resolveContent - large file', function () { const resource = uri.file(path.join(testDir, 'lorem.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.ok(c.value.length > 64000); - - done(); - }, error => onError(error, done)); + }); }); test('Files are intermingled #38331', function () { @@ -851,108 +699,90 @@ suite('FileService', () => { }); }); - test('resolveContent - FILE_IS_BINARY', function (done: () => void) { + test('resolveContent - FILE_IS_BINARY', function () { const resource = uri.file(path.join(testDir, 'binary.txt')); - service.resolveContent(resource, { acceptTextOnly: true }).done(null, (e: FileOperationError) => { + return service.resolveContent(resource, { acceptTextOnly: true }).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_IS_BINARY); return service.resolveContent(uri.file(path.join(testDir, 'small.txt')), { acceptTextOnly: true }).then(r => { assert.equal(r.name, 'small.txt'); - - done(); }); - }, error => onError(error, done)); + }); }); - test('resolveContent - FILE_IS_DIRECTORY', function (done: () => void) { + test('resolveContent - FILE_IS_DIRECTORY', function () { const resource = uri.file(path.join(testDir, 'deep')); - service.resolveContent(resource).done(null, (e: FileOperationError) => { + return service.resolveContent(resource).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_IS_DIRECTORY); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - FILE_NOT_FOUND', function (done: () => void) { + test('resolveContent - FILE_NOT_FOUND', function () { const resource = uri.file(path.join(testDir, '404.html')); - service.resolveContent(resource).done(null, (e: FileOperationError) => { + return service.resolveContent(resource).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_NOT_FOUND); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - FILE_NOT_MODIFIED_SINCE', function (done: () => void) { + test('resolveContent - FILE_NOT_MODIFIED_SINCE', function () { const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { return service.resolveContent(resource, { etag: c.etag }).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_NOT_MODIFIED_SINCE); - - done(); }); - }, error => onError(error, done)); + }); }); - test('resolveContent - FILE_MODIFIED_SINCE', function (done: () => void) { + test('resolveContent - FILE_MODIFIED_SINCE', function () { const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { fs.writeFileSync(resource.fsPath, 'Updates Incoming!'); return service.updateContent(resource, c.value, { etag: c.etag, mtime: c.mtime - 1000 }).then(null, (e: FileOperationError) => { assert.equal(e.fileOperationResult, FileOperationResult.FILE_MODIFIED_SINCE); - - done(); }); - }, error => onError(error, done)); + }); }); - test('resolveContent - encoding picked up', function (done: () => void) { + test('resolveContent - encoding picked up', function () { const resource = uri.file(path.join(testDir, 'index.html')); const encoding = 'windows1252'; - service.resolveContent(resource, { encoding: encoding }).done(c => { + return service.resolveContent(resource, { encoding: encoding }).then(c => { assert.equal(c.encoding, encoding); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - user overrides BOM', function (done: () => void) { + test('resolveContent - user overrides BOM', function () { const resource = uri.file(path.join(testDir, 'some_utf16le.css')); - service.resolveContent(resource, { encoding: 'windows1252' }).done(c => { + return service.resolveContent(resource, { encoding: 'windows1252' }).then(c => { assert.equal(c.encoding, 'windows1252'); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - BOM removed', function (done: () => void) { + test('resolveContent - BOM removed', function () { const resource = uri.file(path.join(testDir, 'some_utf8_bom.txt')); - service.resolveContent(resource).done(c => { + return service.resolveContent(resource).then(c => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(Buffer.from(c.value), 512), null); - - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - invalid encoding', function (done: () => void) { + test('resolveContent - invalid encoding', function () { const resource = uri.file(path.join(testDir, 'index.html')); - service.resolveContent(resource, { encoding: 'superduper' }).done(c => { + return service.resolveContent(resource, { encoding: 'superduper' }).then(c => { assert.equal(c.encoding, 'utf8'); - - done(); - }, error => onError(error, done)); + }); }); - test('watchFileChanges', function (done: () => void) { + test('watchFileChanges', function (done) { const toWatch = uri.file(path.join(testDir, 'index.html')); service.watchFileChanges(toWatch); @@ -969,7 +799,7 @@ suite('FileService', () => { }, 100); }); - test('watchFileChanges - support atomic save', function (done: () => void) { + test('watchFileChanges - support atomic save', function (done) { const toWatch = uri.file(path.join(testDir, 'index.html')); service.watchFileChanges(toWatch); @@ -991,17 +821,17 @@ suite('FileService', () => { }, 100); }); - test('options - encoding', function (done: () => void) { + test('options - encoding override (parent)', function () { // setup const _id = uuid.generateUuid(); const _testDir = path.join(parentDir, _id); const _sourceDir = require.toUrl('./fixtures/service'); - extfs.copy(_sourceDir, _testDir, () => { + return pfs.copy(_sourceDir, _testDir).then(() => { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ - resource: uri.file(path.join(testDir, 'deep')), + parent: uri.file(path.join(testDir, 'deep')), encoding: 'utf16le' }); @@ -1010,26 +840,78 @@ suite('FileService', () => { const textResourceConfigurationService = new TestTextResourceConfigurationService(configurationService); - const _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, toWorkspaceFolders([{ path: _testDir }]))), TestEnvironmentService, textResourceConfigurationService, configurationService, new TestLifecycleService(), { - encodingOverride, - disableWatcher: true - }); + const _service = new FileService( + new TestContextService(new Workspace(_testDir, _testDir, toWorkspaceFolders([{ path: _testDir }]))), + TestEnvironmentService, + textResourceConfigurationService, + configurationService, + new TestLifecycleService(), + new TestStorageService(), + new TestNotificationService(), + { + encodingOverride, + disableWatcher: true + }); - _service.resolveContent(uri.file(path.join(testDir, 'index.html'))).done(c => { + return _service.resolveContent(uri.file(path.join(testDir, 'index.html'))).then(c => { assert.equal(c.encoding, 'windows1252'); - return _service.resolveContent(uri.file(path.join(testDir, 'deep', 'conway.js'))).done(c => { + return _service.resolveContent(uri.file(path.join(testDir, 'deep', 'conway.js'))).then(c => { assert.equal(c.encoding, 'utf16le'); // teardown _service.dispose(); - done(); }); }); }); }); - test('UTF 8 BOMs', function (done: () => void) { + test('options - encoding override (extension)', function () { + + // setup + const _id = uuid.generateUuid(); + const _testDir = path.join(parentDir, _id); + const _sourceDir = require.toUrl('./fixtures/service'); + + return pfs.copy(_sourceDir, _testDir).then(() => { + const encodingOverride: IEncodingOverride[] = []; + encodingOverride.push({ + extension: 'js', + encoding: 'utf16le' + }); + + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('files', { encoding: 'windows1252' }); + + const textResourceConfigurationService = new TestTextResourceConfigurationService(configurationService); + + const _service = new FileService( + new TestContextService(new Workspace(_testDir, _testDir, toWorkspaceFolders([{ path: _testDir }]))), + TestEnvironmentService, + textResourceConfigurationService, + configurationService, + new TestLifecycleService(), + new TestStorageService(), + new TestNotificationService(), + { + encodingOverride, + disableWatcher: true + }); + + return _service.resolveContent(uri.file(path.join(testDir, 'index.html'))).then(c => { + assert.equal(c.encoding, 'windows1252'); + + return _service.resolveContent(uri.file(path.join(testDir, 'deep', 'conway.js'))).then(c => { + assert.equal(c.encoding, 'utf16le'); + + // teardown + _service.dispose(); + }); + }); + }); + }); + + test('UTF 8 BOMs', function () { // setup const _id = uuid.generateUuid(); @@ -1037,42 +919,49 @@ suite('FileService', () => { const _sourceDir = require.toUrl('./fixtures/service'); const resource = uri.file(path.join(testDir, 'index.html')); - const _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, toWorkspaceFolders([{ path: _testDir }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), { - disableWatcher: true - }); + const _service = new FileService( + new TestContextService(new Workspace(_testDir, _testDir, toWorkspaceFolders([{ path: _testDir }]))), + TestEnvironmentService, + new TestTextResourceConfigurationService(), + new TestConfigurationService(), + new TestLifecycleService(), + new TestStorageService(), + new TestNotificationService(), + { + disableWatcher: true + }); - extfs.copy(_sourceDir, _testDir, () => { - fs.readFile(resource.fsPath, (error, data) => { + return pfs.copy(_sourceDir, _testDir).then(() => { + return pfs.readFile(resource.fsPath).then(data => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); const model = TextModel.createFromString('Hello Bom'); // Update content: UTF_8 => UTF_8_BOM - _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8_with_bom }).done(() => { - fs.readFile(resource.fsPath, (error, data) => { + return _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8_with_bom }).then(() => { + return pfs.readFile(resource.fsPath).then(data => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), encodingLib.UTF8); // Update content: PRESERVE BOM when using UTF-8 model.setValue('Please stay Bom'); - _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).done(() => { - fs.readFile(resource.fsPath, (error, data) => { + return _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).then(() => { + return pfs.readFile(resource.fsPath).then(data => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), encodingLib.UTF8); // Update content: REMOVE BOM model.setValue('Go away Bom'); - _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8, overwriteEncoding: true }).done(() => { - fs.readFile(resource.fsPath, (error, data) => { + return _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8, overwriteEncoding: true }).then(() => { + return pfs.readFile(resource.fsPath).then(data => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); // Update content: BOM comes not back model.setValue('Do not come back Bom'); - _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).done(() => { - fs.readFile(resource.fsPath, (error, data) => { + return _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).then(() => { + return pfs.readFile(resource.fsPath).then(data => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); model.dispose(); _service.dispose(); - done(); }); }); }); @@ -1085,21 +974,19 @@ suite('FileService', () => { }); }); - test('resolveContent - from position (ASCII)', function (done: () => void) { + test('resolveContent - from position (ASCII)', function () { const resource = uri.file(path.join(testDir, 'small.txt')); - service.resolveContent(resource, { position: 6 }).done(content => { + return service.resolveContent(resource, { position: 6 }).then(content => { assert.equal(content.value, 'File'); - done(); - }, error => onError(error, done)); + }); }); - test('resolveContent - from position (with umlaut)', function (done: () => void) { + test('resolveContent - from position (with umlaut)', function () { const resource = uri.file(path.join(testDir, 'small_umlaut.txt')); - service.resolveContent(resource, { position: Buffer.from('Small File with Ü').length }).done(content => { + return service.resolveContent(resource, { position: Buffer.from('Small File with Ü').length }).then(content => { assert.equal(content.value, 'mlaut'); - done(); - }, error => onError(error, done)); + }); }); }); diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/examples/company.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/company.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/examples/company.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/company.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/examples/conway.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/conway.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/examples/conway.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/conway.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/examples/employee.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/employee.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/examples/employee.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/employee.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/examples/small.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/small.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/examples/small.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/examples/small.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/index.html b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/index.html similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/index.html rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/index.html diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/company.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/company.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/company.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/company.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/conway.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/conway.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/conway.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/conway.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/employee.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/employee.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/employee.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/employee.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/small.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/small.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/other/deep/small.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/other/deep/small.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/resolver/site.css b/src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/site.css similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/resolver/site.css rename to src/vs/workbench/services/files/test/electron-browser/fixtures/resolver/site.css diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/binary.txt b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/binary.txt similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/binary.txt rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/binary.txt diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/deep/company.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/company.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/deep/company.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/company.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/deep/conway.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/conway.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/deep/conway.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/conway.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/deep/employee.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/employee.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/deep/employee.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/employee.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/deep/small.js b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/small.js similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/deep/small.js rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/deep/small.js diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/index.html b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/index.html similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/index.html rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/index.html diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/lorem.txt b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/lorem.txt similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/lorem.txt rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/lorem.txt diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/small.txt b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/small.txt similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/small.txt rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/small.txt diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/small_umlaut.txt b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/small_umlaut.txt similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/small_umlaut.txt rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/small_umlaut.txt diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/some_utf16le.css b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/some_utf16le.css similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/some_utf16le.css rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/some_utf16le.css diff --git a/src/vs/workbench/services/files/test/node/fixtures/service/some_utf8_bom.txt b/src/vs/workbench/services/files/test/electron-browser/fixtures/service/some_utf8_bom.txt similarity index 100% rename from src/vs/workbench/services/files/test/node/fixtures/service/some_utf8_bom.txt rename to src/vs/workbench/services/files/test/electron-browser/fixtures/service/some_utf8_bom.txt diff --git a/src/vs/workbench/services/files/test/node/resolver.test.ts b/src/vs/workbench/services/files/test/electron-browser/resolver.test.ts similarity index 82% rename from src/vs/workbench/services/files/test/node/resolver.test.ts rename to src/vs/workbench/services/files/test/electron-browser/resolver.test.ts index 0db337a9ba..60a77d5f39 100644 --- a/src/vs/workbench/services/files/test/node/resolver.test.ts +++ b/src/vs/workbench/services/files/test/electron-browser/resolver.test.ts @@ -5,14 +5,14 @@ 'use strict'; -import fs = require('fs'); -import path = require('path'); -import assert = require('assert'); +import * as fs from 'fs'; +import * as path from 'path'; +import * as assert from 'assert'; -import { StatResolver } from 'vs/workbench/services/files/node/fileService'; +import { StatResolver } from 'vs/workbench/services/files/electron-browser/fileService'; import uri from 'vs/base/common/uri'; import { isLinux } from 'vs/base/common/platform'; -import utils = require('vs/workbench/services/files/test/node/utils'); +import * as utils from 'vs/workbench/services/files/test/electron-browser/utils'; function create(relativePath: string): StatResolver { let basePath = require.toUrl('./fixtures/resolver'); @@ -31,9 +31,9 @@ function toResource(relativePath: string): uri { suite('Stat Resolver', () => { - test('resolve file', function (done: () => void) { + test('resolve file', function () { let resolver = create('/index.html'); - resolver.resolve(null).then(result => { + return resolver.resolve(null).then(result => { assert.ok(!result.isDirectory); assert.equal(result.name, 'index.html'); assert.ok(!!result.etag); @@ -42,16 +42,15 @@ suite('Stat Resolver', () => { return resolver.resolve(null).then(result => { assert.ok(result.isDirectory); }); - }) - .done(() => done(), done); + }); }); - test('resolve directory', function (done: () => void) { + test('resolve directory', function () { let testsElements = ['examples', 'other', 'index.html', 'site.css']; let resolver = create('/'); - resolver.resolve(null).then(result => { + return resolver.resolve(null).then(result => { assert.ok(result); assert.ok(result.children); assert.ok(result.children.length > 0); @@ -78,14 +77,13 @@ suite('Stat Resolver', () => { assert.ok(!'Unexpected value ' + path.basename(value.resource.fsPath)); } }); - }) - .done(() => done(), done); + }); }); - test('resolve directory - resolveTo single directory', function (done: () => void) { + test('resolve directory - resolveTo single directory', function () { let resolver = create('/'); - resolver.resolve({ resolveTo: [toResource('other/deep')] }).then(result => { + return resolver.resolve({ resolveTo: [toResource('other/deep')] }).then(result => { assert.ok(result); assert.ok(result.children); assert.ok(result.children.length > 0); @@ -102,14 +100,13 @@ suite('Stat Resolver', () => { assert.ok(deep); assert.ok(deep.children.length > 0); assert.equal(deep.children.length, 4); - }) - .done(() => done(), done); + }); }); - test('resolve directory - resolveTo single directory - mixed casing', function (done: () => void) { + test('resolve directory - resolveTo single directory - mixed casing', function () { let resolver = create('/'); - resolver.resolve({ resolveTo: [toResource('other/Deep')] }).then(result => { + return resolver.resolve({ resolveTo: [toResource('other/Deep')] }).then(result => { assert.ok(result); assert.ok(result.children); assert.ok(result.children.length > 0); @@ -131,14 +128,13 @@ suite('Stat Resolver', () => { assert.ok(deep.children.length > 0); assert.equal(deep.children.length, 4); } - }) - .done(() => done(), done); + }); }); - test('resolve directory - resolveTo multiple directories', function (done: () => void) { + test('resolve directory - resolveTo multiple directories', function () { let resolver = create('/'); - resolver.resolve({ resolveTo: [toResource('other/deep'), toResource('examples')] }).then(result => { + return resolver.resolve({ resolveTo: [toResource('other/deep'), toResource('examples')] }).then(result => { assert.ok(result); assert.ok(result.children); assert.ok(result.children.length > 0); @@ -160,14 +156,13 @@ suite('Stat Resolver', () => { assert.ok(examples); assert.ok(examples.children.length > 0); assert.equal(examples.children.length, 4); - }) - .done(() => done(), done); + }); }); - test('resolve directory - resolveSingleChildFolders', function (done: () => void) { + test('resolve directory - resolveSingleChildFolders', function () { let resolver = create('/other'); - resolver.resolve({ resolveSingleChildDescendants: true }).then(result => { + return resolver.resolve({ resolveSingleChildDescendants: true }).then(result => { assert.ok(result); assert.ok(result.children); assert.ok(result.children.length > 0); @@ -180,7 +175,6 @@ suite('Stat Resolver', () => { assert.ok(deep); assert.ok(deep.children.length > 0); assert.equal(deep.children.length, 4); - }) - .done(() => done(), done); + }); }); }); diff --git a/src/vs/workbench/services/files/test/node/utils.ts b/src/vs/workbench/services/files/test/electron-browser/utils.ts similarity index 100% rename from src/vs/workbench/services/files/test/node/utils.ts rename to src/vs/workbench/services/files/test/electron-browser/utils.ts diff --git a/src/vs/workbench/services/files/test/node/watcher.test.ts b/src/vs/workbench/services/files/test/electron-browser/watcher.test.ts similarity index 97% rename from src/vs/workbench/services/files/test/node/watcher.test.ts rename to src/vs/workbench/services/files/test/electron-browser/watcher.test.ts index 9e4f081b83..227af446dc 100644 --- a/src/vs/workbench/services/files/test/node/watcher.test.ts +++ b/src/vs/workbench/services/files/test/electron-browser/watcher.test.ts @@ -5,16 +5,16 @@ 'use strict'; -import assert = require('assert'); +import * as assert from 'assert'; -import platform = require('vs/base/common/platform'); +import * as platform from 'vs/base/common/platform'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import uri from 'vs/base/common/uri'; import { IRawFileChange, toFileChangesEvent, normalize } from 'vs/workbench/services/files/node/watcher/common'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; class TestFileWatcher { - private _onFileChanges: Emitter; + private readonly _onFileChanges: Emitter; constructor() { this._onFileChanges = new Emitter(); diff --git a/src/vs/workbench/services/group/common/groupService.ts b/src/vs/workbench/services/group/common/groupService.ts index f9f6fdd159..c99d4e0f9c 100644 --- a/src/vs/workbench/services/group/common/groupService.ts +++ b/src/vs/workbench/services/group/common/groupService.ts @@ -8,7 +8,7 @@ import { createDecorator, ServiceIdentifier, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Position, IEditorInput } from 'vs/platform/editor/common/editor'; import { IEditorStacksModel, IEditorGroup, IEditorOpeningEvent } from 'vs/workbench/common/editor'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export enum GroupArrangement { MINIMIZE_OTHERS, diff --git a/src/vs/workbench/services/history/electron-browser/history.ts b/src/vs/workbench/services/history/electron-browser/history.ts index aca59794e6..d01df03cb8 100644 --- a/src/vs/workbench/services/history/electron-browser/history.ts +++ b/src/vs/workbench/services/history/electron-browser/history.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { IEditor } from 'vs/editor/common/editorCommon'; import { IEditor as IBaseEditor, IEditorInput, ITextEditorOptions, IResourceInput, ITextEditorSelection, Position as GroupPosition } from 'vs/platform/editor/common/editor'; diff --git a/src/vs/workbench/services/issue/common/issue.ts b/src/vs/workbench/services/issue/common/issue.ts index 0a7f802746..8556cc2b76 100644 --- a/src/vs/workbench/services/issue/common/issue.ts +++ b/src/vs/workbench/services/issue/common/issue.ts @@ -14,4 +14,5 @@ export const IWorkbenchIssueService = createDecorator('w export interface IWorkbenchIssueService { _serviceBrand: any; openReporter(dataOverrides?: Partial): TPromise; + openProcessExplorer(): TPromise; } diff --git a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts index b06213492c..5b00f414af 100644 --- a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts +++ b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts @@ -8,10 +8,9 @@ import { IssueReporterStyles, IIssueService, IssueReporterData } from 'vs/platform/issue/common/issue'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry'; +import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IExtensionManagementService, IExtensionEnablementService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { webFrame } from 'electron'; import { assign } from 'vs/base/common/objects'; import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; @@ -29,7 +28,7 @@ export class WorkbenchIssueService implements IWorkbenchIssueService { openReporter(dataOverrides: Partial = {}): TPromise { return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => { - const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled({ id: getGalleryExtensionIdFromLocal(extension) })); + const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension)); const theme = this.themeService.getTheme(); const issueReporterData: IssueReporterData = assign( { @@ -42,6 +41,21 @@ export class WorkbenchIssueService implements IWorkbenchIssueService { return this.issueService.openReporter(issueReporterData); }); } + + openProcessExplorer(): TPromise { + const theme = this.themeService.getTheme(); + const data = { + zoomLevel: webFrame.getZoomLevel(), + styles: { + backgroundColor: theme.getColor(editorBackground) && theme.getColor(editorBackground).toString(), + color: theme.getColor(editorForeground).toString(), + hoverBackground: theme.getColor(listHoverBackground) && theme.getColor(listHoverBackground).toString(), + hoverForeground: theme.getColor(listHoverForeground) && theme.getColor(listHoverForeground).toString(), + highlightForeground: theme.getColor(listHighlightForeground) && theme.getColor(listHighlightForeground).toString() + } + }; + return this.issueService.openProcessExplorer(data); + } } export function getIssueReporterStyles(theme: ITheme): IssueReporterStyles { diff --git a/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts b/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts index 00838e1591..876f963ea3 100644 --- a/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts +++ b/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import URI from 'vs/base/common/uri'; -import strings = require('vs/base/common/strings'); -import paths = require('vs/base/common/paths'); +import * as strings from 'vs/base/common/strings'; +import * as paths from 'vs/base/common/paths'; interface IJSONValidationExtensionPoint { fileMatch: string; diff --git a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts index ec9cf16452..d9e9f455f4 100644 --- a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts @@ -74,6 +74,9 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding { constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, firstPart: ScanCodeBinding, chordPart: ScanCodeBinding) { super(); + if (!firstPart) { + throw new Error(`Invalid USLayoutResolvedKeybinding`); + } this._mapper = mapper; this._OS = OS; this._firstPart = firstPart; diff --git a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts index ed36904c6c..22eeff6e81 100644 --- a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts @@ -86,6 +86,9 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { constructor(mapper: WindowsKeyboardMapper, firstPart: SimpleKeybinding, chordPart: SimpleKeybinding) { super(); + if (!firstPart) { + throw new Error(`Invalid WindowsNativeResolvedKeybinding firstPart`); + } this._mapper = mapper; this._firstPart = firstPart; this._chordPart = chordPart; diff --git a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts index 9e80b42889..eff3738a4c 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts @@ -31,7 +31,7 @@ import { IKeyboardMapper, CachedKeyboardMapper } from 'vs/workbench/services/key import { WindowsKeyboardMapper, IWindowsKeyboardMapping, windowsKeyboardMappingEquals } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper'; import { IMacLinuxKeyboardMapping, MacLinuxKeyboardMapper, macLinuxKeyboardMappingEquals } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper'; import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Extensions as ConfigExtensions, IConfigurationRegistry, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -46,8 +46,8 @@ export class KeyboardMapperFactory { private _keyboardMapper: IKeyboardMapper; private _initialized: boolean; - private _onDidChangeKeyboardMapper: Emitter = new Emitter(); - public onDidChangeKeyboardMapper: Event = this._onDidChangeKeyboardMapper.event; + private readonly _onDidChangeKeyboardMapper: Emitter = new Emitter(); + public readonly onDidChangeKeyboardMapper: Event = this._onDidChangeKeyboardMapper.event; private constructor() { this._layoutInfo = null; @@ -415,7 +415,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { /* __GDPR__ "customKeybindingsChanged" : { - "keyCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "keyCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this._telemetryService.publicLog('customKeybindingsChanged', { @@ -567,10 +567,10 @@ let schema: IJSONSchema = { } }; -let schemaRegistry = Registry.as(Extensions.JSONContribution); +let schemaRegistry = Registry.as(Extensions.JSONContribution); schemaRegistry.registerSchema(schemaId, schema); -const configurationRegistry = Registry.as(ConfigExtensions.Configuration); +const configurationRegistry = Registry.as(ConfigExtensions.Configuration); const keyboardConfiguration: IConfigurationNode = { 'id': 'keyboard', 'order': 15, diff --git a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts similarity index 88% rename from src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts rename to src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index f549980070..1116b48366 100644 --- a/src/vs/workbench/services/keybinding/test/node/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -5,22 +5,23 @@ 'use strict'; -import assert = require('assert'); -import os = require('os'); -import path = require('path'); -import fs = require('fs'); +import * as assert from 'assert'; +import * as os from 'os'; +import * as path from 'path'; +import * as fs from 'fs'; import * as json from 'vs/base/common/json'; import { OS } from 'vs/base/common/platform'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; import { TPromise } from 'vs/base/common/winjs.base'; import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCodes'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import extfs = require('vs/base/node/extfs'); -import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices'; +import * as extfs from 'vs/base/node/extfs'; +import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { IWorkspaceContextService, Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; -import uuid = require('vs/base/common/uuid'); +import * as uuid from 'vs/base/common/uuid'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; -import { FileService } from 'vs/workbench/services/files/node/fileService'; +import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -80,7 +81,16 @@ suite('Keybindings Editing', () => { instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(IModeService, ModeServiceImpl); instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); - instantiationService.stub(IFileService, new FileService(new TestContextService(new Workspace(testDir, testDir, toWorkspaceFolders([{ path: testDir }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), lifecycleService, { disableWatcher: true })); + instantiationService.stub(IFileService, new FileService( + new TestContextService(new Workspace(testDir, testDir, toWorkspaceFolders([{ path: testDir }]))), + TestEnvironmentService, + new TestTextResourceConfigurationService(), + new TestConfigurationService(), + lifecycleService, + new TestStorageService(), + new TestNotificationService(), + { disableWatcher: true }) + ); instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); @@ -109,28 +119,28 @@ suite('Keybindings Editing', () => { fs.writeFileSync(keybindingsFile, ',,,,,,,,,,,,,,'); return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } })) .then(() => assert.fail('Should fail with parse errors'), - error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.')); + error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.')); }); test('errors cases - parse errors 2', () => { fs.writeFileSync(keybindingsFile, '[{"key": }]'); return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } })) .then(() => assert.fail('Should fail with parse errors'), - error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.')); + error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.')); }); test('errors cases - dirty', () => { instantiationService.stub(ITextFileService, 'isDirty', true); return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } })) .then(() => assert.fail('Should fail with dirty error'), - error => assert.equal(error.message, 'Unable to write because the keybindings configuration file is dirty. Please save it first and then try again.')); + error => assert.equal(error.message, 'Unable to write because the keybindings configuration file is dirty. Please save it first and then try again.')); }); test('errors cases - did not find an array', () => { fs.writeFileSync(keybindingsFile, '{"key": "alt+c", "command": "hello"}'); return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } })) .then(() => assert.fail('Should fail with dirty error'), - error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. It has an object which is not of type Array. Please open the file to clean up and try again.')); + error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. It has an object which is not of type Array. Please open the file to clean up and try again.')); }); test('edit a default keybinding to an empty file', () => { diff --git a/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts b/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts index 45f4d750bb..a563f4e9ca 100644 --- a/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts +++ b/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts @@ -62,20 +62,16 @@ export function readRawMapping(file: string): TPromise { }); } -export function assertMapping(writeFileIfDifferent: boolean, mapper: IKeyboardMapper, file: string, done: (err?: any) => void): void { +export function assertMapping(writeFileIfDifferent: boolean, mapper: IKeyboardMapper, file: string): TPromise { const filePath = require.toUrl(`vs/workbench/services/keybinding/test/${file}`); - readFile(filePath).then((buff) => { + return readFile(filePath).then((buff) => { let expected = buff.toString(); const actual = mapper.dumpDebugInfo(); if (actual !== expected && writeFileIfDifferent) { writeFile(filePath, actual); } - try { - assert.deepEqual(actual.split(/\r\n|\n/), expected.split(/\r\n|\n/)); - } catch (err) { - return done(err); - } - done(); - }, done); + + assert.deepEqual(actual.split(/\r\n|\n/), expected.split(/\r\n|\n/)); + }); } diff --git a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts index 1b0ab4d34d..35559acd49 100644 --- a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts @@ -27,15 +27,14 @@ suite('keyboardMapper - MAC de_ch', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'mac_de_ch', OperatingSystem.Macintosh).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'mac_de_ch', OperatingSystem.Macintosh).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_de_ch.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_de_ch.txt'); }); function assertKeybindingTranslation(kb: number, expected: string | string[]): void { @@ -378,15 +377,14 @@ suite('keyboardMapper - MAC en_us', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(true, 'mac_en_us', OperatingSystem.Macintosh).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(true, 'mac_en_us', OperatingSystem.Macintosh).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_en_us.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_en_us.txt'); }); test('resolveUserBinding Cmd+[Comma] Cmd+/', () => { @@ -457,15 +455,14 @@ suite('keyboardMapper - LINUX de_ch', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'linux_de_ch', OperatingSystem.Linux).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'linux_de_ch', OperatingSystem.Linux).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_de_ch.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_de_ch.txt'); }); function assertKeybindingTranslation(kb: number, expected: string | string[]): void { @@ -808,15 +805,14 @@ suite('keyboardMapper - LINUX en_us', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(true, 'linux_en_us', OperatingSystem.Linux).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(true, 'linux_en_us', OperatingSystem.Linux).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_en_us.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_en_us.txt'); }); function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void { @@ -1328,15 +1324,14 @@ suite('keyboardMapper - LINUX ru', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'linux_ru', OperatingSystem.Linux).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'linux_ru', OperatingSystem.Linux).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_ru.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_ru.txt'); }); function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void { @@ -1363,15 +1358,14 @@ suite('keyboardMapper - LINUX en_uk', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'linux_en_uk', OperatingSystem.Linux).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'linux_en_uk', OperatingSystem.Linux).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_en_uk.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'linux_en_uk.txt'); }); test('issue #24522: resolveKeyboardEvent Ctrl+Alt+[Minus]', () => { @@ -1402,15 +1396,14 @@ suite('keyboardMapper - MAC zh_hant', () => { let mapper: MacLinuxKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'mac_zh_hant', OperatingSystem.Macintosh).then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'mac_zh_hant', OperatingSystem.Macintosh).then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_zh_hant.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'mac_zh_hant.txt'); }); function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void { diff --git a/src/vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts index 90ff5df308..af37ba5ba5 100644 --- a/src/vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts @@ -28,15 +28,14 @@ suite('keyboardMapper - WINDOWS de_ch', () => { let mapper: WindowsKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'win_de_ch').then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'win_de_ch').then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_de_ch.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_de_ch.txt'); }); test('resolveKeybinding Ctrl+A', () => { @@ -321,15 +320,14 @@ suite('keyboardMapper - WINDOWS en_us', () => { let mapper: WindowsKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(true, 'win_en_us').then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(true, 'win_en_us').then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_en_us.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_en_us.txt'); }); test('resolveKeybinding Ctrl+K Ctrl+\\', () => { @@ -410,15 +408,14 @@ suite('keyboardMapper - WINDOWS por_ptb', () => { let mapper: WindowsKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'win_por_ptb').then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'win_por_ptb').then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_por_ptb.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_por_ptb.txt'); }); test('resolveKeyboardEvent Ctrl+[IntlRo]', () => { @@ -472,15 +469,14 @@ suite('keyboardMapper - WINDOWS ru', () => { let mapper: WindowsKeyboardMapper; - suiteSetup((done) => { - createKeyboardMapper(false, 'win_ru').then((_mapper) => { + suiteSetup(() => { + return createKeyboardMapper(false, 'win_ru').then((_mapper) => { mapper = _mapper; - done(); - }, done); + }); }); - test('mapping', (done) => { - assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_ru.txt', done); + test('mapping', () => { + return assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_ru.txt'); }); test('issue ##24361: resolveKeybinding Ctrl+K Ctrl+K', () => { diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index fd383d57e2..238ddb2c48 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import * as paths from 'vs/base/common/paths'; import { TPromise } from 'vs/base/common/winjs.base'; -import mime = require('vs/base/common/mime'); +import * as mime from 'vs/base/common/mime'; import { IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index 39f87cddb9..ee5fbf695d 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -3,6 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +'use strict'; + import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice } from 'vs/platform/notification/common/notification'; import { INotificationsModel, NotificationsModel } from 'vs/workbench/common/notifications'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/services/panel/common/panelService.ts b/src/vs/workbench/services/panel/common/panelService.ts index 16fdf76c21..85ea4d0b1c 100644 --- a/src/vs/workbench/services/panel/common/panelService.ts +++ b/src/vs/workbench/services/panel/common/panelService.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IPanel } from 'vs/workbench/common/panel'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/services/part/common/partService.ts b/src/vs/workbench/services/part/common/partService.ts index c42e050b21..edfd240a6b 100644 --- a/src/vs/workbench/services/part/common/partService.ts +++ b/src/vs/workbench/services/part/common/partService.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; export enum Parts { ACTIVITYBAR_PART, @@ -28,7 +28,7 @@ export interface ILayoutOptions { source?: Parts; } -export interface Dimension { +export interface IDimension { readonly width: number; readonly height: number; } @@ -46,7 +46,7 @@ export interface IPartService { /** * Emits when the editor part's layout changes. */ - onEditorLayout: Event; + onEditorLayout: Event; /** * Asks the part service to layout all parts. @@ -135,12 +135,12 @@ export interface IPartService { isEditorLayoutCentered(): boolean; /** - * Toggles the workbench in and out of centered editor layout. + * Sets the workbench in and out of centered editor layout. */ - toggleCenteredEditorLayout(): void; + centerEditorLayout(active: boolean): void; /** * Resizes currently focused part on main access */ resizePart(part: Parts, sizeChange: number): void; -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts similarity index 72% rename from src/vs/workbench/parts/preferences/browser/preferencesService.ts rename to src/vs/workbench/services/preferences/browser/preferencesService.ts index bddf0da8bb..11d92d69ad 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -3,7 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/preferences'; import * as network from 'vs/base/common/network'; import { TPromise } from 'vs/base/common/winjs.base'; import * as nls from 'vs/nls'; @@ -22,11 +21,10 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; -import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, DefaultSettings, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; +import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/services/preferences/common/preferences'; +import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, DefaultSettings, WorkspaceConfigurationEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; -import { KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor'; +import { DefaultPreferencesEditorInput, PreferencesEditorInput, KeybindingsEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -34,7 +32,6 @@ import { Position, IPosition } from 'vs/editor/common/core/position'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; -import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IModeService } from 'vs/editor/common/services/modeService'; import { parse } from 'vs/base/common/json'; @@ -49,12 +46,14 @@ export class PreferencesService extends Disposable implements IPreferencesServic private lastOpenedSettingsInput: PreferencesEditorInput = null; - private _onDispose: Emitter = new Emitter(); + private readonly _onDispose: Emitter = new Emitter(); - private _defaultSettingsUriCounter = 0; - private _defaultSettingsContentModel: DefaultSettings; - private _defaultResourceSettingsUriCounter = 0; - private _defaultResourceSettingsContentModel: DefaultSettings; + private _defaultUserSettingsUriCounter = 0; + private _defaultUserSettingsContentModel: DefaultSettings; + private _defaultWorkspaceSettingsUriCounter = 0; + private _defaultWorkspaceSettingsContentModel: DefaultSettings; + private _defaultFolderSettingsUriCounter = 0; + private _defaultFolderSettingsContentModel: DefaultSettings; constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @@ -73,13 +72,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic @IModeService private modeService: IModeService ) { super(); - this.editorGroupService.onEditorsChanged(() => { - const activeEditorInput = this.editorService.getActiveEditorInput(); - if (activeEditorInput instanceof PreferencesEditorInput) { - this.lastOpenedSettingsInput = activeEditorInput; - } - }); - // The default keybindings.json updates based on keyboard layouts, so here we make sure // if a model has been given out we update it accordingly. keybindingService.onDidUpdateKeybindings(() => { @@ -108,9 +100,9 @@ export class PreferencesService extends Disposable implements IPreferencesServic } resolveModel(uri: URI): TPromise { - if (this.isDefaultSettingsResource(uri) || this.isDefaultResourceSettingsResource(uri)) { + if (this.isDefaultSettingsResource(uri)) { - const scope = this.isDefaultSettingsResource(uri) ? ConfigurationScope.WINDOW : ConfigurationScope.RESOURCE; + const target = this.getConfigurationTargetFromDefaultSettingsResource(uri); const mode = this.modeService.getOrCreateMode('jsonc'); const model = this._register(this.modelService.createModel('', mode, uri)); @@ -122,7 +114,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic // model has not been given out => nothing to do return; } - defaultSettings = this.getDefaultSettings(scope); + defaultSettings = this.getDefaultSettings(target); this.modelService.updateModel(model, defaultSettings.parse()); defaultSettings._onDidChange.fire(); } @@ -130,7 +122,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic // Check if Default settings is already created and updated in above promise if (!defaultSettings) { - defaultSettings = this.getDefaultSettings(scope); + defaultSettings = this.getDefaultSettings(target); this.modelService.updateModel(model, defaultSettings.parse()); } @@ -138,7 +130,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } if (this.defaultSettingsRawResource.toString() === uri.toString()) { - let defaultSettings: DefaultSettings = this.getDefaultSettings(ConfigurationScope.WINDOW); + let defaultSettings: DefaultSettings = this.getDefaultSettings(ConfigurationTarget.USER); const mode = this.modeService.getOrCreateMode('jsonc'); const model = this._register(this.modelService.createModel(defaultSettings.raw, mode, uri)); return TPromise.as(model); @@ -155,7 +147,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } createPreferencesEditorModel(uri: URI): TPromise> { - if (this.isDefaultSettingsResource(uri) || this.isDefaultResourceSettingsResource(uri)) { + if (this.isDefaultSettingsResource(uri)) { return this.createDefaultSettingsEditorModel(uri); } @@ -179,8 +171,15 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.editorService.openEditor({ resource: this.defaultSettingsRawResource }, EditorPosition.ONE) as TPromise; } + openSettings(): TPromise { + const editorInput = this.getActiveSettingsEditorInput() || this.lastOpenedSettingsInput; + const resource = editorInput ? editorInput.master.getResource() : this.userSettingsResource; + const target = this.getConfigurationTargetFromSettingsResource(resource); + return this.openOrSwitchSettings(target, resource); + } + openGlobalSettings(options?: IEditorOptions, position?: EditorPosition): TPromise { - return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource, options, position); + return this.openOrSwitchSettings(ConfigurationTarget.USER, this.userSettingsResource, options, position); } openWorkspaceSettings(options?: IEditorOptions, position?: EditorPosition): TPromise { @@ -188,36 +187,26 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.notificationService.info(nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); return TPromise.as(null); } - return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, options, position); + return this.openOrSwitchSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, options, position); } openFolderSettings(folder: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { - return this.doOpenSettings(ConfigurationTarget.WORKSPACE_FOLDER, this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder), options, position); + return this.openOrSwitchSettings(ConfigurationTarget.WORKSPACE_FOLDER, this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder), options, position); } switchSettings(target: ConfigurationTarget, resource: URI): TPromise { const activeEditor = this.editorService.getActiveEditor(); if (activeEditor && activeEditor.input instanceof PreferencesEditorInput) { - return this.getOrCreateEditableSettingsEditorInput(target, this.getEditableSettingsURI(target, resource)) - .then(toInput => { - const replaceWith = new PreferencesEditorInput(this.getPreferencesEditorInputName(target, resource), toInput.getDescription(), this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(target)), toInput); - return this.editorService.replaceEditors([{ - toReplace: this.lastOpenedSettingsInput, - replaceWith - }], activeEditor.position).then(() => { - this.lastOpenedSettingsInput = replaceWith; - }); - }); + return this.doSwitchSettings(target, resource, activeEditor.input, activeEditor.position).then(() => null); } else { - this.doOpenSettings(target, resource); - return undefined; + return this.doOpenSettings(target, resource).then(() => null); } } openGlobalKeybindingSettings(textual: boolean): TPromise { /* __GDPR__ "openKeybindings" : { - "textual" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "textual" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ this.telemetryService.publicLog('openKeybindings', { textual }); @@ -251,6 +240,16 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } + private openOrSwitchSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { + const activeGroup = this.editorGroupService.getStacksModel().activeGroup; + const positionToReplace = position !== void 0 ? position : activeGroup ? this.editorGroupService.getStacksModel().positionOfGroup(activeGroup) : EditorPosition.ONE; + const editorInput = this.getActiveSettingsEditorInput(positionToReplace); + if (editorInput && editorInput.master.getResource().fsPath !== resource.fsPath) { + return this.doSwitchSettings(configurationTarget, resource, editorInput, positionToReplace); + } + return this.doOpenSettings(configurationTarget, resource, options, position); + } + private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: IEditorOptions, position?: EditorPosition): TPromise { const openDefaultSettings = !!this.configurationService.getValue(DEFAULT_SETTINGS_EDITOR_SETTING); return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource) @@ -271,20 +270,72 @@ export class PreferencesService extends Disposable implements IPreferencesServic }); } + private doSwitchSettings(target: ConfigurationTarget, resource: URI, input: PreferencesEditorInput, position?: EditorPosition): TPromise { + return this.getOrCreateEditableSettingsEditorInput(target, this.getEditableSettingsURI(target, resource)) + .then(toInput => { + const replaceWith = new PreferencesEditorInput(this.getPreferencesEditorInputName(target, resource), toInput.getDescription(), this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(target)), toInput); + return this.editorService.replaceEditors([{ + toReplace: input, + replaceWith + }], position).then(editors => { + this.lastOpenedSettingsInput = replaceWith; + return editors[0]; + }); + }); + } + + private getActiveSettingsEditorInput(position?: EditorPosition): PreferencesEditorInput { + const stacksModel = this.editorGroupService.getStacksModel(); + const group = position !== void 0 ? stacksModel.groupAt(position) : stacksModel.activeGroup; + return group && group.getEditors().filter(e => e instanceof PreferencesEditorInput)[0]; + } + + private getConfigurationTargetFromSettingsResource(resource: URI): ConfigurationTarget { + if (this.userSettingsResource.toString() === resource.toString()) { + return ConfigurationTarget.USER; + } + + const workspaceSettingsResource = this.workspaceSettingsResource; + if (workspaceSettingsResource && workspaceSettingsResource.toString() === resource.toString()) { + return ConfigurationTarget.WORKSPACE; + } + + const folder = this.contextService.getWorkspaceFolder(resource); + if (folder) { + return ConfigurationTarget.WORKSPACE_FOLDER; + } + + return ConfigurationTarget.USER; + } + + private getConfigurationTargetFromDefaultSettingsResource(uri: URI) { + return this.isDefaultWorkspaceSettingsResource(uri) ? ConfigurationTarget.WORKSPACE : this.isDefaultFolderSettingsResource(uri) ? ConfigurationTarget.WORKSPACE_FOLDER : ConfigurationTarget.USER; + } + private isDefaultSettingsResource(uri: URI): boolean { + return this.isDefaultUserSettingsResource(uri) || this.isDefaultWorkspaceSettingsResource(uri) || this.isDefaultFolderSettingsResource(uri); + } + + private isDefaultUserSettingsResource(uri: URI): boolean { return uri.authority === 'defaultsettings' && uri.scheme === network.Schemas.vscode && !!uri.path.match(/\/(\d+\/)?settings\.json$/); } - private isDefaultResourceSettingsResource(uri: URI): boolean { + private isDefaultWorkspaceSettingsResource(uri: URI): boolean { + return uri.authority === 'defaultsettings' && uri.scheme === network.Schemas.vscode && !!uri.path.match(/\/(\d+\/)?workspaceSettings\.json$/); + } + + private isDefaultFolderSettingsResource(uri: URI): boolean { return uri.authority === 'defaultsettings' && uri.scheme === network.Schemas.vscode && !!uri.path.match(/\/(\d+\/)?resourceSettings\.json$/); } private getDefaultSettingsResource(configurationTarget: ConfigurationTarget): URI { - if (configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { - return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultResourceSettingsUriCounter++}/resourceSettings.json` }); - } else { - return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultSettingsUriCounter++}/settings.json` }); + switch (configurationTarget) { + case ConfigurationTarget.WORKSPACE: + return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultWorkspaceSettingsUriCounter++}/workspaceSettings.json` }); + case ConfigurationTarget.WORKSPACE_FOLDER: + return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultFolderSettingsUriCounter++}/resourceSettings.json` }); } + return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultUserSettingsUriCounter++}/settings.json` }); } private getPreferencesEditorInputName(target: ConfigurationTarget, resource: URI): string { @@ -314,24 +365,28 @@ export class PreferencesService extends Disposable implements IPreferencesServic private createDefaultSettingsEditorModel(defaultSettingsUri: URI): TPromise { return this.textModelResolverService.createModelReference(defaultSettingsUri) .then(reference => { - const scope = this.isDefaultSettingsResource(defaultSettingsUri) ? ConfigurationScope.WINDOW : ConfigurationScope.RESOURCE; - return this.instantiationService.createInstance(DefaultSettingsEditorModel, defaultSettingsUri, reference, scope, this.getDefaultSettings(scope)); + const target = this.getConfigurationTargetFromDefaultSettingsResource(defaultSettingsUri); + return this.instantiationService.createInstance(DefaultSettingsEditorModel, defaultSettingsUri, reference, this.getDefaultSettings(target)); }); } - private getDefaultSettings(scope: ConfigurationScope): DefaultSettings { - switch (scope) { - case ConfigurationScope.WINDOW: - if (!this._defaultSettingsContentModel) { - this._defaultSettingsContentModel = new DefaultSettings(this.getMostCommonlyUsedSettings(), scope); - } - return this._defaultSettingsContentModel; - case ConfigurationScope.RESOURCE: - if (!this._defaultResourceSettingsContentModel) { - this._defaultResourceSettingsContentModel = new DefaultSettings(this.getMostCommonlyUsedSettings(), scope); - } - return this._defaultResourceSettingsContentModel; + private getDefaultSettings(target: ConfigurationTarget): DefaultSettings { + if (target === ConfigurationTarget.WORKSPACE) { + if (!this._defaultWorkspaceSettingsContentModel) { + this._defaultWorkspaceSettingsContentModel = new DefaultSettings(this.getMostCommonlyUsedSettings(), target); + } + return this._defaultWorkspaceSettingsContentModel; } + if (target === ConfigurationTarget.WORKSPACE_FOLDER) { + if (!this._defaultFolderSettingsContentModel) { + this._defaultFolderSettingsContentModel = new DefaultSettings(this.getMostCommonlyUsedSettings(), target); + } + return this._defaultFolderSettingsContentModel; + } + if (!this._defaultUserSettingsContentModel) { + this._defaultUserSettingsContentModel = new DefaultSettings(this.getMostCommonlyUsedSettings(), target); + } + return this._defaultUserSettingsContentModel; } private getEditableSettingsURI(configurationTarget: ConfigurationTarget, resource?: URI): URI { diff --git a/src/vs/workbench/parts/preferences/common/keybindingsEditorModel.ts b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts similarity index 94% rename from src/vs/workbench/parts/preferences/common/keybindingsEditorModel.ts rename to src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts index 285308dded..8eaba4811b 100644 --- a/src/vs/workbench/parts/preferences/common/keybindingsEditorModel.ts +++ b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts @@ -23,6 +23,9 @@ import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingReso export const KEYBINDING_ENTRY_TEMPLATE_ID = 'keybinding.entry.template'; export const KEYBINDING_HEADER_TEMPLATE_ID = 'keybinding.header.template'; +const SOURCE_DEFAULT = localize('default', "Default"); +const SOURCE_USER = localize('user', "User"); + export interface KeybindingMatch { ctrlKey?: boolean; shiftKey?: boolean; @@ -89,9 +92,35 @@ export class KeybindingsEditorModel extends EditorModel { } public fetch(searchValue: string, sortByPrecedence: boolean = false): IKeybindingItemEntry[] { + let keybindingItems = sortByPrecedence ? this._keybindingItemsSortedByPrecedence : this._keybindingItems; + + if (/@source:\s*(user|default)/i.test(searchValue)) { + keybindingItems = this.filterBySource(keybindingItems, searchValue); + searchValue = searchValue.replace(/@source:\s*(user|default)/i, ''); + } + searchValue = searchValue.trim(); + if (!searchValue) { + return keybindingItems.map(keybindingItem => ({ id: KeybindingsEditorModel.getId(keybindingItem), keybindingItem, templateId: KEYBINDING_ENTRY_TEMPLATE_ID })); + } + + return this.filterByText(keybindingItems, searchValue); + } + + private filterBySource(keybindingItems: IKeybindingItem[], searchValue: string): IKeybindingItem[] { + if (/@source:\s*default/i.test(searchValue)) { + return keybindingItems.filter(k => k.source === SOURCE_DEFAULT); + } + if (/@source:\s*user/i.test(searchValue)) { + return keybindingItems.filter(k => k.source === SOURCE_USER); + } + return keybindingItems; + } + + private filterByText(keybindingItems: IKeybindingItem[], searchValue: string): IKeybindingItemEntry[] { const quoteAtFirstChar = searchValue.charAt(0) === '"'; const quoteAtLastChar = searchValue.charAt(searchValue.length - 1) === '"'; + const completeMatch = quoteAtFirstChar && quoteAtLastChar; if (quoteAtFirstChar) { searchValue = searchValue.substring(1); } @@ -99,13 +128,6 @@ export class KeybindingsEditorModel extends EditorModel { searchValue = searchValue.substring(0, searchValue.length - 1); } searchValue = searchValue.trim(); - return this.fetchKeybindingItems(sortByPrecedence ? this._keybindingItemsSortedByPrecedence : this._keybindingItems, searchValue, quoteAtFirstChar && quoteAtLastChar); - } - - private fetchKeybindingItems(keybindingItems: IKeybindingItem[], searchValue: string, completeMatch: boolean): IKeybindingItemEntry[] { - if (!searchValue) { - return keybindingItems.map(keybindingItem => ({ id: KeybindingsEditorModel.getId(keybindingItem), keybindingItem, templateId: KEYBINDING_ENTRY_TEMPLATE_ID })); - } const result: IKeybindingItemEntry[] = []; const words = searchValue.split(' '); @@ -137,7 +159,7 @@ export class KeybindingsEditorModel extends EditorModel { private splitKeybindingWords(wordsSeparatedBySpaces: string[]): string[] { const result = []; for (const word of wordsSeparatedBySpaces) { - result.push(...word.split('+')); + result.push(...word.split('+').filter(w => !!w)); } return result; } @@ -204,7 +226,7 @@ export class KeybindingsEditorModel extends EditorModel { commandLabel: KeybindingsEditorModel.getCommandLabel(menuCommand, editorActionLabel), commandDefaultLabel: KeybindingsEditorModel.getCommandDefaultLabel(menuCommand, workbenchActionsRegistry), when: keybindingItem.when ? keybindingItem.when.serialize() : '', - source: keybindingItem.isDefault ? localize('default', "Default") : localize('user', "User") + source: keybindingItem.isDefault ? SOURCE_DEFAULT : SOURCE_USER }; } diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts new file mode 100644 index 0000000000..29d4d214f7 --- /dev/null +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import URI from 'vs/base/common/uri'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IEditor, Position, IEditorOptions } from 'vs/platform/editor/common/editor'; +import { ITextModel } from 'vs/editor/common/model'; +import { IRange } from 'vs/editor/common/core/range'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { join } from 'vs/base/common/paths'; +import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { Event } from 'vs/base/common/event'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { localize } from 'vs/nls'; + +export interface ISettingsGroup { + id: string; + range: IRange; + title: string; + titleRange: IRange; + sections: ISettingsSection[]; +} + +export interface ISettingsSection { + titleRange?: IRange; + title?: string; + settings: ISetting[]; +} + +export interface ISetting { + range: IRange; + key: string; + keyRange: IRange; + value: any; + valueRange: IRange; + description: string[]; + descriptionRanges: IRange[]; + overrides?: ISetting[]; + overrideOf?: ISetting; +} + +export interface IExtensionSetting extends ISetting { + extensionName: string; + extensionPublisher: string; +} + +export interface ISearchResult { + filterMatches: ISettingMatch[]; + metadata?: IFilterMetadata; +} + +export interface ISearchResultGroup { + id: string; + label: string; + result: ISearchResult; + order: number; +} + +export interface IFilterResult { + query?: string; + filteredGroups: ISettingsGroup[]; + allGroups: ISettingsGroup[]; + matches: IRange[]; + metadata?: IStringDictionary; +} + +export interface ISettingMatch { + setting: ISetting; + matches: IRange[]; + score: number; +} + +export interface IScoredResults { + [key: string]: IRemoteSetting; +} + +export interface IRemoteSetting { + score: number; + key: string; + id: string; + defaultValue: string; + description: string; + packageId: string; + extensionName?: string; + extensionPublisher?: string; +} + +export interface IFilterMetadata { + requestUrl: string; + requestBody: string; + timestamp: number; + duration: number; + scoredResults: IScoredResults; + extensions?: ILocalExtension[]; + + /** The number of requests made, since requests are split by number of filters */ + requestCount?: number; + + /** The name of the server that actually served the request */ + context: string; +} + +export interface IPreferencesEditorModel { + uri: URI; + getPreference(key: string): T; + dispose(): void; +} + +export type IGroupFilter = (group: ISettingsGroup) => boolean; +export type ISettingMatcher = (setting: ISetting, group: ISettingsGroup) => { matches: IRange[], score: number }; + +export interface ISettingsEditorModel extends IPreferencesEditorModel { + readonly onDidChangeGroups: Event; + settingsGroups: ISettingsGroup[]; + filterSettings(filter: string, groupFilter: IGroupFilter, settingMatcher: ISettingMatcher): ISettingMatch[]; + findValueMatches(filter: string, setting: ISetting): IRange[]; + updateResultGroup(id: string, resultGroup: ISearchResultGroup): IFilterResult; +} + +export interface IKeybindingsEditorModel extends IPreferencesEditorModel { +} + +export const IPreferencesService = createDecorator('preferencesService'); + +export interface IPreferencesService { + _serviceBrand: any; + + userSettingsResource: URI; + workspaceSettingsResource: URI; + getFolderSettingsResource(resource: URI): URI; + + resolveModel(uri: URI): TPromise; + createPreferencesEditorModel(uri: URI): TPromise>; + + openRawDefaultSettings(): TPromise; + openSettings(): TPromise; + openGlobalSettings(options?: IEditorOptions, position?: Position): TPromise; + openWorkspaceSettings(options?: IEditorOptions, position?: Position): TPromise; + openFolderSettings(folder: URI, options?: IEditorOptions, position?: Position): TPromise; + switchSettings(target: ConfigurationTarget, resource: URI): TPromise; + openGlobalKeybindingSettings(textual: boolean): TPromise; + + configureSettingsForLanguage(language: string): void; +} + +export function getSettingsTargetName(target: ConfigurationTarget, resource: URI, workspaceContextService: IWorkspaceContextService): string { + switch (target) { + case ConfigurationTarget.USER: + return localize('userSettingsTarget', "User Settings"); + case ConfigurationTarget.WORKSPACE: + return localize('workspaceSettingsTarget', "Workspace Settings"); + case ConfigurationTarget.WORKSPACE_FOLDER: + const folder = workspaceContextService.getWorkspaceFolder(resource); + return folder ? folder.name : ''; + } + return ''; +} + +export const FOLDER_SETTINGS_PATH = join('.vscode', 'settings.json'); +export const DEFAULT_SETTINGS_EDITOR_SETTING = 'workbench.settings.openDefaultSettings'; diff --git a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts new file mode 100644 index 0000000000..d429d1cba6 --- /dev/null +++ b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { SideBySideEditorInput, EditorInput } from 'vs/workbench/common/editor'; +import { Verbosity } from 'vs/platform/editor/common/editor'; +import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; +import URI from 'vs/base/common/uri'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IHashService } from 'vs/workbench/services/hash/common/hashService'; +import { KeybindingsEditorModel } from 'vs/workbench/services/preferences/common/keybindingsEditorModel'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { OS } from 'vs/base/common/platform'; +import { TPromise } from 'vs/base/common/winjs.base'; + +export class PreferencesEditorInput extends SideBySideEditorInput { + public static readonly ID: string = 'workbench.editorinputs.preferencesEditorInput'; + + getTypeId(): string { + return PreferencesEditorInput.ID; + } + + public supportsSplitEditor(): boolean { + return true; + } + + public getTitle(verbosity: Verbosity): string { + return this.master.getTitle(verbosity); + } +} + +export class DefaultPreferencesEditorInput extends ResourceEditorInput { + public static readonly ID = 'workbench.editorinputs.defaultpreferences'; + constructor(defaultSettingsResource: URI, + @ITextModelService textModelResolverService: ITextModelService, + @IHashService hashService: IHashService + ) { + super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService, hashService); + } + + getTypeId(): string { + return DefaultPreferencesEditorInput.ID; + } + + matches(other: any): boolean { + if (other instanceof DefaultPreferencesEditorInput) { + return true; + } + if (!super.matches(other)) { + return false; + } + return true; + } +} + +export class KeybindingsEditorInput extends EditorInput { + + public static readonly ID: string = 'workbench.input.keybindings'; + public readonly keybindingsModel: KeybindingsEditorModel; + + constructor(@IInstantiationService instantiationService: IInstantiationService) { + super(); + this.keybindingsModel = instantiationService.createInstance(KeybindingsEditorModel, OS); + } + + getTypeId(): string { + return KeybindingsEditorInput.ID; + } + + getName(): string { + return nls.localize('keybindingsInputName', "Keyboard Shortcuts"); + } + + resolve(refresh?: boolean): TPromise { + return TPromise.as(this.keybindingsModel); + } + + matches(otherInput: any): boolean { + return otherInput instanceof KeybindingsEditorInput; + } +} diff --git a/src/vs/workbench/parts/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts similarity index 97% rename from src/vs/workbench/parts/preferences/common/preferencesModels.ts rename to src/vs/workbench/services/preferences/common/preferencesModels.ts index c3dd502d39..fef30231fa 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -9,13 +9,13 @@ import * as map from 'vs/base/common/map'; import { tail, flatten } from 'vs/base/common/arrays'; import URI from 'vs/base/common/uri'; import { IReference, Disposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { visit, JSONVisitor } from 'vs/base/common/json'; import { ITextModel, IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; import { EditorModel } from 'vs/workbench/common/editor'; import { IConfigurationNode, IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN, IConfigurationPropertySchema, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, IGroupFilter, ISettingMatcher, ISettingMatch, ISearchResultGroup, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences'; +import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, IGroupFilter, ISettingMatcher, ISettingMatch, ISearchResultGroup, IFilterMetadata } from 'vs/workbench/services/preferences/common/preferences'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { IRange, Range } from 'vs/editor/common/core/range'; @@ -119,7 +119,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti private _settingsGroups: ISettingsGroup[]; protected settingsModel: ITextModel; - private _onDidChangeGroups: Emitter = this._register(new Emitter()); + private readonly _onDidChangeGroups: Emitter = this._register(new Emitter()); readonly onDidChangeGroups: Event = this._onDidChangeGroups.event; constructor(reference: IReference, private _configurationTarget: ConfigurationTarget) { @@ -403,7 +403,7 @@ export class DefaultSettings extends Disposable { constructor( private _mostCommonlyUsedSettingsKeys: string[], - readonly configurationScope: ConfigurationScope, + readonly target: ConfigurationTarget, ) { super(); } @@ -555,10 +555,13 @@ export class DefaultSettings extends Disposable { } private matchesScope(property: IConfigurationNode): boolean { - if (this.configurationScope === ConfigurationScope.WINDOW) { - return true; + if (this.target === ConfigurationTarget.WORKSPACE_FOLDER) { + return property.scope === ConfigurationScope.RESOURCE; } - return property.scope === this.configurationScope; + if (this.target === ConfigurationTarget.WORKSPACE) { + return property.scope === ConfigurationScope.WINDOW || property.scope === ConfigurationScope.RESOURCE; + } + return true; } private compareConfigurationNodes(c1: IConfigurationNode, c2: IConfigurationNode): number { @@ -597,13 +600,12 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements private _model: ITextModel; - private _onDidChangeGroups: Emitter = this._register(new Emitter()); + private readonly _onDidChangeGroups: Emitter = this._register(new Emitter()); readonly onDidChangeGroups: Event = this._onDidChangeGroups.event; constructor( private _uri: URI, reference: IReference, - readonly configurationScope: ConfigurationScope, private readonly defaultSettings: DefaultSettings ) { super(); @@ -617,6 +619,10 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements return this._uri; } + public get target(): ConfigurationTarget { + return this.defaultSettings.target; + } + public get settingsGroups(): ISettingsGroup[] { return this.defaultSettings.settingsGroups; } diff --git a/src/vs/workbench/parts/preferences/test/common/keybindingsEditorModel.test.ts b/src/vs/workbench/services/preferences/test/common/keybindingsEditorModel.test.ts similarity index 97% rename from src/vs/workbench/parts/preferences/test/common/keybindingsEditorModel.test.ts rename to src/vs/workbench/services/preferences/test/common/keybindingsEditorModel.test.ts index 225ee7e2c8..8691f093e5 100644 --- a/src/vs/workbench/parts/preferences/test/common/keybindingsEditorModel.test.ts +++ b/src/vs/workbench/services/preferences/test/common/keybindingsEditorModel.test.ts @@ -16,7 +16,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KeybindingsEditorModel, IKeybindingItemEntry } from 'vs/workbench/parts/preferences/common/keybindingsEditorModel'; +import { KeybindingsEditorModel, IKeybindingItemEntry } from 'vs/workbench/services/preferences/common/keybindingsEditorModel'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding'; @@ -258,6 +258,28 @@ suite('Keybindings Editor Model test', () => { }); }); + test('filter by default source with "@source: " prefix', () => { + const command = 'a' + uuid.generateUuid(); + const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape }, when: 'context1 && context2', isDefault: true }); + prepareKeybindingService(expected); + + return testObject.resolve({}).then(() => { + const actual = testObject.fetch('@source: default').filter(element => element.keybindingItem.command === command)[0]; + assert.ok(actual); + }); + }); + + test('filter by user source with "@source: " prefix', () => { + const command = 'a' + uuid.generateUuid(); + const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape }, when: 'context1 && context2', isDefault: false }); + prepareKeybindingService(expected); + + return testObject.resolve({}).then(() => { + const actual = testObject.fetch('@source: user').filter(element => element.keybindingItem.command === command)[0]; + assert.ok(actual); + }); + }); + test('filter by when context', () => { const command = 'a' + uuid.generateUuid(); const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape }, when: 'whenContext1 && whenContext2', isDefault: false }); diff --git a/src/vs/workbench/services/progress/browser/media/progress.svg b/src/vs/workbench/services/progress/browser/media/progress.svg deleted file mode 100644 index c3633c0dda..0000000000 --- a/src/vs/workbench/services/progress/browser/media/progress.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/vs/workbench/services/progress/browser/media/progressService2.css b/src/vs/workbench/services/progress/browser/media/progressService2.css index ded88981a9..4ff42ac4ba 100644 --- a/src/vs/workbench/services/progress/browser/media/progressService2.css +++ b/src/vs/workbench/services/progress/browser/media/progressService2.css @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ .monaco-workbench > .part.statusbar > .statusbar-item.progress { - background-image: url(progress.svg); - background-repeat: no-repeat; - background-position: left; - padding-left: 14px; - display: inline; + padding-left: 5px; +} + +.monaco-workbench > .part.statusbar > .statusbar-item.progress .spinner-container { + padding-right: 5px; } .monaco-workbench .progress-badge > .badge-content { diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index f5fb9aed5b..5ef7d7c9f3 100644 --- a/src/vs/workbench/services/progress/browser/progressService.ts +++ b/src/vs/workbench/services/progress/browser/progressService.ts @@ -3,9 +3,9 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import lifecycle = require('vs/base/common/lifecycle'); +import * as lifecycle from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; -import types = require('vs/base/common/types'); +import * as types from 'vs/base/common/types'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -102,17 +102,17 @@ export class WorkbenchProgressService extends ScopedService implements IProgress // Replay Infinite Progress else if (this.progressState.infinite) { - this.progressbar.infinite().getContainer().show(); + this.progressbar.infinite().show(); } // Replay Finite Progress (Total & Worked) else { if (this.progressState.total) { - this.progressbar.total(this.progressState.total).getContainer().show(); + this.progressbar.total(this.progressState.total).show(); } if (this.progressState.worked) { - this.progressbar.worked(this.progressState.worked).getContainer().show(); + this.progressbar.worked(this.progressState.worked).show(); } } } @@ -152,20 +152,12 @@ export class WorkbenchProgressService extends ScopedService implements IProgress // Infinite: Start Progressbar and Show after Delay if (!types.isUndefinedOrNull(infinite)) { - if (types.isUndefinedOrNull(delay)) { - this.progressbar.infinite().getContainer().show(); - } else { - this.progressbar.infinite().getContainer().showDelayed(delay); - } + this.progressbar.infinite().show(delay); } // Finite: Start Progressbar and Show after Delay else if (!types.isUndefinedOrNull(total)) { - if (types.isUndefinedOrNull(delay)) { - this.progressbar.total(total).getContainer().show(); - } else { - this.progressbar.total(total).getContainer().showDelayed(delay); - } + this.progressbar.total(total).show(delay); } } @@ -200,7 +192,7 @@ export class WorkbenchProgressService extends ScopedService implements IProgress this.progressState.infinite = true; this.progressState.worked = void 0; this.progressState.total = void 0; - this.progressbar.infinite().getContainer().show(); + this.progressbar.infinite().show(); } }, @@ -209,7 +201,7 @@ export class WorkbenchProgressService extends ScopedService implements IProgress this.progressState.done = true; if (this.isActive) { - this.progressbar.stop().getContainer().hide(); + this.progressbar.stop().hide(); } } }; @@ -244,7 +236,7 @@ export class WorkbenchProgressService extends ScopedService implements IProgress this.clearProgressState(); if (this.isActive) { - this.progressbar.stop().getContainer().hide(); + this.progressbar.stop().hide(); } }; @@ -257,11 +249,7 @@ export class WorkbenchProgressService extends ScopedService implements IProgress // Show Progress when active if (this.isActive) { - if (types.isUndefinedOrNull(delay)) { - this.progressbar.infinite().getContainer().show(); - } else { - this.progressbar.infinite().getContainer().showDelayed(delay); - } + this.progressbar.infinite().show(delay); } } diff --git a/src/vs/workbench/services/progress/browser/progressService2.ts b/src/vs/workbench/services/progress/browser/progressService2.ts index a9708f8aad..f1035134b0 100644 --- a/src/vs/workbench/services/progress/browser/progressService2.ts +++ b/src/vs/workbench/services/progress/browser/progressService2.ts @@ -16,6 +16,9 @@ import { StatusbarAlignment, IStatusbarRegistry, StatusbarItemDescriptor, Extens import { TPromise } from 'vs/base/common/winjs.base'; import { always } from 'vs/base/common/async'; import { ProgressBadge, IActivityService } from 'vs/workbench/services/activity/common/activity'; +import { INotificationService, Severity, INotificationHandle, INotificationActions } from 'vs/platform/notification/common/notification'; +import { Action } from 'vs/base/common/actions'; +import { once } from 'vs/base/common/event'; class WindowProgressItem implements IStatusbarItem { @@ -30,9 +33,25 @@ class WindowProgressItem implements IStatusbarItem { render(element: HTMLElement): IDisposable { this._element = element; - this._label = new OcticonLabel(this._element); this._element.classList.add('progress'); + + const container = document.createElement('span'); + this._element.appendChild(container); + + const spinnerContainer = document.createElement('span'); + spinnerContainer.classList.add('spinner-container'); + container.appendChild(spinnerContainer); + + const spinner = new OcticonLabel(spinnerContainer); + spinner.text = '$(sync~spin)'; + + const labelContainer = document.createElement('span'); + container.appendChild(labelContainer); + + this._label = new OcticonLabel(labelContainer); + this.hide(); + return null; } @@ -62,15 +81,18 @@ export class ProgressService2 implements IProgressService2 { constructor( @IActivityService private readonly _activityBar: IActivityService, - @IViewletService private readonly _viewletService: IViewletService + @IViewletService private readonly _viewletService: IViewletService, + @INotificationService private readonly _notificationService: INotificationService ) { // } - withProgress

    , R=any>(options: IProgressOptions, task: (progress: IProgress) => P): P { + withProgress

    , R=any>(options: IProgressOptions, task: (progress: IProgress) => P, onDidCancel?: () => void): P { const { location } = options; switch (location) { + case ProgressLocation.Notification: + return this._withNotificationProgress(options, task, onDidCancel); case ProgressLocation.Window: return this._withWindowProgress(options, task); case ProgressLocation.Explorer: @@ -85,7 +107,7 @@ export class ProgressService2 implements IProgressService2 { } } - private _withWindowProgress

    , R=any>(options: IProgressOptions, callback: (progress: IProgress<{ message?: string, percentage?: number }>) => P): P { + private _withWindowProgress

    , R=any>(options: IProgressOptions, callback: (progress: IProgress<{ message?: string }>) => P): P { const task: [IProgressOptions, Progress] = [options, new Progress(() => this._updateWindowProgress())]; @@ -134,8 +156,8 @@ export class ProgressService2 implements IProgressService2 { if (options.title && options.title !== title) { title = localize('progress.subtitle', "{0} - {1}", options.title, title); } - if (options.tooltip) { - title = localize('progress.title', "{0}: {1}", options.tooltip, title); + if (options.source) { + title = localize('progress.title', "{0}: {1}", options.source, title); } WindowProgressItem.Instance.text = text; @@ -144,7 +166,95 @@ export class ProgressService2 implements IProgressService2 { } } - private _withViewletProgress

    , R=any>(viewletId: string, task: (progress: IProgress<{ message?: string, percentage?: number }>) => P): P { + private _withNotificationProgress

    , R=any>(options: IProgressOptions, callback: (progress: IProgress<{ message?: string, increment?: number }>) => P, onDidCancel?: () => void): P { + const toDispose: IDisposable[] = []; + + const createNotification = (message: string, increment?: number): INotificationHandle => { + if (!message) { + return undefined; // we need a message at least + } + + const actions: INotificationActions = { primary: [] }; + if (options.cancellable) { + const cancelAction = new class extends Action { + constructor() { + super('progress.cancel', localize('cancel', "Cancel"), null, true); + } + + run(): TPromise { + if (typeof onDidCancel === 'function') { + onDidCancel(); + } + + return TPromise.as(undefined); + } + }; + toDispose.push(cancelAction); + + actions.primary.push(cancelAction); + } + + const handle = this._notificationService.notify({ + severity: Severity.Info, + message: options.title, + source: options.source, + actions + }); + + updateProgress(handle, increment); + + once(handle.onDidClose)(() => { + dispose(toDispose); + }); + + return handle; + }; + + const updateProgress = (notification: INotificationHandle, increment?: number): void => { + if (typeof increment === 'number' && increment >= 0) { + notification.progress.total(100); // always percentage based + notification.progress.worked(increment); + } else { + notification.progress.infinite(); + } + }; + + let handle: INotificationHandle; + const updateNotification = (message?: string, increment?: number): void => { + if (!handle) { + handle = createNotification(message, increment); + } else { + if (typeof message === 'string') { + handle.updateMessage(message); + } + + if (typeof increment === 'number') { + updateProgress(handle, increment); + } + } + }; + + // Show initially + updateNotification(options.title); + + // Update based on progress + const p = callback({ + report: progress => { + updateNotification(progress.message, progress.increment); + } + }); + + // Show progress for at least 800ms and then hide once done or canceled + always(TPromise.join([TPromise.timeout(800), p]), () => { + if (handle) { + handle.close(); + } + }); + + return p; + } + + private _withViewletProgress

    , R=any>(viewletId: string, task: (progress: IProgress<{ message?: string }>) => P): P { const promise = task(emptyProgress); diff --git a/src/vs/workbench/services/progress/test/progressService.test.ts b/src/vs/workbench/services/progress/test/progressService.test.ts index b718d16561..5ea6cb5f2e 100644 --- a/src/vs/workbench/services/progress/test/progressService.test.ts +++ b/src/vs/workbench/services/progress/test/progressService.test.ts @@ -22,10 +22,12 @@ let activeViewlet: Viewlet = {} as any; class TestViewletService implements IViewletService { public _serviceBrand: any; + onDidViewletRegisterEmitter = new Emitter(); onDidViewletOpenEmitter = new Emitter(); onDidViewletCloseEmitter = new Emitter(); onDidViewletEnableEmitter = new Emitter<{ id: string, enabled: boolean }>(); + onDidViewletRegister = this.onDidViewletRegisterEmitter.event; onDidViewletOpen = this.onDidViewletOpenEmitter.event; onDidViewletClose = this.onDidViewletCloseEmitter.event; onDidViewletEnablementChange = this.onDidViewletEnableEmitter.event; @@ -212,11 +214,12 @@ class TestProgressBar { return this.done(); } - public getContainer() { - return { - show: function () { }, - hide: function () { } - }; + public show(): void { + + } + + public hide(): void { + } } @@ -280,12 +283,12 @@ suite('Progress Service', () => { // Acive: Show While let p = TPromise.as(null); - service.showWhile(p).then(() => { + return service.showWhile(p).then(() => { assert.strictEqual(true, testProgressBar.fDone); viewletService.onDidViewletCloseEmitter.fire(testViewlet); p = TPromise.as(null); - service.showWhile(p).then(() => { + return service.showWhile(p).then(() => { assert.strictEqual(true, testProgressBar.fDone); viewletService.onDidViewletOpenEmitter.fire(testViewlet); diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index 38115eb1af..e7488f43eb 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Command } from 'vs/editor/common/modes'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index cf42d6960b..cdcc3841e0 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -6,7 +6,7 @@ 'use strict'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ISCMService, ISCMProvider, ISCMInput, ISCMRepository, IInputValidator } from './scm'; import { ILogService } from 'vs/platform/log/common/log'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -92,7 +92,7 @@ export class SCMService implements ISCMService { private _onDidRemoveProvider = new Emitter(); get onDidRemoveRepository(): Event { return this._onDidRemoveProvider.event; } - constructor( @ILogService private logService: ILogService) { } + constructor(@ILogService private logService: ILogService) { } registerSCMProvider(provider: ISCMProvider): ISCMRepository { this.logService.trace('SCMService#registerSCMProvider'); diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index e0972f3d29..7f55202e5c 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -8,22 +8,22 @@ import * as childProcess from 'child_process'; import { StringDecoder, NodeStringDecoder } from 'string_decoder'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import fs = require('fs'); -import path = require('path'); +import * as fs from 'fs'; +import * as path from 'path'; import { isEqualOrParent } from 'vs/base/common/paths'; import { Readable } from 'stream'; import { TPromise } from 'vs/base/common/winjs.base'; -import objects = require('vs/base/common/objects'); -import arrays = require('vs/base/common/arrays'); -import platform = require('vs/base/common/platform'); -import strings = require('vs/base/common/strings'); -import types = require('vs/base/common/types'); -import glob = require('vs/base/common/glob'); +import * as objects from 'vs/base/common/objects'; +import * as arrays from 'vs/base/common/arrays'; +import * as platform from 'vs/base/common/platform'; +import * as strings from 'vs/base/common/strings'; +import * as types from 'vs/base/common/types'; +import * as glob from 'vs/base/common/glob'; import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/search'; -import extfs = require('vs/base/node/extfs'); -import flow = require('vs/base/node/flow'); +import * as extfs from 'vs/base/node/extfs'; +import * as flow from 'vs/base/node/flow'; import { IRawFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine, IFolderSearch } from './search'; import { spawnRipgrepCmd } from './ripgrepFileSearch'; import { rgErrorMsgForDisplay } from './ripgrepTextSearch'; diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index 7df9fb2780..bb92e89efe 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -5,15 +5,15 @@ 'use strict'; -import fs = require('fs'); -import { isAbsolute, sep } from 'path'; +import * as fs from 'fs'; +import { isAbsolute, sep, join } from 'path'; -import gracefulFs = require('graceful-fs'); +import * as gracefulFs from 'graceful-fs'; gracefulFs.gracefulify(fs); -import arrays = require('vs/base/common/arrays'); -import objects = require('vs/base/common/objects'); -import strings = require('vs/base/common/strings'); +import * as arrays from 'vs/base/common/arrays'; +import * as objects from 'vs/base/common/objects'; +import * as strings from 'vs/base/common/strings'; import { PPromise, TPromise } from 'vs/base/common/winjs.base'; import { FileWalker, Engine as FileSearchEngine } from 'vs/workbench/services/search/node/fileSearch'; import { MAX_FILE_SIZE } from 'vs/platform/files/node/files'; @@ -22,7 +22,6 @@ import { Engine as TextSearchEngine } from 'vs/workbench/services/search/node/te import { TextSearchWorkerProvider } from 'vs/workbench/services/search/node/textSearchWorkerProvider'; import { IRawSearchService, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchProgressItem, ISerializedSearchComplete, ISearchEngine, IFileSearchProgressItem, ITelemetryEvent } from './search'; import { ICachedSearchStats, IProgress } from 'vs/platform/search/common/search'; -import { fuzzyContains } from 'vs/base/common/strings'; import { compareItemsByScore, IItemAccessor, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; export class SearchService implements IRawSearchService { @@ -133,7 +132,7 @@ export class SearchService implements IRawSearchService { } private rawMatchToSearchItem(match: IRawFileMatch): ISerializedFileMatch { - return { path: match.base ? [match.base, match.relativePath].join(sep) : match.relativePath }; + return { path: match.base ? join(match.base, match.relativePath) : match.relativePath }; } private doSortedSearch(engine: ISearchEngine, config: IRawSearch): PPromise<[ISerializedSearchComplete, IRawFileMatch[]], IProgress> { @@ -144,6 +143,7 @@ export class SearchService implements IRawSearchService { .then(result => { c([result, results]); if (this.telemetryPipe) { + // __GDPR__TODO__ classify event this.telemetryPipe({ eventName: 'fileSearch', data: result.stats @@ -310,7 +310,7 @@ export class SearchService implements IRawSearchService { let entry = cachedEntries[i]; // Check if this entry is a match for the search value - if (!fuzzyContains(entry.relativePath, normalizedSearchValueLowercase)) { + if (!strings.fuzzyContains(entry.relativePath, normalizedSearchValueLowercase)) { continue; } diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 9bfdec4da9..2cf7d7429d 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -32,14 +32,29 @@ function getRgArgs(config: IRawSearch, folderQuery: IFolderSearch, includePatter // includePattern can't have siblingClauses foldersToIncludeGlobs([folderQuery], includePattern, false).forEach(globArg => { - args.push('-g', anchor(isMac ? normalizeNFD(globArg) : globArg)); + const inclusion = anchor(globArg); + args.push('-g', inclusion); + if (isMac) { + const normalized = normalizeNFD(inclusion); + if (normalized !== inclusion) { + args.push('-g', normalized); + } + } }); let siblingClauses: glob.IExpression; const rgGlobs = foldersToRgExcludeGlobs([folderQuery], excludePattern, undefined, false); - rgGlobs.globArgs - .forEach(rgGlob => args.push('-g', `!${anchor(isMac ? normalizeNFD(rgGlob) : rgGlob)}`)); + rgGlobs.globArgs.forEach(globArg => { + const exclusion = `!${anchor(globArg)}`; + args.push('-g', exclusion); + if (isMac) { + const normalized = normalizeNFD(exclusion); + if (normalized !== exclusion) { + args.push('-g', normalized); + } + } + }); siblingClauses = rgGlobs.siblingClauses; if (folderQuery.disregardIgnoreFiles !== false) { diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts index 826c49691d..12fc36c42d 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts @@ -11,8 +11,8 @@ import { StringDecoder, NodeStringDecoder } from 'string_decoder'; import * as cp from 'child_process'; import { rgPath } from 'vscode-ripgrep'; -import objects = require('vs/base/common/objects'); -import platform = require('vs/base/common/platform'); +import * as objects from 'vs/base/common/objects'; +import * as platform from 'vs/base/common/platform'; import * as strings from 'vs/base/common/strings'; import * as paths from 'vs/base/common/paths'; import * as extfs from 'vs/base/node/extfs'; @@ -29,7 +29,7 @@ const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.u export class RipgrepEngine { private isDone = false; private rgProc: cp.ChildProcess; - private killRgProcFn: Function; + private killRgProcFn: (code?: number) => void; private postProcessExclusions: glob.ParsedExpression; private ripgrepParser: RipgrepParser; @@ -169,11 +169,11 @@ export function rgErrorMsgForDisplay(msg: string): string | undefined { } export class RipgrepParser extends EventEmitter { - private static readonly RESULT_REGEX = /^\u001b\[m(\d+)\u001b\[m:(.*)(\r?)/; - private static readonly FILE_REGEX = /^\u001b\[m(.+)\u001b\[m$/; + private static readonly RESULT_REGEX = /^\u001b\[0m(\d+)\u001b\[0m:(.*)(\r?)/; + private static readonly FILE_REGEX = /^\u001b\[0m(.+)\u001b\[0m$/; - public static readonly MATCH_START_MARKER = '\u001b[m\u001b[31m'; - public static readonly MATCH_END_MARKER = '\u001b[m'; + public static readonly MATCH_START_MARKER = '\u001b[0m\u001b[31m'; + public static readonly MATCH_END_MARKER = '\u001b[0m'; private fileMatch: FileMatch; private remainder: string; diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index 385c23f7fb..c25b7663d4 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -6,8 +6,8 @@ import { PPromise, TPromise } from 'vs/base/common/winjs.base'; import uri from 'vs/base/common/uri'; -import objects = require('vs/base/common/objects'); -import strings = require('vs/base/common/strings'); +import * as objects from 'vs/base/common/objects'; +import * as strings from 'vs/base/common/strings'; import { getNextTickChannel } from 'vs/base/parts/ipc/common/ipc'; import { Client, IIPCOptions } from 'vs/base/parts/ipc/node/ipc.cp'; import { IProgress, LineMatch, FileMatch, ISearchComplete, ISearchProgressItem, QueryType, IFileMatch, ISearchQuery, IFolderQuery, ISearchConfiguration, ISearchService, pathIncludedInQuery, ISearchResultProvider } from 'vs/platform/search/common/search'; diff --git a/src/vs/workbench/services/search/node/worker/searchWorker.ts b/src/vs/workbench/services/search/node/worker/searchWorker.ts index f45a3a9e2d..e0ad9b99d7 100644 --- a/src/vs/workbench/services/search/node/worker/searchWorker.ts +++ b/src/vs/workbench/services/search/node/worker/searchWorker.ts @@ -6,16 +6,14 @@ 'use strict'; import * as fs from 'fs'; -import gracefulFs = require('graceful-fs'); +import * as gracefulFs from 'graceful-fs'; gracefulFs.gracefulify(fs); import { onUnexpectedError } from 'vs/base/common/errors'; import * as strings from 'vs/base/common/strings'; import { TPromise } from 'vs/base/common/winjs.base'; import { LineMatch, FileMatch } from '../search'; -import * as baseMime from 'vs/base/common/mime'; -import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode, bomLength } from 'vs/base/node/encoding'; -import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; +import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode, bomLength, detectEncodingFromBuffer } from 'vs/base/node/encoding'; import { ISearchWorker, ISearchWorkerSearchArgs, ISearchWorkerSearchResult } from './searchWorkerIpc'; @@ -208,13 +206,13 @@ export class SearchWorkerEngine { // Detect encoding and mime when this is the beginning of the file if (isFirstRead) { - const mimeAndEncoding = detectMimeAndEncodingFromBuffer({ buffer, bytesRead }, false); - if (mimeAndEncoding.mimes[mimeAndEncoding.mimes.length - 1] !== baseMime.MIME_TEXT) { + const detected = detectEncodingFromBuffer({ buffer, bytesRead }, false); + if (detected.seemsBinary) { return clb(null); // skip files that seem binary } // Check for BOM offset - switch (mimeAndEncoding.encoding) { + switch (detected.encoding) { case UTF8: pos = i = bomLength(UTF8); options.encoding = UTF8; diff --git a/src/vs/workbench/services/search/test/node/ripgrepTextSearch.test.ts b/src/vs/workbench/services/search/test/node/ripgrepTextSearch.test.ts index eaa2154224..23ed1d7521 100644 --- a/src/vs/workbench/services/search/test/node/ripgrepTextSearch.test.ts +++ b/src/vs/workbench/services/search/test/node/ripgrepTextSearch.test.ts @@ -5,11 +5,11 @@ 'use strict'; -import path = require('path'); -import assert = require('assert'); +import * as path from 'path'; +import * as assert from 'assert'; import * as arrays from 'vs/base/common/arrays'; -import platform = require('vs/base/common/platform'); +import * as platform from 'vs/base/common/platform'; import { RipgrepParser, getAbsoluteGlob, fixDriveC } from 'vs/workbench/services/search/node/ripgrepTextSearch'; import { ISerializedFileMatch } from 'vs/workbench/services/search/node/search'; @@ -20,11 +20,11 @@ suite('RipgrepParser', () => { const fileSectionEnd = '\n'; function getFileLine(relativePath: string): string { - return `\u001b\[m${relativePath}\u001b\[m`; + return `\u001b\[0m${relativePath}\u001b\[0m`; } function getMatchLine(lineNum: number, matchParts: string[]): string { - let matchLine = `\u001b\[m${lineNum}\u001b\[m:` + + let matchLine = `\u001b\[0m${lineNum}\u001b\[0m:` + `${matchParts.shift()}${RipgrepParser.MATCH_START_MARKER}${matchParts.shift()}${RipgrepParser.MATCH_END_MARKER}${matchParts.shift()}`; while (matchParts.length) { @@ -156,21 +156,21 @@ suite('RipgrepParser', () => { }); test('Parses chunks broken in the middle of a multibyte character', () => { - const multibyteStr = '漢'; - const multibyteBuf = Buffer.from(multibyteStr); - const text = getFileLine('foo/bar') + '\n' + getMatchLine(0, ['before', 'match', 'after']) + '\n'; + const text = getFileLine('foo/bar') + '\n' + getMatchLine(0, ['before漢', 'match', 'after']) + '\n'; + const buf = new Buffer(text); - // Split the multibyte char into two pieces and divide between the two buffers - const beforeIndex = 24; - const inputBufs = [ - Buffer.concat([Buffer.from(text.substr(0, beforeIndex)), multibyteBuf.slice(0, 2)]), - Buffer.concat([multibyteBuf.slice(2), Buffer.from(text.substr(beforeIndex))]) - ]; + // Split the buffer at every possible position - it should still be parsed correctly + for (let i = 0; i < buf.length; i++) { + const inputBufs = [ + buf.slice(0, i), + buf.slice(i) + ]; - const results = parseInput(inputBufs); - assert.equal(results.length, 1); - assert.equal(results[0].lineMatches.length, 1); - assert.deepEqual(results[0].lineMatches[0].offsetAndLengths, [[7, 5]]); + const results = parseInput(inputBufs); + assert.equal(results.length, 1); + assert.equal(results[0].lineMatches.length, 1); + assert.deepEqual(results[0].lineMatches[0].offsetAndLengths, [[7, 5]]); + } }); }); diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 5729e0f32b..f84c08e48a 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -5,8 +5,8 @@ 'use strict'; -import path = require('path'); -import assert = require('assert'); +import * as path from 'path'; +import * as assert from 'assert'; import { join, normalize } from 'vs/base/common/paths'; import * as platform from 'vs/base/common/platform'; @@ -483,6 +483,26 @@ suite('FileSearchEngine', () => { }); }); + test('Files: *.* include with unicode', function (done: () => void) { + this.timeout(testTimeout); + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + filePattern: '*.*', + includePattern: { '**/üm laut汉语/*': true } + }); + + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error) => { + assert.ok(!error); + assert.equal(count, 1); + done(); + }); + }); + test('Files: multiroot with exclude', function (done: () => void) { this.timeout(testTimeout); const folderQueries: IFolderSearch[] = [ diff --git a/src/vs/workbench/services/search/test/node/searchService.test.ts b/src/vs/workbench/services/search/test/node/searchService.test.ts index 5e3d189687..e6e084e673 100644 --- a/src/vs/workbench/services/search/test/node/searchService.test.ts +++ b/src/vs/workbench/services/search/test/node/searchService.test.ts @@ -6,8 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import { normalize } from 'path'; -import path = require('path'); +import * as path from 'path'; import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/search'; import { ISearchEngine, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchComplete, IFolderSearch } from 'vs/workbench/services/search/node/search'; @@ -15,7 +14,7 @@ import { SearchService as RawSearchService } from 'vs/workbench/services/search/ import { DiskSearch } from 'vs/workbench/services/search/node/searchService'; const TEST_FOLDER_QUERIES = [ - { folder: normalize('/some/where') } + { folder: path.normalize('/some/where') } ]; const TEST_FIXTURES = path.normalize(require.toUrl('./fixtures')); @@ -85,14 +84,14 @@ suite('SearchService', () => { }; const rawMatch: IRawFileMatch = { - base: normalize('/some'), + base: path.normalize('/some'), relativePath: 'where', basename: 'where', size: 123 }; const match: ISerializedFileMatch = { - path: normalize('/some/where') + path: path.normalize('/some/where') }; test('Individual results', function () { @@ -110,7 +109,7 @@ suite('SearchService', () => { assert.deepStrictEqual(value, match); results++; } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }); @@ -132,7 +131,7 @@ suite('SearchService', () => { }); results.push(value.length); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }); @@ -198,7 +197,7 @@ suite('SearchService', () => { this.timeout(testTimeout); const paths = ['bab', 'bbc', 'abb']; const matches: IRawFileMatch[] = paths.map(relativePath => ({ - base: normalize('/some/where'), + base: path.normalize('/some/where'), relativePath, basename: relativePath, size: 3 @@ -214,12 +213,12 @@ suite('SearchService', () => { maxResults: 2 }, 1).then(() => { assert.notStrictEqual(typeof TestSearchEngine.last.config.maxResults, 'number'); - assert.deepStrictEqual(results, [normalize('/some/where/bbc'), normalize('/some/where/bab')]); + assert.deepStrictEqual(results, [path.normalize('/some/where/bbc'), path.normalize('/some/where/bab')]); }, null, value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }); @@ -246,7 +245,7 @@ suite('SearchService', () => { }); results.push(value.length); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }); @@ -255,7 +254,7 @@ suite('SearchService', () => { this.timeout(testTimeout); const paths = ['bcb', 'bbc', 'aab']; const matches: IRawFileMatch[] = paths.map(relativePath => ({ - base: normalize('/some/where'), + base: path.normalize('/some/where'), relativePath, basename: relativePath, size: 3 @@ -271,12 +270,12 @@ suite('SearchService', () => { cacheKey: 'x' }, -1).then(complete => { assert.strictEqual(complete.stats.fromCache, false); - assert.deepStrictEqual(results, [normalize('/some/where/bcb'), normalize('/some/where/bbc'), normalize('/some/where/aab')]); + assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc'), path.normalize('/some/where/aab')]); }, null, value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }).then(() => { const results = []; @@ -287,19 +286,19 @@ suite('SearchService', () => { cacheKey: 'x' }, -1).then(complete => { assert.ok(complete.stats.fromCache); - assert.deepStrictEqual(results, [normalize('/some/where/bcb'), normalize('/some/where/bbc')]); + assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc')]); }, null, value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }).then(() => { return service.clearCache('x'); }).then(() => { matches.push({ - base: normalize('/some/where'), + base: path.normalize('/some/where'), relativePath: 'bc', basename: 'bc', size: 3 @@ -312,12 +311,12 @@ suite('SearchService', () => { cacheKey: 'x' }, -1).then(complete => { assert.strictEqual(complete.stats.fromCache, false); - assert.deepStrictEqual(results, [normalize('/some/where/bc')]); + assert.deepStrictEqual(results, [path.normalize('/some/where/bc')]); }, null, value => { if (Array.isArray(value)) { results.push(...value.map(v => v.path)); } else { - assert.fail(value); + assert.fail(JSON.stringify(value)); } }); }); diff --git a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts index 23e1ee9fcb..acef53d23e 100644 --- a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts @@ -5,8 +5,8 @@ 'use strict'; -import path = require('path'); -import assert = require('assert'); +import * as path from 'path'; +import * as assert from 'assert'; import * as glob from 'vs/base/common/glob'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -87,128 +87,127 @@ function doRipgrepSearchTest(config: IRawSearch, expectedResultCount: number | F }); } -function doSearchTest(config: IRawSearch, expectedResultCount: number, done) { +function doSearchTest(config: IRawSearch, expectedResultCount: number) { return doLegacySearchTest(config, expectedResultCount) - .then(() => doRipgrepSearchTest(config, expectedResultCount)) - .then(done, done); + .then(() => doRipgrepSearchTest(config, expectedResultCount)); } suite('Search-integration', function () { this.timeout(1000 * 60); // increase timeout for this suite - test('Text: GameOfLife', function (done: () => void) { + test('Text: GameOfLife', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'GameOfLife' }, }; - doSearchTest(config, 4, done); + return doSearchTest(config, 4); }); - test('Text: GameOfLife (RegExp)', function (done: () => void) { + test('Text: GameOfLife (RegExp)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'Game.?fL\\w?fe', isRegExp: true } }; - doSearchTest(config, 4, done); + return doSearchTest(config, 4); }); - test('Text: GameOfLife (RegExp to EOL)', function (done: () => void) { + test('Text: GameOfLife (RegExp to EOL)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'GameOfLife.*', isRegExp: true } }; - doSearchTest(config, 4, done); + return doSearchTest(config, 4); }); - test('Text: GameOfLife (Word Match, Case Sensitive)', function (done: () => void) { + test('Text: GameOfLife (Word Match, Case Sensitive)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'GameOfLife', isWordMatch: true, isCaseSensitive: true } }; - doSearchTest(config, 4, done); + return doSearchTest(config, 4); }); - test('Text: GameOfLife (Word Match, Spaces)', function (done: () => void) { + test('Text: GameOfLife (Word Match, Spaces)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: ' GameOfLife ', isWordMatch: true } }; - doSearchTest(config, 1, done); + return doSearchTest(config, 1); }); - test('Text: GameOfLife (Word Match, Punctuation and Spaces)', function (done: () => void) { + test('Text: GameOfLife (Word Match, Punctuation and Spaces)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: ', as =', isWordMatch: true } }; - doSearchTest(config, 1, done); + return doSearchTest(config, 1); }); - test('Text: Helvetica (UTF 16)', function (done: () => void) { + test('Text: Helvetica (UTF 16)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'Helvetica' } }; - doSearchTest(config, 3, done); + return doSearchTest(config, 3); }); - test('Text: e', function (done: () => void) { + test('Text: e', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' } }; - doSearchTest(config, 776, done); + return doSearchTest(config, 776); }); - test('Text: e (with excludes)', function (done: () => void) { + test('Text: e (with excludes)', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' }, excludePattern: { '**/examples': true } }; - doSearchTest(config, 394, done); + return doSearchTest(config, 394); }); - test('Text: e (with includes)', function (done: () => void) { + test('Text: e (with includes)', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' }, includePattern: { '**/examples/**': true } }; - doSearchTest(config, 382, done); + return doSearchTest(config, 382); }); - test('Text: e (with absolute path excludes)', function (done: () => void) { + test('Text: e (with absolute path excludes)', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' }, excludePattern: makeExpression(path.join(TEST_FIXTURES, '**/examples')) }; - doSearchTest(config, 394, done); + return doSearchTest(config, 394); }); - test('Text: e (with mixed absolute/relative path excludes)', function (done: () => void) { + test('Text: e (with mixed absolute/relative path excludes)', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' }, excludePattern: makeExpression(path.join(TEST_FIXTURES, '**/examples'), '*.css') }; - doSearchTest(config, 310, done); + return doSearchTest(config, 310); }); - test('Text: sibling exclude', function (done: () => void) { + test('Text: sibling exclude', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'm' }, @@ -216,10 +215,10 @@ suite('Search-integration', function () { excludePattern: { '*.css': { when: '$(basename).less' } } }; - doSearchTest(config, 1, done); + return doSearchTest(config, 1); }); - test('Text: e (with includes and exclude)', function (done: () => void) { + test('Text: e (with includes and exclude)', () => { const config: any = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'e' }, @@ -227,10 +226,10 @@ suite('Search-integration', function () { excludePattern: { '**/examples/small.js': true } }; - doSearchTest(config, 361, done); + return doSearchTest(config, 361); }); - test('Text: a (capped)', function (done: () => void) { + test('Text: a (capped)', () => { const maxResults = 520; const config = { folderQueries: ROOT_FOLDER_QUERY, @@ -241,58 +240,57 @@ suite('Search-integration', function () { // (Legacy) search can go over the maxResults because it doesn't trim the results from its worker processes to the exact max size. // But the worst-case scenario should be 2*max-1 return doLegacySearchTest(config, count => count < maxResults * 2) - .then(() => doRipgrepSearchTest(config, maxResults)) - .then(done, done); + .then(() => doRipgrepSearchTest(config, maxResults)); }); - test('Text: a (no results)', function (done: () => void) { + test('Text: a (no results)', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: 'ahsogehtdas' } }; - doSearchTest(config, 0, done); + return doSearchTest(config, 0); }); - test('Text: -size', function (done: () => void) { + test('Text: -size', () => { const config = { folderQueries: ROOT_FOLDER_QUERY, contentPattern: { pattern: '-size' } }; - doSearchTest(config, 9, done); + return doSearchTest(config, 9); }); - test('Multiroot: Conway', function (done: () => void) { + test('Multiroot: Conway', () => { const config: IRawSearch = { folderQueries: MULTIROOT_QUERIES, contentPattern: { pattern: 'conway' } }; - doSearchTest(config, 8, done); + return doSearchTest(config, 8); }); - test('Multiroot: e with partial global exclude', function (done: () => void) { + test('Multiroot: e with partial global exclude', () => { const config: IRawSearch = { folderQueries: MULTIROOT_QUERIES, contentPattern: { pattern: 'e' }, excludePattern: makeExpression('**/*.txt') }; - doSearchTest(config, 382, done); + return doSearchTest(config, 382); }); - test('Multiroot: e with global excludes', function (done: () => void) { + test('Multiroot: e with global excludes', () => { const config: IRawSearch = { folderQueries: MULTIROOT_QUERIES, contentPattern: { pattern: 'e' }, excludePattern: makeExpression('**/*.txt', '**/*.js') }; - doSearchTest(config, 0, done); + return doSearchTest(config, 0); }); - test('Multiroot: e with folder exclude', function (done: () => void) { + test('Multiroot: e with folder exclude', () => { const config: IRawSearch = { folderQueries: [ { folder: EXAMPLES_FIXTURES, excludePattern: makeExpression('**/e*.js') }, @@ -301,7 +299,7 @@ suite('Search-integration', function () { contentPattern: { pattern: 'e' } }; - doSearchTest(config, 286, done); + return doSearchTest(config, 286); }); }); diff --git a/src/vs/workbench/services/textMate/electron-browser/TMGrammars.ts b/src/vs/workbench/services/textMate/electron-browser/TMGrammars.ts index 6480485b06..ddc5f64e3a 100644 --- a/src/vs/workbench/services/textMate/electron-browser/TMGrammars.ts +++ b/src/vs/workbench/services/textMate/electron-browser/TMGrammars.ts @@ -12,11 +12,16 @@ export interface IEmbeddedLanguagesMap { [scopeName: string]: string; } +export interface TokenTypesContribution { + [scopeName: string]: string; +} + export interface ITMSyntaxExtensionPoint { language: string; scopeName: string; path: string; embeddedLanguages: IEmbeddedLanguagesMap; + tokenTypes: TokenTypesContribution; injectTo: string[]; } @@ -44,6 +49,13 @@ export const grammarsExtPoint: IExtensionPoint = Exte description: nls.localize('vscode.extension.contributes.grammars.embeddedLanguages', 'A map of scope name to language id if this grammar contains embedded languages.'), type: 'object' }, + tokenTypes: { + description: nls.localize('vscode.extension.contributes.grammars.tokenTypes', 'A map of scope name to token types.'), + type: 'object', + additionalProperties: { + enum: ['string', 'comment', 'other'] + } + }, injectTo: { description: nls.localize('vscode.extension.contributes.grammars.injectTo', 'List of language scope names to which this grammar is injected to.'), type: 'array', diff --git a/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts b/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts index a1ad7d9745..3667d41a3b 100644 --- a/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts +++ b/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts @@ -7,17 +7,17 @@ import * as nls from 'vs/nls'; import * as dom from 'vs/base/browser/dom'; import * as types from 'vs/base/common/types'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { join, normalize } from 'path'; import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; import { ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ITokenizationSupport, TokenizationRegistry, IState, LanguageId, TokenMetadata } from 'vs/editor/common/modes'; import { IModeService } from 'vs/editor/common/services/modeService'; -import { StackElement, IGrammar, Registry, IEmbeddedLanguagesMap as IEmbeddedLanguagesMap2 } from 'vscode-textmate'; +import { StackElement, IGrammar, Registry, IEmbeddedLanguagesMap as IEmbeddedLanguagesMap2, ITokenTypeMap, StandardTokenType } from 'vscode-textmate'; import { IWorkbenchThemeService, ITokenColorizationRule } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService'; -import { grammarsExtPoint, IEmbeddedLanguagesMap, ITMSyntaxExtensionPoint } from 'vs/workbench/services/textMate/electron-browser/TMGrammars'; +import { grammarsExtPoint, IEmbeddedLanguagesMap, ITMSyntaxExtensionPoint, TokenTypesContribution } from 'vs/workbench/services/textMate/electron-browser/TMGrammars'; import { TokenizationResult, TokenizationResult2 } from 'vs/editor/common/core/token'; import { nullTokenize2 } from 'vs/editor/common/modes/nullMode'; import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization'; @@ -28,15 +28,15 @@ export class TMScopeRegistry { private _scopeNameToLanguageRegistration: { [scopeName: string]: TMLanguageRegistration; }; private _encounteredLanguages: boolean[]; - private _onDidEncounterLanguage: Emitter = new Emitter(); - public onDidEncounterLanguage: Event = this._onDidEncounterLanguage.event; + private readonly _onDidEncounterLanguage: Emitter = new Emitter(); + public readonly onDidEncounterLanguage: Event = this._onDidEncounterLanguage.event; constructor() { this._scopeNameToLanguageRegistration = Object.create(null); this._encounteredLanguages = []; } - public register(scopeName: string, filePath: string, embeddedLanguages?: IEmbeddedLanguagesMap): void { + public register(scopeName: string, filePath: string, embeddedLanguages?: IEmbeddedLanguagesMap, tokenTypes?: TokenTypesContribution): void { if (this._scopeNameToLanguageRegistration[scopeName]) { const existingRegistration = this._scopeNameToLanguageRegistration[scopeName]; if (existingRegistration.grammarFilePath !== filePath) { @@ -47,7 +47,7 @@ export class TMScopeRegistry { ); } } - this._scopeNameToLanguageRegistration[scopeName] = new TMLanguageRegistration(scopeName, filePath, embeddedLanguages); + this._scopeNameToLanguageRegistration[scopeName] = new TMLanguageRegistration(scopeName, filePath, embeddedLanguages, tokenTypes); } public getLanguageRegistration(scopeName: string): TMLanguageRegistration { @@ -76,8 +76,9 @@ export class TMLanguageRegistration { readonly scopeName: string; readonly grammarFilePath: string; readonly embeddedLanguages: IEmbeddedLanguagesMap; + readonly tokenTypes: ITokenTypeMap; - constructor(scopeName: string, grammarFilePath: string, embeddedLanguages: IEmbeddedLanguagesMap) { + constructor(scopeName: string, grammarFilePath: string, embeddedLanguages: IEmbeddedLanguagesMap, tokenTypes: TokenTypesContribution | undefined) { this.scopeName = scopeName; this.grammarFilePath = grammarFilePath; @@ -97,6 +98,27 @@ export class TMLanguageRegistration { this.embeddedLanguages[scope] = language; } } + + this.tokenTypes = Object.create(null); + if (tokenTypes) { + // If tokenTypes is configured, fill in `this._tokenTypes` + const scopes = Object.keys(tokenTypes); + for (let i = 0, len = scopes.length; i < len; i++) { + const scope = scopes[i]; + const tokenType = tokenTypes[scope]; + switch (tokenType) { + case 'string': + this.tokenTypes[scope] = StandardTokenType.String; + break; + case 'other': + this.tokenTypes[scope] = StandardTokenType.Other; + break; + case 'comment': + this.tokenTypes[scope] = StandardTokenType.Comment; + break; + } + } + } } } @@ -122,7 +144,7 @@ export class TextMateService implements ITextMateService { private _currentTokenColors: ITokenColorizationRule[]; - public onDidEncounterLanguage: Event; + public readonly onDidEncounterLanguage: Event; constructor( @IModeService modeService: IModeService, @@ -262,13 +284,18 @@ export class TextMateService implements ITextMateService { return; } + if (syntax.tokenTypes && !types.isObject(syntax.tokenTypes)) { + collector.error(nls.localize('invalid.tokenTypes', "Invalid value in `contributes.{0}.tokenTypes`. Must be an object map from scope name to token type. Provided value: {1}", grammarsExtPoint.name, JSON.stringify(syntax.tokenTypes))); + return; + } + let normalizedAbsolutePath = normalize(join(extensionFolderPath, syntax.path)); if (normalizedAbsolutePath.indexOf(extensionFolderPath) !== 0) { collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", grammarsExtPoint.name, normalizedAbsolutePath, extensionFolderPath)); } - this._scopeRegistry.register(syntax.scopeName, normalizedAbsolutePath, syntax.embeddedLanguages); + this._scopeRegistry.register(syntax.scopeName, normalizedAbsolutePath, syntax.embeddedLanguages, syntax.tokenTypes); if (syntax.injectTo) { for (let injectScope of syntax.injectTo) { @@ -336,7 +363,7 @@ export class TextMateService implements ITextMateService { return this._getOrCreateGrammarRegistry().then((_res) => { const [grammarRegistry, initialState] = _res; return new TPromise((c, e, p) => { - grammarRegistry.loadGrammarWithEmbeddedLanguages(scopeName, languageId, embeddedLanguages, (err, grammar) => { + grammarRegistry.loadGrammarWithConfiguration(scopeName, languageId, { embeddedLanguages, tokenTypes: languageRegistration.tokenTypes }, (err, grammar) => { if (err) { return e(err); } diff --git a/src/vs/workbench/services/textMate/electron-browser/textMateService.ts b/src/vs/workbench/services/textMate/electron-browser/textMateService.ts index d056d7eeb1..74939aa883 100644 --- a/src/vs/workbench/services/textMate/electron-browser/textMateService.ts +++ b/src/vs/workbench/services/textMate/electron-browser/textMateService.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IGrammar } from 'vscode-textmate'; import { LanguageId } from 'vs/editor/common/modes'; diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index c300021bca..33b62aedbc 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -5,21 +5,20 @@ 'use strict'; import * as path from 'vs/base/common/paths'; -import nls = require('vs/nls'); -import Event, { Emitter } from 'vs/base/common/event'; +import * as nls from 'vs/nls'; +import { Event, Emitter } from 'vs/base/common/event'; import { TPromise, TValueCallback, ErrorCallback } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; import { guessMimeTypes } from 'vs/base/common/mime'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import URI from 'vs/base/common/uri'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import paths = require('vs/base/common/paths'); -import diagnostics = require('vs/base/common/diagnostics'); -import types = require('vs/base/common/types'); +import * as diagnostics from 'vs/base/common/diagnostics'; +import * as types from 'vs/base/common/types'; import { IMode } from 'vs/editor/common/modes'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -63,8 +62,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil private disposed: boolean; private lastSaveAttemptTime: number; private createTextEditorModelPromise: TPromise; - private _onDidContentChange: Emitter; - private _onDidStateChange: Emitter; + private readonly _onDidContentChange: Emitter; + private readonly _onDidStateChange: Emitter; private inConflictMode: boolean; private inOrphanMode: boolean; @@ -129,38 +128,51 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } private onFileChanges(e: FileChangesEvent): void { + let fileEventImpactsModel = false; + let newInOrphanModeGuess: boolean; - // Track ADD and DELETES for updates of this model to orphan-mode - const modelFileDeleted = e.contains(this.resource, FileChangeType.DELETED); - const modelFileAdded = e.contains(this.resource, FileChangeType.ADDED); - - if (modelFileDeleted || modelFileAdded) { - const newInOrphanModeGuess = modelFileDeleted && !modelFileAdded; - if (this.inOrphanMode !== newInOrphanModeGuess) { - let checkOrphanedPromise: TPromise; - if (newInOrphanModeGuess) { - // We have received reports of users seeing delete events even though the file still - // exists (network shares issue: https://github.com/Microsoft/vscode/issues/13665). - // Since we do not want to mark the model as orphaned, we have to check if the - // file is really gone and not just a faulty file event. - checkOrphanedPromise = TPromise.timeout(100).then(() => { - if (this.disposed) { - return true; - } - - return this.fileService.existsFile(this.resource).then(exists => !exists); - }); - } else { - checkOrphanedPromise = TPromise.as(false); - } - - checkOrphanedPromise.done(newInOrphanModeValidated => { - if (this.inOrphanMode !== newInOrphanModeValidated && !this.disposed) { - this.setOrphaned(newInOrphanModeValidated); - } - }); + // If we are currently orphaned, we check if the model file was added back + if (this.inOrphanMode) { + const modelFileAdded = e.contains(this.resource, FileChangeType.ADDED); + if (modelFileAdded) { + newInOrphanModeGuess = false; + fileEventImpactsModel = true; } } + + // Otherwise we check if the model file was deleted + else { + const modelFileDeleted = e.contains(this.resource, FileChangeType.DELETED); + if (modelFileDeleted) { + newInOrphanModeGuess = true; + fileEventImpactsModel = true; + } + } + + if (fileEventImpactsModel && this.inOrphanMode !== newInOrphanModeGuess) { + let checkOrphanedPromise: TPromise; + if (newInOrphanModeGuess) { + // We have received reports of users seeing delete events even though the file still + // exists (network shares issue: https://github.com/Microsoft/vscode/issues/13665). + // Since we do not want to mark the model as orphaned, we have to check if the + // file is really gone and not just a faulty file event. + checkOrphanedPromise = TPromise.timeout(100).then(() => { + if (this.disposed) { + return true; + } + + return this.fileService.existsFile(this.resource).then(exists => !exists); + }); + } else { + checkOrphanedPromise = TPromise.as(false); + } + + checkOrphanedPromise.done(newInOrphanModeValidated => { + if (this.inOrphanMode !== newInOrphanModeValidated && !this.disposed) { + this.setOrphaned(newInOrphanModeValidated); + } + }); + } } private setOrphaned(orphaned: boolean): void { @@ -244,7 +256,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil if (soft) { loadPromise = TPromise.as(this); } else { - loadPromise = this.load(true /* force */); + loadPromise = this.load({ forceReadFromDisk: true }); } return loadPromise.then(() => { @@ -260,28 +272,28 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil }); } - public load(force?: boolean /* bypass any caches and really go to disk */): TPromise { + public load(options?: ILoadOptions): TPromise { diag('load() - enter', this.resource, new Date()); // It is very important to not reload the model when the model is dirty. We only want to reload the model from the disk // if no save is pending to avoid data loss. This might cause a save conflict in case the file has been modified on the disk // meanwhile, but this is a very low risk. - if (this.dirty) { - diag('load() - exit - without loading because model is dirty', this.resource, new Date()); + if (this.dirty || this.saveSequentializer.hasPendingSave()) { + diag('load() - exit - without loading because model is dirty or being saved', this.resource, new Date()); return TPromise.as(this); } // Only for new models we support to load from backup if (!this.textEditorModel && !this.createTextEditorModelPromise) { - return this.loadWithBackup(force); + return this.loadWithBackup(options); } // Otherwise load from file resource - return this.loadFromFile(force); + return this.loadFromFile(options); } - private loadWithBackup(force: boolean): TPromise { + private loadWithBackup(options?: ILoadOptions): TPromise { return this.backupFileService.loadBackupResource(this.resource).then(backup => { // Make sure meanwhile someone else did not suceed or start loading @@ -293,34 +305,36 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil if (!!backup) { const content: IRawTextContent = { resource: this.resource, - name: paths.basename(this.resource.fsPath), + name: path.basename(this.resource.fsPath), mtime: Date.now(), etag: void 0, value: createTextBufferFactory(''), /* will be filled later from backup */ - encoding: this.fileService.getEncoding(this.resource, this.preferredEncoding) + encoding: this.fileService.encoding.getWriteEncoding(this.resource, this.preferredEncoding) }; return this.loadWithContent(content, backup); } // Otherwise load from file - return this.loadFromFile(force); + return this.loadFromFile(options); }); } - private loadFromFile(force: boolean): TPromise { + private loadFromFile(options?: ILoadOptions): TPromise { + const forceReadFromDisk = options && options.forceReadFromDisk; + const allowBinary = this.isResolved() /* always allow if we resolved previously */ || (options && options.allowBinary); // Decide on etag let etag: string; - if (force) { - etag = void 0; // bypass cache if force loading is true + if (forceReadFromDisk) { + etag = void 0; // reset ETag if we enforce to read from disk } else if (this.lastResolvedDiskStat) { etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching } // Resolve Content return this.textFileService - .resolveTextContent(this.resource, { acceptTextOnly: true, etag, encoding: this.preferredEncoding }) + .resolveTextContent(this.resource, { acceptTextOnly: !allowBinary, etag, encoding: this.preferredEncoding }) .then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error)); } @@ -370,10 +384,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "fileGet" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "CustomerContent", "purpose": "FeatureInsight" } + "path": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) }); + this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) }); } return model; @@ -678,16 +692,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // mark the save participant as current pending save operation return this.saveSequentializer.setPending(versionId, saveParticipantPromise.then(newVersionId => { - // Under certain conditions a save to the model will not cause the contents to the flushed on - // disk because we can assume that the contents are already on disk. Instead, we just touch the - // file to still trigger external file watchers for example. + // Under certain conditions we do a short-cut of flushing contents to disk when we can assume that + // the file has not changed and as such was not dirty before. // The conditions are all of: // - a forced, explicit save (Ctrl+S) // - the model is not dirty (otherwise we know there are changed which needs to go to the file) // - the model is not in orphan mode (because in that case we know the file does not exist on disk) // - the model version did not change due to save participants running if (options.force && !this.dirty && !this.inOrphanMode && options.reason === SaveReason.EXPLICIT && versionId === newVersionId) { - return this.doTouch(); + return this.doTouch(newVersionId); } // update versionId with its new value (if pre-save changes happened) @@ -725,7 +738,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('filePUT', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.lastResolvedDiskStat.resource.fsPath) }); + this.telemetryService.publicLog('filePUT', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.lastResolvedDiskStat.resource.fsPath) }); } // Update dirty state unless model has changed meanwhile @@ -774,16 +787,20 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Check for workspace settings file return this.contextService.getWorkspace().folders.some(folder => { // {{SQL CARBON EDIT}} - return paths.isEqualOrParent(this.resource.fsPath, path.join(folder.uri.fsPath, '.sqlops')); + return path.isEqualOrParent(this.resource.fsPath, path.join(folder.uri.fsPath, '.sqlops')); }); } - private doTouch(): TPromise { - return this.fileService.touchFile(this.resource).then(stat => { + private doTouch(versionId: number): TPromise { + return this.saveSequentializer.setPending(versionId, this.fileService.updateContent(this.lastResolvedDiskStat.resource, this.createSnapshot(), { + mtime: this.lastResolvedDiskStat.mtime, + encoding: this.getEncoding(), + etag: this.lastResolvedDiskStat.etag + }).then(stat => { // Updated resolved stat with updated stat since touching it might have changed mtime this.updateLastResolvedDiskStat(stat); - }, () => void 0 /* gracefully ignore errors if just touching */); + }, () => void 0 /* gracefully ignore errors if just touching */)); } private setDirty(dirty: boolean): () => void { @@ -829,8 +846,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Subsequent resolve - make sure that we only assign it if the mtime is equal or has advanced. - // This is essential a If-Modified-Since check on the client ot prevent race conditions from loading - // and saving. If a save comes in late after a revert was called, the mtime could be out of sync. + // This prevents race conditions from loading and saving. If a save comes in late after a revert + // was called, the mtime could be out of sync. else if (this.lastResolvedDiskStat.mtime <= newVersionOnDiskStat.mtime) { this.lastResolvedDiskStat = newVersionOnDiskStat; } @@ -923,7 +940,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil this.updatePreferredEncoding(encoding); // Load - this.load(true /* force because encoding has changed */).done(null, onUnexpectedError); + this.load({ + forceReadFromDisk: true // because encoding has changed + }).done(null, onUnexpectedError); } } @@ -1083,10 +1102,10 @@ export class SaveSequentializer { class DefaultSaveErrorHandler implements ISaveErrorHandler { - constructor( @INotificationService private notificationService: INotificationService) { } + constructor(@INotificationService private notificationService: INotificationService) { } public onSaveError(error: any, model: TextFileEditorModel): void { - this.notificationService.error(nls.localize('genericSaveError', "Failed to save '{0}': {1}", paths.basename(model.getResource().fsPath), toErrorMessage(error, false))); + this.notificationService.error(nls.localize('genericSaveError', "Failed to save '{0}': {1}", path.basename(model.getResource().fsPath), toErrorMessage(error, false))); } } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts index d99cab1b39..97d19e9d3a 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Event, { Emitter, debounceEvent } from 'vs/base/common/event'; +import { Event, Emitter, debounceEvent } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; -import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ResourceMap } from 'vs/base/common/map'; @@ -17,14 +17,14 @@ import { ResourceMap } from 'vs/base/common/map'; export class TextFileEditorModelManager implements ITextFileEditorModelManager { private toUnbind: IDisposable[]; - private _onModelDisposed: Emitter; - private _onModelContentChanged: Emitter; - private _onModelDirty: Emitter; - private _onModelSaveError: Emitter; - private _onModelSaved: Emitter; - private _onModelReverted: Emitter; - private _onModelEncodingChanged: Emitter; - private _onModelOrphanedChanged: Emitter; + private readonly _onModelDisposed: Emitter; + private readonly _onModelContentChanged: Emitter; + private readonly _onModelDirty: Emitter; + private readonly _onModelSaveError: Emitter; + private readonly _onModelSaved: Emitter; + private readonly _onModelReverted: Emitter; + private readonly _onModelEncodingChanged: Emitter; + private readonly _onModelOrphanedChanged: Emitter; private _onModelsDirtyEvent: Event; private _onModelsSaveError: Event; @@ -167,22 +167,27 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager { return pendingLoad; } + let modelLoadOptions: ILoadOptions; + if (options && options.allowBinary) { + modelLoadOptions = { allowBinary: true }; + } + let modelPromise: TPromise; // Model exists let model = this.get(resource); if (model) { - if (!options || !options.reload) { - modelPromise = TPromise.as(model); + if (options && options.reload) { + modelPromise = model.load(modelLoadOptions); } else { - modelPromise = model.load(); + modelPromise = TPromise.as(model); } } // Model does not exist else { model = this.instantiationService.createInstance(TextFileEditorModel, resource, options ? options.encoding : void 0); - modelPromise = model.load(); + modelPromise = model.load(modelLoadOptions); // Install state change listener this.mapResourceToStateChangeListener.set(resource, model.onDidStateChange(state => { diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 3c66873e9a..55d9db8ba5 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -7,11 +7,11 @@ import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import errors = require('vs/base/common/errors'); -import objects = require('vs/base/common/objects'); -import Event, { Emitter } from 'vs/base/common/event'; -import platform = require('vs/base/common/platform'); +import * as paths from 'vs/base/common/paths'; +import * as errors from 'vs/base/common/errors'; +import * as objects from 'vs/base/common/objects'; +import { Event, Emitter } from 'vs/base/common/event'; +import * as platform from 'vs/base/common/platform'; import { IWindowsService } from 'vs/platform/windows/common/windows'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions, AutoSaveContext } from 'vs/workbench/services/textfile/common/textfiles'; @@ -51,10 +51,10 @@ export abstract class TextFileService implements ITextFileService { private toUnbind: IDisposable[]; private _models: TextFileEditorModelManager; - private _onFilesAssociationChange: Emitter; + private readonly _onFilesAssociationChange: Emitter; private currentFilesAssociationConfig: { [key: string]: string; }; - private _onAutoSaveConfigurationChange: Emitter; + private readonly _onAutoSaveConfigurationChange: Emitter; private configuredAutoSaveDelay: number; private configuredAutoSaveOnFocusChange: boolean; private configuredAutoSaveOnWindowChange: boolean; @@ -484,8 +484,8 @@ export abstract class TextFileService implements ITextFileService { private doSaveAllFiles(resources?: URI[], options: ISaveOptions = Object.create(null)): TPromise { const dirtyFileModels = this.getDirtyFileModels(Array.isArray(resources) ? resources : void 0 /* Save All */) .filter(model => { - if (model.hasState(ModelState.CONFLICT) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) { - return false; // if model is in save conflict, do not save unless save reason is explicit or not provided at all + if ((model.hasState(ModelState.CONFLICT) || model.hasState(ModelState.ERROR)) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) { + return false; // if model is in save conflict or error, do not save unless save reason is explicit or not provided at all } return true; diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index b91937762b..dc2ba05f86 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -6,7 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IEncodingSupport, ConfirmResult } from 'vs/workbench/common/editor'; import { IBaseStat, IResolveContentOptions, ITextSnapshot } from 'vs/platform/files/common/files'; @@ -140,8 +140,22 @@ export interface IRawTextContent extends IBaseStat { } export interface IModelLoadOrCreateOptions { + + + /** + * The encoding to use when resolving the model text content. + */ encoding?: string; + + /** + * Wether to reload the model if it already exists. + */ reload?: boolean; + + /** + * Allow to load a model even if we think it is a binary file. + */ + allowBinary?: boolean; } export interface ITextFileEditorModelManager { @@ -179,6 +193,19 @@ export interface ISaveOptions { writeElevated?: boolean; } +export interface ILoadOptions { + + /** + * Go to disk bypassing any cache of the model if any. + */ + forceReadFromDisk?: boolean; + + /** + * Allow to load a model even if we think it is a binary file. + */ + allowBinary?: boolean; +} + export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport { onDidContentChange: Event; @@ -196,7 +223,7 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport save(options?: ISaveOptions): TPromise; - load(): TPromise; + load(options?: ILoadOptions): TPromise; revert(soft?: boolean): TPromise; diff --git a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts index 74bf40d758..9221479147 100644 --- a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts @@ -5,11 +5,11 @@ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import paths = require('vs/base/common/paths'); -import strings = require('vs/base/common/strings'); -import { isWindows, isLinux } from 'vs/base/common/platform'; +import * as paths from 'vs/base/common/paths'; +import * as strings from 'vs/base/common/strings'; +import { isWindows } from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; import { ConfirmResult } from 'vs/workbench/common/editor'; import { TextFileService as AbstractTextFileService } from 'vs/workbench/services/textfile/common/textFileService'; @@ -21,17 +21,16 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IModeService } from 'vs/editor/common/services/modeService'; import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel'; -import product from 'vs/platform/node/product'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { getConfirmMessage } from 'vs/workbench/services/dialogs/electron-browser/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { getConfirmMessage, IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { Severity } from 'vs/editor/common/standalone/standaloneBase'; export class TextFileService extends AbstractTextFileService { @@ -50,7 +49,8 @@ export class TextFileService extends AbstractTextFileService { @IBackupFileService backupFileService: IBackupFileService, @IWindowsService windowsService: IWindowsService, @IHistoryService historyService: IHistoryService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextKeyService contextKeyService: IContextKeyService, + @IDialogService private dialogService: IDialogService ) { super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, notificationService, environmentService, backupFileService, windowsService, historyService, contextKeyService, modelService); } @@ -84,39 +84,22 @@ export class TextFileService extends AbstractTextFileService { const message = resourcesToConfirm.length === 1 ? nls.localize('saveChangesMessage', "Do you want to save the changes you made to {0}?", paths.basename(resourcesToConfirm[0].fsPath)) : getConfirmMessage(nls.localize('saveChangesMessages', "Do you want to save the changes to the following {0} files?", resourcesToConfirm.length), resourcesToConfirm); - // Button order - // Windows: Save | Don't Save | Cancel - // Mac: Save | Cancel | Don't Save - // Linux: Don't Save | Cancel | Save + const buttons: string[] = [ + resourcesToConfirm.length > 1 ? nls.localize({ key: 'saveAll', comment: ['&& denotes a mnemonic'] }, "&&Save All") : nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save"), + nls.localize({ key: 'dontSave', comment: ['&& denotes a mnemonic'] }, "Do&&n't Save"), + nls.localize('cancel', "Cancel") + ]; - const save = { label: resourcesToConfirm.length > 1 ? mnemonicButtonLabel(nls.localize({ key: 'saveAll', comment: ['&& denotes a mnemonic'] }, "&&Save All")) : mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), result: ConfirmResult.SAVE }; - const dontSave = { label: mnemonicButtonLabel(nls.localize({ key: 'dontSave', comment: ['&& denotes a mnemonic'] }, "Do&&n't Save")), result: ConfirmResult.DONT_SAVE }; - const cancel = { label: nls.localize('cancel', "Cancel"), result: ConfirmResult.CANCEL }; - - const buttons: { label: string; result: ConfirmResult; }[] = []; - if (isWindows) { - buttons.push(save, dontSave, cancel); - } else if (isLinux) { - buttons.push(dontSave, cancel, save); - } else { - buttons.push(save, cancel, dontSave); - } - - const opts: Electron.MessageBoxOptions = { - title: product.nameLong, - message, - type: 'warning', - detail: nls.localize('saveChangesDetail', "Your changes will be lost if you don't save them."), - buttons: buttons.map(b => b.label), - noLink: true, - cancelId: buttons.indexOf(cancel) - }; - - if (isLinux) { - opts.defaultId = 2; - } - - return this.windowService.showMessageBox(opts).then(result => buttons[result.button].result); + return this.dialogService.show(Severity.Warning, message, buttons, { + cancelId: 2, + detail: nls.localize('saveChangesDetail', "Your changes will be lost if you don't save them.") + }).then(index => { + switch (index) { + case 0: return ConfirmResult.SAVE; + case 1: return ConfirmResult.DONT_SAVE; + default: return ConfirmResult.CANCEL; + } + }); } public promptForPath(defaultPath: string): TPromise { diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts index 447806a582..a04c0d7cb5 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts @@ -12,13 +12,14 @@ import { EncodingMode } from 'vs/workbench/common/editor'; import { TextFileEditorModel, SaveSequentializer } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { ITextFileService, ModelState, StateChange } from 'vs/workbench/services/textfile/common/textfiles'; import { workbenchInstantiationService, TestTextFileService, createFileInput, TestFileService } from 'vs/workbench/test/workbenchTestServices'; -import { onError, toResource } from 'vs/base/test/common/utils'; +import { toResource } from 'vs/base/test/common/utils'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { FileOperationResult, FileOperationError, IFileService, snapshotToString } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { timeout } from 'vs/base/common/async'; class ServiceAccessor { - constructor( @ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService, @IFileService public fileService: TestFileService) { + constructor(@ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService, @IFileService public fileService: TestFileService) { } } @@ -46,10 +47,10 @@ suite('Files - TextFileEditorModel', () => { accessor.fileService.setContent(content); }); - test('Save', function (done) { + test('Save', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('bar'); assert.ok(getLastModifiedTime(model) <= Date.now()); @@ -59,10 +60,8 @@ suite('Files - TextFileEditorModel', () => { model.dispose(); assert.ok(!accessor.modelService.getModel(model.getResource())); - - done(); }); - }, error => onError(error, done)); + }); }); test('setEncoding - encode', function () { @@ -88,19 +87,17 @@ suite('Files - TextFileEditorModel', () => { model.dispose(); }); - test('disposes when underlying model is destroyed', function (done) { + test('disposes when underlying model is destroyed', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.dispose(); assert.ok(model.isDisposed()); - - done(); - }, error => onError(error, done)); + }); }); - test('Load does not trigger save', function (done) { + test('Load does not trigger save', function () { const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index.txt'), 'utf8'); assert.ok(model.hasState(ModelState.SAVED)); @@ -108,21 +105,19 @@ suite('Files - TextFileEditorModel', () => { assert.ok(e !== StateChange.DIRTY && e !== StateChange.SAVED); }); - model.load().done(() => { + return model.load().then(() => { assert.ok(model.isResolved()); model.dispose(); assert.ok(!accessor.modelService.getModel(model.getResource())); - - done(); - }, error => onError(error, done)); + }); }); - test('Load returns dirty model as long as model is dirty', function (done) { + test('Load returns dirty model as long as model is dirty', function () { const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(model.isDirty()); @@ -131,13 +126,11 @@ suite('Files - TextFileEditorModel', () => { assert.ok(model.isDirty()); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Revert', function (done) { + test('Revert', function () { let eventCounter = 0; const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); @@ -148,7 +141,7 @@ suite('Files - TextFileEditorModel', () => { } }); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(model.isDirty()); @@ -159,13 +152,11 @@ suite('Files - TextFileEditorModel', () => { assert.equal(eventCounter, 1); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Revert (soft)', function (done) { + test('Revert (soft)', function () { let eventCounter = 0; const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); @@ -176,7 +167,7 @@ suite('Files - TextFileEditorModel', () => { } }); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(model.isDirty()); @@ -187,30 +178,26 @@ suite('Files - TextFileEditorModel', () => { assert.equal(eventCounter, 1); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Load and undo turns model dirty', function (done) { + test('Load and undo turns model dirty', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { accessor.fileService.setContent('Hello Change'); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.undo(); assert.ok(model.isDirty()); - - done(); }); - }, error => onError(error, done)); + }); }); - test('File not modified error is handled gracefully', function (done) { + test('File not modified error is handled gracefully', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { const mtime = getLastModifiedTime(model); accessor.textFileService.setResolveTextContentErrorOnce(new FileOperationError('error', FileOperationResult.FILE_NOT_MODIFIED_SINCE)); @@ -218,32 +205,28 @@ suite('Files - TextFileEditorModel', () => { assert.ok(model); assert.equal(getLastModifiedTime(model), mtime); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Load error is handled gracefully if model already exists', function (done) { + test('Load error is handled gracefully if model already exists', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); - model.load().done(() => { + return model.load().then(() => { accessor.textFileService.setResolveTextContentErrorOnce(new FileOperationError('error', FileOperationResult.FILE_NOT_FOUND)); return model.load().then((model: TextFileEditorModel) => { assert.ok(model); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('save() and isDirty() - proper with check for mtimes', function (done) { + test('save() and isDirty() - proper with check for mtimes', function () { const input1 = createFileInput(instantiationService, toResource.call(this, '/path/index_async2.txt')); const input2 = createFileInput(instantiationService, toResource.call(this, '/path/index_async.txt')); - input1.resolve().done((model1: TextFileEditorModel) => { + return input1.resolve().then((model1: TextFileEditorModel) => { return input2.resolve().then((model2: TextFileEditorModel) => { model1.textEditorModel.setValue('foo'); @@ -259,7 +242,7 @@ suite('Files - TextFileEditorModel', () => { model2.textEditorModel.setValue('foo'); assert.ok(accessor.textFileService.isDirty(toResource.call(this, '/path/index_async.txt'))); - return TPromise.timeout(10).then(() => { + return timeout(10).then(() => { accessor.textFileService.saveAll().then(() => { assert.ok(!accessor.textFileService.isDirty(toResource.call(this, '/path/index_async.txt'))); assert.ok(!accessor.textFileService.isDirty(toResource.call(this, '/path/index_async2.txt'))); @@ -270,15 +253,13 @@ suite('Files - TextFileEditorModel', () => { model1.dispose(); model2.dispose(); - - done(); }); }); }); - }, error => onError(error, done)); + }); }); - test('Save Participant', function (done) { + test('Save Participant', function () { let eventCounter = 0; const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); @@ -300,42 +281,39 @@ suite('Files - TextFileEditorModel', () => { } }); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); return model.save().then(() => { model.dispose(); assert.equal(eventCounter, 2); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Save Participant, async participant', function (done) { + test('Save Participant, async participant', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); TextFileEditorModel.setSaveParticipant({ participate: (model) => { - return TPromise.timeout(10); + return timeout(10); } }); - return model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); + const now = Date.now(); return model.save().then(() => { assert.ok(Date.now() - now >= 10); model.dispose(); - - done(); }); - }, error => onError(error, done)); + }); }); - test('Save Participant, bad participant', function (done) { + test('Save Participant, bad participant', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8'); TextFileEditorModel.setSaveParticipant({ @@ -347,17 +325,12 @@ suite('Files - TextFileEditorModel', () => { return model.load().then(() => { model.textEditorModel.setValue('foo'); return model.save().then(() => { - assert.ok(true); model.dispose(); - - done(); - }, err => { - assert.ok(false); }); - }, error => onError(error, done)); + }); }); - test('SaveSequentializer - pending basics', function (done) { + test('SaveSequentializer - pending basics', function () { const sequentializer = new SaveSequentializer(); assert.ok(!sequentializer.hasPendingSave()); @@ -371,26 +344,24 @@ suite('Files - TextFileEditorModel', () => { assert.ok(!sequentializer.pendingSave); // pending removes itself after done (use timeout) - sequentializer.setPending(2, TPromise.timeout(1)); + sequentializer.setPending(2, timeout(1)); assert.ok(sequentializer.hasPendingSave()); assert.ok(sequentializer.hasPendingSave(2)); assert.ok(!sequentializer.hasPendingSave(1)); assert.ok(sequentializer.pendingSave); - return TPromise.timeout(2).then(() => { + return timeout(2).then(() => { assert.ok(!sequentializer.hasPendingSave()); assert.ok(!sequentializer.hasPendingSave(2)); assert.ok(!sequentializer.pendingSave); - - done(); }); }); - test('SaveSequentializer - pending and next (finishes instantly)', function (done) { + test('SaveSequentializer - pending and next (finishes instantly)', function () { const sequentializer = new SaveSequentializer(); let pendingDone = false; - sequentializer.setPending(1, TPromise.timeout(1).then(() => { pendingDone = true; return null; })); + sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return null; })); // next finishes instantly let nextDone = false; @@ -399,52 +370,46 @@ suite('Files - TextFileEditorModel', () => { return res.done(() => { assert.ok(pendingDone); assert.ok(nextDone); - - done(); }); }); - test('SaveSequentializer - pending and next (finishes after timeout)', function (done) { + test('SaveSequentializer - pending and next (finishes after timeout)', function () { const sequentializer = new SaveSequentializer(); let pendingDone = false; - sequentializer.setPending(1, TPromise.timeout(1).then(() => { pendingDone = true; return null; })); + sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return null; })); // next finishes after timeout let nextDone = false; - const res = sequentializer.setNext(() => TPromise.timeout(1).then(() => { nextDone = true; return null; })); + const res = sequentializer.setNext(() => timeout(1).then(() => { nextDone = true; return null; })); return res.done(() => { assert.ok(pendingDone); assert.ok(nextDone); - - done(); }); }); - test('SaveSequentializer - pending and multiple next (last one wins)', function (done) { + test('SaveSequentializer - pending and multiple next (last one wins)', function () { const sequentializer = new SaveSequentializer(); let pendingDone = false; - sequentializer.setPending(1, TPromise.timeout(1).then(() => { pendingDone = true; return null; })); + sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return null; })); // next finishes after timeout let firstDone = false; - let firstRes = sequentializer.setNext(() => TPromise.timeout(2).then(() => { firstDone = true; return null; })); + let firstRes = sequentializer.setNext(() => timeout(2).then(() => { firstDone = true; return null; })); let secondDone = false; - let secondRes = sequentializer.setNext(() => TPromise.timeout(3).then(() => { secondDone = true; return null; })); + let secondRes = sequentializer.setNext(() => timeout(3).then(() => { secondDone = true; return null; })); let thirdDone = false; - let thirdRes = sequentializer.setNext(() => TPromise.timeout(4).then(() => { thirdDone = true; return null; })); + let thirdRes = sequentializer.setNext(() => timeout(4).then(() => { thirdDone = true; return null; })); return TPromise.join([firstRes, secondRes, thirdRes]).then(() => { assert.ok(pendingDone); assert.ok(!firstDone); assert.ok(!secondDone); assert.ok(thirdDone); - - done(); }); }); }); diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts index e822fce468..a64b509c24 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModelManager.test.ts @@ -7,16 +7,15 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { join } from 'vs/base/common/paths'; import { workbenchInstantiationService, TestEditorGroupService, TestFileService } from 'vs/workbench/test/workbenchTestServices'; -import { onError } from 'vs/base/test/common/utils'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { IFileService, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { timeout } from 'vs/base/common/async'; export class TestTextFileEditorModelManager extends TextFileEditorModelManager { @@ -103,12 +102,12 @@ suite('Files - TextFileEditorModelManager', () => { model3.dispose(); }); - test('loadOrCreate', function (done) { + test('loadOrCreate', function () { const manager: TestTextFileEditorModelManager = instantiationService.createInstance(TestTextFileEditorModelManager); const resource = URI.file('/test.html'); const encoding = 'utf8'; - manager.loadOrCreate(resource, { encoding, reload: true }).done(model => { + return manager.loadOrCreate(resource, { encoding, reload: true }).then(model => { assert.ok(model); assert.equal(model.getEncoding(), encoding); assert.equal(manager.get(resource), model); @@ -123,11 +122,9 @@ suite('Files - TextFileEditorModelManager', () => { assert.equal(manager.get(resource), model3); model3.dispose(); - - done(); }); }); - }, error => onError(error, done)); + }); }); test('removed from cache when model disposed', function () { @@ -150,7 +147,7 @@ suite('Files - TextFileEditorModelManager', () => { model3.dispose(); }); - test('events', function (done) { + test('events', function () { TextFileEditorModel.DEFAULT_CONTENT_CHANGE_BUFFER_DELAY = 0; TextFileEditorModel.DEFAULT_ORPHANED_CHANGE_BUFFER_DELAY = 0; @@ -200,7 +197,7 @@ suite('Files - TextFileEditorModelManager', () => { disposeCounter++; }); - manager.loadOrCreate(resource1, { encoding: 'utf8' }).done(model1 => { + return manager.loadOrCreate(resource1, { encoding: 'utf8' }).then(model1 => { accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource: resource1, type: FileChangeType.DELETED }])); accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource: resource1, type: FileChangeType.ADDED }])); @@ -223,7 +220,7 @@ suite('Files - TextFileEditorModelManager', () => { assert.equal(encodingCounter, 2); // content change event if done async - TPromise.timeout(10).then(() => { + return timeout(10).then(() => { assert.equal(contentCounter, 2); model1.dispose(); @@ -231,17 +228,15 @@ suite('Files - TextFileEditorModelManager', () => { assert.ok(!accessor.modelService.getModel(resource1)); assert.ok(!accessor.modelService.getModel(resource2)); - - done(); }); }); }); }); }); - }, error => onError(error, done)); + }); }); - test('events debounced', function (done) { + test('events debounced', function () { const manager: TestTextFileEditorModelManager = instantiationService.createInstance(TestTextFileEditorModelManager); const resource1 = toResource('/path/index.txt'); @@ -268,7 +263,7 @@ suite('Files - TextFileEditorModelManager', () => { assert.equal(e[0].resource.toString(), resource1.toString()); }); - manager.loadOrCreate(resource1, { encoding: 'utf8' }).done(model1 => { + return manager.loadOrCreate(resource1, { encoding: 'utf8' }).then(model1 => { return manager.loadOrCreate(resource2, { encoding: 'utf8' }).then(model2 => { model1.textEditorModel.setValue('changed'); model1.updatePreferredEncoding('utf16'); @@ -281,7 +276,7 @@ suite('Files - TextFileEditorModelManager', () => { model2.dispose(); return model1.revert().then(() => { // should not trigger another event if disposed - return TPromise.timeout(20).then(() => { + return timeout(20).then(() => { assert.equal(dirtyCounter, 2); assert.equal(revertedCounter, 1); assert.equal(savedCounter, 1); @@ -291,38 +286,35 @@ suite('Files - TextFileEditorModelManager', () => { assert.ok(!accessor.modelService.getModel(resource1)); assert.ok(!accessor.modelService.getModel(resource2)); - - done(); }); }); }); }); }); - }, error => onError(error, done)); + }); }); - test('disposing model takes it out of the manager', function (done) { + test('disposing model takes it out of the manager', function () { const manager: TestTextFileEditorModelManager = instantiationService.createInstance(TestTextFileEditorModelManager); const resource = toResource('/path/index_something.txt'); - manager.loadOrCreate(resource, { encoding: 'utf8' }).done(model => { + return manager.loadOrCreate(resource, { encoding: 'utf8' }).then(model => { model.dispose(); assert.ok(!manager.get(resource)); assert.ok(!accessor.modelService.getModel(model.getResource())); manager.dispose(); - done(); - }, error => onError(error, done)); + }); }); - test('dispose prevents dirty model from getting disposed', function (done) { + test('dispose prevents dirty model from getting disposed', function () { const manager: TestTextFileEditorModelManager = instantiationService.createInstance(TestTextFileEditorModelManager); const resource = toResource('/path/index_something.txt'); - manager.loadOrCreate(resource, { encoding: 'utf8' }).done(model => { + return manager.loadOrCreate(resource, { encoding: 'utf8' }).then(model => { model.textEditorModel.setValue('make dirty'); manager.disposeModel(model as TextFileEditorModel); @@ -334,7 +326,6 @@ suite('Files - TextFileEditorModelManager', () => { assert.ok(model.isDisposed()); manager.dispose(); - done(); - }, error => onError(error, done)); + }); }); }); \ No newline at end of file diff --git a/src/vs/workbench/services/textfile/test/textFileService.test.ts b/src/vs/workbench/services/textfile/test/textFileService.test.ts index e89d65efb1..78d3a27378 100644 --- a/src/vs/workbench/services/textfile/test/textFileService.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileService.test.ts @@ -9,7 +9,7 @@ import * as platform from 'vs/base/common/platform'; import { TPromise } from 'vs/base/common/winjs.base'; import { ILifecycleService, ShutdownEvent, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; import { workbenchInstantiationService, TestLifecycleService, TestTextFileService, TestWindowsService, TestContextService } from 'vs/workbench/test/workbenchTestServices'; -import { onError, toResource } from 'vs/base/test/common/utils'; +import { toResource } from 'vs/base/test/common/utils'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWindowsService } from 'vs/platform/windows/common/windows'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; @@ -77,14 +77,14 @@ suite('Files - TextFileService', () => { } }); - test('confirm onWillShutdown - veto if user cancels', function (done) { + test('confirm onWillShutdown - veto if user cancels', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; service.setConfirmResult(ConfirmResult.CANCEL); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.equal(service.getDirty().length, 1); @@ -93,12 +93,10 @@ suite('Files - TextFileService', () => { accessor.lifecycleService.fireWillShutdown(event); assert.ok(event.value); - - done(); - }, error => onError(error, done)); + }); }); - test('confirm onWillShutdown - no veto and backups cleaned up if user does not want to save (hot.exit: off)', function (done) { + test('confirm onWillShutdown - no veto and backups cleaned up if user does not want to save (hot.exit: off)', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); @@ -106,7 +104,7 @@ suite('Files - TextFileService', () => { service.setConfirmResult(ConfirmResult.DONT_SAVE); service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.equal(service.getDirty().length, 1); @@ -119,19 +117,17 @@ suite('Files - TextFileService', () => { assert.ok(service.cleanupBackupsBeforeShutdownCalled); assert.ok(!veto); - done(); + return void 0; } else { - veto.then(veto => { + return veto.then(veto => { assert.ok(service.cleanupBackupsBeforeShutdownCalled); assert.ok(!veto); - - done(); }); } - }, error => onError(error, done)); + }); }); - test('confirm onWillShutdown - save (hot.exit: off)', function (done) { + test('confirm onWillShutdown - save (hot.exit: off)', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); @@ -139,7 +135,7 @@ suite('Files - TextFileService', () => { service.setConfirmResult(ConfirmResult.SAVE); service.onFilesConfigurationChange({ files: { hotExit: 'off' } }); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.equal(service.getDirty().length, 1); @@ -150,18 +146,16 @@ suite('Files - TextFileService', () => { return (>event.value).then(veto => { assert.ok(!veto); assert.ok(!model.isDirty()); - - done(); }); - }, error => onError(error, done)); + }); }); - test('isDirty/getDirty - files and untitled', function (done) { + test('isDirty/getDirty - files and untitled', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; - model.load().done(() => { + return model.load().then(() => { assert.ok(!service.isDirty(model.getResource())); model.textEditorModel.setValue('foo'); @@ -178,19 +172,17 @@ suite('Files - TextFileService', () => { assert.ok(service.isDirty(untitled.getResource())); assert.equal(service.getDirty().length, 2); assert.equal(service.getDirty([untitled.getResource()])[0].toString(), untitled.getResource().toString()); - - done(); }); - }, error => onError(error, done)); + }); }); - test('save - file', function (done) { + test('save - file', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(service.isDirty(model.getResource())); @@ -198,19 +190,17 @@ suite('Files - TextFileService', () => { return service.save(model.getResource()).then(res => { assert.ok(res); assert.ok(!service.isDirty(model.getResource())); - - done(); }); - }, error => onError(error, done)); + }); }); - test('saveAll - file', function (done) { + test('saveAll - file', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(service.isDirty(model.getResource())); @@ -220,20 +210,18 @@ suite('Files - TextFileService', () => { assert.ok(!service.isDirty(model.getResource())); assert.equal(res.results.length, 1); assert.equal(res.results[0].source.toString(), model.getResource().toString()); - - done(); }); - }, error => onError(error, done)); + }); }); - test('saveAs - file', function (done) { + test('saveAs - file', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; service.setPromptPath(model.getResource().fsPath); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(service.isDirty(model.getResource())); @@ -241,20 +229,18 @@ suite('Files - TextFileService', () => { return service.saveAs(model.getResource()).then(res => { assert.equal(res.toString(), model.getResource().toString()); assert.ok(!service.isDirty(model.getResource())); - - done(); }); - }, error => onError(error, done)); + }); }); - test('revert - file', function (done) { + test('revert - file', function () { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); const service = accessor.textFileService; service.setPromptPath(model.getResource().fsPath); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.ok(service.isDirty(model.getResource())); @@ -262,118 +248,116 @@ suite('Files - TextFileService', () => { return service.revert(model.getResource()).then(res => { assert.ok(res); assert.ok(!service.isDirty(model.getResource())); - - done(); }); - }, error => onError(error, done)); + }); }); // {{SQL CARBON EDIT}} /* suite('Hot Exit', () => { suite('"onExit" setting', () => { - test('should hot exit on non-Mac (reason: CLOSE, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, false, true, !!platform.isMacintosh, done); + test('should hot exit on non-Mac (reason: CLOSE, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, false, true, !!platform.isMacintosh); }); - test('should hot exit on non-Mac (reason: CLOSE, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, false, false, !!platform.isMacintosh, done); + test('should hot exit on non-Mac (reason: CLOSE, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, false, false, !!platform.isMacintosh); }); - test('should NOT hot exit (reason: CLOSE, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, true, true, true, done); + test('should NOT hot exit (reason: CLOSE, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, true, true, true); }); - test('should NOT hot exit (reason: CLOSE, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, true, false, true, done); + test('should NOT hot exit (reason: CLOSE, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, true, false, true); }); - test('should hot exit (reason: QUIT, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, false, true, false, done); + test('should hot exit (reason: QUIT, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, false, true, false); }); - test('should hot exit (reason: QUIT, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, false, false, false, done); + test('should hot exit (reason: QUIT, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, false, false, false); }); - test('should hot exit (reason: QUIT, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, true, true, false, done); + test('should hot exit (reason: QUIT, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, true, true, false); }); - test('should hot exit (reason: QUIT, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, true, false, false, done); + test('should hot exit (reason: QUIT, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.QUIT, true, false, false); }); - test('should hot exit (reason: RELOAD, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, false, true, false, done); + test('should hot exit (reason: RELOAD, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, false, true, false); }); - test('should hot exit (reason: RELOAD, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, false, false, false, done); + test('should hot exit (reason: RELOAD, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, false, false, false); }); - test('should hot exit (reason: RELOAD, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, true, true, false, done); + test('should hot exit (reason: RELOAD, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, true, true, false); }); - test('should hot exit (reason: RELOAD, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, true, false, false, done); + test('should hot exit (reason: RELOAD, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.RELOAD, true, false, false); }); - test('should NOT hot exit (reason: LOAD, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, false, true, true, done); + test('should NOT hot exit (reason: LOAD, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, false, true, true); }); - test('should NOT hot exit (reason: LOAD, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, false, false, true, done); + test('should NOT hot exit (reason: LOAD, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, false, false, true); }); - test('should NOT hot exit (reason: LOAD, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, true, true, true, done); + test('should NOT hot exit (reason: LOAD, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, true, true, true); }); - test('should NOT hot exit (reason: LOAD, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, true, false, true, done); + test('should NOT hot exit (reason: LOAD, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.LOAD, true, false, true); }); }); suite('"onExitAndWindowClose" setting', () => { - test('should hot exit (reason: CLOSE, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, false, true, false, done); + test('should hot exit (reason: CLOSE, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, false, true, false); }); - test('should hot exit (reason: CLOSE, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, false, false, !!platform.isMacintosh, done); + test('should hot exit (reason: CLOSE, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, false, false, !!platform.isMacintosh); }); - test('should hot exit (reason: CLOSE, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, true, true, false, done); + test('should hot exit (reason: CLOSE, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, true, true, false); }); - test('should NOT hot exit (reason: CLOSE, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, true, false, true, done); + test('should NOT hot exit (reason: CLOSE, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.CLOSE, true, false, true); }); - test('should hot exit (reason: QUIT, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, false, true, false, done); + test('should hot exit (reason: QUIT, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, false, true, false); }); - test('should hot exit (reason: QUIT, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, false, false, false, done); + test('should hot exit (reason: QUIT, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, false, false, false); }); - test('should hot exit (reason: QUIT, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, true, true, false, done); + test('should hot exit (reason: QUIT, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, true, true, false); }); - test('should hot exit (reason: QUIT, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, true, false, false, done); + test('should hot exit (reason: QUIT, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.QUIT, true, false, false); }); - test('should hot exit (reason: RELOAD, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, false, true, false, done); + test('should hot exit (reason: RELOAD, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, false, true, false); }); - test('should hot exit (reason: RELOAD, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, false, false, false, done); + test('should hot exit (reason: RELOAD, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, false, false, false); }); - test('should hot exit (reason: RELOAD, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, true, true, false, done); + test('should hot exit (reason: RELOAD, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, true, true, false); }); - test('should hot exit (reason: RELOAD, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, true, false, false, done); + test('should hot exit (reason: RELOAD, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.RELOAD, true, false, false); }); - test('should hot exit (reason: LOAD, windows: single, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, false, true, false, done); + test('should hot exit (reason: LOAD, windows: single, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, false, true, false); }); - test('should NOT hot exit (reason: LOAD, windows: single, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, false, false, true, done); + test('should NOT hot exit (reason: LOAD, windows: single, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, false, false, true); }); - test('should hot exit (reason: LOAD, windows: multiple, workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, true, true, false, done); + test('should hot exit (reason: LOAD, windows: multiple, workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, true, true, false); }); - test('should NOT hot exit (reason: LOAD, windows: multiple, empty workspace)', function (done) { - hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, true, false, true, done); + test('should NOT hot exit (reason: LOAD, windows: multiple, empty workspace)', function () { + return hotExitTest.call(this, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ShutdownReason.LOAD, true, false, true); }); }); - function hotExitTest(this: any, setting: string, shutdownReason: ShutdownReason, multipleWindows: boolean, workspace: true, shouldVeto: boolean, done: () => void): void { + function hotExitTest(this: any, setting: string, shutdownReason: ShutdownReason, multipleWindows: boolean, workspace: true, shouldVeto: boolean): TPromise { model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8'); (accessor.textFileService.models).add(model.getResource(), model); @@ -391,7 +375,7 @@ suite('Files - TextFileService', () => { // Set cancel to force a veto if hot exit does not trigger service.setConfirmResult(ConfirmResult.CANCEL); - model.load().done(() => { + return model.load().then(() => { model.textEditorModel.setValue('foo'); assert.equal(service.getDirty().length, 1); @@ -404,10 +388,8 @@ suite('Files - TextFileService', () => { // When hot exit is set, backups should never be cleaned since the confirm result is cancel assert.ok(!service.cleanupBackupsBeforeShutdownCalled); assert.equal(veto, shouldVeto); - - done(); }); - }, error => onError(error, done)); + }); } }); // {{SQL CARBON EDIT}} diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index 8066c179ba..a8bdb965b8 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -13,10 +13,11 @@ import { IDisposable, toDisposable, IReference, ReferenceCollection, ImmortalRef import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import network = require('vs/base/common/network'); +import * as network from 'vs/base/common/network'; import { ITextModelService, ITextModelContentProvider, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; +import { IFileService } from 'vs/platform/files/common/files'; class ResourceModelCollection extends ReferenceCollection> { @@ -24,19 +25,15 @@ class ResourceModelCollection extends ReferenceCollection { const resource = URI.parse(key); - - if (resource.scheme === network.Schemas.file) { - return this.textFileService.models.loadOrCreate(resource); - } - if (!this.providers[resource.scheme]) { - // TODO@remote + if (this.fileService.canHandleResource(resource)) { return this.textFileService.models.loadOrCreate(resource); } return this.resolveTextModelContent(key).then(() => this.instantiationService.createInstance(ResourceEditorModel, resource)); diff --git a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts index 99f9b46778..f1f72df2c0 100644 --- a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts +++ b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts @@ -56,7 +56,7 @@ suite('Workbench - TextModelResolverService', () => { accessor.untitledEditorService.revertAll(); }); - test('resolve resource', function (done) { + test('resolve resource', function () { const dispose = accessor.textModelResolverService.registerTextModelContentProvider('test', { provideTextContent: function (resource: URI): TPromise { if (resource.scheme === 'test') { @@ -72,7 +72,7 @@ suite('Workbench - TextModelResolverService', () => { let resource = URI.from({ scheme: 'test', authority: null, path: 'thePath' }); let input: ResourceEditorInput = instantiationService.createInstance(ResourceEditorInput, 'The Name', 'The Description', resource); - input.resolve().then(model => { + return input.resolve().then(model => { assert.ok(model); assert.equal(snapshotToString((model as ResourceEditorModel).createSnapshot()), 'Hello Test'); @@ -85,7 +85,6 @@ suite('Workbench - TextModelResolverService', () => { assert.equal(disposed, true); dispose.dispose(); - done(); }); }); diff --git a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts index 82244e74db..90fffb15a9 100644 --- a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts +++ b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { registerColor, getColorRegistry } from 'vs/platform/theme/common/colorRegistry'; import { Color } from 'vs/base/common/color'; diff --git a/src/vs/workbench/services/themes/common/colorThemeSchema.ts b/src/vs/workbench/services/themes/common/colorThemeSchema.ts index 2df196f0b8..0ac401ca4d 100644 --- a/src/vs/workbench/services/themes/common/colorThemeSchema.ts +++ b/src/vs/workbench/services/themes/common/colorThemeSchema.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; @@ -10,7 +10,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { Extensions as ThemeingExtensions, IColorRegistry } from 'vs/platform/theme/common/colorRegistry'; -let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); +let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); let textMateScopes = [ 'comment', 'comment.block', @@ -204,7 +204,7 @@ const schema: IJSONSchema = { }; export function register() { - let schemaRegistry = Registry.as(JSONExtensions.JSONContribution); + let schemaRegistry = Registry.as(JSONExtensions.JSONContribution); schemaRegistry.registerSchema(schemaId, schema); } diff --git a/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts b/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts index e003fe7505..8e9d6abb71 100644 --- a/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts +++ b/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; @@ -219,6 +219,6 @@ const schema: IJSONSchema = { }; export function register() { - let schemaRegistry = Registry.as(JSONExtensions.JSONContribution); + let schemaRegistry = Registry.as(JSONExtensions.JSONContribution); schemaRegistry.registerSchema(schemaId, schema); } \ No newline at end of file diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts index 9015d22e7c..6f8d3a15d7 100644 --- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts @@ -6,7 +6,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { Color } from 'vs/base/common/color'; import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts b/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts index ba93de0f27..8d59299d10 100644 --- a/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts +++ b/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts @@ -4,17 +4,17 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Paths = require('vs/base/common/paths'); -import Json = require('vs/base/common/json'); +import * as Paths from 'vs/base/common/paths'; +import * as Json from 'vs/base/common/json'; import { Color } from 'vs/base/common/color'; import { ExtensionData, ITokenColorCustomizations, ITokenColorizationRule, IColorTheme, IColorMap, IThemeExtensionPoint, VS_LIGHT_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { convertSettings } from 'vs/workbench/services/themes/electron-browser/themeCompatibility'; import { TPromise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import * as objects from 'vs/base/common/objects'; -import pfs = require('vs/base/node/pfs'); +import * as pfs from 'vs/base/node/pfs'; import { Extensions, IColorRegistry, ColorIdentifier, editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { ThemeType } from 'vs/platform/theme/common/themeService'; @@ -22,7 +22,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { WorkbenchThemeService, IColorCustomizations } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService'; import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages'; -let colorRegistry = Registry.as(Extensions.ColorContribution); +let colorRegistry = Registry.as(Extensions.ColorContribution); const tokenGroupToScopesMap: { [setting: string]: string[] } = { comments: ['comment'], diff --git a/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts b/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts index 47cfca3598..176bedba57 100644 --- a/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts +++ b/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import * as Paths from 'path'; @@ -13,7 +13,7 @@ import { IColorTheme, ExtensionData, IThemeExtensionPoint, VS_LIGHT_THEME, VS_DA import { ColorThemeData } from 'vs/workbench/services/themes/electron-browser/colorThemeData'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; let themesExtPoint = ExtensionsRegistry.registerExtensionPoint('themes', [], { @@ -47,11 +47,11 @@ let themesExtPoint = ExtensionsRegistry.registerExtensionPoint; + private readonly onDidChangeEmitter: Emitter; public get onDidChange(): Event { return this.onDidChangeEmitter.event; } - constructor( @IExtensionService private extensionService: IExtensionService, defaultTheme: ColorThemeData) { + constructor(@IExtensionService private extensionService: IExtensionService, defaultTheme: ColorThemeData) { this.extensionsColorThemes = [defaultTheme]; this.onDidChangeEmitter = new Emitter(); this.initialize(); diff --git a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts index 1721c4fd7c..08c4dbc8f9 100644 --- a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts +++ b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts @@ -5,12 +5,12 @@ 'use strict'; import URI from 'vs/base/common/uri'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as Paths from 'path'; -import Json = require('vs/base/common/json'); +import * as Json from 'vs/base/common/json'; import { ExtensionData, IThemeExtensionPoint, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { TPromise } from 'vs/base/common/winjs.base'; -import pfs = require('vs/base/node/pfs'); +import * as pfs from 'vs/base/node/pfs'; import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService'; import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages'; diff --git a/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts b/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts index b719bc24c3..a48cac6874 100644 --- a/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts +++ b/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import * as Paths from 'path'; @@ -12,7 +12,7 @@ import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/serv import { ExtensionData, IThemeExtensionPoint } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { FileIconThemeData } from 'vs/workbench/services/themes/electron-browser/fileIconThemeData'; let iconThemeExtPoint = ExtensionsRegistry.registerExtensionPoint('iconThemes', [], { @@ -41,11 +41,11 @@ let iconThemeExtPoint = ExtensionsRegistry.registerExtensionPoint; + private readonly onDidChangeEmitter: Emitter; public get onDidChange(): Event { return this.onDidChangeEmitter.event; } - constructor( @IExtensionService private extensionService: IExtensionService) { + constructor(@IExtensionService private extensionService: IExtensionService) { this.knownIconThemes = []; this.onDidChangeEmitter = new Emitter(); this.initialize(); diff --git a/src/vs/workbench/services/themes/electron-browser/themeCompatibility.ts b/src/vs/workbench/services/themes/electron-browser/themeCompatibility.ts index 7713116aa0..dfaf13cfbf 100644 --- a/src/vs/workbench/services/themes/electron-browser/themeCompatibility.ts +++ b/src/vs/workbench/services/themes/electron-browser/themeCompatibility.ts @@ -66,6 +66,7 @@ addSettingMapping('rangeHighlight', editorColorRegistry.editorRangeHighlight); addSettingMapping('caret', editorColorRegistry.editorCursorForeground); addSettingMapping('invisibles', editorColorRegistry.editorWhitespaces); addSettingMapping('guide', editorColorRegistry.editorIndentGuides); +addSettingMapping('activeGuide', editorColorRegistry.editorActiveIndentGuides); const ansiColorMap = ['ansiBlack', 'ansiRed', 'ansiGreen', 'ansiYellow', 'ansiBlue', 'ansiMagenta', 'ansiCyan', 'ansiWhite', 'ansiBrightBlack', 'ansiBrightRed', 'ansiBrightGreen', 'ansiBrightYellow', 'ansiBrightBlue', 'ansiBrightMagenta', 'ansiBrightCyan', 'ansiBrightWhite' diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 0d65b727c7..b779817eac 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -5,14 +5,14 @@ 'use strict'; import { TPromise, Promise } from 'vs/base/common/winjs.base'; -import nls = require('vs/nls'); +import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkbenchThemeService, IColorTheme, ITokenColorCustomizations, IFileIconTheme, ExtensionData, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME, COLOR_THEME_SETTING, ICON_THEME_SETTING, CUSTOM_WORKBENCH_COLORS_SETTING, CUSTOM_EDITOR_COLORS_SETTING, CUSTOM_EDITOR_SCOPE_COLORS_SETTING, DETECT_HC_SETTING, HC_THEME_ID } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Registry } from 'vs/platform/registry/common/platform'; -import errors = require('vs/base/common/errors'); +import * as errors from 'vs/base/common/errors'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -20,18 +20,16 @@ import { ColorThemeData } from './colorThemeData'; import { ITheme, Extensions as ThemingExtensions, IThemingRegistry } from 'vs/platform/theme/common/themeService'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { Color } from 'vs/base/common/color'; - -import { $ } from 'vs/base/browser/builder'; -import Event, { Emitter } from 'vs/base/common/event'; - -import colorThemeSchema = require('vs/workbench/services/themes/common/colorThemeSchema'); -import fileIconThemeSchema = require('vs/workbench/services/themes/common/fileIconThemeSchema'); +import { Event, Emitter } from 'vs/base/common/event'; +import * as colorThemeSchema from 'vs/workbench/services/themes/common/colorThemeSchema'; +import * as fileIconThemeSchema from 'vs/workbench/services/themes/common/fileIconThemeSchema'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IBroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService'; import { ColorThemeStore } from 'vs/workbench/services/themes/electron-browser/colorThemeStore'; import { FileIconThemeStore } from 'vs/workbench/services/themes/electron-browser/fileIconThemeStore'; import { FileIconThemeData } from 'vs/workbench/services/themes/electron-browser/fileIconThemeData'; import { IWindowService } from 'vs/platform/windows/common/windows'; +import { removeClasses, addClasses } from 'vs/base/browser/dom'; // implementation // {{SQL CARBON EDIT}} @@ -76,11 +74,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private colorThemeStore: ColorThemeStore; private currentColorTheme: ColorThemeData; private container: HTMLElement; - private onColorThemeChange: Emitter; + private readonly onColorThemeChange: Emitter; private iconThemeStore: FileIconThemeStore; private currentIconTheme: IFileIconTheme; - private onFileIconThemeChange: Emitter; + private readonly onFileIconThemeChange: Emitter; private themingParticipantChangeListener: IDisposable; private _configurationWriter: ConfigurationWriter; @@ -317,11 +315,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private applyTheme(newTheme: ColorThemeData, settingsTarget: ConfigurationTarget, silent = false): TPromise { if (this.container) { if (this.currentColorTheme) { - $(this.container).removeClass(this.currentColorTheme.id); + removeClasses(this.container, this.currentColorTheme.id); } else { - $(this.container).removeClass(VS_DARK_THEME, VS_LIGHT_THEME, VS_HC_THEME); + removeClasses(this.container, VS_DARK_THEME, VS_LIGHT_THEME, VS_HC_THEME); } - $(this.container).addClass(newTheme.id); + addClasses(this.container, newTheme.id); } this.currentColorTheme = newTheme; if (!this.themingParticipantChangeListener) { @@ -363,8 +361,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { "activatePlugin" : { "id" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, "name": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "publisherDisplayName": { "classification": "PublicPersonalData", "purpose": "FeatureInsight" }, + "isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "publisherDisplayName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "themeId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } */ @@ -417,9 +415,9 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { if (this.container) { if (iconThemeData.id) { - $(this.container).addClass(fileIconsEnabledClass); + addClasses(this.container, fileIconsEnabledClass); } else { - $(this.container).removeClass(fileIconsEnabledClass); + removeClasses(this.container, fileIconsEnabledClass); } } if (iconThemeData.id) { @@ -467,7 +465,7 @@ colorThemeSchema.register(); fileIconThemeSchema.register(); class ConfigurationWriter { - constructor( @IConfigurationService private configurationService: IConfigurationService) { + constructor(@IConfigurationService private configurationService: IConfigurationService) { } public writeConfiguration(key: string, value: any, settingsTarget: ConfigurationTarget): TPromise { diff --git a/src/vs/workbench/services/timer/common/timerService.ts b/src/vs/workbench/services/timer/common/timerService.ts index 92ba169bad..67c796e961 100644 --- a/src/vs/workbench/services/timer/common/timerService.ts +++ b/src/vs/workbench/services/timer/common/timerService.ts @@ -10,10 +10,10 @@ export const ITimerService = createDecorator('timerService'); /* __GDPR__FRAGMENT__ "IMemoryInfo" : { - "workingSetSize" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "peakWorkingSetSize": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "privateBytes": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "sharedBytes": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "workingSetSize" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "peakWorkingSetSize": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "privateBytes": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "sharedBytes": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ export interface IMemoryInfo { @@ -26,29 +26,31 @@ export interface IMemoryInfo { /* __GDPR__FRAGMENT__ "IStartupMetrics" : { "version" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "ellapsed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedAppReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedWindowLoad" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedWindowLoadToRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedExtensions" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedExtensionsReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedViewletRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedEditorRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedWorkbench" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "timers.ellapsedTimersToTimersComputed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "ellapsed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedAppReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedWindowLoad" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedWindowLoadToRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedExtensions" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedExtensionsReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedViewletRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedEditorRestore" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedWorkbench" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedTimersToTimersComputed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "timers.ellapsedNlsGeneration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "platform" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "release" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "arch" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "totalmem" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "totalmem" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "freemem" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "meminfo" : { "${inline}": [ "${IMemoryInfo}" ] }, - "cpus.count" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "cpus.speed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "cpus.count" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "cpus.speed" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "cpus.model" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "initialStartup" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "hasAccessibilitySupport" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "isVMLikelyhood" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "emptyWorkbench" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "initialStartup" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "hasAccessibilitySupport" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "isVMLikelyhood" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, + "emptyWorkbench" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "loadavg" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } } */ diff --git a/src/vs/workbench/services/untitled/common/untitledEditorService.ts b/src/vs/workbench/services/untitled/common/untitledEditorService.ts index 3cc7455026..4e0ca02eab 100644 --- a/src/vs/workbench/services/untitled/common/untitledEditorService.ts +++ b/src/vs/workbench/services/untitled/common/untitledEditorService.ts @@ -6,11 +6,11 @@ import URI from 'vs/base/common/uri'; import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import arrays = require('vs/base/common/arrays'); +import * as arrays from 'vs/base/common/arrays'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { IFilesConfiguration } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import Event, { Emitter, once } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import { ResourceMap } from 'vs/base/common/map'; import { TPromise } from 'vs/base/common/winjs.base'; import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; @@ -116,10 +116,10 @@ export class UntitledEditorService implements IUntitledEditorService { private mapResourceToInput = new ResourceMap(); private mapResourceToAssociatedFilePath = new ResourceMap(); - private _onDidChangeContent: Emitter; - private _onDidChangeDirty: Emitter; - private _onDidChangeEncoding: Emitter; - private _onDidDisposeModel: Emitter; + private readonly _onDidChangeContent: Emitter; + private readonly _onDidChangeDirty: Emitter; + private readonly _onDidChangeEncoding: Emitter; + private readonly _onDidDisposeModel: Emitter; constructor( @IInstantiationService private instantiationService: IInstantiationService, diff --git a/src/vs/workbench/services/viewlet/browser/viewlet.ts b/src/vs/workbench/services/viewlet/browser/viewlet.ts index d118e098f7..8ca04eb3ef 100644 --- a/src/vs/workbench/services/viewlet/browser/viewlet.ts +++ b/src/vs/workbench/services/viewlet/browser/viewlet.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { IProgressService } from 'vs/platform/progress/common/progress'; @@ -16,6 +16,7 @@ export const IViewletService = createDecorator('viewletService' export interface IViewletService { _serviceBrand: ServiceIdentifier; + onDidViewletRegister: Event; onDidViewletOpen: Event; onDidViewletClose: Event; onDidViewletEnablementChange: Event<{ id: string, enabled: boolean }>; diff --git a/src/vs/workbench/services/viewlet/browser/viewletService.ts b/src/vs/workbench/services/viewlet/browser/viewletService.ts index 1be0523944..f3756791d9 100644 --- a/src/vs/workbench/services/viewlet/browser/viewletService.ts +++ b/src/vs/workbench/services/viewlet/browser/viewletService.ts @@ -7,7 +7,7 @@ import { TPromise, ValueCallback } from 'vs/base/common/winjs.base'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; import { Registry } from 'vs/platform/registry/common/platform'; import { ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet'; @@ -33,6 +33,7 @@ export class ViewletService implements IViewletService { private _onDidViewletEnable = new Emitter<{ id: string, enabled: boolean }>(); private disposables: IDisposable[] = []; + public get onDidViewletRegister(): Event { return >this.viewletRegistry.onDidRegister; } public get onDidViewletOpen(): Event { return this.sidebarPart.onDidViewletOpen; } public get onDidViewletClose(): Event { return this.sidebarPart.onDidViewletClose; } public get onDidViewletEnablementChange(): Event<{ id: string, enabled: boolean }> { return this._onDidViewletEnable.event; } diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index d5f4a9c9e2..0303827040 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -27,7 +27,6 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { distinct } from 'vs/base/common/arrays'; import { isLinux } from 'vs/base/common/platform'; import { isEqual } from 'vs/base/common/resources'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -42,7 +41,6 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { @IStorageService private storageService: IStorageService, @IExtensionService private extensionService: IExtensionService, @IBackupFileService private backupFileService: IBackupFileService, - @IChoiceService private choiceService: IChoiceService, @INotificationService private notificationService: INotificationService, @ICommandService private commandService: ICommandService ) { @@ -157,31 +155,33 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { private handleWorkspaceConfigurationEditingError(error: JSONEditingError): TPromise { switch (error.code) { case JSONEditingErrorCode.ERROR_INVALID_FILE: - return this.onInvalidWorkspaceConfigurationFileError(); + this.onInvalidWorkspaceConfigurationFileError(); + return TPromise.as(void 0); case JSONEditingErrorCode.ERROR_FILE_DIRTY: - return this.onWorkspaceConfigurationFileDirtyError(); + this.onWorkspaceConfigurationFileDirtyError(); + return TPromise.as(void 0); } this.notificationService.error(error.message); return TPromise.as(void 0); } - private onInvalidWorkspaceConfigurationFileError(): TPromise { + private onInvalidWorkspaceConfigurationFileError(): void { const message = nls.localize('errorInvalidTaskConfiguration', "Unable to write into workspace configuration file. Please open the file to correct errors/warnings in it and try again."); - return this.askToOpenWorkspaceConfigurationFile(message); + this.askToOpenWorkspaceConfigurationFile(message); } - private onWorkspaceConfigurationFileDirtyError(): TPromise { + private onWorkspaceConfigurationFileDirtyError(): void { const message = nls.localize('errorWorkspaceConfigurationFileDirty', "Unable to write into workspace configuration file because the file is dirty. Please save it and try again."); - return this.askToOpenWorkspaceConfigurationFile(message); + this.askToOpenWorkspaceConfigurationFile(message); } - private askToOpenWorkspaceConfigurationFile(message: string): TPromise { - return this.choiceService.choose(Severity.Error, message, [nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration")]) - .then(option => { - if (option === 0) { - this.commandService.executeCommand('workbench.action.openWorkspaceConfigFile'); - } - }); + private askToOpenWorkspaceConfigurationFile(message: string): void { + this.notificationService.prompt(Severity.Error, message, + [{ + label: nls.localize('openWorkspaceConfigurationFile', "Open Workspace Configuration"), + run: () => this.commandService.executeCommand('workbench.action.openWorkspaceConfigFile') + }] + ); } private doEnterWorkspace(mainSidePromise: () => TPromise): TPromise { diff --git a/src/vs/workbench/test/browser/part.test.ts b/src/vs/workbench/test/browser/part.test.ts index 344a7a430d..7f174c878e 100644 --- a/src/vs/workbench/test/browser/part.test.ts +++ b/src/vs/workbench/test/browser/part.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import { Build, Builder } from 'vs/base/browser/builder'; +import { Builder, $ } from 'vs/base/browser/builder'; import { Part } from 'vs/workbench/browser/part'; import * as Types from 'vs/base/common/types'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -16,16 +16,16 @@ import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; class MyPart extends Part { - constructor(private expectedParent: Builder) { + constructor(private expectedParent: HTMLElement) { super('myPart', { hasTitle: true }, new TestThemeService()); } - public createTitleArea(parent: Builder): Builder { + public createTitleArea(parent: HTMLElement): HTMLElement { assert.strictEqual(parent, this.expectedParent); return super.createTitleArea(parent); } - public createContentArea(parent: Builder): Builder { + public createContentArea(parent: HTMLElement): HTMLElement { assert.strictEqual(parent, this.expectedParent); return super.createContentArea(parent); } @@ -41,22 +41,22 @@ class MyPart2 extends Part { super('myPart2', { hasTitle: true }, new TestThemeService()); } - public createTitleArea(parent: Builder): Builder { - return parent.div(function (div) { + public createTitleArea(parent: HTMLElement): HTMLElement { + return $(parent).div(function (div) { div.span({ id: 'myPart.title', innerHtml: 'Title' }); - }); + }).getHTMLElement(); } - public createContentArea(parent: Builder): Builder { - return parent.div(function (div) { + public createContentArea(parent: HTMLElement): HTMLElement { + return $(parent).div(function (div) { div.span({ id: 'myPart.content', innerHtml: 'Content' }); - }); + }).getHTMLElement(); } } @@ -66,17 +66,17 @@ class MyPart3 extends Part { super('myPart2', { hasTitle: false }, new TestThemeService()); } - public createTitleArea(parent: Builder): Builder { + public createTitleArea(parent: HTMLElement): HTMLElement { return null; } - public createContentArea(parent: Builder): Builder { - return parent.div(function (div) { + public createContentArea(parent: HTMLElement): HTMLElement { + return $(parent).div(function (div) { div.span({ id: 'myPart.content', innerHtml: 'Content' }); - }); + }).getHTMLElement(); } } @@ -97,14 +97,13 @@ suite('Workbench Part', () => { }); test('Creation', function () { - let b = Build.withElementById(fixtureId); + let b = new Builder(document.getElementById(fixtureId)); b.div().hide(); - let part = new MyPart(b); - part.create(b); + let part = new MyPart(b.getHTMLElement()); + part.create(b.getHTMLElement()); assert.strictEqual(part.getId(), 'myPart'); - assert.strictEqual(part.getContainer(), b); // Memento let memento = part.getMemento(storage); @@ -115,7 +114,7 @@ suite('Workbench Part', () => { part.shutdown(); // Re-Create to assert memento contents - part = new MyPart(b); + part = new MyPart(b.getHTMLElement()); memento = part.getMemento(storage); assert(memento); @@ -127,31 +126,31 @@ suite('Workbench Part', () => { delete memento.bar; part.shutdown(); - part = new MyPart(b); + part = new MyPart(b.getHTMLElement()); memento = part.getMemento(storage); assert(memento); assert.strictEqual(Types.isEmptyObject(memento), true); }); test('Part Layout with Title and Content', function () { - let b = Build.withElementById(fixtureId); + let b = new Builder(document.getElementById(fixtureId)); b.div().hide(); let part = new MyPart2(); - part.create(b); + part.create(b.getHTMLElement()); - assert(Build.withElementById('myPart.title')); - assert(Build.withElementById('myPart.content')); + assert(document.getElementById('myPart.title')); + assert(document.getElementById('myPart.content')); }); test('Part Layout with Content only', function () { - let b = Build.withElementById(fixtureId); + let b = new Builder(document.getElementById(fixtureId)); b.div().hide(); let part = new MyPart3(); - part.create(b); + part.create(b.getHTMLElement()); - assert(!Build.withElementById('myPart.title')); - assert(Build.withElementById('myPart.content')); + assert(!document.getElementById('myPart.title')); + assert(document.getElementById('myPart.content')); }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts index b6bf0a8038..343038a17f 100644 --- a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts @@ -27,7 +27,7 @@ let EditorInputRegistry: IEditorInputFactoryRegistry = Platform.Registry.as(Edit export class MyEditor extends BaseEditor { - constructor( @ITelemetryService telemetryService: ITelemetryService) { + constructor(@ITelemetryService telemetryService: ITelemetryService) { super('MyEditor', NullTelemetryService, NullThemeService); } @@ -46,7 +46,7 @@ export class MyEditor extends BaseEditor { export class MyOtherEditor extends BaseEditor { - constructor( @ITelemetryService telemetryService: ITelemetryService) { + constructor(@ITelemetryService telemetryService: ITelemetryService) { super('myOtherEditor', NullTelemetryService, NullThemeService); } @@ -101,7 +101,7 @@ class MyResourceInput extends ResourceEditorInput { } suite('Workbench BaseEditor', () => { - test('BaseEditor API', function (done) { + test('BaseEditor API', function () { let e = new MyEditor(NullTelemetryService); let input = new MyOtherInput(); let options = new EditorOptions(); @@ -109,7 +109,7 @@ suite('Workbench BaseEditor', () => { assert(!e.isVisible()); assert(!e.input); assert(!e.options); - e.setInput(input, options).then(() => { + return e.setInput(input, options).then(() => { assert.strictEqual(input, e.input); assert.strictEqual(options, e.options); @@ -125,7 +125,7 @@ suite('Workbench BaseEditor', () => { assert(!e.input); assert(!e.options); assert(!e.getControl()); - }).done(() => done()); + }); }); test('EditorDescriptor', function () { diff --git a/src/vs/workbench/test/browser/parts/editor/editorStacksModel.test.ts b/src/vs/workbench/test/browser/parts/editor/editorStacksModel.test.ts index 54e903826f..f0fbd73865 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorStacksModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorStacksModel.test.ts @@ -202,7 +202,7 @@ class TestEditorInputFactory implements IEditorInputFactory { } } -(Registry.as(EditorExtensions.EditorInputFactories)).registerEditorInputFactory('testEditorInput', TestEditorInputFactory); +(Registry.as(EditorExtensions.EditorInputFactories)).registerEditorInputFactory('testEditorInput', TestEditorInputFactory); suite('Editor Stacks Model', () => { @@ -1202,7 +1202,7 @@ suite('Editor Stacks Model', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); let model: EditorStacksModel = inst.createInstance(EditorStacksModel, true); let group = model.openGroup('group'); @@ -1247,7 +1247,7 @@ suite('Editor Stacks Model', () => { inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); let model: EditorStacksModel = inst.createInstance(EditorStacksModel, true); @@ -1330,7 +1330,7 @@ suite('Editor Stacks Model', () => { inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); let model: EditorStacksModel = inst.createInstance(EditorStacksModel, true); @@ -1381,7 +1381,7 @@ suite('Editor Stacks Model', () => { inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); let model: EditorStacksModel = inst.createInstance(EditorStacksModel, true); @@ -1422,7 +1422,7 @@ suite('Editor Stacks Model', () => { config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } }); inst.stub(IConfigurationService, config); - (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); + (Registry.as(EditorExtensions.EditorInputFactories)).setInstantiationService(inst); let model: EditorStacksModel = inst.createInstance(EditorStacksModel, false); diff --git a/src/vs/workbench/test/browser/parts/editor/rangeDecorations.test.ts b/src/vs/workbench/test/browser/parts/editor/rangeDecorations.test.ts index d14ca785b7..66467aa9b7 100644 --- a/src/vs/workbench/test/browser/parts/editor/rangeDecorations.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/rangeDecorations.test.ts @@ -10,7 +10,7 @@ import { TestEditorService, workbenchInstantiationService } from 'vs/workbench/t import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; -import WorkbenchEditorService = require('vs/workbench/services/editor/common/editorService'); +import * as WorkbenchEditorService from 'vs/workbench/services/editor/common/editorService'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; import { TextModel } from 'vs/editor/common/model/textModel'; import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; diff --git a/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts b/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts new file mode 100644 index 0000000000..49e21dc09d --- /dev/null +++ b/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts @@ -0,0 +1,242 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { ContributableViewsModel } from 'vs/workbench/browser/parts/views/contributableViews'; +import { ViewLocation, ViewsRegistry, IViewDescriptor } from 'vs/workbench/common/views'; +import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; +import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { move } from 'vs/base/common/arrays'; + +const location = ViewLocation.register('test'); + +class ViewDescriptorSequence { + + readonly elements: IViewDescriptor[]; + private disposables: IDisposable[] = []; + + constructor(model: ContributableViewsModel) { + this.elements = [...model.visibleViewDescriptors]; + model.onDidAdd(({ viewDescriptor, index }) => this.elements.splice(index, 0, viewDescriptor), null, this.disposables); + model.onDidRemove(({ viewDescriptor, index }) => this.elements.splice(index, 1), null, this.disposables); + model.onDidMove(({ from, to }) => move(this.elements, from.index, to.index), null, this.disposables); + } + + dispose() { + this.disposables = dispose(this.disposables); + } +} + +suite('ContributableViewsModel', () => { + let contextKeyService: IContextKeyService; + + setup(() => { + const configurationService = new SimpleConfigurationService(); + contextKeyService = new ContextKeyService(configurationService); + }); + + teardown(() => { + contextKeyService.dispose(); + }); + + test('empty model', function () { + const model = new ContributableViewsModel(location, contextKeyService); + assert.equal(model.visibleViewDescriptors.length, 0); + }); + + test('register/unregister', function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + assert.equal(model.visibleViewDescriptors.length, 0); + assert.equal(seq.elements.length, 0); + + const viewDescriptor: IViewDescriptor = { + id: 'view1', + ctor: null, + location, + name: 'Test View 1' + }; + + ViewsRegistry.registerViews([viewDescriptor]); + + assert.equal(model.visibleViewDescriptors.length, 1); + assert.equal(seq.elements.length, 1); + assert.deepEqual(model.visibleViewDescriptors[0], viewDescriptor); + assert.deepEqual(seq.elements[0], viewDescriptor); + + ViewsRegistry.deregisterViews(['view1'], location); + + assert.equal(model.visibleViewDescriptors.length, 0); + assert.equal(seq.elements.length, 0); + }); + + test('when contexts', async function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + assert.equal(model.visibleViewDescriptors.length, 0); + assert.equal(seq.elements.length, 0); + + const viewDescriptor: IViewDescriptor = { + id: 'view1', + ctor: null, + location, + name: 'Test View 1', + when: ContextKeyExpr.equals('showview1', true) + }; + + ViewsRegistry.registerViews([viewDescriptor]); + assert.equal(model.visibleViewDescriptors.length, 0, 'view should not appear since context isnt in'); + assert.equal(seq.elements.length, 0); + + const key = contextKeyService.createKey('showview1', false); + assert.equal(model.visibleViewDescriptors.length, 0, 'view should still not appear since showview1 isnt true'); + assert.equal(seq.elements.length, 0); + + key.set(true); + await new Promise(c => setTimeout(c, 30)); + assert.equal(model.visibleViewDescriptors.length, 1, 'view should appear'); + assert.equal(seq.elements.length, 1); + assert.deepEqual(model.visibleViewDescriptors[0], viewDescriptor); + assert.equal(seq.elements[0], viewDescriptor); + + key.set(false); + await new Promise(c => setTimeout(c, 30)); + assert.equal(model.visibleViewDescriptors.length, 0, 'view should disappear'); + assert.equal(seq.elements.length, 0); + + ViewsRegistry.deregisterViews(['view1'], location); + assert.equal(model.visibleViewDescriptors.length, 0, 'view should not be there anymore'); + assert.equal(seq.elements.length, 0); + + key.set(true); + await new Promise(c => setTimeout(c, 30)); + assert.equal(model.visibleViewDescriptors.length, 0, 'view should not be there anymore'); + assert.equal(seq.elements.length, 0); + }); + + test('when contexts - multiple', async function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + const view1: IViewDescriptor = { id: 'view1', ctor: null, location, name: 'Test View 1' }; + const view2: IViewDescriptor = { id: 'view2', ctor: null, location, name: 'Test View 2', when: ContextKeyExpr.equals('showview2', true) }; + + ViewsRegistry.registerViews([view1, view2]); + assert.deepEqual(model.visibleViewDescriptors, [view1], 'only view1 should be visible'); + assert.deepEqual(seq.elements, [view1], 'only view1 should be visible'); + + const key = contextKeyService.createKey('showview2', false); + assert.deepEqual(model.visibleViewDescriptors, [view1], 'still only view1 should be visible'); + assert.deepEqual(seq.elements, [view1], 'still only view1 should be visible'); + + key.set(true); + await new Promise(c => setTimeout(c, 30)); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2], 'both views should be visible'); + assert.deepEqual(seq.elements, [view1, view2], 'both views should be visible'); + + ViewsRegistry.deregisterViews([view1.id, view2.id], location); + }); + + test('when contexts - multiple 2', async function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + const view1: IViewDescriptor = { id: 'view1', ctor: null, location, name: 'Test View 1', when: ContextKeyExpr.equals('showview1', true) }; + const view2: IViewDescriptor = { id: 'view2', ctor: null, location, name: 'Test View 2' }; + + ViewsRegistry.registerViews([view1, view2]); + assert.deepEqual(model.visibleViewDescriptors, [view2], 'only view2 should be visible'); + assert.deepEqual(seq.elements, [view2], 'only view2 should be visible'); + + const key = contextKeyService.createKey('showview1', false); + assert.deepEqual(model.visibleViewDescriptors, [view2], 'still only view2 should be visible'); + assert.deepEqual(seq.elements, [view2], 'still only view2 should be visible'); + + key.set(true); + await new Promise(c => setTimeout(c, 30)); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2], 'both views should be visible'); + assert.deepEqual(seq.elements, [view1, view2], 'both views should be visible'); + + ViewsRegistry.deregisterViews([view1.id, view2.id], location); + }); + + test('setVisible', function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + const view1: IViewDescriptor = { id: 'view1', ctor: null, location, name: 'Test View 1', canToggleVisibility: true }; + const view2: IViewDescriptor = { id: 'view2', ctor: null, location, name: 'Test View 2', canToggleVisibility: true }; + const view3: IViewDescriptor = { id: 'view3', ctor: null, location, name: 'Test View 3', canToggleVisibility: true }; + + ViewsRegistry.registerViews([view1, view2, view3]); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3]); + assert.deepEqual(seq.elements, [view1, view2, view3]); + + model.setVisible('view2', true); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3], 'nothing should happen'); + assert.deepEqual(seq.elements, [view1, view2, view3]); + + model.setVisible('view2', false); + assert.deepEqual(model.visibleViewDescriptors, [view1, view3], 'view2 should hide'); + assert.deepEqual(seq.elements, [view1, view3]); + + model.setVisible('view1', false); + assert.deepEqual(model.visibleViewDescriptors, [view3], 'view1 should hide'); + assert.deepEqual(seq.elements, [view3]); + + model.setVisible('view3', false); + assert.deepEqual(model.visibleViewDescriptors, [], 'view3 shoud hide'); + assert.deepEqual(seq.elements, []); + + model.setVisible('view1', true); + assert.deepEqual(model.visibleViewDescriptors, [view1], 'view1 should show'); + assert.deepEqual(seq.elements, [view1]); + + model.setVisible('view3', true); + assert.deepEqual(model.visibleViewDescriptors, [view1, view3], 'view3 should show'); + assert.deepEqual(seq.elements, [view1, view3]); + + model.setVisible('view2', true); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3], 'view2 should show'); + assert.deepEqual(seq.elements, [view1, view2, view3]); + + ViewsRegistry.deregisterViews([view1.id, view2.id, view3.id], location); + assert.deepEqual(model.visibleViewDescriptors, []); + assert.deepEqual(seq.elements, []); + }); + + test('move', function () { + const model = new ContributableViewsModel(location, contextKeyService); + const seq = new ViewDescriptorSequence(model); + + const view1: IViewDescriptor = { id: 'view1', ctor: null, location, name: 'Test View 1' }; + const view2: IViewDescriptor = { id: 'view2', ctor: null, location, name: 'Test View 2' }; + const view3: IViewDescriptor = { id: 'view3', ctor: null, location, name: 'Test View 3' }; + + ViewsRegistry.registerViews([view1, view2, view3]); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3], 'model views should be OK'); + assert.deepEqual(seq.elements, [view1, view2, view3], 'sql views should be OK'); + + model.move('view3', 'view1'); + assert.deepEqual(model.visibleViewDescriptors, [view3, view1, view2], 'view3 should go to the front'); + assert.deepEqual(seq.elements, [view3, view1, view2]); + + model.move('view1', 'view2'); + assert.deepEqual(model.visibleViewDescriptors, [view3, view2, view1], 'view1 should go to the end'); + assert.deepEqual(seq.elements, [view3, view2, view1]); + + model.move('view1', 'view3'); + assert.deepEqual(model.visibleViewDescriptors, [view1, view3, view2], 'view1 should go to the front'); + assert.deepEqual(seq.elements, [view1, view3, view2]); + + model.move('view2', 'view3'); + assert.deepEqual(model.visibleViewDescriptors, [view1, view2, view3], 'view2 should go to the middle'); + assert.deepEqual(seq.elements, [view1, view2, view3]); + }); +}); diff --git a/src/vs/workbench/test/browser/quickopen.test.ts b/src/vs/workbench/test/browser/quickopen.test.ts index 541fd418fd..986796ff48 100644 --- a/src/vs/workbench/test/browser/quickopen.test.ts +++ b/src/vs/workbench/test/browser/quickopen.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import 'vs/workbench/browser/parts/editor/editor.contribution'; // make sure to load all contributed editor things into tests import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { Registry } from 'vs/platform/registry/common/platform'; import { QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenAction, QuickOpenHandler } from 'vs/workbench/browser/quickopen'; @@ -66,7 +66,7 @@ suite('Workbench QuickOpen', () => { } test('QuickOpen Handler and Registry', () => { - let registry = (Registry.as(QuickOpenExtensions.Quickopen)); + let registry = (Registry.as(QuickOpenExtensions.Quickopen)); let handler = new QuickOpenHandlerDescriptor( TestHandler, 'testhandler', diff --git a/src/vs/workbench/test/browser/viewlet.test.ts b/src/vs/workbench/test/browser/viewlet.test.ts index 336a161fda..2990f7df7e 100644 --- a/src/vs/workbench/test/browser/viewlet.test.ts +++ b/src/vs/workbench/test/browser/viewlet.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import * as Platform from 'vs/platform/registry/common/platform'; -import { ViewletDescriptor, Extensions, Viewlet } from 'vs/workbench/browser/viewlet'; +import { ViewletDescriptor, Extensions, Viewlet, ViewletRegistry } from 'vs/workbench/browser/viewlet'; import * as Types from 'vs/base/common/types'; suite('Workbench Viewlet', () => { @@ -42,15 +42,15 @@ suite('Workbench Viewlet', () => { }); test('Viewlet extension point and registration', function () { - assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).registerViewlet)); - assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).getViewlet)); - assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).getViewlets)); + assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).registerViewlet)); + assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).getViewlet)); + assert(Types.isFunction(Platform.Registry.as(Extensions.Viewlets).getViewlets)); - let oldCount = Platform.Registry.as(Extensions.Viewlets).getViewlets().length; + let oldCount = Platform.Registry.as(Extensions.Viewlets).getViewlets().length; let d = new ViewletDescriptor(TestViewlet, 'reg-test-id', 'name'); - Platform.Registry.as(Extensions.Viewlets).registerViewlet(d); + Platform.Registry.as(Extensions.Viewlets).registerViewlet(d); - assert(d === Platform.Registry.as(Extensions.Viewlets).getViewlet('reg-test-id')); - assert.equal(oldCount + 1, Platform.Registry.as(Extensions.Viewlets).getViewlets().length); + assert(d === Platform.Registry.as(Extensions.Viewlets).getViewlet('reg-test-id')); + assert.equal(oldCount + 1, Platform.Registry.as(Extensions.Viewlets).getViewlets().length); }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/editor/editor.test.ts b/src/vs/workbench/test/common/editor/editor.test.ts index 3efeec8591..b99d401793 100644 --- a/src/vs/workbench/test/common/editor/editor.test.ts +++ b/src/vs/workbench/test/common/editor/editor.test.ts @@ -7,9 +7,9 @@ import * as assert from 'assert'; import { TPromise } from 'vs/base/common/winjs.base'; -import { EditorInput, toResource } from 'vs/workbench/common/editor'; +import { EditorInput, toResource, EditorViewStateMemento } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; -import { IEditorModel } from 'vs/platform/editor/common/editor'; +import { IEditorModel, Position } from 'vs/platform/editor/common/editor'; import URI from 'vs/base/common/uri'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -17,7 +17,7 @@ import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestSe import { Schemas } from 'vs/base/common/network'; class ServiceAccessor { - constructor( @IUntitledEditorService public untitledEditorService: UntitledEditorService) { + constructor(@IUntitledEditorService public untitledEditorService: UntitledEditorService) { } } @@ -86,4 +86,129 @@ suite('Workbench - Editor', () => { assert.equal(toResource(file, { supportSideBySide: true, filter: Schemas.file }).toString(), file.getResource().toString()); assert.equal(toResource(file, { supportSideBySide: true, filter: [Schemas.file, Schemas.untitled] }).toString(), file.getResource().toString()); }); + + test('EditorViewStateMemento - basics', function () { + interface TestViewState { + line: number; + } + + const rawMemento = Object.create(null); + let memento = new EditorViewStateMemento(rawMemento, 'key', 3); + + let res = memento.loadState(URI.file('/A'), Position.ONE); + assert.ok(!res); + + memento.saveState(URI.file('/A'), Position.ONE, { line: 3 }); + res = memento.loadState(URI.file('/A'), Position.ONE); + assert.ok(res); + assert.equal(res.line, 3); + + memento.saveState(URI.file('/A'), Position.TWO, { line: 5 }); + res = memento.loadState(URI.file('/A'), Position.TWO); + assert.ok(res); + assert.equal(res.line, 5); + + // Ensure capped at 3 elements + memento.saveState(URI.file('/B'), Position.ONE, { line: 1 }); + memento.saveState(URI.file('/C'), Position.ONE, { line: 1 }); + memento.saveState(URI.file('/D'), Position.ONE, { line: 1 }); + memento.saveState(URI.file('/E'), Position.ONE, { line: 1 }); + + assert.ok(!memento.loadState(URI.file('/A'), Position.ONE)); + assert.ok(!memento.loadState(URI.file('/B'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/C'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/D'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/E'), Position.ONE)); + + memento.save(); + + memento = new EditorViewStateMemento(rawMemento, 'key', 3); + assert.ok(memento.loadState(URI.file('/C'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/D'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/E'), Position.ONE)); + + memento.clearState(URI.file('/C')); + memento.clearState(URI.file('/E')); + + assert.ok(!memento.loadState(URI.file('/C'), Position.ONE)); + assert.ok(memento.loadState(URI.file('/D'), Position.ONE)); + assert.ok(!memento.loadState(URI.file('/E'), Position.ONE)); + }); + + test('EditorViewStateMemento - use with editor input', function () { + interface TestViewState { + line: number; + } + + class TestEditorInput extends EditorInput { + constructor(private resource: URI, private id = 'testEditorInput') { + super(); + } + public getTypeId() { return 'testEditorInput'; } + public resolve(): TPromise { return null; } + + public matches(other: TestEditorInput): boolean { + return other && this.id === other.id && other instanceof TestEditorInput; + } + + public getResource(): URI { + return this.resource; + } + } + + const rawMemento = Object.create(null); + let memento = new EditorViewStateMemento(rawMemento, 'key', 3); + + const testInputA = new TestEditorInput(URI.file('/A')); + + let res = memento.loadState(testInputA, Position.ONE); + assert.ok(!res); + + memento.saveState(testInputA, Position.ONE, { line: 3 }); + res = memento.loadState(testInputA, Position.ONE); + assert.ok(res); + assert.equal(res.line, 3); + + // State removed when input gets disposed + testInputA.dispose(); + res = memento.loadState(testInputA, Position.ONE); + assert.ok(!res); + }); + + test('EditorViewStateMemento - migration', function () { + interface TestViewState { + line: number; + } + + const rawMemento = { + 'key': { + [URI.file('/A').toString()]: { + 0: { + line: 5 + } + }, + [URI.file('/B').toString()]: { + 0: { + line: 1 + }, + 1: { + line: 2 + } + } + } + }; + let memento = new EditorViewStateMemento(rawMemento, 'key', 3); + + let res = memento.loadState(URI.file('/A'), Position.ONE); + assert.ok(res); + assert.equal(res.line, 5); + + res = memento.loadState(URI.file('/B'), Position.ONE); + assert.ok(res); + assert.equal(res.line, 1); + + res = memento.loadState(URI.file('/B'), Position.TWO); + assert.ok(res); + assert.equal(res.line, 2); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/editor/editorDiffModel.test.ts b/src/vs/workbench/test/common/editor/editorDiffModel.test.ts index 3fbc9aa8f5..402c87ac00 100644 --- a/src/vs/workbench/test/common/editor/editorDiffModel.test.ts +++ b/src/vs/workbench/test/common/editor/editorDiffModel.test.ts @@ -38,7 +38,7 @@ suite('Workbench - EditorModel', () => { accessor = instantiationService.createInstance(ServiceAccessor); }); - test('TextDiffEditorModel', function (done) { + test('TextDiffEditorModel', function () { const dispose = accessor.textModelResolverService.registerTextModelContentProvider('test', { provideTextContent: function (resource: URI): TPromise { if (resource.scheme === 'test') { @@ -55,7 +55,7 @@ suite('Workbench - EditorModel', () => { let otherInput = instantiationService.createInstance(ResourceEditorInput, 'name2', 'description', URI.from({ scheme: 'test', authority: null, path: 'thePath' })); let diffInput = new DiffEditorInput('name', 'description', input, otherInput); - diffInput.resolve(true).then((model: any) => { + return diffInput.resolve(true).then((model: any) => { assert(model); assert(model instanceof TextDiffEditorModel); @@ -72,8 +72,6 @@ suite('Workbench - EditorModel', () => { dispose.dispose(); }); - }).done(() => { - done(); }); }); }); diff --git a/src/vs/workbench/test/common/editor/editorModel.test.ts b/src/vs/workbench/test/common/editor/editorModel.test.ts index af81f874ad..04a201415e 100644 --- a/src/vs/workbench/test/common/editor/editorModel.test.ts +++ b/src/vs/workbench/test/common/editor/editorModel.test.ts @@ -36,7 +36,7 @@ suite('Workbench - EditorModel', () => { modeService = instantiationService.stub(IModeService, ModeServiceImpl); }); - test('EditorModel', function (done) { + test('EditorModel', function () { let counter = 0; let m = new MyEditorModel(); @@ -46,26 +46,25 @@ suite('Workbench - EditorModel', () => { counter++; }); - m.load().then(model => { + return m.load().then(model => { assert(model === m); assert.strictEqual(m.isResolved(), true); m.dispose(); assert.equal(counter, 1); - }).done(() => done()); + }); }); - test('BaseTextEditorModel', function (done) { + test('BaseTextEditorModel', function () { let modelService = stubModelService(instantiationService); let m = new MyTextEditorModel(modelService, modeService); - m.load().then((model: MyTextEditorModel) => { + return m.load().then((model: MyTextEditorModel) => { assert(model === m); return model.createTextEditorModel(createTextBufferFactory('foo'), null, 'text/plain').then(() => { assert.strictEqual(m.isResolved(), true); }); - }).done(() => { + }).then(() => { m.dispose(); - done(); }); }); diff --git a/src/vs/workbench/test/common/editor/untitledEditor.test.ts b/src/vs/workbench/test/common/editor/untitledEditor.test.ts index 362baef568..a45558fad3 100644 --- a/src/vs/workbench/test/common/editor/untitledEditor.test.ts +++ b/src/vs/workbench/test/common/editor/untitledEditor.test.ts @@ -6,7 +6,6 @@ import URI from 'vs/base/common/uri'; import * as assert from 'assert'; -import { TPromise } from 'vs/base/common/winjs.base'; import { join } from 'vs/base/common/paths'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -18,6 +17,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { snapshotToString } from 'vs/platform/files/common/files'; +import { timeout } from 'vs/base/common/async'; export class TestUntitledEditorService extends UntitledEditorService { @@ -102,7 +102,7 @@ suite('Workbench - Untitled Editor', () => { }); model.textEditorModel.setValue('foo bar'); - }); + }, err => done(err)); }); test('Untitled with associated resource', function () { @@ -115,12 +115,12 @@ suite('Workbench - Untitled Editor', () => { untitled.dispose(); }); - test('Untitled no longer dirty when content gets empty', function (done) { + test('Untitled no longer dirty when content gets empty', function () { const service = accessor.untitledEditorService; const input = service.createOrGet(); // dirty - input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then((model: UntitledEditorModel) => { model.textEditorModel.setValue('foo bar'); assert.ok(model.isDirty()); @@ -128,12 +128,10 @@ suite('Workbench - Untitled Editor', () => { assert.ok(!model.isDirty()); input.dispose(); - - done(); }); }); - test('Untitled via loadOrCreate', function (done) { + test('Untitled via loadOrCreate', function () { const service = accessor.untitledEditorService; service.loadOrCreate().then(model1 => { model1.textEditorModel.setValue('foo bar'); @@ -160,8 +158,6 @@ suite('Workbench - Untitled Editor', () => { model3.dispose(); model4.dispose(); input.dispose(); - - done(); }); }); }); @@ -175,13 +171,13 @@ suite('Workbench - Untitled Editor', () => { assert.ok(service.suggestFileName(input.getResource())); }); - test('Untitled with associated path remains dirty when content gets empty', function (done) { + test('Untitled with associated path remains dirty when content gets empty', function () { const service = accessor.untitledEditorService; const file = URI.file(join('C:\\', '/foo/file.txt')); const input = service.createOrGet(file); // dirty - input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then((model: UntitledEditorModel) => { model.textEditorModel.setValue('foo bar'); assert.ok(model.isDirty()); @@ -189,8 +185,6 @@ suite('Workbench - Untitled Editor', () => { assert.ok(model.isDirty()); input.dispose(); - - done(); }); }); @@ -225,7 +219,7 @@ suite('Workbench - Untitled Editor', () => { input.dispose(); }); - test('encoding change event', function (done) { + test('encoding change event', function () { const service = accessor.untitledEditorService; const input = service.createOrGet(); @@ -237,18 +231,16 @@ suite('Workbench - Untitled Editor', () => { }); // dirty - input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then((model: UntitledEditorModel) => { model.setEncoding('utf16'); assert.equal(counter, 1); input.dispose(); - - done(); }); }); - test('onDidChangeContent event', done => { + test('onDidChangeContent event', () => { const service = accessor.untitledEditorService; const input = service.createOrGet(); @@ -261,32 +253,30 @@ suite('Workbench - Untitled Editor', () => { assert.equal(r.toString(), input.getResource().toString()); }); - input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then((model: UntitledEditorModel) => { model.textEditorModel.setValue('foo'); assert.equal(counter, 0, 'Dirty model should not trigger event immediately'); - TPromise.timeout(3).then(() => { + return timeout(3).then(() => { assert.equal(counter, 1, 'Dirty model should trigger event'); model.textEditorModel.setValue('bar'); - TPromise.timeout(3).then(() => { + return timeout(3).then(() => { assert.equal(counter, 2, 'Content change when dirty should trigger event'); model.textEditorModel.setValue(''); - TPromise.timeout(3).then(() => { + return timeout(3).then(() => { assert.equal(counter, 3, 'Manual revert should trigger event'); model.textEditorModel.setValue('foo'); - TPromise.timeout(3).then(() => { + return timeout(3).then(() => { assert.equal(counter, 4, 'Dirty model should trigger event'); model.revert(); - TPromise.timeout(3).then(() => { + return timeout(3).then(() => { assert.equal(counter, 5, 'Revert should trigger event'); input.dispose(); - - done(); }); }); }); @@ -295,7 +285,7 @@ suite('Workbench - Untitled Editor', () => { }); }); - test('onDidDisposeModel event', done => { + test('onDidDisposeModel event', () => { const service = accessor.untitledEditorService; const input = service.createOrGet(); @@ -306,12 +296,10 @@ suite('Workbench - Untitled Editor', () => { assert.equal(r.toString(), input.getResource().toString()); }); - input.resolve().then((model: UntitledEditorModel) => { + return input.resolve().then((model: UntitledEditorModel) => { assert.equal(counter, 0); input.dispose(); assert.equal(counter, 1); - - done(); }); }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts index 46787341e2..a50cdd55ff 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts @@ -33,6 +33,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import 'vs/workbench/parts/search/electron-browser/search.contribution'; import { NullLogService } from 'vs/platform/log/common/log'; import { ITextModel } from 'vs/editor/common/model'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; +import { generateUuid } from 'vs/base/common/uuid'; +import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; const defaultSelector = { scheme: 'far' }; const model: ITextModel = EditorModel.createFromString( @@ -49,12 +52,14 @@ let rpcProtocol: TestRPCProtocol; let extHost: ExtHostLanguageFeatures; let mainThread: MainThreadLanguageFeatures; let commands: ExtHostCommands; +let task: ExtHostTask; +let workspace: ExtHostWorkspace; let disposables: vscode.Disposable[] = []; let originalErrorHandler: (e: any) => any; suite('ExtHostLanguageFeatureCommands', function () { - suiteSetup((done) => { + suiteSetup(() => { originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); setUnexpectedErrorHandler(() => { }); @@ -115,19 +120,21 @@ suite('ExtHostLanguageFeatureCommands', function () { const heapService = new ExtHostHeapService(); commands = new ExtHostCommands(rpcProtocol, heapService, new NullLogService()); + workspace = new ExtHostWorkspace(rpcProtocol, { id: generateUuid(), name: 'Test', folders: [] }, new NullLogService()); + task = new ExtHostTask(rpcProtocol, workspace); rpcProtocol.set(ExtHostContext.ExtHostCommands, commands); rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol)); - ExtHostApiCommands.register(commands); + ExtHostApiCommands.register(commands, task); const diagnostics = new ExtHostDiagnostics(rpcProtocol); rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics); - extHost = new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, commands, heapService, diagnostics); + extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, heapService, diagnostics); rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost); mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol)); - rpcProtocol.sync().then(done, done); + return rpcProtocol.sync(); }); suiteTeardown(() => { @@ -136,17 +143,16 @@ suite('ExtHostLanguageFeatureCommands', function () { mainThread.dispose(); }); - teardown(function (done) { + teardown(function () { while (disposables.length) { disposables.pop().dispose(); } - rpcProtocol.sync() - .then(() => done(), err => done(err)); + return rpcProtocol.sync(); }); // --- workspace symbols - test('WorkspaceSymbols, invalid arguments', function (done) { + test('WorkspaceSymbols, invalid arguments', function () { let promises = [ commands.executeCommand('vscode.executeWorkspaceSymbolProvider'), commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null), @@ -154,14 +160,12 @@ suite('ExtHostLanguageFeatureCommands', function () { commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true) ]; - TPromise.join(promises).then(undefined, (err: any[]) => { + return TPromise.join(promises).then(undefined, (err: any[]) => { assert.equal(err.length, 4); - done(); - return []; }); }); - test('WorkspaceSymbols, back and forth', function (done) { + test('WorkspaceSymbols, back and forth', function () { disposables.push(extHost.registerWorkspaceSymbolProvider({ provideWorkspaceSymbols(query): any { @@ -180,8 +184,8 @@ suite('ExtHostLanguageFeatureCommands', function () { } })); - rpcProtocol.sync().then(() => { - commands.executeCommand('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => { + return rpcProtocol.sync().then(() => { + return commands.executeCommand('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => { for (let info of value) { assert.ok(info instanceof types.SymbolInformation); @@ -189,9 +193,8 @@ suite('ExtHostLanguageFeatureCommands', function () { assert.equal(info.kind, types.SymbolKind.Array); } assert.equal(value.length, 3); - done(); - }, done); - }, done); + }); + }); }); test('executeWorkspaceSymbolProvider should accept empty string, #39522', async function () { @@ -213,7 +216,7 @@ suite('ExtHostLanguageFeatureCommands', function () { // --- definition - test('Definition, invalid arguments', function (done) { + test('Definition, invalid arguments', function () { let promises = [ commands.executeCommand('vscode.executeDefinitionProvider'), commands.executeCommand('vscode.executeDefinitionProvider', null), @@ -221,10 +224,8 @@ suite('ExtHostLanguageFeatureCommands', function () { commands.executeCommand('vscode.executeDefinitionProvider', true, false) ]; - TPromise.join(promises).then(undefined, (err: any[]) => { + return TPromise.join(promises).then(undefined, (err: any[]) => { assert.equal(err.length, 4); - done(); - return []; }); }); @@ -256,6 +257,49 @@ suite('ExtHostLanguageFeatureCommands', function () { }); }); + // --- type definition + + test('Type Definition, invalid arguments', function () { + const promises = [ + commands.executeCommand('vscode.executeTypeDefinitionProvider'), + commands.executeCommand('vscode.executeTypeDefinitionProvider', null), + commands.executeCommand('vscode.executeTypeDefinitionProvider', undefined), + commands.executeCommand('vscode.executeTypeDefinitionProvider', true, false) + ]; + + return TPromise.join(promises).then(undefined, (err: any[]) => { + assert.equal(err.length, 4); + }); + }); + + test('Type Definition, back and forth', function () { + + disposables.push(extHost.registerTypeDefinitionProvider(defaultSelector, { + provideTypeDefinition(doc: any): any { + return new types.Location(doc.uri, new types.Range(0, 0, 0, 0)); + } + })); + disposables.push(extHost.registerTypeDefinitionProvider(defaultSelector, { + provideTypeDefinition(doc: any): any { + return [ + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + ]; + } + })); + + return rpcProtocol.sync().then(() => { + return commands.executeCommand('vscode.executeTypeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => { + assert.equal(values.length, 4); + for (const v of values) { + assert.ok(v.uri instanceof URI); + assert.ok(v.range instanceof types.Range); + } + }); + }); + }); + // --- references test('reference search, back and forth', function () { @@ -281,7 +325,7 @@ suite('ExtHostLanguageFeatureCommands', function () { // --- outline - test('Outline, back and forth', function (done) { + test('Outline, back and forth', function () { disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { return [ @@ -291,15 +335,14 @@ suite('ExtHostLanguageFeatureCommands', function () { } })); - rpcProtocol.sync().then(() => { - commands.executeCommand('vscode.executeDocumentSymbolProvider', model.uri).then(values => { + return rpcProtocol.sync().then(() => { + return commands.executeCommand('vscode.executeDocumentSymbolProvider', model.uri).then(values => { assert.equal(values.length, 2); let [first, second] = values; assert.equal(first.name, 'testing2'); assert.equal(second.name, 'testing1'); - done(); - }, done); - }, done); + }); + }); }); // --- suggest @@ -362,7 +405,7 @@ suite('ExtHostLanguageFeatureCommands', function () { }); }); - test('Suggest, return CompletionList !array', function (done) { + test('Suggest, return CompletionList !array', function () { disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { provideCompletionItems(): any { let a = new types.CompletionItem('item1'); @@ -371,15 +414,47 @@ suite('ExtHostLanguageFeatureCommands', function () { } }, [])); - rpcProtocol.sync().then(() => { + return rpcProtocol.sync().then(() => { return commands.executeCommand('vscode.executeCompletionItemProvider', model.uri, new types.Position(0, 4)).then(list => { assert.ok(list instanceof types.CompletionList); assert.equal(list.isIncomplete, true); - done(); }); }); }); + test('Suggest, resolve completion items', async function () { + + let resolveCount = 0; + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + let a = new types.CompletionItem('item1'); + let b = new types.CompletionItem('item2'); + let c = new types.CompletionItem('item3'); + let d = new types.CompletionItem('item4'); + return new types.CompletionList([a, b, c, d], false); + }, + resolveCompletionItem(item) { + resolveCount += 1; + return item; + } + }, [])); + + await rpcProtocol.sync(); + + let list = await commands.executeCommand( + 'vscode.executeCompletionItemProvider', + model.uri, + new types.Position(0, 4), + undefined, + 2 // maxItemsToResolve + ); + + assert.ok(list instanceof types.CompletionList); + assert.equal(resolveCount, 2); + + }); + // --- quickfix test('QuickFix, back and forth', function () { @@ -459,6 +534,40 @@ suite('ExtHostLanguageFeatureCommands', function () { }); }); + test('CodeLens, resolve', async function () { + + let resolveCount = 0; + + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { + provideCodeLenses(): any { + return [ + new types.CodeLens(new types.Range(0, 0, 1, 1)), + new types.CodeLens(new types.Range(0, 0, 1, 1)), + new types.CodeLens(new types.Range(0, 0, 1, 1)), + new types.CodeLens(new types.Range(0, 0, 1, 1), { title: 'Already resolved', command: 'fff' }) + ]; + }, + resolveCodeLens(codeLens: types.CodeLens) { + codeLens.command = { title: resolveCount.toString(), command: 'resolved' }; + resolveCount += 1; + return codeLens; + } + })); + + await rpcProtocol.sync(); + + let value = await commands.executeCommand('vscode.executeCodeLensProvider', model.uri, 2); + + assert.equal(value.length, 3); // the resolve argument defines the number of results being returned + assert.equal(resolveCount, 2); + + resolveCount = 0; + value = await commands.executeCommand('vscode.executeCodeLensProvider', model.uri); + + assert.equal(value.length, 4); + assert.equal(resolveCount, 0); + }); + test('Links, back and forth', function () { disposables.push(extHost.registerDocumentLinkProvider(defaultSelector, { @@ -480,4 +589,55 @@ suite('ExtHostLanguageFeatureCommands', function () { }); }); }); + + + test('Color provider', function () { + + disposables.push(extHost.registerColorProvider(defaultSelector, { + provideDocumentColors(): vscode.ColorInformation[] { + return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))]; + }, + provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] { + const cp = new types.ColorPresentation('#ABC'); + cp.textEdit = types.TextEdit.replace(new types.Range(1, 0, 1, 20), '#ABC'); + cp.additionalTextEdits = [types.TextEdit.insert(new types.Position(2, 20), '*')]; + return [cp]; + } + })); + + return rpcProtocol.sync().then(() => { + return commands.executeCommand('vscode.executeDocumentColorProvider', model.uri).then(value => { + assert.equal(value.length, 1); + let [first] = value; + + assert.equal(first.color.red, 0.1); + assert.equal(first.color.green, 0.2); + assert.equal(first.color.blue, 0.3); + assert.equal(first.color.alpha, 0.4); + assert.equal(first.range.start.line, 0); + assert.equal(first.range.start.character, 0); + assert.equal(first.range.end.line, 0); + assert.equal(first.range.end.character, 20); + }); + }).then(() => { + const color = new types.Color(0.5, 0.6, 0.7, 0.8); + const range = new types.Range(0, 0, 0, 20); + return commands.executeCommand('vscode.executeColorPresentationProvider', color, { uri: model.uri, range }).then(value => { + assert.equal(value.length, 1); + let [first] = value; + + assert.equal(first.label, '#ABC'); + assert.equal(first.textEdit.newText, '#ABC'); + assert.equal(first.textEdit.range.start.line, 1); + assert.equal(first.textEdit.range.start.character, 0); + assert.equal(first.textEdit.range.end.line, 1); + assert.equal(first.textEdit.range.end.character, 20); + assert.equal(first.additionalTextEdits.length, 1); + assert.equal(first.additionalTextEdits[0].range.start.line, 2); + assert.equal(first.additionalTextEdits[0].range.start.character, 20); + assert.equal(first.additionalTextEdits[0].range.end.line, 2); + assert.equal(first.additionalTextEdits[0].range.end.character, 20); + }); + }); + }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostCommands.test.ts b/src/vs/workbench/test/electron-browser/api/extHostCommands.test.ts index 4d17913296..311f2b427f 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostCommands.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostCommands.test.ts @@ -29,7 +29,7 @@ suite('ExtHostCommands', function () { }; const commands = new ExtHostCommands(SingleProxyRPCProtocol(shape), undefined, new NullLogService()); - commands.registerCommand('foo', (): any => { }).dispose(); + commands.registerCommand(true, 'foo', (): any => { }).dispose(); assert.equal(lastUnregister, 'foo'); assert.equal(CommandsRegistry.getCommand('foo'), undefined); @@ -49,7 +49,7 @@ suite('ExtHostCommands', function () { }; const commands = new ExtHostCommands(SingleProxyRPCProtocol(shape), undefined, new NullLogService()); - const reg = commands.registerCommand('foo', (): any => { }); + const reg = commands.registerCommand(true, 'foo', (): any => { }); reg.dispose(); reg.dispose(); reg.dispose(); diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index 1ba9df9356..5a71e2809a 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -17,6 +17,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { NullLogService } from 'vs/platform/log/common/log'; +import { assign } from 'vs/base/common/objects'; suite('ExtHostConfiguration', function () { @@ -41,7 +42,8 @@ suite('ExtHostConfiguration', function () { user: new ConfigurationModel(contents), workspace: new ConfigurationModel(), folders: Object.create(null), - configurationScopes: {} + configurationScopes: {}, + isComplete: true }; } @@ -102,35 +104,164 @@ suite('ExtHostConfiguration', function () { 'config2': 'Das Pferd frisst kein Reis.' }, 'config4': '' + }, + 'workbench': { + 'colorCustomizations': { + 'statusBar.foreground': 'somevalue' + } } }); let testObject = all.getConfiguration(); let actual = testObject.get('farboo'); + actual['nested']['config1'] = 41; + assert.equal(41, actual['nested']['config1']); actual['farboo1'] = 'newValue'; assert.equal('newValue', actual['farboo1']); testObject = all.getConfiguration(); - testObject['farboo']['farboo1'] = 'newValue'; - assert.equal('newValue', testObject['farboo']['farboo1']); + actual = testObject.get('farboo'); + assert.equal(actual['nested']['config1'], 42); + assert.equal(actual['farboo1'], undefined); testObject = all.getConfiguration(); - testObject['farboo']['farboo1'] = 'newValue'; - assert.equal('newValue', testObject.get('farboo')['farboo1']); + actual = testObject.get('farboo'); + assert.equal(actual['config0'], true); + actual['config0'] = false; + assert.equal(actual['config0'], false); + + testObject = all.getConfiguration(); + actual = testObject.get('farboo'); + assert.equal(actual['config0'], true); testObject = all.getConfiguration(); actual = testObject.inspect('farboo'); actual['value'] = 'effectiveValue'; assert.equal('effectiveValue', actual['value']); - testObject = all.getConfiguration(); - actual = testObject.get('farboo'); - assert.equal(undefined, actual['farboo1']); + testObject = all.getConfiguration('workbench'); + actual = testObject.get('colorCustomizations'); + delete actual['statusBar.foreground']; + assert.equal(actual['statusBar.foreground'], undefined); + testObject = all.getConfiguration('workbench'); + actual = testObject.get('colorCustomizations'); + assert.equal(actual['statusBar.foreground'], 'somevalue'); + }); - testObject = all.getConfiguration(); - testObject['farboo']['farboo1'] = 'newValue'; - testObject = all.getConfiguration(); - assert.equal(undefined, testObject['farboo']['farboo1']); + test('Stringify returned configuration', function () { + + const all = createExtHostConfiguration({ + 'farboo': { + 'config0': true, + 'nested': { + 'config1': 42, + 'config2': 'Das Pferd frisst kein Reis.' + }, + 'config4': '' + }, + 'workbench': { + 'colorCustomizations': { + 'statusBar.foreground': 'somevalue' + }, + 'emptyobjectkey': { + } + } + }); + + let testObject = all.getConfiguration(); + let actual = testObject.get('farboo'); + assert.deepEqual(JSON.stringify({ + 'config0': true, + 'nested': { + 'config1': 42, + 'config2': 'Das Pferd frisst kein Reis.' + }, + 'config4': '' + }), JSON.stringify(actual)); + + assert.deepEqual(undefined, JSON.stringify(testObject.get('unknownkey'))); + + actual = testObject.get('farboo'); + actual['config0'] = false; + assert.deepEqual(JSON.stringify({ + 'config0': false, + 'nested': { + 'config1': 42, + 'config2': 'Das Pferd frisst kein Reis.' + }, + 'config4': '' + }), JSON.stringify(actual)); + + actual = testObject.get('workbench')['colorCustomizations']; + actual['statusBar.background'] = 'anothervalue'; + assert.deepEqual(JSON.stringify({ + 'statusBar.foreground': 'somevalue', + 'statusBar.background': 'anothervalue' + }), JSON.stringify(actual)); + + actual = testObject.get('workbench'); + actual['unknownkey'] = 'somevalue'; + assert.deepEqual(JSON.stringify({ + 'colorCustomizations': { + 'statusBar.foreground': 'somevalue' + }, + 'emptyobjectkey': {}, + 'unknownkey': 'somevalue' + }), JSON.stringify(actual)); + + actual = all.getConfiguration('workbench').get('emptyobjectkey'); + actual = assign(actual || {}, { + 'statusBar.background': `#0ff`, + 'statusBar.foreground': `#ff0`, + }); + assert.deepEqual(JSON.stringify({ + 'statusBar.background': `#0ff`, + 'statusBar.foreground': `#ff0`, + }), JSON.stringify(actual)); + + actual = all.getConfiguration('workbench').get('unknownkey'); + actual = assign(actual || {}, { + 'statusBar.background': `#0ff`, + 'statusBar.foreground': `#ff0`, + }); + assert.deepEqual(JSON.stringify({ + 'statusBar.background': `#0ff`, + 'statusBar.foreground': `#ff0`, + }), JSON.stringify(actual)); + }); + + test('cannot modify returned configuration', function () { + + const all = createExtHostConfiguration({ + 'farboo': { + 'config0': true, + 'nested': { + 'config1': 42, + 'config2': 'Das Pferd frisst kein Reis.' + }, + 'config4': '' + } + }); + + let testObject = all.getConfiguration(); + + try { + testObject['get'] = null; + assert.fail('This should be readonly'); + } catch (e) { + } + + try { + testObject['farboo']['config0'] = false; + assert.fail('This should be readonly'); + } catch (e) { + } + + try { + testObject['farboo']['farboo1'] = 'hello'; + assert.fail('This should be readonly'); + } catch (e) { + } }); test('inspect in no workspace context', function () { @@ -150,7 +281,8 @@ suite('ExtHostConfiguration', function () { }, ['editor.wordWrap']), workspace: new ConfigurationModel({}, []), folders: Object.create(null), - configurationScopes: {} + configurationScopes: {}, + isComplete: true } ); @@ -196,7 +328,8 @@ suite('ExtHostConfiguration', function () { }, ['editor.wordWrap']), workspace, folders, - configurationScopes: {} + configurationScopes: {}, + isComplete: true } ); @@ -270,7 +403,8 @@ suite('ExtHostConfiguration', function () { }, ['editor.wordWrap']), workspace, folders, - configurationScopes: {} + configurationScopes: {}, + isComplete: true } ); diff --git a/src/vs/workbench/test/electron-browser/api/extHostDiagnostics.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDiagnostics.test.ts index 1063657c04..2e994e97f7 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDiagnostics.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDiagnostics.test.ts @@ -7,12 +7,12 @@ import * as assert from 'assert'; import URI, { UriComponents } from 'vs/base/common/uri'; -import Severity from 'vs/base/common/severity'; import { DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics'; -import { Diagnostic, DiagnosticSeverity, Range } from 'vs/workbench/api/node/extHostTypes'; +import { Diagnostic, DiagnosticSeverity, Range, DiagnosticRelatedInformation, Location } from 'vs/workbench/api/node/extHostTypes'; import { MainThreadDiagnosticsShape } from 'vs/workbench/api/node/extHost.protocol'; -import { IMarkerData } from 'vs/platform/markers/common/markers'; +import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; +import { Emitter, toPromise } from 'vs/base/common/event'; suite('ExtHostDiagnostics', () => { @@ -27,7 +27,7 @@ suite('ExtHostDiagnostics', () => { test('disposeCheck', function () { - const collection = new DiagnosticCollection('test', new DiagnosticsShape()); + const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); collection.dispose(); collection.dispose(); // that's OK @@ -44,13 +44,13 @@ suite('ExtHostDiagnostics', () => { test('diagnostic collection, forEach, clear, has', function () { - let collection = new DiagnosticCollection('test', new DiagnosticsShape()); + let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); assert.equal(collection.name, 'test'); collection.dispose(); assert.throws(() => collection.name); let c = 0; - collection = new DiagnosticCollection('test', new DiagnosticsShape()); + collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); collection.forEach(() => c++); assert.equal(c, 0); @@ -87,7 +87,7 @@ suite('ExtHostDiagnostics', () => { }); test('diagnostic collection, immutable read', function () { - let collection = new DiagnosticCollection('test', new DiagnosticsShape()); + let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); collection.set(URI.parse('foo:bar'), [ new Diagnostic(new Range(0, 0, 1, 1), 'message-1'), new Diagnostic(new Range(0, 0, 1, 1), 'message-2') @@ -112,7 +112,7 @@ suite('ExtHostDiagnostics', () => { test('diagnostics collection, set with dupliclated tuples', function () { - let collection = new DiagnosticCollection('test', new DiagnosticsShape()); + let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); let uri = URI.parse('sc:hightower'); collection.set([ [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], @@ -168,7 +168,7 @@ suite('ExtHostDiagnostics', () => { lastEntries = entries; return super.$changeMany(owner, entries); } - }); + }, new Emitter()); let uri = URI.parse('sc:hightower'); collection.set([[uri, [new Diagnostic(new Range(0, 0, 1, 1), 'error')]]]); @@ -192,7 +192,7 @@ suite('ExtHostDiagnostics', () => { test('diagnostics collection, tuples and undefined (small array), #15585', function () { - const collection = new DiagnosticCollection('test', new DiagnosticsShape()); + const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); let uri = URI.parse('sc:hightower'); let uri2 = URI.parse('sc:nomad'); let diag = new Diagnostic(new Range(0, 0, 0, 1), 'ffff'); @@ -213,7 +213,7 @@ suite('ExtHostDiagnostics', () => { test('diagnostics collection, tuples and undefined (large array), #15585', function () { - const collection = new DiagnosticCollection('test', new DiagnosticsShape()); + const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter()); const tuples: [URI, Diagnostic[]][] = []; for (let i = 0; i < 500; i++) { @@ -242,7 +242,7 @@ suite('ExtHostDiagnostics', () => { lastEntries = entries; return super.$changeMany(owner, entries); } - }); + }, new Emitter()); let uri = URI.parse('aa:bb'); let diagnostics: Diagnostic[] = []; @@ -256,8 +256,72 @@ suite('ExtHostDiagnostics', () => { assert.equal(collection.get(uri).length, 500); assert.equal(lastEntries.length, 1); assert.equal(lastEntries[0][1].length, 251); - assert.equal(lastEntries[0][1][0].severity, Severity.Error); - assert.equal(lastEntries[0][1][200].severity, Severity.Warning); - assert.equal(lastEntries[0][1][250].severity, Severity.Error); + assert.equal(lastEntries[0][1][0].severity, MarkerSeverity.Error); + assert.equal(lastEntries[0][1][200].severity, MarkerSeverity.Warning); + assert.equal(lastEntries[0][1][250].severity, MarkerSeverity.Error); + }); + + test('diagnostic eventing', async function () { + let emitter = new Emitter<(string | URI)[]>(); + let collection = new DiagnosticCollection('ddd', new DiagnosticsShape(), emitter); + + let diag1 = new Diagnostic(new Range(1, 1, 2, 3), 'diag1'); + let diag2 = new Diagnostic(new Range(1, 1, 2, 3), 'diag2'); + let diag3 = new Diagnostic(new Range(1, 1, 2, 3), 'diag3'); + + let p = toPromise(emitter.event).then(a => { + assert.equal(a.length, 1); + assert.equal(a[0].toString(), 'aa:bb'); + assert.ok(URI.isUri(a[0])); + }); + collection.set(URI.parse('aa:bb'), []); + await p; + + p = toPromise(emitter.event).then(e => { + assert.equal(e.length, 2); + assert.ok(URI.isUri(e[0])); + assert.ok(URI.isUri(e[1])); + assert.equal(e[0].toString(), 'aa:bb'); + assert.equal(e[1].toString(), 'aa:cc'); + }); + collection.set([ + [URI.parse('aa:bb'), [diag1]], + [URI.parse('aa:cc'), [diag2, diag3]], + ]); + await p; + + p = toPromise(emitter.event).then(e => { + assert.equal(e.length, 2); + assert.ok(typeof e[0] === 'string'); + assert.ok(typeof e[1] === 'string'); + }); + collection.clear(); + await p; + }); + + test('diagnostics with related information', function (done) { + + let collection = new DiagnosticCollection('ddd', new class extends DiagnosticsShape { + $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]) { + + let [[, data]] = entries; + assert.equal(entries.length, 1); + assert.equal(data.length, 1); + + let [diag] = data; + assert.equal(diag.relatedInformation.length, 2); + assert.equal(diag.relatedInformation[0].message, 'more1'); + assert.equal(diag.relatedInformation[1].message, 'more2'); + done(); + } + }, new Emitter()); + + let diag = new Diagnostic(new Range(0, 0, 1, 1), 'Foo'); + diag.relatedInformation = [ + new DiagnosticRelatedInformation(new Location(URI.parse('cc:dd'), new Range(0, 0, 0, 0)), 'more1'), + new DiagnosticRelatedInformation(new Location(URI.parse('cc:ee'), new Range(0, 0, 0, 0)), 'more2') + ]; + + collection.set(URI.parse('aa:bb'), [diag]); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts index e447f34a57..6fb4e2b394 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDocumentData.test.ts @@ -101,6 +101,7 @@ suite('ExtHostDocumentData', () => { data.onEvents({ changes: [{ range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, + rangeOffset: undefined, rangeLength: undefined, text: '\t ' }], @@ -157,6 +158,7 @@ suite('ExtHostDocumentData', () => { data.onEvents({ changes: [{ range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeOffset: undefined, rangeLength: undefined, text: '' }], @@ -174,6 +176,7 @@ suite('ExtHostDocumentData', () => { data.onEvents({ changes: [{ range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeOffset: undefined, rangeLength: undefined, text: 'is could be' }], @@ -191,6 +194,7 @@ suite('ExtHostDocumentData', () => { data.onEvents({ changes: [{ range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 }, + rangeOffset: undefined, rangeLength: undefined, text: 'is could be\na line with number' }], @@ -211,6 +215,7 @@ suite('ExtHostDocumentData', () => { data.onEvents({ changes: [{ range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 }, + rangeOffset: undefined, rangeLength: undefined, text: '' }], @@ -344,6 +349,7 @@ suite('ExtHostDocumentData updates line mapping', () => { return { changes: [{ range: range, + rangeOffset: undefined, rangeLength: undefined, text: text }], diff --git a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts index 4923954a66..1160b2fd44 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts @@ -19,6 +19,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { NullLogService } from 'vs/platform/log/common/log'; import { isResourceTextEdit, ResourceTextEdit } from 'vs/editor/common/modes'; +import { timeout } from 'vs/base/common/async'; suite('ExtHostDocumentSaveParticipant', () => { @@ -166,12 +167,12 @@ suite('ExtHostDocumentSaveParticipant', () => { let callCount = 0; let sub1 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { callCount += 1; - event.waitUntil(TPromise.timeout(17)); + event.waitUntil(timeout(17)); }); let sub2 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { callCount += 1; - event.waitUntil(TPromise.timeout(17)); + event.waitUntil(timeout(17)); }); let sub3 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { @@ -193,9 +194,9 @@ suite('ExtHostDocumentSaveParticipant', () => { let sub = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { - event.waitUntil(TPromise.timeout(10)); - event.waitUntil(TPromise.timeout(10)); - event.waitUntil(TPromise.timeout(10)); + event.waitUntil(timeout(10)); + event.waitUntil(timeout(10)); + event.waitUntil(timeout(10)); }); return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(() => { @@ -212,7 +213,7 @@ suite('ExtHostDocumentSaveParticipant', () => { event.waitUntil(new TPromise((resolve, reject) => { setTimeout(() => { try { - assert.throws(() => event.waitUntil(TPromise.timeout(10))); + assert.throws(() => event.waitUntil(timeout(10))); resolve(void 0); } catch (e) { reject(e); @@ -231,7 +232,7 @@ suite('ExtHostDocumentSaveParticipant', () => { const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, mainThreadEditors, { timeout: 5, errors: 3 }); let sub = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) { - event.waitUntil(TPromise.timeout(15)); + event.waitUntil(timeout(15)); }); return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(values => { @@ -301,6 +302,7 @@ suite('ExtHostDocumentSaveParticipant', () => { documents.$acceptModelChanged(resource, { changes: [{ range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, + rangeOffset: undefined, rangeLength: undefined, text: 'bar' }], @@ -336,6 +338,7 @@ suite('ExtHostDocumentSaveParticipant', () => { changes: [{ range, text, + rangeOffset: undefined, rangeLength: undefined, }], eol: undefined, diff --git a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts index 3ffda1b141..0c22bb10e4 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -30,7 +30,7 @@ import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefiniti import { getHover } from 'vs/editor/contrib/hover/getHover'; import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/wordHighlighter'; import { provideReferences } from 'vs/editor/contrib/referenceSearch/referenceSearch'; -import { getCodeActions } from 'vs/editor/contrib/quickFix/quickFix'; +import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction'; import { getWorkspaceSymbols } from 'vs/workbench/parts/search/common/search'; import { rename } from 'vs/editor/contrib/rename/rename'; import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp'; @@ -45,6 +45,7 @@ import * as vscode from 'vscode'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { NullLogService } from 'vs/platform/log/common/log'; import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model'; +import { getColors } from 'vs/editor/contrib/colorPicker/color'; const defaultSelector = { scheme: 'far' }; const model: ITextModel = EditorModel.createFromString( @@ -110,7 +111,7 @@ suite('ExtHostLanguageFeatures', function () { const diagnostics = new ExtHostDiagnostics(rpcProtocol); rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics); - extHost = new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, commands, heapService, diagnostics); + extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, heapService, diagnostics); rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost); mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol)); @@ -1033,6 +1034,13 @@ suite('ExtHostLanguageFeatures', function () { }); test('Format Doc, order', function () { + + disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, { + provideDocumentFormattingEdits(): any { + return undefined; + } + })); + disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, { provideDocumentFormattingEdits(): any { return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')]; @@ -1078,6 +1086,11 @@ suite('ExtHostLanguageFeatures', function () { return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')]; } })); + disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, { + provideDocumentRangeFormattingEdits(): any { + return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')]; + } + })); disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, { provideDocumentFormattingEdits(): any { return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')]; @@ -1087,7 +1100,11 @@ suite('ExtHostLanguageFeatures', function () { return getDocumentRangeFormattingEdits(model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }).then(value => { assert.equal(value.length, 1); let [first] = value; - assert.equal(first.text, 'range'); + assert.equal(first.text, 'range2'); + assert.equal(first.range.startLineNumber, 3); + assert.equal(first.range.startColumn, 4); + assert.equal(first.range.endLineNumber, 5); + assert.equal(first.range.endColumn, 6); }); }); }); @@ -1166,4 +1183,26 @@ suite('ExtHostLanguageFeatures', function () { }); }); }); + + test('Document colors, data conversion', function () { + + disposables.push(extHost.registerColorProvider(defaultSelector, { + provideDocumentColors(): vscode.ColorInformation[] { + return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))]; + }, + provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] { + return []; + } + })); + + return rpcProtocol.sync().then(() => { + return getColors(model).then(value => { + assert.equal(value.length, 1); + let [first] = value; + + assert.deepEqual(first.colorInfo.color, { red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4 }); + assert.deepEqual(first.colorInfo.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 21 }); + }); + }); + }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts index e4c05f0fe6..9a54c2a854 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts @@ -8,13 +8,17 @@ import * as assert from 'assert'; import { MainThreadMessageService } from 'vs/workbench/api/electron-browser/mainThreadMessageService'; import { TPromise as Promise, TPromise } from 'vs/base/common/winjs.base'; -import { IChoiceService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotification, NoOpNotification, INotificationHandle, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; -const emptyChoiceService = new class implements IChoiceService { - _serviceBrand: 'choiceService'; - choose(severity, message, options, modal): never { +const emptyDialogService = new class implements IDialogService { + _serviceBrand: 'dialogService'; + show(severity, message, buttons): never { + throw new Error('not implemented'); + } + + confirm(...opts): never { throw new Error('not implemented'); } }; @@ -79,7 +83,7 @@ suite('ExtHostMessageService', function () { let service = new MainThreadMessageService(null, new EmptyNotificationService(notification => { assert.equal(notification.actions.primary.length, 1); setImmediate(() => notification.actions.primary[0].run()); - }), emptyCommandService, emptyChoiceService, null); + }), emptyCommandService, emptyDialogService, null); return service.$showMessage(1, 'h', {}, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => { assert.equal(handle, 42); @@ -87,16 +91,16 @@ suite('ExtHostMessageService', function () { }); suite('modal', () => { - test('calls choice service', () => { + test('calls dialog service', () => { const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, { - choose(severity, message, options, modal) { + show(severity, message, buttons) { assert.equal(severity, 1); assert.equal(message, 'h'); - assert.equal(options.length, 2); - assert.equal(options[1], 'Cancel'); + assert.equal(buttons.length, 2); + assert.equal(buttons[1], 'Cancel'); return Promise.as(0); } - } as IChoiceService, null); + } as IDialogService, null); return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => { assert.equal(handle, 42); @@ -105,10 +109,10 @@ suite('ExtHostMessageService', function () { test('returns undefined when cancelled', () => { const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, { - choose(severity, message, options, modal) { + show(severity, message, buttons) { return Promise.as(1); } - } as IChoiceService, null); + } as IDialogService, null); return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => { assert.equal(handle, undefined); @@ -117,11 +121,11 @@ suite('ExtHostMessageService', function () { test('hides Cancel button when not needed', () => { const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, { - choose(severity, message, options, modal) { - assert.equal(options.length, 1); + show(severity, message, buttons) { + assert.equal(buttons.length, 1); return Promise.as(0); } - } as IChoiceService, null); + } as IDialogService, null); return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => { assert.equal(handle, 42); diff --git a/src/vs/workbench/test/electron-browser/api/extHostTreeViews.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTreeViews.test.ts index 2eb6fed39e..0db961988a 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTreeViews.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTreeViews.test.ts @@ -75,8 +75,8 @@ suite('ExtHostTreeView', function () { testObject = new ExtHostTreeViews(target, new ExtHostCommands(rpcProtocol, new ExtHostHeapService(), new NullLogService())); onDidChangeTreeNode = new Emitter<{ key: string }>(); onDidChangeTreeNodeWithId = new Emitter<{ key: string }>(); - testObject.registerTreeDataProvider('testNodeTreeProvider', aNodeTreeDataProvider(), (fn) => fn); - testObject.registerTreeDataProvider('testNodeWithIdTreeProvider', aNodeWithIdTreeDataProvider(), (fn) => fn); + testObject.createTreeView('testNodeTreeProvider', { treeDataProvider: aNodeTreeDataProvider() }); + testObject.createTreeView('testNodeWithIdTreeProvider', { treeDataProvider: aNodeWithIdTreeDataProvider() }); testObject.$getChildren('testNodeTreeProvider').then(elements => { for (const element of elements) { @@ -405,14 +405,14 @@ suite('ExtHostTreeView', function () { }); test('reveal will throw an error if getParent is not implemented', () => { - const treeView = testObject.registerTreeDataProvider('treeDataProvider', aNodeTreeDataProvider(), (fn) => fn); + const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aNodeTreeDataProvider() }); return treeView.reveal({ key: 'a' }) .then(() => assert.fail('Reveal should throw an error as getParent is not implemented'), () => null); }); test('reveal will return empty array for root element', () => { const revealTarget = sinon.spy(target, '$reveal'); - const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn); + const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }); return treeView.reveal({ key: 'a' }) .then(() => { assert.ok(revealTarget.calledOnce); @@ -423,9 +423,9 @@ suite('ExtHostTreeView', function () { }); }); - test('reveal will return parents array for an element', () => { + test('reveal will return parents array for an element when hierarchy is not loaded', () => { const revealTarget = sinon.spy(target, '$reveal'); - const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn); + const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }); return treeView.reveal({ key: 'aa' }) .then(() => { assert.ok(revealTarget.calledOnce); @@ -436,6 +436,21 @@ suite('ExtHostTreeView', function () { }); }); + test('reveal will return parents array for an element when hierarchy is loaded', () => { + const revealTarget = sinon.spy(target, '$reveal'); + const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }); + return testObject.$getChildren('treeDataProvider') + .then(() => testObject.$getChildren('treeDataProvider', '0/0:a')) + .then(() => treeView.reveal({ key: 'aa' }) + .then(() => { + assert.ok(revealTarget.calledOnce); + assert.deepEqual('treeDataProvider', revealTarget.args[0][0]); + assert.deepEqual({ handle: '0/0:a/0:aa', label: 'aa', collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' }, removeUnsetKeys(revealTarget.args[0][1])); + assert.deepEqual([{ handle: '0/0:a', label: 'a', collapsibleState: TreeItemCollapsibleState.Collapsed }], (>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg))); + assert.equal(void 0, revealTarget.args[0][3]); + })); + }); + test('reveal will return parents array for deeper element with no selection', () => { tree = { 'b': { @@ -445,7 +460,7 @@ suite('ExtHostTreeView', function () { } }; const revealTarget = sinon.spy(target, '$reveal'); - const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn); + const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }); return treeView.reveal({ key: 'bac' }, { select: false }) .then(() => { assert.ok(revealTarget.calledOnce); diff --git a/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts index 86584d89d0..2d32c486a9 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts @@ -513,4 +513,10 @@ suite('ExtHostTypes', function () { assert.equal(string.value, '${BAR}'); }); + + test('instanceof doesn\'t work for FileSystemError #49386', function () { + const error = types.FileSystemError.Unavailable('foo'); + assert.ok(error instanceof Error); + assert.ok(error instanceof types.FileSystemError); + }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts new file mode 100644 index 0000000000..949ff7d8eb --- /dev/null +++ b/src/vs/workbench/test/electron-browser/api/extHostWebview.test.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * 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 assert from 'assert'; +import { MainThreadWebviews } from 'vs/workbench/api/electron-browser/mainThreadWebview'; +import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview'; +import { mock } from 'vs/workbench/test/electron-browser/api/mock'; +import * as vscode from 'vscode'; +import { SingleProxyRPCProtocol } from './testRPCProtocol'; +import { Position as EditorPosition } from 'vs/platform/editor/common/editor'; + +suite('ExtHostWebview', function () { + + test('Cannot register multiple serializer for the same view type', async () => { + const viewType = 'view.type'; + + const shape = createNoopMainThreadWebviews(); + const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape)); + + let lastInvokedDeserializer: vscode.WebviewPanelSerializer | undefined = undefined; + + class NoopSerializer implements vscode.WebviewPanelSerializer { + async serializeWebviewPanel(webview: vscode.WebviewPanel): Promise { /* noop */ } + + async deserializeWebviewPanel(webview: vscode.WebviewPanel, state: any): Promise { + lastInvokedDeserializer = this; + } + } + + const serializerA = new NoopSerializer(); + const serializerB = new NoopSerializer(); + + const serializerARegistration = extHostWebviews.registerWebviewPanelSerializer(viewType, serializerA); + + await extHostWebviews.$deserializeWebviewPanel('x', viewType, 'title', {}, EditorPosition.ONE, {}); + assert.strictEqual(lastInvokedDeserializer, serializerA); + + assert.throws( + () => extHostWebviews.registerWebviewPanelSerializer(viewType, serializerB), + 'Should throw when registering two serializers for the same view'); + + serializerARegistration.dispose(); + + extHostWebviews.registerWebviewPanelSerializer(viewType, serializerB); + + await extHostWebviews.$deserializeWebviewPanel('x', viewType, 'title', {}, EditorPosition.ONE, {}); + assert.strictEqual(lastInvokedDeserializer, serializerB); + }); +}); + + +function createNoopMainThreadWebviews() { + return new class extends mock() { + $registerSerializer() { /* noop */ } + $unregisterSerializer() { /* noop */ } + }; +} + diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadDocuments.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadDocuments.test.ts index 27f4af3fa3..f9436a8a6b 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadDocuments.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadDocuments.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { BoundModelReferenceCollection } from 'vs/workbench/api/electron-browser/mainThreadDocuments'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { TPromise } from 'vs/base/common/winjs.base'; +import { timeout } from 'vs/base/common/async'; suite('BoundModelReferenceCollection', () => { @@ -29,7 +29,7 @@ suite('BoundModelReferenceCollection', () => { } }); - return TPromise.timeout(30).then(() => { + return timeout(30).then(() => { assert.equal(didDispose, true); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts index 3b9f11e6b3..1d373bd52c 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadDocumentsAndEditors.test.ts @@ -17,7 +17,7 @@ import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta } from 'vs/w import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; suite('MainThreadDocumentsAndEditors', () => { @@ -89,7 +89,22 @@ suite('MainThreadDocumentsAndEditors', () => { this.timeout(1000 * 60); // increase timeout for this one test const model = modelService.createModel(hugeModelString, null, null); - assert.ok(model.isTooLargeForHavingARichMode()); + assert.ok(model.isTooLargeForSyncing()); + + assert.equal(deltas.length, 1); + const [delta] = deltas; + assert.equal(delta.newActiveEditor, null); + assert.equal(delta.addedDocuments, undefined); + assert.equal(delta.removedDocuments, undefined); + assert.equal(delta.addedEditors, undefined); + assert.equal(delta.removedEditors, undefined); + }); + + test('ignore simple widget model', function () { + this.timeout(1000 * 60); // increase timeout for this one test + + const model = modelService.createModel('test', null, null, true); + assert.ok(model.isForSimpleWidget); assert.equal(deltas.length, 1); const [delta] = deltas; diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts index c899486ae1..55e4c38cbb 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts @@ -16,7 +16,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/node/extHost.protocol'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import Event from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { MainThreadTextEditors } from 'vs/workbench/api/electron-browser/mainThreadEditors'; import URI from 'vs/base/common/uri'; import { Range } from 'vs/editor/common/core/range'; diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts index 726fad632c..43dd1c5efc 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts @@ -20,7 +20,7 @@ import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/commo import { snapshotToString } from 'vs/platform/files/common/files'; class ServiceAccessor { - constructor( @ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService) { + constructor(@ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService) { } } @@ -39,10 +39,10 @@ suite('MainThreadSaveParticipant', function () { TextFileEditorModel.setSaveParticipant(null); // reset any set participant }); - test('insert final new line', function (done) { + test('insert final new line', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/final_new_line.txt'), 'utf8'); - model.load().then(() => { + return model.load().then(() => { const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'insertFinalNewline': true }); @@ -71,15 +71,13 @@ suite('MainThreadSaveParticipant', function () { model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()), `${lineContent}${model.textEditorModel.getEOL()}`); - - done(); }); }); - test('trim final new lines', function (done) { + test('trim final new lines', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); - model.load().then(() => { + return model.load().then(() => { const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); @@ -111,15 +109,13 @@ suite('MainThreadSaveParticipant', function () { model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${textContent}${eol}`); - - done(); }); }); - test('trim final new lines bug#39750', function (done) { + test('trim final new lines bug#39750', function () { const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); - model.load().then(() => { + return model.load().then(() => { const configService = new TestConfigurationService(); configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); @@ -140,8 +136,34 @@ suite('MainThreadSaveParticipant', function () { participant.participate(model, { reason: SaveReason.EXPLICIT }); model.textEditorModel.redo(); assert.equal(snapshotToString(model.createSnapshot()), `${textContent}.`); - done(); }); }); + test('trim final new lines bug#46075', function () { + const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8'); + + return model.load().then(() => { + const configService = new TestConfigurationService(); + configService.setUserConfiguration('files', { 'trimFinalNewlines': true }); + + const participant = new TrimFinalNewLinesParticipant(configService, undefined); + + const textContent = 'Test'; + const eol = `${model.textEditorModel.getEOL()}`; + + let content = `${textContent}${eol}${eol}`; + model.textEditorModel.setValue(content); + // save many times + for (let i = 0; i < 10; i++) { + participant.participate(model, { reason: SaveReason.EXPLICIT }); + } + // confirm trimming + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`); + // undo should go back to previous content immediately + model.textEditorModel.undo(); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${eol}`); + model.textEditorModel.redo(); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`); + }); + }); }); diff --git a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts index 9e4399c3b1..28188101d4 100644 --- a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts @@ -32,9 +32,9 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { SearchModel } from 'vs/workbench/parts/search/common/searchModel'; import { QueryBuilder } from 'vs/workbench/parts/search/common/queryBuilder'; -import Event, * as event from 'vs/base/common/event'; +import * as event from 'vs/base/common/event'; import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; -import { ILogService, NullLogService } from '../../../platform/log/common/log'; +import { NullLogService, ILogService } from 'vs/platform/log/common/log'; declare var __dirname: string; @@ -150,7 +150,7 @@ class TestTelemetryService implements ITelemetryService { private emitter = new event.Emitter(); - public get eventLogged(): Event { + public get eventLogged(): event.Event { return this.emitter.event; } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index a6bda91e3e..2bb9af4910 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -15,12 +15,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { IEditorGroup, ConfirmResult, IEditorOpeningEvent } from 'vs/workbench/common/editor'; -import Event, { Emitter } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IPartService, Parts, Position as PartPosition, Dimension } from 'vs/workbench/services/part/common/partService'; +import { IPartService, Parts, Position as PartPosition, IDimension } from 'vs/workbench/services/part/common/partService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IEditorInput, IEditorOptions, Position, IEditor, IResourceInput } from 'vs/platform/editor/common/editor'; @@ -32,7 +32,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { IEditorGroupService, GroupArrangement, GroupOrientation, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService'; -import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent, ICreateFileOptions, ITextSnapshot } from 'vs/platform/files/common/files'; +import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent, ICreateFileOptions, ITextSnapshot, IResourceEncodings } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; @@ -62,8 +62,9 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { ITextBufferFactory, DefaultEndOfLine, EndOfLinePreference } from 'vs/editor/common/model'; import { Range } from 'vs/editor/common/core/range'; -import { IChoiceService, IConfirmation, IConfirmationResult, IConfirmationService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotificationHandle, INotification, NoOpNotification, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions } from 'vs/platform/dialogs/common/dialogs'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, void 0); @@ -77,9 +78,9 @@ export class TestContextService implements IWorkspaceContextService { private workspace: IWorkbenchWorkspace; private options: any; - private _onDidChangeWorkspaceName: Emitter; - private _onDidChangeWorkspaceFolders: Emitter; - private _onDidChangeWorkbenchState: Emitter; + private readonly _onDidChangeWorkspaceName: Emitter; + private readonly _onDidChangeWorkspaceFolders: Emitter; + private readonly _onDidChangeWorkbenchState: Emitter; constructor(workspace: any = TestWorkspace, options: any = null) { this.workspace = workspace; @@ -257,17 +258,13 @@ export function workbenchInstantiationService(): IInstantiationService { instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(INotificationService, new TestNotificationService()); instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); + instantiationService.stub(IWindowService, new TestWindowService()); instantiationService.stub(IWindowsService, new TestWindowsService()); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); instantiationService.stub(IEnvironmentService, TestEnvironmentService); instantiationService.stub(IThemeService, new TestThemeService()); instantiationService.stub(IHashService, new TestHashService()); - instantiationService.stub(IChoiceService, { - choose: (severity, message, options, cancelId): TPromise => { - return TPromise.as(cancelId); - } - } as IChoiceService); return instantiationService; } @@ -310,44 +307,17 @@ export class TestHistoryService implements IHistoryService { } } -export class TestNotificationService implements INotificationService { +export class TestDialogService implements IDialogService { public _serviceBrand: any; - private static readonly NO_OP: INotificationHandle = new NoOpNotification(); - - public info(message: string): INotificationHandle { - return this.notify({ severity: Severity.Info, message }); - } - - public warn(message: string): INotificationHandle { - return this.notify({ severity: Severity.Warning, message }); - } - - public error(error: string | Error): INotificationHandle { - return this.notify({ severity: Severity.Error, message: error }); - } - - public notify(notification: INotification): INotificationHandle { - return TestNotificationService.NO_OP; - } - - public prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { - return TestNotificationService.NO_OP; - } -} - -export class TestConfirmationService implements IConfirmationService { - - public _serviceBrand: any; - - public confirm(confirmation: IConfirmation): TPromise { - return TPromise.wrap(false); - } - - public confirmWithCheckbox(confirmation: IConfirmation): Promise { + public confirm(confirmation: IConfirmation): Promise { return TPromise.as({ confirmed: false }); } + + public show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise { + return TPromise.as(0); + } } export class TestPartService implements IPartService { @@ -355,13 +325,13 @@ export class TestPartService implements IPartService { public _serviceBrand: any; private _onTitleBarVisibilityChange = new Emitter(); - private _onEditorLayout = new Emitter(); + private _onEditorLayout = new Emitter(); public get onTitleBarVisibilityChange(): Event { return this._onTitleBarVisibilityChange.event; } - public get onEditorLayout(): Event { + public get onEditorLayout(): Event { return this._onEditorLayout.event; } @@ -438,7 +408,7 @@ export class TestPartService implements IPartService { public toggleZenMode(): void { } public isEditorLayoutCentered(): boolean { return false; } - public toggleCenteredEditorLayout(): void { } + public centerEditorLayout(active: boolean): void { } public resizePart(part: Parts, sizeChange: number): void { } @@ -480,12 +450,12 @@ export class TestEditorGroupService implements IEditorGroupService { private stacksModel: EditorStacksModel; - private _onEditorsChanged: Emitter; - private _onEditorOpening: Emitter; - private _onEditorOpenFail: Emitter; - private _onEditorsMoved: Emitter; - private _onGroupOrientationChanged: Emitter; - private _onTabOptionsChanged: Emitter; + private readonly _onEditorsChanged: Emitter; + private readonly _onEditorOpening: Emitter; + private readonly _onEditorOpenFail: Emitter; + private readonly _onEditorsMoved: Emitter; + private readonly _onGroupOrientationChanged: Emitter; + private readonly _onTabOptionsChanged: Emitter; constructor(callback?: (method: string) => void) { this._onEditorsMoved = new Emitter(); @@ -684,8 +654,10 @@ export class TestFileService implements IFileService { public _serviceBrand: any; - private _onFileChanges: Emitter; - private _onAfterOperation: Emitter; + public encoding: IResourceEncodings; + + private readonly _onFileChanges: Emitter; + private readonly _onAfterOperation: Emitter; private content = 'Hello Html'; @@ -801,8 +773,10 @@ export class TestFileService implements IFileService { return TPromise.as(null); } - touchFile(resource: URI): TPromise { - return TPromise.as(null); + onDidChangeFileSystemProviderRegistrations = Event.None; + + registerProvider(scheme: string, provider) { + return { dispose() { } }; } canHandleResource(resource: URI): boolean { @@ -813,20 +787,13 @@ export class TestFileService implements IFileService { return TPromise.as(null); } - importFile(source: URI, targetFolder: URI): TPromise { - return TPromise.as(null); - } - watchFileChanges(resource: URI): void { } unwatchFileChanges(resource: URI): void { } - updateOptions(options: any): void { - } - - getEncoding(resource: URI): string { + getWriteEncoding(resource: URI): string { return 'utf8'; } @@ -901,7 +868,7 @@ export class TestWindowService implements IWindowService { public _serviceBrand: any; - onDidChangeFocus: Event; + onDidChangeFocus: Event = new Emitter().event; isFocused(): TPromise { return TPromise.as(false); diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index b86cd00069..cdf494f7b1 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -19,10 +19,11 @@ import 'vs/editor/editor.all'; import 'vs/workbench/services/actions/electron-browser/menusExtensionPoint'; // Views +import 'vs/workbench/api/browser/viewsContainersExtensionPoint'; import 'vs/workbench/api/browser/viewsExtensionPoint'; // Localizations -import 'vs/workbench/parts/localizations/browser/localizations.contribution'; +import 'vs/workbench/parts/localizations/electron-browser/localizations.contribution'; // Workbench import 'vs/workbench/browser/actions/toggleActivityBarVisibility'; @@ -64,10 +65,12 @@ import 'vs/workbench/parts/scm/electron-browser/scmViewlet'; // can be packaged // import 'vs/workbench/parts/debug/browser/debugEditorActions'; // import 'vs/workbench/parts/debug/browser/debugViewlet'; // can be packaged separately -import 'vs/workbench/parts/markers/markers.contribution'; -import 'vs/workbench/parts/markers/browser/markersPanel'; // can be packaged separately +import 'vs/workbench/parts/markers/electron-browser/markers.contribution'; -import 'vs/workbench/parts/html/browser/html.contribution'; +import 'vs/workbench/parts/html/electron-browser/html.contribution'; + +import 'vs/workbench/parts/url/electron-browser/url.contribution'; +import 'vs/workbench/parts/webview/electron-browser/webview.contribution'; // {{SQL CARBON EDIT}} // import 'vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution'; @@ -87,8 +90,6 @@ import 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; // can be p import 'vs/workbench/electron-browser/workbench'; -import 'vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution'; - import 'vs/workbench/parts/relauncher/electron-browser/relauncher.contribution'; import 'vs/workbench/parts/tasks/electron-browser/task.contribution'; diff --git a/test/README.md b/test/README.md index 60860e3f52..bccc0fa5c1 100644 --- a/test/README.md +++ b/test/README.md @@ -2,7 +2,7 @@ ## Run -The best way to run the Code tests is from the terminal. To make development changes to unit tests you need to be running `gulp`. See [Development Workflow](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#incremental-build) for more details. From the `vscode` folder run: +The best way to run the Code tests is from the terminal. To make development changes to unit tests you need to be running `yarn run watch`. See [Development Workflow](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#incremental-build) for more details. From the `vscode` folder run: **OS X and Linux** diff --git a/test/electron/index.js b/test/electron/index.js index eec592925a..fda8520c8a 100644 --- a/test/electron/index.js +++ b/test/electron/index.js @@ -10,6 +10,8 @@ const path = require('path'); const mocha = require('mocha'); const events = require('events'); +const defaultReporterName = process.platform === 'win32' ? 'list' : 'spec'; + const optimist = require('optimist') .describe('grep', 'only run tests matching ').alias('grep', 'g').alias('grep', 'f').string('grep') .describe('run', 'only run tests from ').string('run') @@ -17,7 +19,9 @@ const optimist = require('optimist') .describe('build', 'run with build output (out-build)').boolean('build') .describe('coverage', 'generate coverage report').boolean('coverage') .describe('debug', 'open dev tools, keep window open, reuse app data').string('debug') - .describe('reporter', 'the mocha reporter').string('reporter').default('reporter', process.platform === 'win32' ? 'dot' : 'spec') + .describe('reporter', 'the mocha reporter').string('reporter').default('reporter', defaultReporterName) + .describe('reporter-options', 'the mocha reporter options').string('reporter-options').default('reporter-options', '') + .describe('tfs').boolean('tfs') .describe('help', 'show the help').alias('help', 'h'); const argv = optimist.argv; @@ -33,6 +37,9 @@ if (!argv.debug) { function deserializeSuite(suite) { return { + root: suite.root, + suites: suite.suites, + tests: suite.tests, title: suite.title, fullTitle: () => suite.fullTitle, timeout: () => suite.timeout, @@ -84,6 +91,31 @@ class IPCRunner extends events.EventEmitter { } } +function parseReporterOption(value) { + let r = /^([^=]+)=(.*)$/.exec(value); + return r ? { [r[1]]: r[2] } : {}; +} + +class TFSReporter extends mocha.reporters.Base { + + constructor(runner) { + super(runner); + + runner.on('pending', test => { + console.log('PEND', test.fullTitle()); + }); + runner.on('pass', test => { + console.log('OK ', test.fullTitle(), `(${test.duration}ms)`); + }); + runner.on('fail', test => { + console.log('FAIL', test.fullTitle(), `(${test.duration}ms)`); + }); + runner.once('end', () => { + this.epilogue(); + }); + } +} + app.on('ready', () => { const win = new BrowserWindow({ @@ -99,25 +131,38 @@ app.on('ready', () => { win.webContents.on('did-finish-load', () => { if (argv.debug) { win.show(); - win.webContents.openDevTools('right'); + win.webContents.openDevTools({ mode: 'right' }); } win.webContents.send('run', argv); }); win.loadURL(`file://${__dirname}/renderer.html`); - const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter); - let Reporter; - - try { - Reporter = require(reporterPath); - } catch (err) { - console.warn(`could not load reporter: ${argv.reporter}`); - Reporter = process.platform === 'win32' ? mocha.reporters.Dot : mocha.reporters.Spec; - } - const runner = new IPCRunner(); - new Reporter(runner); + + if (argv.tfs) { + new TFSReporter(runner); + } else { + const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter); + let Reporter; + + try { + Reporter = require(reporterPath); + } catch (err) { + try { + Reporter = require(argv.reporter); + } catch (err) { + Reporter = process.platform === 'win32' ? mocha.reporters.List : mocha.reporters.Spec; + console.warn(`could not load reporter: ${argv.reporter}, using ${Reporter.name}`); + } + } + + let reporterOptions = argv['reporter-options']; + reporterOptions = typeof reporterOptions === 'string' ? [reporterOptions] : reporterOptions; + reporterOptions = reporterOptions.reduce((r, o) => Object.assign(r, parseReporterOption(o)), {}); + + new Reporter(runner, { reporterOptions }); + } if (!argv.debug) { ipcMain.on('all done', () => app.exit(runner.didFail ? 1 : 0)); diff --git a/test/electron/renderer.html b/test/electron/renderer.html index 0c94643deb..1eb67318bf 100644 --- a/test/electron/renderer.html +++ b/test/electron/renderer.html @@ -11,7 +11,10 @@ diff --git a/test/electron/renderer.js b/test/electron/renderer.js index 75e5c9b441..4387aa6188 100644 --- a/test/electron/renderer.js +++ b/test/electron/renderer.js @@ -187,6 +187,9 @@ function loadTests(opts) { function serializeSuite(suite) { return { + root: suite.root, + suites: suite.suites.map(serializeSuite), + tests: suite.tests.map(serializeRunnable), title: suite.title, fullTitle: suite.fullTitle(), timeout: suite.timeout(), diff --git a/test/smoke/.gitignore b/test/smoke/.gitignore index 532798d3ea..6601bb4c58 100644 --- a/test/smoke/.gitignore +++ b/test/smoke/.gitignore @@ -4,4 +4,5 @@ Thumbs.db node_modules/ out/ keybindings.*.json -test_data/ \ No newline at end of file +test_data/ +src/vscode/driver.d.ts \ No newline at end of file diff --git a/test/smoke/README.md b/test/smoke/README.md index 8856e45440..0647f5b9bb 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -4,43 +4,26 @@ ``` # Dev -npm run smoketest +yarn smoketest -# Specific build -npm run smoketest -- --build "path/to/code" - -# Data Migration tests -npm run smoketest -- --build "path/to/code-insiders" --stable-build "path/to/code" +# Build +yarn smoketest --build "path/to/code" ``` -The script calls mocha, so all mocha arguments should work fine. For example, use `-f Git` to only run the `Git` tests. +The script calls mocha, so all mocha arguments should work fine. For example, use `-f Git` to filter all tests except the `Git` tests. -By default, screenshots are not captured. To run tests with screenshots use the argument `--screenshots`. +A `--verbose` flag can be used to log to the console all the low level driver calls make to Code. + +Screenshots can be captured when tests fail. In order to get them,you need to use the argument `--screenshots SCREENSHOT_DIR`. ## Pitfalls -- Beware of **state**. The tests within a single suite will share the same state. +- Beware of workbench **state**. The tests within a single suite will share the same state. - Beware of **singletons**. This evil can, and will, manifest itself under the form of FS paths, TCP ports, IPC handles. Whenever writing a test, or setting up more smoke test architecture, make sure it can run simultaneously with any other tests and even itself. All test suites should be able to run many times in parallel. - Beware of **focus**. **Never** depend on DOM elements having focus using `.focused` classes or `:focus` pseudo-classes, since they will lose that state as soon as another window appears on top of the running VS Code window. A safe approach which avoids this problem is to use the `waitForActiveElement` API. Many tests use this whenever they need to wait for a specific element to _have focus_. -- Beware of **timing**. You need to read from or write to the DOM... yeah I know. But is it the right time to do that? Can you 100% promise that that `input` box will be visible and in the DOM at this point in time? Or are you just hoping that it will be so? Every time you want to interact with the DOM, be absolutely sure that you can. Eg. just because you triggered Quick Open, it doesn't mean that it's open; you must wait for the widget to be in the DOM and for its input field to be the active element. +- Beware of **timing**. You need to read from or write to the DOM... but is it the right time to do that? Can you 100% guarantee that that `input` box will be visible at that point in time? Or are you just hoping that it will be so? Hope is your worst enemy in UI tests. Example: just because you triggered Quick Open with `F1`, it doesn't mean that it's open and you can just start typing; you must first wait for the input element to be in the DOM as well as be the current active element. -- Beware of **waiting**. **Never** wait longer than a couple of seconds for anything, unless it's justified. Think of it as a human using Code. Would a human take 10 minutes to run through the Search viewlet smoke test? Then, the computer should even be faster. **Don't** use `setTimeout` just because. Think about what you should wait for in the DOM to be ready, then wait for that instead. - -## Common Issues - -### Certain keys don't appear in input boxes (eg: Space) - -This is a **waiting** issue. Everytime you send keys to Code, you must be aware that the keybinding service can handle them. Even if you're sure that input box is focused. - -Here's an example: when opening quick open, focus goes from its list to its input. We used to simply wait for the input to have focus and then send some text to be typed, like `Workbench: Show Editor`; yet, only `Workbench:ShowEditor` would be rendered in the input box. This happened due to the fact that the [`ListService` takes 50ms to unset the context key which indicates a list is focused](https://github.com/Microsoft/vscode/blob/c8dee4c016d3a3d475011106e04d8e394d9f138c/src/vs/platform/list/browser/listService.ts#L59). The fix was to [wait 50ms as well on the smoke test](https://github.com/Microsoft/vscode/blob/b82fa8dcb06bbf9c85c1502d0d43322e2e9d1a59/test/smoke/src/areas/quickopen/quickopen.ts#L65). - -### I type in a Monaco editor instance, but the text doesn't appear to be there - -This is a **waiting** issue. When you type in a Monaco editor instance, you're really typing in a `textarea`. The `textarea` is then polled for its contents, then the editor model gets updated and finally the editor view gets updated. It's a good idea to always wait for the text to appear rendered in the editor after you type in it. - -### I type in a Monaco editor instance, but the text appears scrambled - -This is an issue which is **not yet fixed**. Unfortunately this seems to happen whenever the CPU load of the system is high. Rerunning the test will often result in a successful outcome. \ No newline at end of file +- Beware of **waiting**. **Never** wait longer than a couple of seconds for anything, unless it's justified. Think of it as a human using Code. Would a human take 10 minutes to run through the Search viewlet smoke test? Then, the computer should even be faster. **Don't** use `setTimeout` just because. Think about what you should wait for in the DOM to be ready and wait for that instead. diff --git a/test/smoke/package.json b/test/smoke/package.json index 97d8c0b3c3..e033db34da 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -3,8 +3,13 @@ "version": "0.1.0", "main": "./src/main.js", "scripts": { - "postinstall": "tsc", - "watch": "tsc --watch", + "postinstall": "npm run compile", + "compile": "npm run copy-driver && npm run copy-driver-definition && tsc", + "watch": "concurrently \"npm run watch-driver\" \"npm run watch-driver-definition\" \"tsc --watch\"", + "copy-driver": "cpx src/vscode/driver.js out/vscode", + "watch-driver": "cpx src/vscode/driver.js out/vscode -w", + "copy-driver-definition": "node tools/copy-driver-definition.js", + "watch-driver-definition": "watch \"node tools/copy-driver-definition.js\" ../../src/vs/platform/driver/common", "mocha": "mocha" }, "devDependencies": { @@ -15,6 +20,8 @@ "@types/node": "8.0.33", "@types/rimraf": "2.0.2", "@types/webdriverio": "4.6.1", + "concurrently": "^3.5.1", + "cpx": "^1.5.0", "electron": "1.7.7", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", @@ -22,9 +29,9 @@ "ncp": "^2.0.0", "portastic": "^1.0.1", "rimraf": "^2.6.1", - "spectron": "^3.7.2", "strip-json-comments": "^2.0.1", "tmp": "0.0.33", - "typescript": "2.5.2" + "typescript": "2.5.2", + "watch": "^1.0.2" } -} \ No newline at end of file +} diff --git a/test/smoke/src/application.ts b/test/smoke/src/application.ts new file mode 100644 index 0000000000..66ef250570 --- /dev/null +++ b/test/smoke/src/application.ts @@ -0,0 +1,146 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Workbench } from './areas/workbench/workbench'; +import * as fs from 'fs'; +import * as cp from 'child_process'; +import { Code, spawn, SpawnOptions } from './vscode/code'; +import { Logger } from './logger'; + +export enum Quality { + Dev, + Insiders, + Stable +} + +export interface ApplicationOptions extends SpawnOptions { + quality: Quality; + workspacePath: string; + workspaceFilePath: string; + waitTime: number; +} + +export class Application { + + private _code: Code | undefined; + private _workbench: Workbench; + private keybindings: any[]; + + constructor(private options: ApplicationOptions) { } + + get quality(): Quality { + return this.options.quality; + } + + get code(): Code { + return this._code!; + } + + get workbench(): Workbench { + return this._workbench; + } + + get logger(): Logger { + return this.options.logger; + } + + get workspacePath(): string { + return this.options.workspacePath; + } + + get extensionsPath(): string { + return this.options.extensionsPath; + } + + get userDataPath(): string { + return this.options.userDataDir; + } + + get workspaceFilePath(): string { + return this.options.workspaceFilePath; + } + + async start(): Promise { + await this._start(); + await this.code.waitForElement('.explorer-folders-view'); + await this.code.waitForActiveElement(`.editor-container[id="workbench.editor.walkThroughPart"] > div > div[tabIndex="0"]`); + } + + async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise { + await this.stop(); + await new Promise(c => setTimeout(c, 1000)); + await this._start(options.workspaceOrFolder, options.extraArgs); + } + + private async _start(workspaceOrFolder = this.options.workspacePath, extraArgs: string[] = []): Promise { + await this.retrieveKeybindings(); + cp.execSync('git checkout .', { cwd: this.options.workspacePath }); + await this.startApplication(workspaceOrFolder, extraArgs); + await this.checkWindowReady(); + } + + async reload(): Promise { + this.code.reload() + .catch(err => null); // ignore the connection drop errors + + // needs to be enough to propagate the 'Reload Window' command + await new Promise(c => setTimeout(c, 1500)); + await this.checkWindowReady(); + } + + async stop(): Promise { + if (this._code) { + this._code.dispose(); + this._code = undefined; + } + } + + async capturePage(): Promise { + return this.code.capturePage(); + } + + private async startApplication(workspaceOrFolder: string, extraArgs: string[] = []): Promise { + this._code = await spawn({ + codePath: this.options.codePath, + workspacePath: workspaceOrFolder, + userDataDir: this.options.userDataDir, + extensionsPath: this.options.extensionsPath, + logger: this.options.logger, + extraArgs + }); + + this._workbench = new Workbench(this._code, this.keybindings, this.userDataPath); + } + + private async checkWindowReady(): Promise { + if (!this.code) { + console.error('No code instance found'); + return; + } + + await this.code.waitForWindowIds(ids => ids.length > 0); + await this.code.waitForElement('.monaco-workbench'); + + // wait a bit, since focus might be stolen off widgets + // as soon as they open (eg quick open) + await new Promise(c => setTimeout(c, 500)); + } + + private retrieveKeybindings(): Promise { + return new Promise((c, e) => { + fs.readFile(process.env.VSCODE_KEYBINDINGS_PATH as string, 'utf8', (err, data) => { + if (err) { + throw err; + } + try { + this.keybindings = JSON.parse(data); + c(); + } catch (e) { + throw new Error(`Error parsing keybindings JSON: ${e}`); + } + }); + }); + } +} diff --git a/test/smoke/src/areas/activitybar/activityBar.ts b/test/smoke/src/areas/activitybar/activityBar.ts index 46b99ce440..1e19856ba1 100644 --- a/test/smoke/src/areas/activitybar/activityBar.ts +++ b/test/smoke/src/areas/activitybar/activityBar.ts @@ -3,8 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Element } from 'webdriverio'; -import { SpectronApplication } from '../../spectron/application'; +import { Code } from '../../vscode/code'; export enum ActivityBarPosition { LEFT = 0, @@ -13,11 +12,9 @@ export enum ActivityBarPosition { export class ActivityBar { - constructor(private spectron: SpectronApplication) { - // noop - } + constructor(private code: Code) { } - public async getActivityBar(position: ActivityBarPosition): Promise { + async waitForActivityBar(position: ActivityBarPosition): Promise { let positionClass: string; if (position === ActivityBarPosition.LEFT) { @@ -28,6 +25,6 @@ export class ActivityBar { throw new Error('No such position for activity bar defined.'); } - return this.spectron.client.waitForElement(`.part.activitybar.${positionClass}`); + await this.code.waitForElement(`.part.activitybar.${positionClass}`); } } \ No newline at end of file diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts index 8943bf053d..cf87d3c5cd 100644 --- a/test/smoke/src/areas/css/css.test.ts +++ b/test/smoke/src/areas/css/css.test.ts @@ -3,55 +3,44 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; import { ProblemSeverity, Problems } from '../problems/problems'; export function setup() { describe('CSS', () => { - before(function () { - this.app.suiteName = 'CSS'; - }); - it('verifies quick outline', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('style.css'); - await app.workbench.editor.openOutline(); + await app.workbench.quickopen.openQuickOutline(); await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 2); }); it('verifies warnings for the empty rule', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('style.css'); await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); - let warning = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING)); - await app.screenCapturer.capture('CSS Warning in editor'); - assert.ok(warning, `Warning squiggle is not shown in 'style.css'.`); + await app.code.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING)); await app.workbench.problems.showProblemsView(); - warning = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING)); - await app.screenCapturer.capture('CSS Warning in problems view'); - assert.ok(warning, 'Warning does not appear in Problems view.'); + await app.code.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING)); await app.workbench.problems.hideProblemsView(); }); it('verifies that warning becomes an error once setting changed', async function () { - const app = this.app as SpectronApplication; + // settings might take a while to update? + this.timeout(40000); + + const app = this.app as Application; await app.workbench.settingsEditor.addUserSetting('css.lint.emptyRules', '"error"'); await app.workbench.quickopen.openFile('style.css'); - await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); - let error = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR)); - await app.screenCapturer.capture('CSS Error in editor'); - assert.ok(error, `Warning squiggle is not shown in 'style.css'.`); + await app.code.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR)); - const problems = new Problems(app); + const problems = new Problems(app.code, app.workbench); await problems.showProblemsView(); - error = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR)); - await app.screenCapturer.capture('CSS Error in probles view'); - assert.ok(error, 'Warning does not appear in Problems view.'); + await app.code.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR)); await problems.hideProblemsView(); }); }); diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index a13c79840d..faa9707838 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -8,17 +8,12 @@ import * as http from 'http'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Debug', () => { - before(async function () { - const app = this.app as SpectronApplication; - app.suiteName = 'Debug'; - }); - it('configure launch json', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.debug.openDebugViewlet(); await app.workbench.quickopen.openFile('app.js'); @@ -31,7 +26,6 @@ export function setup() { fs.writeFileSync(launchJsonPath, JSON.stringify(config, undefined, 4), 'utf8'); await app.workbench.editor.waitForEditorContents('launch.json', contents => /"protocol": "inspector"/.test(contents)); - await app.screenCapturer.capture('launch.json file'); assert.equal(config.configurations[0].request, 'launch'); assert.equal(config.configurations[0].type, 'node'); @@ -43,66 +37,61 @@ export function setup() { }); it('breakpoints', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('index.js'); await app.workbench.debug.setBreakpointOnLine(6); - await app.screenCapturer.capture('breakpoints are set'); }); let port: number; it('start debugging', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; + + // TODO@isidor + await new Promise(c => setTimeout(c, 100)); port = await app.workbench.debug.startDebugging(); - await app.screenCapturer.capture('debugging has started'); await new Promise((c, e) => { const request = http.get(`http://localhost:${port}`); request.on('error', e); app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, 'looking for index.js and line 6').then(c, e); }); - - await app.screenCapturer.capture('debugging is paused'); }); it('focus stack frames and variables', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; - await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables'); + await app.workbench.debug.waitForVariableCount(4); await app.workbench.debug.focusStackFrame('layer.js', 'looking for layer.js'); - await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 5, 'there should be 5 local variables'); + await app.workbench.debug.waitForVariableCount(5); await app.workbench.debug.focusStackFrame('route.js', 'looking for route.js'); - await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 3, 'there should be 3 local variables'); + await app.workbench.debug.waitForVariableCount(3); await app.workbench.debug.focusStackFrame('index.js', 'looking for index.js'); - await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables'); + await app.workbench.debug.waitForVariableCount(4); }); it('stepOver, stepIn, stepOut', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.debug.stepIn(); - await app.screenCapturer.capture('debugging has stepped in'); const first = await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js', 'looking for response.js'); await app.workbench.debug.stepOver(); - await app.screenCapturer.capture('debugging has stepped over'); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js' && sf.lineNumber === first.lineNumber + 1, `looking for response.js and line ${first.lineNumber + 1}`); await app.workbench.debug.stepOut(); - await app.screenCapturer.capture('debugging has stepped out'); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 7, `looking for index.js and line 7`); }); it('continue', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.debug.continue(); - await app.screenCapturer.capture('debugging has continued'); await new Promise((c, e) => { const request = http.get(`http://localhost:${port}`); @@ -110,20 +99,18 @@ export function setup() { app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, `looking for index.js and line 6`).then(c, e); }); - await app.screenCapturer.capture('debugging is paused'); }); it('debug console', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.debug.waitForReplCommand('2 + 2', r => r === '4'); }); it('stop debugging', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.debug.stopDebugging(); - await app.screenCapturer.capture('debugging has stopped'); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index 6ed7388057..717bea0c92 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -3,13 +3,16 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; +import { Commands } from '../workbench/workbench'; +import { Code, findElement } from '../../vscode/code'; +import { Editors } from '../editor/editors'; +import { Editor } from '../editor/editor'; +import { IElement } from '../../vscode/driver'; const VIEWLET = 'div[id="workbench.view.debug"]'; const DEBUG_VIEW = `${VIEWLET} .debug-view-content`; const CONFIGURE = `div[id="workbench.parts.sidebar"] .actions-container .configure`; -const START = `.icon[title="Start Debugging"]`; const STOP = `.debug-actions-widget .debug-action.stop`; const STEP_OVER = `.debug-actions-widget .debug-action.step-over`; const STEP_IN = `.debug-actions-widget .debug-action.step-into`; @@ -20,152 +23,120 @@ const BREAKPOINT_GLYPH = '.debug-breakpoint'; const PAUSE = `.debug-actions-widget .debug-action.pause`; const DEBUG_STATUS_BAR = `.statusbar.debugging`; const NOT_DEBUG_STATUS_BAR = `.statusbar:not(debugging)`; -const TOOLBAR_HIDDEN = `.debug-actions-widget.builder-hidden`; +const TOOLBAR_HIDDEN = `.debug-actions-widget.monaco-builder-hidden`; const STACK_FRAME = `${VIEWLET} .monaco-tree-row .stack-frame`; +const SPECIFIC_STACK_FRAME = filename => `${STACK_FRAME} .file[title$="${filename}"]`; const VARIABLE = `${VIEWLET} .debug-variables .monaco-tree-row .expression`; -const CONSOLE_OUTPUT = `.repl .output.expression`; +const CONSOLE_OUTPUT = `.repl .output.expression .value`; const CONSOLE_INPUT_OUTPUT = `.repl .input-output-pair .output.expression .value`; const REPL_FOCUSED = '.repl-input-wrapper .monaco-editor textarea'; export interface IStackFrame { - id: string; name: string; lineNumber: number; } +function toStackFrame(element: IElement): IStackFrame { + const name = findElement(element, e => /\bfile-name\b/.test(e.className))!; + const line = findElement(element, e => /\bline-number\b/.test(e.className))!; + const lineNumber = line.textContent ? parseInt(line.textContent.split(':').shift() || '0') : 0; + + return { + name: name.textContent || '', + lineNumber + }; +} + export class Debug extends Viewlet { - constructor(spectron: SpectronApplication) { - super(spectron); + constructor(code: Code, private commands: Commands, private editors: Editors, private editor: Editor) { + super(code); } async openDebugViewlet(): Promise { - await this.spectron.runCommand('workbench.view.debug'); - await this.spectron.client.waitForElement(DEBUG_VIEW); + await this.commands.runCommand('workbench.view.debug'); + await this.code.waitForElement(DEBUG_VIEW); } async configure(): Promise { - await this.spectron.client.waitAndClick(CONFIGURE); - await this.spectron.workbench.waitForEditorFocus('launch.json'); + await this.code.waitAndClick(CONFIGURE); + await this.editors.waitForEditorFocus('launch.json'); } async setBreakpointOnLine(lineNumber: number): Promise { - await this.spectron.client.waitForElement(`${GLYPH_AREA}(${lineNumber})`); - await this.spectron.client.leftClick(`${GLYPH_AREA}(${lineNumber})`, 5, 5); - await this.spectron.client.waitForElement(BREAKPOINT_GLYPH); + await this.code.waitForElement(`${GLYPH_AREA}(${lineNumber})`); + await this.code.waitAndClick(`${GLYPH_AREA}(${lineNumber})`, 5, 5); + await this.code.waitForElement(BREAKPOINT_GLYPH); } async startDebugging(): Promise { - await this.spectron.client.waitAndClick(START); - await this.spectron.client.waitForElement(PAUSE); - await this.spectron.client.waitForElement(DEBUG_STATUS_BAR); + await this.commands.runCommand('workbench.action.debug.start'); + await this.code.waitForElement(PAUSE); + await this.code.waitForElement(DEBUG_STATUS_BAR); const portPrefix = 'Port: '; - await this.spectron.client.waitFor(async () => { - const output = await this.getConsoleOutput(); - return output.join(''); - }, text => !!text && text.indexOf(portPrefix) >= 0); - const output = await this.getConsoleOutput(); - const lastOutput = output.pop(); + + const output = await this.waitForOutput(output => output.some(line => line.indexOf(portPrefix) >= 0)); + const lastOutput = output.filter(line => line.indexOf(portPrefix) >= 0)[0]; return lastOutput ? parseInt(lastOutput.substr(portPrefix.length)) : 3000; } async stepOver(): Promise { - await this.spectron.client.waitAndClick(STEP_OVER); + await this.code.waitAndClick(STEP_OVER); } async stepIn(): Promise { - await this.spectron.client.waitAndClick(STEP_IN); + await this.code.waitAndClick(STEP_IN); } async stepOut(): Promise { - await this.spectron.client.waitAndClick(STEP_OUT); + await this.code.waitAndClick(STEP_OUT); } async continue(): Promise { - await this.spectron.client.waitAndClick(CONTINUE); + await this.code.waitAndClick(CONTINUE); await this.waitForStackFrameLength(0); } async stopDebugging(): Promise { - await this.spectron.client.waitAndClick(STOP); - await this.spectron.client.waitForElement(TOOLBAR_HIDDEN); - await this.spectron.client.waitForElement(NOT_DEBUG_STATUS_BAR); + await this.code.waitAndClick(STOP); + await this.code.waitForElement(TOOLBAR_HIDDEN); + await this.code.waitForElement(NOT_DEBUG_STATUS_BAR); } async waitForStackFrame(func: (stackFrame: IStackFrame) => boolean, message: string): Promise { - return await this.spectron.client.waitFor(async () => { - const stackFrames = await this.getStackFrames(); - return stackFrames.filter(func)[0]; - }, void 0, `Waiting for Stack Frame: ${message}`); + const elements = await this.code.waitForElements(STACK_FRAME, true, elements => elements.some(e => func(toStackFrame(e)))); + return elements.map(toStackFrame).filter(s => func(s))[0]; } async waitForStackFrameLength(length: number): Promise { - return await this.spectron.client.waitFor(() => this.getStackFrames(), stackFrames => stackFrames.length === length); + await this.code.waitForElements(STACK_FRAME, false, result => result.length === length); } async focusStackFrame(name: string, message: string): Promise { - const stackFrame = await this.waitForStackFrame(sf => sf.name === name, message); - await this.spectron.client.spectron.client.elementIdClick(stackFrame.id); - await this.spectron.workbench.waitForTab(name); + await this.code.waitAndClick(SPECIFIC_STACK_FRAME(name)); + await this.editors.waitForTab(name); } async waitForReplCommand(text: string, accept: (result: string) => boolean): Promise { - await this.spectron.workbench.quickopen.runCommand('Debug: Focus Debug Console'); - await this.spectron.client.waitForActiveElement(REPL_FOCUSED); - await this.spectron.client.setValue(REPL_FOCUSED, text); + await this.commands.runCommand('Debug: Focus Debug Console'); + await this.code.waitForActiveElement(REPL_FOCUSED); + await this.code.waitForSetValue(REPL_FOCUSED, text); // Wait for the keys to be picked up by the editor model such that repl evalutes what just got typed - await this.spectron.workbench.editor.waitForEditorContents('debug:input', s => s.indexOf(text) >= 0); - await this.spectron.client.keys(['Enter', 'NULL']); - await this.spectron.client.waitForElement(CONSOLE_INPUT_OUTPUT); - await this.spectron.client.waitFor(async () => { - const result = await this.getConsoleOutput(); - return result[result.length - 1] || ''; - }, accept); + await this.editor.waitForEditorContents('debug:input', s => s.indexOf(text) >= 0); + await this.code.dispatchKeybinding('enter'); + await this.code.waitForElement(CONSOLE_INPUT_OUTPUT); + await this.waitForOutput(output => accept(output[output.length - 1] || '')); } - async getLocalVariableCount(): Promise { - return await this.spectron.webclient.selectorExecute(VARIABLE, div => (Array.isArray(div) ? div : [div]).length); + async waitForVariableCount(count: number): Promise { + await this.code.waitForElements(VARIABLE, false, els => els.length === count); } - async getStackFramesLength(): Promise { - const stackFrames = await this.getStackFrames(); - return stackFrames.length; - } - - private async getStackFrames(): Promise { - const result = await this.spectron.webclient.selectorExecute(STACK_FRAME, - div => (Array.isArray(div) ? div : [div]).map(element => { - const name = element.querySelector('.file-name') as HTMLElement; - const line = element.querySelector('.line-number') as HTMLElement; - const lineNumber = line.textContent ? parseInt(line.textContent.split(':').shift() || '0') : 0; - - return { - name: name.textContent, - lineNumber, - element - }; - }) - ); - - if (!Array.isArray(result)) { - return []; - } - - return result - .map(({ name, lineNumber, element }) => ({ name, lineNumber, id: element.ELEMENT })); - } - - private async getConsoleOutput(): Promise { - const result = await this.spectron.webclient.selectorExecute(CONSOLE_OUTPUT, - div => (Array.isArray(div) ? div : [div]).map(element => { - const value = element.querySelector('.value') as HTMLElement; - return value && value.textContent; - }).filter(line => !!line) - ); - - return result; + private async waitForOutput(fn: (output: string[]) => boolean): Promise { + const elements = await this.code.waitForElements(CONSOLE_OUTPUT, false, elements => fn(elements.map(e => e.textContent))); + return elements.map(e => e.textContent); } } diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 35a78c1ff7..4c97f2efea 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -3,27 +3,23 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Editor', () => { - before(function () { - this.app.suiteName = 'Editor'; - }); - it('shows correct quick outline', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('www'); - await app.workbench.editor.openOutline(); + await app.workbench.quickopen.openQuickOutline(); await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6); }); it(`finds 'All References' to 'app'`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('www'); - const references = await app.workbench.editor.findReferences('app', 7); + const references = await app.workbench.editor.findReferences('www', 'app', 7); await references.waitForReferencesCountInTitle(3); await references.waitForReferencesCount(3); @@ -31,11 +27,10 @@ export function setup() { }); it(`renames local 'app' variable`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('www'); await app.workbench.editor.rename('www', 7, 'app', 'newApp'); await app.workbench.editor.waitForEditorContents('www', contents => contents.indexOf('newApp') > -1); - await app.screenCapturer.capture('Rename result'); }); // it('folds/unfolds the code correctly', async function () { @@ -55,19 +50,19 @@ export function setup() { // }); it(`verifies that 'Go To Definition' works`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('app.js'); - await app.workbench.editor.gotoDefinition('express', 11); + await app.workbench.editor.gotoDefinition('app.js', 'express', 11); - await app.workbench.waitForActiveTab('index.d.ts'); + await app.workbench.editors.waitForActiveTab('index.d.ts'); }); it(`verifies that 'Peek Definition' works`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('app.js'); - const peek = await app.workbench.editor.peekDefinition('express', 11); + const peek = await app.workbench.editor.peekDefinition('app.js', 'express', 11); await peek.waitForFile('index.d.ts'); }); diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index f676ff120f..66ffb4446d 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -3,192 +3,131 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; -import { QuickOutline } from './quickoutline'; import { References } from './peek'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; const RENAME_BOX = '.monaco-editor .monaco-editor.rename-box'; const RENAME_INPUT = `${RENAME_BOX} .rename-input`; +const EDITOR = filename => `.monaco-editor[data-uri$="${filename}"]`; +const VIEW_LINES = filename => `${EDITOR(filename)} .view-lines`; +const LINE_NUMBERS = filename => `${EDITOR(filename)} .margin .margin-view-overlays .line-numbers`; export class Editor { - private static readonly VIEW_LINES = '.monaco-editor .view-lines'; - private static readonly LINE_NUMBERS = '.monaco-editor .margin .margin-view-overlays .line-numbers'; private static readonly FOLDING_EXPANDED = '.monaco-editor .margin .margin-view-overlays>:nth-child(${INDEX}) .folding'; private static readonly FOLDING_COLLAPSED = `${Editor.FOLDING_EXPANDED}.collapsed`; - constructor(private spectron: SpectronApplication) { - } + constructor(private code: Code, private commands: Commands) { } - async openOutline(): Promise { - const outline = new QuickOutline(this.spectron); - await outline.open(); - return outline; - } - - async findReferences(term: string, line: number): Promise { - await this.clickOnTerm(term, line); - await this.spectron.workbench.quickopen.runCommand('Find All References'); - const references = new References(this.spectron); + async findReferences(filename: string, term: string, line: number): Promise { + await this.clickOnTerm(filename, term, line); + await this.commands.runCommand('Find All References'); + const references = new References(this.code); await references.waitUntilOpen(); return references; } async rename(filename: string, line: number, from: string, to: string): Promise { - await this.clickOnTerm(from, line); - await this.spectron.workbench.quickopen.runCommand('Rename Symbol'); + await this.clickOnTerm(filename, from, line); + await this.commands.runCommand('Rename Symbol'); - await this.spectron.client.waitForActiveElement(RENAME_INPUT); - await this.spectron.client.setValue(RENAME_INPUT, to); + await this.code.waitForActiveElement(RENAME_INPUT); + await this.code.waitForSetValue(RENAME_INPUT, to); - await this.spectron.client.keys(['Enter', 'NULL']); + await this.code.dispatchKeybinding('enter'); } - async gotoDefinition(term: string, line: number): Promise { - await this.clickOnTerm(term, line); - await this.spectron.workbench.quickopen.runCommand('Go to Definition'); + async gotoDefinition(filename: string, term: string, line: number): Promise { + await this.clickOnTerm(filename, term, line); + await this.commands.runCommand('Go to Definition'); } - async peekDefinition(term: string, line: number): Promise { - await this.clickOnTerm(term, line); - await this.spectron.workbench.quickopen.runCommand('Peek Definition'); - const peek = new References(this.spectron); + async peekDefinition(filename: string, term: string, line: number): Promise { + await this.clickOnTerm(filename, term, line); + await this.commands.runCommand('Peek Definition'); + const peek = new References(this.code); await peek.waitUntilOpen(); return peek; } - async waitForHighlightingLine(line: number): Promise { - const currentLineIndex = await this.getViewLineIndex(line); + async waitForHighlightingLine(filename: string, line: number): Promise { + const currentLineIndex = await this.getViewLineIndex(filename, line); if (currentLineIndex) { - await this.spectron.client.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`); + await this.code.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`); return; } throw new Error('Cannot find line ' + line); } - async getSelector(term: string, line: number): Promise { - const lineIndex = await this.getViewLineIndex(line); - const classNames = await this.spectron.client.waitFor(() => this.getClassSelectors(term, lineIndex), classNames => classNames && !!classNames.length, 'Getting class names for editor lines'); - return `${Editor.VIEW_LINES}>:nth-child(${lineIndex}) span span.${classNames[0]}`; + private async getSelector(filename: string, term: string, line: number): Promise { + const lineIndex = await this.getViewLineIndex(filename, line); + const classNames = await this.getClassSelectors(filename, term, lineIndex); + + return `${VIEW_LINES(filename)}>:nth-child(${lineIndex}) span span.${classNames[0]}`; } - async foldAtLine(line: number): Promise { - const lineIndex = await this.getViewLineIndex(line); - await this.spectron.client.waitAndClick(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); - await this.spectron.client.waitForElement(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); + async foldAtLine(filename: string, line: number): Promise { + const lineIndex = await this.getViewLineIndex(filename, line); + await this.code.waitAndClick(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); + await this.code.waitForElement(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); } - async unfoldAtLine(line: number): Promise { - const lineIndex = await this.getViewLineIndex(line); - await this.spectron.client.waitAndClick(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); - await this.spectron.client.waitForElement(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); + async unfoldAtLine(filename: string, line: number): Promise { + const lineIndex = await this.getViewLineIndex(filename, line); + await this.code.waitAndClick(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); + await this.code.waitForElement(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); } - async waitUntilHidden(line: number): Promise { - await this.spectron.client.waitFor(() => this.getViewLineIndexWithoutWait(line), lineNumber => lineNumber === undefined, 'Waiting until line number is hidden'); + private async clickOnTerm(filename: string, term: string, line: number): Promise { + const selector = await this.getSelector(filename, term, line); + await this.code.waitAndClick(selector); } - async waitUntilShown(line: number): Promise { - await this.getViewLineIndex(line); - } + async waitForEditorFocus(filename: string, lineNumber: number, selectorPrefix = ''): Promise { + const editor = [selectorPrefix || '', EDITOR(filename)].join(' '); + const line = `${editor} .view-lines > .view-line:nth-child(${lineNumber})`; + const textarea = `${editor} textarea`; - async clickOnTerm(term: string, line: number): Promise { - const selector = await this.getSelector(term, line); - await this.spectron.client.waitAndClick(selector); + await this.code.waitAndClick(line, 0, 0); + await this.code.waitForActiveElement(textarea); } async waitForTypeInEditor(filename: string, text: string, selectorPrefix = ''): Promise { - const editor = [ - selectorPrefix || '', - `.monaco-editor[data-uri$="${filename}"]` - ].join(' '); + const editor = [selectorPrefix || '', EDITOR(filename)].join(' '); - await this.spectron.client.element(editor); + await this.code.waitForElement(editor); const textarea = `${editor} textarea`; - await this.spectron.client.waitForActiveElement(textarea); + await this.code.waitForActiveElement(textarea); - // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 - await this.spectron.client.spectron.client.selectorExecute(textarea, (elements, text) => { - const textarea = (Array.isArray(elements) ? elements : [elements])[0] as HTMLTextAreaElement; - const start = textarea.selectionStart; - const newStart = start + text.length; - const value = textarea.value; - const newValue = value.substr(0, start) + text + value.substr(start); - - textarea.value = newValue; - textarea.setSelectionRange(newStart, newStart); - - const event = new Event('input', { 'bubbles': true, 'cancelable': true }); - textarea.dispatchEvent(event); - }, text); + await this.code.waitForTypeInEditor(textarea, text); await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } async waitForEditorContents(filename: string, accept: (contents: string) => boolean, selectorPrefix = ''): Promise { - const selector = [ - selectorPrefix || '', - `.monaco-editor[data-uri$="${filename}"] .view-lines` - ].join(' '); - - return this.spectron.client.waitForTextContent(selector, undefined, c => accept(c.replace(/\u00a0/g, ' '))); + const selector = [selectorPrefix || '', `${EDITOR(filename)} .view-lines`].join(' '); + return this.code.waitForTextContent(selector, undefined, c => accept(c.replace(/\u00a0/g, ' '))); } - async waitForActiveEditor(filename: string): Promise { - const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`; - return this.spectron.client.waitForActiveElement(selector); + private async getClassSelectors(filename: string, term: string, viewline: number): Promise { + const elements = await this.code.waitForElements(`${VIEW_LINES(filename)}>:nth-child(${viewline}) span span`, false, els => els.some(el => el.textContent === term)); + const { className } = elements.filter(r => r.textContent === term)[0]; + return className.split(/\s/g); } - // async waitForActiveEditorFirstLineText(filename: string): Promise { - // const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`; - // const result = await this.spectron.client.waitFor( - // () => this.spectron.client.spectron.client.execute(s => { - // if (!document.activeElement.matches(s)) { - // return undefined; - // } + private async getViewLineIndex(filename: string, line: number): Promise { + const elements = await this.code.waitForElements(LINE_NUMBERS(filename), false, els => { + return els.some(el => el.textContent === `${line}`); + }); - // let element: Element | null = document.activeElement; - // while (element && !/monaco-editor/.test(element.className) && element !== document.body) { - // element = element.parentElement; - // } - - // if (element && /monaco-editor/.test(element.className)) { - // const firstLine = element.querySelector('.view-lines span span:nth-child(1)'); - - // if (firstLine) { - // return (firstLine.textContent || '').replace(/\u00a0/g, ' '); // DAMN - // } - // } - - // return undefined; - // }, selector), - // r => typeof r.value === 'string', - // `wait for active editor first line: ${selector}` - // ); - - // return result.value; - // } - - private async getClassSelectors(term: string, viewline: number): Promise { - const result: { text: string, className: string }[] = await this.spectron.webclient.selectorExecute(`${Editor.VIEW_LINES}>:nth-child(${viewline}) span span`, - elements => (Array.isArray(elements) ? elements : [elements]) - .map(element => ({ text: element.textContent, className: element.className }))); - return result.filter(r => r.text === term).map(({ className }) => className); - } - - private async getViewLineIndex(line: number): Promise { - return await this.spectron.client.waitFor(() => this.getViewLineIndexWithoutWait(line), void 0, 'Getting line index'); - } - - private async getViewLineIndexWithoutWait(line: number): Promise { - const lineNumbers = await this.spectron.webclient.selectorExecute(Editor.LINE_NUMBERS, - elements => (Array.isArray(elements) ? elements : [elements]).map(element => element.textContent)); - for (let index = 0; index < lineNumbers.length; index++) { - if (lineNumbers[index] === `${line}`) { + for (let index = 0; index < elements.length; index++) { + if (elements[index].textContent === `${line}`) { return index + 1; } } - return undefined; + + throw new Error('Line not found'); } } \ No newline at end of file diff --git a/test/smoke/src/areas/editor/editors.ts b/test/smoke/src/areas/editor/editors.ts new file mode 100644 index 0000000000..b3d68d22d3 --- /dev/null +++ b/test/smoke/src/areas/editor/editors.ts @@ -0,0 +1,44 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; + +export class Editors { + + constructor(private code: Code, private commands: Commands) { } + + async saveOpenedFile(): Promise { + await this.commands.runCommand('workbench.action.files.save'); + } + + async selectTab(tabName: string, untitled: boolean = false): Promise { + await this.code.waitAndClick(`.tabs-container div.tab[aria-label="${tabName}, tab"]`); + await this.waitForEditorFocus(tabName, untitled); + } + + async waitForActiveEditor(filename: string): Promise { + const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`; + return this.code.waitForActiveElement(selector); + } + + async waitForEditorFocus(fileName: string, untitled: boolean = false): Promise { + await this.waitForActiveTab(fileName); + await this.waitForActiveEditor(fileName); + } + + async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { + await this.code.waitForElement(`.tabs-container div.tab.active${isDirty ? '.dirty' : ''}[aria-selected="true"][aria-label="${fileName}, tab"]`); + } + + async waitForTab(fileName: string, isDirty: boolean = false): Promise { + await this.code.waitForElement(`.tabs-container div.tab${isDirty ? '.dirty' : ''}[aria-label="${fileName}, tab"]`); + } + + async newUntitledFile(): Promise { + await this.commands.runCommand('workbench.action.files.newUntitledFile'); + await this.waitForEditorFocus('Untitled-1', true); + } +} \ No newline at end of file diff --git a/test/smoke/src/areas/editor/peek.ts b/test/smoke/src/areas/editor/peek.ts index 0d22579c51..1c9a59f15e 100644 --- a/test/smoke/src/areas/editor/peek.ts +++ b/test/smoke/src/areas/editor/peek.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Code } from '../../vscode/code'; export class References { @@ -12,30 +12,41 @@ export class References { private static readonly REFERENCES_TITLE_COUNT = `${References.REFERENCES_WIDGET} .head .peekview-title .meta`; private static readonly REFERENCES = `${References.REFERENCES_WIDGET} .body .ref-tree.inline .monaco-tree-row .reference`; - constructor(private spectron: SpectronApplication) { + constructor(private code: Code) { } + + async waitUntilOpen(): Promise { + await this.code.waitForElement(References.REFERENCES_WIDGET); } - public async waitUntilOpen(): Promise { - await this.spectron.client.waitForElement(References.REFERENCES_WIDGET); - } - - public async waitForReferencesCountInTitle(count: number): Promise { - await this.spectron.client.waitForText(References.REFERENCES_TITLE_COUNT, void 0, titleCount => { + async waitForReferencesCountInTitle(count: number): Promise { + await this.code.waitForTextContent(References.REFERENCES_TITLE_COUNT, void 0, titleCount => { const matches = titleCount.match(/\d+/); return matches ? parseInt(matches[0]) === count : false; }); } - public async waitForReferencesCount(count: number): Promise { - await this.spectron.client.waitForElements(References.REFERENCES, result => result && result.length === count); + async waitForReferencesCount(count: number): Promise { + await this.code.waitForElements(References.REFERENCES, false, result => result && result.length === count); } - public async waitForFile(file: string): Promise { - await this.spectron.client.waitForText(References.REFERENCES_TITLE_FILE_NAME, file); + async waitForFile(file: string): Promise { + await this.code.waitForTextContent(References.REFERENCES_TITLE_FILE_NAME, file); } - public async close(): Promise { - await this.spectron.client.keys(['Escape', 'NULL']); - await this.spectron.client.waitForElement(References.REFERENCES_WIDGET, element => !element); + async close(): Promise { + // Sometimes someone else eats up the `Escape` key + let count = 0; + while (true) { + await this.code.dispatchKeybinding('escape'); + + try { + await this.code.waitForElement(References.REFERENCES_WIDGET, el => !el, 10); + return; + } catch (err) { + if (++count > 5) { + throw err; + } + } + } } } \ No newline at end of file diff --git a/test/smoke/src/areas/editor/quickoutline.ts b/test/smoke/src/areas/editor/quickoutline.ts deleted file mode 100644 index 4f61fbafef..0000000000 --- a/test/smoke/src/areas/editor/quickoutline.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../../spectron/application'; -import { QuickOpen } from '../quickopen/quickopen'; - -export class QuickOutline extends QuickOpen { - - constructor(spectron: SpectronApplication) { - super(spectron); - } - - public async open(): Promise { - await this.spectron.client.waitFor(async () => { - await this.spectron.runCommand('workbench.action.gotoSymbol'); - const entry = await this.spectron.client.element('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry'); - if (entry) { - const text = await this.spectron.client.getText('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span'); - if (text !== 'No symbol information for the file') { - return entry; - } - } - await this.closeQuickOpen(); - }, undefined, 'Opening Outline'); - } -} diff --git a/test/smoke/src/areas/explorer/explorer.test.ts b/test/smoke/src/areas/explorer/explorer.test.ts index cd17d05a25..6db58217aa 100644 --- a/test/smoke/src/areas/explorer/explorer.test.ts +++ b/test/smoke/src/areas/explorer/explorer.test.ts @@ -3,16 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Explorer', () => { - before(function () { - this.app.suiteName = 'Explorer'; - }); - it('quick open search produces correct result', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; const expectedNames = [ '.eslintrc.json', 'tasks.json', @@ -25,11 +21,11 @@ export function setup() { await app.workbench.quickopen.openQuickOpen('.js'); await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); - await app.client.keys(['Escape', 'NULL']); + await app.code.dispatchKeybinding('escape'); }); it('quick open respects fuzzy matching', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; const expectedNames = [ 'tasks.json', 'app.js', @@ -38,7 +34,7 @@ export function setup() { await app.workbench.quickopen.openQuickOpen('a.s'); await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); - await app.client.keys(['Escape', 'NULL']); + await app.code.dispatchKeybinding('escape'); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/explorer/explorer.ts b/test/smoke/src/areas/explorer/explorer.ts index 0f29b86297..95effe2b60 100644 --- a/test/smoke/src/areas/explorer/explorer.ts +++ b/test/smoke/src/areas/explorer/explorer.ts @@ -3,33 +3,34 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; - +import { Editors } from '../editor/editors'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; export class Explorer extends Viewlet { private static readonly EXPLORER_VIEWLET = 'div[id="workbench.view.explorer"]'; private static readonly OPEN_EDITORS_VIEW = `${Explorer.EXPLORER_VIEWLET} .split-view-view:nth-child(1) .title`; - constructor(spectron: SpectronApplication) { - super(spectron); + constructor(code: Code, private commands: Commands, private editors: Editors) { + super(code); } - public openExplorerView(): Promise { - return this.spectron.runCommand('workbench.view.explorer'); + openExplorerView(): Promise { + return this.commands.runCommand('workbench.view.explorer'); } - public getOpenEditorsViewTitle(): Promise { - return this.spectron.client.waitForText(Explorer.OPEN_EDITORS_VIEW); + async waitForOpenEditorsViewTitle(fn: (title: string) => boolean): Promise { + await this.code.waitForTextContent(Explorer.OPEN_EDITORS_VIEW, undefined, fn); } - public async openFile(fileName: string): Promise { - await this.spectron.client.doubleClickAndWait(`div[class="monaco-icon-label file-icon ${fileName}-name-file-icon ${this.getExtensionSelector(fileName)} explorer-item"]`); - await this.spectron.workbench.waitForEditorFocus(fileName); + async openFile(fileName: string): Promise { + await this.code.waitAndDoubleClick(`div[class="monaco-icon-label file-icon ${fileName}-name-file-icon ${this.getExtensionSelector(fileName)} explorer-item"]`); + await this.editors.waitForEditorFocus(fileName); } - public getExtensionSelector(fileName: string): string { + getExtensionSelector(fileName: string): string { const extension = fileName.split('.')[1]; if (extension === 'js') { return 'js-ext-file-icon ext-file-icon javascript-lang-file-icon'; diff --git a/test/smoke/src/areas/extensions/extensions.test.ts b/test/smoke/src/areas/extensions/extensions.test.ts index 7b4506d951..fed1ea3386 100644 --- a/test/smoke/src/areas/extensions/extensions.test.ts +++ b/test/smoke/src/areas/extensions/extensions.test.ts @@ -3,17 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { SpectronApplication, Quality } from '../../spectron/application'; +import { Application, Quality } from '../../application'; export function setup() { describe('Extensions', () => { - before(function () { - this.app.suiteName = 'Extensions'; - }); - it(`install and activate vscode-smoketest-check extension`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; if (app.quality === Quality.Dev) { this.skip(); @@ -23,16 +18,12 @@ export function setup() { const extensionName = 'vscode-smoketest-check'; await app.workbench.extensions.openExtensionsViewlet(); - const installed = await app.workbench.extensions.installExtension(extensionName); - assert.ok(installed); + await app.workbench.extensions.installExtension(extensionName); await app.reload(); - await app.workbench.extensions.waitForExtensionsViewlet(); - await app.workbench.quickopen.runCommand('Smoke Test Check'); - - const statusbarText = await app.workbench.statusbar.getStatusbarTextByTitle('smoke test'); - await app.screenCapturer.capture('Statusbar'); - assert.equal(statusbarText, 'VS Code Smoke Test Check'); + await app.workbench.extensions.openExtensionsViewlet(); + await app.workbench.runCommand('Smoke Test Check'); + await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check'); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/extensions/extensions.ts b/test/smoke/src/areas/extensions/extensions.ts index df412303bc..1b839a2dea 100644 --- a/test/smoke/src/areas/extensions/extensions.ts +++ b/test/smoke/src/areas/extensions/extensions.ts @@ -3,40 +3,32 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; const SEARCH_BOX = 'div.extensions-viewlet[id="workbench.view.extensions"] input.search-box'; export class Extensions extends Viewlet { - constructor(spectron: SpectronApplication) { - super(spectron); + constructor(code: Code, private commands: Commands) { + super(code); } async openExtensionsViewlet(): Promise { - await this.spectron.runCommand('workbench.view.extensions'); - await this.waitForExtensionsViewlet(); - } - - async waitForExtensionsViewlet(): Promise { - await this.spectron.client.waitForActiveElement(SEARCH_BOX); + await this.commands.runCommand('workbench.view.extensions'); + await this.code.waitForActiveElement(SEARCH_BOX); } async searchForExtension(name: string): Promise { - await this.spectron.client.click(SEARCH_BOX); - await this.spectron.client.waitForActiveElement(SEARCH_BOX); - await this.spectron.client.setValue(SEARCH_BOX, name); + await this.code.waitAndClick(SEARCH_BOX); + await this.code.waitForActiveElement(SEARCH_BOX); + await this.code.waitForSetValue(SEARCH_BOX, `name:"${name}"`); } - async installExtension(name: string): Promise { + async installExtension(name: string): Promise { await this.searchForExtension(name); - - // we might want to wait for a while longer since the Marketplace can be slow - // a minute should do - await this.spectron.client.waitFor(() => this.spectron.client.click(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.install`), void 0, 'waiting for install button', 600); - - await this.spectron.client.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.reload`); - return true; + await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.install`); + await this.code.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.reload`); } } \ No newline at end of file diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 9dd4a5ab5b..9e4b3a0a0a 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as cp from 'child_process'; -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; const DIFF_EDITOR_LINE_INSERT = '.monaco-diff-editor .editor.modified .line-insert'; const SYNC_STATUSBAR = 'div[id="workbench.parts.statusbar"] .statusbar-entry a[title$="Synchronize Changes"]'; @@ -12,39 +12,40 @@ const SYNC_STATUSBAR = 'div[id="workbench.parts.statusbar"] .statusbar-entry a[t export function setup() { describe('Git', () => { before(async function () { - const app = this.app as SpectronApplication; - app.suiteName = 'Git'; + const app = this.app as Application; + + cp.execSync('git config user.name testuser', { cwd: app.workspacePath }); + cp.execSync('git config user.email monacotools@microsoft.com', { cwd: app.workspacePath }); }); it('reflects working tree changes', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.scm.openSCMViewlet(); await app.workbench.quickopen.openFile('app.js'); await app.workbench.editor.waitForTypeInEditor('app.js', '.foo{}'); - await app.workbench.saveOpenedFile(); + await app.workbench.editors.saveOpenedFile(); await app.workbench.quickopen.openFile('index.jade'); await app.workbench.editor.waitForTypeInEditor('index.jade', 'hello world'); - await app.workbench.saveOpenedFile(); + await app.workbench.editors.saveOpenedFile(); await app.workbench.scm.refreshSCMViewlet(); await app.workbench.scm.waitForChange('app.js', 'Modified'); await app.workbench.scm.waitForChange('index.jade', 'Modified'); - await app.screenCapturer.capture('changes'); }); it('opens diff editor', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.scm.openSCMViewlet(); await app.workbench.scm.openChange('app.js'); - await app.client.waitForElement(DIFF_EDITOR_LINE_INSERT); + await app.code.waitForElement(DIFF_EDITOR_LINE_INSERT); }); it('stages correctly', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.scm.openSCMViewlet(); @@ -58,7 +59,7 @@ export function setup() { }); it(`stages, commits changes and verifies outgoing change`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.scm.openSCMViewlet(); @@ -67,13 +68,13 @@ export function setup() { await app.workbench.scm.waitForChange('app.js', 'Index Modified'); await app.workbench.scm.commit('first commit'); - await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 1↑'); + await app.code.waitForTextContent(SYNC_STATUSBAR, ' 0↓ 1↑'); - await app.workbench.quickopen.runCommand('Git: Stage All Changes'); + await app.workbench.runCommand('Git: Stage All Changes'); await app.workbench.scm.waitForChange('index.jade', 'Index Modified'); await app.workbench.scm.commit('second commit'); - await app.client.waitForText(SYNC_STATUSBAR, ' 0↓ 2↑'); + await app.code.waitForTextContent(SYNC_STATUSBAR, ' 0↓ 2↑'); cp.execSync('git reset --hard origin/master', { cwd: app.workspacePath }); }); diff --git a/test/smoke/src/areas/git/scm.ts b/test/smoke/src/areas/git/scm.ts index c316f7508b..1284c8485f 100644 --- a/test/smoke/src/areas/git/scm.ts +++ b/test/smoke/src/areas/git/scm.ts @@ -3,8 +3,10 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; +import { Commands } from '../workbench/workbench'; +import { IElement } from '../../vscode/driver'; +import { findElement, findElements, Code } from '../../vscode/code'; const VIEWLET = 'div[id="workbench.view.scm"]'; const SCM_INPUT = `${VIEWLET} .scm-editor textarea`; @@ -22,84 +24,61 @@ interface Change { actions: string[]; } +function toChange(element: IElement): Change { + const name = findElement(element, e => /\blabel-name\b/.test(e.className))!; + const type = element.attributes['data-tooltip'] || ''; + + const actionElementList = findElements(element, e => /\baction-label\b/.test(e.className)); + const actions = actionElementList.map(e => e.attributes['title']); + + return { + name: name.textContent || '', + type, + actions + }; +} + + export class SCM extends Viewlet { - constructor(spectron: SpectronApplication) { - super(spectron); + constructor(code: Code, private commands: Commands) { + super(code); } async openSCMViewlet(): Promise { - await this.spectron.runCommand('workbench.view.scm'); - await this.spectron.client.waitForElement(SCM_INPUT); + await this.commands.runCommand('workbench.view.scm'); + await this.code.waitForElement(SCM_INPUT); } - waitForChange(name: string, type?: string): Promise { - return this.spectron.client.waitFor(async () => { - const changes = await this.queryChanges(name, type); - return changes.length; - }, l => l > 0, 'Getting SCM changes') as Promise as Promise; + async waitForChange(name: string, type?: string): Promise { + const func = (change: Change) => change.name === name && (!type || change.type === type); + await this.code.waitForElements(SCM_RESOURCE, true, elements => elements.some(e => func(toChange(e)))); } async refreshSCMViewlet(): Promise { - await this.spectron.client.click(REFRESH_COMMAND); - } - - private async queryChanges(name: string, type?: string): Promise { - const result = await this.spectron.webclient.selectorExecute(SCM_RESOURCE, (div, name, type) => { - return (Array.isArray(div) ? div : [div]) - .map(element => { - const name = element.querySelector('.label-name') as HTMLElement; - const type = element.getAttribute('data-tooltip') || ''; - const actionElementList = element.querySelectorAll('.actions .action-label'); - const actions: string[] = []; - - for (let i = 0; i < actionElementList.length; i++) { - const element = actionElementList.item(i) as HTMLElement; - actions.push(element.title); - } - - return { - name: name.textContent, - type, - actions - }; - }) - .filter(change => { - if (change.name !== name) { - return false; - } - - if (type && (change.type !== type)) { - return false; - } - - return true; - }); - }, name, type); - - return result; + await this.code.waitAndClick(REFRESH_COMMAND); } async openChange(name: string): Promise { - await this.spectron.client.waitAndClick(SCM_RESOURCE_CLICK(name)); + await this.code.waitAndClick(SCM_RESOURCE_CLICK(name)); } async stage(name: string): Promise { - await this.spectron.client.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Stage Changes')); + await this.code.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Stage Changes')); } async stageAll(): Promise { - await this.spectron.client.waitAndClick(SCM_RESOURCE_GROUP_COMMAND_CLICK('Stage All Changes')); + await this.code.waitAndClick(SCM_RESOURCE_GROUP_COMMAND_CLICK('Stage All Changes')); } async unstage(name: string): Promise { - await this.spectron.client.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Unstage Changes')); + await this.code.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Unstage Changes')); } async commit(message: string): Promise { - await this.spectron.client.waitAndClick(SCM_INPUT); - await this.spectron.client.waitForActiveElement(SCM_INPUT); - await this.spectron.client.setValue(SCM_INPUT, message); - await this.spectron.client.waitAndClick(COMMIT_COMMAND); + await this.code.waitAndClick(SCM_INPUT); + await this.code.waitForActiveElement(SCM_INPUT); + await this.code.waitForSetValue(SCM_INPUT, message); + await this.code.waitAndClick(COMMIT_COMMAND); } } \ No newline at end of file diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index 45848f8ed4..bc442b017b 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -3,16 +3,13 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Multiroot', () => { before(async function () { - this.app.suiteName = 'Multiroot'; - - const app = this.app as SpectronApplication; + const app = this.app as Application; // restart with preventing additional windows from restoring // to ensure the window after restart is the multi-root workspace @@ -20,7 +17,7 @@ export function setup() { }); it('shows results from all folders', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openQuickOpen('*.*'); await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 6); @@ -28,10 +25,8 @@ export function setup() { }); it('shows workspace name in title', async function () { - const app = this.app as SpectronApplication; - const title = await app.client.getTitle(); - await app.screenCapturer.capture('window title'); - assert.ok(title.indexOf('smoketest (Workspace)') >= 0); + const app = this.app as Application; + await app.code.waitForTitle(title => /smoketest \(Workspace\)/i.test(title)); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/preferences/keybindings.ts b/test/smoke/src/areas/preferences/keybindings.ts index 9bcb1e14d7..a1884ce3e3 100644 --- a/test/smoke/src/areas/preferences/keybindings.ts +++ b/test/smoke/src/areas/preferences/keybindings.ts @@ -3,26 +3,28 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; const SEARCH_INPUT = '.settings-search-input input'; export class KeybindingsEditor { - constructor(private spectron: SpectronApplication) { } + constructor(private code: Code, private commands: Commands) { } - async updateKeybinding(command: string, keys: string[], ariaLabel: string): Promise { - await this.spectron.runCommand('workbench.action.openGlobalKeybindings'); - await this.spectron.client.waitForActiveElement(SEARCH_INPUT); - await this.spectron.client.setValue(SEARCH_INPUT, command); + async updateKeybinding(command: string, keybinding: string, ariaLabel: string): Promise { + await this.commands.runCommand('workbench.action.openGlobalKeybindings'); + await this.code.waitForActiveElement(SEARCH_INPUT); + await this.code.waitForSetValue(SEARCH_INPUT, command); - await this.spectron.client.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item'); - await this.spectron.client.waitForElement('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item.focused.selected'); + await this.code.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item'); + await this.code.waitForElement('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item.focused.selected'); - await this.spectron.client.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item .action-item .icon.add'); - await this.spectron.client.waitForElement('.defineKeybindingWidget .monaco-inputbox.synthetic-focus'); + await this.code.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item .action-item .icon.add'); + await this.code.waitForElement('.defineKeybindingWidget .monaco-inputbox.synthetic-focus'); - await this.spectron.client.keys([...keys, 'NULL', 'Enter', 'NULL']); - await this.spectron.client.waitForElement(`div[aria-label="Keybindings"] div[aria-label="Keybinding is ${ariaLabel}."]`); + await this.code.dispatchKeybinding(keybinding); + await this.code.dispatchKeybinding('enter'); + await this.code.waitForElement(`div[aria-label="Keybindings"] div[aria-label="Keybinding is ${ariaLabel}."]`); } } \ No newline at end of file diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index c71b450c77..b154c5d92c 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -3,45 +3,34 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; - -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; import { ActivityBarPosition } from '../activitybar/activityBar'; export function setup() { describe('Preferences', () => { - before(function () { - this.app.suiteName = 'Preferences'; - }); - it('turns off editor line numbers and verifies the live change', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.explorer.openFile('app.js'); - let lineNumbers = await app.client.waitForElements('.line-numbers'); - await app.screenCapturer.capture('app.js has line numbers'); - assert.ok(!!lineNumbers.length, 'Line numbers are not present in the editor before disabling them.'); + await app.code.waitForElements('.line-numbers', false, elements => !!elements.length); await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"'); - await app.workbench.selectTab('app.js'); - lineNumbers = await app.client.waitForElements('.line-numbers', result => !result || result.length === 0); - - await app.screenCapturer.capture('line numbers hidden'); - assert.ok(!lineNumbers.length, 'Line numbers are still present in the editor after disabling them.'); + await app.workbench.editors.selectTab('app.js'); + await app.code.waitForElements('.line-numbers', false, result => !result || result.length === 0); }); it(`changes 'workbench.action.toggleSidebarPosition' command key binding and verifies it`, async function () { - const app = this.app as SpectronApplication; - assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.LEFT), 'Activity bar should be positioned on the left.'); + const app = this.app as Application; + await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.LEFT); - await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', ['Control', 'u'], 'Control+U'); + await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', 'ctrl+u', 'Control+U'); - await app.client.keys(['Control', 'u', 'NULL']); - assert.ok(await app.workbench.activitybar.getActivityBar(ActivityBarPosition.RIGHT), 'Activity bar was not moved to right after toggling its position.'); + await app.code.dispatchKeybinding('ctrl+u'); + await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.RIGHT); }); after(async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.settingsEditor.clearUserSettings(); }); }); diff --git a/test/smoke/src/areas/preferences/settings.ts b/test/smoke/src/areas/preferences/settings.ts index 47c3e43a28..5567638081 100644 --- a/test/smoke/src/areas/preferences/settings.ts +++ b/test/smoke/src/areas/preferences/settings.ts @@ -5,7 +5,10 @@ import * as fs from 'fs'; import * as path from 'path'; -import { SpectronApplication } from '../../spectron/application'; +import { Commands } from '../workbench/workbench'; +import { Editor } from '../editor/editor'; +import { Editors } from '../editor/editors'; +import { Code } from '../../vscode/code'; export enum ActivityBarPosition { LEFT = 0, @@ -13,33 +16,28 @@ export enum ActivityBarPosition { } const SEARCH_INPUT = '.settings-search-input input'; -const EDITOR = '.editable-preferences-editor-container .monaco-editor textarea'; export class SettingsEditor { - constructor(private spectron: SpectronApplication) { } + constructor(private code: Code, private userDataPath: string, private commands: Commands, private editors: Editors, private editor: Editor) { } async addUserSetting(setting: string, value: string): Promise { - await this.spectron.runCommand('workbench.action.openGlobalSettings'); - await this.spectron.client.waitAndClick(SEARCH_INPUT); - await this.spectron.client.waitForActiveElement(SEARCH_INPUT); + await this.commands.runCommand('workbench.action.openGlobalSettings'); + await this.code.waitAndClick(SEARCH_INPUT); + await this.code.waitForActiveElement(SEARCH_INPUT); - await this.spectron.client.keys(['ArrowDown', 'NULL']); - await this.spectron.client.waitForActiveElement(EDITOR); + await this.editor.waitForEditorFocus('settings.json', 1, '.editable-preferences-editor-container'); - await this.spectron.client.keys(['ArrowRight', 'NULL']); - await this.spectron.screenCapturer.capture('user settings is open and focused'); - - await this.spectron.workbench.editor.waitForTypeInEditor('settings.json', `"${setting}": ${value}`, '.editable-preferences-editor-container'); - await this.spectron.workbench.saveOpenedFile(); - - await this.spectron.screenCapturer.capture('user settings has changed'); + await this.code.dispatchKeybinding('right'); + await this.editor.waitForTypeInEditor('settings.json', `"${setting}": ${value}`, '.editable-preferences-editor-container'); + await this.editors.saveOpenedFile(); } async clearUserSettings(): Promise { - const settingsPath = path.join(this.spectron.userDataPath, 'User', 'settings.json'); + const settingsPath = path.join(this.userDataPath, 'User', 'settings.json'); await new Promise((c, e) => fs.writeFile(settingsPath, '{}', 'utf8', err => err ? e(err) : c())); - await this.spectron.workbench.editor.waitForEditorContents('settings.json', c => c.length === 0, '.editable-preferences-editor-container'); + await this.commands.runCommand('workbench.action.openGlobalSettings'); + await this.editor.waitForEditorContents('settings.json', c => c === '{}', '.editable-preferences-editor-container'); } } \ No newline at end of file diff --git a/test/smoke/src/areas/problems/problems.ts b/test/smoke/src/areas/problems/problems.ts index 01fac72dd6..ae5ff25be8 100644 --- a/test/smoke/src/areas/problems/problems.ts +++ b/test/smoke/src/areas/problems/problems.ts @@ -3,7 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; export enum ProblemSeverity { WARNING = 0, @@ -14,31 +15,20 @@ export class Problems { static PROBLEMS_VIEW_SELECTOR = '.panel.markers-panel'; - constructor(private spectron: SpectronApplication) { - // noop - } + constructor(private code: Code, private commands: Commands) { } public async showProblemsView(): Promise { - if (!await this.isVisible()) { - await this.spectron.runCommand('workbench.actions.view.problems'); - await this.waitForProblemsView(); - } + await this.commands.runCommand('workbench.actions.view.problems'); + await this.waitForProblemsView(); } public async hideProblemsView(): Promise { - if (await this.isVisible()) { - await this.spectron.runCommand('workbench.actions.view.problems'); - await this.spectron.client.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR, el => !el); - } - } - - public async isVisible(): Promise { - const element = await this.spectron.client.element(Problems.PROBLEMS_VIEW_SELECTOR); - return !!element; + await this.commands.runCommand('workbench.actions.view.problems'); + await this.code.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR, el => !el); } public async waitForProblemsView(): Promise { - await this.spectron.client.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR); + await this.code.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR); } public static getSelectorInProblemsView(problemType: ProblemSeverity): string { @@ -47,7 +37,7 @@ export class Problems { } public static getSelectorInEditor(problemType: ProblemSeverity): string { - let selector = problemType === ProblemSeverity.WARNING ? 'squiggly-b-warning' : 'squiggly-c-error'; + let selector = problemType === ProblemSeverity.WARNING ? 'squiggly-warning' : 'squiggly-error'; return `.view-overlays .cdr.${selector}`; } -} \ No newline at end of file +} diff --git a/test/smoke/src/areas/quickopen/quickopen.ts b/test/smoke/src/areas/quickopen/quickopen.ts index 55c7e434c1..cb860c0837 100644 --- a/test/smoke/src/areas/quickopen/quickopen.ts +++ b/test/smoke/src/areas/quickopen/quickopen.ts @@ -3,86 +3,110 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Editors } from '../editor/editors'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; export class QuickOpen { - static QUICK_OPEN_HIDDEN = 'div.quick-open-widget[aria-hidden="true"]'; - static QUICK_OPEN = 'div.quick-open-widget[aria-hidden="false"]'; + static QUICK_OPEN_HIDDEN = 'div.monaco-quick-open-widget[aria-hidden="true"]'; + static QUICK_OPEN = 'div.monaco-quick-open-widget[aria-hidden="false"]'; static QUICK_OPEN_INPUT = `${QuickOpen.QUICK_OPEN} .quick-open-input input`; static QUICK_OPEN_FOCUSED_ELEMENT = `${QuickOpen.QUICK_OPEN} .quick-open-tree .monaco-tree-row.focused .monaco-highlighted-label`; static QUICK_OPEN_ENTRY_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry'; + static QUICK_OPEN_ENTRY_LABEL_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry .label-name'; - constructor(readonly spectron: SpectronApplication) { } + constructor(private code: Code, private commands: Commands, private editors: Editors) { } async openQuickOpen(value: string): Promise { - await this.spectron.runCommand('workbench.action.quickOpen'); - await this.waitForQuickOpenOpened(); + let retries = 0; + + // other parts of code might steal focus away from quickopen :( + while (retries < 5) { + await this.commands.runCommand('workbench.action.quickOpen'); + + try { + await this.waitForQuickOpenOpened(10); + break; + } catch (err) { + if (++retries > 5) { + throw err; + } + + await this.code.dispatchKeybinding('escape'); + } + } if (value) { - await this.spectron.client.setValue(QuickOpen.QUICK_OPEN_INPUT, value); + await this.code.waitForSetValue(QuickOpen.QUICK_OPEN_INPUT, value); } } async closeQuickOpen(): Promise { - await this.spectron.runCommand('workbench.action.closeQuickOpen'); + await this.commands.runCommand('workbench.action.closeQuickOpen'); await this.waitForQuickOpenClosed(); } async openFile(fileName: string): Promise { await this.openQuickOpen(fileName); - await this.waitForQuickOpenElements(names => names.some(n => n === fileName)); - await this.spectron.client.keys(['Enter', 'NULL']); - await this.spectron.workbench.waitForActiveTab(fileName); - await this.spectron.workbench.waitForEditorFocus(fileName); + await this.waitForQuickOpenElements(names => names[0] === fileName); + await this.code.dispatchKeybinding('enter'); + await this.editors.waitForActiveTab(fileName); + await this.editors.waitForEditorFocus(fileName); } - async runCommand(commandText: string): Promise { - await this.openQuickOpen(`> ${commandText}`); - - // wait for best choice to be focused - await this.spectron.client.waitForTextContent(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT, commandText); - - // wait and click on best choice - await this.spectron.client.waitAndClick(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT); - } - - async waitForQuickOpenOpened(): Promise { - await this.spectron.client.waitForActiveElement(QuickOpen.QUICK_OPEN_INPUT); + async waitForQuickOpenOpened(retryCount?: number): Promise { + await this.code.waitForActiveElement(QuickOpen.QUICK_OPEN_INPUT, retryCount); } private async waitForQuickOpenClosed(): Promise { - await this.spectron.client.waitForElement(QuickOpen.QUICK_OPEN_HIDDEN); + await this.code.waitForElement(QuickOpen.QUICK_OPEN_HIDDEN); } async submit(text: string): Promise { - await this.spectron.client.setValue(QuickOpen.QUICK_OPEN_INPUT, text); - await this.spectron.client.keys(['Enter', 'NULL']); + await this.code.waitForSetValue(QuickOpen.QUICK_OPEN_INPUT, text); + await this.code.dispatchKeybinding('enter'); await this.waitForQuickOpenClosed(); } async selectQuickOpenElement(index: number): Promise { await this.waitForQuickOpenOpened(); for (let from = 0; from < index; from++) { - await this.spectron.client.keys(['ArrowDown', 'NULL']); + await this.code.dispatchKeybinding('down'); } - await this.spectron.client.keys(['Enter', 'NULL']); + await this.code.dispatchKeybinding('enter'); await this.waitForQuickOpenClosed(); } async waitForQuickOpenElements(accept: (names: string[]) => boolean): Promise { - await this.spectron.client.waitFor(() => this.getQuickOpenElements(), accept); + await this.code.waitForElements(QuickOpen.QUICK_OPEN_ENTRY_LABEL_SELECTOR, false, els => accept(els.map(e => e.textContent))); } - private async getQuickOpenElements(): Promise { - const result = await this.spectron.webclient.selectorExecute(QuickOpen.QUICK_OPEN_ENTRY_SELECTOR, - div => (Array.isArray(div) ? div : [div]).map(element => { - const name = element.querySelector('.label-name') as HTMLElement; - return name.textContent; - }) - ); + async runCommand(command: string): Promise { + await this.openQuickOpen(`> ${command}`); - return Array.isArray(result) ? result : []; + // wait for best choice to be focused + await this.code.waitForTextContent(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT, command); + + // wait and click on best choice + await this.code.waitAndClick(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT); + } + + async openQuickOutline(): Promise { + let retries = 0; + + while (++retries < 10) { + await this.commands.runCommand('workbench.action.gotoSymbol'); + + const text = await this.code.waitForTextContent('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span'); + + if (text !== 'No symbol information for the file') { + return; + } + + await this.closeQuickOpen(); + await new Promise(c => setTimeout(c, 250)); + } } } diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index ca1abadd3f..8aabd0cafc 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -3,16 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Search', () => { - before(function () { - this.app.suiteName = 'Search'; - }); - it('searches for body & checks for correct result number', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.search.openSearchViewlet(); await app.workbench.search.searchFor('body'); @@ -20,7 +16,7 @@ export function setup() { }); it('searches only for *.js files & checks for correct result number', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.search.searchFor('body'); await app.workbench.search.showQueryDetails(); await app.workbench.search.setFilesToIncludeText('*.js'); @@ -32,27 +28,25 @@ export function setup() { }); it('dismisses result & checks for correct result number', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.search.searchFor('body'); await app.workbench.search.removeFileMatch(1); await app.workbench.search.waitForResultText('10 results in 4 files'); }); it('replaces first search result with a replace term', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.search.searchFor('body'); await app.workbench.search.expandReplace(); await app.workbench.search.setReplaceText('ydob'); await app.workbench.search.replaceFileMatch(1); - await app.workbench.saveOpenedFile(); await app.workbench.search.waitForResultText('10 results in 4 files'); await app.workbench.search.searchFor('ydob'); await app.workbench.search.setReplaceText('body'); await app.workbench.search.replaceFileMatch(1); - await app.workbench.saveOpenedFile(); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/search/search.ts b/test/smoke/src/areas/search/search.ts index cbaf7a37d1..f34c6cb666 100644 --- a/test/smoke/src/areas/search/search.ts +++ b/test/smoke/src/areas/search/search.ts @@ -3,85 +3,77 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Viewlet } from '../workbench/viewlet'; +import { Commands } from '../workbench/workbench'; +import { Code } from '../../vscode/code'; const VIEWLET = 'div[id="workbench.view.search"] .search-view'; const INPUT = `${VIEWLET} .search-widget .search-container .monaco-inputbox input`; -const INCLUDE_INPUT = `${VIEWLET} .query-details .monaco-inputbox input[aria-label="Search Include Patterns"]`; +const INCLUDE_INPUT = `${VIEWLET} .query-details .file-types.includes .monaco-inputbox input`; export class Search extends Viewlet { - constructor(spectron: SpectronApplication) { - super(spectron); + constructor(code: Code, private commands: Commands) { + super(code); } async openSearchViewlet(): Promise { - await this.spectron.runCommand('workbench.view.search'); - await this.spectron.client.waitForActiveElement(INPUT); + await this.commands.runCommand('workbench.view.search'); + await this.code.waitForActiveElement(INPUT); } async searchFor(text: string): Promise { - await this.spectron.client.click(INPUT); - await this.spectron.client.waitForActiveElement(INPUT); - await this.spectron.client.setValue(INPUT, text); + await this.code.waitAndClick(INPUT); + await this.code.waitForActiveElement(INPUT); + await this.code.waitForSetValue(INPUT, text); await this.submitSearch(); } async submitSearch(): Promise { - await this.spectron.client.click(INPUT); - await this.spectron.client.waitForActiveElement(INPUT); + await this.code.waitAndClick(INPUT); + await this.code.waitForActiveElement(INPUT); - await this.spectron.client.keys(['Enter', 'NULL']); - await this.spectron.client.element(`${VIEWLET} .messages[aria-hidden="false"]`); + await this.code.dispatchKeybinding('enter'); + await this.code.waitForElement(`${VIEWLET} .messages[aria-hidden="false"]`); } async setFilesToIncludeText(text: string): Promise { - await this.spectron.client.click(INCLUDE_INPUT); - await this.spectron.client.waitForActiveElement(INCLUDE_INPUT); - await this.spectron.client.setValue(INCLUDE_INPUT, text || ''); + await this.code.waitAndClick(INCLUDE_INPUT); + await this.code.waitForActiveElement(INCLUDE_INPUT); + await this.code.waitForSetValue(INCLUDE_INPUT, text || ''); } async showQueryDetails(): Promise { - if (!await this.areDetailsVisible()) { - await this.spectron.client.waitAndClick(`${VIEWLET} .query-details .more`); - } + await this.code.waitAndClick(`${VIEWLET} .query-details .more`); } async hideQueryDetails(): Promise { - if (await this.areDetailsVisible()) { - await this.spectron.client.waitAndClick(`${VIEWLET} .query-details.more .more`); - } - } - - async areDetailsVisible(): Promise { - const element = await this.spectron.client.element(`${VIEWLET} .query-details.more`); - return !!element; + await this.code.waitAndClick(`${VIEWLET} .query-details.more .more`); } async removeFileMatch(index: number): Promise { - await this.spectron.client.waitAndMoveToObject(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); - const file = await this.spectron.client.waitForText(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`); - await this.spectron.client.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-remove`); - await this.spectron.client.waitForText(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`, void 0, result => result !== file); + await this.code.waitAndMove(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); + const file = await this.code.waitForTextContent(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`); + await this.code.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-remove`); + await this.code.waitForTextContent(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`, void 0, result => result !== file); } async expandReplace(): Promise { - await this.spectron.client.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.collapse`); + await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.collapse`); } async setReplaceText(text: string): Promise { - await this.spectron.client.waitAndClick(`${VIEWLET} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`); - await this.spectron.client.element(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`); - await this.spectron.client.setValue(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`, text); + await this.code.waitAndClick(`${VIEWLET} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`); + await this.code.waitForElement(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`); + await this.code.waitForSetValue(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`, text); } async replaceFileMatch(index: number): Promise { - await this.spectron.client.waitAndMoveToObject(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); - await this.spectron.client.click(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-replace-all`); + await this.code.waitAndMove(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`); + await this.code.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-replace-all`); } async waitForResultText(text: string): Promise { - await this.spectron.client.waitForText(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, text); + await this.code.waitForTextContent(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, text); } } diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 8962da8128..e38fbb927c 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -3,19 +3,13 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; - -import { SpectronApplication, Quality } from '../../spectron/application'; +import { Application, Quality } from '../../application'; import { StatusBarElement } from './statusbar'; export function setup() { describe('Statusbar', () => { - before(function () { - this.app.suiteName = 'Statusbar'; - }); - it('verifies presence of all default status bar elements', async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.statusbar.waitForStatusbarElement(StatusBarElement.BRANCH_STATUS); if (app.quality !== Quality.Dev) { @@ -33,7 +27,7 @@ export function setup() { }); it(`verifies that 'quick open' opens when clicking on status bar elements`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.statusbar.clickOn(StatusBarElement.BRANCH_STATUS); await app.workbench.quickopen.waitForQuickOpenOpened(); @@ -55,25 +49,25 @@ export function setup() { }); it(`verifies that 'Problems View' appears when clicking on 'Problems' status element`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.statusbar.clickOn(StatusBarElement.PROBLEMS_STATUS); await app.workbench.problems.waitForProblemsView(); }); it(`verifies that 'Tweet us feedback' pop-up appears when clicking on 'Feedback' icon`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; if (app.quality === Quality.Dev) { return this.skip(); } await app.workbench.statusbar.clickOn(StatusBarElement.FEEDBACK_ICON); - assert.ok(!!await app.client.waitForElement('.feedback-form')); + await app.code.waitForElement('.feedback-form'); }); it(`checks if 'Go to Line' works if called from the status bar`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS); @@ -81,11 +75,11 @@ export function setup() { await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.submit(':15'); - await app.workbench.editor.waitForHighlightingLine(15); + await app.workbench.editor.waitForHighlightingLine('app.js', 15); }); it(`verifies if changing EOL is reflected in the status bar`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS); diff --git a/test/smoke/src/areas/statusbar/statusbar.ts b/test/smoke/src/areas/statusbar/statusbar.ts index de08de39b6..1293b4186b 100644 --- a/test/smoke/src/areas/statusbar/statusbar.ts +++ b/test/smoke/src/areas/statusbar/statusbar.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Code } from '../../vscode/code'; export enum StatusBarElement { BRANCH_STATUS = 0, @@ -23,23 +23,22 @@ export class StatusBar { private readonly leftSelector = '.statusbar-item.left'; private readonly rightSelector = '.statusbar-item.right'; - constructor(private spectron: SpectronApplication) { + constructor(private code: Code) { } + + async waitForStatusbarElement(element: StatusBarElement): Promise { + await this.code.waitForElement(this.getSelector(element)); } - public async waitForStatusbarElement(element: StatusBarElement): Promise { - await this.spectron.client.waitForElement(this.getSelector(element)); + async clickOn(element: StatusBarElement): Promise { + await this.code.waitAndClick(this.getSelector(element)); } - public async clickOn(element: StatusBarElement): Promise { - await this.spectron.client.waitAndClick(this.getSelector(element)); + async waitForEOL(eol: string): Promise { + return this.code.waitForTextContent(this.getSelector(StatusBarElement.EOL_STATUS), eol); } - public async waitForEOL(eol: string): Promise { - return this.spectron.client.waitForText(this.getSelector(StatusBarElement.EOL_STATUS), eol); - } - - public async getStatusbarTextByTitle(title: string): Promise { - return await this.spectron.client.waitForText(`${this.mainSelector} span[title="smoke test"]`); + async waitForStatusbarText(title: string, text: string): Promise { + await this.code.waitForTextContent(`${this.mainSelector} span[title="${title}"]`, text); } private getSelector(element: StatusBarElement): string { @@ -61,7 +60,7 @@ export class StatusBar { case StatusBarElement.LANGUAGE_STATUS: return `${this.mainSelector} ${this.rightSelector} .editor-status-mode`; case StatusBarElement.FEEDBACK_ICON: - return `${this.mainSelector} ${this.rightSelector} .dropdown.send-feedback`; + return `${this.mainSelector} ${this.rightSelector} .monaco-dropdown.send-feedback`; default: throw new Error(element); } diff --git a/test/smoke/src/areas/terminal/terminal.test.ts b/test/smoke/src/areas/terminal/terminal.test.ts index f41842e591..56680c1086 100644 --- a/test/smoke/src/areas/terminal/terminal.test.ts +++ b/test/smoke/src/areas/terminal/terminal.test.ts @@ -3,27 +3,24 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// import { SpectronApplication } from '../../spectron/application'; +// import { Application } from '../../application'; -describe('Terminal', () => { - // let app: SpectronApplication; - // before(() => { app = new SpectronApplication(); return app.start('Terminal'); }); - // after(() => app.stop()); +export function setup() { + describe('Terminal', () => { + // it(`opens terminal, runs 'echo' and verifies the output`, async function () { + // const app = this.app as Application; - // it(`opens terminal, runs 'echo' and verifies the output`, async function () { - // const expected = new Date().getTime().toString(); - // await app.workbench.terminal.showTerminal(); - - // await app.workbench.terminal.runCommand(`echo ${expected}`); - - // await app.workbench.terminal.waitForTerminalText(terminalText => { - // // Last line will not contain the output - // for (let index = terminalText.length - 2; index >= 0; index--) { - // if (!!terminalText[index] && terminalText[index].trim() === expected) { - // return true; - // } - // } - // return false; - // }); - // }); -}); \ No newline at end of file + // const expected = new Date().getTime().toString(); + // await app.workbench.terminal.showTerminal(); + // await app.workbench.terminal.runCommand(`echo ${expected}`); + // await app.workbench.terminal.waitForTerminalText(terminalText => { + // for (let index = terminalText.length - 2; index >= 0; index--) { + // if (!!terminalText[index] && terminalText[index].trim() === expected) { + // return true; + // } + // } + // return false; + // }); + // }); + }); +} diff --git a/test/smoke/src/areas/terminal/terminal.ts b/test/smoke/src/areas/terminal/terminal.ts index af935a5215..eda6eb5825 100644 --- a/test/smoke/src/areas/terminal/terminal.ts +++ b/test/smoke/src/areas/terminal/terminal.ts @@ -3,59 +3,29 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Code } from '../../vscode/code'; +import { Commands } from '../workbench/workbench'; const PANEL_SELECTOR = 'div[id="workbench.panel.terminal"]'; const XTERM_SELECTOR = `${PANEL_SELECTOR} .terminal-wrapper`; +const XTERM_TEXTAREA = `${XTERM_SELECTOR} textarea.xterm-helper-textarea`; export class Terminal { - constructor(private spectron: SpectronApplication) { } + constructor(private code: Code, private commands: Commands) { } async showTerminal(): Promise { - if (!await this.isVisible()) { - await this.spectron.workbench.quickopen.runCommand('View: Toggle Integrated Terminal'); - await this.spectron.client.waitForElement(XTERM_SELECTOR); - await this.waitForTerminalText(text => text.length > 0, 'Waiting for Terminal to be ready'); - } - } - - async isVisible(): Promise { - const element = await this.spectron.client.element(PANEL_SELECTOR); - return !!element; + await this.commands.runCommand('workbench.action.terminal.toggleTerminal'); + await this.code.waitForActiveElement(XTERM_TEXTAREA); + await this.code.waitForTerminalBuffer(XTERM_SELECTOR, lines => lines.some(line => line.length > 0)); } async runCommand(commandText: string): Promise { - // TODO@Tyriar fix this. we should not use type but setValue - // await this.spectron.client.type(commandText); - await this.spectron.client.keys(['Enter', 'NULL']); + await this.code.waitForPaste(XTERM_TEXTAREA, commandText); + await this.code.dispatchKeybinding('enter'); } - async waitForTerminalText(fn: (text: string[]) => boolean, timeOutDescription: string = 'Getting Terminal Text'): Promise { - return this.spectron.client.waitFor(async () => { - const terminalText = await this.getTerminalText(); - if (fn(terminalText)) { - return terminalText; - } - return undefined; - }, void 0, timeOutDescription); - } - - getCurrentLineNumber(): Promise { - return this.getTerminalText().then(text => text.length); - } - - private async getTerminalText(): Promise { - return await this.spectron.webclient.selectorExecute(XTERM_SELECTOR, - div => { - const xterm = ((Array.isArray(div) ? div[0] : div)).xterm; - const buffer = xterm.buffer; - const lines: string[] = []; - for (let i = 0; i < buffer.lines.length; i++) { - lines.push(buffer.translateBufferLineToString(i, true)); - } - return lines; - } - ); + async waitForTerminalText(accept: (buffer: string[]) => boolean): Promise { + await this.code.waitForTerminalBuffer(XTERM_SELECTOR, accept); } } \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index d5c0f9e4cb..957d490d54 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -3,39 +3,30 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +import { Application } from '../../application'; export function setup() { describe('Dataloss', () => { - before(function () { - this.app.suiteName = 'Dataloss'; - }); - it(`verifies that 'hot exit' works for dirty files`, async function () { - const app = this.app as SpectronApplication; - await app.workbench.newUntitledFile(); + const app = this.app as Application; + await app.workbench.editors.newUntitledFile(); const untitled = 'Untitled-1'; const textToTypeInUntitled = 'Hello, Unitled Code'; await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled); - await app.screenCapturer.capture('Untitled file before reload'); const readmeMd = 'readme.md'; const textToType = 'Hello, Code'; await app.workbench.explorer.openFile(readmeMd); await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType); - await app.screenCapturer.capture(`${readmeMd} before reload`); await app.reload(); - await app.screenCapturer.capture('After reload'); - await app.workbench.waitForActiveTab(readmeMd, true); - await app.screenCapturer.capture(`${readmeMd} after reload`); + await app.workbench.editors.waitForActiveTab(readmeMd, true); await app.workbench.editor.waitForEditorContents(readmeMd, c => c.indexOf(textToType) > -1); - await app.workbench.waitForTab(untitled, true); - await app.workbench.selectTab(untitled, true); - await app.screenCapturer.capture('Untitled file after reload'); + await app.workbench.editors.waitForTab(untitled, true); + await app.workbench.editors.selectTab(untitled, true); await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); }); }); diff --git a/test/smoke/src/areas/workbench/data-migration.test.ts b/test/smoke/src/areas/workbench/data-migration.test.ts index 022961c125..2ea5674984 100644 --- a/test/smoke/src/areas/workbench/data-migration.test.ts +++ b/test/smoke/src/areas/workbench/data-migration.test.ts @@ -3,130 +3,109 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; - -import { SpectronApplication, Quality } from '../../spectron/application'; +import { Application, Quality } from '../../application'; import * as rimraf from 'rimraf'; export interface ICreateAppFn { - (quality: Quality): SpectronApplication | null; + (quality: Quality): Application; } export function setup(userDataDir: string, createApp: ICreateAppFn) { describe('Data Migration', () => { + afterEach(async function () { await new Promise((c, e) => rimraf(userDataDir, { maxBusyTries: 10 }, err => err ? e(err) : c())); }); - it('checks if the Untitled file is restored migrating from stable to latest', async function () { - const stableApp = createApp(Quality.Stable); + // it('checks if the Untitled file is restored migrating from stable to latest', async function () { + // const stableApp = createApp(Quality.Stable); - if (!stableApp) { - this.skip(); - return; - } + // if (!stableApp) { + // this.skip(); + // return; + // } - await stableApp.start(); - stableApp.suiteName = 'Data Migration'; + // await stableApp.start(); - const textToType = 'Very dirty file'; + // const textToType = 'Very dirty file'; - await stableApp.workbench.newUntitledFile(); - await stableApp.workbench.editor.waitForTypeInEditor('Untitled-1', textToType); + // await stableApp.workbench.editors.newUntitledFile(); + // await stableApp.workbench.editor.waitForTypeInEditor('Untitled-1', textToType); - await stableApp.stop(); - await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) + // await stableApp.stop(); + // await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) - // Checking latest version for the restored state - const app = createApp(Quality.Insiders); + // // Checking latest version for the restored state + // const app = createApp(Quality.Insiders); - if (!app) { - return assert(false); - } + // await app.start(false); - await app.start(false); - app.suiteName = 'Data Migration'; + // await app.workbench.editors.waitForActiveTab('Untitled-1', true); + // await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1); - assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`); + // await app.stop(); + // }); - await app.workbench.editor.waitForEditorContents('Untitled-1', c => c.indexOf(textToType) > -1); - await app.screenCapturer.capture('Untitled file text'); + // it('checks if the newly created dirty file is restored migrating from stable to latest', async function () { + // const stableApp = createApp(Quality.Stable); - await app.stop(); - }); + // if (!stableApp) { + // this.skip(); + // return; + // } - it('checks if the newly created dirty file is restored migrating from stable to latest', async function () { - const stableApp = createApp(Quality.Stable); + // await stableApp.start(); - if (!stableApp) { - this.skip(); - return; - } + // const fileName = 'app.js'; + // const textPart = 'This is going to be an unsaved file'; - await stableApp.start(); - stableApp.suiteName = 'Data Migration'; + // await stableApp.workbench.quickopen.openFile(fileName); - const fileName = 'app.js'; - const textPart = 'This is going to be an unsaved file'; + // await stableApp.workbench.editor.waitForTypeInEditor(fileName, textPart); - await stableApp.workbench.quickopen.openFile(fileName); + // await stableApp.stop(); + // await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) - await stableApp.workbench.editor.waitForTypeInEditor(fileName, textPart); + // // Checking latest version for the restored state + // const app = createApp(Quality.Insiders); - await stableApp.stop(); - await new Promise(c => setTimeout(c, 500)); // wait until all resources are released (e.g. locked local storage) + // await app.start(false); - // Checking latest version for the restored state - const app = createApp(Quality.Insiders); + // await app.workbench.editors.waitForActiveTab(fileName); + // await app.workbench.editor.waitForEditorContents(fileName, c => c.indexOf(textPart) > -1); - if (!app) { - return assert(false); - } + // await app.stop(); + // }); - await app.start(false); - app.suiteName = 'Data Migration'; + // it('checks if opened tabs are restored migrating from stable to latest', async function () { + // const stableApp = createApp(Quality.Stable); - assert.ok(await app.workbench.waitForActiveTab(fileName), `dirty file tab is not present after migration.`); - await app.workbench.editor.waitForEditorContents(fileName, c => c.indexOf(textPart) > -1); + // if (!stableApp) { + // this.skip(); + // return; + // } - await app.stop(); - }); + // await stableApp.start(); - it('checks if opened tabs are restored migrating from stable to latest', async function () { - const stableApp = createApp(Quality.Stable); + // const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; - if (!stableApp) { - this.skip(); - return; - } + // await stableApp.workbench.quickopen.openFile(fileName1); + // await stableApp.workbench.runCommand('View: Keep Editor'); + // await stableApp.workbench.quickopen.openFile(fileName2); + // await stableApp.workbench.runCommand('View: Keep Editor'); + // await stableApp.workbench.quickopen.openFile(fileName3); + // await stableApp.stop(); - await stableApp.start(); - stableApp.suiteName = 'Data Migration'; + // const app = createApp(Quality.Insiders); - const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; + // await app.start(false); - await stableApp.workbench.quickopen.openFile(fileName1); - await stableApp.workbench.quickopen.runCommand('View: Keep Editor'); - await stableApp.workbench.quickopen.openFile(fileName2); - await stableApp.workbench.quickopen.runCommand('View: Keep Editor'); - await stableApp.workbench.quickopen.openFile(fileName3); - await stableApp.stop(); + // await app.workbench.editors.waitForTab(fileName1); + // await app.workbench.editors.waitForTab(fileName2); + // await app.workbench.editors.waitForTab(fileName3); - const app = createApp(Quality.Insiders); - - if (!app) { - return assert(false); - } - - await app.start(false); - app.suiteName = 'Data Migration'; - - assert.ok(await app.workbench.waitForTab(fileName1), `${fileName1} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForTab(fileName2), `${fileName2} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForTab(fileName3), `${fileName3} tab was not restored after migration.`); - - await app.stop(); - }); + // await app.stop(); + // }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index a8b79f37b6..671f3b5324 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -3,15 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; - -import { SpectronApplication, Quality } from '../../spectron/application'; +import { Application, Quality } from '../../application'; export function setup() { describe('Localization', () => { before(async function () { - const app = this.app as SpectronApplication; - this.app.suiteName = 'Localization'; + const app = this.app as Application; if (app.quality === Quality.Dev) { return; @@ -21,36 +18,26 @@ export function setup() { }); it(`starts with 'DE' locale and verifies title and viewlets text is in German`, async function () { - const app = this.app as SpectronApplication; + const app = this.app as Application; if (app.quality === Quality.Dev) { this.skip(); return; } - let text = await app.workbench.explorer.getOpenEditorsViewTitle(); - await app.screenCapturer.capture('Open editors title'); - assert(/geöffnete editoren/i.test(text)); + await app.workbench.explorer.waitForOpenEditorsViewTitle(title => /geöffnete editoren/i.test(title)); await app.workbench.search.openSearchViewlet(); - text = await app.workbench.search.getTitle(); - await app.screenCapturer.capture('Search title'); - assert(/suchen/i.test(text)); + await app.workbench.search.waitForTitle(title => /suchen/i.test(title)); await app.workbench.scm.openSCMViewlet(); - text = await app.workbench.scm.getTitle(); - await app.screenCapturer.capture('Scm title'); - assert(/quellcodeverwaltung/i.test(text)); + await app.workbench.scm.waitForTitle(title => /quellcodeverwaltung/i.test(title)); await app.workbench.debug.openDebugViewlet(); - text = await app.workbench.debug.getTitle(); - await app.screenCapturer.capture('Debug title'); - assert(/debuggen/i.test(text)); + await app.workbench.debug.waitForTitle(title => /debuggen/i.test(title)); await app.workbench.extensions.openExtensionsViewlet(); - text = await app.workbench.extensions.getTitle(); - await app.screenCapturer.capture('Extensions title'); - assert(/erweiterungen/i.test(text)); + await app.workbench.extensions.waitForTitle(title => /erweiterungen/i.test(title)); }); }); } \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/viewlet.ts b/test/smoke/src/areas/workbench/viewlet.ts index 374b7c4ed9..1df6710b9d 100644 --- a/test/smoke/src/areas/workbench/viewlet.ts +++ b/test/smoke/src/areas/workbench/viewlet.ts @@ -3,16 +3,15 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; +'use strict'; + +import { Code } from '../../vscode/code'; export abstract class Viewlet { - constructor(protected spectron: SpectronApplication) { - // noop - } + constructor(protected code: Code) { } - public async getTitle(): Promise { - return this.spectron.client.waitForText('.monaco-workbench-container .part.sidebar > .title > .title-label > span'); + async waitForTitle(fn: (title: string) => boolean): Promise { + await this.code.waitForTextContent('.monaco-workbench-container .part.sidebar > .title > .title-label > span', undefined, fn); } - } \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/workbench.ts b/test/smoke/src/areas/workbench/workbench.ts index b02a5b5b37..9a98c6181a 100644 --- a/test/smoke/src/areas/workbench/workbench.ts +++ b/test/smoke/src/areas/workbench/workbench.ts @@ -3,7 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SpectronApplication } from '../../spectron/application'; import { Explorer } from '../explorer/explorer'; import { ActivityBar } from '../activitybar/activityBar'; import { QuickOpen } from '../quickopen/quickopen'; @@ -16,13 +15,20 @@ import { StatusBar } from '../statusbar/statusbar'; import { Problems } from '../problems/problems'; import { SettingsEditor } from '../preferences/settings'; import { KeybindingsEditor } from '../preferences/keybindings'; +import { Editors } from '../editor/editors'; +import { Code } from '../../vscode/code'; import { Terminal } from '../terminal/terminal'; -export class Workbench { +export interface Commands { + runCommand(command: string): Promise; +} +export class Workbench implements Commands { + + readonly quickopen: QuickOpen; + readonly editors: Editors; readonly explorer: Explorer; readonly activitybar: ActivityBar; - readonly quickopen: QuickOpen; readonly search: Search; readonly extensions: Extensions; readonly editor: Editor; @@ -34,47 +40,35 @@ export class Workbench { readonly keybindingsEditor: KeybindingsEditor; readonly terminal: Terminal; - constructor(private spectron: SpectronApplication) { - this.explorer = new Explorer(spectron); - this.activitybar = new ActivityBar(spectron); - this.quickopen = new QuickOpen(spectron); - this.search = new Search(spectron); - this.extensions = new Extensions(spectron); - this.editor = new Editor(spectron); - this.scm = new SCM(spectron); - this.debug = new Debug(spectron); - this.statusbar = new StatusBar(spectron); - this.problems = new Problems(spectron); - this.settingsEditor = new SettingsEditor(spectron); - this.keybindingsEditor = new KeybindingsEditor(spectron); - this.terminal = new Terminal(spectron); + constructor(private code: Code, private keybindings: any[], userDataPath: string) { + this.editors = new Editors(code, this); + this.quickopen = new QuickOpen(code, this, this.editors); + this.explorer = new Explorer(code, this.quickopen, this.editors); + this.activitybar = new ActivityBar(code); + this.search = new Search(code, this); + this.extensions = new Extensions(code, this); + this.editor = new Editor(code, this); + this.scm = new SCM(code, this); + this.debug = new Debug(code, this, this.editors, this.editor); + this.statusbar = new StatusBar(code); + this.problems = new Problems(code, this); + this.settingsEditor = new SettingsEditor(code, userDataPath, this, this.editors, this.editor); + this.keybindingsEditor = new KeybindingsEditor(code, this); + this.terminal = new Terminal(code, this); } - public async saveOpenedFile(): Promise { - await this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty'); - await this.spectron.workbench.quickopen.runCommand('File: Save'); - } + /** + * Retrieves the command from keybindings file and executes it with WebdriverIO client API + * @param command command (e.g. 'workbench.action.files.newUntitledFile') + */ + async runCommand(command: string): Promise { + const binding = this.keybindings.find(x => x['command'] === command); - public async selectTab(tabName: string, untitled: boolean = false): Promise { - await this.spectron.client.waitAndClick(`.tabs-container div.tab[aria-label="${tabName}, tab"]`); - await this.waitForEditorFocus(tabName, untitled); - } - - public async waitForEditorFocus(fileName: string, untitled: boolean = false): Promise { - await this.waitForActiveTab(fileName); - await this.editor.waitForActiveEditor(fileName); - } - - public async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { - return this.spectron.client.waitForElement(`.tabs-container div.tab.active${isDirty ? '.dirty' : ''}[aria-selected="true"][aria-label="${fileName}, tab"]`); - } - - public async waitForTab(fileName: string, isDirty: boolean = false): Promise { - return this.spectron.client.waitForElement(`.tabs-container div.tab${isDirty ? '.dirty' : ''}[aria-label="${fileName}, tab"]`).then(() => true); - } - - public async newUntitledFile(): Promise { - await this.spectron.runCommand('workbench.action.files.newUntitledFile'); - await this.waitForEditorFocus('Untitled-1', true); + if (binding) { + await this.code.dispatchKeybinding(binding.key); + } else { + await this.quickopen.runCommand(command); + } } } + diff --git a/test/smoke/src/helpers/screenshot.ts b/test/smoke/src/helpers/screenshot.ts deleted file mode 100644 index 0a504a5136..0000000000 --- a/test/smoke/src/helpers/screenshot.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as path from 'path'; -import * as fs from 'fs'; -import * as mkdirp from 'mkdirp'; -import { Application } from 'spectron'; -import { sanitize } from './utilities'; - -export class ScreenCapturer { - - private static counter = 0; - - constructor( - private application: Application, - public suiteName: string, - private screenshotsDirPath: string | undefined, - ) { } - - async capture(name: string): Promise { - if (!this.screenshotsDirPath) { - return; - } - - const screenshotPath = path.join( - this.screenshotsDirPath, - sanitize(this.suiteName), - `${ScreenCapturer.counter++}-${sanitize(name)}.png` - ); - - const image = await this.application.browserWindow.capturePage(); - await new Promise((c, e) => mkdirp(path.dirname(screenshotPath), err => err ? e(err) : c())); - await new Promise((c, e) => fs.writeFile(screenshotPath, image, err => err ? e(err) : c())); - } -} diff --git a/test/smoke/src/helpers/utilities.ts b/test/smoke/src/helpers/utilities.ts deleted file mode 100644 index 0e831e43d5..0000000000 --- a/test/smoke/src/helpers/utilities.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as fs from 'fs'; -import { dirname } from 'path'; - -export function nfcall(fn: Function, ...args): Promise { - return new Promise((c, e) => fn(...args, (err, r) => err ? e(err) : c(r))); -} - -export async function mkdirp(path: string, mode?: number): Promise { - const mkdir = async () => { - try { - await nfcall(fs.mkdir, path, mode); - } catch (err) { - if (err.code === 'EEXIST') { - const stat = await nfcall(fs.stat, path); - - if (stat.isDirectory) { - return; - } - - throw new Error(`'${path}' exists and is not a directory.`); - } - - throw err; - } - }; - - // is root? - if (path === dirname(path)) { - return true; - } - - try { - await mkdir(); - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } - - await mkdirp(dirname(path), mode); - await mkdir(); - } - - return true; -} - -export function sanitize(name: string): string { - return name.replace(/[&*:\/]/g, ''); -} \ No newline at end of file diff --git a/test/smoke/src/logger.ts b/test/smoke/src/logger.ts new file mode 100644 index 0000000000..909395a8b5 --- /dev/null +++ b/test/smoke/src/logger.ts @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { appendFileSync, writeFileSync } from 'fs'; +import { format } from 'util'; +import { EOL } from 'os'; + +export interface Logger { + log(message: string, ...args: any[]): void; +} + +export class ConsoleLogger implements Logger { + + log(message: string, ...args: any[]): void { + console.log('**', message, ...args); + } +} + +export class FileLogger implements Logger { + + constructor(private path: string) { + writeFileSync(path, ''); + } + + log(message: string, ...args: any[]): void { + const date = new Date().toISOString(); + appendFileSync(this.path, `[${date}] ${format(message, ...args)}${EOL}`); + } +} + +export class MultiLogger implements Logger { + + constructor(private loggers: Logger[]) { } + + log(message: string, ...args: any[]): void { + for (const logger of this.loggers) { + logger.log(message, ...args); + } + } +} \ No newline at end of file diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 5b8641a059..bfea9c29b1 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -11,9 +11,9 @@ import * as minimist from 'minimist'; import * as tmp from 'tmp'; import * as rimraf from 'rimraf'; import * as mkdirp from 'mkdirp'; -import { SpectronApplication, Quality } from './spectron/application'; -import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test'; +import { Application, Quality } from './application'; +import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test'; import { setup as setupDataLossTests } from './areas/workbench/data-loss.test'; import { setup as setupDataExplorerTests } from './areas/explorer/explorer.test'; import { setup as setupDataPreferencesTests } from './areas/preferences/preferences.test'; @@ -24,9 +24,10 @@ import { setup as setupDataDebugTests } from './areas/debug/debug.test'; import { setup as setupDataGitTests } from './areas/git/git.test'; import { setup as setupDataStatusbarTests } from './areas/statusbar/statusbar.test'; import { setup as setupDataExtensionTests } from './areas/extensions/extensions.test'; +import { setup as setupTerminalTests } from './areas/terminal/terminal.test'; import { setup as setupDataMultirootTests } from './areas/multiroot/multiroot.test'; import { setup as setupDataLocalizationTests } from './areas/workbench/localization.test'; -// import './areas/terminal/terminal.test'; +import { MultiLogger, Logger, ConsoleLogger, FileLogger } from './logger'; const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; }; const testDataPath = tmpDir.name; @@ -37,13 +38,20 @@ const opts = minimist(args, { string: [ 'build', 'stable-build', - 'log', - 'wait-time' - ] + 'wait-time', + 'test-repo', + 'keybindings', + 'screenshots', + 'log' + ], + boolean: [ + 'verbose' + ], + default: { + verbose: false + } }); -const artifactsPath = opts.log || ''; - const workspaceFilePath = path.join(testDataPath, 'smoketest.code-workspace'); const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express'; const workspacePath = path.join(testDataPath, 'vscode-smoketest-express'); @@ -51,6 +59,12 @@ const keybindingsPath = path.join(testDataPath, 'keybindings.json'); const extensionsPath = path.join(testDataPath, 'extensions-dir'); mkdirp.sync(extensionsPath); +const screenshotsPath = opts.screenshots ? path.resolve(opts.screenshots) : null; + +if (screenshotsPath) { + mkdirp.sync(screenshotsPath); +} + function fail(errorMessage): void { console.error(errorMessage); process.exit(1); @@ -96,16 +110,16 @@ function getBuildElectronPath(root: string): string { } let testCodePath = opts.build; -let stableCodePath = opts['stable-build']; +// let stableCodePath = opts['stable-build']; let electronPath: string; -let stablePath: string; +// let stablePath: string; if (testCodePath) { electronPath = getBuildElectronPath(testCodePath); - if (stableCodePath) { - stablePath = getBuildElectronPath(stableCodePath); - } + // if (stableCodePath) { + // stablePath = getBuildElectronPath(stableCodePath); + // } } else { testCodePath = getDevElectronPath(); electronPath = testCodePath; @@ -147,96 +161,106 @@ function toUri(path: string): string { return `${path}`; } +async function getKeybindings(): Promise { + if (opts.keybindings) { + console.log('*** Using keybindings: ', opts.keybindings); + const rawKeybindings = fs.readFileSync(opts.keybindings); + fs.writeFileSync(keybindingsPath, rawKeybindings); + } else { + const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/build/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`; + console.log('*** Fetching keybindings...'); + + await new Promise((c, e) => { + https.get(keybindingsUrl, res => { + const output = fs.createWriteStream(keybindingsPath); + res.on('error', e); + output.on('error', e); + output.on('close', c); + res.pipe(output); + }).on('error', e); + }); + } +} + +async function createWorkspaceFile(): Promise { + if (fs.existsSync(workspaceFilePath)) { + return; + } + + console.log('*** Creating workspace file...'); + const workspace = { + folders: [ + { + path: toUri(path.join(workspacePath, 'public')) + }, + { + path: toUri(path.join(workspacePath, 'routes')) + }, + { + path: toUri(path.join(workspacePath, 'views')) + } + ] + }; + + fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t')); +} + +async function setupRepository(): Promise { + if (opts['test-repo']) { + console.log('*** Copying test project repository:', opts['test-repo']); + rimraf.sync(workspacePath); + // not platform friendly + cp.execSync(`cp -R "${opts['test-repo']}" "${workspacePath}"`); + } else { + if (!fs.existsSync(workspacePath)) { + console.log('*** Cloning test project repository...'); + cp.spawnSync('git', ['clone', testRepoUrl, workspacePath]); + } else { + console.log('*** Cleaning test project repository...'); + cp.spawnSync('git', ['fetch'], { cwd: workspacePath }); + cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: workspacePath }); + cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath }); + } + + console.log('*** Running npm install...'); + cp.execSync('npm install', { cwd: workspacePath, stdio: 'inherit' }); + } +} + async function setup(): Promise { console.log('*** Test data:', testDataPath); console.log('*** Preparing smoketest setup...'); - const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/build/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`; - console.log('*** Fetching keybindings...'); - - await new Promise((c, e) => { - https.get(keybindingsUrl, res => { - const output = fs.createWriteStream(keybindingsPath); - res.on('error', e); - output.on('error', e); - output.on('close', c); - res.pipe(output); - }).on('error', e); - }); - - if (!fs.existsSync(workspaceFilePath)) { - console.log('*** Creating workspace file...'); - const workspace = { - folders: [ - { - path: toUri(path.join(workspacePath, 'public')) - }, - { - path: toUri(path.join(workspacePath, 'routes')) - }, - { - path: toUri(path.join(workspacePath, 'views')) - } - ] - }; - - fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t')); - } - - if (!fs.existsSync(workspacePath)) { - console.log('*** Cloning test project repository...'); - cp.spawnSync('git', ['clone', testRepoUrl, workspacePath]); - } else { - console.log('*** Cleaning test project repository...'); - cp.spawnSync('git', ['fetch'], { cwd: workspacePath }); - cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: workspacePath }); - cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath }); - } - - console.log('*** Running npm install...'); - cp.execSync('npm install', { cwd: workspacePath, stdio: 'inherit' }); + await getKeybindings(); + await createWorkspaceFile(); + await setupRepository(); console.log('*** Smoketest setup done!\n'); } -/** - * WebDriverIO 4.8.0 outputs all kinds of "deprecation" warnings - * for common commands like `keys` and `moveToObject`. - * According to https://github.com/Codeception/CodeceptJS/issues/531, - * these deprecation warnings are for Firefox, and have no alternative replacements. - * Since we can't downgrade WDIO as suggested (it's Spectron's dep, not ours), - * we must suppress the warning with a classic monkey-patch. - * - * @see webdriverio/lib/helpers/depcrecationWarning.js - * @see https://github.com/webdriverio/webdriverio/issues/2076 - */ -// Filter out the following messages: -const wdioDeprecationWarning = /^WARNING: the "\w+" command will be deprecated soon../; // [sic] -// Monkey patch: -const warn = console.warn; -console.warn = function suppressWebdriverWarnings(message) { - if (wdioDeprecationWarning.test(message)) { return; } - warn.apply(console, arguments); -}; +function createApp(quality: Quality): Application { + const loggers: Logger[] = []; -function createApp(quality: Quality): SpectronApplication | null { - const path = quality === Quality.Stable ? stablePath : electronPath; - - if (!path) { - return null; + if (opts.verbose) { + loggers.push(new ConsoleLogger()); } - return new SpectronApplication({ + if (opts.log) { + loggers.push(new FileLogger(opts.log)); + } + + return new Application({ quality, - electronPath: path, + codePath: opts.build, workspacePath, userDataDir, extensionsPath, - artifactsPath, workspaceFilePath, - waitTime: parseInt(opts['wait-time'] || '0') || 20 + waitTime: parseInt(opts['wait-time'] || '0') || 20, + logger: new MultiLogger(loggers) }); } + before(async function () { // allow two minutes for setup this.timeout(2 * 60 * 1000); @@ -244,6 +268,7 @@ before(async function () { }); after(async function () { + await new Promise(c => setTimeout(c, 500)); // wait for shutdown await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c())); }); @@ -251,7 +276,7 @@ describe('Data Migration', () => { setupDataMigrationTests(userDataDir, createApp); }); -describe('Everything Else', () => { +describe('Test', () => { before(async function () { const app = createApp(quality); await app!.start(); @@ -262,6 +287,36 @@ describe('Everything Else', () => { await this.app.stop(); }); + if (screenshotsPath) { + afterEach(async function () { + if (this.currentTest.state !== 'failed') { + return; + } + + const app = this.app as Application; + const raw = await app.capturePage(); + const buffer = new Buffer(raw, 'base64'); + + const name = this.currentTest.fullTitle().replace(/[^a-z0-9\-]/ig, '_'); + const screenshotPath = path.join(screenshotsPath, `${name}.png`); + + if (opts.log) { + app.logger.log('*** Screenshot recorded:', screenshotPath); + } + + fs.writeFileSync(screenshotPath, buffer); + }); + } + + if (opts.log) { + beforeEach(async function () { + const app = this.app as Application; + const title = this.currentTest.fullTitle(); + + app.logger.log('*** Test start:', title); + }); + } + setupDataLossTests(); setupDataExplorerTests(); setupDataPreferencesTests(); @@ -272,6 +327,7 @@ describe('Everything Else', () => { setupDataGitTests(); setupDataStatusbarTests(); setupDataExtensionTests(); + setupTerminalTests(); setupDataMultirootTests(); setupDataLocalizationTests(); }); diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts deleted file mode 100644 index 5f9c06dfe1..0000000000 --- a/test/smoke/src/spectron/application.ts +++ /dev/null @@ -1,351 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Application, SpectronClient as WebClient } from 'spectron'; -import { test as testPort } from 'portastic'; -import { SpectronClient } from './client'; -import { ScreenCapturer } from '../helpers/screenshot'; -import { Workbench } from '../areas/workbench/workbench'; -import * as fs from 'fs'; -import * as cp from 'child_process'; -import * as path from 'path'; -import * as mkdirp from 'mkdirp'; -import { sanitize } from '../helpers/utilities'; - -// Just hope random helps us here, cross your fingers! -export async function findFreePort(): Promise { - for (let i = 0; i < 10; i++) { - const port = 10000 + Math.round(Math.random() * 10000); - - if (await testPort(port)) { - return port; - } - } - - throw new Error('Could not find free port!'); -} - -export enum Quality { - Dev, - Insiders, - Stable -} - -export interface SpectronApplicationOptions { - quality: Quality; - electronPath: string; - workspacePath: string; - userDataDir: string; - extensionsPath: string; - artifactsPath: string; - workspaceFilePath: string; - waitTime: number; -} - -/** - * Wraps Spectron's Application instance with its used methods. - */ -export class SpectronApplication { - - private static count = 0; - - private _client: SpectronClient; - private _workbench: Workbench; - private _screenCapturer: ScreenCapturer; - private spectron: Application | undefined; - private keybindings: any[]; private stopLogCollection: (() => Promise) | undefined; - - constructor( - private options: SpectronApplicationOptions - ) { } - - get quality(): Quality { - return this.options.quality; - } - - get client(): SpectronClient { - return this._client; - } - - get webclient(): WebClient { - if (!this.spectron) { - throw new Error('Application not started'); - } - - return this.spectron.client; - } - - get screenCapturer(): ScreenCapturer { - return this._screenCapturer; - } - - get workbench(): Workbench { - return this._workbench; - } - - get workspacePath(): string { - return this.options.workspacePath; - } - - get extensionsPath(): string { - return this.options.extensionsPath; - } - - get userDataPath(): string { - return this.options.userDataDir; - } - - get workspaceFilePath(): string { - return this.options.workspaceFilePath; - } - - private _suiteName: string = 'Init'; - - set suiteName(suiteName: string) { - this._suiteName = suiteName; - this._screenCapturer.suiteName = suiteName; - } - - async start(waitForWelcome: boolean = true): Promise { - await this._start(); - - if (waitForWelcome) { - await this.waitForWelcome(); - } - } - - async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise { - await this.stop(); - await new Promise(c => setTimeout(c, 1000)); - await this._start(options.workspaceOrFolder, options.extraArgs); - } - - private async _start(workspaceOrFolder = this.options.workspacePath, extraArgs: string[] = []): Promise { - await this.retrieveKeybindings(); - cp.execSync('git checkout .', { cwd: this.options.workspacePath }); - await this.startApplication(workspaceOrFolder, extraArgs); - await this.checkWindowReady(); - } - - async reload(): Promise { - await this.workbench.quickopen.runCommand('Reload Window'); - // TODO @sandy: Find a proper condition to wait for reload - await new Promise(c => setTimeout(c, 1500)); - await this.checkWindowReady(); - } - - async stop(): Promise { - if (this.stopLogCollection) { - await this.stopLogCollection(); - this.stopLogCollection = undefined; - } - - if (this.spectron && this.spectron.isRunning()) { - await this.spectron.stop(); - this.spectron = undefined; - } - } - - private async startApplication(workspaceOrFolder: string, extraArgs: string[] = []): Promise { - - let args: string[] = []; - let chromeDriverArgs: string[] = []; - - if (process.env.VSCODE_REPOSITORY) { - args.push(process.env.VSCODE_REPOSITORY as string); - } - - args.push(workspaceOrFolder); - - // Prevent 'Getting Started' web page from opening on clean user-data-dir - args.push('--skip-getting-started'); - - // Prevent 'Getting Started' web page from opening on clean user-data-dir - args.push('--skip-release-notes'); - - // Prevent Quick Open from closing when focus is stolen, this allows concurrent smoketest suite running - args.push('--sticky-quickopen'); - - // Disable telemetry - args.push('--disable-telemetry'); - - // Disable updates - args.push('--disable-updates'); - - // Disable crash reporter - // This seems to be the fix for the strange hangups in which Code stays unresponsive - // and tests finish badly with timeouts, leaving Code running in the background forever - args.push('--disable-crash-reporter'); - - // Ensure that running over custom extensions directory, rather than picking up the one that was used by a tester previously - args.push(`--extensions-dir=${this.options.extensionsPath}`); - - args.push(...extraArgs); - - chromeDriverArgs.push(`--user-data-dir=${this.options.userDataDir}`); - - // Spectron always uses the same port number for the chrome driver - // and it handles gracefully when two instances use the same port number - // This works, but when one of the instances quits, it takes down - // chrome driver with it, leaving the other instance in DISPAIR!!! :( - const port = await findFreePort(); - - // We must get a different port for debugging the smoketest express app - // otherwise concurrent test runs will clash on those ports - const env = { PORT: String(await findFreePort()), ...process.env }; - - const opts: any = { - path: this.options.electronPath, - port, - args, - env, - chromeDriverArgs, - startTimeout: 10000, - requireName: 'nodeRequire' - }; - - const runName = String(SpectronApplication.count++); - let testsuiteRootPath: string | undefined = undefined; - let screenshotsDirPath: string | undefined = undefined; - - if (this.options.artifactsPath) { - testsuiteRootPath = path.join(this.options.artifactsPath, sanitize(runName)); - mkdirp.sync(testsuiteRootPath); - - // Collect screenshots - screenshotsDirPath = path.join(testsuiteRootPath, 'screenshots'); - mkdirp.sync(screenshotsDirPath); - - // Collect chromedriver logs - const chromedriverLogPath = path.join(testsuiteRootPath, 'chromedriver.log'); - opts.chromeDriverLogPath = chromedriverLogPath; - - // Collect webdriver logs - const webdriverLogsPath = path.join(testsuiteRootPath, 'webdriver'); - mkdirp.sync(webdriverLogsPath); - opts.webdriverLogPath = webdriverLogsPath; - } - - this.spectron = new Application(opts); - await this.spectron.start(); - - if (testsuiteRootPath) { - // Collect logs - const mainProcessLogPath = path.join(testsuiteRootPath, 'main.log'); - const rendererProcessLogPath = path.join(testsuiteRootPath, 'renderer.log'); - - const flush = async () => { - if (!this.spectron) { - return; - } - - const mainLogs = await this.spectron.client.getMainProcessLogs(); - await new Promise((c, e) => fs.appendFile(mainProcessLogPath, mainLogs.join('\n'), { encoding: 'utf8' }, err => err ? e(err) : c())); - - const rendererLogs = (await this.spectron.client.getRenderProcessLogs()).map(m => `${m.timestamp} - ${m.level} - ${m.message}`); - await new Promise((c, e) => fs.appendFile(rendererProcessLogPath, rendererLogs.join('\n'), { encoding: 'utf8' }, err => err ? e(err) : c())); - }; - - let running = true; - const loopFlush = async () => { - while (true) { - await flush(); - - if (!running) { - return; - } - - await new Promise(c => setTimeout(c, 1000)); - } - }; - - const loopPromise = loopFlush(); - this.stopLogCollection = () => { - running = false; - return loopPromise; - }; - } - - this._screenCapturer = new ScreenCapturer(this.spectron, this._suiteName, screenshotsDirPath); - this._client = new SpectronClient(this.spectron, this, this.options.waitTime); - this._workbench = new Workbench(this); - } - - private async checkWindowReady(): Promise { - await this.webclient.waitUntilWindowLoaded(); - - // Pick the first workbench window here - const count = await this.webclient.getWindowCount(); - - for (let i = 0; i < count; i++) { - await this.webclient.windowByIndex(i); - - if (/bootstrap\/index\.html/.test(await this.webclient.getUrl())) { - break; - } - } - - await this.client.waitForElement('.monaco-workbench'); - } - - private async waitForWelcome(): Promise { - await this.client.waitForElement('.explorer-folders-view'); - await this.client.waitForElement(`.editor-container[id="workbench.editor.walkThroughPart"] .welcomePage`); - } - - private retrieveKeybindings(): Promise { - return new Promise((c, e) => { - fs.readFile(process.env.VSCODE_KEYBINDINGS_PATH as string, 'utf8', (err, data) => { - if (err) { - throw err; - } - try { - this.keybindings = JSON.parse(data); - c(); - } catch (e) { - throw new Error(`Error parsing keybindings JSON: ${e}`); - } - }); - }); - } - - /** - * Retrieves the command from keybindings file and executes it with WebdriverIO client API - * @param command command (e.g. 'workbench.action.files.newUntitledFile') - */ - runCommand(command: string): Promise { - const binding = this.keybindings.find(x => x['command'] === command); - if (!binding) { - return this.workbench.quickopen.runCommand(command); - } - - const keys: string = binding.key; - let keysToPress: string[] = []; - - const chords = keys.split(' '); - chords.forEach((chord) => { - const keys = chord.split('+'); - keys.forEach((key) => keysToPress.push(this.transliterate(key))); - keysToPress.push('NULL'); - }); - - return this.client.keys(keysToPress); - } - - /** - * Transliterates key names from keybindings file to WebdriverIO keyboard actions defined in: - * https://w3c.github.io/webdriver/webdriver-spec.html#keyboard-actions - */ - private transliterate(key: string): string { - switch (key) { - case 'ctrl': - return 'Control'; - case 'cmd': - return 'Meta'; - default: - return key.length === 1 ? key : key.charAt(0).toUpperCase() + key.slice(1); - } - } -} diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts deleted file mode 100644 index b550f92f5b..0000000000 --- a/test/smoke/src/spectron/client.ts +++ /dev/null @@ -1,204 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Application } from 'spectron'; -import { RawResult, Element } from 'webdriverio'; -import { SpectronApplication } from './application'; - -/** - * Abstracts the Spectron's WebdriverIO managed client property on the created Application instances. - */ -export class SpectronClient { - - // waitFor calls should not take more than 200 * 100 = 20 seconds to complete, excluding - // the time it takes for the actual retry call to complete - private retryCount: number; - private readonly retryDuration = 100; // in milliseconds - - constructor( - readonly spectron: Application, - private application: SpectronApplication, - waitTime: number - ) { - this.retryCount = (waitTime * 1000) / this.retryDuration; - } - - keys(keys: string[]): Promise { - this.spectron.client.keys(keys); - return Promise.resolve(); - } - - async getText(selector: string, capture: boolean = true): Promise { - return this.spectron.client.getText(selector); - } - - async waitForText(selector: string, text?: string, accept?: (result: string) => boolean): Promise { - accept = accept ? accept : result => text !== void 0 ? text === result : !!result; - return this.waitFor(() => this.spectron.client.getText(selector), accept, `getText with selector ${selector}`); - } - - async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean): Promise { - accept = accept ? accept : (result => textContent !== void 0 ? textContent === result : !!result); - const fn = async () => await this.spectron.client.selectorExecute(selector, div => Array.isArray(div) ? div[0].textContent : div.textContent); - return this.waitFor(fn, s => accept!(typeof s === 'string' ? s : ''), `getTextContent with selector ${selector}`); - } - - async waitForValue(selector: string, value?: string, accept?: (result: string) => boolean): Promise { - accept = accept ? accept : result => value !== void 0 ? value === result : !!result; - return this.waitFor(() => this.spectron.client.getValue(selector), accept, `getValue with selector ${selector}`); - } - - async waitAndClick(selector: string): Promise { - return this.waitFor(() => this.spectron.client.click(selector), void 0, `click with selector ${selector}`); - } - - async click(selector: string): Promise { - return this.spectron.client.click(selector); - } - - async doubleClickAndWait(selector: string, capture: boolean = true): Promise { - return this.waitFor(() => this.spectron.client.doubleClick(selector), void 0, `doubleClick with selector ${selector}`); - } - - async leftClick(selector: string, xoffset: number, yoffset: number, capture: boolean = true): Promise { - return this.spectron.client.leftClick(selector, xoffset, yoffset); - } - - async rightClick(selector: string, capture: boolean = true): Promise { - return this.spectron.client.rightClick(selector); - } - - async moveToObject(selector: string, capture: boolean = true): Promise { - return this.spectron.client.moveToObject(selector); - } - - async waitAndMoveToObject(selector: string): Promise { - return this.waitFor(() => this.spectron.client.moveToObject(selector), void 0, `move to object with selector ${selector}`); - } - - async setValue(selector: string, text: string, capture: boolean = true): Promise { - return this.spectron.client.setValue(selector, text); - } - - async waitForElements(selector: string, accept: (result: Element[]) => boolean = result => result.length > 0): Promise { - return this.waitFor>(() => this.spectron.client.elements(selector), result => accept(result.value), `elements with selector ${selector}`) - .then(result => result.value); - } - - async waitForElement(selector: string, accept: (result: Element | undefined) => boolean = result => !!result): Promise { - return this.waitFor>(() => this.spectron.client.element(selector), result => accept(result ? result.value : void 0), `element with selector ${selector}`) - .then(result => result.value); - } - - async waitForVisibility(selector: string, accept: (result: boolean) => boolean = result => result): Promise { - return this.waitFor(() => this.spectron.client.isVisible(selector), accept, `isVisible with selector ${selector}`); - } - - async element(selector: string): Promise { - return this.spectron.client.element(selector) - .then(result => result.value); - } - - async waitForActiveElement(selector: string): Promise { - return this.waitFor( - () => this.spectron.client.execute(s => document.activeElement.matches(s), selector), - r => r.value, - `wait for active element: ${selector}` - ); - } - - async waitForAttribute(selector: string, attribute: string, accept: (result: string) => boolean = result => !!result): Promise { - return this.waitFor(() => this.spectron.client.getAttribute(selector), accept, `attribute with selector ${selector}`); - } - - async dragAndDrop(sourceElem: string, destinationElem: string, capture: boolean = true): Promise { - return this.spectron.client.dragAndDrop(sourceElem, destinationElem); - } - - async selectByValue(selector: string, value: string, capture: boolean = true): Promise { - return this.spectron.client.selectByValue(selector, value); - } - - async getValue(selector: string, capture: boolean = true): Promise { - return this.spectron.client.getValue(selector); - } - - async getAttribute(selector: string, attribute: string, capture: boolean = true): Promise { - return Promise.resolve(this.spectron.client.getAttribute(selector, attribute)); - } - - buttonDown(): any { - return this.spectron.client.buttonDown(); - } - - buttonUp(): any { - return this.spectron.client.buttonUp(); - } - - async isVisible(selector: string, capture: boolean = true): Promise { - return this.spectron.client.isVisible(selector); - } - - async getTitle(): Promise { - return this.spectron.client.getTitle(); - } - - private running = false; - async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; - async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { - if (this.running) { - throw new Error('Not allowed to run nested waitFor calls!'); - } - - this.running = true; - - try { - let trial = 1; - retryCount = typeof retryCount === 'number' ? retryCount : this.retryCount; - - while (true) { - if (trial > retryCount) { - await this.application.screenCapturer.capture('timeout'); - throw new Error(`${timeoutMessage}: Timed out after ${(retryCount * this.retryDuration) / 1000} seconds.`); - } - - let result; - try { - result = await func(); - } catch (e) { - // console.log(e); - } - - if (accept(result)) { - return result; - } - - await new Promise(resolve => setTimeout(resolve, this.retryDuration)); - trial++; - } - } finally { - this.running = false; - } - } - - // type(text: string): Promise { - // return new Promise((res) => { - // let textSplit = text.split(' '); - - // const type = async (i: number) => { - // if (!textSplit[i] || textSplit[i].length <= 0) { - // return res(); - // } - - // const toType = textSplit[i + 1] ? `${textSplit[i]} ` : textSplit[i]; - // await this.keys(toType); - // await this.keys(['NULL']); - // await type(i + 1); - // }; - - // return type(0); - // }); - // } -} \ No newline at end of file diff --git a/test/smoke/src/vscode/code.ts b/test/smoke/src/vscode/code.ts new file mode 100644 index 0000000000..e70cb62824 --- /dev/null +++ b/test/smoke/src/vscode/code.ts @@ -0,0 +1,324 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as cp from 'child_process'; +import * as os from 'os'; +import { tmpName } from 'tmp'; +import { IDriver, connect as connectDriver, IDisposable, IElement } from './driver'; +import { Logger } from '../logger'; + +const repoPath = path.join(__dirname, '../../../..'); + +function getDevElectronPath(): string { + const buildPath = path.join(repoPath, '.build'); + const product = require(path.join(repoPath, 'product.json')); + + switch (process.platform) { + case 'darwin': + return path.join(buildPath, 'electron', `${product.nameLong}.app`, 'Contents', 'MacOS', 'Electron'); + case 'linux': + return path.join(buildPath, 'electron', `${product.applicationName}`); + case 'win32': + return path.join(buildPath, 'electron', `${product.nameShort}.exe`); + default: + throw new Error('Unsupported platform.'); + } +} + +function getBuildElectronPath(root: string): string { + switch (process.platform) { + case 'darwin': + return path.join(root, 'Contents', 'MacOS', 'Electron'); + case 'linux': { + const product = require(path.join(root, 'resources', 'app', 'product.json')); + return path.join(root, product.applicationName); + } + case 'win32': { + const product = require(path.join(root, 'resources', 'app', 'product.json')); + return path.join(root, `${product.nameShort}.exe`); + } + default: + throw new Error('Unsupported platform.'); + } +} + +function getDevOutPath(): string { + return path.join(repoPath, 'out'); +} + +function getBuildOutPath(root: string): string { + switch (process.platform) { + case 'darwin': + return path.join(root, 'Contents', 'Resources', 'app', 'out'); + default: + return path.join(root, 'resources', 'app', 'out'); + } +} + +async function connect(child: cp.ChildProcess, outPath: string, handlePath: string, logger: Logger): Promise { + let errCount = 0; + + while (true) { + try { + const { client, driver } = await connectDriver(outPath, handlePath); + return new Code(child, client, driver, logger); + } catch (err) { + if (++errCount > 50) { + child.kill(); + throw err; + } + + // retry + await new Promise(c => setTimeout(c, 100)); + } + } +} + +// Kill all running instances, when dead +const instances = new Set(); +process.once('exit', () => instances.forEach(code => code.kill())); + +export interface SpawnOptions { + codePath?: string; + workspacePath: string; + userDataDir: string; + extensionsPath: string; + logger: Logger; + extraArgs?: string[]; +} + +async function createDriverHandle(): Promise { + if ('win32' === os.platform()) { + const name = [...Array(15)].map(() => Math.random().toString(36)[3]).join(''); + return `\\\\.\\pipe\\${name}`; + } else { + return await new Promise((c, e) => tmpName((err, handlePath) => err ? e(err) : c(handlePath))); + } +} + +export async function spawn(options: SpawnOptions): Promise { + const codePath = options.codePath; + const electronPath = codePath ? getBuildElectronPath(codePath) : getDevElectronPath(); + const outPath = codePath ? getBuildOutPath(codePath) : getDevOutPath(); + const handle = await createDriverHandle(); + + const args = [ + options.workspacePath, + '--skip-getting-started', + '--skip-release-notes', + '--sticky-quickopen', + '--disable-telemetry', + '--disable-updates', + '--disable-crash-reporter', + `--extensions-dir=${options.extensionsPath}`, + `--user-data-dir=${options.userDataDir}`, + '--driver', handle + ]; + + if (!codePath) { + args.unshift(repoPath); + } + + if (options.extraArgs) { + args.push(...options.extraArgs); + } + + const spawnOptions: cp.SpawnOptions = {}; + + const child = cp.spawn(electronPath, args, spawnOptions); + + instances.add(child); + child.once('exit', () => instances.delete(child)); + + return connect(child, outPath, handle, options.logger); +} + +async function poll( + fn: () => Promise, + acceptFn: (result: T) => boolean, + timeoutMessage: string, + retryCount: number = 200, + retryInterval: number = 100 // millis +): Promise { + let trial = 1; + + while (true) { + if (trial > retryCount) { + throw new Error(`Timeout: ${timeoutMessage} after ${(retryCount * retryInterval) / 1000} seconds.`); + } + + let result; + try { + result = await fn(); + + if (acceptFn(result)) { + return result; + } + } catch (e) { + // console.warn(e); + + if (/Method not implemented/.test(e.message)) { + throw e; + } + } + + await new Promise(resolve => setTimeout(resolve, retryInterval)); + trial++; + } +} + +export class Code { + + private _activeWindowId: number | undefined = undefined; + private driver: IDriver; + + constructor( + private process: cp.ChildProcess, + private client: IDisposable, + driver: IDriver, + readonly logger: Logger + ) { + this.driver = new Proxy(driver, { + get(target, prop, receiver) { + if (typeof target[prop] !== 'function') { + return target[prop]; + } + + return function (...args) { + logger.log(`${prop}`, ...args.filter(a => typeof a === 'string')); + return target[prop].apply(this, args); + }; + } + }); + } + + async capturePage(): Promise { + const windowId = await this.getActiveWindowId(); + return await this.driver.capturePage(windowId); + } + + async waitForWindowIds(fn: (windowIds: number[]) => boolean): Promise { + await poll(() => this.driver.getWindowIds(), fn, `get window ids`); + } + + async dispatchKeybinding(keybinding: string): Promise { + const windowId = await this.getActiveWindowId(); + await this.driver.dispatchKeybinding(windowId, keybinding); + } + + async reload(): Promise { + const windowId = await this.getActiveWindowId(); + await this.driver.reloadWindow(windowId); + } + + async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean): Promise { + const windowId = await this.getActiveWindowId(); + accept = accept || (result => textContent !== void 0 ? textContent === result : !!result); + return await poll(() => this.driver.getElements(windowId, selector).then(els => els[0].textContent), s => accept!(typeof s === 'string' ? s : ''), `get text content '${selector}'`); + } + + async waitAndClick(selector: string, xoffset?: number, yoffset?: number): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.click(windowId, selector, xoffset, yoffset), () => true, `click '${selector}'`); + } + + async waitAndDoubleClick(selector: string): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.doubleClick(windowId, selector), () => true, `double click '${selector}'`); + } + + async waitAndMove(selector: string): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.move(windowId, selector), () => true, `move '${selector}'`); + } + + async waitForSetValue(selector: string, value: string): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.setValue(windowId, selector, value), () => true, `set value '${selector}'`); + } + + async waitForPaste(selector: string, value: string): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.paste(windowId, selector, value), () => true, `paste '${selector}'`); + } + + async waitForElements(selector: string, recursive: boolean, accept: (result: IElement[]) => boolean = result => result.length > 0): Promise { + const windowId = await this.getActiveWindowId(); + return await poll(() => this.driver.getElements(windowId, selector, recursive), accept, `get elements '${selector}'`); + } + + async waitForElement(selector: string, accept: (result: IElement | undefined) => boolean = result => !!result, retryCount: number = 200): Promise { + const windowId = await this.getActiveWindowId(); + return await poll(() => this.driver.getElements(windowId, selector).then(els => els[0]), accept, `get element '${selector}'`, retryCount); + } + + async waitForActiveElement(selector: string, retryCount: number = 200): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.isActiveElement(windowId, selector), r => r, `is active element '${selector}'`, retryCount); + } + + async waitForTitle(fn: (title: string) => boolean): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.getTitle(windowId), fn, `get title`); + } + + async waitForTypeInEditor(selector: string, text: string): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.typeInEditor(windowId, selector, text), () => true, `type in editor '${selector}'`); + } + + async waitForTerminalBuffer(selector: string, accept: (result: string[]) => boolean): Promise { + const windowId = await this.getActiveWindowId(); + await poll(() => this.driver.getTerminalBuffer(windowId, selector), accept, `get terminal buffer '${selector}'`); + } + + private async getActiveWindowId(): Promise { + if (typeof this._activeWindowId !== 'number') { + const windows = await this.driver.getWindowIds(); + this._activeWindowId = windows[0]; + } + + return this._activeWindowId; + } + + dispose(): void { + this.client.dispose(); + this.process.kill(); + } +} + +export function findElement(element: IElement, fn: (element: IElement) => boolean): IElement | null { + const queue = [element]; + + while (queue.length > 0) { + const element = queue.shift()!; + + if (fn(element)) { + return element; + } + + queue.push(...element.children); + } + + return null; +} + +export function findElements(element: IElement, fn: (element: IElement) => boolean): IElement[] { + const result: IElement[] = []; + const queue = [element]; + + while (queue.length > 0) { + const element = queue.shift()!; + + if (fn(element)) { + result.push(element); + } + + queue.push(...element.children); + } + + return result; +} \ No newline at end of file diff --git a/extensions/markdown/src/util/dispose.ts b/test/smoke/src/vscode/driver.js similarity index 53% rename from extensions/markdown/src/util/dispose.ts rename to test/smoke/src/vscode/driver.js index fbce45d605..8b94dbf56d 100644 --- a/extensions/markdown/src/util/dispose.ts +++ b/test/smoke/src/vscode/driver.js @@ -3,14 +3,10 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; - -export function disposeAll(disposables: vscode.Disposable[]) { - while (disposables.length) { - const item = disposables.pop(); - if (item) { - item.dispose(); - } - } -} +const path = require('path'); +exports.connect = function (outPath, handle) { + const bootstrapPath = path.join(outPath, 'bootstrap-amd.js'); + const { bootstrap } = require(bootstrapPath); + return new Promise((c, e) => bootstrap('vs/platform/driver/node/driver', ({ connect }) => connect(handle).then(c, e), e)); +}; \ No newline at end of file diff --git a/test/smoke/test/mocha.opts b/test/smoke/test/mocha.opts index 102d5b65ad..9f76965562 100644 --- a/test/smoke/test/mocha.opts +++ b/test/smoke/test/mocha.opts @@ -1,3 +1,3 @@ ---timeout 60000 +--timeout 20000 --slow 20000 out/main.js \ No newline at end of file diff --git a/test/smoke/tools/copy-driver-definition.js b/test/smoke/tools/copy-driver-definition.js new file mode 100644 index 0000000000..8acbc3927d --- /dev/null +++ b/test/smoke/tools/copy-driver-definition.js @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const fs = require('fs'); +const path = require('path'); + +const root = path.dirname(path.dirname(path.dirname(__dirname))); +const driverPath = path.join(root, 'src/vs/platform/driver/common/driver.ts'); + +let contents = fs.readFileSync(driverPath, 'utf8'); +contents = /\/\/\*START([\s\S]*)\/\/\*END/mi.exec(contents)[1].trim(); +contents = contents.replace(/\bTPromise\b/g, 'Promise'); + +contents = `/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +${contents} + +export interface IDisposable { + dispose(): void; +} + +export function connect(outPath: string, handle: string): Promise<{ client: IDisposable, driver: IDriver }>; +`; + +const srcPath = path.join(path.dirname(__dirname), 'src/vscode'); +const outDriverPath = path.join(srcPath, 'driver.d.ts'); + +fs.writeFileSync(outDriverPath, contents); \ No newline at end of file diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 0508d361c3..2f15aec327 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -58,6 +58,17 @@ dependencies: "@types/node" "*" +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + ajv@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" @@ -67,56 +78,66 @@ ajv@^5.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -ansi-escapes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" +ansi-regex@^0.2.0, ansi-regex@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" +ansi-styles@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" -ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" dependencies: - color-convert "^1.9.0" - -archiver-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" - dependencies: - glob "^7.0.0" - graceful-fs "^4.1.0" - lazystream "^1.0.0" - lodash "^4.8.0" + micromatch "^2.1.5" normalize-path "^2.0.0" - readable-stream "^2.0.0" -archiver@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.0.tgz#d2df2e8d5773a82c1dcce925ccc41450ea999afd" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" dependencies: - archiver-utils "^1.3.0" - async "^2.0.0" - buffer-crc32 "^0.2.1" - glob "^7.0.0" - lodash "^4.8.0" - readable-stream "^2.0.0" - tar-stream "^1.5.0" - zip-stream "^1.2.0" + delegates "^1.0.0" + readable-stream "^2.0.6" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -125,29 +146,35 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -async@^2.0.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - dependencies: - lodash "^4.14.0" +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" +aws4@^1.2.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-runtime@^6.26.0: +babel-runtime@^6.9.2: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -164,16 +191,26 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" dependencies: - readable-stream "^2.0.5" + inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + boom@4.x.x: version "4.3.1" resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" @@ -193,14 +230,18 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" -buffer-crc32@^0.2.1: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -220,23 +261,30 @@ caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -chalk@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" +chalk@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + ansi-styles "^1.1.0" + escape-string-regexp "^1.0.0" + has-ansi "^0.1.0" + strip-ansi "^0.3.0" + supports-color "^0.2.0" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" +chokidar@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: - restore-cursor "^2.0.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" co@^4.6.0: version "4.6.0" @@ -246,22 +294,16 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: delayed-stream "~1.0.0" +commander@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" + commander@2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -272,15 +314,6 @@ commander@^2.8.1: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" -compress-commons@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" - dependencies: - buffer-crc32 "^0.2.1" - crc32-stream "^2.0.0" - normalize-path "^2.0.0" - readable-stream "^2.0.0" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -293,6 +326,23 @@ concat-stream@1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" +concurrently@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.1.tgz#ee8b60018bbe86b02df13e5249453c6ececd2521" + dependencies: + chalk "0.5.1" + commander "2.6.0" + date-fns "^1.23.0" + lodash "^4.5.1" + rx "2.3.24" + spawn-command "^0.0.2-1" + supports-color "^3.2.3" + tree-kill "^1.1.0" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + core-js@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" @@ -301,16 +351,27 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -crc32-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" +cpx@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/cpx/-/cpx-1.5.0.tgz#185be018511d87270dedccc293171e37655ab88f" dependencies: - crc "^3.4.4" - readable-stream "^2.0.0" + babel-runtime "^6.9.2" + chokidar "^1.6.0" + duplexer "^0.1.1" + glob "^7.0.5" + glob2base "^0.0.12" + minimatch "^3.0.2" + mkdirp "^0.5.1" + resolve "^1.1.7" + safe-buffer "^5.0.1" + shell-quote "^1.6.1" + subarg "^1.0.0" -crc@^3.4.4: - version "3.5.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964" +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" cryptiles@3.x.x: version "3.1.2" @@ -318,25 +379,6 @@ cryptiles@3.x.x: dependencies: boom "5.x.x" -css-parse@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" - dependencies: - css "^2.0.0" - -css-value@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/css-value/-/css-value-0.0.1.tgz#5efd6c2eea5ea1fd6b6ac57ec0427b18452424ea" - -css@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" - dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.3.0" - urix "^0.1.0" - currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -349,6 +391,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.23.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + debug@2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" @@ -369,17 +415,17 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deepmerge@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.0.1.tgz#25c1c24f110fb914f80001b925264dd77f3f4312" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" -dev-null@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dev-null/-/dev-null-0.1.1.tgz#5a205ce3c2b2ef77b6238d6ba179eb74c6a0e818" +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" diff@3.2.0: version "3.2.0" @@ -413,23 +459,16 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" dependencies: jsbn "~0.1.0" -ejs@~2.5.6: - version "2.5.7" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a" - -electron-chromedriver@~1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/electron-chromedriver/-/electron-chromedriver-1.7.1.tgz#008c97976007aa4eb18491ee095e94d17ee47610" - dependencies: - electron-download "^4.1.0" - extract-zip "^1.6.5" - electron-download@^3.0.1: version "3.3.0" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-3.3.0.tgz#2cfd54d6966c019c4d49ad65fbe65cc9cdef68c8" @@ -444,20 +483,6 @@ electron-download@^3.0.1: semver "^5.3.0" sumchecker "^1.2.0" -electron-download@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.0.tgz#bf932c746f2f87ffcc09d1dd472f2ff6b9187845" - dependencies: - debug "^2.2.0" - env-paths "^1.0.0" - fs-extra "^2.0.0" - minimist "^1.2.0" - nugget "^2.0.0" - path-exists "^3.0.0" - rc "^1.1.2" - semver "^5.3.0" - sumchecker "^2.0.1" - electron@1.7.7: version "1.7.7" resolved "https://registry.yarnpkg.com/electron/-/electron-1.7.7.tgz#cfd89ca9eba79d763ac0b0c6dcc583792097b9b6" @@ -466,20 +491,10 @@ electron@1.7.7: electron-download "^3.0.1" extract-zip "^1.0.3" -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - dependencies: - once "^1.4.0" - entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - error-ex@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" @@ -490,23 +505,39 @@ es6-promise@^4.0.5: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -extend@~3.0.1: +exec-sh@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" + dependencies: + merge "^1.1.3" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.0.4: - version "2.0.5" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.5.tgz#52c249a3981b9ba187c7cacf5beb50bf1d91a6bc" +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" dependencies: - iconv-lite "^0.4.17" - jschardet "^1.4.2" - tmp "^0.0.33" + is-extglob "^1.0.0" -extract-zip@^1.0.3, extract-zip@^1.6.5: +extract-zip@^1.0.3: version "1.6.6" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" dependencies: @@ -533,11 +564,23 @@ fd-slicer@~1.0.1: dependencies: pend "~1.2.0" -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" dependencies: - escape-string-regexp "^1.0.5" + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" find-up@^1.0.0: version "1.1.2" @@ -546,10 +589,28 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + form-data@~2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" @@ -568,22 +629,46 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -gaze@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" +fsevents@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" dependencies: - globule "^1.0.0" + nan "^2.3.0" + node-pre-gyp "^0.6.39" + +fstream-ignore@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" get-stdin@^4.0.1: version "4.0.1" @@ -595,6 +680,25 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + dependencies: + find-index "^0.1.1" + glob@7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" @@ -606,7 +710,7 @@ glob@7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.5, glob@~7.1.1: +glob@^7.0.5: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -617,15 +721,7 @@ glob@^7.0.0, glob@^7.0.5, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -globule@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" - dependencies: - glob "~7.1.1" - lodash "~4.17.4" - minimatch "~3.0.2" - -graceful-fs@^4.1.0, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -637,10 +733,21 @@ growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + har-validator@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" @@ -648,13 +755,28 @@ har-validator@~5.0.3: ajv "^5.1.0" har-schema "^2.0.0" +has-ansi@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" + dependencies: + ansi-regex "^0.2.0" + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +hawk@3.1.3, hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" hawk@~6.0.2: version "6.0.2" @@ -669,6 +791,10 @@ he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" @@ -692,6 +818,14 @@ htmlparser2@^3.9.2: inherits "^2.0.1" readable-stream "^2.0.2" +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -700,10 +834,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@^0.4.17: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" @@ -717,7 +847,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -725,35 +855,44 @@ ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" dependencies: builtin-modules "^1.0.0" +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -766,13 +905,31 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" -is-promise@^2.1.0: +is-number@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" is-typedarray@~1.0.0: version "1.0.0" @@ -786,10 +943,16 @@ isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -798,10 +961,6 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" -jschardet@^1.4.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678" - json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -810,6 +969,12 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -824,6 +989,10 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -833,18 +1002,24 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" optionalDependencies: graceful-fs "^4.1.9" -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - dependencies: - readable-stream "^2.0.5" - load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -902,9 +1077,9 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash@^4.14.0, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +lodash@^4.5.1: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" loud-rejection@^1.0.0: version "1.6.0" @@ -932,21 +1107,49 @@ meow@^3.1.0: redent "^1.0.0" trim-newlines "^1.0.0" +merge@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + mime-types@^2.1.12, mime-types@~2.1.17: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" -mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" +mime-types@~2.1.7: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -960,17 +1163,13 @@ minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - mkdirp@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" dependencies: minimist "0.0.8" -mkdirp@0.5.1, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -997,14 +1196,37 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" +nan@^2.3.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" ncp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" +node-pre-gyp@^0.6.39: + version "0.6.39" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" + dependencies: + detect-libc "^1.0.2" + hawk "3.1.3" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" @@ -1014,15 +1236,20 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0: +normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" -npm-install-package@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/npm-install-package/-/npm-install-package-2.1.0.tgz#d7efe3cfcd7ab00614b896ea53119dc9ab259125" +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" nugget@^2.0.0: version "2.0.1" @@ -1040,11 +1267,11 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -oauth-sign@~0.8.2: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@^4.0.1: +object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -1052,29 +1279,43 @@ object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" -once@^1.3.0, once@^1.4.0: +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0, once@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -optimist@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -1087,14 +1328,14 @@ path-exists@^2.0.0, path-exists@^2.1.0: dependencies: pinkie-promise "^2.0.0" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -1107,6 +1348,10 @@ pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -1133,6 +1378,10 @@ portastic@^1.0.1: commander "^2.8.1" debug "^2.2.0" +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + pretty-bytes@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" @@ -1144,6 +1393,10 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + progress-stream@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" @@ -1151,25 +1404,24 @@ progress-stream@^1.1.0: speedometer "~0.1.2" through2 "~0.2.3" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" rc@^1.1.2: version "1.2.2" @@ -1180,6 +1432,15 @@ rc@^1.1.2: minimist "^1.2.0" strip-json-comments "~2.0.1" +rc@^1.1.7: + version "1.2.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -1195,7 +1456,7 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2: +readable-stream@^2.0.2, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -1207,6 +1468,18 @@ readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@^2.0.6, readable-stream@^2.1.4: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -1216,6 +1489,15 @@ readable-stream@~1.1.9: isarray "0.0.1" string_decoder "~0.10.x" +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -1227,17 +1509,58 @@ regenerator-runtime@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: is-finite "^1.0.0" -request@^2.45.0, request@^2.81.0, request@~2.83.0: +request@2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@^2.45.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -1264,42 +1587,21 @@ request@^2.45.0, request@^2.81.0, request@~2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -resolve-url@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" +resolve@^1.1.7: + version "1.7.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.0.tgz#2bdf5374811207285df0df652b78f118ab8f3c5e" dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" + path-parse "^1.0.5" -rgb2hex@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.1.0.tgz#ccd55f860ae0c5c4ea37504b958e442d8d12325b" - -rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" +rx@2.3.24: + version "2.3.24" + resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" @@ -1309,7 +1611,24 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" -signal-exit@^3.0.0, signal-exit@^3.0.2: +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +signal-exit@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -1319,30 +1638,21 @@ single-line-log@^1.1.2: dependencies: string-width "^1.0.1" +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + sntp@2.x.x: version "2.1.0" resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" dependencies: hoek "4.x.x" -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" - dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" - -source-map@^0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" +spawn-command@^0.0.2-1: + version "0.0.2-1" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" spdx-correct@~1.0.0: version "1.0.2" @@ -1358,26 +1668,10 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -spectron@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/spectron/-/spectron-3.7.2.tgz#86f41306a9b70ed6ee1500f7f7d3adc389afb446" - dependencies: - dev-null "^0.1.1" - electron-chromedriver "~1.7.1" - request "^2.81.0" - split "^1.0.0" - webdriverio "^4.8.0" - speedometer@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - dependencies: - through "2" - sshpk@^1.7.0: version "1.13.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" @@ -1392,7 +1686,7 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -string-width@^1.0.1: +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: @@ -1400,13 +1694,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -1417,22 +1704,28 @@ string_decoder@~1.0.3: dependencies: safe-buffer "~5.1.0" -stringstream@~0.0.5: +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" -strip-ansi@^3.0.0: +strip-ansi@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" + dependencies: + ansi-regex "^0.2.1" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -1449,6 +1742,12 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + dependencies: + minimist "^1.1.0" + sumchecker@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-1.3.1.tgz#79bb3b4456dd04f18ebdbc0d703a1d1daec5105d" @@ -1456,38 +1755,42 @@ sumchecker@^1.2.0: debug "^2.2.0" es6-promise "^4.0.5" -sumchecker@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e" - dependencies: - debug "^2.2.0" - supports-color@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" dependencies: has-flag "^1.0.0" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - dependencies: - has-flag "^2.0.0" +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" -supports-color@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.0.0.tgz#1db26229f6ae02f9acdb5410907c36ce2e362b13" +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: - has-flag "^2.0.0" + has-flag "^1.0.0" -tar-stream@^1.5.0: - version "1.5.5" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" +tar-pack@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" dependencies: - bl "^1.0.0" - end-of-stream "^1.0.0" - readable-stream "^2.0.0" - xtend "^4.0.0" + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" throttleit@0.0.2: version "0.0.2" @@ -1500,22 +1803,28 @@ through2@~0.2.3: readable-stream "~1.1.9" xtend "~2.1.1" -through@2, through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -tmp@0.0.33, tmp@^0.0.33: +tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" dependencies: os-tmpdir "~1.0.2" +tough-cookie@~2.3.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: punycode "^1.4.1" +tree-kill@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -1538,21 +1847,18 @@ typescript@2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34" -urix@^0.1.0, urix@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -url@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - dependencies: - punycode "1.3.2" - querystring "0.2.0" +uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" +uuid@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -1564,10 +1870,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" -validator@~9.1.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.1.1.tgz#3bdd1065cbd28f9d96ac806dee01030d32fd97ef" - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -1576,53 +1878,23 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -wdio-dot-reporter@~0.0.8: - version "0.0.9" - resolved "https://registry.yarnpkg.com/wdio-dot-reporter/-/wdio-dot-reporter-0.0.9.tgz#929b2adafd49d6b0534fda068e87319b47e38fe5" - -webdriverio@^4.8.0: - version "4.9.8" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-4.9.8.tgz#907180e715d3b9e16cabe20bad59854bec1e44fa" +watch@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/watch/-/watch-1.0.2.tgz#340a717bde765726fa0aa07d721e0147a551df0c" dependencies: - archiver "~2.1.0" - babel-runtime "^6.26.0" - css-parse "~2.0.0" - css-value "~0.0.1" - deepmerge "~2.0.1" - ejs "~2.5.6" - gaze "~1.1.2" - glob "~7.1.1" - inquirer "~3.3.0" - json-stringify-safe "~5.0.1" - mkdirp "~0.5.1" - npm-install-package "~2.1.0" - optimist "~0.6.1" - q "~1.5.0" - request "~2.83.0" - rgb2hex "~0.1.0" - safe-buffer "~5.1.1" - supports-color "~5.0.0" - url "~0.11.0" - validator "~9.1.1" - wdio-dot-reporter "~0.0.8" - wgxpath "~1.0.0" + exec-sh "^0.2.0" + minimist "^1.2.0" -wgxpath@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wgxpath/-/wgxpath-1.0.0.tgz#eef8a4b9d558cc495ad3a9a2b751597ecd9af690" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" @@ -1634,12 +1906,3 @@ yauzl@2.4.1: resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" dependencies: fd-slicer "~1.0.1" - -zip-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" - dependencies: - archiver-utils "^1.3.0" - compress-commons "^1.2.0" - lodash "^4.8.0" - readable-stream "^2.0.0" diff --git a/tsfmt.json b/tsfmt.json index fffcf07c19..72a3195dbc 100644 --- a/tsfmt.json +++ b/tsfmt.json @@ -1,7 +1,6 @@ { "tabSize": 4, "indentSize": 4, - "newLineCharacter": "\n", "convertTabsToSpaces": false, "insertSpaceAfterCommaDelimiter": true, "insertSpaceAfterSemicolonInForStatements": true, @@ -14,4 +13,4 @@ "insertSpaceBeforeFunctionParenthesis": false, "placeOpenBraceOnNewLineForFunctions": false, "placeOpenBraceOnNewLineForControlBlocks": false -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index cd8cbc0b29..afb0737098 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,6 +53,12 @@ normalize-path "^2.0.1" through2 "^2.0.3" +"@types/commander@^2.11.0": + version "2.12.2" + resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae" + dependencies: + commander "*" + "@types/keytar@4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/keytar/-/keytar-4.0.1.tgz#e2cf6405dc33861424e59b67516c66d2cf7bc21b" @@ -73,6 +79,10 @@ version "5.3.30" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.3.30.tgz#b55a3bd07b6b8b35f9d4472e1fc3318b68a493b2" +"@types/semver@^5.4.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" + "@types/sinon@1.16.34": version "1.16.34" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-1.16.34.tgz#a9761fff33d0f7b3fe61875b577778a2576a9a03" @@ -122,7 +132,7 @@ ajv-keywords@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" -ajv@^4.7.0: +ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -172,6 +182,12 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + dependencies: + ansi-wrap "0.1.0" + ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -182,6 +198,12 @@ ansi-gray@^0.1.1: dependencies: ansi-wrap "0.1.0" +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + dependencies: + ansi-wrap "0.1.0" + ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" @@ -233,12 +255,12 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -"argparse@~ 0.1.11": - version "0.1.16" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" dependencies: - underscore "~1.7.0" - underscore.string "~2.4.0" + arr-flatten "^1.0.1" + array-slice "^0.2.3" arr-diff@^2.0.0: version "2.0.0" @@ -258,6 +280,10 @@ arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" @@ -286,6 +312,10 @@ array-series@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/array-series/-/array-series-0.1.5.tgz#df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f" +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + array-slice@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.0.0.tgz#e73034f00dcc1f40876008fd20feae77bd4b7c2f" @@ -379,10 +409,6 @@ async@^2.0.1: dependencies: lodash "^4.14.0" -async@~0.1.22: - version "0.1.22" - resolved "https://registry.yarnpkg.com/async/-/async-0.1.22.tgz#0fc1aaa088a0e3ef0ebe2d8831bab0dcf8845061" - async@~0.2.8: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" @@ -533,10 +559,6 @@ bl@~1.1.2: dependencies: readable-stream "~2.0.5" -bluebird@^3.0.5: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - body-parser@1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" @@ -922,10 +944,6 @@ coffee-script@^1.10.0: version "1.12.7" resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" -coffee-script@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4" - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -973,13 +991,9 @@ colormin@^1.0.5: css-color-names "0.0.4" has "^1.0.1" -colors@0.6.0-1: - version "0.6.0-1" - resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.0-1.tgz#6dbb68ceb8bc60f2b313dcc5ce1599f06d19e67a" - -colors@~0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" +colors@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" colors@~1.1.2: version "1.1.2" @@ -997,6 +1011,10 @@ combined-stream@~0.0.4: dependencies: delayed-stream "0.0.5" +commander@*, commander@^2.11.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + commander@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" @@ -1259,10 +1277,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dateformat@1.0.2-1.2.3: - version "1.0.2-1.2.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.2-1.2.3.tgz#b0220c02de98617433b72851cf47de3df2cdbee9" - dateformat@^1.0.11, dateformat@^1.0.7-1.2.3: version "1.0.12" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" @@ -1520,14 +1534,15 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -editorconfig@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" +editorconfig@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.0.tgz#b6dd4a0b6b9e76ce48e066bdc15381aebb8804fd" dependencies: - bluebird "^3.0.5" - commander "^2.9.0" - lru-cache "^3.2.0" - semver "^5.1.0" + "@types/commander" "^2.11.0" + "@types/semver" "^5.4.0" + commander "^2.11.0" + lru-cache "^4.1.1" + semver "^5.4.1" sigmund "^1.0.1" ee-first@1.1.1: @@ -1615,16 +1630,6 @@ es6-map@^0.1.3: es6-symbol "~3.1.1" event-emitter "~0.3.5" -es6-promise@^4.0.3: - version "4.1.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a" - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - dependencies: - es6-promise "^4.0.3" - es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" @@ -1757,10 +1762,6 @@ esprima@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" -"esprima@~ 1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" - esquery@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" @@ -1809,10 +1810,6 @@ event-stream@^3.1.7, event-stream@^3.3.1, event-stream@^3.3.4, event-stream@~3.3 stream-combiner "~0.0.4" through "~2.3.1" -eventemitter2@~0.4.13: - version "0.4.14" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -1829,10 +1826,6 @@ exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" -exit@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1904,6 +1897,12 @@ express@^4.13.1: utils-merge "1.0.1" vary "~1.1.2" +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + dependencies: + kind-of "^1.1.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -2103,13 +2102,6 @@ findup-sync@^2.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" -findup-sync@~0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.1.3.tgz#7f3e7a97b82392c653bf06589bd85190e93c3683" - dependencies: - glob "~3.2.9" - lodash "~2.4.1" - fined@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" @@ -2141,16 +2133,6 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flatpak-bundler@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/flatpak-bundler/-/flatpak-bundler-0.1.3.tgz#e45dfa0c4a7485c370e0915e4728929798503946" - dependencies: - debug "^2.2.0" - es6-promisify "^5.0.0" - fs-extra "^0.30.0" - lodash "^4.16.2" - tmp "0.0.29" - flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -2253,16 +2235,6 @@ fs-extra@0.26.7, fs-extra@^0.26.5: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - fs-extra@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" @@ -2332,25 +2304,20 @@ getmac@1.0.7: dependencies: extract-opts "^2.2.0" -getobject@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" dependencies: assert-plus "^1.0.0" -github-releases@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.2.1.tgz#91cae3cc7400d0b6144a4371ccaddddf1c02db58" +github-releases@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.4.1.tgz#4a13bdf85c4161344271db3d81db08e7379102ff" dependencies: - grunt "0.4" - minimatch "0.2.12" - optimist "~0.4.0" - prettyjson "~0.8.1" - request "~2.27.0" + minimatch "3.0.4" + optimist "0.6.1" + prettyjson "1.2.1" + request "2.81.0" glob-base@^0.3.0: version "0.3.0" @@ -2359,13 +2326,6 @@ glob-base@^0.3.0: glob-parent "^2.0.0" is-glob "^2.0.0" -glob-expand@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/glob-expand/-/glob-expand-0.2.1.tgz#1b088ac272b57158870b76816111da4618a66a0f" - dependencies: - glob "~4.5.x" - lodash "~4.13.x" - glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" @@ -2415,7 +2375,7 @@ glob2base@^0.0.12: dependencies: find-index "^0.1.1" -glob@3.2.11, glob@~3.2.9: +glob@3.2.11: version "3.2.11" resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" dependencies: @@ -2432,7 +2392,7 @@ glob@5.x, glob@^5.0.13, glob@^5.0.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^4.3.1, glob@~4.5.x: +glob@^4.3.1: version "4.5.3" resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" dependencies: @@ -2564,69 +2524,14 @@ growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" -grunt-legacy-log-utils@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz#c0706b9dd9064e116f36f23fe4e6b048672c0f7e" - dependencies: - colors "~0.6.2" - lodash "~2.4.1" - underscore.string "~2.3.3" - -grunt-legacy-log@~0.1.0: - version "0.1.3" - resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz#ec29426e803021af59029f87d2f9cd7335a05531" - dependencies: - colors "~0.6.2" - grunt-legacy-log-utils "~0.1.1" - hooker "~0.2.3" - lodash "~2.4.1" - underscore.string "~2.3.3" - -grunt-legacy-util@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz#93324884dbf7e37a9ff7c026dff451d94a9e554b" - dependencies: - async "~0.1.22" - exit "~0.1.1" - getobject "~0.1.0" - hooker "~0.2.3" - lodash "~0.9.2" - underscore.string "~2.2.1" - which "~1.0.5" - -grunt@0.4: - version "0.4.5" - resolved "https://registry.yarnpkg.com/grunt/-/grunt-0.4.5.tgz#56937cd5194324adff6d207631832a9d6ba4e7f0" - dependencies: - async "~0.1.22" - coffee-script "~1.3.3" - colors "~0.6.2" - dateformat "1.0.2-1.2.3" - eventemitter2 "~0.4.13" - exit "~0.1.1" - findup-sync "~0.1.2" - getobject "~0.1.0" - glob "~3.1.21" - grunt-legacy-log "~0.1.0" - grunt-legacy-util "~0.2.0" - hooker "~0.2.3" - iconv-lite "~0.2.11" - js-yaml "~2.0.5" - lodash "~0.9.2" - minimatch "~0.2.12" - nopt "~1.0.10" - rimraf "~2.2.8" - underscore.string "~2.2.1" - which "~1.0.5" - -gulp-atom-electron@1.15.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/gulp-atom-electron/-/gulp-atom-electron-1.15.1.tgz#ae13a4107a52e249d3335f584794981f5dcbf9be" +gulp-atom-electron@^1.16.1: + version "1.17.1" + resolved "https://registry.yarnpkg.com/gulp-atom-electron/-/gulp-atom-electron-1.17.1.tgz#fe803088c1410d7cd746b1a8be4d043ef1312757" dependencies: event-stream "^3.1.7" - github-releases "^0.2.0" + github-releases "^0.4.1" gulp-filter "^4.0.0" - gulp-rename "^1.2.0" + gulp-rename "1.2.2" gulp-symdest "^1.0.0" gulp-vinyl-zip "^1.2.0" mkdirp "^0.5.0" @@ -2777,6 +2682,15 @@ gulp-mocha@^2.1.3: temp "^0.8.3" through "^2.3.4" +gulp-plumber@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gulp-plumber/-/gulp-plumber-1.2.0.tgz#18ea03912c9ee483f8a5499973b5954cd90f6ad8" + dependencies: + chalk "^1.1.3" + fancy-log "^1.3.2" + plugin-error "^0.1.2" + through2 "^2.0.3" + gulp-remote-src@^0.4.0: version "0.4.3" resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1" @@ -2787,7 +2701,7 @@ gulp-remote-src@^0.4.0: through2 "~2.0.3" vinyl "~2.0.1" -gulp-rename@^1.2.0: +gulp-rename@1.2.2, gulp-rename@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817" @@ -2976,6 +2890,10 @@ handlebars@^4.0.1: optionalDependencies: uglify-js "^2.6" +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -2989,6 +2907,13 @@ har-validator@~2.0.6: is-my-json-valid "^2.12.4" pinkie-promise "^2.0.0" +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + har-validator@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" @@ -3100,10 +3025,6 @@ homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hooker@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959" - hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -3189,10 +3110,6 @@ iconv-lite@0.4.19, iconv-lite@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@~0.2.11: - version "0.2.11" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.2.11.tgz#1ce60a3a57864a292d1321ff4609ca4bb965adc8" - ignore@^3.2.0: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" @@ -3677,13 +3594,6 @@ js-yaml@3.x, js-yaml@^3.5.1, js-yaml@^3.7.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-2.0.5.tgz#a25ae6509999e97df278c6719da11bd0687743a8" - dependencies: - argparse "~ 0.1.11" - esprima "~ 1.0.2" - js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" @@ -3776,6 +3686,10 @@ keytar@^4.0.5: dependencies: nan "2.5.1" +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + kind-of@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74" @@ -4112,14 +4026,10 @@ lodash@^3.5.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.2, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@~0.9.2: - version "0.9.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-0.9.2.tgz#8f3499c5245d346d682e5b0d3b40767e09f1a92c" - lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" @@ -4128,10 +4038,6 @@ lodash@~2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" -lodash@~4.13.x: - version "4.13.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.13.1.tgz#83e4b10913f48496d4d16fec4a560af2ee744b68" - log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" @@ -4155,12 +4061,6 @@ lru-cache@2: version "2.7.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - dependencies: - pseudomap "^1.0.1" - lru-cache@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -4168,6 +4068,13 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + macaddress@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" @@ -4342,13 +4249,6 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@0.2.12: - version "0.2.12" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.12.tgz#ea82a012ac662c7ddfaa144f1c147e6946f5dafb" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - minimatch@0.3: version "0.3.0" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" @@ -4356,7 +4256,7 @@ minimatch@0.3: lru-cache "2" sigmund "~1.0.0" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -4368,7 +4268,7 @@ minimatch@2.x, minimatch@^2.0.1, minimatch@^2.0.10: dependencies: brace-expansion "^1.0.0" -minimatch@~0.2.11, minimatch@~0.2.12: +minimatch@~0.2.11: version "0.2.14" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" dependencies: @@ -4774,19 +4674,13 @@ optimist@0.3.5: dependencies: wordwrap "~0.0.2" -optimist@^0.6.1: +optimist@0.6.1, optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: minimist "~0.0.1" wordwrap "~0.0.2" -optimist@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.4.0.tgz#cb8ec37f2fe3aa9864cb67a275250e7e19620a25" - dependencies: - wordwrap "~0.0.2" - optionator@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.5.0.tgz#b75a8995a2d417df25b6e4e3862f50aa88651368" @@ -5000,6 +4894,10 @@ pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -5027,6 +4925,16 @@ plist@^1.1.0: xmlbuilder "4.0.0" xmldom "0.1.x" +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + plur@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" @@ -5279,11 +5187,12 @@ pretty-hrtime@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" -prettyjson@~0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-0.8.1.tgz#46d6773ccb0385902884ca5cc1e522faceb8c2cc" +prettyjson@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" dependencies: - colors "0.6.0-1" + colors "^1.1.2" + minimist "^1.2.0" priorityqueuejs@1.0.0: version "1.0.0" @@ -5321,7 +5230,7 @@ proxy-addr@~2.0.2: forwarded "~0.1.2" ipaddr.js "1.5.2" -pseudomap@^1.0.1, pseudomap@^1.0.2: +pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -5356,6 +5265,10 @@ qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -5619,6 +5532,33 @@ request@2.79.0, request@~2.79.0: tunnel-agent "~0.4.1" uuid "^3.0.0" +request@2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + "request@>= 2.44.0 < 3.0.0", request@^2.45.0, request@^2.79.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" @@ -5771,7 +5711,7 @@ rimraf@^2.4.2: dependencies: glob "^7.0.5" -rimraf@~2.2.6, rimraf@~2.2.8: +rimraf@~2.2.6: version "2.2.8" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" @@ -5835,6 +5775,10 @@ semver@4.3.6, semver@^4.1.0, semver@^4.3.4: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" +semver@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + send@0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" @@ -6557,17 +6501,16 @@ typemoq@^0.3.2: dependencies: underscore "^1.7.0" -typescript-formatter@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/typescript-formatter/-/typescript-formatter-4.0.1.tgz#ed82daf856cc9a379bb16b7f1aac9affee2974cd" +typescript-formatter@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/typescript-formatter/-/typescript-formatter-7.1.0.tgz#dd1b5547de211065221f765263e15f18c84c66b8" dependencies: commandpost "^1.0.0" - editorconfig "^0.13.2" - glob-expand "^0.2.1" + editorconfig "^0.15.0" -typescript@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631" +typescript@2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624" typescript@^2.6.2: version "2.6.2" @@ -6612,18 +6555,6 @@ unc-path-regex@^0.1.0, unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" -underscore.string@~2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.2.1.tgz#d7c0fa2af5d5a1a67f4253daee98132e733f0f19" - -underscore.string@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.3.3.tgz#71c08bf6b428b1133f37e78fa3a21c82f7329b0d" - -underscore.string@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" - underscore@1.8.3, underscore@^1.7.0, underscore@^1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" @@ -6632,10 +6563,6 @@ underscore@~1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604" -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" @@ -6910,9 +6837,9 @@ vscode-chokidar@1.6.2: optionalDependencies: vscode-fsevents "0.3.8" -vscode-debugprotocol@1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.27.0.tgz#735a43a3cc1235fe587c0ef93fe4e328def7b17c" +vscode-debugprotocol@1.28.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.28.0.tgz#b9fb97c3fb2dadbec78e5c1619ff12bf741ce406" vscode-fsevents@0.3.8: version "0.3.8" @@ -6936,20 +6863,30 @@ vscode-nls-dev@3.0.7: xml2js "^0.4.19" yargs "^10.1.1" -vscode-ripgrep@0.7.1-patch.0.1: - version "0.7.1-patch.0.1" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-0.7.1-patch.0.1.tgz#f05d2f093fd7f6a9d10fb935171e72620feaf999" +vscode-nsfw@1.0.17: + version "1.0.17" + resolved "https://registry.yarnpkg.com/vscode-nsfw/-/vscode-nsfw-1.0.17.tgz#da3820f26aea3a7e95cadc54bd9e5dae3d47e474" + dependencies: + fs-extra "^0.26.5" + lodash.isinteger "^4.0.4" + lodash.isundefined "^3.0.1" + nan "^2.0.0" + promisify-node "^0.3.0" -vscode-textmate@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-3.2.0.tgz#87e5ab1ed30463291a73fe28b37a58590a7777dc" +vscode-ripgrep@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-0.8.1.tgz#861d2ac97a3764e9f40f305620423efc50632ad1" + +vscode-textmate@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-3.3.3.tgz#8d737f2965046503a4088d47c2793aebe246d355" dependencies: fast-plist "^0.1.2" oniguruma "^6.0.1" -vscode-xterm@3.2.0-beta7: - version "3.2.0-beta7" - resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.2.0-beta7.tgz#352b33a17c31911d90b9c3bcfd1822800b32c8ed" +vscode-xterm@3.4.0-beta3: + version "3.4.0-beta3" + resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.4.0-beta3.tgz#349db387bd3669ad4d6044a6ea6d699e6d649fb5" vso-node-api@^6.1.2-preview: version "6.1.2-preview" @@ -6978,10 +6915,6 @@ which@^1.1.1, which@^1.2.12, which@^1.2.14, which@^1.2.9: dependencies: isexe "^2.0.0" -which@~1.0.5: - version "1.0.9" - resolved "https://registry.yarnpkg.com/which/-/which-1.0.9.tgz#460c1da0f810103d0321a9b633af9e575e64486f" - window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" @@ -6997,9 +6930,9 @@ windows-mutex@^0.2.0: bindings "^1.2.1" nan "^2.1.0" -windows-process-tree@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.1.6.tgz#c2d942a944152ea749a4c1c0bdb769b2f570639f" +windows-process-tree@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.2.2.tgz#1ab2518588d6f389c10e5a6c9c0d5550989506f4" dependencies: nan "^2.6.2"

  2. ${escape(localize('welcomePage.stackOverflow', "Stack Overflow"))}